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 730beb92 authored by Benedikt Zoennchen's avatar Benedikt Zoennchen
Browse files

vornoi intersection computation - not finished jet.

parent ba1a7dd6
...@@ -184,7 +184,7 @@ ...@@ -184,7 +184,7 @@
</executions> </executions>
</plugin> </plugin>
<plugin> <plugin>
<!-- Maven Surefire is used to execute unit tests. --> <!-- Maven Surefire is used to cup unit tests. -->
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
<version>2.19</version> <version>2.19</version>
......
...@@ -137,7 +137,7 @@ public class ClassFinder { ...@@ -137,7 +137,7 @@ public class ClassFinder {
* Scans all classes accessible from the context class loader which belong to the given package * Scans all classes accessible from the context class loader which belong to the given package
* and subpackages. * and subpackages.
* *
* Deprecated since this method is slow if we have to access jar file, which is the case if we execute the project via vadere.jar! * Deprecated since this method is slow if we have to access jar file, which is the case if we cup the project via vadere.jar!
* *
* @param packageName The base package * @param packageName The base package
* @return The classes * @return The classes
......
...@@ -5,7 +5,7 @@ import java.awt.event.ActionEvent; ...@@ -5,7 +5,7 @@ import java.awt.event.ActionEvent;
import org.vadere.gui.topographycreator.model.IDrawPanelModel; import org.vadere.gui.topographycreator.model.IDrawPanelModel;
/** /**
* A ActionBasic is the last action in the decorator pattern which will be execute. * A ActionBasic is the last action in the decorator pattern which will be cup.
* Action: Notify all Observers. * Action: Notify all Observers.
* *
*/ */
......
...@@ -42,7 +42,7 @@ public class ActionMergeObstacles extends TopographyAction { ...@@ -42,7 +42,7 @@ public class ActionMergeObstacles extends TopographyAction {
.collect(Collectors.toList()); .collect(Collectors.toList());
WeilerAtherton weilerAtherton = new WeilerAtherton(polygons); WeilerAtherton weilerAtherton = new WeilerAtherton(polygons);
List<VPolygon> mergedPolygons = weilerAtherton.execute(); List<VPolygon> mergedPolygons = weilerAtherton.cup();
// remove polygon obstacles // remove polygon obstacles
getScenarioPanelModel().removeObstacleIf(obstacle -> getScenarioPanelModel().removeObstacleIf(obstacle ->
......
...@@ -53,6 +53,6 @@ public class EditMergeObstacles extends AbstractUndoableEdit { ...@@ -53,6 +53,6 @@ public class EditMergeObstacles extends AbstractUndoableEdit {
@Override @Override
public String getPresentationName() { public String getPresentationName() {
return "merge obstacles"; return "cup obstacles";
} }
} }
...@@ -78,7 +78,7 @@ ...@@ -78,7 +78,7 @@
</executions> </executions>
</plugin> </plugin>
<plugin> <plugin>
<!-- Maven Surefire is used to execute unit tests. --> <!-- Maven Surefire is used to cup unit tests. -->
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
<version>2.19</version> <version>2.19</version>
......
...@@ -15,9 +15,11 @@ import org.vadere.util.geometry.shapes.VPolygon; ...@@ -15,9 +15,11 @@ import org.vadere.util.geometry.shapes.VPolygon;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
...@@ -125,7 +127,9 @@ public class WeilerAtherton { ...@@ -125,7 +127,9 @@ public class WeilerAtherton {
// compute intersections and add those to the two faces, this implementation is rather slow! // compute intersections and add those to the two faces, this implementation is rather slow!
boolean intersectionFound = true; boolean intersectionFound = true;
int count = 0;
while (intersectionFound) { while (intersectionFound) {
List<PHalfEdge<WeilerPoint>> clippingEdges = clippingMesh.getEdges(clippingFace); List<PHalfEdge<WeilerPoint>> clippingEdges = clippingMesh.getEdges(clippingFace);
List<PHalfEdge<WeilerPoint>> subjectEdges = subjectMesh.getEdges(subjectFace); List<PHalfEdge<WeilerPoint>> subjectEdges = subjectMesh.getEdges(subjectFace);
intersectionFound = false; intersectionFound = false;
...@@ -133,7 +137,6 @@ public class WeilerAtherton { ...@@ -133,7 +137,6 @@ public class WeilerAtherton {
for(PHalfEdge<WeilerPoint> clippingEdge : clippingEdges) { for(PHalfEdge<WeilerPoint> clippingEdge : clippingEdges) {
for(PHalfEdge<WeilerPoint> subjectEdge : subjectEdges) { for(PHalfEdge<WeilerPoint> subjectEdge : subjectEdges) {
Optional<VPoint> optIntersectionPoint = equalIntersectionPoints(subjectEdge, subjectMesh, clippingEdge, clippingMesh); Optional<VPoint> optIntersectionPoint = equalIntersectionPoints(subjectEdge, subjectMesh, clippingEdge, clippingMesh);
if(!optIntersectionPoint.isPresent()) { if(!optIntersectionPoint.isPresent()) {
VLine l1 = subjectMesh.toLine(subjectEdge); VLine l1 = subjectMesh.toLine(subjectEdge);
VLine l2 = clippingMesh.toLine(clippingEdge); VLine l2 = clippingMesh.toLine(clippingEdge);
...@@ -165,6 +168,9 @@ public class WeilerAtherton { ...@@ -165,6 +168,9 @@ public class WeilerAtherton {
PVertex<WeilerPoint> ip1 = IPolyConnectivity.splitEdge(subjectEdge, wp1, subjectMesh); PVertex<WeilerPoint> ip1 = IPolyConnectivity.splitEdge(subjectEdge, wp1, subjectMesh);
PVertex<WeilerPoint> ip2 = IPolyConnectivity.splitEdge(clippingEdge, wp2, clippingMesh); PVertex<WeilerPoint> ip2 = IPolyConnectivity.splitEdge(clippingEdge, wp2, clippingMesh);
subjectMesh.getPoint(ip1).setInside(true);
clippingMesh.getPoint(ip2).setInside(true);
wp1.setTwinPoint(ip2); wp1.setTwinPoint(ip2);
wp2.setTwinPoint(ip1); wp2.setTwinPoint(ip1);
...@@ -263,7 +269,7 @@ public class WeilerAtherton { ...@@ -263,7 +269,7 @@ public class WeilerAtherton {
* *
* @return a list of merged polygons * @return a list of merged polygons
*/ */
public List<VPolygon> execute() { public List<VPolygon> cup() {
boolean merged = true; boolean merged = true;
List<VPolygon> newPolygons = new ArrayList<>(); List<VPolygon> newPolygons = new ArrayList<>();
...@@ -273,17 +279,18 @@ public class WeilerAtherton { ...@@ -273,17 +279,18 @@ public class WeilerAtherton {
int ii = -1; int ii = -1;
int jj = -1; int jj = -1;
merged = false; merged = false;
Pair<VPolygon, VPolygon> mergeResult = null; List<VPolygon> cupResult = null;
for(int i = 0; i < newPolygons.size(); i++) { for(int i = 0; i < newPolygons.size(); i++) {
VPolygon first = newPolygons.get(i); VPolygon first = newPolygons.get(i);
for(int j = i+1; j < newPolygons.size(); j++) { for(int j = i+1; j < newPolygons.size(); j++) {
VPolygon second = newPolygons.get(j); VPolygon second = newPolygons.get(j);
mergeResult = merge(first, second); cupResult = cup(first, second);
assert cupResult.size() <= 2;
// something got merged // something got merged
if(mergeResult.getSecond() == null) { if(cupResult.size() <= 1) {
merged = true; merged = true;
ii = i; ii = i;
jj = j; jj = j;
...@@ -299,7 +306,7 @@ public class WeilerAtherton { ...@@ -299,7 +306,7 @@ public class WeilerAtherton {
if(merged) { if(merged) {
newPolygons.remove(ii); newPolygons.remove(ii);
newPolygons.remove(jj-1); newPolygons.remove(jj-1);
newPolygons.add(mergeResult.getFirst()); newPolygons.add(cupResult.get(0));
} }
} }
...@@ -307,50 +314,159 @@ public class WeilerAtherton { ...@@ -307,50 +314,159 @@ public class WeilerAtherton {
} }
/** /**
* Executes the Weiler-Atherton-Algorithm for two polygons. * Executes the Weiler-Atherton-Algorithm for all of its polygons.
* *
* @param subjectCandidat the first polygon * @return a list of merged polygons
* @param clippingCandidat the second polygon
* @return a pair of polygon where the second element is null if the polygons got merged. This is not the case if there do not overlap.
*/ */
public Pair<VPolygon, VPolygon> merge(@NotNull final VPolygon subjectCandidat, @NotNull final VPolygon clippingCandidat) { public Optional<VPolygon> cap() {
List<VPolygon> newPolygons = new ArrayList<>();
newPolygons.addAll(polygons);
if(polygons.size() == 0) {
return Optional.empty();
}
else if(polygons.size() == 1) {
return Optional.of(polygons.get(0));
}
else {
LinkedList<VPolygon> toDo = new LinkedList<>();
toDo.addAll(polygons);
VPolygon subject = GeometryUtils.isCCW(subjectCandidat) ? subjectCandidat.revertOrder() : subjectCandidat; while (toDo.size() >= 2) {
VPolygon clipping = GeometryUtils.isCCW(clippingCandidat) ? clippingCandidat.revertOrder() : clippingCandidat; VPolygon poly1 = toDo.remove();
VPolygon poly2 = toDo.remove();
List<VPolygon> capResult = cap(poly1, poly2);
if(capResult.isEmpty()) {
return Optional.empty();
}
toDo.addAll(capResult);
}
assert toDo.size() == 1;
return Optional.of(toDo.remove());
}
}
private List<VPolygon> construct(
@NotNull final VPolygon subjectCandidat,
@NotNull final VPolygon clippingCandidat,
final boolean cap) {
//Predicate<WeilerPoint> startEdgeCondition = cap ? p -> p.isInside() : p -> !p.isInside();
VPolygon subject = GeometryUtils.isCCW(subjectCandidat) ? subjectCandidat : subjectCandidat.revertOrder();
VPolygon clipping = GeometryUtils.isCCW(clippingCandidat) ? clippingCandidat : clippingCandidat.revertOrder();
PMesh<WeilerPoint> subjectMesh = new PMesh<>((x,y) -> new WeilerPoint(new VPoint(x,y), false, false)); PMesh<WeilerPoint> subjectMesh = new PMesh<>((x,y) -> new WeilerPoint(new VPoint(x,y), false, false));
PMesh<WeilerPoint> clippingMesh = new PMesh<>((x,y) -> new WeilerPoint(new VPoint(x,y), false, false)); PMesh<WeilerPoint> clippingMesh = new PMesh<>((x,y) -> new WeilerPoint(new VPoint(x,y), false, false));
List<VPolygon> result = new ArrayList<>(2); //List<VPolygon> result = new ArrayList<>(2);
/**
* (1) construct the list connections
*/
Pair<PFace<WeilerPoint>, PFace<WeilerPoint>> pair = constructIntersectionFaces(subject, subjectMesh, clipping, clippingMesh); Pair<PFace<WeilerPoint>, PFace<WeilerPoint>> pair = constructIntersectionFaces(subject, subjectMesh, clipping, clippingMesh);
PFace<WeilerPoint> subjectFace = pair.getFirst(); PFace<WeilerPoint> subjectFace = pair.getFirst();
PFace<WeilerPoint> clippingFace = pair.getSecond(); PFace<WeilerPoint> clippingFace = pair.getSecond();
Set<PHalfEdge<WeilerPoint>> subjectExitingEdges = subjectMesh
.streamEdges(subjectFace)
.filter(edge -> subjectMesh.getPoint(edge).isIntersectionPoint())
.filter(edge -> !subjectMesh.getPoint(subjectMesh.getNext(edge)).isIntersectionPoint() &&
!clipping.contains(subjectMesh.getPoint(subjectMesh.getNext(edge))))
.collect(Collectors.toSet());
Set<PHalfEdge<WeilerPoint>> subjectEnteringEdges = subjectMesh
.streamEdges(subjectFace)
.filter(edge -> subjectMesh.getPoint(edge).isIntersectionPoint())
.filter(edge -> subjectMesh.getPoint(subjectMesh.getNext(edge)).isIntersectionPoint() ||
clipping.contains(subjectMesh.getPoint(subjectMesh.getNext(edge))))
.collect(Collectors.toSet());
List<VPoint> points = new ArrayList<>();
List<VPolygon> polygons = new ArrayList<>();
PMesh<WeilerPoint> mesh = subjectMesh;
Set<PHalfEdge<WeilerPoint>> intersectionSet = cap ? subjectEnteringEdges : subjectExitingEdges;
// cup will preserve the polyons.
if(!cap && intersectionSet.isEmpty()) {
polygons.add(subjectCandidat);
polygons.add(clippingCandidat);
}
while (!intersectionSet.isEmpty()) {
PHalfEdge<WeilerPoint> subjectEdge = intersectionSet.iterator().next();
PHalfEdge<WeilerPoint> next = subjectEdge;
intersectionSet.remove(subjectEdge);
do {
next = mesh.getNext(next);
// adaptPath
if(mesh.getPoint(next).isIntersectionPoint() && !intersectionSet.contains(next)) {
mesh = mesh.equals(subjectMesh) ? clippingMesh : subjectMesh;
next = mesh.getEdge(mesh.getPoint(next).getTwinPoint());
intersectionSet.remove(next);
}
points.add(new VPoint(mesh.getPoint(next)));
} while (!next.equals(subjectEdge));
polygons.add(GeometryUtils.toPolygon(GeometryUtils.filterUselessPoints(points, EPSILON)));
}
return polygons;
/*PFace<WeilerPoint> subjectFace = pair.getFirst();
PFace<WeilerPoint> clippingFace = pair.getSecond();
// phase (2) // phase (2)
Optional<PHalfEdge<WeilerPoint>> intersectionEdges = subjectMesh.findAnyEdge(p -> p.isIntersectionPoint()); Optional<PHalfEdge<WeilerPoint>> intersectionEdges = subjectMesh.findAnyEdge(p -> p.isIntersectionPoint());
Optional<PHalfEdge<WeilerPoint>> optStartPointSub = subjectMesh.findAnyEdge(p -> !p.isIntersectionPoint() && !p.isInside()); Optional<PHalfEdge<WeilerPoint>> optStartPointSub = subjectMesh.findAnyEdge(startEdgeCondition);
Optional<PHalfEdge<WeilerPoint>> optStartPointClip = clippingMesh.findAnyEdge(p -> !p.isIntersectionPoint() && !p.isInside()); Optional<PHalfEdge<WeilerPoint>> optStartPointClip = clippingMesh.findAnyEdge(startEdgeCondition);
Optional<PHalfEdge<WeilerPoint>> subInsideEdge = subjectMesh.findAnyEdge(p -> p.isInside());
Optional<PHalfEdge<WeilerPoint>> clipInsideEdge = clippingMesh.findAnyEdge(p -> p.isInside());
Optional<PHalfEdge<WeilerPoint>> subOutsideEdge = subjectMesh.findAnyEdge(p -> !p.isInside());
Optional<PHalfEdge<WeilerPoint>> clipOutsideEdge = clippingMesh.findAnyEdge(p -> !p.isInside());
// no point intersection and no point is contained in the other polygon => polygons do not overlap at all // no point intersection and no point is contained in the other polygon => polygons do not overlap at all
if(optStartPointSub.isPresent() && optStartPointClip.isPresent() && !intersectionEdges.isPresent()) { if(!subInsideEdge.isPresent() && !clipInsideEdge.isPresent() && !intersectionEdges.isPresent()) {
result.add(subject); // complete merge
result.add(clipping); if(!cap) {
return Pair.create(subject, clipping); return Pair.create(subject, clipping);
} }
else {
return Pair.create(null, null);
}
}
// no point intersections and there is a point of the subject outside of the clipping => clipping is fully contained in subject // no point intersections and there is a point of the subject outside of the clipping => clipping is fully contained in subject
if(optStartPointSub.isPresent() && !intersectionEdges.isPresent()) { if(subOutsideEdge.isPresent() && !intersectionEdges.isPresent()) {
result.add(subject); // cup is the subject
if(!cap) {
return Pair.create(subject, null); return Pair.create(subject, null);
} // cap is the clipping
else {
return Pair.create(clipping, null);
}
} }
// no point intersections and there is a point of the clipping outside of the subject => subject is fully contained in clipping // no point intersections and there is a point of the clipping outside of the subject => subject is fully contained in clipping
if(optStartPointClip.isPresent() && !intersectionEdges.isPresent()) { if(clipOutsideEdge.isPresent() && !intersectionEdges.isPresent()) {
result.add(clipping); // cup is the subject
return pair.create(clipping, null); if(!cap) {
return Pair.create(clipping, null);
} // cap is the clipping
else {
return Pair.create(subject, null);
}
} }
PHalfEdge<WeilerPoint> first = null; PHalfEdge<WeilerPoint> first = null;
...@@ -374,24 +490,61 @@ public class WeilerAtherton { ...@@ -374,24 +490,61 @@ public class WeilerAtherton {
PMesh<WeilerPoint> mesh = mesh1; PMesh<WeilerPoint> mesh = mesh1;
List<VPoint> points = new ArrayList<>(); List<VPoint> points = new ArrayList<>();
int count = 0;
boolean foundDiff = false;
do { do {
next = mesh.getNext(next); count++;
//next = mesh.getNext(next);
WeilerPoint wp = mesh.getPoint(next); WeilerPoint wp = mesh.getPoint(next);
// walk into the other mesh / polygon // walk into the other mesh / polygon
if(wp.isIntersectionPoint()) { if(wp.isIntersectionPoint()) {
// swap meshes // swap meshes
mesh = mesh == mesh1 ? mesh2 : mesh1; mesh = (mesh == mesh1 ? mesh2 : mesh1);
// swap edges // swap edges
next = mesh.getEdge(wp.twinPoint); next = mesh.getEdge(wp.twinPoint);
} }
if(count > 1000) {
System.out.println(count + " (2)");
constructIntersectionFaces(subject, subjectMesh, clipping, clippingMesh);
}
try {
next = mesh.getNext(next);
}
catch (NullPointerException e) {
System.out.println("shit");
}
points.add(new VPoint(wp)); points.add(new VPoint(wp));
if(!points.get(0).equals(mesh.getPoint(next))) {
foundDiff = true;
}
}
while (!foundDiff || !points.get(0).equals(mesh.getPoint(next)));
try{
Pair.create(GeometryUtils.toPolygon(GeometryUtils.filterUselessPoints(points, EPSILON)), null);
}
catch (Exception e) {
System.out.println("baba");
}
return Pair.create(GeometryUtils.toPolygon(GeometryUtils.filterUselessPoints(points, EPSILON)), null);*/
} }
while (!next.equals(first));
return Pair.create(GeometryUtils.toPolygon(GeometryUtils.filterUselessPoints(points, EPSILON)), null); public List<VPolygon> cap(@NotNull final VPolygon subjectCandidat, @NotNull final VPolygon clippingCandidat) {
return construct(subjectCandidat, clippingCandidat, true);
}
/**
* Executes the Weiler-Atherton-Algorithm for two polygons.
*
* @param subjectCandidat the first polygon
* @param clippingCandidat the second polygon
* @return a pair of polygon where the second element is null if the polygons got merged. This is not the case if there do not overlap.
*/
public List<VPolygon> cup(@NotNull final VPolygon subjectCandidat, @NotNull final VPolygon clippingCandidat) {
return construct(subjectCandidat, clippingCandidat, false);
} }
} }
...@@ -491,7 +491,7 @@ public class AMesh<P extends IPoint> implements IMesh<P, AVertex<P>, AHalfEdge<P ...@@ -491,7 +491,7 @@ public class AMesh<P extends IPoint> implements IMesh<P, AVertex<P>, AHalfEdge<P
// clone the old one! // clone the old one!
AMesh<P> cMesh = clone(); AMesh<P> cMesh = clone();
// merge some of them? // cup some of them?
int nullIdentifier = -2; int nullIdentifier = -2;
// rebuild // rebuild
...@@ -554,7 +554,7 @@ public class AMesh<P extends IPoint> implements IMesh<P, AVertex<P>, AHalfEdge<P ...@@ -554,7 +554,7 @@ public class AMesh<P extends IPoint> implements IMesh<P, AVertex<P>, AHalfEdge<P
} }
private void copyFace(@NotNull final AFace<P> face, @NotNull int[] vertexMap, @NotNull int[] edgeMap, @NotNull int[] faceMap, @NotNull final AMesh<P> cMesh) { private void copyFace(@NotNull final AFace<P> face, @NotNull int[] vertexMap, @NotNull int[] edgeMap, @NotNull int[] faceMap, @NotNull final AMesh<P> cMesh) {
// merge some of them? // cup some of them?
int nullIdentifier = -2; int nullIdentifier = -2;
// face not jet copied // face not jet copied
......
...@@ -160,11 +160,13 @@ public interface IPolyConnectivity<P extends IPoint, V extends IVertex<P>, E ext ...@@ -160,11 +160,13 @@ public interface IPolyConnectivity<P extends IPoint, V extends IVertex<P>, E ext
*/ */
static <P extends IPoint, V extends IVertex<P>, E extends IHalfEdge<P>, F extends IFace<P>> V splitEdge( static <P extends IPoint, V extends IVertex<P>, E extends IHalfEdge<P>, F extends IFace<P>> V splitEdge(
@NotNull final E edge, @NotNull P p, @NotNull IMesh<P, V, E, F> mesh) { @NotNull final E edge, @NotNull P p, @NotNull IMesh<P, V, E, F> mesh) {
V u = mesh.createVertex(p);
E twin = mesh.getTwin(edge); E twin = mesh.getTwin(edge);
E prev = mesh.getPrev(edge); E prev = mesh.getPrev(edge);
E tNext = mesh.getNext(twin); E tNext = mesh.getNext(twin);
V u = mesh.createVertex(p);
E e = mesh.createEdge(u); E e = mesh.createEdge(u);
mesh.setFace(e, mesh.getFace(edge)); mesh.setFace(e, mesh.getFace(edge));
E t = mesh.createEdge(mesh.getVertex(twin)); E t = mesh.createEdge(mesh.getVertex(twin));
...@@ -411,10 +413,10 @@ public interface IPolyConnectivity<P extends IPoint, V extends IVertex<P>, E ext ...@@ -411,10 +413,10 @@ public interface IPolyConnectivity<P extends IPoint, V extends IVertex<P>, E ext
* <p>Changes the connectivity.</p> * <p>Changes the connectivity.</p>
* *
* @param face the face * @param face the face
* @param mergeCondition the merge condition * @param mergeCondition the cup condition
* @param deleteIsolatedVertices if true, vertices with degree zero will be removed from the mesh data structure otherwise they will not. * @param deleteIsolatedVertices if true, vertices with degree zero will be removed from the mesh data structure otherwise they will not.
* *
* @return the merge result i.e. the resulting face. * @return the cup result i.e. the resulting face.
*/ */
default Optional<F> mergeFaces(@NotNull final F face, @NotNull final Predicate<F> mergeCondition, final boolean deleteIsolatedVertices) { default Optional<F> mergeFaces(@NotNull final F face, @NotNull final Predicate<F> mergeCondition, final boolean deleteIsolatedVertices) {
return mergeFaces(face, mergeCondition, deleteIsolatedVertices, -1); return mergeFaces(face, mergeCondition, deleteIsolatedVertices, -1);
...@@ -430,11 +432,11 @@ public interface IPolyConnectivity<P extends IPoint, V extends IVertex<P>, E ext ...@@ -430,11 +432,11 @@ public interface IPolyConnectivity<P extends IPoint, V extends IVertex<P>, E ext
* <p>Changes the connectivity.</p> * <p>Changes the connectivity.</p>
* *
* @param face the face * @param face the face
* @param mergeCondition the merge condition * @param mergeCondition the cup condition
* @param deleteIsolatedVertices if true, vertices with degree zero will be removed from the mesh data structure otherwise they will not. * @param deleteIsolatedVertices if true, vertices with degree zero will be removed from the mesh data structure otherwise they will not.
* @param maxDept the maximum dept / neighbouring distance at which faces can be removed * @param maxDept the maximum dept / neighbouring distance at which faces can be removed
* *
* @return the merge result i.e. the resulting face. * @return the cup result i.e. the resulting face.
*/ */
default Optional<F> mergeFaces(@NotNull final F face, @NotNull final Predicate<F> mergeCondition, final boolean deleteIsolatedVertices, final int maxDept) { default Optional<F> mergeFaces(@NotNull final F face, @NotNull final Predicate<F> mergeCondition, final boolean deleteIsolatedVertices, final int maxDept) {
boolean modified = true; boolean modified = true;
...@@ -480,14 +482,14 @@ public interface IPolyConnectivity<P extends IPoint, V extends IVertex<P>, E ext ...@@ -480,14 +482,14 @@ public interface IPolyConnectivity<P extends IPoint, V extends IVertex<P>, E ext