Commit 1b2630ed authored by Benedikt Zoennchen's avatar Benedikt Zoennchen

add recording functionality for the online vis.

parent 5be80e2c
Pipeline #268338 passed with stages
in 177 minutes and 10 seconds
......@@ -233,7 +233,7 @@ PostVis.additional.border.text=PostVis
PostVis.btnPlay.tooltip=Play (Space)
PostVis.btnPause.tooltip=Pause (Space)
PostVis.btnStop.tooltip=Stop (Backspace)
PostVis.btnRecord.tooltip=Start Recording
PostVis.btnRecord.tooltip=Start / Stop Recording
PostVis.btnAbout.tooltip=About
PostVis.about.title=About
PostVis.title=Vadere Post-Visualization
......@@ -269,6 +269,7 @@ PostVis.menuRecentFiles.title=Recent Files
PostVis.menuOpenFile.title=Open File...
PostVis.menuCloseFloorFieldFile.title=Remove Floor Field File
OnlineVis.btnRecord.tooltip=Start / Stop Recording
OnlineVis.btnShowPotentialfield.tooltip=Show the different Potential Fields for the selected Agent
OnlineVis.msgDialogShowPotentialfield.title=Potentialfield visualization
OnlineVis.msgDialogShowPotentialfield.text=Choose the Potential Field to be displayed.
......
......@@ -232,7 +232,7 @@ PostVis.chShowCriteriaColor.text=F\u00e4rbung nach Bedingung
PostVis.btnPlay.tooltip=Start (Leertaste)
PostVis.btnPause.tooltip=Pause (Leertaste)
PostVis.btnStop.tooltip=Stopp (Backspace-Taste)
PostVis.btnRecord.tooltip=Starte Aufnahme
PostVis.btnRecord.tooltip=Starte / Beende Aufnahme
PostVis.chbHidePedAtTarget.text=Verschwundene Fu\u00dfg\u00E4nger im Ziel nicht anzeigen
PostVis.chbHideTrajAtTarget.text=Verschwundene Trajektorien am Ziel nicht anzeigen
......@@ -263,6 +263,7 @@ PostVis.menuRecentFiles.title=K\u00FCrzlich verwendete Dateien
PostVis.menuOpenFile.title=Datei \u00F6ffnen...
PostVis.menuCloseFloorFieldFile.title=Floor Field-Datei l\u00F6schen
OnlineVis.btnRecord.tooltip=Starte / Beende Aufnahme
OnlineVis.btnShowPotentialfield.tooltip=Zeige Potentialfeld des ausgew\u00E4hlten Agenten
OnlineVis.msgDialogShowPotentialfield.title=Potentialfeld visualisieren
OnlineVis.msgDialogShowPotentialfield.text=W\u00E4hle Potentialfeld
......
package org.vadere.gui.postvisualization.control;
package org.vadere.gui.components.control.simulation;
import org.apache.commons.configuration2.Configuration;
import org.vadere.gui.components.control.simulation.ActionVisualization;
import org.vadere.gui.components.model.SimulationModel;
import org.vadere.gui.components.utils.Resources;
import org.vadere.gui.postvisualization.model.PostvisualizationModel;
import org.vadere.gui.components.view.SimulationRenderer;
import org.vadere.gui.postvisualization.utils.IRecorder;
import org.vadere.gui.postvisualization.utils.MovRecorder;
import org.vadere.gui.postvisualization.view.ImageSizeDialog;
import org.vadere.gui.postvisualization.view.PostvisualizationRenderer;
import org.vadere.util.config.VadereConfig;
import org.vadere.util.logging.Logger;
......@@ -18,15 +17,15 @@ import java.io.IOException;
public class ActionRecording extends ActionVisualization {
private static Logger logger = Logger.getLogger(ActionRecording.class);
private static final Configuration CONFIG = VadereConfig.getConfig();
private static Resources resources = Resources.getInstance("postvisualization");
private static Resources resources = Resources.getInstance("global");
private final PostvisualizationModel model;
private final SimulationModel model;
private JButton button;
private final int iconWidth;
private final int iconHeight;
private IRecorder recorder;
public ActionRecording(final String name, final Icon icon, final PostvisualizationRenderer renderer) {
public ActionRecording(final String name, final Icon icon, final SimulationRenderer renderer) {
super(name, icon, renderer.getModel());
this.iconWidth = CONFIG.getInt("ProjectView.icon.width.value");
this.iconHeight = CONFIG.getInt("ProjectView.icon.height.value");
......
......@@ -21,6 +21,7 @@ public class DefaultSimulationConfig extends DefaultConfig {
private double densityStandardDerivation = CONFIG.getDouble("Density.standardDeviation");
private double pedestrianTorso = CONFIG.getDouble("Pedestrian.radius") * 2;
private boolean recording = false;
private boolean interpolatePositions = true;
private boolean showPedestrianIds = false;
private boolean showPedestrianInOutGroup = false;
......@@ -377,4 +378,11 @@ public class DefaultSimulationConfig extends DefaultConfig {
setChanged();
}
public void setRecording(boolean recording) {
this.recording = recording;
}
public boolean isRecording() {
return recording;
}
}
......@@ -44,6 +44,10 @@ public abstract class SimulationRenderer extends DefaultRenderer {
this.agentRender = new AgentRender(model);
}
public SimulationModel getModel() {
return model;
}
@Override
protected void renderPreTransformation(Graphics2D graphics2D, int width, int height) {
if (model.isFloorFieldAvailable() && (model.config.isShowTargetPotentialField() || model.config.isShowPotentialField())) {
......
......@@ -13,6 +13,7 @@ import org.vadere.gui.components.control.simulation.ActionGenerateINETenv;
import org.vadere.gui.components.control.simulation.ActionGeneratePNG;
import org.vadere.gui.components.control.simulation.ActionGenerateSVG;
import org.vadere.gui.components.control.simulation.ActionGenerateTikz;
import org.vadere.gui.components.control.simulation.ActionRecording;
import org.vadere.gui.components.control.simulation.ActionSwapSelectionMode;
import org.vadere.gui.components.control.simulation.ActionVisualization;
import org.vadere.gui.components.utils.Messages;
......@@ -216,6 +217,12 @@ public class OnlineVisualisationWindow extends JPanel implements Observer {
resources.getIcon("potentialField.png", iconWidth, iconHeight),
model);
ActionRecording recording = new ActionRecording(
"showPotentialField",
resources.getIcon("record.png", iconWidth, iconHeight),
renderer);
mainPanel.addRendererChangeListener(generatePNG);
mainPanel.addRendererChangeListener(generateSVG);
mainPanel.addRendererChangeListener(generateTikz);
......@@ -234,7 +241,6 @@ public class OnlineVisualisationWindow extends JPanel implements Observer {
SwingUtils.addActionToToolbar(toolbar, drawMesh, Messages.getString("ProjectView.btnDrawMesh.tooltip"));
SwingUtils.addActionToToolbar(toolbar, paintGridAction, Messages.getString("ProjectView.btnShowGrid.tooltip"));
SwingUtils.addActionToToolbar(toolbar, paintDensity, Messages.getString("ProjectView.btnShowDensity.tooltip"));
SwingUtils.addActionToToolbar(toolbar, showPotentialField, Messages.getString("OnlineVis.btnShowPotentialfield.tooltip"));
toolbar.addSeparator();
// Snapshot options
......@@ -251,6 +257,10 @@ public class OnlineVisualisationWindow extends JPanel implements Observer {
JButton imgMenuBtn = SwingUtils.addActionToToolbar(toolbar, imgDialog, Messages.getString("ProjectView.btnSnapshot.tooltip"));
imgDialog.setParent(imgMenuBtn);
SwingUtils.addActionToToolbar(toolbar, showPotentialField, Messages.getString("OnlineVis.btnShowPotentialfield.tooltip"));
JButton recordButton = SwingUtils.addActionToToolbar(toolbar, recording, Messages.getString("OnlineVis.btnRecord.tooltip"));
recording.setButton(recordButton);
toolbar.add(Box.createHorizontalGlue());
SwingUtils.addActionToToolbar(toolbar, openSettingsDialog, Messages.getString("ProjectView.btnSettings.tooltip"));
......
......@@ -10,7 +10,6 @@ public class PostvisualizationConfig extends DefaultSimulationConfig {
private static final Configuration CONFIG = VadereConfig.getConfig();
private boolean recording = false;
private boolean showAllTrajectories = true;
private boolean showFaydedPedestrians = false;
private boolean loadTopographyInformationsOnly = false;
......@@ -61,14 +60,6 @@ public class PostvisualizationConfig extends DefaultSimulationConfig {
setChanged();
}
public void setRecording(boolean recording) {
this.recording = recording;
}
public boolean isRecording() {
return recording;
}
public boolean isLoadTopographyInformationsOnly() {
return loadTopographyInformationsOnly;
}
......
......@@ -3,8 +3,10 @@ package org.vadere.gui.postvisualization.utils;
import org.apache.commons.configuration2.Configuration;
import org.jcodec.api.awt.SequenceEncoder;
import org.vadere.gui.components.model.SimulationModel;
import org.vadere.gui.components.utils.Messages;
import org.vadere.gui.components.utils.Resources;
import org.vadere.gui.components.view.SimulationRenderer;
import org.vadere.gui.postvisualization.model.PostvisualizationModel;
import org.vadere.gui.postvisualization.view.PostvisualizationRenderer;
import org.vadere.util.config.VadereConfig;
......@@ -22,9 +24,8 @@ import java.util.Observable;
public class MovRecorder implements IRecorder {
private static Logger logger = Logger.getLogger(MovRecorder.class);
private static final Configuration CONFIG = VadereConfig.getConfig();
private static Resources resources = Resources.getInstance("postvisualization");
private final PostvisualizationModel model;
private final SimulationModel model;
private ImageGenerator generator;
private SequenceEncoder enc;
private double simTimeInSec;
......@@ -33,7 +34,7 @@ public class MovRecorder implements IRecorder {
private boolean finished;
private File outputFile;
public MovRecorder(final PostvisualizationRenderer renderer) {
public MovRecorder(final SimulationRenderer renderer) {
this.model = renderer.getModel();
this.imageSize = model.getWindowBound();
this.viewport = model.getViewportBound();
......
......@@ -32,6 +32,7 @@ public class PostvisualizationRenderer extends SimulationRenderer {
this.lastPedestrianPositions = new HashMap<>();
}
@Override
public PostvisualizationModel getModel() {
return model;
}
......
......@@ -25,7 +25,7 @@ import org.vadere.gui.components.view.ScenarioElementView;
import org.vadere.gui.postvisualization.control.ActionOpenFile;
import org.vadere.gui.postvisualization.control.ActionPause;
import org.vadere.gui.postvisualization.control.ActionPlay;
import org.vadere.gui.postvisualization.control.ActionRecording;
import org.vadere.gui.components.control.simulation.ActionRecording;
import org.vadere.gui.postvisualization.control.ActionRemoveFloorFieldFile;
import org.vadere.gui.postvisualization.control.ActionShowPotentialField;
import org.vadere.gui.postvisualization.control.ActionStop;
......
......@@ -21,7 +21,7 @@ public interface ITriEventListener<V extends IVertex, E extends IHalfEdge, F ext
* @param f3 the third new triangle / face
* @param v the new vertex
*/
void postSplitTriangleEvent(F original, F f1, F f2, F f3, V v);
default void postSplitTriangleEvent(F original, F f1, F f2, F f3, V v) {}
/**
* This method is triggered after an half-edge is split. Note that if the half-edge is not
......@@ -34,7 +34,7 @@ public interface ITriEventListener<V extends IVertex, E extends IHalfEdge, F ext
* @param f2 one of the new face, which might be the original
* @param v the new vertex
*/
void postSplitHalfEdgeEvent(E originalEdge, F original, F f1, F f2, V v);
default void postSplitHalfEdgeEvent(E originalEdge, F original, F f1, F f2, V v) {}
/**
* This method is triggered after an edge e with neighbouring faces f1, f2 is flipped.
......@@ -42,12 +42,12 @@ public interface ITriEventListener<V extends IVertex, E extends IHalfEdge, F ext
* @param f1 the first face of the edge
* @param f2 the second face of the edge
*/
void postFlipEdgeEvent(F f1, F f2);
default void postFlipEdgeEvent(F f1, F f2) {}
/**
* This method is triggered after a point is inserted into the triangulation.
*
* @param vertex the vertex of the point which was inserted
*/
void postInsertEvent(V vertex);
default void postInsertEvent(V vertex) {}
}
......@@ -12,6 +12,7 @@ import org.vadere.meshing.mesh.inter.IFace;
import org.vadere.meshing.mesh.inter.IHalfEdge;
import org.vadere.meshing.mesh.inter.IIncrementalTriangulation;
import org.vadere.meshing.mesh.inter.IMesh;
import org.vadere.meshing.mesh.inter.ITriEventListener;
import org.vadere.meshing.mesh.inter.IVertex;
import org.vadere.meshing.mesh.inter.IVertexContainerBoolean;
import org.vadere.meshing.mesh.inter.IVertexContainerDouble;
......@@ -32,6 +33,7 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* @author Benedikt Zoennchen
......@@ -40,10 +42,11 @@ import java.util.function.Function;
* @param <E> the type of the half-edges of the triangulation
* @param <F> the type of the faces of the triangulation
*/
public abstract class AMeshEikonalSolver<V extends IVertex, E extends IHalfEdge, F extends IFace> implements MeshEikonalSolver<V, E, F> {
public abstract class AMeshEikonalSolver<V extends IVertex, E extends IHalfEdge, F extends IFace> implements MeshEikonalSolver<V, E, F>, ITriEventListener<V, E, F> {
@Nullable private ITimeCostFunction timeCostFunction;
@Nullable private ITimeCostFunctionMesh<V> meshTimeCostFunction;
@Nullable IDistanceFunction distanceFunction;
private final IIncrementalTriangulation<V, E, F> triangulation;
private Collection<V> initialVertices;
......@@ -86,6 +89,8 @@ public abstract class AMeshEikonalSolver<V extends IVertex, E extends IHalfEdge,
}
this.triangulation = triangulation;
this.triangulation.removeTriEventListener(this);
this.triangulation.addTriEventListener(this);
// get access to containers
this.burned = getMesh().getBooleanVertexContainer(identifier + "_" + nameBurned);
......@@ -108,6 +113,7 @@ public abstract class AMeshEikonalSolver<V extends IVertex, E extends IHalfEdge,
*/
public void setInitialVertices(@NotNull final Collection<V> initialVertices, @NotNull final IDistanceFunction distanceFunction) {
this.initialVertices = initialVertices;
this.distanceFunction = distanceFunction;
for(V v : initialVertices) {
double dist = distanceFunction.apply(new VPoint(getMesh().toPoint(v)));
setPotential(v, dist);
......@@ -124,6 +130,7 @@ public abstract class AMeshEikonalSolver<V extends IVertex, E extends IHalfEdge,
}
setTimeCost(v);
});
initialVertices = initialVertices.stream().filter(v -> !getMesh().isDestroyed(v)).collect(Collectors.toList());
solved = false;
}
......@@ -540,4 +547,15 @@ public abstract class AMeshEikonalSolver<V extends IVertex, E extends IHalfEdge,
protected DoubleArrayList getVirtualSupportCosPhi(@NotNull final E edge) {
return virtualSupportCosPhi.getValue(edge);
}
@Override
public void postInsertEvent(@NotNull final V vertex) {
double dist = distanceFunction.apply(getMesh().toPoint(vertex));
if(distanceFunction.apply(getMesh().toPoint(vertex)) <= 0) {
initialVertices.add(vertex);
setPotential(vertex, dist);
setBurned(vertex);
setAsInitialVertex(vertex);
}
}
}
package org.vadere.simulator.models.potential.solver.calculators.mesh;
import it.unimi.dsi.fastutil.doubles.DoubleArrayList;
import org.jetbrains.annotations.NotNull;
import org.vadere.meshing.mesh.inter.IFace;
import org.vadere.meshing.mesh.inter.IHalfEdge;
import org.vadere.meshing.mesh.inter.IIncrementalTriangulation;
import org.vadere.meshing.mesh.inter.IVertex;
import org.vadere.meshing.mesh.inter.IVertexContainerInteger;
import org.vadere.meshing.mesh.inter.IVertexContainerObject;
import org.vadere.simulator.models.potential.solver.timecost.ITimeCostFunction;
import org.vadere.util.geometry.shapes.VShape;
......
......@@ -6,7 +6,10 @@ import org.vadere.meshing.mesh.inter.IHalfEdge;
import org.vadere.meshing.mesh.inter.IIncrementalTriangulation;
import org.vadere.meshing.mesh.inter.IVertex;
import org.vadere.simulator.models.potential.solver.timecost.ITimeCostFunction;
import org.vadere.util.geometry.GeometryUtils;
import org.vadere.util.geometry.shapes.IPoint;
import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.geometry.shapes.VPolygon;
import org.vadere.util.geometry.shapes.VShape;
import org.vadere.util.logging.Logger;
import org.vadere.util.math.IDistanceFunction;
......@@ -15,6 +18,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
......@@ -145,16 +149,43 @@ public class MeshEikonalSolverFMM<V extends IVertex, E extends IHalfEdge, F exte
//TODO a more clever init!
List<V> initialVertices = new ArrayList<>();
for(VShape shape : targetShapes) {
List<V> partilyInitialVertices = new ArrayList<>();
getMesh().streamVertices()
.filter(v -> shape.contains(getMesh().toPoint(v)))
.forEach(v -> {
for(V u : getMesh().getAdjacentVertexIt(v)) {
initialVertices.add(u);
partilyInitialVertices.add(u);
setAsInitialVertex(u);
}
initialVertices.add(v);
partilyInitialVertices.add(v);
setAsInitialVertex(v);
});
// this might happen if the target is very small or the mesh is to coarse!
if(partilyInitialVertices.isEmpty()) {
VPoint centroid = shape.getCentroid();
if(shape.contains(centroid)) {
Optional<F> optFace = triangulation.locate(centroid);
if(optFace.isPresent()) {
F face = optFace.get();
getMesh().streamVertices(face).forEach(v -> {
for(V u : getMesh().getAdjacentVertexIt(v)) {
partilyInitialVertices.add(u);
setAsInitialVertex(u);
}
partilyInitialVertices.add(v);
setAsInitialVertex(v);
});
} else {
throw new IllegalArgumentException("the shape " + shape + " is not a legal target shape given the current mesh.");
}
}
else {
throw new IllegalArgumentException("the shape " + shape + " is not a legal target shape given the current mesh.");
}
}
initialVertices.addAll(partilyInitialVertices);
}
setInitialVertices(initialVertices, IDistanceFunction.createToTargets(targetShapes));
......
......@@ -48,7 +48,7 @@ public class TimeCostPedestrianDensityMesh<V extends IVertex, E extends IHalfEdg
private GenRegularRefinement<V, E, F> refiner;
private final double R = 0.7;
private final int influenceRadius = 9;
private final int influenceRadius = 5;
private final double a;
private final double Sp;
private final double c;
......@@ -94,20 +94,20 @@ public class TimeCostPedestrianDensityMesh<V extends IVertex, E extends IHalfEdg
}
private boolean coarse(@NotNull final V vertex) {
return true;
/*for(Pedestrian pedestrian : topography.getPedestrianDynamicElements().getElements()) {
//return true;
for(Pedestrian pedestrian : topography.getPedestrianDynamicElements().getElements()) {
if(pedestrian.getPosition().distanceSq(triangulation.getMesh().toPoint(vertex)) > influenceRadius * influenceRadius) {
return true;
}
}*/
//return false;
}
return false;
}
private boolean refine(@NotNull final E e) {
//return refiner.getLevel(e) < 2;
if(!triangulation.getMesh().isBoundary(e)) {
VTriangle triangle = triangulation.getMesh().toTriangle(triangulation.getMesh().getFace(e));
if(/*!refiner.isGreen(e) || */triangulation.getMesh().toLine(e).length() > 1.0) {
if(/*!refiner.isGreen(e) || */triangulation.getMesh().toLine(e).length() > 5) {
for(Pedestrian pedestrian : topography.getPedestrianDynamicElements().getElements()) {
if(pedestrian.getPosition().distanceSq(triangle.midPoint()) < influenceRadius * influenceRadius) {
return true;
......
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