Commit 38622449 by Benedikt Zoennchen

software architecture improvement for the triangulation

parent 8f2bf247
 ... ... @@ -534,6 +534,22 @@ public class GeometryUtils { return new VRectangle(pMin.getX(), pMin.getY(), pMax.getX() - pMin.getX(), pMax.getY() - pMin.getY()); } public static double sign(final double x1, final double y1, final double x2, final double y2, final double x3, final double y3) { return (x1 - x3) * (y2 - y3) - (x2 -x3) * (y1 - y3); } public static

VRectangle bound(final Collection

points) { if(points.isEmpty()) { throw new IllegalArgumentException("the point collection is empty."); } VPoint pMax = points.stream().map(p -> new VPoint(p.getX(), p.getY())).reduce((p1, p2) -> new VPoint(Math.max(p1.getX(), p2.getX()), Math.max(p1.getY(), p2.getY()))).get(); VPoint pMin = points.stream().map(p -> new VPoint(p.getX(), p.getY())).reduce((p1, p2) -> new VPoint(Math.min(p1.getX(), p2.getX()), Math.min(p1.getY(), p2.getY()))).get(); return new VRectangle(pMin.getX(), pMin.getY(), pMax.getX() - pMin.getX(), pMax.getY() - pMin.getY()); } /** * This method follows the construction from * https://proofwiki.org/wiki/Obtuse_Triangle_Divided_into_Acute_Triangles ... ...

 ... ... @@ -82,16 +82,6 @@ public class PMesh

implements IMesh, PFace

> return halfEdge.isBoundary(); } @Override public boolean isHole(@NotNull PFace

face) { return false; } @Override public boolean isHole(@NotNull PHalfEdge

halfEdge) { return false; } @Override public boolean isDestroyed(@NotNull PFace

face) { return face.isDestroyed(); ... ... @@ -152,6 +142,11 @@ public class PMesh

implements IMesh, PFace

> return vertices.size(); } @Override public int getNumberOfFaces() { return faces.size(); } @Override public PHalfEdge

createEdge(@NotNull P vertex) { PHalfEdge

edge = new PHalfEdge<>(vertex); ... ... @@ -190,6 +185,11 @@ public class PMesh

implements IMesh, PFace

> return vertex; } @Override public PFace

getBoundary() { return boundary; } @Override public void insert(P vertex) { vertices.add(vertex); ... ...

 ... ... @@ -33,7 +33,7 @@ public interface IPolyConnectivity

, F e return Optional.empty(); } default Optional locate(final IPoint point) { default Optional locate(final P point) { return locate(point.getX(), point.getY()); } ... ...

 ... ... @@ -26,7 +26,7 @@ public interface ITriConnectivity

, F ex default void flipEdgeEvent(F f1, F f2) {} default void insertEvent(P vertex) {}; default void insertEvent(E vertex) {}; boolean isIllegal(E edge); ... ... @@ -381,13 +381,18 @@ public interface ITriConnectivity

, F ex } @Override default Optional locate(final IPoint point) { default Optional locate(final P point) { return this.locate(point.getX(), point.getY()); } @Override default Optional locate(final double x, final double y) { return locate(x, y, getMesh().getFace()); if(getMesh().getNumberOfFaces() > 0) { return locate(x, y, getMesh().getFace()); } else { return Optional.empty(); } } /*default Optional

locateVertex(double x, double y, F startFace) { ... ...

 ... ... @@ -26,7 +26,7 @@ import java.util.Optional; */ public class BasePointLocator

, F extends IFace

> implements IPointLocator { private final ITriConnectivity triConnectivity; private ITriConnectivity triConnectivity; public BasePointLocator(final ITriConnectivity triConnectivity) { this.triConnectivity = triConnectivity; ... ... @@ -39,7 +39,7 @@ public class BasePointLocator

, F extend public void flipEdgeEvent(final F f1, final F f2) {} @Override public void insertEvent(final P vertex) {} public void insertEvent(E vertex) {} @Override public void deleteBoundaryFace(final F face) {} ... ...

 ... ... @@ -2,24 +2,50 @@ package org.vadere.util.geometry.mesh.triangulations; import org.vadere.util.geometry.mesh.inter.IFace; import org.vadere.util.geometry.mesh.inter.IHalfEdge; import org.vadere.util.geometry.mesh.inter.IMesh; import org.vadere.util.geometry.mesh.inter.IPointLocator; import org.vadere.util.geometry.mesh.inter.ITriConnectivity; import org.vadere.util.geometry.mesh.inter.ITriangulation; import org.vadere.util.geometry.shapes.IPoint; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Random; import java.util.function.Supplier; /** * Created by bzoennchen on 21.04.17. * @author Benedikt Zoennchen * * @param

* @param * @param */ public class DelaunayHierarchy

, F extends IFace

> implements IPointLocator { //private List> private List> hierarchySets; private ITriConnectivity triConnectivity; private List> hierarchyConnector; public DelaunayHierarchy(final ITriConnectivity triConnectivity) { this.triConnectivity = triConnectivity; private ITriConnectivity base; private Supplier> triangulationSupplier; private double alpha; private Random random; public DelaunayHierarchy(final ITriangulation base, final Supplier> triangulationSupplier) { this.hierarchySets = new ArrayList<>(); this.hierarchyConnector = new ArrayList<>(); this.random = new Random(); this.triangulationSupplier = triangulationSupplier; hierarchySets.add(base); hierarchyConnector.add(new HashMap<>()); } @Override ... ... @@ -29,8 +55,31 @@ public class DelaunayHierarchy

, F exten public void flipEdgeEvent(F f1, F f2) {} @Override public void insertEvent(P vertex) { public void insertEvent(final E halfEdge) { P vertex = base.getMesh().getVertex(halfEdge); E lastEdge = halfEdge; for(int i = 1; i < hierarchySets.size(); ++i) { if(random.nextDouble() < alpha) { if(hierarchySets.size() <= i) { hierarchySets.add(triangulationSupplier.get()); } E edge = hierarchySets.get(i).insert(vertex); if(hierarchyConnector.size() < i) { hierarchyConnector.add(new HashMap<>()); } hierarchyConnector.get(i-1).put(lastEdge, edge); lastEdge = edge; } else { break; } } } @Override ... ... @@ -39,12 +88,33 @@ public class DelaunayHierarchy

, F exten } @Override public Collection locatePoint(IPoint point, boolean insertion) { public Collection locatePoint(P point, boolean insertion) { return null; } @Override public Optional locate(IPoint point) { return null; public Optional locate(final P point) { Optional optStartFace = Optional.empty(); for(int i = hierarchySets.size()-1; i >= 0; --i) { if(!optStartFace.isPresent()) { optStartFace = hierarchySets.get(i).locate(point.getX(), point.getY()); } else { E edge = getNearestPoint(hierarchySets.get(i-1), optStartFace.get(), point); E newEdge = hierarchyConnector.get(i-1).get(edge); optStartFace = hierarchySets.get(i).locate(point.getX(), point.getY(), hierarchySets.get(i).getMesh().getFace(newEdge)); if(!optStartFace.isPresent()) { return Optional.empty(); } } } return optStartFace; } public E getNearestPoint(final ITriangulation triangulation, final F face, final P point) { IMesh mesh = triangulation.getMesh(); return triangulation.getMesh().streamEdges(face).reduce((p1, p2) -> mesh.getVertex(p1).distance(point) > mesh.getVertex(p2).distance(point) ? p2 : p1).get(); } }

 ... ... @@ -24,16 +24,27 @@ public class DelaunayTree

, F extends IF private final IMesh mesh; private double eps = 0.0000001; public DelaunayTree(final ITriangulation triangulation, final F superTriangle) { public DelaunayTree(final ITriangulation triangulation) { this.mesh = triangulation.getMesh(); this.map = new HashMap<>(); } private void checkRoot() { if(dag == null) { F face = mesh.getFace(); this.dag = new DAG<>(new DAGElement<>(superTriangle, mesh.toTriple(superTriangle))); this.map.put(superTriangle, dag); if(mesh.isBoundary(face)) { face = mesh.getTwinFace(mesh.getEdge(face)); } this.dag = new DAG<>(new DAGElement<>(face, mesh.toTriple(face))); this.map.put(face, dag); } } @Override public Collection locatePoint(final IPoint point, final boolean insertion) { public Collection locatePoint(final P point, final boolean insertion) { checkRoot(); Set>> leafs = new HashSet<>(); LinkedList>> nodesToVisit = new LinkedList<>(); ... ... @@ -60,7 +71,8 @@ public class DelaunayTree

, F extends IF } @Override public Optional locate(final IPoint point) { public Optional locate(final P point) { checkRoot(); Optional optFace = locatePoint(point, false).stream().findAny(); if(optFace.isPresent()) { return Optional.of(optFace.get()); ... ... @@ -72,6 +84,7 @@ public class DelaunayTree

, F extends IF @Override public void splitFaceEvent(F original, F[] faces) { checkRoot(); DAG> faceDag = map.remove(original); for(F face : faces) { List

points = mesh.getVertices(face); ... ... @@ -83,6 +96,7 @@ public class DelaunayTree

, F extends IF @Override public void flipEdgeEvent(final F f1, final F f2) { checkRoot(); DAG> f1Dag = map.remove(f1); DAG> f2Dag = map.remove(f2); List

points1 = mesh.getVertices(f1); ... ... @@ -102,10 +116,11 @@ public class DelaunayTree

, F extends IF } @Override public void insertEvent(P vertex) {} public void insertEvent(E vertex) {} @Override public void deleteBoundaryFace(F face) { checkRoot(); assert mesh.isBoundary(face); map.remove(face); } ... ...

 ... ... @@ -3,7 +3,7 @@ package org.vadere.util.geometry.mesh.triangulations; import org.apache.commons.collections.IteratorUtils; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.jetbrains.annotations.NotNull; import org.vadere.util.geometry.GeometryUtils; import org.vadere.util.geometry.mesh.impl.PFace; import org.vadere.util.geometry.mesh.iterators.FaceIterator; import org.vadere.util.geometry.mesh.inter.IFace; ... ... @@ -51,11 +51,13 @@ public class IncrementalTriangulation

, private E he0; private E he1; private E he2; private P p_max; private P p_min; private boolean finalized; private final VRectangle bound; private boolean finalized = false; private IMesh mesh; private IPointLocator pointLocator; private boolean initialized = false; // TODO this epsilon it hard coded!!! => replace it with a user choice private double epsilon = 0.0001; protected F superTriangle; ... ... @@ -64,48 +66,43 @@ public class IncrementalTriangulation

, private static Logger log = LogManager.getLogger(IncrementalTriangulation.class); public IncrementalTriangulation( final IMesh mesh, final Set

points, final Predicate illegalPredicate) { this.mesh = mesh; this.points = points; this.illegalPredicate = illegalPredicate; P p_max = points.parallelStream().reduce(mesh.createVertex(Double.MIN_VALUE, Double.MIN_VALUE), (a, b) -> mesh.createVertex(Math.max(a.getX(), b.getX()), Math.max(a.getY(), b.getY()))); P p_min = points.parallelStream().reduce(mesh.createVertex(Double.MIN_VALUE, Double.MIN_VALUE), (a, b) -> mesh.createVertex(Math.min(a.getX(), b.getX()), Math.min(a.getY(), b.getY()))); init(p_max, p_min); this.bound = GeometryUtils.bound(points); } public IncrementalTriangulation(final IMesh mesh, final Set

points) { this(mesh, points, halfEdge -> true); public IncrementalTriangulation(final Set

points) { this(points, halfEdge -> true); } public IncrementalTriangulation( final IMesh mesh, final double minX, final double minY, final double width, final double height, final VRectangle bound, final Predicate illegalPredicate) { this.mesh = mesh; this.points = new HashSet<>(); this.illegalPredicate = illegalPredicate; this.p_max = mesh.createVertex(minX + width, minY + height); this.p_min = mesh.createVertex(minX, minY); init(p_max, p_min); this.bound = bound; } public IncrementalTriangulation( final IMesh mesh, final double minX, final double minY, final double width, final double height) { this(mesh, minX, minY, width, height, halfEdge -> true); public IncrementalTriangulation(final VRectangle bound) { this(bound, halfEdge -> true); } public void setPointLocator(final IPointLocator pointLocator) { this.pointLocator = pointLocator; } public void setMesh(final IMesh mesh) { this.mesh = mesh; } private void init(final P p_max, final P p_min) { VRectangle bound = new VRectangle(p_min.getX(), p_min.getY(), p_max.getX()-p_min.getX(), p_max.getY()- p_min.getY()); public F getSuperTriangle() { return superTriangle; } @Override public void init() { double gap = 1.0; double max = Math.max(bound.getWidth(), bound.getHeight())*2; p0 = mesh.insertVertex(bound.getX() - max - gap, bound.getY() - gap); ... ... @@ -120,14 +117,15 @@ public class IncrementalTriangulation

, he1 = borderEdges.get(1); he2 = borderEdges.get(2); // this.pointLocator = IPointLocator.createDelaunayTree(this, superTriangle); this.pointLocator = IPointLocator.createBaseLocator(this); this.finalized = false; this.initialized = true; } @Override public void compute() { init(); // 1. insert points for(P p : points) { insert(p); ... ... @@ -155,14 +153,16 @@ public class IncrementalTriangulation

, F face = faces.iterator().next(); splitTriangle(face, point, true); insertedEdge = mesh.getEdge(point); insertEvent(insertedEdge); } // point lies on an edge of 2 triangles else if(faces.size() == 2) { Iterator it = faces.iterator(); log.info("splitEdge:" + point); E halfEdge = findTwins(it.next(), it.next()).get(); splitEdge(point, halfEdge, true); insertedEdge = mesh.getEdge(point); List newEdges = splitEdge(point, halfEdge, true); insertedEdge = newEdges.stream().filter(he -> getMesh().getVertex(he).equals(point)).findAny().get(); insertEvent(insertedEdge); } else if(faces.size() == 0) { log.warn("ignore insertion point, since the point " + point + " already exists or it is too close to another point!"); ... ... @@ -174,6 +174,18 @@ public class IncrementalTriangulation

, return insertedEdge; } @Override public void insert(final Set

points) { if(!initialized) { init(); } // 1. insert points for(P p : points) { insert(p); } } /** * Removes the super triangle from the mesh data structure. */ ... ... @@ -282,7 +294,7 @@ public class IncrementalTriangulation

, } @Override public Optional locate(final IPoint point) { public Optional locate(final P point) { return pointLocator.locate(point); } ... ... @@ -296,6 +308,11 @@ public class IncrementalTriangulation

, return stream(); } @Override public Stream streamTriangles() { return stream().map(f -> getMesh().toTriangle(f)); } @Override public void remove(P point) { throw new UnsupportedOperationException("not jet implemented."); ... ... @@ -341,9 +358,7 @@ public class IncrementalTriangulation

, P x = mesh.getVertex(t0); P y = mesh.getVertex(t1); P z = mesh.getVertex(t2); if(x.equals(y)) { System.out.print("error"); } VTriangle triangle = new VTriangle(new VPoint(x), new VPoint(y), new VPoint(z)); return triangle.isInCircumscribedCycle(p); } ... ... @@ -374,8 +389,8 @@ public class IncrementalTriangulation

, } @Override public void insertEvent(final P vertex) { pointLocator.insertEvent(vertex); public void insertEvent(final E halfEdge) { pointLocator.insertEvent(halfEdge); } @Override ... ... @@ -408,8 +423,13 @@ public class IncrementalTriangulation

, IPointConstructor pointConstructor = (x, y) -> new VPoint(x, y); long ms = System.currentTimeMillis(); IncrementalTriangulation, PFace> bw = new IncrementalTriangulation<>(new PMesh<>(pointConstructor), points); PMesh mesh = new PMesh<>(pointConstructor); IncrementalTriangulation, PFace> bw = new IncrementalTriangulation<>(points); bw.setMesh(mesh); bw.setPointLocator(new DelaunayTree<>(bw)); bw.compute(); Set edges = bw.getEdges(); edges.addAll(bw.getTriangles().stream().map(triangle -> new VLine(triangle.getIncenter(), triangle.p1)).collect(Collectors.toList())); System.out.println(System.currentTimeMillis() - ms); ... ... @@ -433,9 +453,13 @@ public class IncrementalTriangulation

, window2.getContentPane().add(new Lines(edges2, points, max)); window2.setVisible(true); UniformTriangulation, PFace> uniformTriangulation = new UniformTriangulation<>(new PMesh<>(pointConstructor),0, 0, width, height, 10.0); UniformTriangulation, PFace> uniformTriangulation = ITriangulation.createUnifirmTriangulation( IPointLocator.Type.DELAUNAY_TREE, new VRectangle(0, 0, width, height), 10.0, (x, y) -> new VPoint(x, y)); uniformTriangulation.compute(); uniformTriangulation.finalize(); Set edges3 = uniformTriangulation.getEdges(); JFrame window3 = new JFrame(); ... ... @@ -444,7 +468,12 @@ public class IncrementalTriangulation

, window3.getContentPane().add(new Lines(edges3, edges3.stream().flatMap(edge -> edge.streamPoints()).collect(Collectors.toSet()), max)); window3.setVisible(true); UniformRefinementTriangulation, PFace> uniformRefinement = new UniformRefinementTriangulation<>(new PMesh<>(pointConstructor), 0, 0, width, height, Arrays.asList(new VRectangle(200, 200, 100, 200)), p -> 10.0); UniformRefinementTriangulation uniformRefinement = new UniformRefinementTriangulation<>( new VRectangle(0, 0, width, height), Arrays.asList(new VRectangle(200, 200, 100, 200)), p -> 10.0, (x, y) -> new VPoint(x, y)); uniformRefinement.compute(); Set edges4 = uniformRefinement.getEdges(); ... ...