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

before changing Rupperts algorithm.

parent b8da33b0
......@@ -238,6 +238,7 @@ ProjectView.btnSnapshot.tooltip=Snapshot
ProjectView.btnPNGSnapshot.tooltip=PNG Snapshot
ProjectView.btnSVGSnapshot.tooltip=SVG Snapshot
ProjectView.btnTikZSnapshot.tooltip=TikZ Snapshot
ProjectView.btnPolySnapshot.tooltip=Poly Snapshot
PostVis.menuFile.title=File
PostVis.menuSettings.title=Setting
PostVis.menuRecentFiles.title=Recent Files
......
......@@ -234,6 +234,7 @@ ProjectView.btnSnapshot.tooltip=Snapshot
ProjectView.btnPNGSnapshot.tooltip=PNG-Snapshot
ProjectView.btnSVGSnapshot.tooltip=SVG-Snapshot
ProjectView.btnTikZSnapshot.tooltip=TikZ-Snapshot
ProjectView.btnPolySnapshot.tooltip=Poly-Snapshot
PostVis.menuFile.title=Datei
PostVis.menuSettings.title=Einstellungen
PostVis.menuRecentFiles.title=K\u00FCrzlich verwendete Dateien
......
package org.vadere.gui.components.control.simulation;
import org.vadere.gui.components.model.DefaultSimulationConfig;
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.PostVisualisation;
import org.vadere.meshing.utils.io.poly.PolyGenerator;
import org.vadere.state.scenario.Obstacle;
import org.vadere.util.geometry.shapes.VPolygon;
import org.vadere.util.geometry.shapes.VRectangle;
import org.vadere.util.logging.Logger;
import java.awt.event.ActionEvent;
import java.awt.geom.Rectangle2D;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.prefs.Preferences;
import java.util.stream.Collectors;
import javax.swing.*;
public class ActionGeneratePoly extends AbstractAction {
private static Logger logger = Logger.getLogger(ActionGeneratePNG.class);
private static Resources resources = Resources.getInstance("global");
private final SimulationModel<? extends DefaultSimulationConfig> model;
public ActionGeneratePoly(final String name, Icon icon, final SimulationRenderer renderer,
final SimulationModel<? extends DefaultSimulationConfig> model) {
super(name, icon);
this.model = model;
}
@Override
public void actionPerformed(final ActionEvent e) {
JFileChooser fileChooser = new JFileChooser(Preferences.userNodeForPackage(PostVisualisation.class).get("SettingsDialog.snapshotDirectory.path", "."));
Date todaysDate = new java.util.Date();
SimpleDateFormat formatter = new SimpleDateFormat(resources.getProperty("SettingsDialog.dataFormat"));
String formattedDate = formatter.format(todaysDate);
File outputFile = new File(Messages.getString("FileDialog.filenamePrefix") + formattedDate + ".poly");
fileChooser.setSelectedFile(outputFile);
int returnVal = fileChooser.showDialog(null, "Save");
if (returnVal == JFileChooser.APPROVE_OPTION) {
outputFile = fileChooser.getSelectedFile().toString().endsWith(".poly") ? fileChooser.getSelectedFile()
: new File(fileChooser.getSelectedFile().toString() + ".poly");
List<Obstacle> boundingObstacles = model.getTopography().getBoundaryObstacles();
Rectangle2D.Double boundWithBorder = model.getTopography().getBounds();
double boundWidth = model.getTopography().getBoundingBoxWidth();
VRectangle bound = new VRectangle(boundWithBorder.x + boundWidth, boundWithBorder.y + boundWidth, boundWithBorder.width - 2*boundWidth, boundWithBorder.height - 2*boundWidth);
List<Obstacle> obstacles = new ArrayList<>(model.getTopography().getObstacles());
obstacles.removeAll(model.getTopography().getBoundaryObstacles());
String polyString = PolyGenerator.toPSLG(
new VPolygon(bound),
obstacles.stream()
.map(obs -> obs.getShape())
.map(shape -> new VPolygon(shape))
.collect(Collectors.toList()));
try {
outputFile.createNewFile();
Writer out = new OutputStreamWriter(new FileOutputStream(outputFile), "UTF-8");
out.write(polyString);
out.flush();
logger.info("generate new Poly.file: " + outputFile.getAbsolutePath());
} catch (IOException e1) {
logger.error(e1.getMessage());
e1.printStackTrace();
}
}
}
}
......@@ -7,6 +7,7 @@ import org.vadere.gui.components.control.IViewportChangeListener;
import org.vadere.gui.components.control.JViewportChangeListener;
import org.vadere.gui.components.control.PanelResizeListener;
import org.vadere.gui.components.control.ViewportChangeListener;
import org.vadere.gui.components.control.simulation.ActionGeneratePoly;
import org.vadere.gui.components.utils.Messages;
import org.vadere.gui.components.utils.Resources;
import org.vadere.gui.components.utils.SwingUtils;
......@@ -174,7 +175,6 @@ public class OnlineVisualisationWindow extends JPanel implements Observer {
renderer,
model);
ActionGenerateSVG generateSVG = new ActionGenerateSVG(
Messages.getString("ProjectView.btnSVGSnapshot.tooltip"),
resources.getIcon("camera_svg.png", iconWidth, iconHeight),
......@@ -187,6 +187,12 @@ public class OnlineVisualisationWindow extends JPanel implements Observer {
renderer,
model);
ActionGeneratePoly generatePoly = new ActionGeneratePoly(
Messages.getString("ProjectView.btnPolySnapshot.tooltip"),
resources.getIcon("camera_poly.png", iconWidth, iconHeight),
renderer,
model);
ActionShowPotentialField showPotentialField = new ActionShowPotentialField(
"showPotentialField",
resources.getIcon("potentialField.png", iconWidth, iconHeight),
......@@ -222,6 +228,7 @@ public class OnlineVisualisationWindow extends JPanel implements Observer {
imgOptions.add(generatePNG);
imgOptions.add(generateSVG);
imgOptions.add(generateTikz);
imgOptions.add(generatePoly);
ActionOnlineVisMenu imgDialog = new ActionOnlineVisMenu(
"camera_menu",
......
......@@ -8,6 +8,7 @@ import org.vadere.gui.components.control.JViewportChangeListener;
import org.vadere.gui.components.control.PanelResizeListener;
import org.vadere.gui.components.control.ViewportChangeListener;
import org.vadere.gui.components.control.simulation.ActionGeneratePNG;
import org.vadere.gui.components.control.simulation.ActionGeneratePoly;
import org.vadere.gui.components.control.simulation.ActionGenerateSVG;
import org.vadere.gui.components.control.simulation.ActionGenerateTikz;
import org.vadere.gui.components.control.simulation.ActionSwapSelectionMode;
......@@ -242,11 +243,16 @@ public class PostvisualizationWindow extends JPanel implements Observer {
renderer, model);
AbstractAction tikzImg = new ActionGenerateTikz(Messages.getString("ProjectView.btnTikZSnapshot.tooltip"), resources.getIcon("camera_tikz.png", iconWidth, iconHeight),
renderer, model);
AbstractAction polyImg = new ActionGeneratePoly(Messages.getString("ProjectView.btnPolySnapshot.tooltip"), resources.getIcon("camera_poly.png", iconWidth, iconHeight),
renderer, model);
// add new ImageGenerator Action ...
imgOptions.add(pngImg);
imgOptions.add(svgImg);
imgOptions.add(tikzImg);
imgOptions.add(polyImg);
// add Action to List ....
ActionVisualizationMenu imgDialog = new ActionVisualizationMenu(
......
# a.poly
#
# The capital letter A
#
# Declare 29 vertices, 2 dimensions, 1 attribute, no boundary markers.
#
29 2 1 0
#
# List the vertices.
#
1 0.200000 -0.776400 -0.57
2 0.220000 -0.773200 -0.55
3 0.245600 -0.756400 -0.51
4 0.277600 -0.702000 -0.53
5 0.488800 -0.207600 0.28
6 0.504800 -0.207600 0.30
7 0.740800 -0.739600 0
8 0.756000 -0.761200 -0.01
9 0.774400 -0.772400 0
10 0.800000 -0.776400 0.02
11 0.800000 -0.792400 0.01
12 0.579200 -0.792400 -0.21
13 0.579200 -0.776400 -0.2
14 0.621600 -0.771600 -0.15
15 0.633600 -0.762800 -0.13
16 0.639200 -0.744400 -0.1
17 0.620800 -0.684400 -0.06
18 0.587200 -0.604400 -0.01
19 0.360800 -0.604400 -0.24
20 0.319200 -0.706800 -0.39
21 0.312000 -0.739600 -0.43
22 0.318400 -0.761200 -0.44
23 0.334400 -0.771600 -0.44
24 0.371200 -0.776400 -0.41
25 0.371200 -0.792400 -0.42
26 0.374400 -0.570000 -0.2
27 0.574400 -0.570000 0
28 0.473600 -0.330800 0.14
29 0.200000 -0.792400 -0.59
#
# Declare the number of segments.
#
29 0
#
# List the segments.
#
1 29 1
2 1 2
3 2 3
4 3 4
5 4 5
6 5 6
7 6 7
8 7 8
9 8 9
10 9 10
11 10 11
12 11 12
13 12 13
14 13 14
15 14 15
16 15 16
17 16 17
18 17 18
19 18 19
20 19 20
21 20 21
22 21 22
23 22 23
24 23 24
25 24 25
26 25 29
27 26 27
28 27 28
29 28 26
#
# Declare the number of holes.
#
1
#
# Define the hole.
#
1 0.47 -0.5
\ No newline at end of file
......@@ -5,6 +5,8 @@ import org.vadere.meshing.mesh.inter.IPointConstructor;
import org.vadere.meshing.mesh.triangulation.IEdgeLengthFunction;
import org.vadere.meshing.mesh.triangulation.improver.eikmesh.gen.GenEikMesh;
import org.vadere.meshing.mesh.triangulation.improver.eikmesh.gen.PEikMeshGen;
import org.vadere.meshing.mesh.triangulation.triangulator.impl.PDelaunayTriangulator;
import org.vadere.meshing.utils.io.poly.PolyGenerator;
import org.vadere.util.geometry.GeometryUtils;
import org.vadere.meshing.mesh.gen.PFace;
import org.vadere.meshing.mesh.gen.PHalfEdge;
......@@ -21,6 +23,7 @@ import org.vadere.util.math.IDistanceFunction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
/**
* Shows a very basic example how {@link GenEikMesh} can be used
......@@ -28,14 +31,54 @@ import java.util.List;
*/
public class EikMeshExamples {
public static void main(String... args) {
uniformMeshShapes();
public static void main(String... args) throws InterruptedException {
//delaunayTriangulation();
//uniformMeshShapes();
uniformMeshDiscFunction();
uniformMeshRingFunction();
combineDistanceFunctions();
//uniformMeshRingFunction();
/*combineDistanceFunctions();
edgeLengthFunction();
edgeLengthAndDistanceFunction();
userDefinedPoints();
userDefinedPoints();*/
}
public static void delaunayTriangulation() throws InterruptedException {
Random random = new Random(0);
int width = 10;
int height = 10;
int numberOfPoints = 200;
double linePoints = (int)Math.sqrt(numberOfPoints)+5;
List<EikMeshPoint> points = new ArrayList<>();
for(double i = 0; i < linePoints; i++) {
points.add(new EikMeshPoint(0.1, 0.1 + i / linePoints * (height-0.2), true));
points.add(new EikMeshPoint(0.1 + i / linePoints * (width-0.2), 0.1, true));
points.add(new EikMeshPoint(width-0.2, 0.1 + i / linePoints * (height-0.2), true));
points.add(new EikMeshPoint(0.1 + i / linePoints * (width-0.2), height-0.2, true));
}
for(int i = 0; i < numberOfPoints-15; i++) {
points.add(new EikMeshPoint(1.5 + random.nextDouble() * (width-3), 1.5 + random.nextDouble() * (height-3)));
}
var delaunayTriangulator = new PDelaunayTriangulator<>(points, (x, y) -> new EikMeshPoint(x, y, false));
var triangulation = delaunayTriangulator.generate();
var improver = new PEikMeshGen<>(p -> 1.0, triangulation);
var panel = new PMeshPanel<>(triangulation.getMesh(), 500, 500);
panel.display("A square mesh");
panel.repaint();
for(int i = 0; i < 1000; i++) {
Thread.sleep(5000);
improver.improve();
panel.repaint();
}
}
/**
......@@ -109,36 +152,48 @@ public class EikMeshExamples {
* The edgeLength is a measure for the approximate edge lengths of all edges since it is a uniform triangulation,
* i.e. the desired edge length function is a constant.
*/
public static void uniformMeshDiscFunction() {
public static void uniformMeshDiscFunction() throws InterruptedException {
// define a bounding box
VRectangle bound = new VRectangle(-0.1, -0.1, 2.2, 2.2);
// distance function that defines a disc with radius 1 at (1,1).
IDistanceFunction d = p -> Math.sqrt((p.getX() - 1) * (p.getX() - 1) + (p.getY() - 1) * (p.getY() - 1)) - 1.0;
//IDistanceFunction.createDisc(1, 1, 1.0);
VPoint center = new VPoint(1,1);
IDistanceFunction d = IDistanceFunction.createDisc(center.x, center.y, 1.0);
IEdgeLengthFunction h = p -> 1.0 + 5.0 * Math.abs(d.apply(p));
// define the EikMesh-Improver
double h0 = 0.1;
PEikMeshGen<EikMeshPoint, Double, Double> meshImprover = new PEikMeshGen<>(
d,
h,
p -> 1.0,
Arrays.asList(center),
h0,
bound,
(x, y) -> new EikMeshPoint(x, y, false));
meshImprover.generate();
//meshImprover.generate();
//System.out.println(TexGraphGenerator.toTikz(meshImprover.getMesh()));
// (optional) define the gui to display the mesh
//PMeshPanel<EikMeshPoint, Double, Double> meshPanel = new PMeshPanel<>(meshImprover.getMesh(), 1000, 800);
PMeshPanel<EikMeshPoint, Double, Double> meshPanel = new PMeshPanel<>(meshImprover.getMesh(), 1000, 800);
// generate the mesh
// display the mesh
//meshPanel.display("Geometry defined by a distance function (disc)");
meshPanel.display("Geometry defined by a distance function (disc)");
while (true) {
synchronized (meshImprover.getMesh()) {
meshImprover.improve();
}
Thread.sleep(100);
meshPanel.repaint();
}
//System.out.println(PolyGenerator.to2DPoly(meshImprover.getMesh()));
}
/**
......@@ -170,6 +225,8 @@ public class EikMeshExamples {
// generate the mesh
meshImprover.generate();
System.out.println(PolyGenerator.to2DPoly(meshImprover.getMesh()));
// display the mesh
meshPanel.display("Geometry defined by a distance function (ring)");
}
......
......@@ -109,7 +109,7 @@ public class IncrementalTriangulation<P extends IPoint, CE, CF, V extends IVerte
this.mesh = mesh;
this.points = points;
this.illegalPredicate = illegalPredicate;
this.bound = GeometryUtils.bound(points, epsilon);
this.bound = GeometryUtils.boundRelative(points);
this.finalized = false;
this.initialized = false;
this.mesh = mesh;
......@@ -197,7 +197,7 @@ public class IncrementalTriangulation<P extends IPoint, CE, CF, V extends IVerte
this.mesh = mesh;
this.points = new HashSet<>();
this.illegalPredicate = illegalPredicate;
this.bound = GeometryUtils.bound(mesh.getPoints(mesh.getBorder()), epsilon);
this.bound = GeometryUtils.boundRelative(mesh.getPoints(mesh.getBorder()));
this.initialized = false;
this.finalized = false;
this.virtualVertices = new ArrayList<>();
......@@ -305,13 +305,11 @@ public class IncrementalTriangulation<P extends IPoint, CE, CF, V extends IVerte
double min = Math.min(bound.getWidth(), bound.getHeight());
double epsilon = BUFFER_PERCENTAGE * max; // 1% gap
double xMin = bound.getMinX();
double yMin = bound.getMinY();
double xMin = bound.getMinX() - epsilon;
double yMin = bound.getMinY() - epsilon;
double xMax = bound.getMinX() + bound.getWidth() * 2 + epsilon;
double yMax = bound.getMinY() + bound.getHeight() * 2 + epsilon;
double xMax = bound.getMinX() + 2*max;
double yMax = bound.getMinY() + 2*max;
V p0 = mesh.insertVertex(xMin, yMin);
V p1 = mesh.insertVertex(xMax, yMin);
......@@ -372,7 +370,7 @@ public class IncrementalTriangulation<P extends IPoint, CE, CF, V extends IVerte
initialized = false;
finalized = false;
points = mesh.getPoints();
bound = GeometryUtils.bound(points, epsilon);
bound = GeometryUtils.boundRelative(points);
mesh.clear();
setPointLocator(type);
compute();
......@@ -411,7 +409,10 @@ public class IncrementalTriangulation<P extends IPoint, CE, CF, V extends IVerte
}
else {
//log.info("splitTriangle()");
assert contains(vertex.getX(), vertex.getY(), face);
/*if(!contains(vertex.getX(), vertex.getY(), face)) {
System.out.println("wtf" + contains(vertex.getX(), vertex.getY(), f));
}*/
assert contains(vertex.getX(), vertex.getY(), face) : face + " does not contain " + vertex;
E newEdge = splitTriangle(face, vertex, true);
insertEvent(newEdge);
......@@ -716,25 +717,7 @@ public class IncrementalTriangulation<P extends IPoint, CE, CF, V extends IVerte
@Override
public boolean isIllegal(E edge, V p) {
if(!mesh.isAtBoundary(edge) && illegalPredicate.test(edge)) {
//assert mesh.getVertex(mesh.getNext(edge)).equals(p);
//V p = mesh.getVertex(mesh.getNext(edge));
E t0 = mesh.getTwin(edge);
E t1 = mesh.getNext(t0);
E t2 = mesh.getNext(t1);
V x = mesh.getVertex(t0);
V y = mesh.getVertex(t1);
V z = mesh.getVertex(t2);
//return Utils.angle(x, y, z) + Utils.angle(x, p, z) > Math.PI;
//return Utils.isInCircumscribedCycle(x, y, z, p);
//if(Utils.ccw(z,x,y) > 0) {
return GeometryUtils.isInsideCircle(z, x, y, p);
//}
//else {
// return Utils.isInsideCircle(x, z, y, p);
//}
return isDelaunayIllegal(edge, p);
}
return false;
......
......@@ -59,11 +59,33 @@ public class MeshPanel<P extends IPoint, CE, CF, V extends IVertex<P>, E extends
/**
* Construct a mesh panel filling faces with the color defined by the color function.
*
* @param mesh the mesh which will be rendered
* @param alertPred a {@link Predicate} of {@link F} which marks a face to be drawn in a special way.
* @param width width of the canvas
* @param height height of the canvas
* @param colorFunction color function coloring faces
* @param mesh the mesh which will be rendered
* @param alertPred a {@link Predicate} of {@link F} which marks a face to be drawn in a special way.
* @param width width of the canvas
* @param height height of the canvas
* @param colorFunction color function coloring faces
* @param edgeColorFunction color function coloring edges
*/
public MeshPanel(
@NotNull final IMesh<P, CE, CF, V, E, F> mesh,
@NotNull final Predicate<F> alertPred,
final double width,
final double height,
@NotNull final Function<F, Color> colorFunction,
@NotNull final Function<E, Color> edgeColorFunction) {
this.meshRenderer = new MeshRenderer<>(mesh, alertPred, colorFunction, edgeColorFunction);
this.height = height;
this.width = width;
}
/**
* Construct a mesh panel filling faces with the color defined by the color function.
*
* @param mesh the mesh which will be rendered
* @param alertPred a {@link Predicate} of {@link F} which marks a face to be drawn in a special way.
* @param width width of the canvas
* @param height height of the canvas
* @param colorFunction color function coloring faces
*/
public MeshPanel(
@NotNull final IMesh<P, CE, CF, V, E, F> mesh,
......@@ -71,7 +93,7 @@ public class MeshPanel<P extends IPoint, CE, CF, V extends IVertex<P>, E extends
final double width,
final double height,
@NotNull final Function<F, Color> colorFunction) {
this.meshRenderer = new MeshRenderer<>(mesh, alertPred, colorFunction);
this.meshRenderer = new MeshRenderer<>(mesh, alertPred, colorFunction, e -> Color.GRAY);
this.height = height;
this.width = width;
}
......@@ -89,7 +111,7 @@ public class MeshPanel<P extends IPoint, CE, CF, V extends IVertex<P>, E extends
@NotNull final Predicate<F> alertPred,
final double width,
final double height) {
this(mesh, alertPred, width, height, f -> Color.WHITE);
this(mesh, alertPred, width, height, f -> Color.WHITE, e -> Color.GRAY);
}
/**
......@@ -103,7 +125,7 @@ public class MeshPanel<P extends IPoint, CE, CF, V extends IVertex<P>, E extends
@NotNull final IMesh<P, CE, CF, V, E, F> mesh,
final double width,
final double height) {
this(mesh, f -> false, width, height, f -> Color.WHITE);
this(mesh, f -> false, width, height, f -> Color.WHITE, e -> Color.GRAY);
}
@Override
......
......@@ -7,6 +7,7 @@ import org.vadere.meshing.mesh.inter.IHalfEdge;
import org.vadere.meshing.mesh.inter.IMesh;
import org.vadere.meshing.mesh.inter.IVertex;
import org.vadere.util.geometry.shapes.IPoint;
import org.vadere.util.geometry.shapes.VLine;
import org.vadere.util.geometry.shapes.VPolygon;
import org.vadere.util.geometry.shapes.VRectangle;
import org.vadere.util.logging.Logger;
......@@ -45,6 +46,8 @@ public class MeshRenderer<P extends IPoint, CE, CF, V extends IVertex<P>, E exte
*/
private Collection<F> faces;
private Collection<E> edges;
/**
* A {@link Predicate} of {@link F} which marks a face to be drawn (not filled) in a special way.
*/
......@@ -54,7 +57,9 @@ public class MeshRenderer<P extends IPoint, CE, CF, V extends IVertex<P>, E exte
/**
* A function which decides by which color the face should be filled.
*/
@Nullable private Function<F, Color> colorFunction;
@Nullable private Function<F, Color> faceColorFunction;
@Nullable private Function<E, Color> edgeColorFunction;
private BufferedImage bufferedImage = null;
......@@ -70,10 +75,20 @@ public class MeshRenderer<P extends IPoint, CE, CF, V extends IVertex<P>, E exte
@NotNull final IMesh<P, CE, CF, V, E, F> mesh,
@NotNull final Predicate<F> alertPred,
@Nullable final Function<F, Color> colorFunction) {
this(mesh, alertPred, colorFunction, null);
}