diff --git a/CityDoctorParent/CityDoctorModel/pom.xml b/CityDoctorParent/CityDoctorModel/pom.xml
index 2354ab19d548ea33db673f519204cfee747cd009..1b8c32a18c38449bdc40a7c8237b1d058031382f 100644
--- a/CityDoctorParent/CityDoctorModel/pom.xml
+++ b/CityDoctorParent/CityDoctorModel/pom.xml
@@ -58,6 +58,14 @@
org.locationtech.proj4j
proj4j
+
+ org.locationtech.jts
+ jts-core
+
+
+ io.github.earcut4j
+ earcut4j
+
diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/MovedPolygon.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/MovedPolygon.java
index 4019f80215eee08283d9d596b7e564737a0052e0..c05fc4eb9076810bf7767f8af2dabe4a0450ce03 100644
--- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/MovedPolygon.java
+++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/MovedPolygon.java
@@ -39,6 +39,25 @@ public class MovedPolygon {
private MovedRing exteriorRing;
private List innerRings;
+ /**
+ * Moves the polygon by the first exterior vertex. The center of the polygon
+ * will not me the origin, the polygon will just be near the origin. This can
+ * eliviate numeric issues in large calculations.
+ *
+ * @param p the polygon that is moved to the center.
+ * @return the moved polygon.
+ */
+ public static MovedPolygon ofPolygon(Polygon p) {
+ Vector3d movedBy = p.getExteriorRing().getVertices().get(0);
+ MovedPolygon indPoly = new MovedPolygon();
+ indPoly.original = p;
+ indPoly.exteriorRing = MovedRing.ofRing(p.getExteriorRing(), movedBy);
+ for (LinearRing inner : p.getInnerRings()) {
+ indPoly.addInnerRing(MovedRing.ofRing(inner, movedBy));
+ }
+ return indPoly;
+ }
+
public static MovedPolygon ofPolygon(Polygon p, Vector3d movedBy) {
MovedPolygon indPoly = new MovedPolygon();
indPoly.original = p;
diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Polygon2d.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Polygon2d.java
index 6ccf32f3eeb71c03ccf3d4b6efffcc7f98219594..bd766219edecf5514bb521158c5ad048be8e8a58 100644
--- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Polygon2d.java
+++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Polygon2d.java
@@ -40,6 +40,11 @@ public class Polygon2d {
ProjectionAxis axis = ProjectionAxis.of(poly);
return projectTo2D(poly, axis);
}
+
+ public static Polygon2d withProjection(MovedPolygon poly) {
+ ProjectionAxis axis = ProjectionAxis.of(poly.getOriginal());
+ return projectTo2D(poly, axis);
+ }
public static Polygon2d withProjection(MovedPolygon poly, ProjectionAxis projectionAxis) {
return projectTo2D(poly, projectionAxis);
diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Vector3d.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Vector3d.java
index ab5f495feea7441312bd8203cd10da69084d0488..df1486e30fa0109b0eb40bd85bb6e1c4bec8fe45 100644
--- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Vector3d.java
+++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Vector3d.java
@@ -22,6 +22,8 @@ import java.io.Serial;
import java.io.Serializable;
import java.util.Arrays;
+import org.locationtech.jts.geom.Coordinate;
+
/**
* A three dimensional vector
*
@@ -44,6 +46,17 @@ public class Vector3d implements Serializable {
public Vector3d() {
this(0d, 0d, 0d);
}
+
+ /**
+ * Convert JTS Coordinate class to Vector3d.
+ * @param coord JTS Coordinate
+ */
+ public Vector3d(Coordinate coord) {
+ coords = new double[3];
+ coords[0] = coord.getX();
+ coords[1] = coord.getY();
+ coords[2] = coord.getZ();
+ }
public Vector3d(double x, double y, double z) {
coords = new double[3];
diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/tesselation/EarcutTesselator.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/tesselation/EarcutTesselator.java
new file mode 100644
index 0000000000000000000000000000000000000000..c160e081fb1a8e8c0f350cdb249c8a2a15814df2
--- /dev/null
+++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/tesselation/EarcutTesselator.java
@@ -0,0 +1,89 @@
+package de.hft.stuttgart.citydoctor2.tesselation;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
+import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
+import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
+import de.hft.stuttgart.citydoctor2.math.Polygon2d;
+import de.hft.stuttgart.citydoctor2.math.Ring2d;
+import de.hft.stuttgart.citydoctor2.math.Triangle3d;
+import de.hft.stuttgart.citydoctor2.math.Vector2d;
+import earcut4j.Earcut;
+
+/**
+ * Tesselator to create triangles out of polygons. Uses earcut4j implementation.
+ *
+ * @author Matthias Betz
+ *
+ */
+public class EarcutTesselator {
+
+ public static TesselatedPolygon tesselatePolygon(Polygon p) {
+ // sum number of vertices, don't use duplicate last point
+ // assume polygons are closed
+ int nrOfVertices = p.getExteriorRing().getVertices().size() - 1;
+ int[] holeStart = null;
+ if (!p.getInnerRings().isEmpty()) {
+ holeStart = new int[p.getInnerRings().size()];
+ List innerRings = p.getInnerRings();
+ for (int i = 0; i < innerRings.size(); i++) {
+ LinearRing r = innerRings.get(i);
+ holeStart[i] = nrOfVertices;
+ nrOfVertices += r.getVertices().size() - 1;
+ }
+ }
+ // collect vertices
+ // project polygon to 2D space as library is buggy for more than 2 dimensions
+ Polygon2d projectedPolygon = Polygon2d.withProjection(p);
+
+ double[] vertices = new double[nrOfVertices * 2];
+ List vertexObjects = new ArrayList<>();
+ addVerticesToList(p.getExteriorRing(), vertexObjects);
+ for (LinearRing innerRing : p.getInnerRings()) {
+ addVerticesToList(innerRing, vertexObjects);
+ }
+
+ int start = addRingToArray(projectedPolygon.getExterior(), vertices, 0);
+ for (Ring2d innerRing : projectedPolygon.getInteriorRings()) {
+ start = addRingToArray(innerRing, vertices, start);
+ }
+
+ // triangulation
+ List indices = Earcut.earcut(vertices, holeStart, 2);
+ List triangles = new ArrayList<>();
+ if (indices.size() % 3 != 0) {
+ throw new IllegalStateException();
+ }
+ for (int i = 0; i < indices.size(); i = i + 3) {
+ Triangle3d t = new Triangle3d(vertexObjects.get(indices.get(i + 0)),
+ vertexObjects.get(indices.get(i + 1)),
+ vertexObjects.get(indices.get(i + 2)));
+ triangles.add(t);
+ }
+ return new TesselatedPolygon(triangles, p);
+ }
+
+ private static void addVerticesToList(LinearRing ring, List vertexObjects) {
+ List vertices = ring.getVertices();
+ for (int i = 0; i < vertices.size() - 1; i++) {
+ Vertex v = vertices.get(i);
+ vertexObjects.add(v);
+ }
+ }
+
+ private static int addRingToArray(Ring2d ring, double[] vertices, int start) {
+ List ringVertices = ring.getVertices();
+ for (int i = 0; i < ringVertices.size() - 1; i++) {
+ Vector2d v = ringVertices.get(i);
+ vertices[start++] = v.getX();
+ vertices[start++] = v.getY();
+ }
+ return start;
+ }
+
+ private EarcutTesselator() {
+ }
+
+}
diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/tesselation/JoglTesselator.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/tesselation/JoglTesselator.java
index d20c878d73b6b9b702aa2e453a3ff36c3503bf27..a98c330b5cb68851bd5ca60506e63ba086fdcf50 100644
--- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/tesselation/JoglTesselator.java
+++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/tesselation/JoglTesselator.java
@@ -33,7 +33,7 @@ import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
import de.hft.stuttgart.citydoctor2.math.Vector3d;
/**
- * Tesselator to create triangles out of polygons.
+ * Tesselator to create triangles out of polygons. Uses JOGL implementation.
*
* @author Matthias Betz
*
@@ -102,6 +102,10 @@ public class JoglTesselator {
}
public static TesselatedPolygon tesselatePolygon(Polygon p) {
+ return tesselatePolygon(p, true);
+ }
+
+ public static TesselatedPolygon tesselatePolygon(Polygon p, boolean discardDegeneratedTriangles) {
ArrayList vertices = new ArrayList<>();
Vector3d normal = p.calculateNormalNormalized();
synchronized (tess) {
@@ -121,7 +125,7 @@ public class JoglTesselator {
GLU.gluTessEndPolygon(tess);
ArrayList indices = new ArrayList<>();
for (Primitive primitive : primitives) {
- primitive.fillListWithIndices(indices);
+ primitive.fillListWithIndices(indices, discardDegeneratedTriangles);
}
primitives.clear();
return new TesselatedPolygon(vertices, indices, p);
@@ -137,7 +141,7 @@ public class JoglTesselator {
GLU.gluTessEndContour(tess);
}
- public static TesselatedRing tesselateRing(LinearRing r) {
+ public static TesselatedRing tesselateRing(LinearRing r, boolean discardDegeneratedTriangles) {
ArrayList vertices = new ArrayList<>();
Vector3d normal = r.calculateNormal();
synchronized (tess) {
@@ -147,12 +151,16 @@ public class JoglTesselator {
GLU.gluTessEndPolygon(tess);
ArrayList indices = new ArrayList<>();
for (Primitive primitive : primitives) {
- primitive.fillListWithIndices(indices);
+ primitive.fillListWithIndices(indices, discardDegeneratedTriangles);
}
primitives.clear();
return new TesselatedRing(vertices, indices, r);
}
}
+
+ public static TesselatedRing tesselateRing(LinearRing r) {
+ return tesselateRing(r, true);
+ }
private JoglTesselator() {
// only static useage
diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/tesselation/Primitive.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/tesselation/Primitive.java
index 3f59db768d54a9dcb3c1cada8cf4f20572f8c982..4e65d89076bb0cd6da5ca7b52326e00d57b1436a 100644
--- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/tesselation/Primitive.java
+++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/tesselation/Primitive.java
@@ -49,30 +49,34 @@ public class Primitive {
this.type = type;
}
- public void fillListWithIndices(List indices) {
+ public void fillListWithIndices(List indices, boolean discardDegeneratedTriangles) {
switch (type) {
case GL.GL_TRIANGLES:
for (int i = 0; i < pIndices.size(); i += 3) {
- addToListIfAreaNonNull(pIndices.get(i), pIndices.get(i + 1), pIndices.get(i + 2), indices);
+ addToListIfAreaNonNull(pIndices.get(i), pIndices.get(i + 1), pIndices.get(i + 2), indices,
+ discardDegeneratedTriangles);
}
break;
case GL.GL_TRIANGLE_STRIP:
for (int i = 0; i < pIndices.size() - 2; i++) {
if (i % 2 == 0) {
- addToListIfAreaNonNull(pIndices.get(i), pIndices.get(i + 1), pIndices.get(i + 2), indices);
+ addToListIfAreaNonNull(pIndices.get(i), pIndices.get(i + 1), pIndices.get(i + 2), indices,
+ discardDegeneratedTriangles);
} else {
- addToListIfAreaNonNull(pIndices.get(i), pIndices.get(i + 2), pIndices.get(i + 1), indices);
+ addToListIfAreaNonNull(pIndices.get(i), pIndices.get(i + 2), pIndices.get(i + 1), indices,
+ discardDegeneratedTriangles);
}
}
break;
case GL.GL_TRIANGLE_FAN:
Integer first = pIndices.get(0);
for (int i = 0; i < pIndices.size() - 2; i++) {
- addToListIfAreaNonNull(first, pIndices.get(i + 1), pIndices.get(i + 2), indices);
+ addToListIfAreaNonNull(first, pIndices.get(i + 1), pIndices.get(i + 2), indices,
+ discardDegeneratedTriangles);
}
break;
default:
- throw new IllegalStateException("unknown type found: " + type);
+ throw new IllegalStateException("unknown triangle type found: " + type);
}
}
@@ -80,20 +84,21 @@ public class Primitive {
pIndices.add(i);
}
- private void addToListIfAreaNonNull(Integer i1, Integer i2, Integer i3, List indices) {
+ private void addToListIfAreaNonNull(Integer i1, Integer i2, Integer i3, List indices,
+ boolean discardDegeneratedTriangles) {
Vector3d v1 = vertices.get(i1);
Vector3d v2 = vertices.get(i2);
Vector3d v3 = vertices.get(i3);
- double area = Math.abs(calculateAreaOfTriangle(v1, v2, v3));
- if (area > AREA_EPSILON) {
+ if (discardDegeneratedTriangles && Math.abs(calculateAreaOfTriangle(v1, v2, v3)) <= AREA_EPSILON) {
+ // switch to discard degenerated triangles is enabled and triangle has nearly no area
+ logger.trace("Tesselator created degenerated triangle, ignoring");
+ } else {
indices.add(i1);
indices.add(i2);
indices.add(i3);
- } else {
- logger.trace("Tesselator created degenerated triangle, ignoring");
}
}
-
+
/**
* Calculates the area of a triangle given by the 3 points
*
diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/PolygonIntersection.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/PolygonIntersection.java
index 62f9b877aea4dd7857f0120beaba8c943b58d5db..8b23003d2ef7152723c5085c6c551d246d2d5dfa 100644
--- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/PolygonIntersection.java
+++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/PolygonIntersection.java
@@ -25,6 +25,7 @@ import java.util.List;
import de.hft.stuttgart.citydoctor2.datastructure.ConcretePolygon;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import de.hft.stuttgart.citydoctor2.math.Segment3d;
+import de.hft.stuttgart.citydoctor2.math.Triangle3d;
/**
* Result of a polygon polygon intersection.
@@ -38,7 +39,7 @@ public class PolygonIntersection implements Serializable {
private static final long serialVersionUID = -6301963226688351725L;
public enum IntersectionType {
- NONE, LINE, POLYGON
+ NONE, LINE, POLYGON, TRIANGLES
}
private final IntersectionType type;
@@ -47,10 +48,30 @@ public class PolygonIntersection implements Serializable {
private Polygon p1;
private Polygon p2;
+
+ private Triangle3d t1;
+ private Triangle3d t2;
public static PolygonIntersection none() {
return new PolygonIntersection(IntersectionType.NONE);
}
+
+
+ public static PolygonIntersection triangles(Triangle3d t1, Triangle3d t2) {
+ PolygonIntersection poly = new PolygonIntersection(IntersectionType.TRIANGLES);
+ poly.p1 = t1.getPartOf().getOriginal();
+ poly.p2 = t2.getPartOf().getOriginal();
+ poly.t1 = t1;
+ poly.t2 = t2;
+ return poly;
+ }
+
+ public static PolygonIntersection any(Polygon p1, Polygon p2) {
+ PolygonIntersection poly = new PolygonIntersection(IntersectionType.POLYGON);
+ poly.p1 = p1;
+ poly.p2 = p2;
+ return poly;
+ }
public static PolygonIntersection lines(List lines, Polygon p1, Polygon p2) {
PolygonIntersection poly = new PolygonIntersection(IntersectionType.LINE);
@@ -75,6 +96,14 @@ public class PolygonIntersection implements Serializable {
public Polygon getP2() {
return p2;
}
+
+ public Triangle3d getT1() {
+ return t1;
+ }
+
+ public Triangle3d getT2() {
+ return t2;
+ }
private PolygonIntersection(IntersectionType type) {
this.type = type;
diff --git a/CityDoctorParent/CityDoctorModel/src/main/resources/CityDoctorLocalization.properties b/CityDoctorParent/CityDoctorModel/src/main/resources/CityDoctorLocalization.properties
index ddba2444a0e7b17ccb89ea6b0eb324fe2e585fa5..be6dc1cb7827abc21d06ff6ea4eedc779cd6eee7 100644
--- a/CityDoctorParent/CityDoctorModel/src/main/resources/CityDoctorLocalization.properties
+++ b/CityDoctorParent/CityDoctorModel/src/main/resources/CityDoctorLocalization.properties
@@ -119,4 +119,13 @@ OpenFileDialog.loadFailed=Failed to load CityGML File
MainWindow.memoryLabel=Memory:
CheckDialog.checksReenabledAlert=Some checks have been reenabled so that other wanted checks can be executed\nSee the log for more information.
MainWindow.availableLabel=Available:
-OpenFileDialog.lowMemoryLabel=Low Memory Consumption Mode
\ No newline at end of file
+OpenFileDialog.lowMemoryLabel=Low Memory Consumption Mode
+ErrorItemVisitor.intersection=Intersection
+ErrorItemVisitor.component=Component
+ErrorItemVisitor.nameOfAttribute=Name of attribute
+ErrorItemVisitor.childId=Child id
+ErrorItemVisitor.distance=Distance
+ErrorItemVisitor.pointTouchesEdge=Point touches edge
+ErrorItemVisitor.degeneratedRing=Degenerated ring
+ErrorItemVisitor.deviation=Deviation
+ErrorItemVisitor.triangles=Triangles
\ No newline at end of file
diff --git a/CityDoctorParent/CityDoctorModel/src/main/resources/CityDoctorLocalization_de.properties b/CityDoctorParent/CityDoctorModel/src/main/resources/CityDoctorLocalization_de.properties
index b93a1419fd7c859b8da3210dbafd579b8d424eb5..a1a556493019c8721283ed5f84137a3893021448 100644
--- a/CityDoctorParent/CityDoctorModel/src/main/resources/CityDoctorLocalization_de.properties
+++ b/CityDoctorParent/CityDoctorModel/src/main/resources/CityDoctorLocalization_de.properties
@@ -117,4 +117,13 @@ OpenFileDialog.loadFailed=Konnte CityGML Datei nicht laden
MainWindow.memoryLabel=Speicher:
CheckDialog.checksReenabledAlert=Manche Pr\u00fcfungen wurden reaktiviert damit andere gewollte Pr\u00fcfungen durchgef\u00fchrt werden k\u00f6nnen\nMehr Details sind im Log geschrieben
MainWindow.availableLabel=Verf\u00fcgbar:
-OpenFileDialog.lowMemoryLabel=Reduzierter Speicherverbrauchsmodus
\ No newline at end of file
+OpenFileDialog.lowMemoryLabel=Reduzierter Speicherverbrauchsmodus
+ErrorItemVisitor.intersection=Verschneidung
+ErrorItemVisitor.component=Komponente
+ErrorItemVisitor.nameOfAttribute=Name des Attributs
+ErrorItemVisitor.childId=Kind ID
+ErrorItemVisitor.distance=Distanz
+ErrorItemVisitor.pointTouchesEdge=Punkt ber\u00fchrt Kante
+ErrorItemVisitor.degeneratedRing=Degenerierter Ring
+ErrorItemVisitor.deviation=Abweichung
+ErrorItemVisitor.triangles=Dreiecke
\ No newline at end of file
diff --git a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/geometry/SolidSelfIntCheck.java b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/geometry/SolidSelfIntCheck.java
index 6a373f92c68c65a699197625b67369e177e82e06..01162cd05bbf9aa5b8fafec6b81721ad89b3f5bd 100644
--- a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/geometry/SolidSelfIntCheck.java
+++ b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/geometry/SolidSelfIntCheck.java
@@ -27,19 +27,16 @@ import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.CheckResult;
-import de.hft.stuttgart.citydoctor2.check.RequirementType;
import de.hft.stuttgart.citydoctor2.check.GeometrySelfIntersection;
import de.hft.stuttgart.citydoctor2.check.Requirement;
+import de.hft.stuttgart.citydoctor2.check.RequirementType;
import de.hft.stuttgart.citydoctor2.check.ResultStatus;
import de.hft.stuttgart.citydoctor2.check.error.SolidSelfIntError;
import de.hft.stuttgart.citydoctor2.checks.util.CollectionUtils;
import de.hft.stuttgart.citydoctor2.checks.util.SelfIntersectionUtil;
-import de.hft.stuttgart.citydoctor2.datastructure.ConcretePolygon;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.datastructure.GeometryType;
-import de.hft.stuttgart.citydoctor2.math.Segment3d;
import de.hft.stuttgart.citydoctor2.utils.PolygonIntersection;
-import de.hft.stuttgart.citydoctor2.utils.PolygonIntersection.IntersectionType;
/**
* Check for self intersecting solids
@@ -78,7 +75,8 @@ public class SolidSelfIntCheck extends Check {
return;
}
CheckResult cr;
- List intersections = SelfIntersectionUtil.doesSolidSelfIntersect2(g);
+ List intersections = SelfIntersectionUtil.calculateSolidSelfIntersection(g);
+// List intersections = SelfIntersectionUtil.doesSolidSelfIntersect2(g);
if (intersections.isEmpty()) {
cr = new CheckResult(this, ResultStatus.OK, null);
} else {
diff --git a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/util/SelfIntersectionUtil.java b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/util/SelfIntersectionUtil.java
index a68b0b4b5fc5b8926cb52ca9064aa47d0a14880f..602eb04545a19a7052a10e30eda1f7f72d45a1ca 100644
--- a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/util/SelfIntersectionUtil.java
+++ b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/util/SelfIntersectionUtil.java
@@ -62,6 +62,7 @@ import de.hft.stuttgart.citydoctor2.math.Segment3d;
import de.hft.stuttgart.citydoctor2.math.Triangle3d;
import de.hft.stuttgart.citydoctor2.math.Vector2d;
import de.hft.stuttgart.citydoctor2.math.Vector3d;
+import de.hft.stuttgart.citydoctor2.tesselation.EarcutTesselator;
import de.hft.stuttgart.citydoctor2.tesselation.JoglTesselator;
import de.hft.stuttgart.citydoctor2.tesselation.TesselatedPolygon;
import de.hft.stuttgart.citydoctor2.utils.PolygonIntersection;
@@ -75,15 +76,33 @@ import de.hft.stuttgart.citydoctor2.utils.PolygonIntersection.IntersectionType;
*/
public class SelfIntersectionUtil {
-
private static final Logger logger = LogManager.getLogger(SelfIntersectionUtil.class);
-
+
private static final GeometryFactory factory = new GeometryFactory(new PrecisionModel(PrecisionModel.FLOATING));
private SelfIntersectionUtil() {
}
+ public static List calculateSolidSelfIntersection(Geometry g) {
+ List tesselatedPolygons = new ArrayList<>();
+ for (Polygon p : g.getPolygons()) {
+ tesselatedPolygons.add(EarcutTesselator.tesselatePolygon(p));
+ }
+ List intersections = new ArrayList<>();
+ for (int i = 0; i < tesselatedPolygons.size() - 1; i++) {
+ TesselatedPolygon p1 = tesselatedPolygons.get(i);
+ for (int j = i + 1; j < tesselatedPolygons.size(); j++) {
+ TesselatedPolygon p2 = tesselatedPolygons.get(j);
+ GeometrySelfIntersection intersection = doPolygonsIntersect(p1, p2);
+ if (intersection != null) {
+ intersections.add(PolygonIntersection.triangles(intersection.t1(), intersection.t2()));
+ }
+ }
+ }
+ return intersections;
+ }
+
public static GeometrySelfIntersection doesSolidSelfIntersect(Geometry g) {
return selfIntersectionJava(g);
}
@@ -114,14 +133,15 @@ public class SelfIntersectionUtil {
return intersections;
}
- private static void performEdgeSelfIntersection(List intersections, Map edgePolyMap,
- Polygon p1, Polygon p2) {
+ private static void performEdgeSelfIntersection(List intersections,
+ Map edgePolyMap, Polygon p1, Polygon p2) {
EdgePolygon edgeP1 = edgePolyMap.get(p1);
EdgePolygon edgeP2 = edgePolyMap.get(p2);
- List results = IntersectPlanarPolygons.intersectPolygons(edgeP1, edgeP2, 0.000001, 0.001);
+ List results = IntersectPlanarPolygons.intersectPolygons(edgeP1, edgeP2, 0.000001,
+ 0.001);
if (!results.isEmpty()) {
// at least one intersection happened
- for (PolygonPolygonIntersection result: results) {
+ for (PolygonPolygonIntersection result : results) {
// Ensure that Intersection-Edge is not a Null-Line.
// If it is a Null-Line, detected Intersection is a False-Positive.
if (!result.getPolyLine().isNullLine()) {
diff --git a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/checks/util/GeometryTestUtils.java b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/checks/util/GeometryTestUtils.java
index 0c4db51a209d6003b4d4923dbbd20d7a26ca1ac7..9a8e56ba8c110f6c8334a8d0c3a127924850d329 100644
--- a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/checks/util/GeometryTestUtils.java
+++ b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/checks/util/GeometryTestUtils.java
@@ -21,6 +21,7 @@ package de.hft.stuttgart.citydoctor2.checks.util;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.StringJoiner;
import de.hft.stuttgart.citydoctor2.datastructure.ConcretePolygon;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/ListErrorVisitor.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/ListErrorVisitor.java
index 65b7cc10bb7303e0d841cd22335782c29af9fb17..ae8c3112f9c2434cc53829ef38b315e666535ede 100644
--- a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/ListErrorVisitor.java
+++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/ListErrorVisitor.java
@@ -43,6 +43,7 @@ import de.hft.stuttgart.citydoctor2.check.error.UnknownCheckError;
import de.hft.stuttgart.citydoctor2.datastructure.Edge;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
+import de.hft.stuttgart.citydoctor2.utils.PolygonIntersection;
import javafx.scene.paint.Color;
public class ListErrorVisitor implements ErrorVisitor {
@@ -171,7 +172,11 @@ public class ListErrorVisitor implements ErrorVisitor {
@Override
public void visit(SolidSelfIntError err) {
- // nothing to display for now
+ controller.clearHighlights();
+ for (PolygonIntersection intersection : err.getIntersections()) {
+ controller.addHighlight(intersection.getP1(), geom);
+ controller.addHighlight(intersection.getP2(), geom);
+ }
}
@Override
@@ -208,22 +213,22 @@ public class ListErrorVisitor implements ErrorVisitor {
@Override
public void visit(NotCeilingError err) {
- // nothing to display
+ controller.highlight(err.getPolygon(), geom);
}
@Override
public void visit(NotFloorError err) {
- // nothing to display
+ controller.highlight(err.getPolygon(), geom);
}
@Override
public void visit(NotWallError err) {
- // nothing to display
+ controller.highlight(err.getPolygon(), geom);
}
@Override
public void visit(NotGroundError err) {
- // nothing to display
+ controller.highlight(err.getPolygon(), geom);
}
@Override
diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/ErrorItemVisitor.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/ErrorItemVisitor.java
index 52fb5a4b8b7051712e9952ff103884ee1f859520..d28cca5eb34404b17232085c5ed1ba4ae7d95c03 100644
--- a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/ErrorItemVisitor.java
+++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/ErrorItemVisitor.java
@@ -39,16 +39,23 @@ import de.hft.stuttgart.citydoctor2.check.error.SurfaceUnfragmentedError;
import de.hft.stuttgart.citydoctor2.check.error.DegeneratedRingError;
import de.hft.stuttgart.citydoctor2.check.error.TooFewPolygonsError;
import de.hft.stuttgart.citydoctor2.check.error.UnknownCheckError;
+import de.hft.stuttgart.citydoctor2.datastructure.ConcretePolygon;
import de.hft.stuttgart.citydoctor2.datastructure.Edge;
+import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
+import de.hft.stuttgart.citydoctor2.datastructure.LinearRing.LinearRingType;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
import de.hft.stuttgart.citydoctor2.gui.CheckStatus;
+import de.hft.stuttgart.citydoctor2.math.Triangle3d;
+import de.hft.stuttgart.citydoctor2.utils.Localization;
+import de.hft.stuttgart.citydoctor2.utils.PolygonIntersection;
+import de.hft.stuttgart.citydoctor2.utils.PolygonIntersection.IntersectionType;
import javafx.scene.control.TreeItem;
public class ErrorItemVisitor implements ErrorVisitor {
-
- private static final String NAME_OF_ATTRIBUTE = "Name of Attribute: ";
- private static final String CHILD_ID = "ChildId: ";
+
+ private static String nameOfAttribute = Localization.getText("ErrorItemVisitor.nameOfAttribute") + ": ";
+ private static String childId = Localization.getText("ErrorItemVisitor.childId") + ": ";
private final TreeItem root;
public ErrorItemVisitor(TreeItem root) {
@@ -74,7 +81,7 @@ public class ErrorItemVisitor implements ErrorVisitor {
@Override
public void visit(MultipleConnectedComponentsError err) {
for (int i = 0; i < err.getComponents().size(); i++) {
- TextNode textNode = new TextNode("Component " + i);
+ TextNode textNode = new TextNode(Localization.getText("ErrorItemVisitor.component") + " " + i);
TreeItem textItem = new TreeItem<>(textNode);
root.getChildren().add(textItem);
List component = err.getComponents().get(i);
@@ -99,7 +106,7 @@ public class ErrorItemVisitor implements ErrorVisitor {
TreeItem vertexItem = new TreeItem<>(vertexNode);
root.getChildren().add(vertexItem);
for (int i = 0; i < err.getComponents().size(); i++) {
- TextNode textNode = new TextNode("Component " + i);
+ TextNode textNode = new TextNode(Localization.getText("ErrorItemVisitor.component") + " " + i);
TreeItem textItem = new TreeItem<>(textNode);
root.getChildren().add(textItem);
List component = err.getComponents().get(i);
@@ -144,7 +151,7 @@ public class ErrorItemVisitor implements ErrorVisitor {
@Override
public void visit(UnknownCheckError err) {
// not displayed
-
+
}
@Override
@@ -159,11 +166,11 @@ public class ErrorItemVisitor implements ErrorVisitor {
LinearRingNode ringNode = new LinearRingNode(err.getRing(), CheckStatus.NOT_CHECKED);
TreeItem ringItem = new TreeItem<>(ringNode);
root.getChildren().add(ringItem);
-
+
VertexNode vertexNode = new VertexNode(err.getVertex1());
TreeItem vertexItem = new TreeItem<>(vertexNode);
root.getChildren().add(vertexItem);
-
+
vertexNode = new VertexNode(err.getVertex2());
vertexItem = new TreeItem<>(vertexNode);
root.getChildren().add(vertexItem);
@@ -193,7 +200,7 @@ public class ErrorItemVisitor implements ErrorVisitor {
LinearRingNode ringNode = new LinearRingNode(err.getRing(), CheckStatus.NOT_CHECKED);
TreeItem ringItem = new TreeItem<>(ringNode);
root.getChildren().add(ringItem);
-
+
if (err.getRing().getGmlId().isGenerated()) {
PolygonNode polyNode = new PolygonNode(err.getRing().getParent(), CheckStatus.NOT_CHECKED);
TreeItem polyItem = new TreeItem<>(polyNode);
@@ -206,8 +213,9 @@ public class ErrorItemVisitor implements ErrorVisitor {
PolygonNode polyNode = new PolygonNode(err.getPolygon(), CheckStatus.NOT_CHECKED);
TreeItem polyItem = new TreeItem<>(polyNode);
root.getChildren().add(polyItem);
-
- TextNode textNode = new TextNode("Deviation: " + err.getDeviation());
+
+ TextNode textNode = new TextNode(
+ Localization.getText("ErrorItemVisitor.deviation") + ": " + err.getDeviation());
TreeItem textItem = new TreeItem<>(textNode);
root.getChildren().add(textItem);
}
@@ -217,15 +225,16 @@ public class ErrorItemVisitor implements ErrorVisitor {
PolygonNode polyNode = new PolygonNode(err.getPolygon(), CheckStatus.NOT_CHECKED);
TreeItem polyItem = new TreeItem<>(polyNode);
root.getChildren().add(polyItem);
-
+
VertexNode vertexNode = new VertexNode(err.getVertex());
TreeItem vertexItem = new TreeItem<>(vertexNode);
root.getChildren().add(vertexItem);
-
- TextNode textNode = new TextNode("Distance: " + err.getDistance() + "m");
+
+ TextNode textNode = new TextNode(
+ Localization.getText("ErrorItemVisitor.distance") + ": " + err.getDistance() + "m");
TreeItem textItem = new TreeItem<>(textNode);
root.getChildren().add(textItem);
-
+
}
@Override
@@ -237,18 +246,54 @@ public class ErrorItemVisitor implements ErrorVisitor {
@Override
public void visit(SolidSelfIntError err) {
- PolygonNode polyNode1 = new PolygonNode(err.getIntersections().get(0).getP1(), CheckStatus.NOT_CHECKED);
- TreeItem polyItem1 = new TreeItem<>(polyNode1);
- root.getChildren().add(polyItem1);
- PolygonNode polyNode2 = new PolygonNode(err.getIntersections().get(0).getP2(), CheckStatus.NOT_CHECKED);
- TreeItem polyItem2 = new TreeItem<>(polyNode2);
- root.getChildren().add(polyItem2);
+ List intersections = err.getIntersections();
+ for (int i = 0; i < intersections.size(); i++) {
+ PolygonIntersection pi = intersections.get(i);
+ TextNode intersectionNode = new TextNode(Localization.getText("ErrorItemVisitor.intersection") + " " + i);
+ TreeItem intersectionItem = new TreeItem<>(intersectionNode);
+ root.getChildren().add(intersectionItem);
+
+ PolygonNode polyNode1 = new PolygonNode(pi.getP1(), CheckStatus.NOT_CHECKED);
+ TreeItem polyItem1 = new TreeItem<>(polyNode1);
+ intersectionItem.getChildren().add(polyItem1);
+ PolygonNode polyNode2 = new PolygonNode(pi.getP2(), CheckStatus.NOT_CHECKED);
+ TreeItem polyItem2 = new TreeItem<>(polyNode2);
+ intersectionItem.getChildren().add(polyItem2);
+ PolygonIntersection intersection = err.getIntersections().get(0);
+ if (intersection.getType() == IntersectionType.TRIANGLES) {
+ TextNode trianglesNode = new TextNode(Localization.getText("ErrorItemVisitor.triangles"));
+ TreeItem trianglesItem = new TreeItem<>(trianglesNode);
+ intersectionItem.getChildren().add(trianglesItem);
+
+ ConcretePolygon c = createPolygonForTriangle(intersection.getT1());
+ PolygonNode pN1 = new PolygonNode(c, CheckStatus.NOT_CHECKED);
+ TreeItem pI1 = new TreeItem<>(pN1);
+ trianglesItem.getChildren().add(pI1);
+
+ ConcretePolygon c2 = createPolygonForTriangle(intersection.getT2());
+ PolygonNode pN2 = new PolygonNode(c2, CheckStatus.NOT_CHECKED);
+ TreeItem pI2 = new TreeItem<>(pN2);
+ trianglesItem.getChildren().add(pI2);
+ }
+ }
+ }
+
+ private ConcretePolygon createPolygonForTriangle(Triangle3d t) {
+ ConcretePolygon c = new ConcretePolygon();
+ LinearRing extRing = new LinearRing(LinearRingType.EXTERIOR);
+ Vertex start = new Vertex(t.getP1());
+ extRing.getVertices().add(start);
+ extRing.getVertices().add(new Vertex(t.getP2()));
+ extRing.getVertices().add(new Vertex(t.getP3()));
+ extRing.getVertices().add(start);
+ c.setExteriorRing(extRing);
+ return c;
}
@Override
public void visit(TooFewPolygonsError err) {
// not displayed
-
+
}
@Override
@@ -256,11 +301,11 @@ public class ErrorItemVisitor implements ErrorVisitor {
LinearRingNode ringNode = new LinearRingNode(err.getRing(), CheckStatus.NOT_CHECKED);
TreeItem ringItem = new TreeItem<>(ringNode);
root.getChildren().add(ringItem);
-
+
VertexNode vertexNode = new VertexNode(err.getVertex1());
TreeItem vertexItem = new TreeItem<>(vertexNode);
root.getChildren().add(vertexItem);
-
+
vertexNode = new VertexNode(err.getVertex2());
vertexItem = new TreeItem<>(vertexNode);
root.getChildren().add(vertexItem);
@@ -272,11 +317,11 @@ public class ErrorItemVisitor implements ErrorVisitor {
LinearRingNode ringNode = new LinearRingNode(err.getRing(), CheckStatus.NOT_CHECKED);
TreeItem ringItem = new TreeItem<>(ringNode);
root.getChildren().add(ringItem);
-
+
EdgeNode edgeNode = new EdgeNode(err.getEdge1());
TreeItem edgeItem = new TreeItem<>(edgeNode);
root.getChildren().add(edgeItem);
-
+
EdgeNode edge2Node = new EdgeNode(err.getEdge2());
TreeItem edge2Item = new TreeItem<>(edge2Node);
root.getChildren().add(edge2Item);
@@ -288,18 +333,18 @@ public class ErrorItemVisitor implements ErrorVisitor {
@Override
public void visit(PointTouchesEdgeError err) {
- TextNode textNode = new TextNode("Point touches edge");
+ TextNode textNode = new TextNode(Localization.getText("ErrorItemVisitor.pointTouchesEdge"));
TreeItem textItem = new TreeItem<>(textNode);
root.getChildren().add(textItem);
-
+
VertexNode vertexNode = new VertexNode(err.getVertex());
TreeItem vertexItem = new TreeItem<>(vertexNode);
root.getChildren().add(vertexItem);
-
+
EdgeNode edgeNode = new EdgeNode(err.getEdge());
TreeItem edgeItem = new TreeItem<>(edgeNode);
root.getChildren().add(edgeItem);
-
+
LinearRingNode ringNode = new LinearRingNode(err.getRing(), CheckStatus.NOT_CHECKED);
TreeItem ringItem = new TreeItem<>(ringNode);
root.getChildren().add(ringItem);
@@ -337,7 +382,7 @@ public class ErrorItemVisitor implements ErrorVisitor {
public void visit(CheckError err) {
// not used
}
-
+
@Override
public void visit(SchematronError err) {
TextNode textNode = new TextNode(err.getErrorIdString());
@@ -347,17 +392,18 @@ public class ErrorItemVisitor implements ErrorVisitor {
@Override
public void visit(SurfaceUnfragmentedError err) {
- TextNode textNode = new TextNode("Deviation: " + err.getAngleDeviation());
+ TextNode textNode = new TextNode(
+ Localization.getText("ErrorItemVisitor.deviation") + ": " + err.getAngleDeviation());
TreeItem textItem = new TreeItem<>(textNode);
root.getChildren().add(textItem);
}
@Override
public void visit(DegeneratedRingError err) {
- TextNode textNode = new TextNode("Type: degenerated ring");
+ TextNode textNode = new TextNode(Localization.getText("ErrorItemVisitor.degeneratedRing"));
TreeItem textItem = new TreeItem<>(textNode);
root.getChildren().add(textItem);
-
+
LinearRingNode polyNode = new LinearRingNode(err.getRing(), CheckStatus.NOT_CHECKED);
TreeItem polyItem = new TreeItem<>(polyNode);
root.getChildren().add(polyItem);
@@ -366,11 +412,11 @@ public class ErrorItemVisitor implements ErrorVisitor {
@Override
public void visit(AttributeMissingError err) {
if (!err.getChildId().isEmpty()) {
- TextNode textNode = new TextNode(CHILD_ID + err.getChildId());
+ TextNode textNode = new TextNode(childId + err.getChildId());
TreeItem textItem = new TreeItem<>(textNode);
root.getChildren().add(textItem);
}
- TextNode nameNode = new TextNode(NAME_OF_ATTRIBUTE + err.getNameOfAttribute());
+ TextNode nameNode = new TextNode(nameOfAttribute + err.getNameOfAttribute());
TreeItem nameItem = new TreeItem<>(nameNode);
root.getChildren().add(nameItem);
@@ -379,23 +425,23 @@ public class ErrorItemVisitor implements ErrorVisitor {
@Override
public void visit(AttributeValueWrongError err) {
if (!err.getChildId().isEmpty()) {
- TextNode textNode = new TextNode(CHILD_ID + err.getChildId());
+ TextNode textNode = new TextNode(childId + err.getChildId());
TreeItem textItem = new TreeItem<>(textNode);
root.getChildren().add(textItem);
}
- TextNode nameNode = new TextNode(NAME_OF_ATTRIBUTE + err.getNameOfAttribute());
+ TextNode nameNode = new TextNode(nameOfAttribute + err.getNameOfAttribute());
TreeItem nameItem = new TreeItem<>(nameNode);
root.getChildren().add(nameItem);
}
-
+
@Override
public void visit(AttributeInvalidError err) {
if (!err.getChildId().isEmpty()) {
- TextNode textNode = new TextNode(CHILD_ID + err.getChildId());
+ TextNode textNode = new TextNode(childId + err.getChildId());
TreeItem textItem = new TreeItem<>(textNode);
root.getChildren().add(textItem);
}
- TextNode nameNode = new TextNode(NAME_OF_ATTRIBUTE + err.getNameOfAttribute());
+ TextNode nameNode = new TextNode(nameOfAttribute + err.getNameOfAttribute());
TreeItem nameItem = new TreeItem<>(nameNode);
root.getChildren().add(nameItem);
}
diff --git a/CityDoctorParent/pom.xml b/CityDoctorParent/pom.xml
index d037089435eacd67f7b66f1abf16f7908216b132..be26e9b0be37f21c88c6ee3e769cb69fcecf9188 100644
--- a/CityDoctorParent/pom.xml
+++ b/CityDoctorParent/pom.xml
@@ -1,278 +1,282 @@
-
- 4.0.0
- de.hft.stuttgart
- CityDoctorParent
- 3.16.0
- pom
- CityDoctorParent
-
- UTF-8
- 17
- 17
- 2.18.0
- ${project.version}
- ${project.baseUri}../non-maven-libs
- 17.0.10
- ${jre-version-short}+13
- 17.0.12
-
-
-
- non-maven-libs
- ${nonMavenLibsPath}
-
-
- sonartype
- https://oss.sonatype.org/content/repositories/snapshots/
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
- 2.22.0
-
- false
-
- **/SolidSelfIntCheckFalsePositiveBigMeshTest.java
-
-
-
-
-
-
-
- maven-compiler-plugin
- 3.13.0
-
- true
- true
-
-
-
- org.codehaus.plexus
- plexus-compiler-api
- 2.15.0
-
-
- org.codehaus.plexus
- plexus-compiler-manager
- 2.15.0
-
-
- org.codehaus.plexus
- plexus-compiler-eclipse
- 2.15.0
-
-
- org.openjfx
- javafx-maven-plugin
- 0.0.8
-
-
-
-
-
-
- org.openjfx
- javafx-controls
- ${jfx-version}
-
-
- org.openjfx
- javafx-fxml
- ${jfx-version}
-
-
- org.openjfx
- javafx-swing
- ${jfx-version}
-
-
- de.hft.stuttgart
- CityDoctorModel
- ${revision}
-
-
- de.hft.stuttgart
- CityDoctorAutoPro
- ${revision}
-
-
- de.hft.stuttgart
- CityDoctorValidation
- ${revision}
-
-
- de.hft.stuttgart
- CityDoctorGUI
- ${revision}
-
-
- de.hft.stuttgart
- CityDoctorEdge
- ${revision}
-
-
- de.hft.stuttgart
- CityDoctorCheckResult
- ${revision}
-
-
- de.hft.stuttgart
- CityDoctorHealer
- ${revision}
-
-
- net.sf.saxon
- Saxon-HE
- 12.2
-
-
- org.hibernate
- hibernate-core
- 5.6.9.Final
-
-
- org.citygml4j
- citygml4j-core
- 3.2.0
-
-
- org.citygml4j
- citygml4j-xml
- 3.2.0
-
-
- de.hft.stuttgart
- citygml4j-quality-ade
- 3.2.0
-
-
- org.apache.xmlgraphics
- fop
- 2.7
-
-
- org.jdom
- jdom2
- 2.0.6.1
-
-
- junit
- junit
- 4.13.2
- test
-
-
- org.jogamp.gluegen
- gluegen-rt-main
- 2.3.2
-
-
- gov.nist.math
- jama
- 1.0.3
-
-
- org.jogamp.jogl
- jogl-all-main
- 2.3.2
-
-
- org.apache.logging.log4j
- log4j-api
- ${log4j.version}
-
-
- org.apache.logging.log4j
- log4j-core
- ${log4j.version}
-
-
- org.apache.logging.log4j
- log4j-jul
- ${log4j.version}
-
-
- org.yaml
- snakeyaml
- 2.0
-
-
- org.apache.logging.log4j
- log4j-slf4j18-impl
- ${log4j.version}
-
-
- org.locationtech.proj4j
- proj4j
- 1.1.5
-
-
- org.hibernate
- hibernate-search-orm
- 5.11.9.Final
-
-
- org.locationtech.jts
- jts-core
- 1.19.0
-
-
- com.sun.xml.bind
- jaxb-impl
- 2.3.3
-
-
- jakarta.xml.bind
- jakarta.xml.bind-api
- 2.3.3
-
-
-
-
-
- org.mockito
- mockito-core
- 4.6.1
- test
-
-
- org.openjfx
- javafx-controls
- ${jfx-version}
-
-
- org.openjfx
- javafx-fxml
- ${jfx-version}
-
-
- org.openjfx
- javafx-swing
- ${jfx-version}
-
-
-
-
- CityDoctorModel
- CityDoctorValidation
- CityDoctorEdge
- CityDoctorCheckResult
+
+ 4.0.0
+ de.hft.stuttgart
+ CityDoctorParent
+ 3.16.0
+ pom
+ CityDoctorParent
+
+ UTF-8
+ 17
+ 17
+ 2.18.0
+ ${project.version}
+ ${project.baseUri}../non-maven-libs
+ 17.0.10
+ ${jre-version-short}+13
+ 17.0.12
+
+
+
+ non-maven-libs
+ ${nonMavenLibsPath}
+
+
+ sonartype
+ https://oss.sonatype.org/content/repositories/snapshots/
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 2.22.0
+
+ false
+
+ **/SolidSelfIntCheckFalsePositiveBigMeshTest.java
+
+
+
+
+
+
+
+ maven-compiler-plugin
+ 3.13.0
+
+ true
+ true
+
+
+
+ org.codehaus.plexus
+ plexus-compiler-api
+ 2.15.0
+
+
+ org.codehaus.plexus
+ plexus-compiler-manager
+ 2.15.0
+
+
+ org.codehaus.plexus
+ plexus-compiler-eclipse
+ 2.15.0
+
+
+ org.openjfx
+ javafx-maven-plugin
+ 0.0.8
+
+
+
+
+
+
+ org.openjfx
+ javafx-controls
+ ${jfx-version}
+
+
+ org.openjfx
+ javafx-fxml
+ ${jfx-version}
+
+
+ org.openjfx
+ javafx-swing
+ ${jfx-version}
+
+
+ de.hft.stuttgart
+ CityDoctorModel
+ ${revision}
+
+
+ de.hft.stuttgart
+ CityDoctorAutoPro
+ ${revision}
+
+
+ de.hft.stuttgart
+ CityDoctorValidation
+ ${revision}
+
+
+ de.hft.stuttgart
+ CityDoctorGUI
+ ${revision}
+
+
+ de.hft.stuttgart
+ CityDoctorEdge
+ ${revision}
+
+
+ de.hft.stuttgart
+ CityDoctorCheckResult
+ ${revision}
+
+
+ de.hft.stuttgart
+ CityDoctorHealer
+ ${revision}
+
+
+ net.sf.saxon
+ Saxon-HE
+ 12.2
+
+
+ org.hibernate
+ hibernate-core
+ 5.6.9.Final
+
+
+ org.citygml4j
+ citygml4j-core
+ 3.2.0
+
+
+ org.citygml4j
+ citygml4j-xml
+ 3.2.0
+
+
+ de.hft.stuttgart
+ citygml4j-quality-ade
+ 3.2.0
+
+
+ org.apache.xmlgraphics
+ fop
+ 2.7
+
+
+ org.jdom
+ jdom2
+ 2.0.6.1
+
+
+ junit
+ junit
+ 4.13.2
+ test
+
+
+ org.jogamp.gluegen
+ gluegen-rt-main
+ 2.3.2
+
+
+ gov.nist.math
+ jama
+ 1.0.3
+
+
+ org.jogamp.jogl
+ jogl-all-main
+ 2.3.2
+
+
+ org.apache.logging.log4j
+ log4j-api
+ ${log4j.version}
+
+
+ org.apache.logging.log4j
+ log4j-core
+ ${log4j.version}
+
+
+ org.apache.logging.log4j
+ log4j-jul
+ ${log4j.version}
+
+
+ org.yaml
+ snakeyaml
+ 2.0
+
+
+ org.apache.logging.log4j
+ log4j-slf4j18-impl
+ ${log4j.version}
+
+
+ org.locationtech.proj4j
+ proj4j
+ 1.1.5
+
+
+ org.hibernate
+ hibernate-search-orm
+ 5.11.9.Final
+
+
+ org.locationtech.jts
+ jts-core
+ 1.20.0
+
+
+ com.sun.xml.bind
+ jaxb-impl
+ 2.3.3
+
+
+ jakarta.xml.bind
+ jakarta.xml.bind-api
+ 2.3.3
+
+
+ io.github.earcut4j
+ earcut4j
+ 2.2.2
+
+
+
+
+
+ org.mockito
+ mockito-core
+ 4.6.1
+ test
+
+
+ org.openjfx
+ javafx-controls
+ ${jfx-version}
+
+
+ org.openjfx
+ javafx-fxml
+ ${jfx-version}
+
+
+ org.openjfx
+ javafx-swing
+ ${jfx-version}
+
+
+
+
+ CityDoctorModel
+ CityDoctorValidation
+ CityDoctorEdge
+ CityDoctorCheckResult
-
- Extensions/CityDoctorGUI
-
+ Extensions/CityDoctorGUI
+
-
+
\ No newline at end of file