Notice to GitKraken users: A vulnerability has been found in the SSH key generation of GitKraken versions 7.6.0 to 8.0.0 (https://www.gitkraken.com/blog/weak-ssh-key-fix). If you use GitKraken and have generated a SSH key using one of these versions, please remove it both from your local workstation and from your LRZ GitLab profile.

21.10.2021, 9:00 - 11:00: Due to updates GitLab may be unavailable for some minutes between 09:00 and 11:00.

Commit 922fde6e authored by Stefan Schuhbaeck's avatar Stefan Schuhbaeck
Browse files

Merge branch 'source_shape'

parents 38b5f9b1 d678b2ce
Pipeline #72863 failed with stages
in 76 minutes and 46 seconds
...@@ -51,6 +51,8 @@ public class AgentRender implements Renderer { ...@@ -51,6 +51,8 @@ public class AgentRender implements Renderer {
} }
private void renderGroup(Pedestrian ped, Graphics2D g) { private void renderGroup(Pedestrian ped, Graphics2D g) {
g.setColor(Color.DARK_GRAY);
g.fill(ped.getShape());
g.setColor(getGroupColor(ped)); g.setColor(getGroupColor(ped));
DefaultRenderer.fill(getShape(ped), g); DefaultRenderer.fill(getShape(ped), g);
} }
......
...@@ -260,6 +260,8 @@ public class TopographyWindow extends JPanel { ...@@ -260,6 +260,8 @@ public class TopographyWindow extends JPanel {
obstacleAndTargetDrawModes.add(pen2); obstacleAndTargetDrawModes.add(pen2);
sourceDrawModes.add(rectangle); sourceDrawModes.add(rectangle);
sourceDrawModes.add(pen);
sourceDrawModes.add(pen2);
sourceDrawModes.add(dot); sourceDrawModes.add(dot);
/* open obstacle paint method dialog action */ /* open obstacle paint method dialog action */
......
...@@ -14,6 +14,8 @@ ScenarioChecker.source.targetIdNotFound=The following target ids where not found ...@@ -14,6 +14,8 @@ ScenarioChecker.source.targetIdNotFound=The following target ids where not found
ScenarioChecker.source.noTargetIdSet=No Target Ids set for Source. ScenarioChecker.source.noTargetIdSet=No Target Ids set for Source.
ScenarioChecker.source.noTargetIdAndNoSpawn=No Target Ids set for Source with SpawnNumber 0. This might be an error. ScenarioChecker.source.noTargetIdAndNoSpawn=No Target Ids set for Source with SpawnNumber 0. This might be an error.
ScenarioChecker.source.idNotUnique=Multiple Sources have the same ID. ScenarioChecker.source.idNotUnique=Multiple Sources have the same ID.
ScenarioChecker.source.spawnAtRandomButNotAtFreeSpace=Combination isSpawnAtRandomPositions=true and isUseFreeSpaceOnly=false not allowed.
ScenarioChecker.source.spawnUseNotAtFreeSpace=Deprecated. Will be removed in future relases. Not all models can handle overlapping pedestrians.
ScenarioChecker.stairs.wrongTreadDim=Stair treadDepth outside of allowed dimension. Change the thread numbers to compensate. ScenarioChecker.stairs.wrongTreadDim=Stair treadDepth outside of allowed dimension. Change the thread numbers to compensate.
ScenarioChecker.target.unused=The target is not used in any source. Remove target to increase performance. ScenarioChecker.target.unused=The target is not used in any source. Remove target to increase performance.
ScenarioChecker.pedestrian.speedsetup=speedDistributionMean must be within min/max range. ScenarioChecker.pedestrian.speedsetup=speedDistributionMean must be within min/max range.
......
...@@ -13,6 +13,8 @@ ScenarioChecker.type.processor.warning=Procesor Warnung ...@@ -13,6 +13,8 @@ ScenarioChecker.type.processor.warning=Procesor Warnung
ScenarioChecker.source.targetIdNotFound=Die folgenden Ziel-IDs wurden nicht im Szenario gefunden. ScenarioChecker.source.targetIdNotFound=Die folgenden Ziel-IDs wurden nicht im Szenario gefunden.
ScenarioChecker.source.noTargetIdSet=In der Quelle wurden keine Ziel Ids vergeben. ScenarioChecker.source.noTargetIdSet=In der Quelle wurden keine Ziel Ids vergeben.
ScenarioChecker.source.noTargetIdAndNoSpawn=In der Quelle wurden keine Ziel Ids vergeben, aber die Spawn Anzahl ist bei 0. ScenarioChecker.source.noTargetIdAndNoSpawn=In der Quelle wurden keine Ziel Ids vergeben, aber die Spawn Anzahl ist bei 0.
ScenarioChecker.source.spawnAtRandomButNotAtFreeSpace=Kombination aus isSpawnAtRandomPositions=true und isUseFreeSpaceOnly=false ist nicht erlaubt.
ScenarioChecker.source.spawnUseNotAtFreeSpace=Deprecated. Dieses Attribut wird in zuk\u00fcnfigen version entfernt. Nicht alle Modell k\u00f6nnen mit \u00fcberlappungen umgehen.
ScenarioChecker.source.idNotUnique=Quellen haben keine eindeutige ID. ScenarioChecker.source.idNotUnique=Quellen haben keine eindeutige ID.
ScenarioChecker.stairs.wrongTreadDim=Stufentiefe ist au\u00dferhalb des Definitionsbereichs. Passen Sie die Anzahl der Stufen entsprechend an. ScenarioChecker.stairs.wrongTreadDim=Stufentiefe ist au\u00dferhalb des Definitionsbereichs. Passen Sie die Anzahl der Stufen entsprechend an.
ScenarioChecker.target.unused=Das Ziel wird von keiner Quelle verwendet. Entferne das Ziel um die Performance zu erh\u00f6hen ScenarioChecker.target.unused=Das Ziel wird von keiner Quelle verwendet. Entferne das Ziel um die Performance zu erh\u00f6hen
......
package org.vadere.simulator.control; package org.vadere.simulator.control;
import org.jetbrains.annotations.NotNull;
import org.vadere.simulator.control.util.GroupSpawnArray;
import org.vadere.simulator.models.DynamicElementFactory; import org.vadere.simulator.models.DynamicElementFactory;
import org.vadere.simulator.models.groups.GroupModel; import org.vadere.simulator.models.groups.GroupModel;
import org.vadere.state.attributes.scenario.AttributesDynamicElement; import org.vadere.state.attributes.scenario.AttributesDynamicElement;
import org.vadere.state.scenario.Source; import org.vadere.state.scenario.Source;
import org.vadere.state.scenario.Topography; import org.vadere.state.scenario.Topography;
import org.vadere.util.geometry.PointPositioned;
import org.vadere.util.geometry.shapes.VPoint; import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.geometry.shapes.VRectangle;
import org.vadere.util.geometry.shapes.VShape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
import java.util.stream.Collectors;
public class GroupSourceController extends SourceController { public class GroupSourceController extends SourceController {
private static final int NUMBER_OF_REPOSITION_TRIES = 20;
private final GroupModel groupModel; private final GroupModel groupModel;
private LinkedList<Integer> groupsToSpawn; private LinkedList<Integer> groupsToSpawn;
protected final GroupSpawnArray spawnArray;
public GroupSourceController(Topography scenario, Source source, public GroupSourceController(Topography scenario, Source source,
DynamicElementFactory dynamicElementFactory, DynamicElementFactory dynamicElementFactory,
...@@ -24,6 +36,14 @@ public class GroupSourceController extends SourceController { ...@@ -24,6 +36,14 @@ public class GroupSourceController extends SourceController {
super(scenario, source, dynamicElementFactory, attributesDynamicElement, random); super(scenario, source, dynamicElementFactory, attributesDynamicElement, random);
this.groupModel = groupModel; this.groupModel = groupModel;
this.groupsToSpawn = new LinkedList<>(); this.groupsToSpawn = new LinkedList<>();
VRectangle elementBound = new VRectangle(dynamicElementFactory.getDynamicElementRequiredPlace(new VPoint(0, 0)).getBounds2D());
this.spawnArray = new GroupSpawnArray(source.getShape(),
new VRectangle(0, 0, elementBound.getWidth(), elementBound.getHeight()),
dynamicElementFactory::getDynamicElementRequiredPlace,
this::testFreeSpace);
} }
@Override @Override
...@@ -38,7 +58,14 @@ public class GroupSourceController extends SourceController { ...@@ -38,7 +58,14 @@ public class GroupSourceController extends SourceController {
Iterator<Integer> iter = groupsToSpawn.iterator(); Iterator<Integer> iter = groupsToSpawn.iterator();
while (iter.hasNext()) { while (iter.hasNext()) {
int groupSize = iter.next(); int groupSize = iter.next();
List<VPoint> newGroup = spawnArray.getNextFreeGroup(groupSize, random, getDynElementsAtSource()); List<VPoint> newGroup = getRealRandomPositions(
groupSize,
random,
getDynElementsAtSource().stream()
.map(PointPositioned::getPosition)
.map(dynamicElementFactory::getDynamicElementRequiredPlace)
.collect(Collectors.toList())
);
if (newGroup.size() > 0) { if (newGroup.size() > 0) {
// add immediately to Scenario to update DynElementsAtSource // add immediately to Scenario to update DynElementsAtSource
addElementToScenario(newGroup); addElementToScenario(newGroup);
...@@ -51,7 +78,14 @@ public class GroupSourceController extends SourceController { ...@@ -51,7 +78,14 @@ public class GroupSourceController extends SourceController {
Iterator<Integer> iter = groupsToSpawn.iterator(); Iterator<Integer> iter = groupsToSpawn.iterator();
while (iter.hasNext()) { while (iter.hasNext()) {
int groupSize = iter.next(); int groupSize = iter.next();
List<VPoint> newGroup = spawnArray.getNextGroup(groupSize, random, getDynElementsAtSource()); List<VPoint> newGroup = spawnArray.getNextGroup(
groupSize,
random,
getDynElementsAtSource().stream()
.map(PointPositioned::getPosition)
.map(dynamicElementFactory::getDynamicElementRequiredPlace)
.collect(Collectors.toList())
);
if (newGroup.isEmpty()) if (newGroup.isEmpty())
throw new RuntimeException("Cannot spawn new Group. Source " + source.getId() + " is set " + throw new RuntimeException("Cannot spawn new Group. Source " + source.getId() + " is set " +
"to useFreeSpaceOnly == false but no space is left to spawn group without exactly" + "to useFreeSpaceOnly == false but no space is left to spawn group without exactly" +
...@@ -68,7 +102,13 @@ public class GroupSourceController extends SourceController { ...@@ -68,7 +102,13 @@ public class GroupSourceController extends SourceController {
Iterator<Integer> iter = groupsToSpawn.iterator(); Iterator<Integer> iter = groupsToSpawn.iterator();
while (iter.hasNext()) { while (iter.hasNext()) {
int groupSize = iter.next(); int groupSize = iter.next();
List<VPoint> newGroup = spawnArray.getNextFreeGroup(groupSize, getDynElementsAtSource()); List<VPoint> newGroup = spawnArray.getNextFreeGroup(
groupSize,
getDynElementsAtSource().stream()
.map(PointPositioned::getPosition)
.map(dynamicElementFactory::getDynamicElementRequiredPlace)
.collect(Collectors.toList())
);
if (newGroup != null && !newGroup.isEmpty()) { if (newGroup != null && !newGroup.isEmpty()) {
// add immediately to Scenario to update DynElementsAtSource // add immediately to Scenario to update DynElementsAtSource
addElementToScenario(newGroup); addElementToScenario(newGroup);
...@@ -81,7 +121,13 @@ public class GroupSourceController extends SourceController { ...@@ -81,7 +121,13 @@ public class GroupSourceController extends SourceController {
Iterator<Integer> iter = groupsToSpawn.iterator(); Iterator<Integer> iter = groupsToSpawn.iterator();
while (iter.hasNext()) { while (iter.hasNext()) {
int groupSize = iter.next(); int groupSize = iter.next();
List<VPoint> newGroup = spawnArray.getNextGroup(groupSize, getDynElementsAtSource()); List<VPoint> newGroup = spawnArray.getNextGroup(
groupSize,
getDynElementsAtSource().stream()
.map(PointPositioned::getPosition)
.map(dynamicElementFactory::getDynamicElementRequiredPlace)
.collect(Collectors.toList())
);
if (newGroup == null || newGroup.isEmpty()) if (newGroup == null || newGroup.isEmpty())
throw new RuntimeException("Cannot spawn new Group. Source " + source.getId() + " is set " + throw new RuntimeException("Cannot spawn new Group. Source " + source.getId() + " is set " +
"to useFreeSpaceOnly == false but no space is left to spawn group without exactly" + "to useFreeSpaceOnly == false but no space is left to spawn group without exactly" +
...@@ -99,6 +145,72 @@ public class GroupSourceController extends SourceController { ...@@ -99,6 +145,72 @@ public class GroupSourceController extends SourceController {
} }
} }
/**
* Computes random positions for ONE group based on the blockPedestrianShapes which contains
* the shapes representing the required space for the specified group size. For each required
* position the algorithms tries {@link GroupSourceController#NUMBER_OF_REPOSITION_TRIES} times
* to get a feasible free position for this group.
*
* @param groupSize size of group to spawn at a random positions
* @param random random generator
* @param blockPedestrianShapes the required space of other pedestrians
* @return list of Points representing the group members or an empty list if group cannot be
* placed after {@link GroupSourceController#NUMBER_OF_REPOSITION_TRIES} of tries.
*/
private List<VPoint> getRealRandomPositions(final int groupSize, @NotNull final Random random, @NotNull final List<VShape> blockPedestrianShapes) {
List<VPoint> randomPositions = new ArrayList<>(groupSize);
List<VPoint> defaultPoints = spawnArray.getDefaultGroup(groupSize);
for (int i = 0; i < NUMBER_OF_REPOSITION_TRIES; i++) {
randomPositions = moveRandomInSourceBound(defaultPoints, random);
boolean groupValid = randomPositions.stream()
.map(dynamicElementFactory::getDynamicElementRequiredPlace)
.allMatch(candidateShape ->
source.getShape().containsShape(candidateShape) &&
testFreeSpace(candidateShape, blockPedestrianShapes));
if (groupValid) {
return randomPositions;
}
}
return new ArrayList<>();
}
/**
* @param points default points of group members. First allowed position if the spawn would be
* based on the spawn grid.
* @param random random object
* @return transformed set of points based on a random translation and rotation within the
* bound of the source
*/
private List<VPoint> moveRandomInSourceBound(List<VPoint> points, @NotNull final Random random) {
Rectangle2D bound = source.getShape().getBounds2D();
double angle = random.nextDouble() * 2 * Math.PI;
VPoint p0 = points.get(0);
double dxBound = (bound.getX() - p0.getX());
double dyBound = (bound.getY() - p0.getY());
double dxRnd = random.nextDouble() * (bound.getMaxX() - bound.getX());
double dyRnd = random.nextDouble() * (bound.getMaxY() - bound.getY());
AffineTransform at0 = new AffineTransform();
at0.setToTranslation(dxBound, dyBound);
AffineTransform at1 = new AffineTransform();
at1.setToRotation(angle, bound.getX(), bound.getY());
AffineTransform at2 = new AffineTransform();
at2.setToTranslation(dxRnd, dyRnd);
List<VPoint> ret = new ArrayList<>();
points.stream().map(VPoint::asPoint2D).forEach(p -> {
at0.transform(p, p);
at1.transform(p, p);
at2.transform(p, p);
ret.add(new VPoint(p));
}
);
return ret;
}
private void addElementToScenario(List<VPoint> group) { private void addElementToScenario(List<VPoint> group) {
if (!group.isEmpty() && !isMaximumNumberOfSpawnedElementsReached()) { if (!group.isEmpty() && !isMaximumNumberOfSpawnedElementsReached()) {
addNewAgentToScenario(group); addNewAgentToScenario(group);
......
...@@ -3,14 +3,17 @@ package org.vadere.simulator.control; ...@@ -3,14 +3,17 @@ package org.vadere.simulator.control;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.vadere.simulator.models.DynamicElementFactory; import org.vadere.simulator.models.DynamicElementFactory;
import org.vadere.state.attributes.scenario.AttributesDynamicElement; import org.vadere.state.attributes.scenario.AttributesDynamicElement;
import org.vadere.state.scenario.Obstacle;
import org.vadere.state.scenario.Source; import org.vadere.state.scenario.Source;
import org.vadere.state.scenario.Topography; import org.vadere.state.scenario.Topography;
import org.vadere.simulator.control.util.SingleSpawnArray;
import org.vadere.util.geometry.PointPositioned;
import org.vadere.util.geometry.shapes.VPoint; import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.geometry.shapes.VRectangle;
import org.vadere.util.geometry.shapes.VShape; import org.vadere.util.geometry.shapes.VShape;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.Random; import java.util.Random;
...@@ -19,15 +22,21 @@ import java.util.stream.Collectors; ...@@ -19,15 +22,21 @@ import java.util.stream.Collectors;
public class SingleSourceController extends SourceController { public class SingleSourceController extends SourceController {
private int numberToSpawn; private int numberToSpawn;
private DynamicElementFactory dynamicElementFactory;
private static final int NUMBER_OF_REPOSITION_TRIES = 10; private static final int NUMBER_OF_REPOSITION_TRIES = 10;
private static final int NUMBER_OF_POINT_SEARCH = 1_000; // todo based on shape and position of source
private SingleSpawnArray spawnArray;
public SingleSourceController(Topography scenario, Source source, public SingleSourceController(Topography scenario, Source source,
DynamicElementFactory dynamicElementFactory, DynamicElementFactory dynamicElementFactory,
AttributesDynamicElement attributesDynamicElement, AttributesDynamicElement attributesDynamicElement,
Random random) { Random random) {
super(scenario, source, dynamicElementFactory, attributesDynamicElement, random); super(scenario, source, dynamicElementFactory, attributesDynamicElement, random);
this.dynamicElementFactory = dynamicElementFactory; VRectangle elementBound = new VRectangle(dynamicElementFactory.getDynamicElementRequiredPlace(new VPoint(0, 0)).getBounds2D());
this.spawnArray = new SingleSpawnArray(source.getShape(),
new VRectangle(0, 0, elementBound.getWidth(), elementBound.getHeight()),
this.dynamicElementFactory::getDynamicElementRequiredPlace,
this::testFreeSpace);
} }
@Override @Override
...@@ -35,18 +44,17 @@ public class SingleSourceController extends SourceController { ...@@ -35,18 +44,17 @@ public class SingleSourceController extends SourceController {
if (!isSourceFinished(simTimeInSec)) { if (!isSourceFinished(simTimeInSec)) {
if (simTimeInSec >= timeOfNextEvent || numberToSpawn > 0) { if (simTimeInSec >= timeOfNextEvent || numberToSpawn > 0) {
determineNumberOfSpawnsAndNextEvent(simTimeInSec); determineNumberOfSpawnsAndNextEvent(simTimeInSec);
List<VPoint> spawnPoints = new LinkedList<>(); List<VPoint> spawnPoints;
if (sourceAttributes.isSpawnAtRandomPositions()) { if (sourceAttributes.isSpawnAtRandomPositions()) {
if (sourceAttributes.isUseFreeSpaceOnly()) { if (sourceAttributes.isUseFreeSpaceOnly()) {
//spawnPoints = spawnArray.getNextFreeRandomSpawnPoints(numberToSpawn, random, getDynElementsAtSource());
spawnPoints = getRealRandomPositions( spawnPoints = getRealRandomPositions(
numberToSpawn, numberToSpawn,
random, random,
getDynElementsAtSource().stream() getDynElementsAtSource().stream()
.map(element -> element.getPosition()) .map(PointPositioned::getPosition)
.map(position -> dynamicElementFactory.getDynamicElementRequiredPlace(position)) .map(dynamicElementFactory::getDynamicElementRequiredPlace)
.collect(Collectors.toList()) .collect(Collectors.toList())
); );
...@@ -54,19 +62,25 @@ public class SingleSourceController extends SourceController { ...@@ -54,19 +62,25 @@ public class SingleSourceController extends SourceController {
assert (numberToSpawn >= 0); assert (numberToSpawn >= 0);
} else { } else {
throw new IllegalArgumentException("use random position without free space only makes no sense."); throw new IllegalArgumentException("use random position without free space only makes no sense.");
/*spawnPoints = spawnArray.getNextRandomSpawnPoints(numberToSpawn, random, getDynElementsAtSource());
numberToSpawn -= spawnPoints.size();
assert (numberToSpawn >= 0);*/
} }
} else { } else {
if (sourceAttributes.isUseFreeSpaceOnly()) { if (sourceAttributes.isUseFreeSpaceOnly()) {
spawnPoints = spawnArray.getNextFreeSpawnPoints(numberToSpawn, getDynElementsAtSource()); spawnPoints = getRealPositions(
numberToSpawn,
getDynElementsAtSource().stream()
.map(PointPositioned::getPosition)
.map(dynamicElementFactory::getDynamicElementRequiredPlace)
.collect(Collectors.toList())
);
numberToSpawn -= spawnPoints.size(); numberToSpawn -= spawnPoints.size();
assert (numberToSpawn >= 0); assert (numberToSpawn >= 0);
} else { } else {
spawnPoints = spawnArray.getNextSpawnPoints(numberToSpawn, getDynElementsAtSource()); spawnPoints = getRealPositions(
numberToSpawn,
new ArrayList<>()
);
numberToSpawn -= spawnPoints.size(); numberToSpawn -= spawnPoints.size();
assert (numberToSpawn >= 0); assert (numberToSpawn >= 0);
} }
...@@ -83,20 +97,37 @@ public class SingleSourceController extends SourceController { ...@@ -83,20 +97,37 @@ public class SingleSourceController extends SourceController {
} }
} }
private List<VPoint> getRealPositions(final int numberToSpawn, @NotNull final List<VShape> blockPedestrianShapes) {
List<VPoint> positions = new ArrayList<>(numberToSpawn);
for (int i = 0; i < numberToSpawn; i++) {
Optional<VPoint> optPosition = spawnArray.getNextPosition(blockPedestrianShapes);
if (optPosition.isPresent()) {
VPoint position = optPosition.get();
blockPedestrianShapes.add(dynamicElementFactory.getDynamicElementRequiredPlace(position));
positions.add(position);
}
}
return positions;
}
/** /**
* Computes numberToSpawn or less random positions based on the blockPedestrianShapes which contains the shapes representing the required space of each pedestrian. * Computes numberToSpawn or less random positions based on the blockPedestrianShapes which
* For each required position the algorithms tries {@link SingleSourceController#NUMBER_OF_REPOSITION_TRIES} times to get a feasible free position. * contains the shapes representing the required space of each pedestrian. For each required
* position the algorithms tries {@link SingleSourceController#NUMBER_OF_REPOSITION_TRIES} times
* to get a feasible free position.
* *
* @param numberToSpawn number of required spawn positions * @param numberToSpawn number of required spawn positions
* @param random random generator * @param random random generator
* @param blockPedestrianShapes the required space of other pedestrians * @param blockPedestrianShapes the required space of other pedestrians
* @return numberToSpawn or less random feasible positions * @return numberToSpawn or less random feasible positions
*/ */
private List<VPoint> getRealRandomPositions(final int numberToSpawn, @NotNull final Random random, @NotNull final List<VShape> blockPedestrianShapes) { private List<VPoint> getRealRandomPositions(final int numberToSpawn, @NotNull final Random random, @NotNull final List<VShape> blockPedestrianShapes) {
List<VPoint> randomPositions = new ArrayList<>(numberToSpawn); List<VPoint> randomPositions = new ArrayList<>(numberToSpawn);
for(int i = 0; i < numberToSpawn; i++) { for (int i = 0; i < numberToSpawn; i++) {
Optional<VPoint> optRandomPosition = getNextRandomPosition(random, blockPedestrianShapes, NUMBER_OF_REPOSITION_TRIES); Optional<VPoint> optRandomPosition = getNextRandomPosition(random, blockPedestrianShapes, NUMBER_OF_POINT_SEARCH, NUMBER_OF_REPOSITION_TRIES);
if (optRandomPosition.isPresent()) { if (optRandomPosition.isPresent()) {
VPoint randomPosition = optRandomPosition.get(); VPoint randomPosition = optRandomPosition.get();
...@@ -108,16 +139,26 @@ public class SingleSourceController extends SourceController { ...@@ -108,16 +139,26 @@ public class SingleSourceController extends SourceController {
return randomPositions; return randomPositions;
} }
private Optional<VPoint> getNextRandomPosition(@NotNull final Random random, @NotNull final List<VShape> blockPedestrianShapes, final int tries) {
private Optional<VPoint> getNextRandomPosition(@NotNull final Random random, @NotNull final List<VShape> blockPedestrianShapes,
final int tries_find_valid_point, final int tries_reposition) {
Rectangle2D rec = source.getShape().getBounds2D(); Rectangle2D rec = source.getShape().getBounds2D();
for(int i = 0; i < tries; i++) { for (int i = 0; i < tries_reposition; i++) {
VPoint randomPoint = new VPoint(rec.getMinX() + random.nextDouble() * rec.getWidth(), rec.getMinY() + random.nextDouble() * rec.getHeight()); VShape freeSpaceRequired = null;
VShape freeSpaceRequired = dynamicElementFactory.getDynamicElementRequiredPlace(randomPoint); VPoint randomPoint = null;
boolean pointFound = false;
// find point in source boundary
int j = 0;
while (j < tries_find_valid_point && !pointFound) {
randomPoint = new VPoint(rec.getMinX() + random.nextDouble() * rec.getWidth(), rec.getMinY() + random.nextDouble() * rec.getHeight());
freeSpaceRequired = dynamicElementFactory.getDynamicElementRequiredPlace(randomPoint);
pointFound = source.getShape().containsShape(freeSpaceRequired);
j++;
}
// no intersection with other free spaces (obstacles & other pedestrians) // no intersection with other free spaces (obstacles & other pedestrians)
if(blockPedestrianShapes.stream().noneMatch(shape -> shape.intersects(freeSpaceRequired)) if (testFreeSpace(freeSpaceRequired, blockPedestrianShapes)) {
&& this.getTopography().getObstacles().stream().noneMatch(obs -> obs.getShape().intersects(freeSpaceRequired))) {
return Optional.of(randomPoint); return Optional.of(randomPoint);
} }
} }
...@@ -125,7 +166,6 @@ public class SingleSourceController extends SourceController { ...@@ -125,7 +166,6 @@ public class SingleSourceController extends SourceController {
return Optional.empty(); return Optional.empty();
} }
@Override @Override
protected boolean isQueueEmpty() { protected boolean isQueueEmpty() {
return numberToSpawn == 0; return numberToSpawn == 0;
......
...@@ -8,16 +8,15 @@ import org.vadere.state.scenario.Agent; ...@@ -8,16 +8,15 @@ import org.vadere.state.scenario.Agent;
import org.vadere.state.scenario.Car; import org.vadere.state.scenario.Car;
import org.vadere.state.scenario.DistributionFactory; import org.vadere.state.scenario.DistributionFactory;
import org.vadere.state.scenario.DynamicElement; import org.vadere.state.scenario.DynamicElement;
import org.vadere.state.scenario.Obstacle;
import org.vadere.state.scenario.Pedestrian; import org.vadere.state.scenario.Pedestrian;
import org.vadere.state.scenario.Source; import org.vadere.state.scenario.Source;
import org.vadere.state.scenario.Topography; import org.vadere.state.scenario.Topography;
import org.vadere.state.util.SpawnArray;
import org.vadere.util.geometry.LinkedCellsGrid; import org.vadere.util.geometry.LinkedCellsGrid;
import org.vadere.util.geometry.shapes.VCircle; import org.vadere.util.geometry.shapes.VCircle;
import org.vadere.util.geometry.shapes.VPoint; import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.geometry.shapes.VRectangle; import org.vadere.util.geometry.shapes.VShape;
import java.awt.geom.Rectangle2D;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
...@@ -25,21 +24,22 @@ import java.util.Random; ...@@ -25,21 +24,22 @@ import java.util.Random;
public abstract class SourceController { public abstract class SourceController {
protected final double NO_EVENT = Double.MAX_VALUE; protected final double NO_EVENT = Double.MAX_VALUE;
public static final double SPAWN_BUFFER_SIZE = 0.03;