Commit 0fb76bd7 authored by Benedikt Zoennchen's avatar Benedikt Zoennchen
Browse files

before refactoring of the mesh ds

parent d89bd0ef
package org.vadere.util.geometry.data;
package org.vadere.util.geometry.mesh;
import org.jetbrains.annotations.NotNull;
......
package org.vadere.util.geometry.data;
package org.vadere.util.geometry.mesh;
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;
......
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);
}
default Optional<F> 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();
}
}
package org.vadere.util.geometry.mesh;
import org.vadere.util.geometry.shapes.IPoint;
import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.geometry.shapes.VPolygon;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
/**
* @author Benedikt Zoennchen
*/
public interface IPolyConnectivity<P extends IPoint, E extends IHalfEdge<P>, F extends IFace<P>> extends Iterable<F>{
IMesh<P, E, F> getMesh();
default boolean isBoundary(E halfEdge) {
IMesh<P, E, F> mesh = getMesh();
return mesh.isBoundary(halfEdge) || mesh.isBoundary(mesh.getTwin(halfEdge));
}
default Optional<F> locate(final double x, final double y) {
for(F face : getMesh().getFaces()) {
VPolygon polygon = getMesh().toPolygon(face);
if(polygon.contains(new VPoint(x, y))) {
return Optional.of(face);
}
}
return Optional.empty();
}
default Optional<F> locate(final P point) {
return locate(point.getX(), point.getY());
}
default boolean isBoundary(F face) {
return getMesh().getEdges(face).stream().anyMatch(edge -> isBoundary(edge));
}
default void adjustVertex(P vertex){
List<E> edges = getMesh().getEdges(vertex);
edges.stream().filter(edge -> isBoundary(edge)).findAny().ifPresent(edge -> getMesh().setEdge(vertex, edge));
}
default Optional<E> findEdge(P begin, P end) {
IMesh<P, E, F> mesh = getMesh();
return mesh.getNeighbours(mesh.getEdge(begin)).stream().filter(edge -> mesh.getPrev(edge).equals(end)).map(edge -> mesh.getTwin(edge)).findAny();
}
default boolean isSimpleLink(E halfEdge) {
E edge = halfEdge;
E twin = getMesh().getTwin(halfEdge);
F twinFace = getMesh().getFace(twin);
E next = getMesh().getNext(edge);
while (!edge.equals(next)) {
if (twinFace.equals(getMesh().getTwinFace(next))) {
return false;
}
next = getMesh().getNext(next);
}
return true;
}
default boolean isSimpleConnected(F face) {
Set<F> faceSet = new HashSet<>();
E edge = getMesh().getEdge(face);
E next = getMesh().getNext(edge);
faceSet.add(getMesh().getTwinFace(edge));
while (!edge.equals(next)) {
if(faceSet.contains(getMesh().getTwinFace(next))) {
return false;
}
else {
faceSet.add(getMesh().getTwinFace(next));
}
next = getMesh().getNext(next);
}
return true;
}
default void split(F face, P vertex) {
E hend = getMesh().getEdge(face);
E hh = getMesh().getNext(hend);
E hold = getMesh().createEdge(vertex);
E twin = getMesh().createEdge(getMesh().getVertex(hend));
getMesh().setTwin(hold, twin);
getMesh().setNext(hend, hold);
getMesh().setFace(hold, face);
hold = getMesh().getTwin(hold);
while (!hh.equals(hend)) {
E hnext = getMesh().getNext(hh);
F newFace = getMesh().createFace();
getMesh().setEdge(newFace, hh);
E hnew = getMesh().createEdge(vertex);
getMesh().setNext(hnew, hold);
getMesh().setNext(hold, hh);
getMesh().setNext(hh, hnew);
getMesh().setFace(hnew, newFace);
getMesh().setFace(hold, newFace);
getMesh().setFace(hh, newFace);
E hnewTwin = getMesh().createEdge(getMesh().getVertex(hh));
getMesh().setTwin(hnew, hnewTwin);
hold = hnewTwin;
hh = hnext;
}
getMesh().setNext(hold, hend);
getMesh().setNext(getMesh().getNext(hend), hold);
getMesh().setFace(hold, face);
}
}
package org.vadere.util.geometry.mesh;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.tuple.Triple;
import org.jetbrains.annotations.NotNull;
import org.vadere.util.geometry.shapes.IPoint;
import java.util.ArrayList;
import java.util.List;
/**
* @author Benedikt Zoennchen
*
* @param <P>
* @param <E>
* @param <F>
*/
public interface ITriConnectivity<P extends IPoint, E extends IHalfEdge<P>, F extends IFace<P>> extends IPolyConnectivity<P, E, F> {
default void splitTriangleEvent(F face, List<F> faces) {}
default void flipEvent(F f1, F f2) {}
void splitEdgeEvent(List<E> newEdges);
boolean isIllegal(E edge);
/**
* Splits the half-edge at point p, preserving a valid triangulation.
*
* @param p the split point
* @param halfEdge the half-edge which will be split
*/
default List<E> splitEdge(@NotNull P p, @NotNull E halfEdge) {
IMesh<P, E, F> mesh = getMesh();
List<E> newEdges = new ArrayList<>(4);
/*
* Situation: h0 = halfEdge
* h1 -> h2 -> h0
* f0
* o2 <- o1 <- o0
* f3
*
* After splitEdge:
* h0 -> h1 -> t0
* f0
* t1 <- h2 <- e0
* f1
*
* e1 -> o1 -> t2
* f2
* o0 <- o2 <- e2
* f3
*/
//h0,(t0),t1
//e2,(o0,
E h0 = halfEdge;
E o0 = mesh.getTwin(h0);
P v2 = mesh.getVertex(o0);
F f0 = mesh.getFace(h0);
F f3 = mesh.getFace(o0);
// faces correct?
mesh.createEdge(v2, mesh.getFace(o0));
E e1 = mesh.createEdge(v2, mesh.getFace(o0));
E t1 = mesh.createEdge(p, mesh.getFace(h0));
mesh.setTwin(e1, t1);
mesh.setVertex(o0, p);
newEdges.add(t1);
newEdges.add(h0);
if(!mesh.isBoundary(h0)) {
F f1 = mesh.createFace();
E h1 = mesh.getNext(h0);
E h2 = mesh.getNext(h1);
P v1 = mesh.getVertex(h1);
E e0 = mesh.createEdge(v1, f1);
E t0 = mesh.createEdge(p, f0);
mesh.setTwin(e0, t0);
newEdges.add(t0);
mesh.setEdge(f0, h0);
mesh.setEdge(f1, h2);
mesh.setFace(h1, f0);
mesh.setFace(t0, f0);
mesh.setFace(h0, f0);
mesh.setFace(h2, f1);
mesh.setFace(t1, f1);
mesh.setFace(e0, f1);