it.unibo.alchemist.model.movestrategies.RandomTarget.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of alchemist-euclidean-geometry Show documentation
Show all versions of alchemist-euclidean-geometry Show documentation
Alchemist geometric components for Euclidean spaces
/*
* Copyright (C) 2010-2023, Danilo Pianini and contributors
* listed, for each module, in the respective subproject's build.gradle.kts file.
*
* This file is part of Alchemist, and is distributed under the terms of the
* GNU General Public License, with a linking exception,
* as described in the file LICENSE in the Alchemist distribution's top directory.
*/
package it.unibo.alchemist.model.movestrategies
import it.unibo.alchemist.model.Environment
import it.unibo.alchemist.model.Node
import it.unibo.alchemist.model.Reaction
import it.unibo.alchemist.model.environments.Environment2DWithObstacles
import it.unibo.alchemist.model.positions.Euclidean2DPosition
import it.unibo.alchemist.util.RandomGenerators.nextDouble
import org.apache.commons.math3.distribution.RealDistribution
import org.apache.commons.math3.random.RandomGenerator
import kotlin.math.PI
import kotlin.math.cos
import kotlin.math.sin
/**
* Selects a target based on a random direction extracted from [directionRng],
* and a random distance extracted from [distanceDistribution].
* [getCurrentPosition] should return the current position of the object to move.
* [T] is the type of the concentration of the node.
*/
class RandomTarget(
private val environment: Environment,
getCurrentPosition: () -> Euclidean2DPosition,
private val makePosition: (Double, Double) -> Euclidean2DPosition,
private val directionRng: RandomGenerator,
private val distanceDistribution: RealDistribution,
) : ChangeTargetOnCollision(getCurrentPosition) {
/**
* Handy constructor for Alchemist where the object to move is a [node] in the [environment].
*/
constructor(
environment: Environment,
node: Node,
directionRng: RandomGenerator,
distanceDistribution: RealDistribution,
) : this(
environment,
{ environment.getPosition(node) },
{ x, y -> environment.makePosition(x, y) },
directionRng,
distanceDistribution,
)
override fun chooseTarget() = with(directionRng.nextDouble(0.0, 2 * PI)) {
val distance = distanceDistribution.sample()
val current = getCurrentPosition()
val delta = makePosition(distance * cos(this), distance * sin(this))
val desired = current + delta
when (environment) {
is Environment2DWithObstacles<*, T> -> environment.next(current, desired)
else -> desired
}
}
override fun cloneIfNeeded(destination: Node?, reaction: Reaction?): RandomTarget =
RandomTarget(environment, getCurrentPosition, makePosition, directionRng, distanceDistribution)
}