Commit 07536903 authored by Benedikt Zoennchen's avatar Benedikt Zoennchen

Merge branch 'master' of https://gitlab.lrz.de/vadere/vadere

parents 1993b961 7658fc30
Pipeline #79339 failed with stages
in 54 seconds
......@@ -10,9 +10,9 @@ __pycache__/
*.py[cod]
*$py.class
**/venv/
Tools/VadereAnalysisTool/dist/
Tools/VadereAnalysisTool/build/
Tools/VadereAnalysisTool/VadereAnalysisTool.egg-info/
Tools/VadereAnalysisTools/VadereAnalysisTool/VadereAnalysisTool.egg-info/
Tools/VadereAnalysisTools/VadereAnalysisTool/build/
Tools/VadereAnalysisTools/VadereAnalysisTool/dist/
Tools/ContinuousIntegration/**/output
# C extensions
*.so
......
......@@ -46,15 +46,29 @@ unit_tests_with_coverage:
- mvn -Dtest=!TestConvolution,!TestBitonicSort,!TestCLLinkedList,!TestCLOptimalStepsModel test
- python3 Tools/ContinuousIntegration/collect_line_and_branch_coverage.py
run_origin_test:
run_scenario_files:
stage: deploy
script:
- Documentation/version-control/git-hook-vadere-software
- mvn clean
- mvn -Dmaven.test.skip=true package
- python3 Tools/VadereAnalysisTools/VadereAnalysisTool/setup.py install --user
- python3 Tools/ContinuousIntegration/run_orign_translation_test.py
- python3 Tools/ContinuousIntegration/run_vadere_console_with_all_scenario_files.py
artifacts:
paths:
- "log_dir"
expire_in: 1 week
# exclude. Finde solution an then add this test again.
# run_origin_test:
# stage: deploy
# script:
# - Documentation/version-control/git-hook-vadere-software
# - mvn clean
# - mvn -Dmaven.test.skip=true package
# - python3 Tools/VadereAnalysisTools/VadereAnalysisTool/setup.py install --user
# - python3 Tools/ContinuousIntegration/run_orign_translation_test.py
run_seed_test:
stage: deploy
......@@ -66,11 +80,3 @@ run_seed_test:
- python3 Tools/VadereAnalysisTools/VadereAnalysisTool/setup.py install --user
- python3 Tools/ContinuousIntegration/run_seed_comparison_test.py
run_scenario_files:
stage: deploy
script:
- Documentation/version-control/git-hook-vadere-software
- mvn clean
- mvn -Dmaven.test.skip=true package
- python3 Tools/ContinuousIntegration/run_vadere_console_with_all_scenario_files.py
\ No newline at end of file
......@@ -86,7 +86,7 @@ def run_simulations(test_project_path):
if __name__ == '__main__':
test_project_path = "Tools/ContinuousIntegration/run_orign_translation_test.d"
# run_simulations(test_project_path)
run_simulations(test_project_path)
output_pairs = get_output_pairs()
print("comparing {} output pairs".format(len(output_pairs)))
......
......@@ -14,6 +14,8 @@ import re
import shutil
import subprocess
import time
import argparse
def find_scenario_files(path="VadereModelTests", scenario_search_pattern = "*.scenario", exclude_patterns = ["TESTOVM", "output","legacy"]):
scenario_files = []
......@@ -36,25 +38,34 @@ def find_scenario_files(path="VadereModelTests", scenario_search_pattern = "*.sc
def run_scenario_files_with_vadere_console(scenario_files, vadere_console="VadereSimulator/target/vadere-console.jar", scenario_timeout_in_sec=60):
output_dir = "output"
log_dir = "log_dir"
if not os.path.exists(output_dir):
os.makedirs(output_dir)
if not os.path.exists(log_dir):
os.makedirs(log_dir)
total_scenario_files = len(scenario_files)
passed_scenarios = []
failed_scenarios_with_exception = []
failed_summary = []
for i, scenario_file in enumerate(scenario_files):
try:
print("Running scenario file ({}/{}): {}".format(i + 1, total_scenario_files, scenario_file))
scenario_name = os.path.basename(scenario_file).split('.')[0]
log_file = os.path.join(log_dir, scenario_name + ".log")
# Measure wall time and not CPU time simply because it is the simplest method.
wall_time_start = time.time()
# Use timout feature, check return value and capture stdout/stderr to a PIPE (use completed_process.stdout to get it).
completed_process = subprocess.run(args=["java", "-enableassertions", "-jar", vadere_console, "scenario-run", "-f", scenario_file, "-o", output_dir],
completed_process = subprocess.run(args=["java", "-enableassertions", "-jar", vadere_console,
"--logname", log_file, "scenario-run", "-f",
scenario_file, "-o", output_dir],
timeout=scenario_timeout_in_sec,
check=True,
stdout=subprocess.PIPE,
......@@ -65,10 +76,13 @@ def run_scenario_files_with_vadere_console(scenario_files, vadere_console="Vader
print("Finished scenario file ({:.1f} s): {}".format(wall_time_delta, scenario_file))
passed_scenarios.append(scenario_file)
except subprocess.TimeoutExpired as exception:
print("Scenario file failed: {}".format(scenario_file))
print("-> Reason: timeout after {} s".format(exception.timeout))
failed_summary.append("Scenario file failed: {}".format(scenario_file))
failed_summary.append("-> Reason: timeout after {} s".format(exception.timeout))
failed_scenarios_with_exception.append((scenario_file, exception))
except subprocess.CalledProcessError as exception:
prefix = ""
......@@ -76,17 +90,39 @@ def run_scenario_files_with_vadere_console(scenario_files, vadere_console="Vader
prefix = " * OSM * "
print(prefix + "Scenario file failed: {}".format(scenario_file))
print("-> Reason: non-zero return value {}".format(exception.returncode))
print(" {}".format(read_first_error_linies(exception.stderr)))
failed_summary.append(prefix + "Scenario file failed: {}".format(scenario_file))
failed_summary.append("-> Reason: non-zero return value {}".format(exception.returncode))
failed_summary.append(" {}".format(read_first_error_linies(exception.stderr)))
failed_scenarios_with_exception.append((scenario_file, exception))
if os.path.exists(output_dir):
shutil.rmtree(output_dir)
return {"passed": passed_scenarios, "failed": failed_scenarios_with_exception}
return {"passed": passed_scenarios, "failed": failed_scenarios_with_exception, "failed_summary": failed_summary}
def read_first_error_linies(error_byte_string):
err_string_lines = error_byte_string.decode('utf-8').split('\n')
if len(err_string_lines) >= 2:
return re.sub('\s+', ' ', ' '.join(err_string_lines[:2]))
else:
return 'unknown error see vadere log file.'
def print_summary(passed_and_failed_scenarios):
total_passed_scenarios = len(passed_and_failed_scenarios["passed"])
total_failed_scenarios = + len(passed_and_failed_scenarios["failed"])
total_scenarios = total_passed_scenarios + total_failed_scenarios
faild_summary = passed_and_failed_scenarios["failed_summary"]
if len(faild_summary) > 0:
print("#################")
print("# Failed Summary #")
print("#################")
for line in faild_summary:
print(line)
print("###########")
print("# Summary #")
......@@ -96,17 +132,18 @@ def print_summary(passed_and_failed_scenarios):
print("Passed: {}".format(total_passed_scenarios))
print("Failed: {}".format(total_failed_scenarios))
if __name__ == "__main__":
def run_all():
long_running_scenarios = [
"basic_4_1_wall_gnm1",
"queueing",
"rimea_09",
"rimea_11",
"TestSFM",
"thin_wall_and_closer_source_nelder_mead_ok",
"thin_wall_and_closer_source_pso_could_fail",
"rimea_04_flow_osm1_550_up",
"basic_4_1_wall_gnm1",
"queueing",
"rimea_09",
"rimea_11",
"TestSFM",
"thin_wall_and_closer_source_nelder_mead_ok",
"thin_wall_and_closer_source_pso_could_fail",
"rimea_04_flow_osm1_550_up",
"stairs_diagonal_both_1_2_+1.scenario",
]
excluded_scenarios = ["TESTOVM", "output", "legacy"]
......@@ -118,9 +155,24 @@ if __name__ == "__main__":
for scenario in long_running_scenarios:
search_pattern = "*" + scenario + "*.scenario"
scenario_files_long = find_scenario_files(scenario_search_pattern=search_pattern)
tmp_passed_and_failed_scenarios = run_scenario_files_with_vadere_console(scenario_files_long, scenario_timeout_in_sec=480)
tmp_passed_and_failed_scenarios = run_scenario_files_with_vadere_console(scenario_files_long,
scenario_timeout_in_sec=480)
passed_and_failed_scenarios["passed"].extend(tmp_passed_and_failed_scenarios["passed"])
passed_and_failed_scenarios["failed"].extend(tmp_passed_and_failed_scenarios["failed"])
passed_and_failed_scenarios["failed_summary"].extend(tmp_passed_and_failed_scenarios["failed_summary"])
return passed_and_failed_scenarios
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Run ModelTest')
parser.add_argument('--scenario', '-s', nargs='?', default='', metavar='S', help='only run one selected scenario')
args = vars(parser.parse_args())
if args['scenario'] == '':
passed_and_failed_scenarios = run_all()
else:
passed_and_failed_scenarios = run_scenario_files_with_vadere_console([args['scenario']])
print_summary(passed_and_failed_scenarios)
......
......@@ -148,7 +148,9 @@ def create_vadere_obstacles_from_points(cartesian_points):
vadere_obstacle_string = """{
"shape" : {
"type" : "POLYGON",
"points" : [ $points ]
"points" : [
$points
]
},
"id" : -1
}"""
......@@ -158,7 +160,7 @@ def create_vadere_obstacles_from_points(cartesian_points):
point_string_template = Template(vadere_point_string)
points_as_string = [point_string_template.substitute(x=x, y=y) for x, y in cartesian_points]
points_as_string_concatenated = ", ".join(points_as_string)
points_as_string_concatenated = ",\n".join(points_as_string)
vadere_obstacle_as_string = obstacle_string_template.substitute(points=points_as_string_concatenated)
......
......@@ -8,4 +8,3 @@ pyparsing==2.3.0
python-dateutil==2.7.5
pytz==2018.7
six==1.11.0
VadereAnalysisTool==0.0.4
......@@ -109,7 +109,7 @@ public class GuiScenarioCheckerMessageFormatter extends AbstractScenarioCheckerM
sb.append("] ");
}
sb.append("Reason: ").append(Messages.getString(msg.getReason().getLocalMessageId()));
sb.append("<b>Reason:</b> ").append(Messages.getString(msg.getReason().getLocalMessageId()));
if (!msg.getReasonModifier().isEmpty()) {
sb.append(" ").append(msg.getReasonModifier());
}
......
......@@ -18,6 +18,7 @@ ScenarioChecker.source.spawnAtRandomButNotAtFreeSpace=Combination isSpawnAtRando
ScenarioChecker.source.toSmall=Source is to small
ScenarioChecker.source.spawnUseNotAtFreeSpace=useFreeSpaceOnly=false is 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.topography.offset=With a big translation in the coordinate origin the simulator can produce errors. Reset offset to (0,0) and use PedestrianOffsetPositionProcessor. This Processor will write trajectories with a selected offset.
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.speedNotLogical=Min or Max speed of pedestrian is bigger than world record.
......
......@@ -18,6 +18,7 @@ ScenarioChecker.source.toSmall=Quelle ist zu klein
ScenarioChecker.source.spawnUseNotAtFreeSpace=useFreeSpaceOnly=false ist 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.stairs.wrongTreadDim=Stufentiefe ist au\u00dferhalb des Definitionsbereichs. Passen Sie die Anzahl der Stufen entsprechend an.
ScenarioChecker.topography.offset=Mit einer großen Verschiebungen des Koordinatenursprung kann es zu Fehlern in den Trajectories kommen. Verschieben Sie den Ursprung auf (0,0) und verwenden Sie den PedestrianOffsetPosition Prozessor. Dieser Prozessor erstellt Trajectories mit einem Offset.
ScenarioChecker.target.unused=Das Ziel wird von keiner Quelle verwendet. Entferne das Ziel um die Performance zu erh\u00f6hen
ScenarioChecker.pedestrian.speedsetup=speedDistributionMean muss im Bereich min/max liegen.
ScenarioChecker.pedestrian.speedNotLogical=Min or Max Geschwindigkeit ist gr\u00f6\u00dfer als Weltrekord.
......
......@@ -211,7 +211,7 @@ public class Simulation {
c.preUpdate(simTimeInSec);
}
assert assertAllPedestrianInBounds();
assert assertAllPedestrianInBounds(): "Pedestrians are outside of topography bound.";
updateCallbacks(simTimeInSec);
updateWriters(simTimeInSec);
......@@ -289,7 +289,7 @@ public class Simulation {
targetController.update(simTimeInSec);
}
topographyController.update(simTimeInSec);
topographyController.update(simTimeInSec); //rebuild CellGrid
step++;
for (Model m : models) {
......
......@@ -27,9 +27,9 @@ public class TargetController {
public TrafficLightPhase phase = TrafficLightPhase.GREEN;
public TargetController(Topography scenario, Target target) {
public TargetController(Topography topography, Target target) {
this.target = target;
this.topography = scenario;
this.topography = topography;
if (this.target.isStartingWithRedLight()) {
phase = TrafficLightPhase.RED;
......
......@@ -21,6 +21,9 @@ public class VadereConsole {
private final static Logger logger = Logger.getLogger(VadereConsole.class);
public static void main(String[] args) {
// rimea_01_pathway_gnm1.scenario rimea_04_flow_gnm1_050_h.scenario
// String[] tmp = {"scenario-run", "-f", "VadereModelTests/TestGNM/scenarios/rimea_04_flow_gnm1_050_h.scenario"};
// args = tmp;
ArgumentParser parser = createArgumentParser();
try {
......
......@@ -179,7 +179,10 @@ public abstract class ODEModel<T extends DynamicElement, TAttributes extends Att
equations.getVelocity(counter, y, newVelocity);
// set data to ped
VPoint oldPosition = element.getPosition();
setPosition(element, newPos);
topography.moveElement(element, oldPosition);
setVelocity(element, new Vector2D(newVelocity[0], newVelocity[1]));
counter++;
}
......
package org.vadere.simulator.projects.dataprocessing.processor;
import org.vadere.annotation.factories.dataprocessors.DataProcessorClass;
import org.vadere.simulator.control.SimulationState;
import org.vadere.simulator.projects.dataprocessing.ProcessorManager;
import org.vadere.simulator.projects.dataprocessing.datakey.PedestrianIdKey;
import org.vadere.simulator.projects.dataprocessing.datakey.TimestepKey;
import org.vadere.simulator.projects.dataprocessing.datakey.TimestepPedestrianIdKey;
import org.vadere.state.attributes.processor.AttributesOffsetPositionProcessor;
import org.vadere.state.scenario.Pedestrian;
import org.vadere.util.geometry.shapes.VPoint;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @author Mario Teixeira Parente
*/
@DataProcessorClass()
public class PedestrianOffsetPositionProcessor extends DataProcessor<TimestepPedestrianIdKey, VPoint> {
public PedestrianOffsetPositionProcessor() {
super("x_offset", "y_offset");
setAttributes(new AttributesOffsetPositionProcessor());
}
Map<PedestrianIdKey, VPoint> getPositions(TimestepKey timestepKey) {
return this.getData().entrySet().stream()
.filter(e -> e.getKey().getTimestep().equals(timestepKey.getTimestep()))
.collect(Collectors.toMap(e -> new PedestrianIdKey(e.getKey().getPedestrianId()), Map.Entry::getValue));
}
@Override
protected void doUpdate(final SimulationState state) {
Integer timeStep = state.getStep();
AttributesOffsetPositionProcessor attr = (AttributesOffsetPositionProcessor) getAttributes();
for (Pedestrian p : state.getTopography().getElements(Pedestrian.class)) {
this.putValue(new TimestepPedestrianIdKey(timeStep, p.getId()), p.getPosition().add(attr.getOffset()));
}
}
@Override
public void init(final ProcessorManager manager) {
super.init(manager);
}
@Override
public String[] toStrings(TimestepPedestrianIdKey key) {
VPoint p = this.getValue(key);
if(p == null) {
return new String[]{Double.toString(0), Double.toString(0)};
}
else {
return new String[]{Double.toString(p.x), Double.toString(p.y)};
}
//return new String[]{Double.toString(p.x), Double.toString(p.y)};
}
}
......@@ -8,6 +8,7 @@ import org.vadere.simulator.utils.scenariochecker.checks.topography.PedestrianSp
import org.vadere.simulator.utils.scenariochecker.checks.topography.SourceMinRadiusCheck;
import org.vadere.simulator.utils.scenariochecker.checks.topography.SourceSpawnSettingCheck;
import org.vadere.simulator.utils.scenariochecker.checks.topography.StairTreadSanityCheck;
import org.vadere.simulator.utils.scenariochecker.checks.topography.TopographyOffsetCheck;
import org.vadere.simulator.utils.scenariochecker.checks.topography.TopographyOverlapCheck;
import org.vadere.simulator.utils.scenariochecker.checks.topography.UniqueSourceIdCheck;
import org.vadere.simulator.utils.scenariochecker.checks.topography.UnusedTargetsCheck;
......@@ -65,6 +66,7 @@ public class ScenarioChecker {
ret.addAll(checkSimulationAttribues());
ret.addAll(checkSourceSpawnSetting());
ret.addAll(checkMinSourceRadius());
ret.addAll(runCheck(new TopographyOffsetCheck()));
return ret;
}
......
......@@ -17,6 +17,7 @@ public enum ScenarioCheckerReason {
SOURCE_TO_SMALL("ScenarioChecker.source.toSmall"),
SOURCE_SPAWN_USE_NOT_FREE_SPACE("ScenarioChecker.source.spawnUseNotAtFreeSpace"),
STAIRS_TREAD_DIM_WRONG("ScenarioChecker.stairs.wrongTreadDim"),
TOPOGRAPHY_OFFSET("ScenarioChecker.topography.offset"),
OVERLAP_STAIR_STAIR("ScenarioChecker.overlap.stair.stair"),
OVERLAP_TARGET_TARGET("ScenarioChecker.overlap.target.target"),
......
package org.vadere.simulator.utils.scenariochecker.checks.topography;
import org.vadere.simulator.utils.scenariochecker.ScenarioCheckerMessage;
import org.vadere.simulator.utils.scenariochecker.ScenarioCheckerReason;
import org.vadere.simulator.utils.scenariochecker.checks.AbstractScenarioCheck;
import org.vadere.simulator.utils.scenariochecker.checks.TopographyCheckerTest;
import org.vadere.state.scenario.Topography;
import java.util.PriorityQueue;
public class TopographyOffsetCheck extends AbstractScenarioCheck implements TopographyCheckerTest {
@Override
public PriorityQueue<ScenarioCheckerMessage> runScenarioCheckerTest(Topography topography) {
PriorityQueue<ScenarioCheckerMessage> ret = new PriorityQueue<>();
if (topography.getBounds().x != 0.0 || topography.getBounds().y != 0.0){
ret.add(msgBuilder.topographyWarning().reason(ScenarioCheckerReason.TOPOGRAPHY_OFFSET).build());
}
return ret;
}
}
package org.vadere.simulator.utils.scenariochecker.checks.topography;
import org.junit.Test;
import org.vadere.simulator.utils.TopographyTestBuilder;
import org.vadere.simulator.utils.scenariochecker.ScenarioChecker;
import org.vadere.simulator.utils.scenariochecker.ScenarioCheckerMessage;
import org.vadere.simulator.utils.scenariochecker.ScenarioCheckerMessageType;
import org.vadere.simulator.utils.scenariochecker.ScenarioCheckerReason;
import org.vadere.state.scenario.Topography;
import org.vadere.util.geometry.shapes.VRectangle;
import java.util.PriorityQueue;
import static org.junit.Assert.*;
public class TopographyOffsetCheckTest {
@Test
public void runScenarioCheckerTestNoWarning() {
Topography topography = new Topography();
topography.getAttributes().setBounds(new VRectangle(0.0, 0.0 , 10 ,12));
TopographyOffsetCheck check = new TopographyOffsetCheck();
PriorityQueue<ScenarioCheckerMessage> ret = check.runScenarioCheckerTest(topography);
assertEquals(0, ret.size());
}
@Test
public void runScenarioCheckerTestWarning1() {
Topography topography = new Topography();
topography.getAttributes().setBounds(new VRectangle(0.1, 0.0 , 10 ,12));
TopographyOffsetCheck check = new TopographyOffsetCheck();
PriorityQueue<ScenarioCheckerMessage> ret = check.runScenarioCheckerTest(topography);
assertEquals(1, ret.size());
assertEquals(ScenarioCheckerReason.TOPOGRAPHY_OFFSET, ret.poll().getReason());
}
@Test
public void runScenarioCheckerTestWarning2() {
Topography topography = new Topography();
topography.getAttributes().setBounds(new VRectangle(0.0, 0.1 , 10 ,12));
TopographyOffsetCheck check = new TopographyOffsetCheck();
PriorityQueue<ScenarioCheckerMessage> ret = check.runScenarioCheckerTest(topography);
assertEquals(1, ret.size());
assertEquals(ScenarioCheckerReason.TOPOGRAPHY_OFFSET, ret.poll().getReason());
}
@Test
public void runScenarioCheckerTestWarning3() {
Topography topography = new Topography();
topography.getAttributes().setBounds(new VRectangle(500000, 500000 , 10 ,12));
TopographyOffsetCheck check = new TopographyOffsetCheck();
PriorityQueue<ScenarioCheckerMessage> ret = check.runScenarioCheckerTest(topography);
assertEquals(1, ret.size());
assertEquals(ScenarioCheckerReason.TOPOGRAPHY_OFFSET, ret.poll().getReason());
}
}
\ No newline at end of file
package org.vadere.state.attributes.processor;
import org.vadere.util.geometry.shapes.VPoint;
public class AttributesOffsetPositionProcessor extends AttributesProcessor {
private VPoint offset = new VPoint(0,0);
public VPoint getOffset() {
return offset;
}
public void setOffset(VPoint offset) {
checkSealed();
this.offset = offset;
}
}
......@@ -61,7 +61,9 @@ public class DynamicElementContainer<T extends DynamicElement> {
this.elementMap.put(element.getId(), element);
this.cellsElements.addObject(element);
assert (elementMap.size() == cellsElements.size());
assert (elementMap.size() == cellsElements.size())
: "Number of pedestrians in LinkedCellGrid does not match number of pedestrians" +
" in topography";
for (DynamicElementAddListener<T> listener : addListener) {
listener.elementAdded(element);
......@@ -71,7 +73,10 @@ public class DynamicElementContainer<T extends DynamicElement> {
public synchronized void moveElement(T element, VPoint oldPosition) {
this.cellsElements.moveObject(element, oldPosition);
assert (elementMap.size() == cellsElements.size());
assert (elementMap.size() == cellsElements.size())
: "Number of pedestrians in LinkedCellGrid does not match number of pedestrians" +
" in topography";
for (DynamicElementMoveListener<T> listener : moveListener) {
listener.elementMove(element);
}
......@@ -81,7 +86,9 @@ public class DynamicElementContainer<T extends DynamicElement> {
this.elementMap.remove(element.getId());
this.cellsElements.removeObject(element);
assert (elementMap.size() == cellsElements.size());
assert (elementMap.size() == cellsElements.size())
: "Number of pedestrians in LinkedCellGrid does not match number of pedestrians" +
" in topography";
for (DynamicElementRemoveListener<T> listener : removeListener) {
listener.elementRemoved(element);
}
......
package org.vadere.state.scenario;
import org.vadere.util.geometry.shapes.VPoint;
public interface DynamicElementMover {
/**
* @param element the DynamicElement which was moved to a new position
* @param oldPosition the old potion the DynamicElement was prior to this call. (The new position is contained in the element)
*/
<T extends DynamicElement> void moveElement(T element, final VPoint oldPosition);
<T extends DynamicElement> void addElement(T element);
<T extends DynamicElement> void removeElement(T element);
}
......@@ -30,7 +30,7 @@ import org.vadere.util.geometry.shapes.VPolygon;
import org.vadere.util.geometry.shapes.VShape;
@JsonIgnoreProperties(value = {"allOtherAttributes", "obstacleDistanceFunction"})
public class Topography {
public class Topography implements DynamicElementMover{
/** Transient to prevent JSON serialization. */
private static Logger logger = Logger.getLogger(Topography.class);
......@@ -216,14 +216,17 @@ public class Topography {
return getContainer(elementType).getElement(id);
}
@Override
public <T extends DynamicElement> void addElement(T element) {
((DynamicElementContainer<T>) getContainer(element.getClass())).addElement(element);
}
@Override
public <T extends DynamicElement> void removeElement(T element) {
((DynamicElementContainer<T>) getContainer(element.getClass())).removeElement(element);
}
@Override
public <T extends DynamicElement> void moveElement(T element, final VPoint oldPosition) {
((DynamicElementContainer<T>) getContainer(element.getClass())).moveElement(element, oldPosition);
}
......
......@@ -76,6 +76,33 @@ public class LinkedCellsGrid<T extends PointPositioned> implements Iterable<T> {
}
}
private class ContainerisedElement {
final private int[] cell;
final private T object;
ContainerisedElement(int[] cell, T object){
this.cell = cell;
this.object = object;
}
public int[] getCell() {
return cell;
}
public T getObject() {
return object;
}
@Override
public String toString() {
return "ContainerisedElement{" +
"cell=" + Arrays.toString(cell) +
", object=" + object +
", pos= " + ((PointPositioned)object).getPosition() +
'}';
}
}