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

Commit 8b4c313d authored by Benedikt Zoennchen's avatar Benedikt Zoennchen

adapt LinkedCellGrid such that an element can be updated if it moves from one position to another.

parent 1cb60daf
......@@ -65,13 +65,11 @@ public class OfflineTopographyController {
protected void recomputeCells() {
this.topography.getSpatialMap(Pedestrian.class).clear();
for (Pedestrian pedestrian : this.topography.getElements(Pedestrian.class)) {
this.topography.getSpatialMap(Pedestrian.class).addObject(pedestrian,
pedestrian.getPosition());
this.topography.getSpatialMap(Pedestrian.class).addObject(pedestrian);
}
this.topography.getSpatialMap(Car.class).clear();
for (Car car : this.topography.getElements(Car.class)) {
this.topography.getSpatialMap(Car.class).addObject(car,
car.getPosition());
this.topography.getSpatialMap(Car.class).addObject(car);
}
}
}
......@@ -104,16 +104,16 @@ public class PedestrianOSM extends Pedestrian {
switch (updateType) {
case EVENT_DRIVEN:
result = new UpdateSchemeEventDriven(pedestrian);
result = new UpdateSchemeEventDriven(pedestrian, pedestrian.topography);
break;
case PARALLEL:
result = new UpdateSchemeParallel(pedestrian);
break;
case SEQUENTIAL:
result = new UpdateSchemeSequential(pedestrian);
result = new UpdateSchemeSequential(pedestrian, pedestrian.topography);
break;
default:
result = new UpdateSchemeSequential(pedestrian);
result = new UpdateSchemeSequential(pedestrian, pedestrian.topography);
}
return result;
......
package org.vadere.simulator.models.osm.updateScheme;
import org.vadere.simulator.models.osm.PedestrianOSM;
import org.vadere.state.scenario.Topography;
import org.vadere.util.geometry.shapes.VPoint;
public class UpdateSchemeEventDriven implements UpdateSchemeOSM {
private final PedestrianOSM pedestrian;
private final Topography topography;
public UpdateSchemeEventDriven(PedestrianOSM pedestrian) {
public UpdateSchemeEventDriven(PedestrianOSM pedestrian, Topography topography) {
this.pedestrian = pedestrian;
this.topography = topography;
}
@Override
public void update(double timeStepInSec, double currentTimeInSec, CallMethod callMethod) {
VPoint oldPosition = pedestrian.getPosition();
// for the first step after creation, timeOfNextStep has to be initialized
if (pedestrian.getTimeOfNextStep() == 0) {
pedestrian.setTimeOfNextStep(currentTimeInSec);
......@@ -22,6 +28,8 @@ public class UpdateSchemeEventDriven implements UpdateSchemeOSM {
pedestrian.updateNextPosition();
pedestrian.makeStep(pedestrian.getDurationNextStep());
pedestrian.setTimeOfNextStep(pedestrian.getTimeOfNextStep() + pedestrian.getDurationNextStep());
topography.moveElement(pedestrian, oldPosition);
}
}
package org.vadere.simulator.models.osm.updateScheme;
import org.vadere.simulator.models.osm.PedestrianOSM;
import org.vadere.state.scenario.Topography;
import org.vadere.util.geometry.shapes.VPoint;
public class UpdateSchemeSequential implements UpdateSchemeOSM {
private final PedestrianOSM pedestrian;
private final Topography topography;
public UpdateSchemeSequential(PedestrianOSM pedestrian) {
public UpdateSchemeSequential(PedestrianOSM pedestrian, Topography topography) {
this.pedestrian = pedestrian;
this.topography = topography;
}
@Override
public void update(double timeStepInSec, double currentTimeInSec, CallMethod callMethod) {
VPoint oldPosition = pedestrian.getPosition();
pedestrian.setTimeCredit(pedestrian.getTimeCredit() + timeStepInSec);
pedestrian.setDurationNextStep(pedestrian.getStepSize() / pedestrian.getDesiredSpeed());
......@@ -20,5 +26,7 @@ public class UpdateSchemeSequential implements UpdateSchemeOSM {
pedestrian.makeStep(timeStepInSec);
pedestrian.setDurationNextStep(pedestrian.getStepSize() / pedestrian.getDesiredSpeed());
}
topography.moveElement(pedestrian, oldPosition);
}
}
......@@ -4,10 +4,12 @@ import java.awt.geom.RectangularShape;
import java.util.*;
import org.vadere.util.geometry.LinkedCellsGrid;
import org.vadere.util.geometry.shapes.VPoint;
public class DynamicElementContainer<T extends DynamicElement> {
private transient final List<DynamicElementAddListener<T>> addListener;
private transient final List<DynamicElementRemoveListener<T>> removeListener;
private transient final List<DynamicElementMoveListener<T>> moveListener;
private final Map<Integer, T> elementMap;
......@@ -32,6 +34,7 @@ public class DynamicElementContainer<T extends DynamicElement> {
this.addListener = new LinkedList<>();
this.removeListener = new LinkedList<>();
this.moveListener = new LinkedList<>();
}
public LinkedCellsGrid<T> getCellsElements() {
......@@ -56,13 +59,21 @@ public class DynamicElementContainer<T extends DynamicElement> {
public void addElement(T element) {
this.elementMap.put(element.getId(), element);
this.cellsElements.addObject(element, element.getPosition());
this.cellsElements.addObject(element);
for (DynamicElementAddListener<T> listener : addListener) {
listener.elementAdded(element);
}
}
public void moveElement(T element, VPoint oldPosition) {
this.cellsElements.moveObject(element, oldPosition);
for (DynamicElementMoveListener<T> listener : moveListener) {
listener.elementMove(element);
}
}
public void removeElement(T element) {
this.elementMap.remove(element.getId());
this.cellsElements.removeObject(element);
......
package org.vadere.state.scenario;
/**
* @Benedikt Zoennchen
*/
public interface DynamicElementMoveListener<T extends DynamicElement> {
public void elementMove(T element);
}
......@@ -220,6 +220,10 @@ public class Topography {
((DynamicElementContainer<T>) getContainer(element.getClass())).removeElement(element);
}
public <T extends DynamicElement> void moveElement(T element, final VPoint oldPosition) {
((DynamicElementContainer<T>) getContainer(element.getClass())).moveElement(element, oldPosition);
}
public List<Source> getSources() {
return sources;
}
......
package org.vadere.util.geometry;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
......@@ -14,75 +15,19 @@ import org.vadere.util.geometry.shapes.VPoint;
/**
* A grid augmenting the position of generic objects, for faster access. O(1)
* instead of O(n) for one fixed radius check. See
* {@link LinkedCellsGrid#getObjects(java.awt.geometry.shapes.VPoint, double)}.
* {@link LinkedCellsGrid#getObjects(VPoint, double)}.
*
*
*/
public class LinkedCellsGrid<T> implements Iterable<T> {
/**
* Key value pair holding an object with its assigned position.
*
*
*/
private class ObjectWithPosition<U> {
U object;
VPoint position;
public ObjectWithPosition(U object, VPoint pos) {
this.object = object;
this.position = pos;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((object == null) ? 0 : object.hashCode());
result = prime * result
+ ((position == null) ? 0 : position.hashCode());
return result;
}
@SuppressWarnings("unchecked")
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
ObjectWithPosition<U> other = (ObjectWithPosition<U>) obj;
if (object == null) {
if (other.object != null) {
return false;
}
} else if (!object.equals(other.object)) {
return false;
}
if (position == null) {
if (other.position != null) {
return false;
}
} else if (!position.equals(other.position)) {
return false;
}
return true;
}
}
public class LinkedCellsGrid<T extends PointPositioned> implements Iterable<T> {
final private double left;
final private double top;
final private double width;
final private double height;
private GridCell<T>[][] grid;
private List<ObjectWithPosition<T>> totalObjects = new LinkedList<ObjectWithPosition<T>>();
private int[] gridSize = new int[2];
private double[] cellSize = new double[2];
private int size;
/**
* One cell in the grid. It contains a mapping from points to lists of
......@@ -92,8 +37,8 @@ public class LinkedCellsGrid<T> implements Iterable<T> {
* @param <E>
* type of objects stored in this cell.
*/
private class GridCell<E> {
public Map<VPoint, List<E>> objects = new HashMap<VPoint, List<E>>();
private class GridCell<E extends PointPositioned> {
public List<E> objects = new ArrayList<>();
@Override
public int hashCode() {
......@@ -148,7 +93,7 @@ public class LinkedCellsGrid<T> implements Iterable<T> {
for (int r = 0; r < grid.length; r++) {
// TODO [priority=medium] [task=test] changed this [20.08.2014] here 1 to r - pls check this
for (int c = 0; c < grid[r].length; c++) {
grid[r][c] = new GridCell<T>();
grid[r][c] = new GridCell<>();
}
}
......@@ -177,6 +122,7 @@ public class LinkedCellsGrid<T> implements Iterable<T> {
this.top = top;
this.width = width;
this.height = height;
this.size = 0;
// create grid
......@@ -221,30 +167,20 @@ public class LinkedCellsGrid<T> implements Iterable<T> {
}
/**
* Adds a given object to the grid at the given position. The position is
* Adds a given object to the grid at position of the object. The position is
* discretized automatically to fit in the cells.
*
* @param object
* object to add
* @param pos
* position in the grid
* @param object object to add
*/
public void addObject(final T object, final VPoint pos) {
int[] gridPos = gridPos(pos);
// store object in the grid cell.
// if there is nothing there yet, create the list.
if (!this.grid[gridPos[0]][gridPos[1]].objects.containsKey(pos)) {
this.grid[gridPos[0]][gridPos[1]].objects.put(pos,
new LinkedList<T>());
}
List<T> objects = this.grid[gridPos[0]][gridPos[1]].objects.get(pos);
// add the object to the list stored in this cell
objects.add(object);
public synchronized void addObject(final T object) {
int[] gridPos = gridPos(object.getPosition());
grid[gridPos[0]][gridPos[1]].objects.add(object);
size++;
}
// also store it in the total objects list for easy iteration over all
// stored objects.
totalObjects.add(new ObjectWithPosition<T>(object, pos));
public void moveObject(final T object, final VPoint oldPosition) {
removeObject(object, oldPosition);
addObject(object);
}
/**
......@@ -256,25 +192,24 @@ public class LinkedCellsGrid<T> implements Iterable<T> {
* radius of the ball
* @return set of objects, or an empty set if no objects are present.
*/
public List<T> getObjects(final VPoint pos, final double radius) {
public synchronized List<T> getObjects(final VPoint pos, final double radius) {
final List<T> result = new LinkedList<T>();
int[] gridPos = gridPos(pos);
int[] discreteRad = new int[2];
discreteRad[0] = (int) Math.ceil(radius / this.cellSize[0]);
discreteRad[1] = (int) Math.ceil(radius / this.cellSize[1]);
discreteRad[0] = (int) Math.ceil(radius / cellSize[0]);
discreteRad[1] = (int) Math.ceil(radius / cellSize[1]);
final int maxRow = Math.min(this.gridSize[0] - 1, gridPos[0] + discreteRad[0]);
final int maxCol = Math.min(this.gridSize[1] - 1, gridPos[1] + discreteRad[1]);
final int maxRow = Math.min(gridSize[0] - 1, gridPos[0] + discreteRad[0]);
final int maxCol = Math.min(gridSize[1] - 1, gridPos[1] + discreteRad[1]);
for (int row = Math.max(0, gridPos[0] - discreteRad[0]); row <= maxRow; row++) {
for (int col = Math.max(0, gridPos[1] - discreteRad[1]); col <= maxCol; col++) {
for (Entry<VPoint, List<T>> entry : this.grid[row][col].objects
.entrySet()) {
for (T object : grid[row][col].objects) {
// if the given position is closer than the radius, add all objects stored there
if (entry.getKey().distance(pos) < radius) {
result.addAll(entry.getValue());
if (object.getPosition().distance(pos) < radius) {
result.add(object);
}
}
}
......@@ -289,26 +224,17 @@ public class LinkedCellsGrid<T> implements Iterable<T> {
*
* @param object
*/
public void removeObject(T object) {
for (Iterator<ObjectWithPosition<T>> iter = totalObjects.iterator(); iter
.hasNext();) {
ObjectWithPosition<T> obj = iter.next();
if (obj.object.equals(object)) {
iter.remove();
// get the list of objects stored at the given position and
// remove the object.
VPoint pos = obj.position;
int[] gridPos = gridPos(pos);
List<T> objectsAtPos = this.grid[gridPos[0]][gridPos[1]].objects
.get(pos);
objectsAtPos.remove(object);
// if the list is empty, remove the entry at this position
if (objectsAtPos.isEmpty()) {
this.grid[gridPos[0]][gridPos[1]].objects.remove(pos);
}
}
public synchronized void removeObject(T object) {
int[] gridPos = gridPos(object.getPosition());
if(grid[gridPos[0]][gridPos[1]].objects.removeIf(element -> element.equals(object))){
size--;
}
}
public synchronized void removeObject(T object, final VPoint oldPosition) {
int[] gridPos = gridPos(oldPosition);
if(grid[gridPos[0]][gridPos[1]].objects.removeIf(element -> element.equals(object))){
size--;
}
}
......@@ -316,8 +242,20 @@ public class LinkedCellsGrid<T> implements Iterable<T> {
* Removes all objects.
*/
public void clear() {
totalObjects.clear();
this.grid = generateGrid(gridSize[0], gridSize[1]);
grid = generateGrid(gridSize[0], gridSize[1]);
size = 0;
}
public List<T> getElements() {
List<T> elements = new ArrayList<>();
for (int r = 0; r < grid.length; r++) {
// TODO [priority=medium] [task=test] changed this [20.08.2014] here 1 to r - pls check this
for (int c = 0; c < grid[r].length; c++) {
elements.addAll(grid[r][c].objects);
}
}
return elements;
}
/**
......@@ -325,31 +263,7 @@ public class LinkedCellsGrid<T> implements Iterable<T> {
*/
@Override
public Iterator<T> iterator() {
return new Iterator<T>() {
private Iterator<ObjectWithPosition<T>> objectsIter = totalObjects
.iterator();
@Override
public boolean hasNext() {
return objectsIter.hasNext();
}
@Override
public T next() {
// only return the object itself, not the position
ObjectWithPosition<T> obj = objectsIter.next();
if (obj == null) {
return null;
} else {
return obj.object;
}
}
@Override
public void remove() {
objectsIter.remove();
}
};
return getElements().iterator();
}
/**
......@@ -358,7 +272,7 @@ public class LinkedCellsGrid<T> implements Iterable<T> {
* @return the size (number of different keys &lt;T&gt;) of List
*/
public int size() {
return totalObjects.size();
return size;
}
/**
......@@ -393,8 +307,6 @@ public class LinkedCellsGrid<T> implements Iterable<T> {
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = java.lang.Double.doubleToLongBits(top);
result = prime * result + (int) (temp ^ (temp >>> 32));
result = prime * result
+ ((totalObjects == null) ? 0 : totalObjects.hashCode());
temp = java.lang.Double.doubleToLongBits(width);
result = prime * result + (int) (temp ^ (temp >>> 32));
return result;
......@@ -434,13 +346,6 @@ public class LinkedCellsGrid<T> implements Iterable<T> {
.doubleToLongBits(other.top)) {
return false;
}
if (totalObjects == null) {
if (other.totalObjects != null) {
return false;
}
} else if (!totalObjects.equals(other.totalObjects)) {
return false;
}
if (java.lang.Double.doubleToLongBits(width) != java.lang.Double
.doubleToLongBits(other.width)) {
return false;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment