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 @@ <groupId>org.locationtech.proj4j</groupId> <artifactId>proj4j</artifactId> </dependency> + <dependency> + <groupId>org.locationtech.jts</groupId> + <artifactId>jts-core</artifactId> + </dependency> + <dependency> + <groupId>io.github.earcut4j</groupId> + <artifactId>earcut4j</artifactId> + </dependency> </dependencies> <build> <resources> 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<MovedRing> 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<LinearRing> 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<Vertex> 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<Integer> indices = Earcut.earcut(vertices, holeStart, 2); + List<Triangle3d> 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<Vertex> vertexObjects) { + List<Vertex> 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<Vector2d> 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<Vector3d> vertices = new ArrayList<>(); Vector3d normal = p.calculateNormalNormalized(); synchronized (tess) { @@ -121,7 +125,7 @@ public class JoglTesselator { GLU.gluTessEndPolygon(tess); ArrayList<Integer> 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<Vector3d> vertices = new ArrayList<>(); Vector3d normal = r.calculateNormal(); synchronized (tess) { @@ -147,12 +151,16 @@ public class JoglTesselator { GLU.gluTessEndPolygon(tess); ArrayList<Integer> 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<Integer> indices) { + public void fillListWithIndices(List<Integer> 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<Integer> indices) { + private void addToListIfAreaNonNull(Integer i1, Integer i2, Integer i3, List<Integer> 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<Segment3d> 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<PolygonIntersection> intersections = SelfIntersectionUtil.doesSolidSelfIntersect2(g); + List<PolygonIntersection> intersections = SelfIntersectionUtil.calculateSolidSelfIntersection(g); +// List<PolygonIntersection> 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<PolygonIntersection> calculateSolidSelfIntersection(Geometry g) { + List<TesselatedPolygon> tesselatedPolygons = new ArrayList<>(); + for (Polygon p : g.getPolygons()) { + tesselatedPolygons.add(EarcutTesselator.tesselatePolygon(p)); + } + List<PolygonIntersection> 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<PolygonIntersection> intersections, Map<Polygon, EdgePolygon> edgePolyMap, - Polygon p1, Polygon p2) { + private static void performEdgeSelfIntersection(List<PolygonIntersection> intersections, + Map<Polygon, EdgePolygon> edgePolyMap, Polygon p1, Polygon p2) { EdgePolygon edgeP1 = edgePolyMap.get(p1); EdgePolygon edgeP2 = edgePolyMap.get(p2); - List<PolygonPolygonIntersection> results = IntersectPlanarPolygons.intersectPolygons(edgeP1, edgeP2, 0.000001, 0.001); + List<PolygonPolygonIntersection> 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<Renderable> root; public ErrorItemVisitor(TreeItem<Renderable> 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<Renderable> textItem = new TreeItem<>(textNode); root.getChildren().add(textItem); List<Polygon> component = err.getComponents().get(i); @@ -99,7 +106,7 @@ public class ErrorItemVisitor implements ErrorVisitor { TreeItem<Renderable> 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<Renderable> textItem = new TreeItem<>(textNode); root.getChildren().add(textItem); List<Polygon> 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<Renderable> ringItem = new TreeItem<>(ringNode); root.getChildren().add(ringItem); - + VertexNode vertexNode = new VertexNode(err.getVertex1()); TreeItem<Renderable> 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<Renderable> ringItem = new TreeItem<>(ringNode); root.getChildren().add(ringItem); - + if (err.getRing().getGmlId().isGenerated()) { PolygonNode polyNode = new PolygonNode(err.getRing().getParent(), CheckStatus.NOT_CHECKED); TreeItem<Renderable> polyItem = new TreeItem<>(polyNode); @@ -206,8 +213,9 @@ public class ErrorItemVisitor implements ErrorVisitor { PolygonNode polyNode = new PolygonNode(err.getPolygon(), CheckStatus.NOT_CHECKED); TreeItem<Renderable> 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<Renderable> 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<Renderable> polyItem = new TreeItem<>(polyNode); root.getChildren().add(polyItem); - + VertexNode vertexNode = new VertexNode(err.getVertex()); TreeItem<Renderable> 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<Renderable> 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<Renderable> polyItem1 = new TreeItem<>(polyNode1); - root.getChildren().add(polyItem1); - PolygonNode polyNode2 = new PolygonNode(err.getIntersections().get(0).getP2(), CheckStatus.NOT_CHECKED); - TreeItem<Renderable> polyItem2 = new TreeItem<>(polyNode2); - root.getChildren().add(polyItem2); + List<PolygonIntersection> 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<Renderable> intersectionItem = new TreeItem<>(intersectionNode); + root.getChildren().add(intersectionItem); + + PolygonNode polyNode1 = new PolygonNode(pi.getP1(), CheckStatus.NOT_CHECKED); + TreeItem<Renderable> polyItem1 = new TreeItem<>(polyNode1); + intersectionItem.getChildren().add(polyItem1); + PolygonNode polyNode2 = new PolygonNode(pi.getP2(), CheckStatus.NOT_CHECKED); + TreeItem<Renderable> 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<Renderable> trianglesItem = new TreeItem<>(trianglesNode); + intersectionItem.getChildren().add(trianglesItem); + + ConcretePolygon c = createPolygonForTriangle(intersection.getT1()); + PolygonNode pN1 = new PolygonNode(c, CheckStatus.NOT_CHECKED); + TreeItem<Renderable> pI1 = new TreeItem<>(pN1); + trianglesItem.getChildren().add(pI1); + + ConcretePolygon c2 = createPolygonForTriangle(intersection.getT2()); + PolygonNode pN2 = new PolygonNode(c2, CheckStatus.NOT_CHECKED); + TreeItem<Renderable> 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<Renderable> ringItem = new TreeItem<>(ringNode); root.getChildren().add(ringItem); - + VertexNode vertexNode = new VertexNode(err.getVertex1()); TreeItem<Renderable> 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<Renderable> ringItem = new TreeItem<>(ringNode); root.getChildren().add(ringItem); - + EdgeNode edgeNode = new EdgeNode(err.getEdge1()); TreeItem<Renderable> edgeItem = new TreeItem<>(edgeNode); root.getChildren().add(edgeItem); - + EdgeNode edge2Node = new EdgeNode(err.getEdge2()); TreeItem<Renderable> 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<Renderable> textItem = new TreeItem<>(textNode); root.getChildren().add(textItem); - + VertexNode vertexNode = new VertexNode(err.getVertex()); TreeItem<Renderable> vertexItem = new TreeItem<>(vertexNode); root.getChildren().add(vertexItem); - + EdgeNode edgeNode = new EdgeNode(err.getEdge()); TreeItem<Renderable> edgeItem = new TreeItem<>(edgeNode); root.getChildren().add(edgeItem); - + LinearRingNode ringNode = new LinearRingNode(err.getRing(), CheckStatus.NOT_CHECKED); TreeItem<Renderable> 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<Renderable> 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<Renderable> textItem = new TreeItem<>(textNode); root.getChildren().add(textItem); - + LinearRingNode polyNode = new LinearRingNode(err.getRing(), CheckStatus.NOT_CHECKED); TreeItem<Renderable> 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<Renderable> 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<Renderable> 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<Renderable> 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<Renderable> 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<Renderable> 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<Renderable> 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 @@ <?xml version="1.0" encoding="utf-8"?> -<project xmlns="http://maven.apache.org/POM/4.0.0" -> - <modelVersion>4.0.0</modelVersion> - <groupId>de.hft.stuttgart</groupId> - <artifactId>CityDoctorParent</artifactId> - <version>3.16.0</version> - <packaging>pom</packaging> - <name>CityDoctorParent</name> - <properties> - <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - <maven.compiler.source>17</maven.compiler.source> - <maven.compiler.target>17</maven.compiler.target> - <log4j.version>2.18.0</log4j.version> - <revision>${project.version}</revision> - <nonMavenLibsPath>${project.baseUri}../non-maven-libs</nonMavenLibsPath> - <jre-version-short>17.0.10</jre-version-short> - <jre-version>${jre-version-short}+13</jre-version> - <jfx-version>17.0.12</jfx-version> - </properties> - <repositories> - <repository> - <id>non-maven-libs</id> - <url>${nonMavenLibsPath}</url> - </repository> - <repository> - <id>sonartype</id> - <url>https://oss.sonatype.org/content/repositories/snapshots/</url> - </repository> - </repositories> - <build> - <pluginManagement> - <plugins> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-surefire-plugin</artifactId> - <version>2.22.0</version> - <configuration> - <testFailureIgnore>false</testFailureIgnore> - <excludes> - <exclude>**/SolidSelfIntCheckFalsePositiveBigMeshTest.java</exclude> - </excludes> - </configuration> - </plugin> - </plugins> - </pluginManagement> - <plugins> - <plugin> - <artifactId>maven-compiler-plugin</artifactId> - <version>3.13.0</version> - <configuration> - <showWarnings>true</showWarnings> - <showDeprecation>true</showDeprecation> - </configuration> - </plugin> - <plugin> - <groupId>org.codehaus.plexus</groupId> - <artifactId>plexus-compiler-api</artifactId> - <version>2.15.0</version> - </plugin> - <plugin> - <groupId>org.codehaus.plexus</groupId> - <artifactId>plexus-compiler-manager</artifactId> - <version>2.15.0</version> - </plugin> - <plugin> - <groupId>org.codehaus.plexus</groupId> - <artifactId>plexus-compiler-eclipse</artifactId> - <version>2.15.0</version> - </plugin> - <plugin> - <groupId>org.openjfx</groupId> - <artifactId>javafx-maven-plugin</artifactId> - <version>0.0.8</version> - </plugin> - </plugins> - </build> - <dependencyManagement> - <dependencies> - <dependency> - <groupId>org.openjfx</groupId> - <artifactId>javafx-controls</artifactId> - <version>${jfx-version}</version> - </dependency> - <dependency> - <groupId>org.openjfx</groupId> - <artifactId>javafx-fxml</artifactId> - <version>${jfx-version}</version> - </dependency> - <dependency> - <groupId>org.openjfx</groupId> - <artifactId>javafx-swing</artifactId> - <version>${jfx-version}</version> - </dependency> - <dependency> - <groupId>de.hft.stuttgart</groupId> - <artifactId>CityDoctorModel</artifactId> - <version>${revision}</version> - </dependency> - <dependency> - <groupId>de.hft.stuttgart</groupId> - <artifactId>CityDoctorAutoPro</artifactId> - <version>${revision}</version> - </dependency> - <dependency> - <groupId>de.hft.stuttgart</groupId> - <artifactId>CityDoctorValidation</artifactId> - <version>${revision}</version> - </dependency> - <dependency> - <groupId>de.hft.stuttgart</groupId> - <artifactId>CityDoctorGUI</artifactId> - <version>${revision}</version> - </dependency> - <dependency> - <groupId>de.hft.stuttgart</groupId> - <artifactId>CityDoctorEdge</artifactId> - <version>${revision}</version> - </dependency> - <dependency> - <groupId>de.hft.stuttgart</groupId> - <artifactId>CityDoctorCheckResult</artifactId> - <version>${revision}</version> - </dependency> - <dependency> - <groupId>de.hft.stuttgart</groupId> - <artifactId>CityDoctorHealer</artifactId> - <version>${revision}</version> - </dependency> - <dependency> - <groupId>net.sf.saxon</groupId> - <artifactId>Saxon-HE</artifactId> - <version>12.2</version> - </dependency> - <dependency> - <groupId>org.hibernate</groupId> - <artifactId>hibernate-core</artifactId> - <version>5.6.9.Final</version> - </dependency> - <dependency> - <groupId>org.citygml4j</groupId> - <artifactId>citygml4j-core</artifactId> - <version>3.2.0</version> - </dependency> - <dependency> - <groupId>org.citygml4j</groupId> - <artifactId>citygml4j-xml</artifactId> - <version>3.2.0</version> - </dependency> - <dependency> - <groupId>de.hft.stuttgart</groupId> - <artifactId>citygml4j-quality-ade</artifactId> - <version>3.2.0</version> - </dependency> - <dependency> - <groupId>org.apache.xmlgraphics</groupId> - <artifactId>fop</artifactId> - <version>2.7</version> - </dependency> - <dependency> - <groupId>org.jdom</groupId> - <artifactId>jdom2</artifactId> - <version>2.0.6.1</version> - </dependency> - <dependency> - <groupId>junit</groupId> - <artifactId>junit</artifactId> - <version>4.13.2</version> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.jogamp.gluegen</groupId> - <artifactId>gluegen-rt-main</artifactId> - <version>2.3.2</version> - </dependency> - <dependency> - <groupId>gov.nist.math</groupId> - <artifactId>jama</artifactId> - <version>1.0.3</version> - </dependency> - <dependency> - <groupId>org.jogamp.jogl</groupId> - <artifactId>jogl-all-main</artifactId> - <version>2.3.2</version> - </dependency> - <dependency> - <groupId>org.apache.logging.log4j</groupId> - <artifactId>log4j-api</artifactId> - <version>${log4j.version}</version> - </dependency> - <dependency> - <groupId>org.apache.logging.log4j</groupId> - <artifactId>log4j-core</artifactId> - <version>${log4j.version}</version> - </dependency> - <dependency> - <groupId>org.apache.logging.log4j</groupId> - <artifactId>log4j-jul</artifactId> - <version>${log4j.version}</version> - </dependency> - <dependency> - <groupId>org.yaml</groupId> - <artifactId>snakeyaml</artifactId> - <version>2.0</version> - </dependency> - <dependency> - <groupId>org.apache.logging.log4j</groupId> - <artifactId>log4j-slf4j18-impl</artifactId> - <version>${log4j.version}</version> - </dependency> - <dependency> - <groupId>org.locationtech.proj4j</groupId> - <artifactId>proj4j</artifactId> - <version>1.1.5</version> - </dependency> - <dependency> - <groupId>org.hibernate</groupId> - <artifactId>hibernate-search-orm</artifactId> - <version>5.11.9.Final</version> - </dependency> - <dependency> - <groupId>org.locationtech.jts</groupId> - <artifactId>jts-core</artifactId> - <version>1.19.0</version> - </dependency> - <dependency> - <groupId>com.sun.xml.bind</groupId> - <artifactId>jaxb-impl</artifactId> - <version>2.3.3</version> - </dependency> - <dependency> - <groupId>jakarta.xml.bind</groupId> - <artifactId>jakarta.xml.bind-api</artifactId> - <version>2.3.3</version> - </dependency> - </dependencies> - </dependencyManagement> - <dependencies> - <dependency> - <groupId>org.mockito</groupId> - <artifactId>mockito-core</artifactId> - <version>4.6.1</version> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.openjfx</groupId> - <artifactId>javafx-controls</artifactId> - <version>${jfx-version}</version> - </dependency> - <dependency> - <groupId>org.openjfx</groupId> - <artifactId>javafx-fxml</artifactId> - <version>${jfx-version}</version> - </dependency> - <dependency> - <groupId>org.openjfx</groupId> - <artifactId>javafx-swing</artifactId> - <version>${jfx-version}</version> - </dependency> - </dependencies> - <modules> - <!--CityDoctor2 Core Modules--> - <module>CityDoctorModel</module> - <module>CityDoctorValidation</module> - <module>CityDoctorEdge</module> - <module>CityDoctorCheckResult</module> +<project xmlns="http://maven.apache.org/POM/4.0.0"> + <modelVersion>4.0.0</modelVersion> + <groupId>de.hft.stuttgart</groupId> + <artifactId>CityDoctorParent</artifactId> + <version>3.16.0</version> + <packaging>pom</packaging> + <name>CityDoctorParent</name> + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <maven.compiler.source>17</maven.compiler.source> + <maven.compiler.target>17</maven.compiler.target> + <log4j.version>2.18.0</log4j.version> + <revision>${project.version}</revision> + <nonMavenLibsPath>${project.baseUri}../non-maven-libs</nonMavenLibsPath> + <jre-version-short>17.0.10</jre-version-short> + <jre-version>${jre-version-short}+13</jre-version> + <jfx-version>17.0.12</jfx-version> + </properties> + <repositories> + <repository> + <id>non-maven-libs</id> + <url>${nonMavenLibsPath}</url> + </repository> + <repository> + <id>sonartype</id> + <url>https://oss.sonatype.org/content/repositories/snapshots/</url> + </repository> + </repositories> + <build> + <pluginManagement> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <version>2.22.0</version> + <configuration> + <testFailureIgnore>false</testFailureIgnore> + <excludes> + <exclude>**/SolidSelfIntCheckFalsePositiveBigMeshTest.java</exclude> + </excludes> + </configuration> + </plugin> + </plugins> + </pluginManagement> + <plugins> + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.13.0</version> + <configuration> + <showWarnings>true</showWarnings> + <showDeprecation>true</showDeprecation> + </configuration> + </plugin> + <plugin> + <groupId>org.codehaus.plexus</groupId> + <artifactId>plexus-compiler-api</artifactId> + <version>2.15.0</version> + </plugin> + <plugin> + <groupId>org.codehaus.plexus</groupId> + <artifactId>plexus-compiler-manager</artifactId> + <version>2.15.0</version> + </plugin> + <plugin> + <groupId>org.codehaus.plexus</groupId> + <artifactId>plexus-compiler-eclipse</artifactId> + <version>2.15.0</version> + </plugin> + <plugin> + <groupId>org.openjfx</groupId> + <artifactId>javafx-maven-plugin</artifactId> + <version>0.0.8</version> + </plugin> + </plugins> + </build> + <dependencyManagement> + <dependencies> + <dependency> + <groupId>org.openjfx</groupId> + <artifactId>javafx-controls</artifactId> + <version>${jfx-version}</version> + </dependency> + <dependency> + <groupId>org.openjfx</groupId> + <artifactId>javafx-fxml</artifactId> + <version>${jfx-version}</version> + </dependency> + <dependency> + <groupId>org.openjfx</groupId> + <artifactId>javafx-swing</artifactId> + <version>${jfx-version}</version> + </dependency> + <dependency> + <groupId>de.hft.stuttgart</groupId> + <artifactId>CityDoctorModel</artifactId> + <version>${revision}</version> + </dependency> + <dependency> + <groupId>de.hft.stuttgart</groupId> + <artifactId>CityDoctorAutoPro</artifactId> + <version>${revision}</version> + </dependency> + <dependency> + <groupId>de.hft.stuttgart</groupId> + <artifactId>CityDoctorValidation</artifactId> + <version>${revision}</version> + </dependency> + <dependency> + <groupId>de.hft.stuttgart</groupId> + <artifactId>CityDoctorGUI</artifactId> + <version>${revision}</version> + </dependency> + <dependency> + <groupId>de.hft.stuttgart</groupId> + <artifactId>CityDoctorEdge</artifactId> + <version>${revision}</version> + </dependency> + <dependency> + <groupId>de.hft.stuttgart</groupId> + <artifactId>CityDoctorCheckResult</artifactId> + <version>${revision}</version> + </dependency> + <dependency> + <groupId>de.hft.stuttgart</groupId> + <artifactId>CityDoctorHealer</artifactId> + <version>${revision}</version> + </dependency> + <dependency> + <groupId>net.sf.saxon</groupId> + <artifactId>Saxon-HE</artifactId> + <version>12.2</version> + </dependency> + <dependency> + <groupId>org.hibernate</groupId> + <artifactId>hibernate-core</artifactId> + <version>5.6.9.Final</version> + </dependency> + <dependency> + <groupId>org.citygml4j</groupId> + <artifactId>citygml4j-core</artifactId> + <version>3.2.0</version> + </dependency> + <dependency> + <groupId>org.citygml4j</groupId> + <artifactId>citygml4j-xml</artifactId> + <version>3.2.0</version> + </dependency> + <dependency> + <groupId>de.hft.stuttgart</groupId> + <artifactId>citygml4j-quality-ade</artifactId> + <version>3.2.0</version> + </dependency> + <dependency> + <groupId>org.apache.xmlgraphics</groupId> + <artifactId>fop</artifactId> + <version>2.7</version> + </dependency> + <dependency> + <groupId>org.jdom</groupId> + <artifactId>jdom2</artifactId> + <version>2.0.6.1</version> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.13.2</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.jogamp.gluegen</groupId> + <artifactId>gluegen-rt-main</artifactId> + <version>2.3.2</version> + </dependency> + <dependency> + <groupId>gov.nist.math</groupId> + <artifactId>jama</artifactId> + <version>1.0.3</version> + </dependency> + <dependency> + <groupId>org.jogamp.jogl</groupId> + <artifactId>jogl-all-main</artifactId> + <version>2.3.2</version> + </dependency> + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-api</artifactId> + <version>${log4j.version}</version> + </dependency> + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-core</artifactId> + <version>${log4j.version}</version> + </dependency> + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-jul</artifactId> + <version>${log4j.version}</version> + </dependency> + <dependency> + <groupId>org.yaml</groupId> + <artifactId>snakeyaml</artifactId> + <version>2.0</version> + </dependency> + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-slf4j18-impl</artifactId> + <version>${log4j.version}</version> + </dependency> + <dependency> + <groupId>org.locationtech.proj4j</groupId> + <artifactId>proj4j</artifactId> + <version>1.1.5</version> + </dependency> + <dependency> + <groupId>org.hibernate</groupId> + <artifactId>hibernate-search-orm</artifactId> + <version>5.11.9.Final</version> + </dependency> + <dependency> + <groupId>org.locationtech.jts</groupId> + <artifactId>jts-core</artifactId> + <version>1.20.0</version> + </dependency> + <dependency> + <groupId>com.sun.xml.bind</groupId> + <artifactId>jaxb-impl</artifactId> + <version>2.3.3</version> + </dependency> + <dependency> + <groupId>jakarta.xml.bind</groupId> + <artifactId>jakarta.xml.bind-api</artifactId> + <version>2.3.3</version> + </dependency> + <dependency> + <groupId>io.github.earcut4j</groupId> + <artifactId>earcut4j</artifactId> + <version>2.2.2</version> + </dependency> + </dependencies> + </dependencyManagement> + <dependencies> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <version>4.6.1</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.openjfx</groupId> + <artifactId>javafx-controls</artifactId> + <version>${jfx-version}</version> + </dependency> + <dependency> + <groupId>org.openjfx</groupId> + <artifactId>javafx-fxml</artifactId> + <version>${jfx-version}</version> + </dependency> + <dependency> + <groupId>org.openjfx</groupId> + <artifactId>javafx-swing</artifactId> + <version>${jfx-version}</version> + </dependency> + </dependencies> + <modules> + <!--CityDoctor2 Core Modules--> + <module>CityDoctorModel</module> + <module>CityDoctorValidation</module> + <module>CityDoctorEdge</module> + <module>CityDoctorCheckResult</module> - <!--CityDoctor2 Extension Modules--> - <module>Extensions/CityDoctorGUI</module> - <!-- + <!--CityDoctor2 Extension Modules--> + <module>Extensions/CityDoctorGUI</module> + <!-- <module>Extensions/CityDoctorAutoPro</module> <module>Extensions/CityDoctorHealer</module> <module>Extensions/CityDoctorHealerGenetic</module> <module>Extensions/CityDoctorHealerGUI</module> <module>Extensions/CityDoctorWebService</module> --> - </modules> + </modules> </project> \ No newline at end of file