Starting from 2021-07-01, all LRZ GitLab users will be required to explicitly accept the GitLab Terms of Service. Please see the detailed information at and make sure that your projects conform to the requirements.

Commit 065dabd4 authored by Benedikt Zoennchen's avatar Benedikt Zoennchen
Browse files

Merge branch 'master' of

parents 280a2bc8 40bf0d23
......@@ -43,7 +43,7 @@ unit_tests_with_coverage:
- Documentation/version-control/git-hook-vadere-software
- mvn clean
- mvn -Dtest=!TestConvolution,!TestBitonicSort,!TestCLLinkedList test
- mvn -Dtest=!TestConvolution,!TestBitonicSort,!TestCLLinkedList,!TestCLOptimalStepsModel test
- python3 Tools/ContinuousIntegration/
......@@ -2,6 +2,13 @@
# In Progress: v0.7
## Added
- In package `org.vadere.simulator.util`, added `TopographyChecker` to show user if the current topography contains problems. The
`TopographyChecker` will check for overlapping `ScenarioElements` and check for inconsistence settings such as missing
TargetIDs for sources or inconsistenct speed ranges for pedestrians. See this [table](Documentation/changelLogImages/ for supported warnings and erros
as well as this [picture](Documentation/changelLogImages/TopographyChecker.png) to see which kind of overlap produces erros or warnings.
# v0.6 (2018-09-07)
## Added
# TopographyChecker Messages
## Overlapping ScenarioElements
|Type of Elemetns | TotalOvelrap/ contained in | PartialOverlap |
|Obstacle / Obstacle | WARN | ./. |
|Obstacle / Source | ERROR | ERROR |
|Obstacle / Target | ERROR | WARN |
|Obstacle / Stairs | ERROR | WARN |
|Obstacle / Ped. | ERROR | ERROR |
|Source / Source | WARN | WARN |
|Source / Target | WARN | WARN |
|Source / Stairs | WARN | WARN |
|Target / Target | WARN | WARN |
|Target / Stairs | WARN | WARN |
|Stairs / Stairs | ERROR | ERROR |
WARN Warning but simulation is possible
ERROR Error and simulation is not possible
./. Nothing to do all good
## Misc Tests
### Errors
- A Source has no targetId set but is setup to spawn pedestrians. Solution: Set targetId
- A Source has a targetId set but the target does not exist. Solution: Create target or remove unused targetId from Source.
- If the SpeedDistributionMean of a pedestrian ist not between min/max speed.
### Warnings
- A Source has no targetId set and does not spawn pedestrians. Solution: Possible error
- A Target is never used by any Source. Solution: Possible error and this will cost performance.
- The Stairs model only works for 'normal' one-step-stairs. If the tread is outside of
the range of 10cm < x < 35cm. The simulation does not make sense.
- If the speed setup of a pedestrian is bigger then 12.0 m/s (world record). This is possible an error.
......@@ -82,7 +82,7 @@
......@@ -298,9 +298,38 @@ TopographyCreator.btnConvexHull.label=Convex Hull
TopographyCreator.btnSimplePolygon.label=Simple Polygon
TopographyCreator.btnChecker.tooltip=Show Topography Checker Messages
TopographyCreator.btnMakro.tooltip=Generate not set IDs.
select_shape_tooltip=Select Shape
# TopographyChecker
TopographyChecker.source.targetIdNotFound=The following target ids where not found in the scenario.
TopographyChecker.source.noTargetIdSet=No Target Ids set for Source.
TopographyChecker.source.noTargetIdAndNoSpawn=No Target Ids set for Source with SpawnNumber 0. This might be an error.
TopographyChecker.source.idNotUnique=Multiple Sources have the same ID.
TopographyChecker.stairs.wrongTreadDim=Stair treadDepth outside of allowed dimension. target is not used in any source. Remove target to increase performance.
TopographyChecker.pedestrian.speedsetup=speedDistributionMean must be within min/max range.
TopographyChecker.pedestrian.speedNotLogical=Min or Max speed of pedestrian is bigger than world record.
TopographyChecker.pedestrian.speedIsNegative=Min or Max speed is negative.
TopographyChecker.overlap.stair.stair=Stairs cannot overlap. target and a stairs element overlap in scenario.
TopographyChecker.overlap.source.stair=A source and a stairs element overlap in scenario. source and a target element overlap in scenario.
TopographyChecker.overlap.source.source=Two source overlap. This can cause overlapping when useFreeSpaceOnly is not set. targets overlap.
TopographyChecker.overlap.obstacle.stairs.err=Stairs is completely contained in an obstacle.
TopographyChecker.overlap.obstacle.stairs.warn=Stairs contains an obstacle. This setup works put is not tested. Split in two stairs. is completely contained in an obstacle. contains an obstacle. This setup works but reduces the actual size of the target.
TopographyChecker.overlap.obstacle.source=Obstacle overlaps with a source. This setup will spawn pedestrians within the obstacle.
TopographyChecker.overlap.obstacle.obstacle=Two obstacles overlap / is enclosed completely. Delete one for better performance.
# tab titles Topography creator / postvis
......@@ -335,8 +364,12 @@ ActionSeeDiscardChanges.popup.title=Unsaved changes
SaveDespiteJsonErrors.text=There are errors in the JSON of the currently open scenario. Do you want to correct those?
SaveDespiteTopographyCheckerErrors.text=There are errors in the Topography of the currently open scenario. Do you want to correct those?
RunScenarioJsonErrors.title=Resolve JSON errors
RunScenarioJsonErrors.text=The simulation can't be started with erroneous JSON.
RunScenarioTopographyCheckerErrors.title=Resolve TopographyChecker errors
RunScenarioTopographyCheckerErrors.text=The simulation can't be started with erroneous Topography setup.
RunScenarioNotReadyToRun.text=One or more of the selected scenarios isn't ready to run. description
......@@ -297,6 +297,34 @@ TopographyCreator.btnConvexHull.label=Convexe H\u00fclle
TopographyCreator.btnSimplePolygon.label=Einfaches Polygon
TopographyCreator.btnChecker.tooltip=Topography Linter Nachrichten
TopographyCreator.btnMakro.tooltip=Erzeuge nicht gesetzte IDs.
# TopographyChecker
TopographyChecker.source.targetIdNotFound=Die folgenden Ziel-IDs wurden nicht im Szenario gefunden.
TopographyChecker.source.noTargetIdSet=In der Quelle wurden keine Ziel Ids vergeben.
TopographyChecker.source.noTargetIdAndNoSpawn=In der Quelle wurden keine Ziel Ids vergeben, aber die Spawn Anzahl ist bei 0.
TopographyChecker.source.idNotUnique=Quellen haben keine eindeutige ID.
TopographyChecker.stairs.wrongTreadDim=Stufentiefe ist au\u00dferhalb des Definitionsbereichs. Ziel wird von keiner Quelle verwendet. Entferne das Ziel um die Performance zu erh\u00f6hen
TopographyChecker.pedestrian.speedsetup=speedDistributionMean muss im Bereich min/max liegen.
TopographyChecker.pedestrian.speedNotLogical=Min or Max Geschwindigkeit ist gr\u00f6\u00dfer als Weltrekord.
TopographyChecker.pedestrian.speedIsNegative=Min or Max Geschwindigkeit ist negativ.
TopographyChecker.overlap.stair.stair=Treppen d\u00fcrfen nicht \u00fcberlappen. Ziel und eine Treppen \u00fcberlappen im Scenario.
TopographyChecker.overlap.source.stair=Eine Quelle und eine Treppe \u00fcberlappen im Scenario. Quelle und eine Ziel \u00fcberappen im Scenario.
TopographyChecker.overlap.source.source=Zwei Quellen \u00fcberlappen. Wenn useFreeSpaceOnly nicht gesetzt ist kann dies zu \u00fcberlappungen von Pedestrians f\u00fchren. Ziele \u00fcberlappen.
TopographyChecker.overlap.obstacle.stairs.err=Treppe ist komplett in einem Hinderniss eingeschossen.
TopographyChecker.overlap.obstacle.stairs.warn=Treppe hat ein Hinderiss in sich. Dies ist m\u00f6glich aber nicht getestet. Wenn m\u00f6glich in zwei treppen aufteilen. ist komplett in einem Hinderniss eingeschlossen hat ein Hinderniss in sich. Dies ist m\u00f6glich reduziert aber die tats\u00c4chliche Fl\u00c4che des Ziels.
TopographyChecker.overlap.obstacle.source=Hinderniss \u00fcberdeckt Quelle. Die f\u00fchrt dazu, dass Pedestrians im Hinderniss erzeugt werden.
TopographyChecker.overlap.obstacle.obstacle=Zwei identische bzw. eingeschlossene Obstacles gefunden. L\u00f6sche eins f\u00fcr bessere Performance
# tab titles Topography creator / postvis
......@@ -332,8 +360,12 @@ ActionSeeDiscardChanges.popup.title=Ungespeicherte \u00c4nderungen
SaveDespiteJsonErrors.title=Fehlerhaftes JSON.
SaveDespiteJsonErrors.text=Im ge\u00f6ffneten Szenario bestehen Fehler im JSON. Wollen Sie diese korrigieren?
SaveDespiteTopographyCheckerErrors.title=Fehlerhafte Topography.
SaveDespiteTopographyCheckerErrors.text=Im ge\u00f6ffneten Szenario bestehen Fehler in der Topography. Wollen Sie diese korrigieren?
RunScenarioJsonErrors.title=JSON Fehler beheben
RunScenarioJsonErrors.text=Die Simulation kann nicht mit fehlerhaftem JSON gestartet werden.
RunScenarioTopographyCheckerErrors.title=TopographyChecker Fehler beheben
RunScenarioTopographyCheckerErrors.text=Die Simulation kann nicht mit einer fehlerhaften Topography gestartet werden.
RunScenarioNotReadyToRun.text=Eines oder mehrere der ausgew\u00e4hlten Szenario sind derzeit nicht lauff\u00e4hig. bearbeiten
package org.vadere.gui.components.view;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Toolkit;
import javax.swing.BoxLayout;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
import org.fife.ui.rsyntaxtextarea.Theme;
import org.vadere.simulator.entrypoints.ReflectionAttributeModifier;
import org.vadere.gui.components.model.IDefaultModel;
import org.vadere.gui.projectview.view.JsonValidIndicator;
import org.vadere.gui.projectview.view.ProjectView;
import org.vadere.gui.projectview.view.ScenarioPanel;
import org.vadere.gui.topographycreator.model.AgentWrapper;
import org.vadere.gui.topographycreator.model.TopographyCreatorModel;
import org.vadere.simulator.util.TopographyChecker;
import org.vadere.state.attributes.Attributes;
import org.vadere.state.scenario.Pedestrian;
import org.vadere.state.scenario.ScenarioElement;
import org.vadere.state.util.StateJsonConverter;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
import java.awt.*;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
* The ScenarioElementView display's a ScenarioElement in JSON-Format.
......@@ -48,26 +42,26 @@ public class ScenarioElementView extends JPanel implements ISelectScenarioElemen
private JsonValidIndicator jsonValidIndicator;
public ScenarioElementView(final IDefaultModel defaultModel) {
this(defaultModel, null);
this(defaultModel,null, null);
public ScenarioElementView(final IDefaultModel defaultModel, final Component topComponent) {
public ScenarioElementView(final IDefaultModel defaultModel, final JsonValidIndicator jsonValidIndicator, final Component topComponent) {
this.panelModel = defaultModel;
this.jsonValidIndicator = jsonValidIndicator;
CellConstraints cc = new CellConstraints();
JScrollPane scrollPane = new JScrollPane();
scrollPane.setPreferredSize(new Dimension(1, Toolkit.getDefaultToolkit().getScreenSize().height));
if (topComponent != null) {
if (topComponent != null && this.jsonValidIndicator !=null) {
setLayout(new FormLayout("default:grow", "pref, default"));
JPanel jsonMeta = new JPanel(); // name of the scenario element and indicator of
// valid/invalid
jsonMeta.setLayout(new BoxLayout(jsonMeta, BoxLayout.Y_AXIS));
jsonValidIndicator = new JsonValidIndicator();
add(jsonMeta, cc.xy(1, 1));
......@@ -19,7 +19,6 @@ import javax.swing.*;
import java.util.*;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.prefs.Preferences;
......@@ -390,6 +389,15 @@ public class ProjectViewModel {
return false;
JEditorPane errorPanel = ScenarioPanel.getActiveTopographyErrorMsg();
if (errorPanel != null) {
errorPanel, JOptionPane.ERROR_MESSAGE);
return false;
return true;
......@@ -55,6 +55,7 @@ public class ScenarioPanel extends JPanel implements IProjectChangeListener, Pro
private ProjectViewModel model;
private static String activeJsonParsingErrorMsg = null;
private static JEditorPane activeTopographyErrorMsg = null;
ScenarioPanel(JLabel scenarioName, ProjectViewModel model) {
......@@ -324,6 +325,14 @@ public class ScenarioPanel extends JPanel implements IProjectChangeListener, Pro
postVisualizationView.loadOutputFile(trajectoryFile, scenarioRM);
public static void setActiveTopographyErrorMsg(JEditorPane msg){
activeTopographyErrorMsg = msg;
public static JEditorPane getActiveTopographyErrorMsg(){
return activeTopographyErrorMsg;
public static void setActiveJsonParsingErrorMsg(String msg) {
activeJsonParsingErrorMsg = msg;
......@@ -50,6 +50,14 @@ public class VDialogManager {
title, buttonOptions);
public static int showConfirmDialogWithBodyAndEditorPane(String title, String body, JEditorPane editorPane,
int buttonOptions) {
return JOptionPane.showConfirmDialog(
getPanelWithBodyAndTextEditorPane(body, editorPane),
title, buttonOptions);
public static void showMessageDialogWithBodyAndTextArea(String title, String body, String textAreaContent,
int messageType) {
......@@ -61,6 +69,16 @@ public class VDialogManager {
title, messageType);
public static void showMessageDialogWithBodyAndTextEditorPane(String title, String body, JEditorPane jEditorPane,
int messageType) {
"<html>" + body + "<br><br></html>",
title, messageType);
public static JPanel getPanelWithBodyAndTextArea(String body, String textAreaContent) {
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
......@@ -75,6 +93,19 @@ public class VDialogManager {
return panel;
public static JPanel getPanelWithBodyAndTextEditorPane(String body, JEditorPane jEditorPane){
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
JLabel label = new JLabel(body);
JScrollPane jsp = new JScrollPane(jEditorPane);
jsp.setPreferredSize(new Dimension(600, 300));
return panel;
public static void showMessageDialogWithTextArea(String title, String textAreaContent, int messageType) {
JScrollPane jsp = new JScrollPane(new JTextArea(textAreaContent)); // via
jsp.setPreferredSize(new Dimension(600, 300));
......@@ -93,6 +124,15 @@ public class VDialogManager {
if (ret == JOptionPane.YES_OPTION)
return false;
JEditorPane jEditorPane = ScenarioPanel.getActiveTopographyErrorMsg();
if (jEditorPane != null) {
int ret = VDialogManager.showConfirmDialogWithBodyAndEditorPane(
"<html>" + Messages.getString("SaveDespiteTopographyCheckerErrors.text") + "<br><br><html>",
jEditorPane, JOptionPane.YES_NO_OPTION);
if (ret == JOptionPane.YES_OPTION)
return false;
return true;
package org.vadere.gui.topographycreator.control;
import org.vadere.gui.components.utils.Messages;
import org.vadere.gui.components.utils.Resources;
import org.vadere.gui.projectview.view.JsonValidIndicator;
import org.vadere.gui.projectview.view.ScenarioPanel;
import org.vadere.gui.projectview.view.VDialogManager;
import org.vadere.gui.topographycreator.model.IDrawPanelModel;
import org.vadere.simulator.util.TopographyChecker;
import org.vadere.simulator.util.TopographyCheckerMessage;
import org.vadere.simulator.util.TopographyCheckerMessageType;
import org.vadere.state.scenario.ScenarioElement;
import java.awt.event.ActionEvent;
import java.util.HashMap;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import java.util.PriorityQueue;
import javax.swing.*;
import javax.swing.event.HyperlinkEvent;
public class ActionTopographyCheckerMenu extends TopographyAction implements Observer {
private final static ImageIcon iconRed = new ImageIcon(Resources.class.getResource("/icons/light_red_icon.png"));
private final static ImageIcon iconYellow = new ImageIcon(Resources.class.getResource("/icons/light_yellow_icon.png"));
private final static ImageIcon iconGreen = new ImageIcon(Resources.class.getResource("/icons/light_green_icon.png"));
private final JsonValidIndicator jsonValidIndicator;
private PriorityQueue<TopographyCheckerMessage> errorMsg;
private PriorityQueue<TopographyCheckerMessage> warnMsg;
private MsgDocument msgDocument;
public ActionTopographyCheckerMenu(String name, IDrawPanelModel<?> panelModel, JsonValidIndicator jsonValidIndicator) {
super(name, iconYellow, panelModel);
this.jsonValidIndicator = jsonValidIndicator;
this.errorMsg = new PriorityQueue<>();
this.warnMsg = new PriorityQueue<>();
* Handel click on traffic light icon and show all TopographyChecker messages generated for the
* current state of the topography.
public void actionPerformed(ActionEvent e) {
"Topography Checker",
"The following problems where found",
* After each change of the Topography which yields a valid json representation check run the
* {@link TopographyChecker} and change the icon respectively. This function also creates the
* message document presented in various dialog windows.
public void update(Observable o, Object arg) {
if (jsonValidIndicator.isValid()) {
TopographyChecker checker = new TopographyChecker(getScenarioPanelModel().getTopography());
putValue(Action.SMALL_ICON, iconGreen);
if (warnMsg.size() > 0) {
putValue(Action.SMALL_ICON, iconYellow);
if (errorMsg.size() > 0) {
putValue(Action.SMALL_ICON, iconRed);
* @return MsgDocument containing erros and warnings with links to the specific scenario element
private MsgDocument checkerMessagesToDoc() {
StringBuilder sb = new StringBuilder();
MsgDocument doc = new MsgDocument();
if (errorMsg.size() > 0) {
sb.append("<h3> Errors </h3>").append("<br>");
errorMsg.forEach(m -> msgToDocString(sb, m, doc));
if (warnMsg.size() > 0) {
if (sb.length() > 0) {
sb.append("<h3> Warnings </h3>").append("<br>");
warnMsg.forEach(m -> msgToDocString(sb, m, doc));
if (errorMsg.size() == 0 && warnMsg.size() == 0) {
sb.append("No Problems found.");
return doc;
private void msgToDocString(StringBuilder sb, TopographyCheckerMessage msg, MsgDocument doc) {
msg.getMsgTarget().getTargets().forEach(t -> {
doc.makeLink(t, sb);
sb.append(", ");
sb.append("] ");
sb.append("Reason: ").append(Messages.getString(msg.getReason().getLocalMessageId()));
if (!msg.getReasonModifier().isEmpty()) {
sb.append(" ").append(msg.getReasonModifier());
private void addMsg(List<TopographyCheckerMessage> msg) {
msg.forEach(m -> {
if (m.getMsgType().equals(TopographyCheckerMessageType.WARN)) {
} else {
msgDocument = checkerMessagesToDoc();
if (errorMsg.size() > 0) {
* Simple {@link JEditorPane} wrapper which manages the links within the document to highlight
* the {@link ScenarioElement} producing the error / warning.
class MsgDocument extends JEditorPane {
HashMap<String, ScenarioElement> linkMap;
int id;
MsgDocument() {
linkMap = new HashMap<>();
id = 0;
addHyperlinkListener(e -> {
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
ScenarioElement element = linkMap.getOrDefault(e.getDescription(), null);
if (element != null) {
void makeLink(ScenarioElement element, StringBuilder sb) {
linkMap.put("element/id/" + id, element);
sb.append("<a href='element/id/")
package org.vadere.gui.topographycreator.control;
import org.vadere.gui.topographycreator.model.IDrawPanelModel;
import java.awt.event.ActionEvent;
import javax.swing.*;
public class ActionTopographyMakroMenu extends TopographyAction {
public ActionTopographyMakroMenu(String name, ImageIcon icon, IDrawPanelModel<?> panelModel) {
super(name, icon, panelModel);
public void actionPerformed(ActionEvent e) {