Commit 085d931a authored by Benedikt Zoennchen's avatar Benedikt Zoennchen
Browse files

construction of a new half-edge datastructure to solve the point location problem

parent 5698b1d2
......@@ -4,6 +4,7 @@ import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.ImmutableTriple;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.tuple.Triple;
import org.vadere.util.geometry.LinkedCellsGrid;
import org.vadere.util.geometry.shapes.VCircle;
import org.vadere.util.geometry.shapes.VLine;
import org.vadere.util.geometry.shapes.VPoint;
......@@ -41,7 +42,7 @@ public class BowyerWatson<P extends VPoint> {
P max = points.parallelStream().reduce(pointConstructor.apply(Double.MIN_VALUE, Double.MIN_VALUE), (a, b) -> pointConstructor.apply(Math.max(a.getX(), b.getX()), Math.max(a.getY(), b.getY())));
P min = points.parallelStream().reduce(pointConstructor.apply(Double.MIN_VALUE, Double.MIN_VALUE), (a, b) -> pointConstructor.apply(Math.min(a.getX(), b.getX()), Math.min(a.getY(), b.getY())));
VRectangle bound = new VRectangle(min.getX(), min.getY(), max.getX()-min.getX(), max.getY()- min.getY());
init(bound);
init(bound);
points.stream().forEach(point -> handle(point));
cleanUp();
}
......@@ -80,6 +81,7 @@ public class BowyerWatson<P extends VPoint> {
private void handle(final P point) {
HashSet<Line> edges = new HashSet<>();
// This is way to expensive O(n) instead of O(log(n))
Map<Boolean, List<Triple<P, P, P>>> partition = triangles.parallelStream().collect(Collectors.partitioningBy(t -> pointsToTriangle(t).isInCircumscribedCycle(point)));
List<Triple<P, P, P>> badTriangles = partition.get(true);
......@@ -171,7 +173,7 @@ public class BowyerWatson<P extends VPoint> {
points.add(new VPoint(80,70));*/
Random r = new Random();
for(int i=0; i<10000; i++) {
for(int i=0; i<100; i++) {
VPoint point = new VPoint(width*r.nextDouble(), height*r.nextDouble());
points.add(point);
}
......
package org.vadere.util.delaunay;
import org.jetbrains.annotations.NotNull;
import org.vadere.util.geometry.shapes.VPoint;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Face implements Iterable<HalfEdge> {
/**
* one of the half-edges bordering this face.
*/
private HalfEdge edge;
public Face(final @NotNull HalfEdge edge) {
this.edge = edge;
}
public double getArea() {
List<VPoint> pointList = getPoints();
double result = 0;
for (int i = 0; i < pointList.size() - 1; i++) {
result += (pointList.get(i).y + pointList.get(i + 1).y)
* (pointList.get(i).x - pointList.get(i + 1).x);
}
return Math.abs(result) / 2.0;
}
public List<VPoint> getPoints() {
List<VPoint> list = new ArrayList<>();
for(HalfEdge edge : this) {
list.add(edge.getEnd());
}
return list;
}
@Override
public Iterator<HalfEdge> iterator() {
return new HalfEdgeIterator();
}
private class HalfEdgeIterator implements Iterator<HalfEdge> {
private HalfEdge currentHalfEdge;
private boolean started = false;
private HalfEdgeIterator(){
this.currentHalfEdge = edge;
}
@Override
public boolean hasNext() {
return currentHalfEdge != null && (!started || !currentHalfEdge.equals(edge));
}
@Override
public HalfEdge next() {
started = true;
HalfEdge result = currentHalfEdge;
currentHalfEdge = currentHalfEdge.getNext();
return result;
}
}
}
package org.vadere.util.delaunay;
import org.jetbrains.annotations.NotNull;
import org.vadere.util.geometry.shapes.VPoint;
/**
* Created by bzoennchen on 13.11.16.
*/
public class HalfEdge {
/**
* point at the end of the half edge.
*/
private VPoint end;
/**
* next half-edge around the face.
*/
private HalfEdge next;
/**
* previous half-edge around the face.
*/
private HalfEdge previous;
/**
* oppositely oriented adjacnet half-edge. If the face is a the boundary
* there is no twin.
*/
private HalfEdge twin;
/**
* the face the half-edge borders.
*/
private Face face;
public HalfEdge (final VPoint end, final Face face) {
this.end = end;
this.face = face;
}
public VPoint getEnd() {
return end;
}
public boolean hasNext() {
return next != null;
}
public HalfEdge getNext() {
return next;
}
public HalfEdge getPrevious() {
return previous;
}
public HalfEdge getTwin() {
return twin;
}
public void setTwin(final @NotNull HalfEdge twin) {
this.twin = twin;
if(twin.getTwin() != this) {
twin.setTwin(this);
}
}
public void setPrevious(final @NotNull HalfEdge previous) {
this.previous = previous;
if(previous.getNext() != this) {
previous.setNext(this);
}
}
public void setNext(final @NotNull HalfEdge next) {
this.next = next;
if(next.getPrevious() != this) {
next.setPrevious(this);
}
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
HalfEdge halfEdge = (HalfEdge) o;
if (!end.equals(halfEdge.end)) return false;
if (next != null ? !next.equals(halfEdge.next) : halfEdge.next != null) return false;
if (previous != null ? !previous.equals(halfEdge.previous) : halfEdge.previous != null)
return false;
if (twin != null ? !twin.equals(halfEdge.twin) : halfEdge.twin != null) return false;
return face.equals(halfEdge.face);
}
@Override
public int hashCode() {
int result = end.hashCode();
result = 31 * result + (next != null ? next.hashCode() : 0);
result = 31 * result + (previous != null ? previous.hashCode() : 0);
result = 31 * result + (twin != null ? twin.hashCode() : 0);
result = 31 * result + face.hashCode();
return result;
}
}
......@@ -10,12 +10,11 @@ import org.vadere.util.geometry.shapes.VPoint;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertEquals;
public class TestFace {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment