Commit f50e2e76 authored by Benedikt Zoennchen's avatar Benedikt Zoennchen
Browse files

improved video and picture making for the PostVis and change the PostVis from...

improved video and picture making for the PostVis and change the PostVis from time step granularity to simulation time granularity.
parent 3e147ded
Pipeline #126921 failed with stages
in 3 minutes and 13 seconds
......@@ -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);