Commit a24b1c3f authored by Benedikt Zoennchen's avatar Benedikt Zoennchen

Merge branch 'develop' of https://gitlab.lrz.de/vadere/vadere into develop

parents edfae8b4 e4d8e9d8
Pipeline #58893 passed with stage
in 49 seconds
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="744.09448819"
height="1052.3622047"
id="svg2"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="source_icon.svg"
inkscape:export-filename="C:\Users\Benedikt\Repositories\Software\VadereGui\resources\icons\source_icon.png"
inkscape:export-xdpi="39.389999"
inkscape:export-ydpi="39.389999">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="4"
inkscape:cx="508.27116"
inkscape:cy="318.54973"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1680"
inkscape:window-height="987"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Ground">
<path
sodipodi:type="arc"
style="fill:#000000;fill-opacity:1;stroke:none"
id="path2999"
sodipodi:cx="567.25"
sodipodi:cy="745.61218"
sodipodi:rx="29"
sodipodi:ry="12.25"
d="m 596.25,745.61218 a 29,12.25 0 1 1 -58,0 29,12.25 0 1 1 58,0 z"
transform="matrix(1.2543104,0,0,1.132653,-152.88254,-93.532738)" />
</g>
<g
inkscape:label="Arrow Out"
inkscape:groupmode="layer"
id="layer1">
<path
style="fill:#800000"
d="m 523.54785,718.71229 c 3.67872,-11.89789 14.75259,-23.56593 25.00868,-26.35049 15.48687,-4.20472 28.23708,5.48211 29.97739,22.77504 0.84941,8.44048 0.94863,8.5832 5.84654,8.41155 7.70502,-0.27004 6.43547,2.77305 -5.6306,13.4965 l -11.11785,9.88075 -8.90828,-10.02363 c -4.89957,-5.51302 -8.8233,-10.84316 -8.71949,-11.84479 0.10385,-1.00163 2.96952,-1.86734 6.36816,-1.9238 5.73649,-0.0953 6.21234,-0.42061 6.63925,-4.53837 0.68171,-6.57556 -6.18382,-13.29468 -12.96608,-12.68957 -6.25183,0.5578 -17.03698,9.10527 -23.24218,18.41998 -5.07932,7.6246 -6.55947,5.07255 -3.25554,-5.61317 z"
id="path2996"
inkscape:connector-curvature="0" />
</g>
</svg>
......@@ -219,6 +219,7 @@ PostVis.chbShowSources.text=Show Sources
PostVis.chbShowStairs.text=Show Stairs
PostVis.btnPNGSnapshot.tooltip=PNG Snapshot
PostVis.btnSVGSnapshot.tooltip=SVG Snapshot
PostVis.btnTikZSnapshot.tooltip=TikZ Snapshot
PostVis.menuFile.title=File
PostVis.menuSettings.title=Setting
PostVis.menuRecentFiles.title=Recent Files
......
......@@ -219,6 +219,7 @@ PostVis.chbShowSources.text=Quellen anzeigen
PostVis.chbShowStairs.text=Treppen anzeigen
PostVis.btnPNGSnapshot.tooltip=PNG-Snapshot
PostVis.btnSVGSnapshot.tooltip=SVG-Snapshot
PostVis.btnTikZSnapshot.tooltip=TikZ Snapshot
PostVis.menuFile.title=Datei
PostVis.menuSettings.title=Einstellungen
PostVis.menuRecentFiles.title=K\u00FCrzlich verwendete Dateien
......
package org.vadere.gui.onlinevisualization.control;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.vadere.gui.components.model.DefaultSimulationConfig;
import org.vadere.gui.components.model.SimulationModel;
import org.vadere.gui.components.utils.Resources;
import org.vadere.gui.components.view.SimulationRenderer;
import org.vadere.gui.onlinevisualization.view.IRendererChangeListener;
import org.vadere.gui.postvisualization.PostVisualisation;
import org.vadere.gui.postvisualization.utils.SVGGenerator;
import org.vadere.gui.postvisualization.utils.TikzGenerator;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.prefs.Preferences;
public class ActionGenerateTikz extends AbstractAction implements IRendererChangeListener {
private static Logger logger = LogManager.getLogger(ActionGenerateTikz.class);
private static Resources resources = Resources.getInstance("postvisualization");
private final TikzGenerator tikzGenerator;
private final SimulationModel<? extends DefaultSimulationConfig> model;
public ActionGenerateTikz(final String name, final Icon icon, final SimulationRenderer renderer,
final SimulationModel<? extends DefaultSimulationConfig> model) {
super(name, icon);
this.tikzGenerator = new TikzGenerator(renderer, model);
this.model = model;
}
@Override
public void actionPerformed(ActionEvent e) {
Date todaysDate = new Date();
SimpleDateFormat formatter = new SimpleDateFormat(resources.getProperty("View.dataFormat"));
String formattedDate = formatter.format(todaysDate);
JFileChooser fileChooser = new JFileChooser(Preferences.userNodeForPackage(PostVisualisation.class).get("PostVis.snapshotDirectory.path", "."));
File outputFile = new File("pv_snapshot_" + formattedDate + ".tex");
fileChooser.setSelectedFile(outputFile);
int returnVal = fileChooser.showDialog(null, "Save");
if (returnVal == JFileChooser.APPROVE_OPTION) {
outputFile = fileChooser.getSelectedFile().toString().endsWith(".tex") ? fileChooser.getSelectedFile()
: new File(fileChooser.getSelectedFile().toString() + ".tex");
boolean completeDocument = true;
tikzGenerator.generateTikz(outputFile, completeDocument);
}
}
@Override
public void update(SimulationRenderer renderer) {}
}
......@@ -17,6 +17,7 @@ import org.vadere.gui.components.view.ScenarioScrollPane;
import org.vadere.gui.components.view.SimulationInfoPanel;
import org.vadere.gui.onlinevisualization.control.ActionGeneratePNG;
import org.vadere.gui.onlinevisualization.control.ActionGenerateSVG;
import org.vadere.gui.onlinevisualization.control.ActionGenerateTikz;
import org.vadere.gui.onlinevisualization.control.ActionShowPotentialField;
import org.vadere.gui.onlinevisualization.model.OnlineVisualizationModel;
......@@ -150,6 +151,12 @@ public class OnlineVisualisationWindow extends JPanel implements Observer {
new OnlinevisualizationRenderer(model),
model);
ActionGenerateTikz generateTikz = new ActionGenerateTikz(
"generateTikz",
resources.getIcon("camera_tikz.png", iconWidth, iconHeight),
new OnlinevisualizationRenderer(model),
model);
ActionShowPotentialField showPotentialField = new ActionShowPotentialField(
"showPotentialField",
resources.getIcon("potentialField.png", iconWidth, iconHeight),
......@@ -157,6 +164,7 @@ public class OnlineVisualisationWindow extends JPanel implements Observer {
mainPanel.addRendererChangeListener(generatePNG);
mainPanel.addRendererChangeListener(generateSVG);
mainPanel.addRendererChangeListener(generateTikz);
mainPanel.addRendererChangeListener(showPotentialField);
......@@ -176,6 +184,7 @@ public class OnlineVisualisationWindow extends JPanel implements Observer {
SwingUtils.addActionToToolbar(toolbar, generatePNG, Messages.getString("PostVis.btnPNGSnapshot.tooltip"));
SwingUtils.addActionToToolbar(toolbar, generateSVG, Messages.getString("PostVis.btnSVGSnapshot.tooltip"));
SwingUtils.addActionToToolbar(toolbar, generateTikz, Messages.getString("PostVis.btnTikzSnapshot.tooltip"));
SwingUtils.addActionToToolbar(toolbar, showPotentialField, Messages.getString("OnlineVis.btnShowPotentialfield.tooltip"));
add(toolbar, cc.xyw(2, 2, 3));
......
package org.vadere.gui.postvisualization.control;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.vadere.gui.components.utils.Resources;
import org.vadere.gui.postvisualization.PostVisualisation;
import org.vadere.gui.postvisualization.utils.TikzGenerator;
import org.vadere.gui.postvisualization.view.PostvisualizationRenderer;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.prefs.Preferences;
public class ActionGenerateTikz extends ActionVisualization {
private static Logger logger = LogManager.getLogger(ActionGenerateTikz.class);
private static Resources resources = Resources.getInstance("postvisualization");
private final TikzGenerator tikzGenerator;
public ActionGenerateTikz(final String name, final Icon icon, final PostvisualizationRenderer renderer) {
super(name, icon, renderer.getModel());
this.tikzGenerator = new TikzGenerator(renderer, renderer.getModel());
}
@Override
public void actionPerformed(ActionEvent e) {
Date todaysDate = new Date();
SimpleDateFormat formatter = new SimpleDateFormat(resources.getProperty("View.dataFormat"));
String formattedDate = formatter.format(todaysDate);
JFileChooser fileChooser = new JFileChooser(Preferences.userNodeForPackage(PostVisualisation.class).get("PostVis.snapshotDirectory.path", "."));
File outputFile = new File("pv_snapshot_" + formattedDate + ".tex");
fileChooser.setSelectedFile(outputFile);
int returnVal = fileChooser.showDialog(null, "Save");
if (returnVal == JFileChooser.APPROVE_OPTION) {
outputFile = fileChooser.getSelectedFile().toString().endsWith(".tex") ? fileChooser.getSelectedFile()
: new File(fileChooser.getSelectedFile().toString() + ".tex");
boolean completeDocument = true;
tikzGenerator.generateTikz(outputFile, completeDocument);
}
}
}
package org.vadere.gui.postvisualization.utils;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.vadere.gui.components.model.DefaultSimulationConfig;
import org.vadere.gui.components.model.SimulationModel;
import org.vadere.gui.components.view.SimulationRenderer;
import org.vadere.state.scenario.*;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.PathIterator;
import java.io.*;
import java.util.*;
import static java.awt.geom.PathIterator.*;
/**
* Convert the (Java) scenario description into a TikZ representation.
*
* Usually, each (Java) scenario element is represented as a path via
* @see PathIterator This PathSeparator must be converted into its TikZ
* representation.
*
* For example, traversing a Java path with PathIterator returns two
* segments:
*
*
* segment type= 0 (SEG_MOVETO) with coords: [1.0, 1.0, 0.0, 0.0, 0.0, 0.0]
* segment type= 3 (SEG_LINETO) with coords: [2.0, 2.0, 0.0, 0.0, 0.0, 0.0]
*
* This must be transformed to TikZ:
*
* (1.0,1.0) to (2.0,2.0)
*
* The TikZGenerator should also respect the GUI settings (e.g., enabled
* elements, colors etc.).
*/
public class TikzGenerator {
private final static Logger logger = LogManager.getLogger(TikzGenerator.class);
private final SimulationRenderer renderer;
private final SimulationModel<? extends DefaultSimulationConfig> model;
private final String[] translationTable;
public TikzGenerator(final SimulationRenderer renderer,
final SimulationModel<? extends DefaultSimulationConfig> model) {
this.renderer = renderer;
this.model = model;
this.translationTable = new String[SEG_CLOSE + 1];
initializeTranslationTable(translationTable);
}
private void initializeTranslationTable(String[] translationTable) {
// Map Java path commands to TikZ commands.
translationTable[SEG_MOVETO] = "(%f,%f) ";
translationTable[SEG_LINETO] = "to (%f,%f) ";
translationTable[SEG_QUADTO] = ".. controls (%f,%f) .. (%f,%f) ";
translationTable[SEG_CUBICTO] = ".. controls (%f,%f) and (%f,%f) .. (%f,%f) ";
translationTable[SEG_CLOSE] = "to cycle;";
}
public void generateTikz(final File file, final boolean generateCompleteDocument) {
String texTemplate = "" +
"\\documentclass{standalone}\n" +
"\\usepackage{tikz}\n\n" +
"\\begin{document}\n" +
"\\begin{tikzpicture}\n" +
"%s" +
"\\end{tikzpicture}\n" +
"\\end{document}\n";
String tikzCode = "";
tikzCode += generateTikzColorDefinitions(model);
tikzCode += convertScenarioElementsToTikz();
String output = (generateCompleteDocument) ? String.format(texTemplate, tikzCode) : tikzCode ;
// TODO: maybe uses Java's resources notation (in general, writing the file should be done by the caller not here).
try {
file.createNewFile();
Writer out = new OutputStreamWriter(new FileOutputStream(file), "UTF-8");
out.write(output);
out.flush();
logger.info("generate new TikZ: " + file.getAbsolutePath());
} catch (IOException e1) {
logger.error(e1.getMessage());
e1.printStackTrace();
}
}
private String generateTikzColorDefinitions(SimulationModel<? extends DefaultSimulationConfig> model) {
String colorDefinitions = "% Color Definitions\n";
String colorTextPattern = "\\definecolor{%s}{RGB}{%d,%d,%d}\n";
Color sourceColor = model.getConfig().getSourceColor();
colorDefinitions += String.format(colorTextPattern, "SourceColor", sourceColor.getRed(), sourceColor.getGreen(), sourceColor.getBlue());
Color targetColor = model.getConfig().getTargetColor();
colorDefinitions += String.format(colorTextPattern, "TargetColor", targetColor.getRed(), targetColor.getGreen(), targetColor.getBlue());
Color obstacleColor = model.getConfig().getObstacleColor();
colorDefinitions += String.format(colorTextPattern, "ObstacleColor", obstacleColor.getRed(), obstacleColor.getGreen(), obstacleColor.getBlue());
Color stairColor = model.getConfig().getStairColor();
colorDefinitions += String.format(colorTextPattern, "StairColor", stairColor.getRed(), stairColor.getGreen(), stairColor.getBlue());
Color agentColor = model.getConfig().getPedestrianDefaultColor();
colorDefinitions += String.format(colorTextPattern, "AgentColor", agentColor.getRed(), agentColor.getGreen(), agentColor.getBlue());
return colorDefinitions;
}
private String convertScenarioElementsToTikz() {
String generatedCode = "";
DefaultSimulationConfig config = model.getConfig();
Topography topography = model.getTopography();
// Draw background elements first, then agents.
generatedCode += "% Ground\n";
String groundTextPattern = (config.isShowGrid()) ? "\\draw[help lines] (%f,%f) grid (%f,%f);\n" : "\\fill[white] (%f,%f) rectangle (%f,%f);\n";
generatedCode += String.format(groundTextPattern,
topography.getBounds().x,
topography.getBounds().y,
topography.getBounds().x + topography.getBounds().width,
topography.getBounds().y + topography.getBounds().height);
if (config.isShowSources()) {
generatedCode += "% Sources\n";
for (Source source : topography.getSources()) {
generatedCode += String.format("\\fill[SourceColor] %s\n", generatePathForScenarioElement(source));
}
} else {
generatedCode += "% Sources (not enabled in config)\n";
}
if (config.isShowTargets()) {
generatedCode += "% Targets\n";
for (Target target : topography.getTargets()) {
generatedCode += String.format("\\fill[TargetColor] %s\n", generatePathForScenarioElement(target));
}
} else {
generatedCode += "% Targets (not enabled in config)\n";
}
if (config.isShowObstacles()) {
generatedCode += "% Obstacles\n";
for (Obstacle obstacle : topography.getObstacles()) {
generatedCode += String.format("\\fill[ObstacleColor] %s\n", generatePathForScenarioElement(obstacle));
}
} else {
generatedCode += "% Obstacles (not enabled in config)\n";
}
if (config.isShowStairs()) {
generatedCode += "% Stairs\n";
for (Stairs stair : topography.getStairs()) {
generatedCode += String.format("\\fill[StairColor] %s\n", generatePathForScenarioElement(stair));
}
} else {
generatedCode += "% Stairs (not enabled in config)\n";
}
// TODO: maybe, draw also trajectories.
if (config.isShowPedestrians()) {
generatedCode += "% Agents\n";
for (Agent agent : model.getAgents()) {
String agentTextPattern = "\\fill[AgentColor] (%f,%f) circle [radius=%fcm];\n";
generatedCode += String.format(agentTextPattern, agent.getPosition().x, agent.getPosition().y, agent.getRadius());
// Do not draw agents as path for performance reasons. Usually, agents have a circular shape.
// generatedCode += String.format("\\fill[AgentColor] %s\n", generatePathForScenarioElement(agent));
}
} else {
generatedCode += "% Agents (not enabled in config)\n";
}
return generatedCode;
}
private String generatePathForScenarioElement(ScenarioElement element) {
String generatedPath = "";
AffineTransform noTransformation = new AffineTransform();
PathIterator pathIterator = element.getShape().getPathIterator(noTransformation);
while (!pathIterator.isDone()) {
float[] coords = new float[6];
int type = pathIterator.currentSegment(coords);
generatedPath += convertJavaToTikzPath(type, coords);
pathIterator.next();
}
return generatedPath;
}
private String convertJavaToTikzPath(int type, float[] coords) {
if (type < SEG_MOVETO || type > SEG_CLOSE) {
throw new IllegalStateException(String.format("Cannot process path segment type: %d (coordinates: %s)", type, Arrays.toString(coords)));
}
String convertedPath = translationTable[type];
if (type == SEG_MOVETO) {
convertedPath = String.format(convertedPath, coords[0], coords[1]);
} else if (type == SEG_LINETO) {
convertedPath = String.format(convertedPath, coords[0], coords[1]);
} else if (type == SEG_QUADTO) {
convertedPath = String.format(convertedPath, coords[0], coords[1], coords[2], coords[3]);
} else if (type == SEG_CUBICTO) {
convertedPath = String.format(convertedPath, coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]);
}
return convertedPath;
}
}
......@@ -13,29 +13,16 @@ import org.vadere.gui.components.utils.Resources;
import org.vadere.gui.components.utils.SwingUtils;
import org.vadere.gui.components.view.ScenarioElementView;
import org.vadere.gui.postvisualization.PostVisualisation;
import org.vadere.gui.postvisualization.control.ActionGeneratePNG;
import org.vadere.gui.postvisualization.control.ActionGenerateSVG;
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.postvisualization.control.ActionRemoveFloorFieldFile;
import org.vadere.gui.postvisualization.control.ActionShowPotentialField;
import org.vadere.gui.postvisualization.control.ActionStop;
import org.vadere.gui.postvisualization.control.ActionSwapSelectionMode;
import org.vadere.gui.postvisualization.control.ActionVisualization;
import org.vadere.gui.postvisualization.control.Player;
import org.vadere.gui.postvisualization.control.*;
import org.vadere.gui.postvisualization.model.PostvisualizationModel;
import org.vadere.gui.projectview.control.ActionDeselect;
import org.vadere.simulator.projects.Scenario;
import org.vadere.simulator.projects.io.HashGenerator;
import org.vadere.simulator.projects.io.IOOutput;
import org.vadere.util.geometry.shapes.VRectangle;
import org.vadere.util.io.IOUtils;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.text.MessageFormat;
......@@ -259,6 +246,11 @@ public class PostvisualizationWindow extends JPanel implements Observer {
new ActionGenerateSVG("svg_snapshot", resources.getIcon("camera_svg.png", iconWidth, iconHeight),
renderer),
"PostVis.btnSVGSnapshot.tooltip");
addActionToToolbar(
toolbar,
new ActionGenerateTikz("tikz_snapshot", resources.getIcon("camera_tikz.png", iconWidth, iconHeight),
renderer),
"PostVis.btnTikZSnapshot.tooltip");
toolbar.addSeparator(new Dimension(5, 50));
......
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