Commit 17ae5bd4 authored by Benedikt Zoennchen's avatar Benedikt Zoennchen
Browse files

new initial meshing for sharp geometries.

parent 45cb5696
......@@ -5,7 +5,6 @@ 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.utils.tex.TexGraphGenerator;
import org.vadere.util.geometry.GeometryUtils;
import org.vadere.meshing.mesh.gen.PFace;
import org.vadere.meshing.mesh.gen.PHalfEdge;
......
......@@ -9,11 +9,14 @@ import org.vadere.meshing.mesh.impl.PMeshPanel;
import org.vadere.meshing.mesh.impl.PTriangulation;
import org.vadere.meshing.mesh.inter.IIncrementalTriangulation;
import org.vadere.meshing.mesh.triangulation.improver.eikmesh.EikMeshPoint;
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.PContrainedDelaunayTriangulator;
import org.vadere.meshing.mesh.triangulation.triangulator.impl.PDelaunayRefinement;
import org.vadere.meshing.mesh.triangulation.triangulator.impl.PDelaunayTriangulation;
import org.vadere.meshing.mesh.triangulation.triangulator.impl.PDirichletRefinement;
import org.vadere.meshing.mesh.triangulation.triangulator.impl.PRuppertsTriangulator;
import org.vadere.meshing.utils.tex.TexGraphGenerator;
import org.vadere.meshing.utils.io.tex.TexGraphGenerator;
import org.vadere.util.data.cellgrid.IPotentialPoint;
import org.vadere.util.data.cellgrid.PathFindingTag;
import org.vadere.util.geometry.GeometryUtils;
......@@ -23,13 +26,13 @@ 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.geometry.shapes.VTriangle;
import org.vadere.util.math.DistanceFunction;
import org.vadere.util.math.IDistanceFunction;
import org.vadere.util.math.InterpolationUtil;
import java.awt.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
......@@ -39,8 +42,50 @@ import java.util.stream.Collectors;
public class MeshExamples {
public static void main(String... args) {
ruppertsAndEikMesh();
public static void main(String... args) throws InterruptedException {
dirichletRefinment();
delaunayRefinment();
}
public static void faceTest() throws InterruptedException {
VPoint p1 = new VPoint(-1,0);
VPoint p2 = new VPoint(1, 0);
VPoint p3 = new VPoint(0, Math.sqrt(4-1));
VPoint p4 = new VPoint(4,4);
VPoint p5 = new VPoint(3,0);
List<VPoint> points = new ArrayList<>();
points.add(p1);
points.add(p2);
points.add(p3);
points.add(p4);
points.add(p5);
VTriangle triangle = new VTriangle(p1, p2, p3);
VPoint c = triangle.getCircumcenter();
VLine line = new VLine(p2, p3);
VPoint midpoint = line.midPoint();
VPoint toC = midpoint.subtract(c).norm().scalarMultiply(triangle.getCircumscribedRadius());
VPoint newPoint = midpoint.subtract(c).scalarMultiply(2).add(c).add(toC);
points.add(newPoint);
PDelaunayTriangulation<VPoint, Double, Double> delaunayTriangulation = new PDelaunayTriangulation<>(points, (x, y) -> new VPoint(x, y));
delaunayTriangulation.generate();
System.out.println(TexGraphGenerator.toTikz(delaunayTriangulation.getMesh()));
System.out.println(newPoint);
System.out.println(triangle.getCircumcenter());
VPoint ca = new VTriangle(p2,p3,p4).getCircumcenter();
System.out.println("ca" + ca);
System.out.println("cca" + new VTriangle(p2,p3,ca).getCircumcenter());
System.out.println("ccar" + new VTriangle(p2,p3,ca).getCircumscribedRadius());
System.out.println(midpoint);
System.out.println(new VTriangle(newPoint, p2, p3).getCircumcenter());
System.out.println(new VTriangle(newPoint, p2, p3).getCircumscribedRadius());
PMeshPanel<VPoint, Double, Double> panel = new PMeshPanel<>(delaunayTriangulation.getMesh(), 500, 500);
panel.display("A square mesh");
panel.repaint();
}
public static void square() {
......@@ -61,11 +106,6 @@ public class MeshExamples {
panel.repaint();
mesh.getNext(mesh.getEdge(mesh.getFace()));
for(VPoint point : mesh.getPointIt(mesh.getBorder())) {
}
mesh.streamPoints(mesh.getBorder()).parallel();
......@@ -257,6 +297,199 @@ public class MeshExamples {
}
}
public static void dirichletRefinment() throws InterruptedException {
// bounding polygon
VPolygon boundingBox = GeometryUtils.toPolygon(
new VCircle(new VPoint(15.0/2.0, 15.0/2.0), 20.0),
100);
// first polygon
VPolygon house = GeometryUtils.toPolygon(
new VPoint(1, 1),
new VPoint(1, 5),
new VPoint(3, 7),
new VPoint(5,5),
new VPoint(5,1));
IDistanceFunction distanceFunction = IDistanceFunction.create(boundingBox, house);
PDirichletRefinement<EikMeshPoint, Double, Double> delaunayRefinement = new PDirichletRefinement<>(
boundingBox,
Arrays.asList(house),
(x, y) -> new EikMeshPoint(x, y),
true,
0.5,
p -> 0.5 /*+ 0.5*Math.abs(distanceFunction.apply(p))*/);
Function<PFace<EikMeshPoint, Double, Double>, Color> colorFunction = f -> {
float quality = delaunayRefinement.getMesh().isBoundary(f) ? 1.0f : (float)GeometryUtils.qualityOf(delaunayRefinement.getMesh().toTriangle(f));
return new Color(quality, quality, quality);
};
PMeshPanel<EikMeshPoint, Double, Double> panel = new PMeshPanel<>(delaunayRefinement.getMesh(), 1000, 1000, colorFunction);
panel.display("Dirichlet Refinement");
delaunayRefinement.generate();
PEikMeshGen<EikMeshPoint, Double, Double> meshImprover = new PEikMeshGen<>(
distanceFunction,
p -> 1.0 /*+ 0.5*Math.abs(distanceFunction.apply(p))*/,
1.0,
delaunayRefinement.getTriangulation());
while (true) {
synchronized (meshImprover.getMesh()) {
meshImprover.improve();
}
panel.repaint();
Thread.sleep(10);
}
//panel.repaint();
}
public static void delaunayRefinment() throws InterruptedException {
// bounding polygon
VPolygon boundingBox = GeometryUtils.toPolygon(
new VCircle(new VPoint(15.0/2.0, 15.0/2.0), 20.0),
100);
// first polygon
VPolygon house = GeometryUtils.toPolygon(
new VPoint(1, 1),
new VPoint(1, 5),
new VPoint(3, 7),
new VPoint(5,5),
new VPoint(5,1));
PDelaunayRefinement<VPoint, Double, Double> delaunayRefinement = new PDelaunayRefinement<>(
boundingBox,
Arrays.asList(house),
(x, y) -> new VPoint(x, y),
true,
0.3,
p -> 1.0);
Function<PFace<VPoint, Double, Double>, Color> colorFunction = f -> {
float quality = delaunayRefinement.getMesh().isBoundary(f) ? 1.0f : (float)GeometryUtils.qualityOf(delaunayRefinement.getMesh().toTriangle(f));
return new Color(quality, quality, quality);
};
PMeshPanel<VPoint, Double, Double> panel = new PMeshPanel<>(delaunayRefinement.getMesh(), 1000, 1000, colorFunction);
panel.display("Delaunay Refinement");
delaunayRefinement.generate();
/*while (!delaunayRefinement.isFinished()) {
synchronized (delaunayRefinement.getMesh()) {
delaunayRefinement.refine();
}
panel.repaint();
Thread.sleep(10);
}*/
panel.repaint();
}
public static void ruppertsAndEikMeshShort() {
// bounding polygon
VPolygon boundingBox = GeometryUtils.toPolygon(
new VCircle(new VPoint(15.0/2.0, 15.0/2.0), 20.0),
100);
// first polygon
VPolygon house = GeometryUtils.toPolygon(
new VPoint(1, 1),
new VPoint(1, 5),
new VPoint(3, 7),
new VPoint(5,5),
new VPoint(5,1));
//IDistanceFunction distanceFunction = IDistanceFunction.create(boundingBox, Arrays.asList(house));
PEikMeshGen<EikMeshPoint, Double, Double> meshImprover = new PEikMeshGen<>(
p -> 1.0 /*+ Math.abs(approxDistance.apply(p))*0.3*/,
1.0,
boundingBox,
Arrays.asList(house), (x, y) -> new EikMeshPoint(x, y));
Function<PFace<EikMeshPoint, Double, Double>, Color> colorFunction = f -> {
float quality = meshImprover.getMesh().isBoundary(f) ? 1.0f : (float)GeometryUtils.qualityOf(meshImprover.getMesh().toTriangle(f));
return new Color(quality, quality, quality);
};
PMeshPanel<EikMeshPoint, Double, Double> panel = new PMeshPanel<>(meshImprover.getMesh(), 1000, 1000, colorFunction);
panel.display("EikMesh and Ruppert's Algorithm");
meshImprover.initialize();
while (true) {
meshImprover.improve();
panel.repaint();
/*try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}*/
}
}
public static void ruppertsAndEikMeshShort2() {
// bounding polygon
VPolygon boundingBox = GeometryUtils.toPolygon(
new VCircle(new VPoint(15.0/2.0, 15.0/2.0), 20.0),
100);
// first polygon
VPolygon house = GeometryUtils.toPolygon(
new VPoint(1, 1),
new VPoint(1, 5),
new VPoint(3, 7),
new VPoint(5,5),
new VPoint(5,1));
IDistanceFunction distanceFunction = GenEikMesh.createDistanceFunction(boundingBox, Arrays.asList(house));
PEikMeshGen<EikMeshPoint, Double, Double> meshImprover = new PEikMeshGen<>(
distanceFunction,
p -> 1.0 /*+ Math.abs(approxDistance.apply(p))*0.3*/,
2.0,
new VRectangle(boundingBox.getBounds2D()),
Arrays.asList(house), (x, y) -> new EikMeshPoint(x, y));
Function<PFace<EikMeshPoint, Double, Double>, Color> colorFunction = f -> {
float quality = meshImprover.getMesh().isBoundary(f) ? 1.0f : (float)GeometryUtils.qualityOf(meshImprover.getMesh().toTriangle(f));
return new Color(quality, quality, quality);
};
PMeshPanel<EikMeshPoint, Double, Double> panel = new PMeshPanel<>(meshImprover.getMesh(), 1000, 1000, colorFunction);
panel.display("EikMesh and Ruppert's Algorithm");
int counter = 0;
while (counter < 100) {
counter++;
meshImprover.improve();
panel.repaint();
/*try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}*/
}
meshImprover.finish();
panel.repaint();
}
public static void realWorldExample() {
}
private static boolean isLowOfQuality(@NotNull final VTriangle triangle) {
double alpha = 30; // lowest angle in degree
double radAlpha = Math.toRadians(alpha);
......
package org.vadere.meshing.mesh.gen;
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.ITriConnectivity;
import org.vadere.meshing.mesh.inter.IVertex;
import org.vadere.util.geometry.shapes.IPoint;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
public class BackgroundMesh<P extends IPoint, CE, CF, V extends IVertex<P>, E extends IHalfEdge<CE>, F extends IFace<CF>> {
private ITriConnectivity<P, CE, CF, V, E, F> triConnectivity;
private Map<Object, F> cache;
public BackgroundMesh(@NotNull final ITriConnectivity<P, CE, CF, V, E, F> triConnectivity) {
this.triConnectivity = triConnectivity;
this.cache = new HashMap<>();
}
public Optional<F> locate(@NotNull final Object obj, @NotNull final P point) {
return locate(obj, point.getX(), point.getY());
}
public Optional<F> locate(@NotNull final Object obj, final double x, final double y) {
if(cache.containsKey(obj)) {
F startFace = cache.get(obj);
return triConnectivity.locateFace(x, y, startFace);
}
else {
Optional<F> optionalF = triConnectivity.locateFace(x, y);
if(optionalF.isPresent()) {
cache.put(obj, optionalF.get());
}
return optionalF;
}
}
}
package org.vadere.meshing.mesh.gen;
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.IVertex;
import org.vadere.util.data.Node;
import org.vadere.util.geometry.shapes.IPoint;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class GenEar<
P extends IPoint,
CE,
CF,
V extends IVertex<P>,
E extends IHalfEdge<CE>,
F extends IFace<CF>> implements Comparable<GenEar<P, CE, CF, V, E, F>>{
private final List<E> edges;
private double power;
public GenEar(@NotNull final E e1, @NotNull final E e2, @NotNull final E e3, final double power) {
this.edges = new ArrayList<>(3);
this.edges.add(e1);
this.edges.add(e2);
this.edges.add(e3);
this.power = power;
}
public E getLast() {
return this.edges.get(2);
}
public E getFirst() {
return this.edges.get(0);
}
public void setLast(@NotNull final E e) {
this.edges.set(2, e);
}
public void setFirst(@NotNull final E e) {
this.edges.set(0, e);
}
private double getPower() {
return power;
}
public void setPower(final double power) {
this.power = power;
}
public List<E> getEdges() {
return edges;
}
@Override
public int compareTo(@NotNull final GenEar<P, CE, CF, V, E, F> o) {
return Double.compare(getPower(), o.getPower());
}
public static class EarNodeComparator<
P extends IPoint,
CE,
CF,
V extends IVertex<P>,
E extends IHalfEdge<CE>,
F extends IFace<CF>> implements Comparator<Node<GenEar<P, CE, CF, V, E, F>>> {
@Override
public int compare(@NotNull final Node<GenEar<P, CE, CF, V, E, F>> o1, @NotNull final Node<GenEar<P, CE, CF, V, E, F>> o2) {
return Double.compare(o1.getElement().getPower(), o2.getElement().getPower());
}
}
}
......@@ -9,6 +9,7 @@ import org.vadere.meshing.mesh.inter.IPointConstructor;
import org.vadere.meshing.mesh.inter.IPointLocator;
import org.vadere.meshing.mesh.inter.ITriConnectivity;
import org.vadere.meshing.mesh.inter.IIncrementalTriangulation;
import org.vadere.meshing.mesh.inter.ITriEventListener;
import org.vadere.meshing.mesh.inter.IVertex;
import org.vadere.meshing.mesh.iterators.FaceIterator;
import org.vadere.meshing.mesh.triangulation.BowyerWatsonSlow;
......@@ -71,6 +72,8 @@ public class IncrementalTriangulation<P extends IPoint, CE, CF, V extends IVerte
private List<V> virtualVertices;
private boolean useMeshForBound;
private IPointLocator.Type type;
private final List<ITriEventListener<P, CE, CF, V, E, F>> triEventListeners;
private static double BUFFER_PERCENTAGE = GeometryUtils.DOUBLE_EPS;
......@@ -110,6 +113,7 @@ public class IncrementalTriangulation<P extends IPoint, CE, CF, V extends IVerte
this.finalized = false;
this.initialized = false;
this.mesh = mesh;
this.triEventListeners = new ArrayList<>();
this.setPointLocator(type);
}
......@@ -137,6 +141,7 @@ public class IncrementalTriangulation<P extends IPoint, CE, CF, V extends IVerte
this.bound = bound;
this.finalized = false;
this.initialized = false;
this.triEventListeners = new ArrayList<>();
this.setPointLocator(type);
}
......@@ -197,6 +202,7 @@ public class IncrementalTriangulation<P extends IPoint, CE, CF, V extends IVerte
this.finalized = false;
this.virtualVertices = new ArrayList<>();
this.virtualVertices.addAll(mesh.getVertices());
this.triEventListeners = new ArrayList<>();
this.setPointLocator(type);
}
......@@ -374,11 +380,16 @@ public class IncrementalTriangulation<P extends IPoint, CE, CF, V extends IVerte
@Override
public E insert(@NotNull P point, @NotNull F face) {
return insert(getMesh().createVertex(point), face);
}
@Override
public E insert(@NotNull V vertex, @NotNull F face) {
if(!initialized) {
init();
}
E edge = mesh.closestEdge(face, point.getX(), point.getY());
E edge = mesh.closestEdge(face, vertex.getX(), vertex.getY());
P p1 = mesh.getPoint(mesh.getPrev(edge));
P p2 = mesh.getPoint(edge);
......@@ -388,26 +399,21 @@ public class IncrementalTriangulation<P extends IPoint, CE, CF, V extends IVerte
* 2) point lies on an edge of a face => split the edge
* 3) point lies in the interior of the face => split the face (this should be the main case)
*/
if(isClose(point.getX(), point.getY(), face, edgeCoincidenceTolerance)) {
log.info("ignore insertion point, since the point " + point + " already exists or it is too close to another point!");
return getCloseEdge(face, point.getX(), point.getY(), edgeCoincidenceTolerance).get();
if(isClose(vertex.getX(), vertex.getY(), face, edgeCoincidenceTolerance)) {
//log.info("ignore insertion point, since the point " + vertex + " already exists or it is too close to another point!");
return getCloseEdge(face, vertex.getX(), vertex.getY(), edgeCoincidenceTolerance).get();
}
if(GeometryUtils.isOnEdge(p1, p2, point, edgeCoincidenceTolerance)) {
if(GeometryUtils.isOnEdge(p1, p2, vertex, edgeCoincidenceTolerance)) {
//log.info("splitEdge()");
E newEdge = getAnyEdge(splitEdge(point, edge, true));
E newEdge = getAnyEdge(splitEdge(vertex, edge, true));
insertEvent(newEdge);
return newEdge;
}
else {
//log.info("splitTriangle()");
if(!contains(point.getX(), point.getY(), face)) {
Optional<F> f = locateFace(point);
f = locateFace(point);
}
assert contains(point.getX(), point.getY(), face);
assert contains(vertex.getX(), vertex.getY(), face);
E newEdge = splitTriangle(face, point, true);
E newEdge = splitTriangle(face, vertex, true);
insertEvent(newEdge);
return newEdge;
}
......@@ -539,6 +545,16 @@ public class IncrementalTriangulation<P extends IPoint, CE, CF, V extends IVerte
}
}
@Override
public void addTriEventListener(@NotNull ITriEventListener<P, CE, CF, V, E, F> triEventListener) {
triEventListeners.add(triEventListener);
}
@Override
public void removeTriEventListener(@NotNull ITriEventListener<P, CE, CF, V, E, F> triEventListener) {
triEventListeners.remove(triEventListener);
}
public boolean isDeletionOk(final F face) {
if(mesh.isDestroyed(face)) {
return false;
......@@ -812,21 +828,33 @@ public class IncrementalTriangulation<P extends IPoint, CE, CF, V extends IVerte
@Override
public void flipEdgeEvent(final F f1, final F f2) {
pointLocator.postFlipEdgeEvent(f1, f2);
for(ITriEventListener<P, CE, CF, V, E, F> triEventListener : triEventListeners) {
triEventListener.postFlipEdgeEvent(f1, f2);
}
}
@Override
public void splitTriangleEvent(final F original, final F f1, F f2, F f3) {
pointLocator.postSplitTriangleEvent(original, f1, f2, f3);
for(ITriEventListener<P, CE, CF, V, E, F> triEventListener : triEventListeners) {
triEventListener.postSplitTriangleEvent(original, f1, f2, f3);
}
}
@Override
public void splitEdgeEvent(F original, F f1, F f2) {
pointLocator.postSplitHalfEdgeEvent(original, f1, f2);
for(ITriEventListener<P, CE, CF, V, E, F> triEventListener : triEventListeners) {
triEventListener.postSplitHalfEdgeEvent(original, f1, f2);
}
}
@Override
public void insertEvent(@NotNull final E halfEdge) {
pointLocator.postInsertEvent(getMesh().getVertex(halfEdge));
for(ITriEventListener<P, CE, CF, V, E, F> triEventListener : triEventListeners) {
triEventListener.postInsertEvent(getMesh().getVertex(halfEdge));
}
}
@Override
......
......@@ -6,19 +6,12 @@ import org.vadere.meshing.mesh.inter.IHalfEdge;
import org.vadere.meshing.mesh.inter.IPointLocator;
import org.vadere.meshing.mesh.inter.IIncrementalTriangulation;
import org.vadere.meshing.mesh.inter.IVertex;
import org.vadere.meshing.utils.tex.TexGraphGenerator;