Commit d89bd0ef authored by Benedikt Zoennchen's avatar Benedikt Zoennchen
Browse files

before new data structure for triangles

parent 8d94d9df
......@@ -7,7 +7,7 @@ import org.vadere.util.geometry.shapes.VPoint;
import java.awt.geom.Line2D;
import java.util.Iterator;
public class LineIterator implements Iterator<IPoint> {
public class ConstantLineIterator implements Iterator<IPoint> {
private final Line2D.Double line;
private final double delta;
......@@ -23,7 +23,7 @@ public class LineIterator implements Iterator<IPoint> {
private int counter;
private int numberOfSegments;
public LineIterator(final Line2D.Double line, final double delta) {
public ConstantLineIterator(final Line2D.Double line, final double delta) {
this.line = line;
if(line.getX1() < line.getX2()) {
......
package org.vadere.util.geometry;
import org.vadere.util.geometry.shapes.IPoint;
import org.vadere.util.geometry.shapes.VLine;
import org.vadere.util.geometry.shapes.VShape;
import org.vadere.util.triangulation.IPointConstructor;
import java.awt.geom.PathIterator;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Function;
/**
* @author Benedikt Zoennchen
* @param <P>
*/
public class FixPointGenerator<P extends IPoint> {
public Collection<P> generate(final VShape shape, final Function<IPoint, Double> segmentLenFunc, final IPointConstructor<P> pointConstructor) {
Set<P> points = new HashSet<>();
PathIterator path = shape.getPathIterator(null);
double[] tempCoords = new double[6];
double[] coordinates = new double[6];
path.currentSegment(tempCoords);
while (!path.isDone()) {
path.next();
path.currentSegment(coordinates);
if (coordinates[0] == tempCoords[0] && coordinates[1] == tempCoords[1]) {
break;
}
SplitLineIterator<P> iterator = new SplitLineIterator<>(new VLine(coordinates[0], coordinates[1], tempCoords[0], tempCoords[1]), segmentLenFunc, pointConstructor);
while (iterator.hasNext()) {
points.add(iterator.next());
}
path.currentSegment(tempCoords);
}
return points;
}
}
package org.vadere.util.geometry;
import org.vadere.util.geometry.shapes.IPoint;
import org.vadere.util.geometry.shapes.VLine;
import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.triangulation.IPointConstructor;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.function.Function;
/**
* @author Benedikt Zoennchen
*/
public class SplitLineIterator<P extends IPoint> implements Iterator<P>{
private final Function<IPoint, Double> segmentLenFunc;
private final List<P> points;
private final IPointConstructor<P> pointConstructor;
private final Iterator<P> iterator;
public SplitLineIterator(final VLine line, final Function<IPoint, Double> segmentLenFunc, final IPointConstructor<P> pointConstructor) {
this.segmentLenFunc = segmentLenFunc;
this.pointConstructor = pointConstructor;
this.points = new ArrayList<>();
this.points.add(pointConstructor.create(line.getX1(), line.getY1()));
this.points.add(pointConstructor.create(line.getX2(), line.getY2()));
splitLine(line);
iterator = points.iterator();
}
public void splitLine(final VLine line) {
VPoint midPoint = line.midPoint();
if(segmentLenFunc.apply(midPoint) < line.length()) {
points.add(pointConstructor.create(midPoint.getX(), midPoint.getY()));
VPoint start = new VPoint(line.getX1(), line.getY1());
VPoint end = new VPoint(line.getX2(), line.getY2());
splitLine(new VLine(start, midPoint));
splitLine(new VLine(midPoint, end));
}
}
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public P next() {
return iterator.next();
}
}
package org.vadere.util.triangulation;
package org.vadere.util.geometry.data;
import org.apache.commons.lang3.tuple.Triple;
import org.vadere.util.geometry.data.Face;
......
......@@ -102,6 +102,10 @@ public class Face<P extends IPoint> implements Iterable<HalfEdge<P>> {
destroyed = true;
}
public void toBorder() {
border = true;
}
/**
* Sets one of the half-edges bordering this face.
*
......@@ -211,7 +215,7 @@ public class Face<P extends IPoint> implements Iterable<HalfEdge<P>> {
@Override
public boolean hasNext() {
return currentHalfEdge != null && (!started || !currentHalfEdge.equals(edge));
return !started || !currentHalfEdge.equals(edge);
}
@Override
......
package org.vadere.util.triangulation;
package org.vadere.util.geometry.data;
import org.vadere.util.geometry.data.Face;
import org.vadere.util.geometry.data.HalfEdge;
......@@ -51,7 +51,7 @@ public class FaceIterator<P extends IPoint> implements Iterator<Face<P>> {
for(HalfEdge<P> he : nextFace) {
Face<P> twinFace = he.getTwin().getFace();
if(twinFace.isBorder() || twinFace.isDestroyed() || !facePredicate.test(twinFace)) {
if(twinFace.isBorder() || twinFace.isDestroyed() || !facePredicate.test(twinFace)) {
visitedFaces.add(twinFace);
}
......
......@@ -44,7 +44,7 @@ public class HalfEdge<P extends IPoint> implements Iterable<HalfEdge<P>> {
this.face = face;
}
public Face getFace() {
public Face<P> getFace() {
return face;
}
......@@ -120,7 +120,7 @@ public class HalfEdge<P extends IPoint> implements Iterable<HalfEdge<P>> {
}
public VLine toLine() {
return new VLine((VPoint) this.getPrevious().getEnd(), (VPoint) this.getEnd());
return new VLine(new VPoint(this.getPrevious().getEnd()), new VPoint(this.getEnd()));
}
public Iterator<HalfEdge<P>> incidentVertexIterator() {
......
......@@ -9,6 +9,7 @@ import org.vadere.util.geometry.GeometryUtils;
public class VLine extends Line2D.Double {
private String identifier;
// TODO: delete these points
private VPoint p1;
private VPoint p2;
......@@ -22,7 +23,7 @@ public class VLine extends Line2D.Double {
}
public VLine(double x1, double y1, double x2, double y2) {
super(x1, y1, x2, y2);
this(new VPoint(x1, y1), new VPoint(x2, y2));
}
public double ptSegDist(IPoint point) {
......@@ -37,6 +38,10 @@ public class VLine extends Line2D.Double {
return GeometryUtils.closestToSegment(this, point).distance(point);
}
public VPoint midPoint() {
return p1.add(p2).scalarMultiply(0.5);
}
@Override
public int hashCode() {
// this has to be symmetric
......
......@@ -36,7 +36,6 @@ public class VPoint implements Cloneable, IPoint {
this.identifier = identifier;
}
public VPoint(Point2D.Double copy) {
this.x = copy.x;
this.y = copy.y;
......
......@@ -126,12 +126,12 @@ public class VRectangle extends Rectangle2D.Double implements VShape {
@Override
public boolean intersect(final VShape shape) {
if(shape instanceof VPolygon) {
return toPolygon().intersects((VPolygon) shape);
}
else if(shape instanceof VRectangle){
if(shape instanceof VRectangle){
return intersects(((VRectangle)shape));
}
else if(shape instanceof VPolygon) {
return shape.intersect(this);
}
else {
throw new UnsupportedOperationException("not yet implemented");
}
......
......@@ -3,7 +3,7 @@ package org.vadere.util.potential.calculators;
import org.vadere.util.geometry.GeometryUtils;
import org.vadere.util.geometry.data.Face;
import org.vadere.util.geometry.data.HalfEdge;
import org.vadere.util.geometry.data.Triangulation;
import org.vadere.util.triangulation.ITriangulation;
import org.vadere.util.geometry.shapes.IPoint;
import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.math.InterpolationUtil;
......@@ -20,7 +20,7 @@ import java.util.PriorityQueue;
public class EikonalSolverFMMAcuteTriangulation implements EikonalSolver {
private ITimeCostFunction timeCostFunction;
private Triangulation<? extends PotentialPoint> triangulation;
private ITriangulation<? extends PotentialPoint> triangulation;
private boolean calculationFinished;
private PriorityQueue<FFMHalfEdge> narrowBand;
private final Collection<IPoint> targetPoints;
......@@ -38,7 +38,7 @@ public class EikonalSolverFMMAcuteTriangulation implements EikonalSolver {
public EikonalSolverFMMAcuteTriangulation(final Collection<IPoint> targetPoints,
final ITimeCostFunction timeCostFunction,
final Triangulation<? extends PotentialPoint> triangulation) {
final ITriangulation<? extends PotentialPoint> triangulation) {
this.triangulation = triangulation;
this.calculationFinished = false;
this.timeCostFunction = timeCostFunction;
......
......@@ -3,10 +3,10 @@ package org.vadere.util.potential.calculators;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.vadere.util.geometry.GeometryUtils;
import org.vadere.util.geometry.LineIterator;
import org.vadere.util.geometry.ConstantLineIterator;
import org.vadere.util.geometry.data.Face;
import org.vadere.util.geometry.data.HalfEdge;
import org.vadere.util.geometry.data.Triangulation;
import org.vadere.util.triangulation.ITriangulation;
import org.vadere.util.geometry.shapes.IPoint;
import org.vadere.util.geometry.shapes.VCone;
import org.vadere.util.geometry.shapes.VLine;
......@@ -17,8 +17,8 @@ import org.vadere.util.math.InterpolationUtil;
import org.vadere.util.math.MathUtil;
import org.vadere.util.potential.PathFindingTag;
import org.vadere.util.potential.timecost.ITimeCostFunction;
import org.vadere.util.triangulation.FaceIterator;
import org.vadere.util.triangulation.PointConstructor;
import org.vadere.util.geometry.data.FaceIterator;
import org.vadere.util.triangulation.IPointConstructor;
import java.util.ArrayList;
import java.util.Arrays;
......@@ -38,11 +38,11 @@ public class EikonalSolverFMMTriangulation<P extends PotentialPoint> implements
private static Logger logger = LogManager.getLogger(EikonalSolverFMMTriangulation.class);
private ITimeCostFunction timeCostFunction;
private Triangulation<P> triangulation;
private ITriangulation<P> triangulation;
private boolean calculationFinished;
private PriorityQueue<FFMHalfEdge> narrowBand;
private final Collection<VRectangle> targetAreas;
private PointConstructor<P> pointConstructor;
private IPointConstructor<P> pointConstructor;
private Comparator<FFMHalfEdge> pointComparator = (he1, he2) -> {
if (he1.halfEdge.getEnd().getPotential() < he2.halfEdge.getEnd().getPotential()) {
......@@ -57,8 +57,8 @@ public class EikonalSolverFMMTriangulation<P extends PotentialPoint> implements
public EikonalSolverFMMTriangulation(final Collection<VRectangle> targetAreas,
final ITimeCostFunction timeCostFunction,
final Triangulation<P> triangulation,
final PointConstructor<P> pointConstructor
final ITriangulation<P> triangulation,
final IPointConstructor<P> pointConstructor
) {
this.triangulation = triangulation;
this.calculationFinished = false;
......@@ -70,7 +70,7 @@ public class EikonalSolverFMMTriangulation<P extends PotentialPoint> implements
public EikonalSolverFMMTriangulation(final Collection<IPoint> targetPoints,
final ITimeCostFunction timeCostFunction,
final Triangulation<P> triangulation
final ITriangulation<P> triangulation
) {
this.triangulation = triangulation;
this.calculationFinished = false;
......@@ -103,14 +103,14 @@ public class EikonalSolverFMMTriangulation<P extends PotentialPoint> implements
VPoint bottomLeft = new VPoint(rectangle.getX(), rectangle.getMaxY());
VPoint bottomRight = new VPoint(rectangle.getMaxX(), rectangle.getMaxY());
VPoint topRight = new VPoint(rectangle.getMaxX(), rectangle.getY());
LineIterator lineIterator1 = new LineIterator(new VLine(topLeft, topRight), 1.0);
LineIterator lineIterator2 = new LineIterator(new VLine(topLeft, bottomLeft), 1.0);
LineIterator lineIterator3 = new LineIterator(new VLine(bottomLeft, bottomRight), 1.0);
LineIterator lineIterator4 = new LineIterator(new VLine(topRight, bottomRight), 1.0);
ConstantLineIterator lineIterator1 = new ConstantLineIterator(new VLine(topLeft, topRight), 1.0);
ConstantLineIterator lineIterator2 = new ConstantLineIterator(new VLine(topLeft, bottomLeft), 1.0);
ConstantLineIterator lineIterator3 = new ConstantLineIterator(new VLine(bottomLeft, bottomRight), 1.0);
ConstantLineIterator lineIterator4 = new ConstantLineIterator(new VLine(topRight, bottomRight), 1.0);
List<LineIterator> lineIterators = Arrays.asList(lineIterator1, lineIterator2, lineIterator3, lineIterator4);
List<ConstantLineIterator> lineIterators = Arrays.asList(lineIterator1, lineIterator2, lineIterator3, lineIterator4);
for(LineIterator lineIterator : lineIterators) {
for(ConstantLineIterator lineIterator : lineIterators) {
while (lineIterator.hasNext()) {
IPoint next = lineIterator.next();
P potentialPoint = pointConstructor.create(next.getX(), next.getY());
......
......@@ -25,6 +25,7 @@ import javax.swing.*;
* 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.
*/
@Deprecated
public class BowyerWatson3 {
private List<VTriangle> triangles;
private Collection<VPoint> points;
......
......@@ -25,6 +25,7 @@ import java.util.stream.Stream;
* 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.
*/
@Deprecated
public class BowyerWatsonSlow<P extends IPoint> {
private List<Triple<P, P, P>> triangles;
private Collection<P> points;
......
......@@ -3,6 +3,6 @@ package org.vadere.util.triangulation;
import org.vadere.util.geometry.shapes.IPoint;
@FunctionalInterface
public interface PointConstructor<P extends IPoint> {
public interface IPointConstructor<P extends IPoint> {
P create(double x, double y);
}
......@@ -4,6 +4,6 @@ import org.vadere.util.geometry.shapes.IPoint;
import org.vadere.util.geometry.shapes.VTriangle;
@FunctionalInterface
public interface TriangleConstructor<P extends IPoint> {
public interface ITriangleConstructor<P extends IPoint> {
VTriangle create(P p1, P p2, P p3);
}
package org.vadere.util.geometry.data;
package org.vadere.util.triangulation;
import org.vadere.util.geometry.data.Face;
import org.vadere.util.geometry.data.HalfEdge;
import org.vadere.util.geometry.shapes.IPoint;
import java.util.Set;
import java.util.stream.Stream;
public interface Triangulation<P extends IPoint> extends Iterable<Face<P>> {
public interface ITriangulation<P extends IPoint> extends Iterable<Face<P>> {
void compute();
Face<P> locate(final double x, final double y);
Face<P> locate(final IPoint point);
......
......@@ -6,10 +6,11 @@ import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.jetbrains.annotations.NotNull;
import org.vadere.util.geometry.data.DAG;
import org.vadere.util.geometry.data.DAGElement;
import org.vadere.util.geometry.data.Face;
import org.vadere.util.geometry.data.FaceIterator;
import org.vadere.util.geometry.data.HalfEdge;
import org.vadere.util.geometry.GeometryUtils;
import org.vadere.util.geometry.data.Triangulation;
import org.vadere.util.geometry.shapes.IPoint;
import org.vadere.util.geometry.shapes.VCircle;
import org.vadere.util.geometry.shapes.VLine;
......@@ -19,6 +20,7 @@ import org.vadere.util.geometry.shapes.VTriangle;
import java.awt.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
......@@ -28,17 +30,18 @@ import java.util.List;
import java.util.Optional;
import java.util.Random;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import javax.swing.*;
public class DelaunayTriangulation<P extends IPoint> implements Triangulation<P> {
public class IncrementalTriangulation<P extends IPoint> implements ITriangulation<P> {
private Face<P> face;
private final Set<P> points;
private final PointConstructor<P> pointConstructor;
protected Set<P> points;
protected final IPointConstructor<P> pointConstructor;
// TODO: use symbolic for the super-triangle points instead of real points!
private P p0;
......@@ -47,19 +50,24 @@ public class DelaunayTriangulation<P extends IPoint> implements Triangulation<P>
private HalfEdge<P> he0;
private HalfEdge<P> he1;
private HalfEdge<P> he2;
private P p_max;
private P p_min;
private boolean finalized;
private DAG<DAGElement<P>> dag;
private final HashMap<Face<P>, DAG<DAGElement<P>>> map;
private double eps = 0.0000001;
private Face<P> superTriangle;
protected Face<P> superTriangle;
private Face<P> borderFace;
private static Logger log = LogManager.getLogger(DelaunayTriangulation.class);
private final Predicate<HalfEdge<P>> illegalPredicate;
private static Logger log = LogManager.getLogger(IncrementalTriangulation.class);
public DelaunayTriangulation(
public IncrementalTriangulation(
final Set<P> points,
final PointConstructor<P> pointConstructor) {
final IPointConstructor<P> pointConstructor,
final Predicate<HalfEdge<P>> illegalPredicate) {
this.points = points;
this.illegalPredicate = illegalPredicate;
this.pointConstructor = pointConstructor;
this.map = new HashMap<>();
P p_max = points.parallelStream().reduce(pointConstructor.create(Double.MIN_VALUE, Double.MIN_VALUE), (a, b) -> pointConstructor.create(Math.max(a.getX(), b.getX()), Math.max(a.getY(), b.getY())));
......@@ -67,20 +75,37 @@ public class DelaunayTriangulation<P extends IPoint> implements Triangulation<P>
init(p_max, p_min);
}
public DelaunayTriangulation(
public IncrementalTriangulation(
final Set<P> points,
final IPointConstructor<P> pointConstructor) {
this(points, pointConstructor, halfEdge -> isIllegalEdge(halfEdge));
}
public IncrementalTriangulation(
final double minX,
final double minY,
final double width,
final double height,
final PointConstructor<P> pointConstructor) {
this.points = new HashSet<P>();
final IPointConstructor<P> pointConstructor,
final Predicate<HalfEdge<P>> illegalPredicate) {
this.points = new HashSet<>();
this.pointConstructor = pointConstructor;
this.map = new HashMap<>();
P p_max = pointConstructor.create(minX + width, minY + height);
P p_min = pointConstructor.create(minX, minY);
this.illegalPredicate = illegalPredicate;
p_max = pointConstructor.create(minX + width, minY + height);
p_min = pointConstructor.create(minX, minY);
init(p_max, p_min);
}
public IncrementalTriangulation(
final double minX,
final double minY,
final double width,
final double height,
final IPointConstructor<P> pointConstructor) {
this(minX, minY, width, height, pointConstructor, halfEdge -> isIllegalEdge(halfEdge));
}
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());
......@@ -133,7 +158,7 @@ public class DelaunayTriangulation<P extends IPoint> implements Triangulation<P>
else if(leafs.size() == 2) {
Iterator<DAG<DAGElement<P>>> it = leafs.iterator();
//log.info("splitEdge");
return splitEdgeDB(point, findTwins(it.next().getElement().getFace(), it.next().getElement().getFace()));
return splitEdgeDB(point, findTwins(it.next().getElement().getFace(), it.next().getElement().getFace())).get(0);
}
else if(leafs.size() == 0) {
// problem due numerical calculation.
......@@ -176,6 +201,17 @@ public class DelaunayTriangulation<P extends IPoint> implements Triangulation<P>
}
}
public void clear() {
List<Face<P>> faces = IteratorUtils.toList(iterator());
for(Face<P> face : faces) {
for(HalfEdge<P> edge : face) {
edge.destroy();
}
face.destroy();
}
init(p_max, p_min);
}
public boolean isDeletionOk(final Face<P> face) {
if(face.isDestroyed()) {
return false;
......@@ -371,8 +407,8 @@ public class DelaunayTriangulation<P extends IPoint> implements Triangulation<P>
* @param p the split point
* @param halfEdge the half-edge which will be split
*/
public HalfEdge<P> splitEdge(@NotNull P p, @NotNull HalfEdge<P> halfEdge) {
public List<HalfEdge<P>> splitEdge(@NotNull P p, @NotNull HalfEdge<P> halfEdge) {
List<HalfEdge<P>> newEdges = new ArrayList<>(4);
/*
* Situation: h0 = halfEdge
* h1 -> h2 -> h0
......@@ -392,6 +428,9 @@ public class DelaunayTriangulation<P extends IPoint> implements Triangulation<P>
* f3
*/
//h0,(t0),t1
//e2,(o0,
HalfEdge<P> h0 = halfEdge;
HalfEdge<P> o0 = h0.getTwin();
......@@ -404,6 +443,8 @@ public class DelaunayTriangulation<P extends IPoint> implements Triangulation<P>
HalfEdge<P> t1 = new HalfEdge<>(p, h0.getFace());
e1.setTwin(t1);
o0.setEnd(p);
newEdges.add(t1);
newEdges.add(h0);
if(!h0.isBoundary()) {
Face<P> f1 = new Face<>();
......@@ -415,6 +456,7 @@ public class DelaunayTriangulation<P extends IPoint> implements Triangulation<P>
HalfEdge<P> e0 = new HalfEdge<>(v1, f1);
HalfEdge<P> t0 = new HalfEdge<>(p, f0);
e0.setTwin(t0);
newEdges.add(t0);
f0.setEdge(h0);
f1.setEdge(h2);
......@@ -451,6 +493,7 @@ public class DelaunayTriangulation<P extends IPoint> implements Triangulation<P>
HalfEdge<P> e2 = new HalfEdge<>(v3, o0.getFace());
HalfEdge<P> t2 = new HalfEdge<>(p, f2);
e2.setTwin(t2);
newEdges.add(t2);