Commit 27da0fa3 authored by Benedikt Zoennchen's avatar Benedikt Zoennchen

introduce a more coarse background mesh to compute the distance function.

parent 7763e6f4
......@@ -136,6 +136,7 @@ ProjectView.chooseFile=Chose file
ProjectView.ScenarioChecker.title=Scenario Checker
ProjectView.ScenarioChecker.deactive.text=ScenarioChecker deactivated. Project > Activate ScenarioChecker
ProjectView.ScenarioChecker.active.text=The following problems where found
ProjectView.btnGenerateMesh.tooltip=Generate background mesh
SaveBeforeClosing.text=Do you want to save the current project before closing?
......@@ -353,6 +354,7 @@ TopographyCreator.btnSubtractMeasurementArea.label=Subtract Obstacle from Area
TopographyCreator.PlaceRandomPedestrians.label=Place Random Pedestrians
TopographyCreator.btnChecker.tooltip=Show Topography Checker Messages
TopographyCreator.btnGenerateIds.tooltip=Generate missing Ids for sources, targets, ...
TopographyCreator.btnGenerateMesh.tooltip=Generate background mesh
select_shape_tooltip=Select Shape
......
......@@ -137,6 +137,7 @@ ProjectView.label.simResults=Simulationsergebniss
ProjectView.ScenarioChecker.title=Scenario Checker
ProjectView.ScenarioChecker.deactive.text=ScenarioChecker deaktiviert. Projekt > ScenarioChecker aktivieren
ProjectView.ScenarioChecker.active.text=Probleme gefunden
ProjectView.btnGenerateMesh.tooltip=Generiere Hintergrundgitter
SaveBeforeClosing.text=Aktuelles Projekt vor dem Beenden speichern?
......@@ -348,7 +349,7 @@ TopographyCreator.btnSubtractMeasurementArea.label=Subtrahiere Hindernis von Mes
TopographyCreator.PlaceRandomPedestrians.label=Plaziere Zuf\u00e4llige Fu\u00dfg\u00e4nger
TopographyCreator.btnChecker.tooltip=Topography Linter Nachrichten
TopographyCreator.btnGenerateIds.tooltip=Erzeuge fehlende Ids f\u00fcr Quellen, Ziele, ...
TopographyCreator.btnGenerateMesh.tooltip=Generiere Hintergrundgitter
# tab titles Topography creator / postvis
Tab.Simulation.title=Simulation
......
package org.vadere.gui.components.control;
import org.apache.commons.configuration2.Configuration;
import org.jetbrains.annotations.NotNull;
import org.vadere.gui.components.control.simulation.ActionGeneratePNG;
import org.vadere.gui.projectview.model.ProjectViewModel;
import org.vadere.gui.topographycreator.view.ActionTranslateTopographyDialog;
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.impl.PSLG;
import org.vadere.meshing.mesh.inter.IMesh;
import org.vadere.meshing.utils.MeshConstructor;
import org.vadere.meshing.utils.io.poly.MeshPolyWriter;
import org.vadere.simulator.utils.pslg.PSLGConverter;
import org.vadere.util.config.VadereConfig;
import org.vadere.util.io.IOUtils;
import org.vadere.util.logging.Logger;
import java.awt.event.ActionEvent;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.concurrent.CompletableFuture;
import javax.swing.*;
public class ActionGenerateMesh extends AbstractAction {
private static Logger logger = Logger.getLogger(ActionGeneratePNG.class);
private static final Configuration CONFIG = VadereConfig.getConfig();
private final ProjectViewModel model;
public ActionGenerateMesh(final String name, Icon icon, final ProjectViewModel model) {
super(name, icon);
this.model = model;
}
@Override
public void actionPerformed(final ActionEvent e) {
/*JFileChooser fileChooser = new JFileChooser(CONFIG.getString("SettingsDialog.snapshotDirectory.path"));
Date todaysDate = new java.util.Date();
SimpleDateFormat formatter = new SimpleDateFormat(CONFIG.getString("SettingsDialog.dataFormat"));
String formattedDate = formatter.format(todaysDate);*/
ActionTranslateTopographyDialog dialog = new ActionTranslateTopographyDialog(0.5, 5.0, "hmin, hmax");
if (dialog.getValue()){
double hmin = dialog.getX();
double hmax = dialog.getY();
PSLGConverter pslgConverter = new PSLGConverter();
PSLG pslg = pslgConverter.toPSLG(model.getCurrentScenario().getTopography());
logger.info("generate poly");
MeshConstructor constructor = new MeshConstructor();
CompletableFuture.supplyAsync(() -> constructor.pslgToAdaptivePMesh(pslg, hmin, hmax, true)).thenAccept(mesh -> saveFloorFieldMesh(mesh,""));
CompletableFuture.supplyAsync(() -> constructor.pslgToCoarsePMesh(pslg, true)).thenAccept(mesh -> saveFloorFieldMesh(mesh,IOUtils.BACKGROUND_MESH_ENDING));
}
}
private void saveFloorFieldMesh(@NotNull final IMesh<PVertex, PHalfEdge, PFace> mesh, final String ending) {
logger.info("generate mesh");
File meshDir = new File(model.getCurrentProjectPath().concat("/" + IOUtils.SCENARIO_DIR + "/" + IOUtils.MESH_DIR));
File outputFile = new File(meshDir.getAbsoluteFile() + "/" + model.getCurrentScenario().getName() + ending + ".poly");
MeshPolyWriter<PVertex, PHalfEdge, PFace> meshPolyWriter = new MeshPolyWriter<>();
String meshString = meshPolyWriter.to2DPoly(mesh);
if(meshDir.exists()) {
meshDir.mkdir();
}
if(!outputFile.exists()) {
try {
outputFile.createNewFile();
} catch (IOException e1) {
e1.printStackTrace();
}
}
try(FileWriter fileWriter = new FileWriter(outputFile)) {
fileWriter.write(meshString);
logger.info("generate new mesh file: " + outputFile.getAbsolutePath());
} catch (IOException ex) {
logger.error(ex.getMessage());
ex.printStackTrace();
}
}
}
......@@ -256,7 +256,7 @@ public class ScenarioPanel extends JPanel implements IProjectChangeListener, Pro
tabbedPane.removeTabAt(tabbedPane.indexOfComponent(topographyCreatorView));
}
topographyCreatorView = new TopographyWindow(scenario);
topographyCreatorView = new TopographyWindow(scenario, model);
tabbedPane.addTab(Messages.getString("Tab.TopographyCreator.title"), topographyCreatorView);
tabbedPane.validate();
tabbedPane.repaint();
......
......@@ -19,8 +19,13 @@ public class ActionTranslateTopographyDialog {
private final double xOld;
private final double yOld;
private boolean valid;
private final String label;
public ActionTranslateTopographyDialog(final double x, double y){
this(x, y, "x, y");
}
public ActionTranslateTopographyDialog(final double x, double y, final String label){
this.textField = new JTextField(30);
this.textField.setText(String.format(Locale.ENGLISH, "%f, %f", x, y));
......@@ -30,6 +35,7 @@ public class ActionTranslateTopographyDialog {
this.y = y;
this.xOld = x;
this.yOld = y;
this.label = label;
}
public double getX() {
......@@ -44,7 +50,7 @@ public class ActionTranslateTopographyDialog {
return JOptionPane.showConfirmDialog(
ProjectView.getMainWindow(),
textField,
"x, y",
label,
JOptionPane.OK_CANCEL_OPTION) == JOptionPane.OK_OPTION;
}
......
......@@ -3,6 +3,8 @@ package org.vadere.gui.topographycreator.view;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
import org.jetbrains.annotations.NotNull;
import org.vadere.gui.components.control.ActionGenerateMesh;
import org.vadere.gui.components.control.ActionGeneratePoly;
import org.vadere.gui.components.control.IViewportChangeListener;
import org.vadere.gui.components.control.JViewportChangeListener;
......@@ -14,6 +16,7 @@ import org.vadere.gui.components.view.InfoPanel;
import org.vadere.gui.components.view.ScenarioElementView;
import org.vadere.gui.components.view.ScenarioToolBar;
import org.vadere.gui.projectview.control.ActionDeselect;
import org.vadere.gui.projectview.model.ProjectViewModel;
import org.vadere.gui.projectview.view.JsonValidIndicator;
import org.vadere.gui.topographycreator.control.ActionBasic;
import org.vadere.gui.topographycreator.control.ActionCopyElement;
......@@ -81,7 +84,7 @@ public class TopographyWindow extends JPanel {
private UndoableEditSupport undoSupport;
private UndoManager undoManager;
public TopographyWindow(final Scenario currentScenario) {
public TopographyWindow(final Scenario currentScenario, @NotNull final ProjectViewModel model) {
toolbar = new ScenarioToolBar("Toolbar");
int toolbarSize = VadereConfig.getConfig().getInt("Gui.toolbar.size");
......@@ -99,7 +102,7 @@ public class TopographyWindow extends JPanel {
undoManager = new UndoManager();
undoSupport.addUndoableEditListener(new UndoAdaptor(undoManager));
setTopography(new TopographyCreatorModel(currentScenario));
setTopography(new TopographyCreatorModel(currentScenario), model);
}
private static JButton addActionToToolbar(final JToolBar toolbar, final Action action,
......@@ -120,7 +123,7 @@ public class TopographyWindow extends JPanel {
return button;
}
private void setTopography(final TopographyCreatorModel panelModel) {
private void setTopography(final TopographyCreatorModel panelModel, @NotNull final ProjectViewModel model) {
this.panelModel = panelModel;
this.panelModel.setMouseSelectionMode(new SelectElementMode(panelModel, undoSupport));
......@@ -423,6 +426,10 @@ public class TopographyWindow extends JPanel {
resources.getIcon("camera_poly.png", iconWidth, iconHeight),
panelModel);
AbstractAction generateMesh = new ActionGenerateMesh(Messages.getString("ProjectView.btnGenerateMesh.tooltip"),
resources.getIcon("generate_mesh.png", iconWidth, iconHeight),
model);
/* create toolbar*/
addActionToToolbar(toolbar, selectShape, "select_shape_tooltip");
......@@ -468,6 +475,7 @@ public class TopographyWindow extends JPanel {
addActionToToolbar(toolbar, resetScenarioAction, "TopographyCreator.btnNewTopography.tooltip");
addActionToToolbar(toolbar, saveScenarioAction, "TopographyCreator.btnQuickSave.tooltip");
addActionToToolbar(toolbar, polyImg, "TopographyCreator.btnGeneratePoly.tooltip");
addActionToToolbar(toolbar, generateMesh, "TopographyCreator.btnGenerateMesh.tooltip");
toolbar.addSeparator(new Dimension(5, 50));
addActionToToolbar(toolbar, undoAction, "TopographyCreator.btnUndo.tooltip");
......
# nVertices dimension nAttributes boundaryMarker
19 2 0 0
18 2 0 0
# vertexId x y
1 10.068317 15.240938
2 0.500000 12.473684
3 49.500000 49.500000
4 49.500000 0.500000
5 7.711478 10.030659
6 0.500000 45.907735
7 0.500000 42.907735
8 32.129121 5.936819
9 0.500000 49.500000
10 3.888684 20.251412
11 1.463889 42.907735
12 1.821300 11.082842
13 23.463889 45.907735
14 49.500000 5.936819
15 15.459378 12.808810
16 20.931872 10.544835
17 29.892589 0.500000
18 49.500000 42.506680
19 31.295924 42.506680
2 49.500000 49.500000
3 49.500000 0.500000
4 7.711478 10.030659
5 0.500000 45.907735
6 32.129121 5.936819
7 0.500000 49.500000
8 3.888684 20.251412
9 0.985522 42.000000
10 0.500000 11.318871
11 23.463889 45.907735
12 49.500000 5.936819
13 15.459378 12.808810
14 29.892589 0.500000
15 20.931872 10.544835
16 49.500000 42.506680
17 0.500000 42.000000
18 31.295924 42.506680
#
# nSegments boundaryMarker
19 0
18 0
# lineId vertexId1 vertexId2
1 4 14
2 14 8
3 8 16
4 16 19
5 19 18
6 18 3
7 3 9
8 9 6
9 6 13
10 13 15
11 15 1
12 1 10
13 10 11
14 11 7
15 7 2
16 2 12
17 12 5
18 5 17
19 17 4
1 10 4
2 4 14
3 14 3
4 3 12
5 12 6
6 6 15
7 15 18
8 18 16
9 16 2
10 2 7
11 7 5
12 5 11
13 11 13
14 13 1
15 1 8
16 8 9
17 9 17
18 17 10
#
# nHoles
0
......
package org.vadere.meshing.examples;
import org.jetbrains.annotations.NotNull;
import org.vadere.meshing.mesh.gen.PMesh;
import org.vadere.meshing.mesh.impl.PSLG;
import org.vadere.meshing.mesh.triangulation.DistanceFunctionApproxBF;
import org.vadere.meshing.mesh.triangulation.EdgeLengthFunctionApprox;
......@@ -42,7 +43,7 @@ public class BackgroundMeshExamples {
public static void distance(@NotNull final String fileName) throws IOException {
final InputStream inputStream = MeshExamples.class.getResourceAsStream(fileName);
PSLG pslg = PSLGGenerator.toPSLG(inputStream);
DistanceFunctionApproxBF distFunctionApprox = new DistanceFunctionApproxBF(pslg, IDistanceFunction.create(pslg.getSegmentBound(), pslg.getHoles()));
DistanceFunctionApproxBF distFunctionApprox = new DistanceFunctionApproxBF(pslg, IDistanceFunction.create(pslg.getSegmentBound(), pslg.getHoles()),() -> new PMesh());
distFunctionApprox.printPython();
}
}
......@@ -57,7 +57,7 @@ public class EikMeshPoly {
Collection<VPolygon> holes = pslg.getHoles();
VPolygon segmentBound = pslg.getSegmentBound();
IDistanceFunction distanceFunction = IDistanceFunction.create(segmentBound, holes);
IDistanceFunction distanceFunctionApproximation = new DistanceFunctionApproxBF(pslg, distanceFunction);
IDistanceFunction distanceFunctionApproximation = new DistanceFunctionApproxBF(pslg, distanceFunction, () -> new PMesh());
var ruppert = new PRuppertsTriangulator(
pslg,
......
package org.vadere.meshing.examples;
import org.vadere.meshing.mesh.gen.MeshRenderer;
import org.vadere.meshing.mesh.gen.PFace;
import org.vadere.meshing.mesh.impl.PMeshPanel;
import org.vadere.meshing.mesh.impl.PSLG;
import org.vadere.meshing.mesh.triangulation.EdgeLengthFunctionApprox;
import org.vadere.meshing.mesh.triangulation.improver.eikmesh.impl.PEikMesh;
import org.vadere.meshing.utils.color.Colors;
import org.vadere.meshing.utils.io.poly.PSLGGenerator;
import org.vadere.meshing.utils.io.tex.TexGraphGenerator;
import org.vadere.util.geometry.shapes.VTriangle;
import org.vadere.util.math.IDistanceFunction;
import java.awt.*;
import java.io.IOException;
import java.io.InputStream;
import java.util.function.Function;
public class ElementSizeFunction {
public static void main(String ... args) throws IOException {
String fileName = "/poly/kaiserslautern.poly";
final InputStream inputStream = ElementSizeFunction.class.getResourceAsStream("/poly/kaiserslautern.poly");
System.out.println(String.format("Meshing %s...", fileName));
PSLG pslg = PSLGGenerator.toPSLG(inputStream);
System.out.println("minX = " + pslg.getAllPoints().stream().mapToDouble(p -> p.getX()).min().getAsDouble());
System.out.println("minY = " + pslg.getAllPoints().stream().mapToDouble(p -> p.getY()).min().getAsDouble());
System.out.println("maxX = " + pslg.getAllPoints().stream().mapToDouble(p -> p.getX()).max().getAsDouble());
System.out.println("maxY = " + pslg.getAllPoints().stream().mapToDouble(p -> p.getY()).max().getAsDouble());
EdgeLengthFunctionApprox edgeLengthFunctionApprox = new EdgeLengthFunctionApprox(pslg);
edgeLengthFunctionApprox.smooth(0.4);
edgeLengthFunctionApprox.printPython();
Function<PFace, Color> colorFunction = f -> {
VTriangle triangle = edgeLengthFunctionApprox.getMesh().toTriangle(f);
if(pslg.getHoles().stream().anyMatch(hole -> hole.contains(triangle.midPoint())) || !pslg.getSegmentBound().contains(triangle.midPoint())) {
return Color.WHITE;
} else {
return Colors.YELLOW;
}
};
System.out.println(TexGraphGenerator.toTikz(edgeLengthFunctionApprox.getMesh(), colorFunction, e -> Color.BLACK, v -> Color.BLACK, 1.0f, true));
System.out.println(edgeLengthFunctionApprox.getMesh().getNumberOfVertices());
double h0 = 1.0;
var meshImprover = new PEikMesh(
IDistanceFunction.create(pslg.getSegmentBound(), pslg.getHoles()),
p -> edgeLengthFunctionApprox.apply(p),
h0,
pslg.getBoundingBox(),
pslg.getAllPolygons()
);
var meshRenderer = new MeshRenderer<>(meshImprover.getMesh(), f -> false, f -> Color.WHITE, e -> Color.GRAY, v -> Color.BLACK);
var meshPanel = new PMeshPanel(meshRenderer, 1000, 800);
meshPanel.display("Combined distance functions " + h0);
meshImprover.improve();
int i = 1;
while (!meshImprover.isFinished()) {
synchronized (meshImprover.getMesh()) {
meshImprover.improve();
}
//Thread.sleep(500);
meshPanel.repaint();
System.out.println(i + ":" + meshImprover.getQuality());
i++;
}
System.out.println(TexGraphGenerator.toTikz(meshImprover.getMesh(), colorFunction, e -> Color.BLACK, v -> Color.BLACK, 1.0f, true));
}
}
......@@ -57,7 +57,7 @@ public class MeshExamples {
/*for(int i = 1; i <= 629; i++) {
System.out.println(i + " " + i + " " + (i + 1));
}*/
eikMeshRandom();
//eikMeshRandom();
//eikMeshGreenland();
//ruppertsTriangulationKaiserslauternLarge();
//ruppertsTriangulationPoly();
......@@ -65,10 +65,10 @@ public class MeshExamples {
// delaunayTriangulation();
//dirichletRefinment();
// delaunayRefinment();
//constrainedDelaunayTriangulation();
// constrainedDelaunayTriangulation();
//eikMeshKaiserslautern();
//eikMeshKaiserslauternApprox();
//eikMeshA();
eikMeshA();
//eikMeshEik();
}
......@@ -580,7 +580,7 @@ public class MeshExamples {
//IDistanceFunction d = IDistanceFunction.create(pslg.getSegmentBound(), pslg.getHoles());
PEikMesh meshImprover = new PEikMesh(pslg.getSegmentBound(), 0.04, pslg.getHoles());
var panel = new PMeshPanel(meshImprover.getMesh(), 1000, 1000);
var panel = new PMeshPanel(meshImprover.getMesh(), 500, 500);
panel.display("EikMesh");
while (!meshImprover.isFinished()) {
......@@ -922,7 +922,7 @@ public class MeshExamples {
private static boolean isLowOfQuality(@NotNull final VTriangle triangle) {
double alpha = 30; // lowest angle in degree
double alpha = 30; // lowest angle3D in degree
double radAlpha = Math.toRadians(alpha);
return GeometryUtils.angle(triangle.p1, triangle.p2, triangle.p3) < radAlpha
......
......@@ -18,6 +18,8 @@ import org.vadere.meshing.mesh.triangulation.improver.eikmesh.impl.AEikMesh;
import org.vadere.meshing.mesh.triangulation.improver.eikmesh.impl.PEikMesh;
import org.vadere.meshing.mesh.triangulation.triangulator.impl.PContrainedDelaunayTriangulator;
import org.vadere.meshing.utils.color.Colors;
import org.vadere.meshing.utils.io.IOUtils;
import org.vadere.meshing.utils.io.poly.MeshPolyWriter;
import org.vadere.meshing.utils.io.poly.PSLGGenerator;
import org.vadere.meshing.utils.io.tex.TexGraphGenerator;
import org.vadere.util.geometry.GeometryUtils;
......@@ -48,7 +50,7 @@ import java.util.stream.Collectors;
public class MeshQuantityPrinting {
public static void main(String... args) throws InterruptedException, IOException {
spaceFillingCurve();
spaceFillingCurve2();
//uniformMeshDiscFunction(0.10);
//uniformMeshDiscFunctionDistMesh(0.05);
//distMeshFail(0.05);
......@@ -72,7 +74,7 @@ public class MeshQuantityPrinting {
IDistanceFunction d = IDistanceFunction.substract(drect3, p -> disc3.distance(p));
// define the EikMesh-Improver
IEdgeLengthFunction h = p -> h0 + 0.2 * Math.abs(d.apply(p));
IEdgeLengthFunction h = p -> h0 + 0.5 * Math.abs(d.apply(p));
List<VShape> constrains = new ArrayList<>();
constrains.add(bound);
......@@ -85,10 +87,14 @@ public class MeshQuantityPrinting {
);
//HSBtoRGB
int partitions = 3;
int numberOfFaces = 1924;
Function<AFace, Color> faceColorFunction = f -> {
int id = ((AFace)f).getId();
//ColorHelper colorHelper = new ColorHelper(7400);
return new Color(Color.HSBtoRGB(id / 2864.0f, 0.7f, 1.0f));
int fac = numberOfFaces / partitions;
float part = id / numberOfFaces;
return new Color(Color.HSBtoRGB((id / fac) / ((float)partitions), 0.7f, 1.0f));
//return colorHelper.numberToColor(id);
};
......@@ -96,17 +102,81 @@ public class MeshQuantityPrinting {
MeshPanel<AVertex, AHalfEdge, AFace> meshPanel = new MeshPanel<>(meshRenderer, 500, 500);
meshPanel.display();
while (!meshImprover.isInitialized()) {
while (!meshImprover.isFinished()) {
Thread.sleep(10);
meshImprover.improve();
meshPanel.repaint();
System.out.println(meshImprover.getMesh().getFaces().stream().mapToInt(f -> f.getId()).max().getAsInt());
}
BufferedWriter meshWriter = getWriter("spaceFillingCurve_mesh.tex", new File("/Users/bzoennchen/Development/workspaces/hmRepo/PersZoennchen/PhD/trash/generated/eikmesh/"));
BufferedWriter meshWriter = IOUtils.getWriter("spaceFillingCurve_partition_mesh.tex", new File("/Users/bzoennchen/Development/workspaces/hmRepo/PersZoennchen/PhD/trash/generated/eikmesh/"));
meshWriter.write(TexGraphGenerator.toTikz(meshImprover.getMesh(), faceColorFunction, e -> Color.BLACK, v -> Color.BLACK, 1.0f, true));
meshWriter.close();
}
private static void spaceFillingCurve2() throws InterruptedException, IOException {
String fileName = "/poly/kaiserslautern.poly";
final InputStream inputStream = ElementSizeFunction.class.getResourceAsStream("/poly/bridge.poly");
PSLG pslg = PSLGGenerator.toPSLG(inputStream);
IDistanceFunction d = IDistanceFunction.create(pslg.getSegmentBound(), pslg.getHoles());
double h0 = 0.5;
// define the EikMesh-Improver
IEdgeLengthFunction h = p -> h0 + 0.4 * Math.abs(d.apply(p));
List<VShape> constrains = new ArrayList<>();
constrains.add(pslg.getSegmentBound());
constrains.addAll(pslg.getHoles());
AEikMesh meshImprover = new AEikMesh(
d,
h,
h0,
pslg.getBoundingBox(),
constrains
);
//HSBtoRGB
int partitions = 3;
int numberOfFaces = 8376;
Function<AFace, Color> faceColorFunction = f -> {
int id = ((AFace)f).getId();
//ColorHelper colorHelper = new ColorHelper(7400);
int fac = numberOfFaces / partitions;
float part = id / numberOfFaces;
//return new Color(Color.HSBtoRGB((id / fac) / ((float)partitions), 0.7f, 1.0f));
return new Color(Color.HSBtoRGB(((float)id) / numberOfFaces, 0.7f, 1.0f));
//return colorHelper.numberToColor(id);
};
Function<AVertex, Color> vertexColorFunction = v -> {
if(meshImprover.isFixPoint(v)) {
return Colors.RED;
} else if(meshImprover.isSlidePoint(v)) {
return Colors.BLUE;