Commit d678b2ce authored by Stefan Schuhbaeck's avatar Stefan Schuhbaeck
Browse files

Merge branch 'master' into source_shape

parents 0820012e 180c7d31
......@@ -280,6 +280,7 @@ ProjectView.btnCancel=Cancel
ProjectView.btnExpertCSV=Export as csv
ProjectView.label.simResults=Simulation Results
TopographyCreator.btnMergeObstacles.tooltip=Merge Obstacles
TopographyCreator.btnMinimizeTopography.tooltip=Select Viewport area
TopographyCreator.btnMaximizeTopography.tooltip=Maximize Viewport area
TopographyCreator.btnQuickSave.tooltip=Quicksave
......
......@@ -273,6 +273,7 @@ ProjectView.btnSettings.tooltip=Einstellungen
ProjectView.btnOk=OK
ProjectView.btnCancel=Abbrechen
TopographyCreator.btnMergeObstacles.tooltip=Hindernisse zusammenf\u00fchren
TopographyCreator.btnMinimizeTopography.tooltip=Select Viewport area
TopographyCreator.btnMaximizeTopography.tooltip=Anzeigebereich maximieren
TopographyCreator.btnQuickSave.tooltip=Schnelles speichern
......
......@@ -5,7 +5,6 @@ import javax.swing.*;
import org.vadere.gui.components.model.IDefaultModel;
import org.vadere.util.geometry.shapes.VRectangle;
import java.awt.*;
import java.awt.event.MouseEvent;
public class DefaultSelectionMode extends RectangleSelectionMode {
......
......@@ -2,20 +2,44 @@ package org.vadere.gui.components.model;
import javax.swing.*;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.vadere.gui.components.control.*;
import org.vadere.gui.components.view.ISelectScenarioElementListener;
import org.vadere.simulator.models.potential.fields.IPotentialField;
import org.vadere.simulator.models.potential.fields.PotentialFieldDistancesBruteForce;
import org.vadere.simulator.utils.TexGraphGenerator;
import org.vadere.state.attributes.models.AttributesFloorField;
import org.vadere.state.scenario.Obstacle;
import org.vadere.state.scenario.ScenarioElement;
import org.vadere.state.scenario.Topography;
import org.vadere.state.types.ScenarioElementType;
import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.geometry.shapes.VRectangle;
import org.vadere.util.geometry.shapes.VShape;
import org.vadere.meshing.mesh.gen.PFace;
import org.vadere.meshing.mesh.gen.PHalfEdge;
import org.vadere.meshing.mesh.gen.PVertex;
import org.vadere.meshing.mesh.inter.ITriangulation;
import org.vadere.util.geometry.shapes.IPoint;
import org.vadere.util.geometry.shapes.VPolygon;
import org.vadere.util.geometry.shapes.VTriangle;
import org.vadere.util.data.cellgrid.CellGrid;
import org.vadere.util.data.cellgrid.CellState;
import org.vadere.util.data.cellgrid.PathFindingTag;
import org.vadere.util.math.DistanceFunction;
import org.vadere.util.math.IDistanceFunction;
import org.vadere.meshing.mesh.triangulation.improver.EikMeshPoint;
import org.vadere.meshing.mesh.triangulation.improver.PEikMesh;
import org.vadere.util.voronoi.VoronoiDiagram;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.util.*;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
......@@ -23,6 +47,8 @@ public abstract class DefaultModel<T extends DefaultConfig> extends Observable i
// private static final int BORDER_WIDTH = 20;
// private static final int BORDER_HEIGHT = 20;
private static Logger log = LogManager.getLogger(DefaultModel.class);
private IMode mouseSelectionMode;
protected ScenarioElement selectedElement;
......@@ -37,6 +63,8 @@ public abstract class DefaultModel<T extends DefaultConfig> extends Observable i
private boolean showVoroniDiagram;
private boolean showTriangulation;
private VPoint cursorWorldPosition;
private VPoint startSelectionPoint;
......@@ -59,6 +87,12 @@ public abstract class DefaultModel<T extends DefaultConfig> extends Observable i
public T config;
private ITriangulation<EikMeshPoint, PVertex<EikMeshPoint>, PHalfEdge<EikMeshPoint>, PFace<EikMeshPoint>> triangulation;
private Collection<VTriangle> triangles;
protected boolean triangulationTriggered = false;
public DefaultModel(final T config) {
this.config = config;
this.scaleFactor = 50;
......@@ -67,16 +101,18 @@ public abstract class DefaultModel<T extends DefaultConfig> extends Observable i
this.cursorWorldPosition = VPoint.ZERO;
this.selectScenarioElementListener = new LinkedList<>();
this.voronoiDiagram = null;
this.showTriangulation = false;
this.showVoroniDiagram = true;
this.showSelection = false;
this.mouseSelectionMode = new DefaultSelectionMode(this);
this.viewportChangeListeners = new ArrayList<>();
this.scaleChangeListeners = new ArrayList<>();
this.triangulation = null;
}
@Override
public Color getScenarioElementColor(final ScenarioElementType elementType) {
Color c = null;
Color c;
switch (elementType) {
case OBSTACLE:
c = getConfig().getObstacleColor();
......@@ -156,6 +192,10 @@ public abstract class DefaultModel<T extends DefaultConfig> extends Observable i
}
}
public boolean isTriangulationVisible() {
return showTriangulation;
}
@Override
public void notifyScaleListeners() {
for (IScaleChangeListener listener : scaleChangeListeners) {
......@@ -345,6 +385,18 @@ public abstract class DefaultModel<T extends DefaultConfig> extends Observable i
setChanged();
}
@Override
public void showTriangulation() {
showTriangulation = true;
setChanged();
}
@Override
public void hideTriangulation() {
showTriangulation = false;
setChanged();
}
@Override
public void showSelection() {
showSelection = true;
......@@ -490,4 +542,136 @@ public abstract class DefaultModel<T extends DefaultConfig> extends Observable i
public T getConfig() {
return config;
}
/*
* returns the adaptive triangulation (see persson-2004 'A Simple Mesh Generator in MATLAB.')
*/
public void startTriangulation() {
if(!triangulationTriggered) {
triangulationTriggered = true;
VRectangle bound = new VRectangle(getTopographyBound());
Collection<Obstacle> obstacles = Topography.createObstacleBoundary(getTopography());
obstacles.addAll(getTopography().getObstacles());
List<VShape> shapes = obstacles.stream().map(obstacle -> obstacle.getShape()).collect(Collectors.toList());
IPotentialField distanceField = new PotentialFieldDistancesBruteForce(
getTopography().getObstacles().stream().map(obs -> obs.getShape()).collect(Collectors.toList()),
new VRectangle(getTopography().getBounds()),
new AttributesFloorField());
Function<IPoint, Double> obstacleDistance = p -> distanceField.getPotential(p, null);
IDistanceFunction distanceFunc = new DistanceFunction(bound, shapes);
CellGrid cellGrid = new CellGrid(bound.getWidth(), bound.getHeight(), 0.1, new CellState());
cellGrid.pointStream().forEach(p -> cellGrid.setValue(p, new CellState(distanceFunc.apply(cellGrid.pointToCoord(p)), PathFindingTag.Reachable)));
Function<IPoint, Double> interpolationFunction = cellGrid.getInterpolationFunction();
IDistanceFunction approxDistance = p -> interpolationFunction.apply(p);
/*PPSMeshing meshImprover = new PPSMeshing(
distanceFunc,
p -> Math.min(1.0 + Math.pow(Math.max(-distanceFunc.apply(p), 0)*0.8, 2), 6.0),
0.3,
bound, getTopography().getObstacles().stream().map(obs -> obs.getShape()).collect(Collectors.toList()));*/
PEikMesh meshImprover = new PEikMesh(
distanceFunc,
p -> Math.min(1.0 + Math.max(approxDistance.apply(p)*approxDistance.apply(p), 0)*0.3, 5.0),
0.35,
bound, getTopography().getObstacles().stream().map(obs -> obs.getShape()).collect(Collectors.toList()));
/*PPSMeshing meshImprover = new PPSMeshing(
distanceFunc,
p -> 1.0,
1.0,
bound, getTopography().getObstacles().stream().map(obs -> obs.getShape()).collect(Collectors.toList()));*/
triangulation = meshImprover.getTriangulation();
Thread t = new Thread(() -> {
while(!meshImprover.isFinished()) {
meshImprover.improve();
/*try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}*/
setChanged();
notifyObservers();
}
//meshImprover.improve();
Function<PFace<EikMeshPoint>, Color> colorFunction = f -> {
float grayScale = (float) meshImprover.faceToQuality(f);
return triangulation.isValid(f) ? new Color(grayScale, grayScale, grayScale) : Color.RED;
};
log.info(TexGraphGenerator.toTikz(meshImprover.getMesh(), colorFunction, 1.0f));
log.info("number of points = " + meshImprover.getMesh().getVertices().size());
log.info("number of triangle = " + meshImprover.getMesh().getFaces().size());
log.info("avg-quality = " + meshImprover.getQuality());
log.info("min-quality = " + meshImprover.getMinQuality());
});
t.start();
}
}
public Collection<VTriangle> getTriangles() {
if(triangulation == null) {
return Collections.EMPTY_LIST;
}
synchronized (triangulation.getMesh()) {
return triangulation.streamTriangles().collect(Collectors.toList());
}
}
public Collection<VPolygon> getHoles() {
if(triangulation == null) {
return Collections.EMPTY_LIST;
}
synchronized (triangulation.getMesh()) {
return triangulation.getMesh().streamHoles().map(f -> triangulation.getMesh().toPolygon(f)).collect(Collectors.toList());
}
}
/*public void startTriangulation() {
if(!triangulationTriggered) {
triangulationTriggered = true;
VRectangle bound = new VRectangle(getTopographyBound());
Collection<Obstacle> obstacles = Topography.createObstacleBoundary(getTopography());
obstacles.addAll(getTopography().getObstacles());
List<VShape> shapes = obstacles.stream().map(obstacle -> obstacle.getShape()).collect(Collectors.toList());
IDistanceFunction distanceFunc = new DistanceFunction(bound, shapes);
PSDistmesh meshImprover = new PSDistmesh(
distanceFunc,
p -> Math.min(1.0 + Math.pow(Math.max(-distanceFunc.apply(p), 0), 2), 4.0),
0.3,
bound, getTopography().getObstacles().stream().map(obs -> obs.getShape()).collect(Collectors.toList()));
triangles = meshImprover.getTriangles();
// meshImprover.improve();
Thread t = new Thread(() -> {
while(!meshImprover.isFinished()) {
meshImprover.improve();
setChanged();
notifyObservers();
}
Function<VTriangle, Color> colorFunction = f -> {
float grayScale = (float) meshImprover.getQuality(f);
return new Color(grayScale, grayScale, grayScale);
};
log.info(TexGraphGenerator.toTikz(meshImprover.getTriangles(), colorFunction, 1.0f, getTopography()));
});
t.start();
}
}
public Collection<VTriangle> getTriangles() {
if(triangles == null) {
return Collections.EMPTY_LIST;
}
return triangles;
}*/
}
......@@ -6,8 +6,8 @@ import java.util.Map;
import java.util.Optional;
import java.util.TreeMap;
import org.vadere.gui.components.utils.ColorHelper;
import org.vadere.gui.components.utils.Resources;
import org.vadere.meshing.color.ColorHelper;
public class DefaultSimulationConfig extends DefaultConfig {
private static Resources resources = Resources.getInstance("global");
......
......@@ -297,5 +297,9 @@ public interface IDefaultModel<T extends DefaultConfig> extends Iterable<Scenari
*/
void notifyObservers(final Object args);
void hideTriangulation();
void showTriangulation();
T getConfig();
}
package org.vadere.gui.components.model;
import java.awt.*;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import org.vadere.state.scenario.Agent;
import org.vadere.util.geometry.shapes.IPoint;
import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.geometry.shapes.VRectangle;
......@@ -27,7 +25,7 @@ public abstract class SimulationModel<T extends DefaultSimulationConfig> extends
public abstract double getSimTimeInSec();
public abstract Function<VPoint, Double> getPotentialField();
public abstract Function<IPoint, Double> getPotentialField();
public abstract boolean isFloorFieldAvailable();
......
package org.vadere.gui.components.utils;
import java.awt.*;
import java.awt.image.BufferedImage;
import org.vadere.gui.components.model.DefaultSimulationConfig;
import org.vadere.gui.components.model.SimulationModel;
import org.vadere.gui.components.utils.ColorHelper;
import org.vadere.meshing.color.ColorHelper;
import org.vadere.simulator.models.density.IGaussianFilter;
import org.vadere.state.attributes.scenario.AttributesAgent;
......
package org.vadere.gui.components.utils;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.apache.log4j.Priority;
import org.jcodec.api.awt.SequenceEncoder;
import org.jetbrains.annotations.NotNull;
import org.vadere.gui.postvisualization.PostVisualisation;
import org.vadere.gui.postvisualization.utils.IRecorder;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Observable;
import java.util.prefs.Preferences;
import javax.swing.*;
public class Recorder implements IRecorder {
private static Logger logger = LogManager.getLogger(Recorder.class);
private SequenceEncoder enc;
private static Resources resources = Resources.getInstance("global");
@Override
public void startRecording() {
Date todaysDate = new java.util.Date();
SimpleDateFormat formatter = new SimpleDateFormat(resources.getProperty("SettingsDialog.dataFormat"));
String formattedDate = formatter.format(todaysDate);
JFileChooser fileChooser = new JFileChooser(Preferences.userNodeForPackage(PostVisualisation.class).get("SettingsDialog.snapshotDirectory.path", "."));
File outputFile = new File("VADERE_sim_" + formattedDate + ".mov");
fileChooser.setSelectedFile(outputFile);
int returnVal = fileChooser.showDialog(null, "Save");
if (returnVal == JFileChooser.APPROVE_OPTION) {
outputFile = fileChooser.getSelectedFile().toString().endsWith(".mov") ? fileChooser.getSelectedFile()
: new File(fileChooser.getSelectedFile().toString() + ".mov");
try {
this.enc = new SequenceEncoder(outputFile);
} catch (IOException e) {
e.printStackTrace();
logger.error(e.getMessage());
}
logger.info(this + " start recording");
}
}
public synchronized void addPicture(@NotNull final BufferedImage bi) throws IOException {
enc.encodeImage(bi);
logger.info(this + " add picture");
}
@Override
public void startRecording(Rectangle2D.Double imageSize) {
startRecording();
}
@Override
public void stopRecording() throws IOException {
try {
enc.finish();
} catch (IndexOutOfBoundsException error) {
logger.log(Priority.DEBUG, "Nothing recorded! " + error.getMessage());
}
logger.info(this + " stop recording");
}
@Override
public void update(Observable o, Object arg) {}
}
......@@ -5,14 +5,14 @@ import org.vadere.gui.components.model.IDefaultModel;
import org.vadere.state.scenario.Agent;
import org.vadere.state.scenario.ScenarioElement;
import org.vadere.state.scenario.Stairs;
import org.vadere.util.geometry.Vector2D;
import org.vadere.util.geometry.shapes.Vector2D;
import org.vadere.util.geometry.shapes.VCircle;
import org.vadere.util.geometry.shapes.VLine;
import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.geometry.shapes.VPolygon;
import org.vadere.util.geometry.shapes.VRectangle;
import org.vadere.util.math.MathUtil;
import org.vadere.util.potential.CellGrid;
import org.vadere.util.data.cellgrid.CellGrid;
import org.vadere.util.voronoi.Face;
import org.vadere.util.voronoi.HalfEdge;
import org.vadere.util.voronoi.RectangleLimits;
......
......@@ -8,21 +8,17 @@ import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Stream;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.jetbrains.annotations.NotNull;
import org.vadere.meshing.color.ColorHelper;
import org.vadere.gui.components.model.SimulationModel;
import org.vadere.gui.components.utils.CLGaussianCalculator;
import org.vadere.gui.components.utils.ColorHelper;
import org.vadere.gui.components.utils.Resources;
import org.vadere.gui.renderer.agent.AgentRender;
import org.vadere.state.scenario.Agent;
import org.vadere.state.scenario.Pedestrian;
import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.geometry.shapes.VRectangle;
import org.vadere.util.geometry.shapes.VTriangle;
......@@ -91,9 +87,9 @@ public abstract class SimulationRenderer extends DefaultRenderer {
renderStairs(model.getTopography().getStairs(), graphics, model.config.getStairColor());
}
if (model.config.isShowTargets()) {
renderScenarioElement(model.getTopography().getTargets(), graphics, model.config.getTargetColor());
}
if (model.config.isShowTargets()) {
renderScenarioElement(model.getTopography().getTargets(), graphics, model.config.getTargetColor());
}
if (model.config.isShowSources()) {
renderScenarioElement(model.getTopography().getSources(), graphics, model.config.getSourceColor());
......
......@@ -116,7 +116,7 @@ public class OnlineVisualization implements PassiveCallback {
synchronized (model.getDataSynchronizer()) {
/* Push new snapshot of the observation area to the draw thread. */
IPotentialField pft = (model.config.isShowTargetPotentialField() && potentialFieldTarget != null) ? potentialFieldTarget.copyFields() : null;
IPotentialField pft = (model.config.isShowTargetPotentialField() && potentialFieldTarget != null) ? potentialFieldTarget.getSolution() : null;
IPotentialField pedPotentialField = null;
Agent selectedAgent = null;
......
......@@ -13,7 +13,7 @@ import org.vadere.gui.components.model.SimulationModel;
import org.vadere.gui.onlinevisualization.OnlineVisualization;
import org.vadere.simulator.models.potential.fields.IPotentialField;
import org.vadere.state.scenario.*;
import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.geometry.shapes.IPoint;
import org.vadere.util.voronoi.VoronoiDiagram;
public class OnlineVisualizationModel extends SimulationModel<DefaultSimulationConfig> {
......@@ -185,8 +185,8 @@ public class OnlineVisualizationModel extends SimulationModel<DefaultSimulationC
}
@Override
public Function<VPoint, Double> getPotentialField() {
Function<VPoint, Double> f = pos -> 0.0;
public Function<IPoint, Double> getPotentialField() {
Function<IPoint, Double> f = pos -> 0.0;
if(potentialField != null && config.isShowPotentialField() && agent.equals(getSelectedElement())) {
f = pos -> potentialField.getPotential(pos, agent);
......
......@@ -30,10 +30,9 @@ import org.vadere.state.scenario.TopographyIterator;
import org.vadere.state.simulation.Step;
import org.vadere.state.simulation.Trajectory;
import org.vadere.state.util.StateJsonConverter;
import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.io.parser.JsonLogicParser;
import org.vadere.util.geometry.shapes.IPoint;
import org.vadere.util.io.parser.VPredicate;
import org.vadere.util.potential.CellGrid;
import org.vadere.util.data.cellgrid.CellGrid;
import com.fasterxml.jackson.databind.JsonNode;
......@@ -146,6 +145,10 @@ public class PostvisualizationModel extends SimulationModel<PostvisualizationCon
}
public void init(final Scenario vadere, final String projectPath) {
// avoid the long computation
this.hideTriangulation();
this.triangulationTriggered = false;
this.vadere = vadere;
this.agentsByStep = new HashMap<>();
this.steps = new ArrayList<>();
......@@ -175,8 +178,8 @@ public class PostvisualizationModel extends SimulationModel<PostvisualizationCon
}
@Override
public Function<VPoint, Double> getPotentialField() {
Function<VPoint, Double> f = p -> 0.0;
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());
......
......@@ -3,10 +3,10 @@ package org.vadere.gui.postvisualization.utils;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.vadere.util.potential.CellGrid;
import org.vadere.util.potential.CellGridConverter;
import org.vadere.util.potential.CellState;
import org.vadere.util.potential.PathFindingTag;
import org.vadere.util.data.cellgrid.CellGrid;
import org.vadere.util.data.cellgrid.CellGridConverter;
import org.vadere.util.data.cellgrid.CellState;
import org.vadere.util.data.cellgrid.PathFindingTag;
import java.io.BufferedReader;
import java.io.File;
......
......@@ -9,7 +9,7 @@ import java.util.stream.Stream;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.vadere.gui.components.utils.ColorHelper;
import org.vadere.meshing.color.ColorHelper;
import org.vadere.gui.components.view.DefaultRenderer;
import org.vadere.gui.components.view.SimulationRenderer;
import org.vadere.gui.postvisualization.model.PostvisualizationModel;
......
......@@ -166,6 +166,25 @@ public class PostvisualizationWindow extends JPanel implements Observer {
}, "ProjectView.btnShowTrajectories.tooltip");
addActionToToolbar(toolbar,
new ActionVisualization("show_triangulation",
resources.getIcon("triangulation.png", iconWidth, iconHeight), model) {
@Override
public void actionPerformed(ActionEvent e) {