The expiration time for new job artifacts in CI/CD pipelines is now 30 days (GitLab default). Previously generated artifacts in already completed jobs will not be affected by the change. The latest artifacts for all jobs in the latest successful pipelines will be kept. More information: https://gitlab.lrz.de/help/user/admin_area/settings/continuous_integration.html#default-artifacts-expiration

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

update triangulation algorithm, implementation of the delaunay-hierarchy

parent a3b8d98c
......@@ -46,7 +46,7 @@ public interface IGaussianFilter {
void setInputValue(final int x, final int y, final double value);
/** refresh or update the values of the image that contains all values. */
/** refresh or update the values of the image that triangleContains all values. */
void filterImage();
void clear();
......
......@@ -30,7 +30,7 @@
//
//
///**
// * This class contains tests that test both Voronoi-Implementation (the JTS-Version and our own
// * This class triangleContains tests that test both Voronoi-Implementation (the JTS-Version and our own
// * version).
// */
//public class TestVoronoiDensityProcessors {
......
......@@ -16,7 +16,7 @@ package org.vadere.state.attributes;
* VPoint,...).
*
* The standard clone method makes a flat copy. This is enough if the subclass
* only contains immutable fields. If the subclass contains other Attributes
* only triangleContains immutable fields. If the subclass triangleContains other Attributes
* objects, it must implement a copy constructor and override {@link #clone()}
* to make a deep copy.
*
......
......@@ -243,9 +243,9 @@ public class Table implements Iterable<Row> {
}
/**
* Returns true if this table contains no elements.
* Returns true if this table triangleContains no elements.
*
* @return true if this table contains no elements
* @return true if this table triangleContains no elements
*/
public boolean isEmpty() {
return columns() == 0 || size() == 0 || getEntry(getColumnNames()[0], 0) == null;
......
......@@ -7,6 +7,8 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.vadere.util.geometry.shapes.IPoint;
import org.vadere.util.geometry.shapes.VCircle;
import org.vadere.util.geometry.shapes.VLine;
......@@ -23,6 +25,8 @@ public class GeometryUtils {
*/
public static final double DOUBLE_EPS = 1e-8;
public static final Logger log = LogManager.getLogger(GeometryUtils.class);
/**
* Interpolates between start and end with the given factor.
*/
......@@ -42,6 +46,23 @@ public class GeometryUtils {
return false;
}
public static VPoint getCircumcenter(final IPoint p1, final IPoint p2, final IPoint p3) {
double d = 2 * (p1.getX() * (p2.getY() - p3.getY()) + p2.getX() * (p3.getY() - p1.getY()) + p3.getX() * (p1.getY() - p2.getY()));
double x = ((p1.getX() * p1.getX() + p1.getY() * p1.getY()) * (p2.getY() - p3.getY())
+ (p2.getX() * p2.getX() + p2.getY() * p2.getY()) * (p3.getY() - p1.getY())
+ (p3.getX() * p3.getX() + p3.getY() * p3.getY()) * (p1.getY() - p2.getY())) / d;
double y = ((p1.getX() * p1.getX() + p1.getY() * p1.getY()) * (p3.getX() - p2.getX())
+ (p2.getX() * p2.getX() + p2.getY() * p2.getY()) * (p1.getX() - p3.getX())
+ (p3.getX() * p3.getX() + p3.getY() * p3.getY()) * (p2.getX() - p1.getX())) / d;
return new VPoint(x,y);
}
public static boolean isInCircumscribedCycle(final IPoint p1, final IPoint p2, final IPoint p3, final IPoint point) {
VPoint circumcenter = getCircumcenter(p1, p2, p3);
return circumcenter.distance(point) < circumcenter.distance(p1);
}
/**
* Computes the point on the line segment that is closest to the given point
* point. from:
......@@ -93,11 +114,6 @@ public class GeometryUtils {
/**
* Computes area (it maybe a negative area) of the parallelogram defined by p, q, r.
* Note: + This area is zero if p, q, r lie on one line.
* + The area is < 0 if the points p, q, r are aligned clockwise (order matters).
* This is equivalent to: r lies on the right side of the line defined by p, q.
* + The area is > 0 if the points p, q, r are aligned counter-clockwise (order matters).
* This is equivalent to: r lies on the left side of the line defined by p, q.
*
* @param pX x-coordinate of p
* @param pY y-coordinate of p
......@@ -108,7 +124,37 @@ public class GeometryUtils {
* @return
*/
public static double ccw(final double qX, final double qY, final double pX, final double pY, final double rX, final double rY) {
return (qX - pX) * (rY - pY) - (rX - pX) * (qY - pY);
return -((qX - pX) * (rY - pY) - (rX - pX) * (qY - pY));
}
/**
* Returns true if q is right of the oriented-line defined by (p1, p2).
* @param p1
* @param p2
* @param q
* @return true if q is right of the oriented-line defined by (p1, p2), false otherwise
*/
public static boolean isRightOf(final IPoint p1, final IPoint p2, final IPoint q) {
return isRightOf(p1, p2, q.getX(), q.getY());
}
/**
* Returns true if q is left of the oriented-line defined by (p1, p2).
* @param p1
* @param p2
* @param q
* @return true if q is right of the oriented-line defined by (p1, p2), false otherwise
*/
public static boolean isLeftOf(final IPoint p1, final IPoint p2, final IPoint q) {
return isLeftOf(p1, p2, q.getX(), q.getY());
}
public static boolean isRightOf(final IPoint p1, final IPoint p2, final double x, final double y) {
return isCW(p1.getX(), p1.getY(), p2.getX(), p2.getY(), x, y);
}
public static boolean isLeftOf(final IPoint p1, final IPoint p2, final double x, final double y) {
return isCCW(p1.getX(), p1.getY(), p2.getX(), p2.getY(), x, y);
}
/**
......@@ -134,7 +180,7 @@ public class GeometryUtils {
}
public static boolean isCCW(final IPoint p1, final IPoint p2, final IPoint p3) {
return ccw(p1, p2, p3) > 0;
return isCCW(p1.getX(), p1.getY(), p2.getX(), p2.getY(), p3.getX(), p3.getY());
}
public static boolean isCW(final double qX, final double qY, final double pX, final double pY, final double rX, final double rY) {
......@@ -201,9 +247,9 @@ public class GeometryUtils {
* @param p2 point of the triangle
* @param p3 point of the triangle
* @param r point which the triangle might contain.
* @return if the triangle (p1,p2,p3) contains the point r, otherwise false.
* @return true if the triangle (p1,p2,p3) contains the point r, otherwise false.
*/
public static boolean contains(final IPoint p1, final IPoint p2, final IPoint p3, final IPoint r) {
public static boolean triangleContains(final IPoint p1, final IPoint p2, final IPoint p3, final IPoint r) {
boolean b1, b2, b3;
double d1 = GeometryUtils.ccw(r, p1, p2);
double d2 = GeometryUtils.ccw(r, p2, p3);
......@@ -214,6 +260,54 @@ public class GeometryUtils {
return ((b1 == b2) && (b2 == b3));
}
/**
* Tests if the circle defined by three non-lin points (p1,p2,p3) contains the point r.
* The center of the circle is the circumcenter of the triangle and the radius is equalt to the
* distance between the circumcenter and any point of {p1, p2, p3}.
*
* @param a point of the triangle
* @param b point of the triangle
* @param c point of the triangle
* @param p point which the circle might contain.
* @return true, if the circle defined by three non-lin points (p1,p2,p3) contains the point r, otherwise false
*/
public static boolean isInsideCircle(final IPoint a, final IPoint b, final IPoint c, final IPoint p) {
return isInsideCircle(a, b, c, p.getX(), p.getY());
}
public static boolean isInsideCircle(final IPoint a, final IPoint b, final IPoint c, double x , double y) {
/*IPoint qp = q.subtract(p);
IPoint rp = r.subtract(p);
IPoint tp = t.subtract(p);
double a = qp.getX() * tp.getY() - qp.getY() * tp.getX();
double b = tp.getX() * (t.getX() - q.getX()) + tp.getY() * (t.getY() - q.getY());
double c = qp.getX() * rp.getY() - qp.getY() * rp.getX();
double d = rp.getX() * (r.getX() - q.getX()) + rp.getY() * (r.getY() - q.getY());
return a * d > c * b;*/
double adx = a.getX() - x;
double ady = a.getY() - y;
double bdx = b.getX() - x;
double bdy = b.getY() - y;
double cdx = c.getX() - x;
double cdy = c.getY() - y;
double abdet = adx * bdy - bdx * ady;
double bcdet = bdx * cdy - cdx * bdy;
double cadet = cdx * ady - adx * cdy;
double alift = adx * adx + ady * ady;
double blift = bdx * bdx + bdy * bdy;
double clift = cdx * cdx + cdy * cdy;
double disc = alift * bcdet + blift * cadet + clift * abdet;
//log.info("inCicle = " + disc);
return disc > 0;
}
/**
* Computes the cross product of two vectors and store it in the cross
* vector.
......@@ -282,6 +376,38 @@ public class GeometryUtils {
return Math.abs(result) / 2.0;
}
/**
* Computes the distance from the line-segment defined by (p1,p2) to the point p.
* @param p1 first point of the line-segment
* @param p2 second point of the line-segment
* @param p the point
* @return he distance from the line-segment defined by (p1,p2) to the point p.
*/
public static double distanceToLineSegment(final IPoint p1, final IPoint p2, final IPoint p) {
return distanceToLineSegment(p1, p2, p.getX(), p.getY());
}
public static double distanceToLineSegment(final IPoint p1, final IPoint p2, final double x, final double y) {
if (p1.getX() == p2.getX() && p1.getY() == p2.getY())
return p1.distance(x,y);
double len2 = (p2.getX() - p1.getX()) * (p2.getX() - p1.getX()) + (p2.getY() - p1.getY()) * (p2.getY() - p1.getY());
double r = ((x - p1.getX()) * (p2.getX() - p1.getX()) + (y - p1.getY()) * (p2.getY() - p1.getY())) / len2;
if (r <= 0.0)
return p1.distance(x,y);
if (r >= 1.0)
return p2.distance(x,y);
double s = ((p1.getY() - y) * (p2.getX() - p1.getX()) - (p1.getX() - x) * (p2.getY() - p1.getY())) / len2;
return Math.abs(s) * Math.sqrt(len2);
}
public static boolean isOnEdge(final IPoint p1, final IPoint p2, final IPoint p, double tolerance) {
return distanceToLineSegment(p1, p2, p) < tolerance;
}
/**
* Computes the intersection points of a line and a circle. The line is supposed to have infinity
* length and is defined by the two points of the VLine.
......
......@@ -85,7 +85,7 @@ public class LinkedCellsGrid<T> implements Iterable<T> {
private double[] cellSize = new double[2];
/**
* One cell in the grid. It contains a mapping from points to lists of
* One cell in the grid. It triangleContains a mapping from points to lists of
* objects. This means that one can store multiple objects in one cell.
*
*
......@@ -362,7 +362,7 @@ public class LinkedCellsGrid<T> implements Iterable<T> {
}
/**
* Tests whether the linked cells grid contains an object that equals(the
* Tests whether the linked cells grid triangleContains an object that equals(the
* given object). The complexity of this operation is O(N), N = number of
* objects in the grid.
*
......
......@@ -11,7 +11,7 @@ public class PHalfEdge<P extends IPoint> implements IHalfEdge<P> {
/**
* point at the end of the half edge.
*/
private P end;
private PVertex<P> end;
/**
* next half-edge around the face.
......@@ -35,12 +35,12 @@ public class PHalfEdge<P extends IPoint> implements IHalfEdge<P> {
private PFace<P> face;
PHalfEdge(@NotNull final P end, @NotNull final PFace<P> face) {
PHalfEdge(@NotNull final PVertex<P> end, @NotNull final PFace<P> face) {
this.end = end;
this.face = face;
}
PHalfEdge(@NotNull final P end) {
PHalfEdge(@NotNull final PVertex<P> end) {
this.end = end;
this.face = null;
}
......@@ -53,7 +53,7 @@ public class PHalfEdge<P extends IPoint> implements IHalfEdge<P> {
this.face = face;
}
P getEnd() {
PVertex<P> getEnd() {
return end;
}
......@@ -116,7 +116,7 @@ public class PHalfEdge<P extends IPoint> implements IHalfEdge<P> {
}
}
void setEnd(P end) {
void setEnd(PVertex<P> end) {
this.end = end;
}
......
......@@ -11,17 +11,18 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @author Benedikt Zoennchen
*/
public class PMesh<P extends IPoint> implements IMesh<P, PHalfEdge<P>, PFace<P>> {
public class PMesh<P extends IPoint> implements IMesh<P, PVertex<P>, PHalfEdge<P>, PFace<P>> {
private List<PFace<P>> faces;
private PFace<P> boundary;
private List<PHalfEdge<P>> edges;
private IPointConstructor<P> pointConstructor;
private Set<P> vertices;
private Set<PVertex<P>> vertices;
public PMesh(final IPointConstructor<P> pointConstructor) {
this.faces = new ArrayList<>();
......@@ -48,13 +49,13 @@ public class PMesh<P extends IPoint> implements IMesh<P, PHalfEdge<P>, PFace<P>>
}
@Override
public PFace<P> getFace(final PHalfEdge<P> halfEdge) {
public PFace<P> getFace(@NotNull final PHalfEdge<P> halfEdge) {
return halfEdge.getFace();
}
@Override
public PHalfEdge<P> getEdge(@NotNull P vertex) {
return null;
public PHalfEdge<P> getEdge(@NotNull PVertex<P> vertex) {
return vertex.getEdge();
}
@Override
......@@ -63,10 +64,20 @@ public class PMesh<P extends IPoint> implements IMesh<P, PHalfEdge<P>, PFace<P>>
}
@Override
public P getVertex(@NotNull PHalfEdge<P> halfEdge) {
public P getPoint(@NotNull PHalfEdge<P> halfEdge) {
return getVertex(halfEdge).getPoint();
}
@Override
public PVertex<P> getVertex(@NotNull PHalfEdge<P> halfEdge) {
return halfEdge.getEnd();
}
@Override
public P getPoint(@NotNull PVertex<P> vertex) {
return vertex.getPoint();
}
@Override
public PFace<P> getFace() {
return faces.stream().filter(face -> !face.isDestroyed()).findAny().get();
......@@ -118,22 +129,22 @@ public class PMesh<P extends IPoint> implements IMesh<P, PHalfEdge<P>, PFace<P>>
}
@Override
public void setEdge(@NotNull P vertex, @NotNull PHalfEdge<P> edge) {
throw new UnsupportedOperationException("not jet implemented.");
public void setEdge(@NotNull PVertex<P> vertex, @NotNull PHalfEdge<P> edge) {
vertex.setEdge(edge);
}
@Override
public void setVertex(@NotNull PHalfEdge<P> halfEdge, @NotNull P vertex) {
public void setVertex(@NotNull PHalfEdge<P> halfEdge, @NotNull PVertex<P> vertex) {
halfEdge.setEnd(vertex);
}
@Override
public List<PHalfEdge<P>> getEdges(@NotNull P vertex) {
public List<PHalfEdge<P>> getEdges(@NotNull final PVertex<P> vertex) {
return edges.stream().filter(edge -> !edge.isValid()).filter(edge -> getVertex(edge).equals(vertex)).collect(Collectors.toList());
}
@Override
public Collection<P> getVertices() {
public Collection<PVertex<P>> getVertices() {
return vertices;
}
......@@ -148,14 +159,14 @@ public class PMesh<P extends IPoint> implements IMesh<P, PHalfEdge<P>, PFace<P>>
}
@Override
public PHalfEdge<P> createEdge(@NotNull P vertex) {
public PHalfEdge<P> createEdge(@NotNull PVertex<P> vertex) {
PHalfEdge<P> edge = new PHalfEdge<>(vertex);
edges.add(edge);
return edge;
}
@Override
public PHalfEdge<P> createEdge(@NotNull P vertex, @NotNull PFace<P> face) {
public PHalfEdge<P> createEdge(@NotNull PVertex<P> vertex, @NotNull PFace<P> face) {
PHalfEdge<P> edge = new PHalfEdge<>(vertex, face);
edges.add(edge);
return edge;
......@@ -179,10 +190,20 @@ public class PMesh<P extends IPoint> implements IMesh<P, PHalfEdge<P>, PFace<P>>
}
@Override
public P createVertex(double x, double y) {
P vertex = pointConstructor.create(x, y);
//vertices.add(vertex);
return vertex;
public P createPoint(double x, double y) {
return pointConstructor.create(x, y);
}
// TODO: maybe remove insertVertex!
@Override
public PVertex<P> createVertex(double x, double y) {
return createVertex(pointConstructor.create(x, y));
}
@Override
public PVertex<P> createVertex(P point) {
return new PVertex<>(point);
}
@Override
......@@ -191,12 +212,12 @@ public class PMesh<P extends IPoint> implements IMesh<P, PHalfEdge<P>, PFace<P>>
}
@Override
public void insert(P vertex) {
public void insert(final PVertex<P> vertex) {
vertices.add(vertex);
}
@Override
public void insertVertex(P vertex) {
public void insertVertex(final PVertex<P> vertex) {
vertices.add(vertex);
}
......@@ -213,12 +234,32 @@ public class PMesh<P extends IPoint> implements IMesh<P, PHalfEdge<P>, PFace<P>>
}
@Override
public void destroyVertex(@NotNull P vertex) {
public void setDown(@NotNull PVertex<P> up, @NotNull PVertex<P> down) {
up.setDown(down);
}
@Override
public PVertex<P> getDown(@NotNull PVertex<P> vertex) {
return vertex.getDown();
}
@Override
public void destroyVertex(@NotNull PVertex<P> vertex) {
vertices.remove(vertex);
}
@Override
public Stream<PFace<P>> streamFaces() {
return faces.stream();
}
@Override
public Stream<PHalfEdge<P>> streamEdges() {
return streamFaces().flatMap(face -> streamEdges(face));
}
@Override
public List<PFace<P>> getFaces() {
return faces.stream().filter(face -> !face.isDestroyed()).collect(Collectors.toList());
return streamFaces().filter(face -> !face.isDestroyed()).collect(Collectors.toList());
}
}
package org.vadere.util.geometry.mesh.impl;
import org.vadere.util.geometry.mesh.inter.IVertex;
import org.vadere.util.geometry.shapes.IPoint;
/**
* @author Benedikt Zoennchen
* @param <P>
*/
public class PVertex<P extends IPoint> implements IVertex<P> {
private final P point;
private PVertex<P> down;
private PHalfEdge<P> halfEdge;
public PVertex(final P point) {
this.point = point;
this.down = null;
}
@Override
public P getPoint() {
return point;
}
public PHalfEdge<P> getEdge() {
return halfEdge;
}
public void setEdge(final PHalfEdge<P> halfEdge) {
this.halfEdge = halfEdge;
}
public PVertex<P> getDown() {
return down;
}
public void setDown(final PVertex<P> down) {
this.down = down;
}
@Override
public boolean equals(Object obj) {
if(obj == null) {
return false;
}
if(obj.getClass() != this.getClass()) {
return false;
}
return point.equals(((PVertex<P>)obj).getPoint());
}
@Override
public int hashCode() {
return point.hashCode();
}
@Override
public String toString() {
return point.toString();
}
}
......@@ -7,10 +7,12 @@ import org.vadere.util.geometry.GeometryUtils;
import org.vadere.util.geometry.mesh.impl.PFace;
import org.vadere.util.geometry.mesh.impl.PHalfEdge;
import org.vadere.util.geometry.mesh.impl.PMesh;
import org.vadere.util.geometry.mesh.impl.PVertex;
import org.vadere.util.geometry.mesh.iterators.EdgeIterator;
import org.vadere.util.geometry.mesh.iterators.AdjacentFaceIterator;
import org.vadere.util.geometry.mesh.iterators.IncidentEdgeIterator;
import org.vadere.util.geometry.mesh.iterators.SurroundingFaceIterator;
import org.vadere.util.geometry.mesh.iterators.VertexIterator;
import org.vadere.util.geometry.shapes.IPoint;
import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.geometry.shapes.VPolygon;
......@@ -39,22 +41,37 @@ import java.util.stream.StreamSupport;
* @param <E> the type of the half-edges
* @param <F> the type of the faces
*/
public interface IMesh<P extends IPoint, E extends IHalfEdge<P>, F extends IFace<P>> extends Iterable<F> {
public interface IMesh<P extends IPoint, V extends IVertex<P>, E extends IHalfEdge<P>, F extends IFace<P>> extends Iterable<F> {
E getNext(@NotNull E halfEdge);
E getPrev(@NotNull E halfEdge);
E getTwin(@NotNull E halfEdge);
F getFace(@NotNull E halfEdge);
E getEdge(@NotNull P vertex);
E getEdge(@NotNull V vertex);
E getEdge(@NotNull F face);