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

Commit 30789e14 authored by Benedikt Zoennchen's avatar Benedikt Zoennchen
Browse files

Merge branch 'dev/granularPostVis' into 'master'

Dev/granular post vis

See merge request !72
parents b7b56c02 13b33141
Pipeline #127214 canceled with stages
......@@ -204,6 +204,7 @@ OutputprocessorsView.dataProcessor.text={Processor: ""}
AdjustPanel.lblVelocity.text=FPS
AdjustPanel.lblTime=Time
AdjustPanel.lblStep.text=Timestep
AdjustPanel.lblVisTime.text=Res.
ProjectView.warning.lwjgl.title=Warning
ProjectView.warning.opencl.title=Warning
......
......@@ -209,6 +209,7 @@ OutputprocessorsView.dataProcessor.text={"Processor": ""}
AdjustPanel.lblVelocity.text=FPS
AdjustPanel.lblTime=Zeit
AdjustPanel.lblStep.text=Zeitschritt
AdjustPanel.lblVisTime.text=Aufl.
ProjectView.mntmOutputToSceneario.text=Generiere Szenario
ProjectView.mntmRunOutput.text=Offline erneut starten
......
......@@ -135,8 +135,26 @@ public abstract class DefaultModel<T extends DefaultConfig> extends Observable i
@Override
public boolean setScale(final double scale) {
boolean hasChanged = true;
double oldScale = scaleFactor;
boolean hasChanged = setScaleWithoutChangingViewport(scale);
// update the viewport, since it depends on the scaleFactor
if (hasChanged) {
Rectangle2D.Double oldViewPort = getViewportBound();
Rectangle2D.Double newViewPort = new Rectangle2D.Double(
oldViewPort.getMinX(),
oldViewPort.getMinY(),
oldViewPort.getWidth() * oldScale / scaleFactor,
oldViewPort.getHeight() * oldScale / scaleFactor);
setViewportBound(newViewPort);
setChanged();
}
return hasChanged;
}
@Override
public boolean setScaleWithoutChangingViewport(double scale) {
boolean hasChanged = true;
if (scale < MIN_SCALE_FACTOR) {
this.scaleFactor = MIN_SCALE_FACTOR;
......@@ -148,17 +166,10 @@ public abstract class DefaultModel<T extends DefaultConfig> extends Observable i
hasChanged = false;
}
// update the viewport, since it depends on the scaleFactor
if (hasChanged) {
Rectangle2D.Double oldViewPort = getViewportBound();
Rectangle2D.Double newViewPort = new Rectangle2D.Double(
oldViewPort.getMinX(),
oldViewPort.getMinY(),
oldViewPort.getWidth() * oldScale / scaleFactor,
oldViewPort.getHeight() * oldScale / scaleFactor);
setViewportBound(newViewPort);
if(hasChanged) {
setChanged();
}
return hasChanged;
}
......@@ -254,7 +265,7 @@ public abstract class DefaultModel<T extends DefaultConfig> extends Observable i
}
@Override
public void setViewportBound(final Rectangle2D.Double viewportBound) {
public synchronized void setViewportBound(final Rectangle2D.Double viewportBound) {
Rectangle2D.Double oldViewportBound = this.viewportBound;
if (!oldViewportBound.equals(viewportBound)) {
......
......@@ -28,6 +28,8 @@ public interface IDefaultModel<T extends DefaultConfig> extends Iterable<Scenari
boolean setScale(final double scale);
boolean setScaleWithoutChangingViewport(final double scale);
void notifyScaleListeners();
Color getScenarioElementColor(final ScenarioElementType elementType);
......
......@@ -87,7 +87,7 @@ public abstract class SimulationModel<T extends DefaultSimulationConfig> extends
}*/
@Override
public void notifyObservers() {
public synchronized void notifyObservers() {
// synchronized (config) {
if (config.hasChanged()) {
setChanged();
......
......@@ -59,37 +59,45 @@ public abstract class DefaultRenderer {
* @param height
*/
public void render(final Graphics2D targetGraphics2D, final int width, final int height) {
render(targetGraphics2D, 0, 0, width, height);
synchronized (defaultModel) {
render(targetGraphics2D, 0, 0, width, height);
}
}
public void render(final Graphics2D targetGraphics2D, final int x, final int y, final int width, final int height) {
targetGraphics2D.drawImage(renderImage(width, height), x, y, null);
targetGraphics2D.dispose();
synchronized (defaultModel) {
targetGraphics2D.drawImage(renderImage(width, height), x, y, null);
targetGraphics2D.dispose();
}
}
public void renderGraphics(final Graphics2D targetGraphics2D, final int width, final int height) {
targetGraphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
synchronized (defaultModel) {
targetGraphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// (1) clear background
targetGraphics2D.setColor(Color.GRAY);
//targetGraphics2D.fill();
targetGraphics2D.fillRect(0, 0, width, height);
// (1) clear background
targetGraphics2D.setColor(Color.GRAY);
//targetGraphics2D.fill();
targetGraphics2D.fillRect(0, 0, width, height);
// (2) render everything which can be rendered before the transformation
renderPreTransformation(targetGraphics2D, width, height);
// (2) render everything which can be rendered before the transformation
renderPreTransformation(targetGraphics2D, width, height);
// (3)
transformGraphics(targetGraphics2D);
// (3)
transformGraphics(targetGraphics2D);
// (4) render everything which can be rendered after the transformation
renderPostTransformation(targetGraphics2D, width, height);
// (4) render everything which can be rendered after the transformation
renderPostTransformation(targetGraphics2D, width, height);
}
}
public BufferedImage renderImage(final int width, final int height) {
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D bufferGraphics2D = (Graphics2D) image.getGraphics();
renderGraphics(bufferGraphics2D, width, height);
return image;
synchronized (defaultModel) {
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D bufferGraphics2D = (Graphics2D) image.getGraphics();
renderGraphics(bufferGraphics2D, width, height);
return image;
}
}
public void setLogo(final BufferedImage logo) {
......@@ -99,33 +107,36 @@ public abstract class DefaultRenderer {
protected void renderPreTransformation(final Graphics2D graphics2D, final int width, final int height) {}
protected void renderPostTransformation(final Graphics2D graphics2D, final int width, final int height) {
graphics2D.setColor(Color.WHITE);
Rectangle2D.Double topographyBound = defaultModel.getTopographyBound();
fill(new VRectangle(
topographyBound.getMinX() + defaultModel.getBoundingBoxWidth(),
topographyBound.getMinY() + defaultModel.getBoundingBoxWidth(),
(defaultModel.getTopographyBound().getWidth() - defaultModel.getBoundingBoxWidth() * 2),
(defaultModel.getTopographyBound().getHeight() - defaultModel.getBoundingBoxWidth() * 2)), graphics2D);
synchronized (defaultModel) {
graphics2D.setColor(Color.WHITE);
Rectangle2D.Double topographyBound = defaultModel.getTopographyBound();
fill(new VRectangle(
topographyBound.getMinX() + defaultModel.getBoundingBoxWidth(),
topographyBound.getMinY() + defaultModel.getBoundingBoxWidth(),
(defaultModel.getTopographyBound().getWidth() - defaultModel.getBoundingBoxWidth() * 2),
(defaultModel.getTopographyBound().getHeight() - defaultModel.getBoundingBoxWidth() * 2)), graphics2D);
}
}
protected void transformGraphics(final Graphics2D graphics2D) {
Rectangle2D.Double topographyBound = defaultModel.getTopographyBound();
mirrowHorizonzal(graphics2D, (int) (topographyBound.getHeight() * defaultModel.getScaleFactor()));
graphics2D.scale(defaultModel.getScaleFactor(), defaultModel.getScaleFactor());
synchronized (defaultModel) {
Rectangle2D.Double topographyBound = defaultModel.getTopographyBound();
mirrowHorizonzal(graphics2D, (int) (topographyBound.getHeight() * defaultModel.getScaleFactor()));
graphics2D.scale(defaultModel.getScaleFactor(), defaultModel.getScaleFactor());
//graphics2D.translate(-topographyBound.getMinX(), -topographyBound.getMinY());
//graphics2D.translate(-topographyBound.getMinX(), -topographyBound.getMinY());
/*
* This calculation we need since the viewport.y = 0 if the user scrolls to the bottom
*/
Rectangle2D.Double viewportBound = defaultModel.getViewportBound();
double dy = topographyBound.getHeight() - viewportBound.getHeight();
graphics2D.translate(-viewportBound.getX(), Math.max((dy - viewportBound.getY()), - viewportBound.getY()));
// graphics2D.translate(+viewportBound.getX(), -Math.max((dy - viewportBound.getY()), 0));
/*
* This calculation we need since the viewport.y = 0 if the user scrolls to the bottom
*/
Rectangle2D.Double viewportBound = defaultModel.getViewportBound();
double dy = topographyBound.getHeight() - viewportBound.getHeight();
graphics2D.translate(-viewportBound.getX(), Math.max((dy - viewportBound.getY()), - viewportBound.getY()));
// graphics2D.translate(+viewportBound.getX(), -Math.max((dy - viewportBound.getY()), 0));
}
}
protected void renderScenarioElement(final Iterable<? extends ScenarioElement> elements, final Graphics2D g,
......
......@@ -11,6 +11,7 @@ import org.vadere.gui.postvisualization.utils.ImageGenerator;
import org.vadere.gui.postvisualization.utils.SVGGenerator;
import org.vadere.gui.postvisualization.utils.TikzGenerator;
import org.vadere.gui.postvisualization.view.PostvisualizationRenderer;
import org.vadere.simulator.projects.Scenario;
import org.vadere.simulator.projects.io.IOOutput;
import org.vadere.simulator.projects.io.TrajectoryReader;
import org.vadere.util.io.IOUtils;
......@@ -22,7 +23,6 @@ import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Locale;
import java.util.Optional;
......@@ -118,8 +118,9 @@ public class PostVisualizationConsole {
Optional<File> scenarioFile = IOUtils.getFirstFile(path.toFile(), IOUtils.SCENARIO_FILE_EXTENSION);
if (trajectoryFile.isPresent() && scenarioFile.isPresent()) {
TrajectoryReader reader = new TrajectoryReader(trajectoryFile.get().toPath());
model.init(reader.readFile(), IOOutput.readScenario(scenarioFile.get().toPath()), trajectoryFile.get().getParent());
Scenario scenario = IOOutput.readScenario(scenarioFile.get().toPath());
TrajectoryReader reader = new TrajectoryReader(trajectoryFile.get().toPath(), scenario);
model.init(reader.readFile(), scenario, trajectoryFile.get().getParent());
} else {
System.err.println("could not find trajectory or scenario file in: " + outputDirectoryPath);
}
......@@ -142,7 +143,7 @@ public class PostVisualizationConsole {
if (step != -1) {
model.setStep(step);
} else {
model.setTime(time);
model.setVisTime(time);
}
if (showGroups){
......
......@@ -2,13 +2,15 @@ package org.vadere.gui.postvisualization.control;
import org.vadere.gui.postvisualization.model.PostvisualizationModel;
import org.vadere.state.simulation.Step;
import org.vadere.util.logging.Logger;
import java.util.Optional;
public class Player implements Runnable {
private static Logger logger = Logger.getLogger(Player.class);
private static volatile Player instance;
private Thread currentThread;
private int currentStep;
enum State {
STOPPED, PAUSED, RUNNING
......@@ -29,7 +31,6 @@ public class Player implements Runnable {
private Player(final PostvisualizationModel model) {
this.model = model;
this.currentStep = 1;
this.currentThread = null;
state = State.STOPPED;
}
......@@ -41,7 +42,6 @@ public class Player implements Runnable {
public void stop() {
state = State.STOPPED;
running = false;
currentStep = 1;
if (currentThread != null) {
currentThread.interrupt();
......@@ -63,8 +63,6 @@ public class Player implements Runnable {
currentThread.start();
}
state = State.RUNNING;
model.getStep().ifPresent(s -> currentStep = s.getStepNumber());
synchronized (model) {
model.notifyAll();
}
......@@ -79,8 +77,8 @@ public class Player implements Runnable {
}
}
private boolean isRunable() {
return model.getStep().isPresent() && model.getFirstStep().isPresent() && model.getLastStep().isPresent();
private boolean isRunnable() {
return !model.isEmpty();
}
@Override
......@@ -91,17 +89,16 @@ public class Player implements Runnable {
// synchronized (model) {
switch (state) {
case RUNNING: {
if (isRunable()) {
if (model.getLastStep().get().getStepNumber() > model.getStep().get().getStepNumber()) {
currentStep = model.getStep().get().getStepNumber() + 1;
model.setStep(currentStep);
} else {
pause();
if (isRunnable()) {
double newSimeTimeInSec = model.getSimTimeInSec() + model.getVisTimeStepLength();
if(model.getSimTimeInSec() >= model.getMaxSimTimeInSec()) {
newSimeTimeInSec = 0;
}
model.setVisTime(newSimeTimeInSec);
}
}
model.notifyObservers();
break;
model.notifyObservers();
break;
case PAUSED: {
synchronized (model) {
......@@ -112,17 +109,18 @@ public class Player implements Runnable {
}
}
}
break;
default:
break;
break;
default: break;
}
// }
diffMs = System.currentTimeMillis() - ms;
sleepTimeMS = (int) Math.round((1000.0 - diffMs) / model.config.getFps());
try {
Thread.sleep(Math.max(0, sleepTimeMS));
} catch (InterruptedException e) {
logger.info("Player interrupted while sleeping");
sleepTimeMS = (int) Math.round((1000.0 / model.config.getFps() - diffMs));
if(sleepTimeMS > 0) {
try {
Thread.sleep(Math.max(0, sleepTimeMS));
} catch (InterruptedException e) {
logger.info("Player interrupted while sleeping");
}
}
}
}
......
......@@ -7,6 +7,7 @@ import org.vadere.gui.components.model.SimulationModel;
import org.vadere.gui.postvisualization.control.TableListenerLogicExpression;
import org.vadere.gui.postvisualization.utils.PotentialFieldContainer;
import org.vadere.simulator.projects.Scenario;
import org.vadere.state.attributes.AttributesSimulation;
import org.vadere.state.scenario.Agent;
import org.vadere.state.scenario.Pedestrian;
import org.vadere.state.scenario.ScenarioElement;
......@@ -39,7 +40,15 @@ public class PostvisualizationModel extends SimulationModel<PostvisualizationCon
private static Logger logger = Logger.getLogger(PostvisualizationModel.class);
private Step step;
//private Step step;
//private double ratio;
private double visTime;
private double visTimeStepLength;
private double simTimeStepLength;
private int topographyId;
......@@ -55,7 +64,7 @@ public class PostvisualizationModel extends SimulationModel<PostvisualizationCon
private Map<Step, List<Agent>> agentsByStep;
private Comparator<Step> stepComparator = (s1, s2) -> s1.getStepNumber() - s2.getStepNumber();
private Comparator<Step> stepComparator = Comparator.comparingInt(Step::getStepNumber);
private List<Step> steps;
......@@ -73,7 +82,9 @@ public class PostvisualizationModel extends SimulationModel<PostvisualizationCon
this.potentialContainer = null;
this.pedestrianColorTableModel = new PedestrianColorTableModel();
this.steps = new ArrayList<>();
this.simTimeStepLength = new AttributesSimulation().getSimTimeStepLength();
this.visTimeStepLength = this.simTimeStepLength;
this.visTime = 0;
/*for (int i = 0; i < 5; i++) {
try {
colorEvalFunctions.put(i, new JsonLogicParser("false").parse());
......@@ -93,7 +104,6 @@ public class PostvisualizationModel extends SimulationModel<PostvisualizationCon
colorEvalFunctions.remove(row);
}
/**
* Initialize the {@link PostvisualizationModel}.
*
......@@ -102,6 +112,7 @@ public class PostvisualizationModel extends SimulationModel<PostvisualizationCon
* @param projectPath the path to the project.
*/
public void init(final Map<Step, List<Agent>> agentsByStep, final Scenario scenario, final String projectPath) {
simTimeStepLength = scenario.getAttributesSimulation().getSimTimeStepLength();
logger.info("start the initialization of the PostvisualizationModel.");
init(scenario, projectPath);
this.agentsByStep = agentsByStep;
......@@ -124,7 +135,7 @@ public class PostvisualizationModel extends SimulationModel<PostvisualizationCon
for(Agent agent : agentsByStep.get(map.get(stepNumber))) {
if(!trajectories.containsKey(agent.getId())) {
trajectories.put(agent.getId(), new Trajectory(agent.getId()));
trajectories.put(agent.getId(), new Trajectory(agent.getId(), simTimeStepLength));
}
trajectories.get(agent.getId()).addStep(map.get(stepNumber), agent);
}
......@@ -138,10 +149,14 @@ public class PostvisualizationModel extends SimulationModel<PostvisualizationCon
trajectory.fill();
}
this.step = !steps.isEmpty() ? steps.get(0) : null;
this.visTime = 0;
logger.info("finished init postvis model");
}
private double stepToTime(final int step) {
return visTimeStepLength * (step - 1);
}
public void init(final Scenario vadere, final String projectPath) {
this.vadere = vadere;
this.agentsByStep = new HashMap<>();
......@@ -151,6 +166,18 @@ public class PostvisualizationModel extends SimulationModel<PostvisualizationCon
this.outputPath = projectPath;
}
public double getVisTimeStepLength() {
return visTimeStepLength;
}
public synchronized void setVisTimeStepLength(final double visTimeStepLength) {
this.visTimeStepLength = visTimeStepLength;
}
public double getSimTimeStepLength() {
return simTimeStepLength;
}
public Optional<Step> getLastStep() {
if (!steps.isEmpty()) {
return Optional.of(steps.get(steps.size() - 1));
......@@ -167,6 +194,14 @@ public class PostvisualizationModel extends SimulationModel<PostvisualizationCon
}
}
public Step fist() {
return getFirstStep().get();
}
public Step last() {
return getLastStep().get();
}
public Scenario getScenarioRunManager() {
return vadere;
}
......@@ -175,8 +210,8 @@ public class PostvisualizationModel extends SimulationModel<PostvisualizationCon
public Function<IPoint, Double> getPotentialField() {
Function<IPoint, Double> f = p -> 0.0;
try {
if (potentialContainer != null && step != null) {
final CellGrid potentialField = potentialContainer.getPotentialField(step.getStepNumber());
if (potentialContainer != null) {
final CellGrid potentialField = potentialContainer.getPotentialField(Step.toFloorStep(getSimTimeInSec(), getSimTimeStepLength()).getStepNumber());
f = potentialField.getInterpolationFunction();
}
} catch (IOException e) {
......@@ -188,12 +223,12 @@ public class PostvisualizationModel extends SimulationModel<PostvisualizationCon
@Override
public boolean isFloorFieldAvailable() {
return potentialContainer != null && step != null;
return potentialContainer != null;
}
@Override
public Collection<Agent> getAgents() {
return getAlivePedestrians().map(t -> t.getAgent(step)).filter(ped -> ped.isPresent()).map(ped -> ped.get())
return getAlivePedestrians().map(t -> t.getAgent(getSimTimeInSec())).filter(ped -> ped.isPresent()).map(ped -> ped.get())
.collect(Collectors.toList());
}
......@@ -212,22 +247,49 @@ public class PostvisualizationModel extends SimulationModel<PostvisualizationCon
return config.getGridWidth();
}
public synchronized Optional<Step> getStep() {
/*public synchronized Optional<Step> getStep() {
return Optional.ofNullable(step);
}
public synchronized Optional<Double> getRatio() {
return Optional.ofNullable(ratio);
}*/
public int getStepCount() {
return steps.size();
}
public synchronized void setTime(final double time) {
if (steps.size() >= 2 && steps.get(1).getSimTimeInSec().isPresent()
&& steps.get(0).getSimTimeInSec().isPresent()) {
double dt = steps.get(1).getSimTimeInSec().get() - steps.get(0).getSimTimeInSec().get();
int step = (int) Math.round(time / dt) + 1;
setStep(step);
} else if (1.0e-10 < Math.abs(time)) {
setStep(1);
public synchronized void setVisTime(final double visTimeInSec) {
if(!isEmpty()) {
double validVisTime = Math.min(Step.toSimTimeInSec(last(), simTimeStepLength), Math.max(Step.toSimTimeInSec(fist(), simTimeStepLength), visTimeInSec));
if(this.visTime != validVisTime) {
this.visTime = validVisTime;
if (isVoronoiDiagramAvailable() && isVoronoiDiagramVisible()) {
synchronized(getVoronoiDiagram()) {
getVoronoiDiagram().computeVoronoiDiagram(
trajectories.values().stream()
.filter(t -> t.isAlive(visTime))
.map(t -> t.getAgent(visTime).get().getPosition())
.collect(Collectors.toList()));
}
}
if (isElementSelected() && getSelectedElement() instanceof Pedestrian) {
Trajectory trajectory = trajectories.get(getSelectedElement().getId());
if (trajectory != null) {
Optional<Agent> ped = trajectory.getAgent(visTime);
setSelectedElement(ped.orElse(null));
}
}
// so the new pedestrian position is displayed!
if (isElementSelected()) {
notifySelectSecenarioElementListener(getSelectedElement());
}
setChanged();
}
}
}
......@@ -258,9 +320,34 @@ public class PostvisualizationModel extends SimulationModel<PostvisualizationCon
return pedestrianColorTableModel;
}
public synchronized void setStep(final int step) {
// speed up the computation if every step is available, which is the default case!
Optional<Step> optionalStep = steps.size() >= step && steps.get(step - 1).getStepNumber() == step
/*public synchronized void setStep(final double visTimeInSec) {
this.visTime = visTimeInSec;
if (isVoronoiDiagramAvailable() && isVoronoiDiagramVisible()) {
synchronized(getVoronoiDiagram()) {
getVoronoiDiagram().computeVoronoiDiagram(
trajectories.values().stream()
.filter(t -> t.isAlive(visTimeInSec))
.map(t -> t.getAgent(visTimeInSec).get().getPosition())
.collect(Collectors.toList()));
}
}
if (isElementSelected() && getSelectedElement() instanceof Pedestrian) {
Trajectory trajectory = trajectories.get(getSelectedElement().getId());
if (trajectory != null) {
Optional<Agent> ped = trajectory.getAgent(visTimeInSec);