Commit 8d9e9bef by Benedikt Zoennchen

much faster implementation of the BowyerWatson algorithm and a splitting...

`much faster implementation of the BowyerWatson algorithm and a splitting algorithm for obscuse triangles`
parent a2a75c7c
 package org.vadere.util.delaunay; import org.apache.commons.lang3.tuple.ImmutableTriple; import org.apache.commons.lang3.tuple.Triple; import org.vadere.util.geometry.shapes.VCircle; import org.vadere.util.geometry.shapes.VLine; import org.vadere.util.geometry.shapes.VPoint; import org.vadere.util.geometry.shapes.VRectangle; import org.vadere.util.geometry.shapes.VTriangle; import javax.swing.*; import java.awt.*; import java.util.*; import java.util.List; import java.util.function.BiFunction; import java.util.function.Predicate; import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.stream.Stream; /** * @author Benedikt Zoennchen * * This class is for computing the DelaunayTriangulation using the BowyerWatson-Algorithm. In average the algorithm should perfom in O(n log(n)) but * in degenerated cases its runtime can be in O(n^2) where n is the number of points. */ public class BowyerWatsonSlow

{ private List> triangles; private Collection

points; private List

initPoints; private final BiFunction pointConstructor; public BowyerWatsonSlow(final Collection

{ private Face

face; private Triple vertices; private T triangle; public DAGElement(final Face

face, final Triple vertices, final TriangleConstructor triangleConstructor) { this.face = face; this.vertices = vertices; this.triangle = triangleConstructor.create(vertices.getLeft(), vertices.getMiddle(), vertices.getRight()); } public Face

getFace() { return face; } public T getTriangle() { return triangle; } public Triple getVertices() { return vertices; } }

 package org.vadere.util.delaunay; import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; import org.vadere.util.data.DAG; import org.vadere.util.geometry.shapes.VPoint; import org.vadere.util.geometry.shapes.VPolygon; import java.awt.geom.Path2D; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; import java.util.stream.StreamSupport; public class Face implements Iterable { public class Face

implements Iterable> { /** * one of the half-edges bordering this face. */ private HalfEdge edge; private HalfEdge

edge; public Face(final HalfEdge edge) { public Face(final HalfEdge

edge) { this.edge = edge; } public Face() {} public void setEdge(@NotNull HalfEdge edge) { public static

Face

of(P p1, P p2, P p3) { Face superTriangle = new Face(); HalfEdge edge1 = new HalfEdge(p1, superTriangle); HalfEdge edge2 = new HalfEdge(p2, superTriangle); HalfEdge edge3 = new HalfEdge(p3, superTriangle); edge1.setNext(edge2); edge2.setNext(edge3); edge3.setNext(edge1); superTriangle.setEdge(edge1); return superTriangle; } public void setEdge(@NotNull HalfEdge

edge) { this.edge = edge; } public double getArea() { List pointList = getPoints(); List

pointList = getPoints(); double result = 0; for (int i = 0; i < pointList.size() - 1; i++) { ... ... @@ -39,15 +53,11 @@ public class Face implements Iterable { return Math.abs(result) / 2.0; } public List getPoints() { List list = new ArrayList<>(); for(HalfEdge edge : this) { list.add(edge.getEnd()); } return list; public List

getPoints() { return streamPoints().collect(Collectors.toList()); } public boolean contains(final VPoint point) { public boolean contains(final P point) { return toPolygon().contains(point); } ... ... @@ -61,17 +71,25 @@ public class Face implements Iterable { } @Override public Iterator iterator() { public Iterator> iterator() { return new HalfEdgeIterator(); } public Stream stream () { Iterable iterable = () -> iterator(); public Stream> stream () { Iterable> iterable = () -> iterator(); return StreamSupport.stream(iterable.spliterator(), false); } private class HalfEdgeIterator implements Iterator { private HalfEdge currentHalfEdge; public List> getEdges() { return stream().collect(Collectors.toList()); } public Stream

streamPoints() { return stream().map(edge -> edge.getEnd()); } private class HalfEdgeIterator implements Iterator> { private HalfEdge

currentHalfEdge; private boolean started = false; private HalfEdgeIterator(){ ... ... @@ -84,7 +102,7 @@ public class Face implements Iterable { } @Override public HalfEdge next() { public HalfEdge

next() { started = true; HalfEdge result = currentHalfEdge; currentHalfEdge = currentHalfEdge.getNext(); ... ...

{ P create(double x, double y); }

 ... ... @@ -12,48 +12,50 @@ import java.util.Comparator; import java.util.List; import java.util.Optional; import java.util.Set; import java.util.function.BiFunction; import java.util.function.Predicate; import java.util.stream.Collectors; public class PointLocation { public class PointLocation

{ private final Collection faces; private final List orderedPointList; private final List> halfeEdgesSegments; private final List> intersectionPointsInSegment; private final Collection> faces; private final List

orderedPointList; private final List>> halfeEdgesSegments; private final List> intersectionPointsInSegment; private final BiFunction pointConstructor; private Comparator pointComparatorX = (p1, p2) -> { private Comparator

pointComparatorX = (p1, p2) -> { double dx = p1.getX() - p2.getX(); if(dx < 0) return -1; else if(dx > 0) return 1; else return 0; }; private Comparator pointComparatorY = (p1, p2) -> { private Comparator

pointComparatorY = (p1, p2) -> { double dy = p1.getY() - p2.getY(); if(dy < 0) return -1; else if(dy > 0) return 1; else return 0; }; private class BetweenTwoPoints implements Predicate { private class BetweenTwoPoints implements Predicate> { private VPoint p1; private VPoint p2; private P p1; private P p2; private BetweenTwoPoints(final VPoint p1, final VPoint p2) { private BetweenTwoPoints(final P p1, final P p2) { this.p1 = p1; this.p2 = p2; } @Override public boolean test(final HalfEdge halfEdge) { public boolean test(final HalfEdge

halfEdge) { return (halfEdge.getEnd().getX() > p1.getX() && halfEdge.getPrevious().getEnd().getX() < p2.getX()) || (halfEdge.getEnd().getX() > p2.getX() && halfEdge.getPrevious().getEnd().getX() < p1.getX()); } } private class HalfEdgeComparator implements Comparator { private class HalfEdgeComparator implements Comparator> { private double x1; private double x2; ... ... @@ -64,7 +66,7 @@ public class PointLocation { } @Override public int compare(final HalfEdge edge1, final HalfEdge edge2) { public int compare(final HalfEdge

edge1, final HalfEdge

edge2) { VLine line1 = edge1.toLine(); VLine line2 = edge2.toLine(); double slope1 = line1.slope(); ... ... @@ -79,10 +81,12 @@ public class PointLocation { } } public PointLocation(final Collection faces) { public PointLocation(final Collection> faces, final BiFunction pointConstructor) { this.faces = faces; this.pointConstructor = pointConstructor; //TODO distinct is maybe slow here Set pointSet = faces.stream() Set

pointSet = faces.stream() .flatMap(face -> face.stream()).map(edge -> edge.getEnd()) .sorted(pointComparatorX).collect(Collectors.toSet()); ... ... @@ -91,11 +95,11 @@ public class PointLocation { intersectionPointsInSegment = new ArrayList<>(orderedPointList.size()-1); for(int i = 0; i < orderedPointList.size() - 1; i++) { VPoint p1 = orderedPointList.get(i); VPoint p2 = orderedPointList.get(i+1); List halfEdges = faces.stream().flatMap(face -> face.stream()).filter(new BetweenTwoPoints(p1, p2)) P p1 = orderedPointList.get(i); P p2 = orderedPointList.get(i+1); List> halfEdges = faces.stream().flatMap(face -> face.stream()).filter(new BetweenTwoPoints(p1, p2)) .sorted(new HalfEdgeComparator(p1.getX(), p2.getX())).collect(Collectors.toList()); List intersectionPoints = halfEdges.stream() List

intersectionPoints = halfEdges.stream() .map(hf -> hf.toLine()) .map(line -> intersectionWithX(p1.getX(), line)).collect(Collectors.toList());