Currently job artifacts in CI/CD pipelines on LRZ GitLab never expire. Starting from Wed 26.1.2022 the default expiration time will be 30 days (GitLab default). Currently existing 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 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);