In January 2021 we will introduce a 10 GB quota for project repositories. Higher limits for individual projects will be available on request. Please see https://doku.lrz.de/display/PUBLIC/GitLab for more information.

Commit 074f4e91 authored by Benedikt Zoennchen's avatar Benedikt Zoennchen

before refactoring of the mesh ds

parent 89c47fd2
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 <E> type of the elements of the DAG.
*/
public class DAG<E> {
/**
* The element of this DAG-Node.
*/
private final E element;
/**
* The children of the DAG-Node.
*/
private final List<DAG<E>> 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<DAG<E>> 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<E>(child));
}
/**
* Adds a new Node to as child node to the DAG.
* @param child a new child node
*/
public void addChild(DAG<E> child) {
this.children.add(child);
}
/**
* Returns the element of the DAG.
* @return
*/
public E getElement() {
return element;
}
public Collection<E> collectLeafs() {
Collection<E> leafs = new ArrayList<>();
LinkedList<DAG<E>> nodesToVisit = new LinkedList<>();
nodesToVisit.add(this);
while (!nodesToVisit.isEmpty()) {
DAG<E> 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<E> findFirstElement(final Predicate<E> test){
Optional<DAG<E>> 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<DAG<E>> findFirst(final Predicate<E> test){
LinkedList<DAG<E>> nodesToVisit = new LinkedList<>();
nodesToVisit.add(this);
while(!nodesToVisit.isEmpty()) {
DAG<E> 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<DAG<E>> matchFirst(final Predicate<E> test) {
DAG<E> currentNode = this;
if(!test.test(currentNode.getElement())){
return Optional.empty();
}
else {
while(!currentNode.isLeaf()) {
Optional<DAG<E>> 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<DAG<E>> matchAll(final Predicate<E> test) {
Set<DAG<E>> leafs = new HashSet<>();
LinkedList<DAG<E>> nodesToVisit = new LinkedList<>();
nodesToVisit.add(this);
while(!nodesToVisit.isEmpty()) {
DAG<E> currentNode = nodesToVisit.removeLast();
if(test.test(currentNode.getElement())) {
nodesToVisit.addAll(currentNode.children);
if(currentNode.isLeaf()) {
leafs.add(currentNode);
}
}
}
return leafs;
}
}
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<P extends IPoint> {
private Face<P> face;
private Triple<P, P, P> vertices;
private VTriangle triangle;
public DAGElement(final Face<P> face, final Triple<P, P, P> 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<P> getFace() {
return face;
}
public VTriangle getTriangle() {
return triangle;
}
public Triple<P, P, P> getVertices() {
return vertices;
}
@Override
public String toString() {
return triangle.toString();
}
}
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<P extends IPoint, F extends IFace<P>> {
private F face;
public class DAGElement<P extends IPoint> {
private Face<P> face;
private Triple<P, P, P> vertices;
private VTriangle triangle;
public DAGElement(final F face, List<P> 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<P, P, P> vertices) {
public DAGElement(final Face<P> face, final Triple<P, P, P> 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<P> getFace() {
return face;
}
......
package org.vadere.util.geometry.mesh;
import org.vadere.util.geometry.shapes.IPoint;
import java.util.Iterator;
/**
* @author Benedikt Zoennchen
*/
public class EdgeIterator<P extends IPoint, E extends IHalfEdge<P>, F extends IFace<P>> implements Iterator<E> {
private E currentHalfEdge;
private E edge;
private boolean started = false;
private IMesh<P, E, F> mesh;
public EdgeIterator(final IMesh<P, E, F> 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
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 <P> the type of the coordinates the face uses.
*/
public class Face<P extends IPoint> implements Iterable<HalfEdge<P>> {
public class Face<P extends IPoint> implements Iterable<PHalfEdge<P>>, IFace<P> {
public static <P extends IPoint> Face<P> 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<P extends IPoint> implements Iterable<HalfEdge<P>> {
/**
* One of the half-edges bordering this face.
*/
private HalfEdge<P> edge;
private PHalfEdge<P> edge;
private boolean border;
......@@ -72,11 +71,11 @@ public class Face<P extends IPoint> implements Iterable<HalfEdge<P>> {
*
* @param edge one of the half-edges bordering this face.
*/
public Face(@NotNull final HalfEdge<P> edge) {
public Face(@NotNull final PHalfEdge<P> edge) {
this(edge, false);
}
public Face(@NotNull final HalfEdge<P> edge, boolean border) {
public Face(@NotNull final PHalfEdge<P> edge, boolean border) {
this.border = border;
this.edge = edge;
}
......@@ -111,11 +110,11 @@ public class Face<P extends IPoint> implements Iterable<HalfEdge<P>> {
*
* @param edge half-edge bordering this face
*/
public void setEdge(final HalfEdge<P> edge) {
public void setEdge(final PHalfEdge<P> edge) {
this.edge = edge;
}
public HalfEdge<P> getEdge() {
public PHalfEdge<P> getEdge() {
return edge;
}
......@@ -158,7 +157,7 @@ public class Face<P extends IPoint> implements Iterable<HalfEdge<P>> {
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<P extends IPoint> implements Iterable<HalfEdge<P>> {
* @return a triangle which is defined by this face
*/
public VTriangle toTriangle() {
List<HalfEdge<P>> edges = getEdges();
List<PHalfEdge<P>> edges = getEdges();
if(edges.size() != 3) {
throw new IllegalArgumentException("this face is not a feasible triangle.");
}
......@@ -184,16 +183,16 @@ public class Face<P extends IPoint> implements Iterable<HalfEdge<P>> {
}
@Override
public Iterator<HalfEdge<P>> iterator() {
public Iterator<PHalfEdge<P>> iterator() {
return new HalfEdgeIterator();
}
public Stream<HalfEdge<P>> stream () {
Iterable<HalfEdge<P>> iterable = () -> iterator();
public Stream<PHalfEdge<P>> stream () {
Iterable<PHalfEdge<P>> iterable = () -> iterator();
return StreamSupport.stream(iterable.spliterator(), false);
}
public List<HalfEdge<P>> getEdges() {
public List<PHalfEdge<P>> getEdges() {
return stream().collect(Collectors.toList());
}
......@@ -205,8 +204,13 @@ public class Face<P extends IPoint> implements Iterable<HalfEdge<P>> {
return stream().map(edge -> edge.getEnd());
}
private class HalfEdgeIterator implements Iterator<HalfEdge<P>> {
private HalfEdge<P> currentHalfEdge;
@Override
public String toString() {
return stream().map(edge -> edge.getEnd().toString()).reduce("", (s1, s2) -> s1 + " " + s2);
}
private class HalfEdgeIterator implements Iterator<PHalfEdge<P>> {
private PHalfEdge<P> currentHalfEdge;
private boolean started = false;
private HalfEdgeIterator(){
......@@ -215,13 +219,13 @@ public class Face<P extends IPoint> implements Iterable<HalfEdge<P>> {
@Override
public boolean hasNext() {
return !started || !currentHalfEdge.equals(edge);
return currentHalfEdge != null && (!started || !currentHalfEdge.equals(edge));
}
@Override
public HalfEdge<P> next() {
public PHalfEdge<P> next() {
started = true;
HalfEdge result = currentHalfEdge;
PHalfEdge result = currentHalfEdge;
currentHalfEdge = currentHalfEdge.getNext();
return result;
}
......
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<P extends IPoint> implements Iterator<Face<P>> {
Face<P> nextFace = facesToVisit.removeFirst();
visitedFaces.add(nextFace);
for(HalfEdge<P> he : nextFace) {
for(PHalfEdge<P> he : nextFace) {
Face<P> twinFace = he.getTwin().getFace();
if(twinFace.isBorder() || twinFace.isDestroyed() || !facePredicate.test(twinFace)) {
......
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 <P>
*/
public interface IFace<P extends IPoint> {
}
package org.vadere.util.geometry.mesh;
import org.vadere.util.geometry.shapes.IPoint;
public interface IHalfEdge<P extends IPoint> {}
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 <P>
*/
public interface IMesh<P extends IPoint, 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 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<E> getEdges(@NotNull P vertex);
default List<E> getEdges(@NotNull F face) {
return IteratorUtils.toList(new EdgeIterator(this, face));
}
default List<F> getFaces(@NotNull E edge) { return IteratorUtils.toList(new NeighbourFaceIterator(this, edge)); }
default List<E> getNeighbours(@NotNull E edge) { return IteratorUtils.toList(new NeighbourIterator(this, edge)); }
default Iterable<E> getNeighbourIt(E edge) {
return () -> new NeighbourIterator(this, edge);
}
default Iterable<E> getEdgeIt(F face) {
return () -> new EdgeIterator(this, face);
}
default Iterable<F> 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<F> getFaces();
@Override
default Iterator<F> 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);
}