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 @@
</executions>
</plugin>
<plugin>
<!-- Maven Surefire is used to execute unit tests. -->
<!-- Maven Surefire is used to cup unit tests. -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19</version>
......
......@@ -137,7 +137,7 @@ public class ClassFinder {
* Scans all classes accessible from the context class loader which belong to the given package
* 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
* @return The classes
......
......@@ -5,7 +5,7 @@ import java.awt.event.ActionEvent;
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.
*
*/
......
......@@ -42,7 +42,7 @@ public class ActionMergeObstacles extends TopographyAction {
.collect(Collectors.toList());
WeilerAtherton weilerAtherton = new WeilerAtherton(polygons);
List<VPolygon> mergedPolygons = weilerAtherton.execute();
List<VPolygon> mergedPolygons = weilerAtherton.cup();
// remove polygon obstacles
getScenarioPanelModel().removeObstacleIf(obstacle ->
......
......@@ -53,6 +53,6 @@ public class EditMergeObstacles extends AbstractUndoableEdit {
@Override
public String getPresentationName() {
return "merge obstacles";
return "cup obstacles";
}
}
......@@ -78,7 +78,7 @@
</executions>
</plugin>
<plugin>
<!-- Maven Surefire is used to execute unit tests. -->
<!-- Maven Surefire is used to cup unit tests. -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19</version>
......
......@@ -15,9 +15,11 @@ import org.vadere.util.geometry.shapes.VPolygon;
import java.util.ArrayList;
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;
import java.util.stream.Collectors;
/**
......@@ -125,7 +127,9 @@ public class WeilerAtherton {
// compute intersections and add those to the two faces, this implementation is rather slow!
boolean intersectionFound = true;
int count = 0;
while (intersectionFound) {
List<PHalfEdge<WeilerPoint>> clippingEdges = clippingMesh.getEdges(clippingFace);
List<PHalfEdge<WeilerPoint>> subjectEdges = subjectMesh.getEdges(subjectFace);
intersectionFound = false;
......@@ -133,7 +137,6 @@ public class WeilerAtherton {
for(PHalfEdge<WeilerPoint> clippingEdge : clippingEdges) {
for(PHalfEdge<WeilerPoint> subjectEdge : subjectEdges) {
Optional<VPoint> optIntersectionPoint = equalIntersectionPoints(subjectEdge, subjectMesh, clippingEdge, clippingMesh);
if(!optIntersectionPoint.isPresent()) {
VLine l1 = subjectMesh.toLine(subjectEdge);
VLine l2 = clippingMesh.toLine(clippingEdge);
......@@ -165,6 +168,9 @@ public class WeilerAtherton {
PVertex<WeilerPoint> ip1 = IPolyConnectivity.splitEdge(subjectEdge, wp1, subjectMesh);
PVertex<WeilerPoint> ip2 = IPolyConnectivity.splitEdge(clippingEdge, wp2, clippingMesh);
subjectMesh.getPoint(ip1).setInside(true);
clippingMesh.getPoint(ip2).setInside(true);
wp1.setTwinPoint(ip2);
wp2.setTwinPoint(ip1);
......@@ -263,7 +269,7 @@ public class WeilerAtherton {
*
* @return a list of merged polygons
*/
public List<VPolygon> execute() {
public List<VPolygon> cup() {
boolean merged = true;
List<VPolygon> newPolygons = new ArrayList<>();
......@@ -273,17 +279,18 @@ public class WeilerAtherton {
int ii = -1;
int jj = -1;
merged = false;
Pair<VPolygon, VPolygon> mergeResult = null;
List<VPolygon> cupResult = null;
for(int i = 0; i < newPolygons.size(); i++) {
VPolygon first = newPolygons.get(i);
for(int j = i+1; j < newPolygons.size(); j++) {
VPolygon second = newPolygons.get(j);
mergeResult = merge(first, second);
cupResult = cup(first, second);
assert cupResult.size() <= 2;
// something got merged
if(mergeResult.getSecond() == null) {
if(cupResult.size() <= 1) {
merged = true;
ii = i;
jj = j;
......@@ -299,7 +306,7 @@ public class WeilerAtherton {
if(merged) {
newPolygons.remove(ii);
newPolygons.remove(jj-1);
newPolygons.add(mergeResult.getFirst());
newPolygons.add(cupResult.get(0));
}
}
......@@ -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
* @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.
* @return a list of merged polygons
*/
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;
VPolygon clipping = GeometryUtils.isCCW(clippingCandidat) ? clippingCandidat.revertOrder() : clippingCandidat;
while (toDo.size() >= 2) {
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> 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);
PFace<WeilerPoint> subjectFace = pair.getFirst();
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)
Optional<PHalfEdge<WeilerPoint>> intersectionEdges = subjectMesh.findAnyEdge(p -> p.isIntersectionPoint());
Optional<PHalfEdge<WeilerPoint>> optStartPointSub = subjectMesh.findAnyEdge(p -> !p.isIntersectionPoint() && !p.isInside());
Optional<PHalfEdge<WeilerPoint>> optStartPointClip = clippingMesh.findAnyEdge(p -> !p.isIntersectionPoint() && !p.isInside());
Optional<PHalfEdge<WeilerPoint>> optStartPointSub = subjectMesh.findAnyEdge(startEdgeCondition);
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
if(optStartPointSub.isPresent() && optStartPointClip.isPresent() && !intersectionEdges.isPresent()) {
result.add(subject);
result.add(clipping);
return Pair.create(subject, clipping);
if(!subInsideEdge.isPresent() && !clipInsideEdge.isPresent() && !intersectionEdges.isPresent()) {
// complete merge
if(!cap) {
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
if(optStartPointSub.isPresent() && !intersectionEdges.isPresent()) {
result.add(subject);
return Pair.create(subject, null);
if(subOutsideEdge.isPresent() && !intersectionEdges.isPresent()) {
// cup is the subject
if(!cap) {
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
if(optStartPointClip.isPresent() && !intersectionEdges.isPresent()) {
result.add(clipping);
return pair.create(clipping, null);
if(clipOutsideEdge.isPresent() && !intersectionEdges.isPresent()) {
// cup is the subject
if(!cap) {
return Pair.create(clipping, null);
} // cap is the clipping
else {
return Pair.create(subject, null);
}
}
PHalfEdge<WeilerPoint> first = null;
......@@ -374,24 +490,61 @@ public class WeilerAtherton {
PMesh<WeilerPoint> mesh = mesh1;
List<VPoint> points = new ArrayList<>();
int count = 0;
boolean foundDiff = false;
do {
next = mesh.getNext(next);
count++;
//next = mesh.getNext(next);
WeilerPoint wp = mesh.getPoint(next);
// walk into the other mesh / polygon
if(wp.isIntersectionPoint()) {
// swap meshes
mesh = mesh == mesh1 ? mesh2 : mesh1;
mesh = (mesh == mesh1 ? mesh2 : mesh1);
// swap edges
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));
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");
}
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);
}
return Pair.create(GeometryUtils.toPolygon(GeometryUtils.filterUselessPoints(points, EPSILON)), null);
/**
* 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
// clone the old one!
AMesh<P> cMesh = clone();
// merge some of them?
// cup some of them?
int nullIdentifier = -2;
// rebuild
......@@ -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) {
// merge some of them?
// cup some of them?
int nullIdentifier = -2;
// face not jet copied
......
......@@ -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(
@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 prev = mesh.getPrev(edge);
E tNext = mesh.getNext(twin);
V u = mesh.createVertex(p);
E e = mesh.createEdge(u);
mesh.setFace(e, mesh.getFace(edge));
E t = mesh.createEdge(mesh.getVertex(twin));
......@@ -411,10 +413,10 @@ public interface IPolyConnectivity<P extends IPoint, V extends IVertex<P>, E ext
* <p>Changes the connectivity.</p>
*
* @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.
*
* @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) {
return mergeFaces(face, mergeCondition, deleteIsolatedVertices, -1);
......@@ -430,11 +432,11 @@ public interface IPolyConnectivity<P extends IPoint, V extends IVertex<P>, E ext
* <p>Changes the connectivity.</p>
*
* @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 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) {
boolean modified = true;
......@@ -480,14 +482,14 @@ public interface IPolyConnectivity<P extends IPoint, V extends IVertex<P>, E ext
/**
* Creates a new hole or extends an existing hole by removing neighbouring faces as
* long as the merge condition holds.
* long as the cup condition holds.
*
* Changes the connectivity.
*
* @param face they face which will be transformed into a hole
* @param mergeCondition the merge condition
* @param mergeCondition the cup condition
* @param deleteIsoletedVertices if true isolated vertices, i.e. vertices without any edges, will be removed from the mesh
* @return (optional) the hole or face itself it the face does not fulfill the merge condition
* @return (optional) the hole or face itself it the face does not fulfill the cup condition
* or empty if due to the creation of the hole all faces will be removed!
*/
default Optional<F> createHole(@NotNull final F face, @NotNull final Predicate<F> mergeCondition, final boolean deleteIsoletedVertices) {
......
......@@ -253,7 +253,7 @@ public class EikMesh<P extends EikMeshPoint, V extends IVertex<P>, E extends IHa
//removeTrianglesInsideObstacles();
}
/*public void execute() {
/*public void cup() {
double quality = getQuality();
while (quality < Parameters.qualityMeasurement) {
improve();
......
......@@ -9,10 +9,13 @@ import org.vadere.meshing.mesh.gen.PMesh;
import org.vadere.util.geometry.GeometryUtils;
import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.geometry.shapes.VPolygon;
import org.vadere.util.geometry.shapes.VRectangle;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
......@@ -24,6 +27,18 @@ public class TestWeilerAtherton {
@Before
public void setUp() throws Exception {}
@Test
public void testRectangleIntersection() {
VRectangle rec1 = new VRectangle(0, 0, 5, 5);
VRectangle rec2 = new VRectangle(4, 4, 2, 2);
VRectangle expectedResult = new VRectangle(4,4,1,1);
List<VPolygon> originalList = Arrays.asList(new VPolygon(rec1), new VPolygon(rec2));
WeilerAtherton weilerAtherton = new WeilerAtherton(originalList);
Optional<VPolygon> optPolygon = weilerAtherton.cap();
assertTrue(optPolygon.isPresent());
assertTrue(GeometryUtils.equalsPolygons(new VPolygon(expectedResult), optPolygon.get()));
}
@Test
public void testNoIntersection() {
......@@ -35,13 +50,31 @@ public class TestWeilerAtherton {
originalList.add(poly2);
WeilerAtherton weilerAtherton = new WeilerAtherton(originalList);
List<VPolygon> polygonList = weilerAtherton.execute();
List<VPolygon> polygonList = weilerAtherton.cup();
assertTrue(polygonList.contains(poly1));
assertTrue(polygonList.contains(poly2));
assertTrue(!weilerAtherton.cap().isPresent());
assertEquals(2, polygonList.size());
}
@Test
public void testIntersection() {
VPolygon poly1 = GeometryUtils.toPolygon(new VPoint(0, 0), new VPoint(1, 1), new VPoint(1, -1));
VPolygon poly2 = GeometryUtils.toPolygon(new VPoint(0.3, 0), new VPoint(-1, 1), new VPoint(-1, -1));
List<VPolygon> originalList = new ArrayList<>(2);
originalList.add(poly1);
originalList.add(poly2);
WeilerAtherton weilerAtherton = new WeilerAtherton(originalList);
List<VPolygon> polygonList = weilerAtherton.cup();
Optional<VPolygon> capResult = weilerAtherton.cap();
assertEquals(1, polygonList.size());
assertTrue(capResult.isPresent());
}
@Test
public void testIntersectionFaceConstructionNoIntersections() {
VPolygon poly1 = GeometryUtils.toPolygon(new VPoint(0, 0), new VPoint(1, 1), new VPoint(1, -1));
......
......@@ -51,12 +51,12 @@ public class TestMeshManipulations {
// locate a face / triangle containing (4, 5)
PFace<VPoint> face = triangulation.locateFace(6, 6).get();
// merge faces until infinity, therefore consumes all faces!
// cup faces until infinity, therefore consumes all faces!
Predicate<PFace<VPoint>> mergePredicate = f -> true;
int maxDept = 1;
// since max dept is equal to 1 we merge 4 (the face and its 3 neighbours) triangles into 1 polygon
// since max dept is equal to 1 we cup 4 (the face and its 3 neighbours) triangles into 1 polygon
assertTrue(triangulation.mergeFaces(face, mergePredicate, true, maxDept).isPresent());
// and therefore the number of faces decreases by 3!
......@@ -68,7 +68,7 @@ public class TestMeshManipulations {
// locate a face / triangle containing (4, 5)
PFace<VPoint> face = triangulation.locateFace(4, 5).get();
// merge faces until infinity, therefore consumes all faces!
// cup faces until infinity, therefore consumes all faces!
Predicate<PFace<VPoint>> shrinkCondition = f -> true;
triangulation.shrinkBorder(shrinkCondition, true);
......
......@@ -21,8 +21,16 @@
"processors" : [ 6 ]
}, {
"type" : "org.vadere.simulator.projects.dataprocessing.outputfile.PedestrianIdOutputFile",
"filename" : "bTimeStep.fundamentalDiagram",
"filename" : "bPedestrian.fundamentalDiagram",
"processors" : [ 9 ]
}, {
"type" : "org.vadere.simulator.projects.dataprocessing.outputfile.TimestepOutputFile",
"filename" : "cTimeStep.fundamentalDiagram",
"processors" : [ 11 ]
}, {
"type" : "org.vadere.simulator.projects.dataprocessing.outputfile.TimestepOutputFile",
"filename" : "dTimeStep.fundamentalDiagram",
"processors" : [ 12 ]
} ],
"processors" : [ {
"type" : "org.vadere.simulator.projects.dataprocessing.processor.PedestrianPositionProcessor",
......@@ -102,6 +110,39 @@
"y" : 0.0
}
}
}, {
"type" : "org.vadere.simulator.projects.dataprocessing.processor.PedestrianFundamentalDiagramCProcessor",