diff --git a/VadereUtils/src/org/vadere/util/geometry/data/DAG.java b/VadereUtils/src/org/vadere/util/geometry/data/DAG.java deleted file mode 100644 index e5d26338e42bd0ed0efd59c6324f7a7f98d046a4..0000000000000000000000000000000000000000 --- a/VadereUtils/src/org/vadere/util/geometry/data/DAG.java +++ /dev/null @@ -1,190 +0,0 @@ -package org.vadere.util.geometry.data; - -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Optional; -import java.util.Set; -import java.util.function.Predicate; - -/** - * Directed Acyclic graph. Each node of the DAG is a DAG itself. - * - * @param type of the elements of the DAG. - */ -public class DAG { - - /** - * The element of this DAG-Node. - */ - private final E element; - - /** - * The children of the DAG-Node. - */ - private final List> children; - - /** - * Default constructor. - * @param element - */ - public DAG(@NotNull final E element) { - this.element = element; - children = new ArrayList<>(); - } - - /** - * Returns all child nodes of the DAG. - * @return all child nodes of the DAG - */ - public List> getChildren() { - return children; - } - - /** - * Adds a new element as child node to the DAG. - * @param child a new element - */ - public void addChild(E child) { - this.children.add(new DAG(child)); - } - - /** - * Adds a new Node to as child node to the DAG. - * @param child a new child node - */ - public void addChild(DAG child) { - this.children.add(child); - } - - /** - * Returns the element of the DAG. - * @return - */ - public E getElement() { - return element; - } - - public Collection collectLeafs() { - Collection leafs = new ArrayList<>(); - LinkedList> nodesToVisit = new LinkedList<>(); - nodesToVisit.add(this); - - while (!nodesToVisit.isEmpty()) { - DAG currentNode = nodesToVisit.removeLast(); - nodesToVisit.addAll(currentNode.children); - - if(currentNode.isLeaf()) - leafs.add(currentNode.getElement()); - } - - return leafs; - } - - /** - * Test whether this DAG-Node is a child or not. - * @return true if this node is a child node, false otherwise. - */ - public boolean isLeaf(){ - return children.isEmpty(); - } - - /** - * Finds the first DAG-node element in a dept first fashion. - * @param test the predicate the element of the DAG-node has to fulfill. - * @return - */ - public Optional findFirstElement(final Predicate test){ - Optional> optDag = findFirst(test); - if(optDag.isPresent()) { - return Optional.of(optDag.get().getElement()); - } - else { - return Optional.empty(); - } - } - - /** - * Finds the first DAG-node in a dept first fashion. - * @param test the predicate the element of the DAG-node has to fulfill. - * @return - */ - public Optional> findFirst(final Predicate test){ - LinkedList> nodesToVisit = new LinkedList<>(); - nodesToVisit.add(this); - - while(!nodesToVisit.isEmpty()) { - DAG currentNode = nodesToVisit.removeLast(); - if(test.test(currentNode.getElement())) { - return Optional.of(currentNode); - } - nodesToVisit.addAll(currentNode.children); - } - - return Optional.empty(); - } - - /** - * Returns the last node of a path of elements that satisfy the test. - * The path will be constructed in a dept first fashion, therefore there - * may exist other paths. - * - * @param test - * @return - */ - public Optional> matchFirst(final Predicate test) { - - DAG currentNode = this; - - if(!test.test(currentNode.getElement())){ - return Optional.empty(); - } - else { - while(!currentNode.isLeaf()) { - Optional> opt = currentNode.children.stream().filter(node -> test.test(node.getElement())).findFirst(); - - // we stop at the last path element we found - if(!opt.isPresent()) { - return Optional.of(currentNode); - } - else { - currentNode = opt.get(); - } - } - } - - return Optional.of(currentNode); - } - - /** - * Returns a set of Dag elements containing all leafs such that there is a path - * to the leaf and for each node on the path the condition is feasible including - * the leaf itself. - * - * @param test - * @return - */ - public Set> matchAll(final Predicate test) { - Set> leafs = new HashSet<>(); - LinkedList> nodesToVisit = new LinkedList<>(); - nodesToVisit.add(this); - - while(!nodesToVisit.isEmpty()) { - DAG currentNode = nodesToVisit.removeLast(); - - if(test.test(currentNode.getElement())) { - nodesToVisit.addAll(currentNode.children); - - if(currentNode.isLeaf()) { - leafs.add(currentNode); - } - } - } - - return leafs; - } -} diff --git a/VadereUtils/src/org/vadere/util/geometry/data/DAGElement.java b/VadereUtils/src/org/vadere/util/geometry/data/DAGElement.java deleted file mode 100644 index b13e8f6f05a89f8ba9e9f5a5e75127d31f837f98..0000000000000000000000000000000000000000 --- a/VadereUtils/src/org/vadere/util/geometry/data/DAGElement.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.vadere.util.geometry.data; - -import org.apache.commons.lang3.tuple.Triple; -import org.vadere.util.geometry.data.Face; -import org.vadere.util.geometry.shapes.IPoint; -import org.vadere.util.geometry.shapes.VPoint; -import org.vadere.util.geometry.shapes.VTriangle; - -public class DAGElement

{ - private Face

face; - private Triple vertices; - private VTriangle triangle; - - public DAGElement(final Face

face, final Triple vertices) { - this.face = face; - this.vertices = vertices; - VPoint p1 = new VPoint(vertices.getLeft().getX(), vertices.getLeft().getY()); - VPoint p2 = new VPoint(vertices.getMiddle().getX(), vertices.getMiddle().getY()); - VPoint p3 = new VPoint(vertices.getRight().getX(), vertices.getRight().getY()); - this.triangle = new VTriangle(p1, p2, p3); - } - - public Face

getFace() { - return face; - } - - public VTriangle getTriangle() { - return triangle; - } - - public Triple getVertices() { - return vertices; - } - - @Override - public String toString() { - return triangle.toString(); - } -} diff --git a/VadereUtils/src/org/vadere/util/geometry/mesh/DAGElement.java b/VadereUtils/src/org/vadere/util/geometry/mesh/DAGElement.java index 2bda7efb07a8fe0e085f90bc204f4f9aadf02a9c..3d683960bda09d53621fb9d4cfefc384d1f905d7 100644 --- a/VadereUtils/src/org/vadere/util/geometry/mesh/DAGElement.java +++ b/VadereUtils/src/org/vadere/util/geometry/mesh/DAGElement.java @@ -1,38 +1,25 @@ package org.vadere.util.geometry.mesh; import org.apache.commons.lang3.tuple.Triple; -import org.vadere.util.geometry.mesh.inter.IFace; import org.vadere.util.geometry.shapes.IPoint; import org.vadere.util.geometry.shapes.VPoint; import org.vadere.util.geometry.shapes.VTriangle; -import java.util.List; - -public class DAGElement

> { - private F face; +public class DAGElement

{ + private Face

face; private Triple vertices; private VTriangle triangle; - public DAGElement(final F face, List

points) { - P p1 = points.get(0); - P p2 = points.get(1); - P p3 = points.get(2); - - this.face = face; - this.vertices = Triple.of(p1, p2, p3); - this.triangle = new VTriangle(new VPoint(p1), new VPoint(p2), new VPoint(p3)); - } - - public DAGElement(final F face, final Triple vertices) { + public DAGElement(final Face

face, final Triple vertices) { this.face = face; this.vertices = vertices; - VPoint p1 = new VPoint(vertices.getLeft()); - VPoint p2 = new VPoint(vertices.getMiddle()); - VPoint p3 = new VPoint(vertices.getRight()); + VPoint p1 = new VPoint(vertices.getLeft().getX(), vertices.getLeft().getY()); + VPoint p2 = new VPoint(vertices.getMiddle().getX(), vertices.getMiddle().getY()); + VPoint p3 = new VPoint(vertices.getRight().getX(), vertices.getRight().getY()); this.triangle = new VTriangle(p1, p2, p3); } - public F getFace() { + public Face

getFace() { return face; } diff --git a/VadereUtils/src/org/vadere/util/geometry/mesh/EdgeIterator.java b/VadereUtils/src/org/vadere/util/geometry/mesh/EdgeIterator.java new file mode 100644 index 0000000000000000000000000000000000000000..99e79932559acfec935407afefa4ded1ecd8ffc5 --- /dev/null +++ b/VadereUtils/src/org/vadere/util/geometry/mesh/EdgeIterator.java @@ -0,0 +1,34 @@ +package org.vadere.util.geometry.mesh; + +import org.vadere.util.geometry.shapes.IPoint; +import java.util.Iterator; + + +/** + * @author Benedikt Zoennchen + */ +public class EdgeIterator

, F extends IFace

> implements Iterator { + private E currentHalfEdge; + private E edge; + private boolean started = false; + private IMesh mesh; + + public EdgeIterator(final IMesh mesh, final F face){ + this.edge = mesh.getEdge(face); + this.currentHalfEdge = edge; + this.mesh = mesh; + } + + @Override + public boolean hasNext() { + return currentHalfEdge != null && (!started || !currentHalfEdge.equals(edge)); + } + + @Override + public E next() { + started = true; + E result = currentHalfEdge; + currentHalfEdge = mesh.getNext(currentHalfEdge); + return result; + } +} \ No newline at end of file diff --git a/VadereUtils/src/org/vadere/util/geometry/data/Face.java b/VadereUtils/src/org/vadere/util/geometry/mesh/Face.java similarity index 77% rename from VadereUtils/src/org/vadere/util/geometry/data/Face.java rename to VadereUtils/src/org/vadere/util/geometry/mesh/Face.java index ab0d21b502a5f21570f93572c8962f3f49c3a1b1..7e9854051176a28be08c1f748551d63961c0686a 100644 --- a/VadereUtils/src/org/vadere/util/geometry/data/Face.java +++ b/VadereUtils/src/org/vadere/util/geometry/mesh/Face.java @@ -1,10 +1,9 @@ -package org.vadere.util.geometry.data; +package org.vadere.util.geometry.mesh; import org.jetbrains.annotations.NotNull; import org.vadere.util.geometry.GeometryUtils; import org.vadere.util.geometry.shapes.IPoint; import org.vadere.util.geometry.shapes.MLine; -import org.vadere.util.geometry.shapes.VLine; import org.vadere.util.geometry.shapes.VPoint; import org.vadere.util.geometry.shapes.VPolygon; import org.vadere.util.geometry.shapes.VTriangle; @@ -12,7 +11,6 @@ import org.vadere.util.geometry.shapes.VTriangle; import java.awt.geom.Path2D; import java.util.Iterator; import java.util.List; -import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; import java.util.stream.StreamSupport; @@ -20,24 +18,25 @@ import java.util.stream.StreamSupport; /** * A Face is a region of a planar separation of the 2-D space, e.g. the region of a Polygon/Triangle and so on. * + * @author Benedikt Zoennchen * @param

the type of the coordinates the face uses. */ -public class Face

implements Iterable> { +public class Face

implements Iterable>, IFace

{ public static

Face

of(P x, P y, P z) { Face superTriangle = new Face(); Face borderFace = new Face(true); - HalfEdge xy = new HalfEdge(y, superTriangle); - HalfEdge yz = new HalfEdge(z, superTriangle); - HalfEdge zx = new HalfEdge(x, superTriangle); + PHalfEdge xy = new PHalfEdge(y, superTriangle); + PHalfEdge yz = new PHalfEdge(z, superTriangle); + PHalfEdge zx = new PHalfEdge(x, superTriangle); xy.setNext(yz); yz.setNext(zx); zx.setNext(xy); - HalfEdge yx = new HalfEdge(x, borderFace); - HalfEdge zy = new HalfEdge(y, borderFace); - HalfEdge xz = new HalfEdge(z, borderFace); + PHalfEdge yx = new PHalfEdge(x, borderFace); + PHalfEdge zy = new PHalfEdge(y, borderFace); + PHalfEdge xz = new PHalfEdge(z, borderFace); yx.setNext(xz); xz.setNext(zy); @@ -60,7 +59,7 @@ public class Face

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

edge; + private PHalfEdge

edge; private boolean border; @@ -72,11 +71,11 @@ public class Face

implements Iterable> { * * @param edge one of the half-edges bordering this face. */ - public Face(@NotNull final HalfEdge

edge) { + public Face(@NotNull final PHalfEdge

edge) { this(edge, false); } - public Face(@NotNull final HalfEdge

edge, boolean border) { + public Face(@NotNull final PHalfEdge

edge, boolean border) { this.border = border; this.edge = edge; } @@ -111,11 +110,11 @@ public class Face

implements Iterable> { * * @param edge half-edge bordering this face */ - public void setEdge(final HalfEdge

edge) { + public void setEdge(final PHalfEdge

edge) { this.edge = edge; } - public HalfEdge

getEdge() { + public PHalfEdge

getEdge() { return edge; } @@ -158,7 +157,7 @@ public class Face

implements Iterable> { public VPolygon toPolygon() { Path2D path2D = new Path2D.Double(); path2D.moveTo(edge.getPrevious().getEnd().getX(), edge.getPrevious().getEnd().getY()); - for(HalfEdge edge : this) { + for(PHalfEdge edge : this) { path2D.lineTo(edge.getEnd().getX(), edge.getEnd().getY()); } return new VPolygon(path2D); @@ -171,7 +170,7 @@ public class Face

implements Iterable> { * @return a triangle which is defined by this face */ public VTriangle toTriangle() { - List> edges = getEdges(); + List> edges = getEdges(); if(edges.size() != 3) { throw new IllegalArgumentException("this face is not a feasible triangle."); } @@ -184,16 +183,16 @@ 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); } - public List> getEdges() { + public List> getEdges() { return stream().collect(Collectors.toList()); } @@ -205,8 +204,13 @@ public class Face

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

currentHalfEdge; + @Override + public String toString() { + return stream().map(edge -> edge.getEnd().toString()).reduce("", (s1, s2) -> s1 + " " + s2); + } + + private class HalfEdgeIterator implements Iterator> { + private PHalfEdge

currentHalfEdge; private boolean started = false; private HalfEdgeIterator(){ @@ -215,13 +219,13 @@ public class Face

implements Iterable> { @Override public boolean hasNext() { - return !started || !currentHalfEdge.equals(edge); + return currentHalfEdge != null && (!started || !currentHalfEdge.equals(edge)); } @Override - public HalfEdge

next() { + public PHalfEdge

next() { started = true; - HalfEdge result = currentHalfEdge; + PHalfEdge result = currentHalfEdge; currentHalfEdge = currentHalfEdge.getNext(); return result; } diff --git a/VadereUtils/src/org/vadere/util/geometry/data/FaceIterator.java b/VadereUtils/src/org/vadere/util/geometry/mesh/FaceIterator.java similarity index 89% rename from VadereUtils/src/org/vadere/util/geometry/data/FaceIterator.java rename to VadereUtils/src/org/vadere/util/geometry/mesh/FaceIterator.java index d522c67a2503e7bf679ec896d819d437fee86209..d9cb2305255b32828cea53c2a50e1ab2488b0964 100644 --- a/VadereUtils/src/org/vadere/util/geometry/data/FaceIterator.java +++ b/VadereUtils/src/org/vadere/util/geometry/mesh/FaceIterator.java @@ -1,7 +1,5 @@ -package org.vadere.util.geometry.data; +package org.vadere.util.geometry.mesh; -import org.vadere.util.geometry.data.Face; -import org.vadere.util.geometry.data.HalfEdge; import org.vadere.util.geometry.shapes.IPoint; import java.util.HashSet; @@ -48,7 +46,7 @@ public class FaceIterator

implements Iterator> { Face

nextFace = facesToVisit.removeFirst(); visitedFaces.add(nextFace); - for(HalfEdge

he : nextFace) { + for(PHalfEdge

he : nextFace) { Face

twinFace = he.getTwin().getFace(); if(twinFace.isBorder() || twinFace.isDestroyed() || !facePredicate.test(twinFace)) { diff --git a/VadereUtils/src/org/vadere/util/geometry/mesh/IFace.java b/VadereUtils/src/org/vadere/util/geometry/mesh/IFace.java new file mode 100644 index 0000000000000000000000000000000000000000..2ae48b2522ee5f388efd3ad2c8e9590ce4b21d29 --- /dev/null +++ b/VadereUtils/src/org/vadere/util/geometry/mesh/IFace.java @@ -0,0 +1,16 @@ +package org.vadere.util.geometry.mesh; + +import org.vadere.util.geometry.shapes.IPoint; +import org.vadere.util.geometry.shapes.VPolygon; + +import java.awt.geom.Path2D; + +/** + * @author Benedikt Zoennchen + * @param

+ */ +public interface IFace

{ + + + +} diff --git a/VadereUtils/src/org/vadere/util/geometry/mesh/IHalfEdge.java b/VadereUtils/src/org/vadere/util/geometry/mesh/IHalfEdge.java new file mode 100644 index 0000000000000000000000000000000000000000..22b757438cdbd30f9d4346d9d07794ed4b20aa16 --- /dev/null +++ b/VadereUtils/src/org/vadere/util/geometry/mesh/IHalfEdge.java @@ -0,0 +1,5 @@ +package org.vadere.util.geometry.mesh; + +import org.vadere.util.geometry.shapes.IPoint; + +public interface IHalfEdge

{} diff --git a/VadereUtils/src/org/vadere/util/geometry/mesh/IMesh.java b/VadereUtils/src/org/vadere/util/geometry/mesh/IMesh.java new file mode 100644 index 0000000000000000000000000000000000000000..3c4e660cbc40c7be782648abc88ed2ddf8056493 --- /dev/null +++ b/VadereUtils/src/org/vadere/util/geometry/mesh/IMesh.java @@ -0,0 +1,106 @@ +package org.vadere.util.geometry.mesh; + +import org.apache.commons.collections.IteratorUtils; +import org.jetbrains.annotations.NotNull; +import org.vadere.util.geometry.shapes.IPoint; +import org.vadere.util.geometry.shapes.VPoint; +import org.vadere.util.geometry.shapes.VPolygon; + +import java.awt.geom.Path2D; +import java.util.Iterator; +import java.util.List; +import java.util.Optional; + +/** + * @author Benedikt Zoennchen + * @param

+ */ +public interface IMesh

, F extends IFace

> extends Iterable { + 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 F face); + + P getVertex(@NotNull E halfEdge); + + default F getTwinFace(@NotNull E halfEdge) { + return getFace(getTwin(halfEdge)); + } + + boolean isBoundary(@NotNull F face); + boolean isBoundary(@NotNull E halfEdge); + boolean isDestroyed(@NotNull F face); + + void setTwin(@NotNull E halfEdge, @NotNull E twin); + void setNext(@NotNull E halfEdge, @NotNull E next); + void setPrev(@NotNull E halfEdge, @NotNull E prev); + void setFace(@NotNull E halfEdge, @NotNull F face); + + void setEdge(@NotNull F face, @NotNull E edge); + void setEdge(@NotNull P vertex, @NotNull E edge); + void setVertex(@NotNull E halfEdge, @NotNull P vertex); + + List getEdges(@NotNull P vertex); + + default List getEdges(@NotNull F face) { + return IteratorUtils.toList(new EdgeIterator(this, face)); + } + + default List getFaces(@NotNull E edge) { return IteratorUtils.toList(new NeighbourFaceIterator(this, edge)); } + + default List getNeighbours(@NotNull E edge) { return IteratorUtils.toList(new NeighbourIterator(this, edge)); } + + default Iterable getNeighbourIt(E edge) { + return () -> new NeighbourIterator(this, edge); + } + + default Iterable getEdgeIt(F face) { + return () -> new EdgeIterator(this, face); + } + + default Iterable getIncidentFacesIt(@NotNull E edge) { return () -> new NeighbourFaceIterator<>(this, edge); } + + E createEdge(@NotNull P vertex); + E createEdge(@NotNull P vertex, @NotNull F face); + F createFace(); + + void destroyFace(@NotNull F face); + void destroyEdge(@NotNull E edge); + + List getFaces(); + + @Override + default Iterator iterator() { + return getFaces().iterator(); + } + + default VPolygon toPolygon(F face) { + Path2D path2D = new Path2D.Double(); + E edge = getEdge(face); + E prev = getPrev(edge); + + path2D.moveTo(getVertex(prev).getX(), getVertex(prev).getY()); + path2D.lineTo(getVertex(edge).getX(), getVertex(edge).getY()); + + while (!edge.equals(prev)) { + edge = getNext(edge); + P p = getVertex(edge); + path2D.lineTo(p.getX(), p.getY()); + } + + return new VPolygon(path2D); + } + + default Optional locate(final double x, final double y) { + for(F face : getFaces()) { + VPolygon polygon = toPolygon(face); + if(polygon.contains(new VPoint(x, y))) { + return Optional.of(face); + } + } + return Optional.empty(); + } +} diff --git a/VadereUtils/src/org/vadere/util/geometry/mesh/NeighbourFaceIterator.java b/VadereUtils/src/org/vadere/util/geometry/mesh/NeighbourFaceIterator.java new file mode 100644 index 0000000000000000000000000000000000000000..a91fb957b9d9eec6c74abbf039f541218bcc1254 --- /dev/null +++ b/VadereUtils/src/org/vadere/util/geometry/mesh/NeighbourFaceIterator.java @@ -0,0 +1,31 @@ +package org.vadere.util.geometry.mesh; + +import org.vadere.util.geometry.shapes.IPoint; + +import java.util.Iterator; + +/** + * This iterator assumes that the this edge is completely surrounded by faces. + * + * @author Benedikt Zoennchen + */ +public +class NeighbourFaceIterator

, F extends IFace

> implements Iterator { + private NeighbourIterator neighbourIterator; + private IMesh mesh; + + public NeighbourFaceIterator(final IMesh mesh, E edge) { + this.neighbourIterator = new NeighbourIterator<>(mesh, edge); + this.mesh = mesh; + } + + @Override + public boolean hasNext() { + return neighbourIterator.hasNext(); + } + + @Override + public F next() { + return mesh.getFace(neighbourIterator.next()); + } +} \ No newline at end of file diff --git a/VadereUtils/src/org/vadere/util/geometry/mesh/NeighbourIterator.java b/VadereUtils/src/org/vadere/util/geometry/mesh/NeighbourIterator.java new file mode 100644 index 0000000000000000000000000000000000000000..997aa30b6dcd2e00170e31d2e222bf589a438399 --- /dev/null +++ b/VadereUtils/src/org/vadere/util/geometry/mesh/NeighbourIterator.java @@ -0,0 +1,39 @@ +package org.vadere.util.geometry.mesh; + +import org.vadere.util.geometry.shapes.IPoint; + +import java.util.Iterator; + +/** + * @author Benedikt Zoennchen + * @param

+ * @param + * @param + */ +public class NeighbourIterator

, F extends IFace

> implements Iterator { + + private IMesh mesh; + private E current; + private E edge; + private boolean first; + + public NeighbourIterator(final IMesh mesh, final E edge) { + this.mesh = mesh; + this.edge = edge; + this.current = mesh.getNext(edge); + this.first = true; + } + + @Override + public boolean hasNext() { + return (first || current != mesh.getNext(edge)); + } + + @Override + public E next() { + E result = current; + current = mesh.getNext(mesh.getTwin(result)); + first = false; + return result; + } +} diff --git a/VadereUtils/src/org/vadere/util/geometry/data/HalfEdge.java b/VadereUtils/src/org/vadere/util/geometry/mesh/PHalfEdge.java similarity index 100% rename from VadereUtils/src/org/vadere/util/geometry/data/HalfEdge.java rename to VadereUtils/src/org/vadere/util/geometry/mesh/PHalfEdge.java diff --git a/VadereUtils/src/org/vadere/util/geometry/mesh/PMesh.java b/VadereUtils/src/org/vadere/util/geometry/mesh/PMesh.java new file mode 100644 index 0000000000000000000000000000000000000000..b9ebec44a632da5e1189064cde06faa204fdf4ec --- /dev/null +++ b/VadereUtils/src/org/vadere/util/geometry/mesh/PMesh.java @@ -0,0 +1,109 @@ +package org.vadere.util.geometry.mesh; + +import org.jetbrains.annotations.NotNull; +import org.vadere.util.geometry.shapes.IPoint; + +import java.util.List; + +/** + * @author Benedikt Zoennchen + */ +public class PMesh

implements IMesh, Face

> { + + public PMesh() {} + + @Override + public PHalfEdge

getNext(final PHalfEdge

halfEdge) { + return halfEdge.getNext(); + } + + @Override + public PHalfEdge

getPrev(final PHalfEdge

halfEdge) { + return halfEdge.getPrevious(); + } + + @Override + public PHalfEdge

getTwin(final PHalfEdge

halfEdge) { + return halfEdge.getTwin(); + } + + @Override + public Face

getFace(final PHalfEdge

halfEdge) { + return halfEdge.getFace(); + } + + @Override + public PHalfEdge

getEdge(@NotNull P vertex) { + return null; + } + + @Override + public PHalfEdge

getEdge(Face

face) { + return face.getEdge(); + } + + @Override + public P getVertex(@NotNull PHalfEdge

halfEdge) { + return halfEdge.getEnd(); + } + + @Override + public boolean isBoundary(@NotNull PHalfEdge

halfEdge) { + return halfEdge.isBoundary(); + } + + @Override + public void setTwin(final PHalfEdge

halfEdge, final PHalfEdge

twin) { + halfEdge.setTwin(twin); + } + + @Override + public void setNext(final PHalfEdge

halfEdge, final PHalfEdge

next) { + halfEdge.setNext(next); + } + + @Override + public void setPrev(final PHalfEdge

halfEdge, final PHalfEdge

prev) { + halfEdge.setPrevious(prev); + } + + @Override + public void setFace(final PHalfEdge

halfEdge, final Face

face) { + halfEdge.setFace(face); + } + + @Override + public void setEdge(final Face

face, final PHalfEdge

edge) { + face.setEdge(edge); + } + + @Override + public void setEdge(@NotNull P vertex, @NotNull PHalfEdge

edge) { + throw new UnsupportedOperationException("not jet implemented."); + } + + @Override + public void setVertex(@NotNull PHalfEdge

halfEdge, @NotNull P vertex) { + halfEdge.setEnd(vertex); + } + + @Override + public List> getEdges(@NotNull P vertex) { + throw new UnsupportedOperationException("no jet implemented."); + } + + @Override + public PHalfEdge

createEdge(@NotNull P vertex) { + return new PHalfEdge<>(vertex); + } + + @Override + public PHalfEdge

createEdge(@NotNull P vertex, @NotNull Face

face) { + return new PHalfEdge

(vertex, face); + } + + @Override + public Face

createFace() { + return new Face<>(); + } +} diff --git a/VadereUtils/src/org/vadere/util/triangulation/ITriangulation.java b/VadereUtils/src/org/vadere/util/triangulation/ITriangulation.java index 9a584624d9f7666ce2ac6a0f143b3773eb36e496..74161c1c5158b3ee09c693d2a5ec3725a9637fea 100644 --- a/VadereUtils/src/org/vadere/util/triangulation/ITriangulation.java +++ b/VadereUtils/src/org/vadere/util/triangulation/ITriangulation.java @@ -1,18 +1,17 @@ package org.vadere.util.triangulation; -import org.vadere.util.geometry.data.Face; -import org.vadere.util.geometry.data.HalfEdge; +import org.vadere.util.geometry.mesh.IFace; +import org.vadere.util.geometry.mesh.IHalfEdge; +import org.vadere.util.geometry.mesh.ITriConnectivity; import org.vadere.util.geometry.shapes.IPoint; import java.util.Set; import java.util.stream.Stream; -public interface ITriangulation

extends Iterable> { +public interface ITriangulation

, F extends IFace

> extends Iterable, ITriConnectivity { void compute(); - Face

locate(final double x, final double y); - Face

locate(final IPoint point); - Stream> streamFaces(); - Set> getFaces(); - HalfEdge

insert(final P point); + Stream streamFaces(); + Set getFaces(); + E insert(final P point); void remove(final P point); } diff --git a/VadereUtils/src/org/vadere/util/triangulation/PointLocation.java b/VadereUtils/src/org/vadere/util/triangulation/PointLocation.java index 7f5a6b0e781fed2c2d2fde10b8152c8b75c72652..08ff95c0299e9fb4022c70782953c00c6a9a708e 100644 --- a/VadereUtils/src/org/vadere/util/triangulation/PointLocation.java +++ b/VadereUtils/src/org/vadere/util/triangulation/PointLocation.java @@ -1,7 +1,7 @@ package org.vadere.util.triangulation; -import org.vadere.util.geometry.data.Face; -import org.vadere.util.geometry.data.HalfEdge; +import org.vadere.util.geometry.mesh.Face; +import org.vadere.util.geometry.mesh.PHalfEdge; import org.vadere.util.geometry.shapes.VLine; import org.vadere.util.geometry.shapes.VPoint; @@ -20,7 +20,7 @@ public class PointLocation

{ private final Collection> faces; private final List

orderedPointList; - private final List>> halfeEdgesSegments; + private final List>> halfeEdgesSegments; private final List> intersectionPointsInSegment; private final BiFunction pointConstructor; @@ -38,7 +38,7 @@ public class PointLocation

{ else return 0; }; - private class BetweenTwoPoints implements Predicate> { + private class BetweenTwoPoints implements Predicate> { private P p1; private P p2; @@ -49,13 +49,13 @@ public class PointLocation

{ } @Override - public boolean test(final HalfEdge

halfEdge) { + public boolean test(final PHalfEdge

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; @@ -66,7 +66,7 @@ public class PointLocation

{ } @Override - public int compare(final HalfEdge

edge1, final HalfEdge

edge2) { + public int compare(final PHalfEdge

edge1, final PHalfEdge

edge2) { VLine line1 = edge1.toLine(); VLine line2 = edge2.toLine(); double slope1 = line1.slope(); @@ -97,7 +97,7 @@ public class PointLocation

{ for(int i = 0; i < orderedPointList.size() - 1; i++) { P p1 = orderedPointList.get(i); P p2 = orderedPointList.get(i+1); - List> halfEdges = faces.stream().flatMap(face -> face.stream()).filter(new BetweenTwoPoints(p1, p2)) + 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() .map(hf -> hf.toLine()) @@ -124,7 +124,7 @@ public class PointLocation

{ return Optional.empty(); } - HalfEdge

edge = halfeEdgesSegments.get(xSegmentIndex).get(ySegmentIndex); + PHalfEdge

edge = halfeEdgesSegments.get(xSegmentIndex).get(ySegmentIndex); if(edge.getFace().contains(point)) { return Optional.of(edge.getFace()); diff --git a/VadereUtils/src/org/vadere/util/triangulation/UniformRefinementTriangulation.java b/VadereUtils/src/org/vadere/util/triangulation/UniformRefinementTriangulation.java index 71f11f1fab730ab08d201a4fee65b4d7bc2107a8..de2ed6566bdc5fdad7f1b99d1886586f2229b95d 100644 --- a/VadereUtils/src/org/vadere/util/triangulation/UniformRefinementTriangulation.java +++ b/VadereUtils/src/org/vadere/util/triangulation/UniformRefinementTriangulation.java @@ -2,9 +2,8 @@ package org.vadere.util.triangulation; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; -import org.vadere.util.geometry.FixPointGenerator; -import org.vadere.util.geometry.data.Face; -import org.vadere.util.geometry.data.HalfEdge; +import org.vadere.util.geometry.mesh.Face; +import org.vadere.util.geometry.mesh.PHalfEdge; import org.vadere.util.geometry.shapes.IPoint; import org.vadere.util.geometry.shapes.VLine; import org.vadere.util.geometry.shapes.VPoint; @@ -19,8 +18,6 @@ import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Set; -import java.util.function.Predicate; -import java.util.stream.Collectors; /** * @author Benedikt Zoennchen @@ -31,7 +28,7 @@ public class UniformRefinementTriangulation

{ private final Collection boundary; private final VRectangle bbox; private final IEdgeLengthFunction lenFunc; - private final Set> refinedEdges; + private final Set> refinedEdges; private int splitCount; private IncrementalTriangulation

triangulation; private IPointConstructor

pointConstructor; @@ -57,7 +54,7 @@ public class UniformRefinementTriangulation

{ this.splitCount = 0; } - public boolean isCompleted(final HalfEdge

edge) { + public boolean isCompleted(final PHalfEdge

edge) { VTriangle triangle = edge.isBoundary() ? edge.getTwin().getFace().toTriangle() : edge.getFace().toTriangle(); //System.out.println(bbox.distance(triangle.midPoint())); return !bbox.intersect(triangle) || boundary.stream().anyMatch(shape -> shape.contains(triangle.getBounds2D())) || edge.getEnd().distance(edge.getPrevious().getEnd()) <= lenFunc.apply(midPoint(edge)); @@ -66,19 +63,19 @@ public class UniformRefinementTriangulation

{ public void compute() { logger.info("start computation"); int count = 0; - LinkedList> toRefineEdges = new LinkedList<>(); - List> edges = triangulation.superTriangle.getEdges(); + LinkedList> toRefineEdges = new LinkedList<>(); + List> edges = triangulation.superTriangle.getEdges(); - for(HalfEdge

edge : edges) { + for(PHalfEdge

edge : edges) { if(!isCompleted(edge) && !points.contains(edge.getEnd())) { toRefineEdges.add(edge); } } while (!toRefineEdges.isEmpty()) { - HalfEdge

edge = toRefineEdges.removeFirst(); + PHalfEdge

edge = toRefineEdges.removeFirst(); count++; - for(HalfEdge

refinedHalfEdges : refine(edge)) { + for(PHalfEdge

refinedHalfEdges : refine(edge)) { if(!isCompleted(refinedHalfEdges)) { toRefineEdges.addLast(refinedHalfEdges); } @@ -92,69 +89,71 @@ public class UniformRefinementTriangulation

{ if(face != null) { // 2. build a border-face: delete edges as long as they are inside the boundary //face.toBorder(); - boolean changed = true; - HalfEdge

startEdge = face.getEdge(); - HalfEdge

edge = null; + PHalfEdge

beginEdge = face.getEdge(); + PHalfEdge

currentEdge = null; - while (!startEdge.equals(edge)) { - if (edge == null) { - edge = startEdge; + while (!beginEdge.equals(currentEdge) && count < 7941) { + if (currentEdge == null) { + currentEdge = beginEdge; } - boolean eqNext = edge.getTwin().getFace().equals(edge.getNext().getTwin().getFace()); - boolean eqPrev = edge.getTwin().getFace().equals(edge.getPrevious().getTwin().getFace()); + if(currentEdge.getFace().equals(currentEdge.getTwin().getFace())) { + System.out.println("special case"); + } + + PHalfEdge

candidate = currentEdge; + LinkedList> toRemove = new LinkedList<>(); + toRemove.addLast(candidate); + while (candidate.hasSameTwinFace(candidate.getNext())) { + toRemove.addLast(candidate.getNext()); + candidate = candidate.getNext(); + } + + candidate = currentEdge; + while(candidate.hasSameTwinFace(candidate.getPrevious())) { + toRemove.addFirst(candidate.getPrevious()); + candidate = candidate.getPrevious(); + } + + System.out.println("toRemove:" + toRemove.size()); - if (eqNext || eqPrev) { - HalfEdge

h0 = eqNext ? edge : edge.getPrevious(); - if (shape.intersects(h0.toLine()) || shape.intersects(h0.getNext().toLine())) { - // change the face - HalfEdge

middleEdge = h0.getTwin().getNext(); - middleEdge.setFace(face); + PHalfEdge

next = toRemove.peekLast().getNext(); + PHalfEdge

previous = toRemove.peekFirst().getPrevious(); - // build connectivity - h0.getPrevious().setNext(middleEdge); - h0.getNext().getNext().setPrevious(middleEdge); + LinkedList> toUpdate = new LinkedList<>(); + PHalfEdge

start = toRemove.peekFirst().getTwin().getNext(); + PHalfEdge

end = toRemove.peekLast().getTwin(); - // change the edge of the face since we might destroy it - face.setEdge(h0.getNext().getNext()); - edge = h0.getNext().getNext(); - startEdge = middleEdge; + while (!start.equals(end)) { + toUpdate.addLast(start); + start = start.getNext(); + } - // destroy - h0.getNext().getTwin().destroy(); - h0.getNext().destroy(); - h0.getFace().destroy(); + System.out.println("toUpdate:" + toUpdate.size()); - h0.getTwin().destroy(); - h0.destroy(); + if((toUpdate.size() + toRemove.size()) != 3) { + System.out.println("wtf"); + } - } else { - edge = edge.getNext(); + if(!toUpdate.isEmpty()) { + toUpdate.peekFirst().getFace().destroy(); + for(PHalfEdge

halfEdge : toUpdate) { + halfEdge.setFace(face); } - } else if (shape.intersects(edge.toLine())) { - HalfEdge

twin = edge.getTwin(); - HalfEdge

destroyEdge = edge; - - // change the face - twin.getNext().setFace(face); - twin.getPrevious().setFace(face); - - // build connectivity - edge.getPrevious().setNext(twin.getNext()); - edge.getNext().setPrevious(twin.getPrevious()); - startEdge = twin.getPrevious(); - - // change the edge of the face since we might destroy it - face.setEdge(edge.getNext()); - edge = edge.getNext(); - - // destroy - twin.getFace().destroy(); - destroyEdge.destroy(); - twin.destroy(); - } else { - edge = edge.getNext(); } + + currentEdge = toRemove.peekLast().getNext(); + face.setEdge(currentEdge); + for(PHalfEdge

halfEdge : toRemove) { + halfEdge.getTwin().destroy(); + halfEdge.destroy(); + } + + next.setPrevious(toUpdate.peekLast()); + previous.setNext(toUpdate.peekFirst()); + + count++; + System.out.println(count); } } } @@ -165,7 +164,7 @@ public class UniformRefinementTriangulation

{ return triangulation.getEdges(); } - public Collection> refine(final HalfEdge

edge) { + public Collection> refine(final PHalfEdge

edge) { VPoint midPoint = midPoint(edge); P p = pointConstructor.create(midPoint.getX(), midPoint.getY()); @@ -179,7 +178,7 @@ public class UniformRefinementTriangulation

{ } } - private boolean flipEdgeCrossBoundary(final HalfEdge

edge) { + private boolean flipEdgeCrossBoundary(final PHalfEdge

edge) { P p1 = edge.getNext().getEnd(); P p2 = edge.getTwin().getNext().getEnd(); @@ -192,7 +191,7 @@ public class UniformRefinementTriangulation

{ return false; } - private VPoint midPoint(final HalfEdge

edge) { + private VPoint midPoint(final PHalfEdge

edge) { VPoint p1 = new VPoint(edge.getEnd()); VPoint p2 = new VPoint(edge.getPrevious().getEnd()); return p2.add(p1).scalarMultiply(0.5); diff --git a/VadereUtils/tests/org/vadere/util/triangulation/TestBoyerWatson.java b/VadereUtils/tests/org/vadere/util/triangulation/TestBoyerWatson.java index 00455af69cbde4212e6b1a15d08dea243cd10da0..1e3705bd5a6e95fb4b207d8df12a02b008b344f8 100644 --- a/VadereUtils/tests/org/vadere/util/triangulation/TestBoyerWatson.java +++ b/VadereUtils/tests/org/vadere/util/triangulation/TestBoyerWatson.java @@ -3,9 +3,9 @@ package org.vadere.util.triangulation; import org.apache.commons.lang3.tuple.Triple; import org.junit.Before; import org.junit.Test; -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.mesh.DAG; +import org.vadere.util.geometry.mesh.DAGElement; +import org.vadere.util.geometry.mesh.Face; import org.vadere.util.geometry.shapes.VPoint; import org.vadere.util.geometry.shapes.VTriangle;