Commit 39ffb121 authored by Matthias Betz's avatar Matthias Betz
Browse files

Solid self intersection with better triangulation to eliminate false positives

parent 8afe47c2
Pipeline #10954 passed with stage
in 1 minute and 12 seconds
...@@ -58,6 +58,14 @@ ...@@ -58,6 +58,14 @@
<groupId>org.locationtech.proj4j</groupId> <groupId>org.locationtech.proj4j</groupId>
<artifactId>proj4j</artifactId> <artifactId>proj4j</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.locationtech.jts</groupId>
<artifactId>jts-core</artifactId>
</dependency>
<dependency>
<groupId>io.github.earcut4j</groupId>
<artifactId>earcut4j</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>
<resources> <resources>
......
...@@ -39,6 +39,25 @@ public class MovedPolygon { ...@@ -39,6 +39,25 @@ public class MovedPolygon {
private MovedRing exteriorRing; private MovedRing exteriorRing;
private List<MovedRing> innerRings; 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) { public static MovedPolygon ofPolygon(Polygon p, Vector3d movedBy) {
MovedPolygon indPoly = new MovedPolygon(); MovedPolygon indPoly = new MovedPolygon();
indPoly.original = p; indPoly.original = p;
......
...@@ -40,6 +40,11 @@ public class Polygon2d { ...@@ -40,6 +40,11 @@ public class Polygon2d {
ProjectionAxis axis = ProjectionAxis.of(poly); ProjectionAxis axis = ProjectionAxis.of(poly);
return projectTo2D(poly, axis); 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) { public static Polygon2d withProjection(MovedPolygon poly, ProjectionAxis projectionAxis) {
return projectTo2D(poly, projectionAxis); return projectTo2D(poly, projectionAxis);
......
...@@ -22,6 +22,8 @@ import java.io.Serial; ...@@ -22,6 +22,8 @@ import java.io.Serial;
import java.io.Serializable; import java.io.Serializable;
import java.util.Arrays; import java.util.Arrays;
import org.locationtech.jts.geom.Coordinate;
/** /**
* A three dimensional vector * A three dimensional vector
* *
...@@ -44,6 +46,17 @@ public class Vector3d implements Serializable { ...@@ -44,6 +46,17 @@ public class Vector3d implements Serializable {
public Vector3d() { public Vector3d() {
this(0d, 0d, 0d); 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) { public Vector3d(double x, double y, double z) {
coords = new double[3]; coords = new double[3];
......
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() {
}
}
...@@ -33,7 +33,7 @@ import de.hft.stuttgart.citydoctor2.datastructure.Vertex; ...@@ -33,7 +33,7 @@ import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
import de.hft.stuttgart.citydoctor2.math.Vector3d; 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 * @author Matthias Betz
* *
...@@ -102,6 +102,10 @@ public class JoglTesselator { ...@@ -102,6 +102,10 @@ public class JoglTesselator {
} }
public static TesselatedPolygon tesselatePolygon(Polygon p) { public static TesselatedPolygon tesselatePolygon(Polygon p) {
return tesselatePolygon(p, true);
}
public static TesselatedPolygon tesselatePolygon(Polygon p, boolean discardDegeneratedTriangles) {
ArrayList<Vector3d> vertices = new ArrayList<>(); ArrayList<Vector3d> vertices = new ArrayList<>();
Vector3d normal = p.calculateNormalNormalized(); Vector3d normal = p.calculateNormalNormalized();
synchronized (tess) { synchronized (tess) {
...@@ -121,7 +125,7 @@ public class JoglTesselator { ...@@ -121,7 +125,7 @@ public class JoglTesselator {
GLU.gluTessEndPolygon(tess); GLU.gluTessEndPolygon(tess);
ArrayList<Integer> indices = new ArrayList<>(); ArrayList<Integer> indices = new ArrayList<>();
for (Primitive primitive : primitives) { for (Primitive primitive : primitives) {
primitive.fillListWithIndices(indices); primitive.fillListWithIndices(indices, discardDegeneratedTriangles);
} }
primitives.clear(); primitives.clear();
return new TesselatedPolygon(vertices, indices, p); return new TesselatedPolygon(vertices, indices, p);
...@@ -137,7 +141,7 @@ public class JoglTesselator { ...@@ -137,7 +141,7 @@ public class JoglTesselator {
GLU.gluTessEndContour(tess); GLU.gluTessEndContour(tess);
} }
public static TesselatedRing tesselateRing(LinearRing r) { public static TesselatedRing tesselateRing(LinearRing r, boolean discardDegeneratedTriangles) {
ArrayList<Vector3d> vertices = new ArrayList<>(); ArrayList<Vector3d> vertices = new ArrayList<>();
Vector3d normal = r.calculateNormal(); Vector3d normal = r.calculateNormal();
synchronized (tess) { synchronized (tess) {
...@@ -147,12 +151,16 @@ public class JoglTesselator { ...@@ -147,12 +151,16 @@ public class JoglTesselator {
GLU.gluTessEndPolygon(tess); GLU.gluTessEndPolygon(tess);
ArrayList<Integer> indices = new ArrayList<>(); ArrayList<Integer> indices = new ArrayList<>();
for (Primitive primitive : primitives) { for (Primitive primitive : primitives) {
primitive.fillListWithIndices(indices); primitive.fillListWithIndices(indices, discardDegeneratedTriangles);
} }
primitives.clear(); primitives.clear();
return new TesselatedRing(vertices, indices, r); return new TesselatedRing(vertices, indices, r);
} }
} }
public static TesselatedRing tesselateRing(LinearRing r) {
return tesselateRing(r, true);
}
private JoglTesselator() { private JoglTesselator() {
// only static useage // only static useage
......
...@@ -49,30 +49,34 @@ public class Primitive { ...@@ -49,30 +49,34 @@ public class Primitive {
this.type = type; this.type = type;
} }
public void fillListWithIndices(List<Integer> indices) { public void fillListWithIndices(List<Integer> indices, boolean discardDegeneratedTriangles) {
switch (type) { switch (type) {
case GL.GL_TRIANGLES: case GL.GL_TRIANGLES:
for (int i = 0; i < pIndices.size(); i += 3) { 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; break;
case GL.GL_TRIANGLE_STRIP: case GL.GL_TRIANGLE_STRIP:
for (int i = 0; i < pIndices.size() - 2; i++) { for (int i = 0; i < pIndices.size() - 2; i++) {
if (i % 2 == 0) { 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 { } 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; break;
case GL.GL_TRIANGLE_FAN: case GL.GL_TRIANGLE_FAN:
Integer first = pIndices.get(0); Integer first = pIndices.get(0);
for (int i = 0; i < pIndices.size() - 2; i++) { 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; break;
default: default:
throw new IllegalStateException("unknown type found: " + type); throw new IllegalStateException("unknown triangle type found: " + type);
} }
} }
...@@ -80,20 +84,21 @@ public class Primitive { ...@@ -80,20 +84,21 @@ public class Primitive {
pIndices.add(i); 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 v1 = vertices.get(i1);
Vector3d v2 = vertices.get(i2); Vector3d v2 = vertices.get(i2);
Vector3d v3 = vertices.get(i3); Vector3d v3 = vertices.get(i3);
double area = Math.abs(calculateAreaOfTriangle(v1, v2, v3)); if (discardDegeneratedTriangles && Math.abs(calculateAreaOfTriangle(v1, v2, v3)) <= AREA_EPSILON) {
if (area > 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(i1);
indices.add(i2); indices.add(i2);
indices.add(i3); indices.add(i3);
} else {
logger.trace("Tesselator created degenerated triangle, ignoring");
} }
} }
/** /**
* Calculates the area of a triangle given by the 3 points * Calculates the area of a triangle given by the 3 points
* *
......
...@@ -25,6 +25,7 @@ import java.util.List; ...@@ -25,6 +25,7 @@ import java.util.List;
import de.hft.stuttgart.citydoctor2.datastructure.ConcretePolygon; import de.hft.stuttgart.citydoctor2.datastructure.ConcretePolygon;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon; import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import de.hft.stuttgart.citydoctor2.math.Segment3d; import de.hft.stuttgart.citydoctor2.math.Segment3d;
import de.hft.stuttgart.citydoctor2.math.Triangle3d;
/** /**
* Result of a polygon polygon intersection. * Result of a polygon polygon intersection.
...@@ -38,7 +39,7 @@ public class PolygonIntersection implements Serializable { ...@@ -38,7 +39,7 @@ public class PolygonIntersection implements Serializable {
private static final long serialVersionUID = -6301963226688351725L; private static final long serialVersionUID = -6301963226688351725L;
public enum IntersectionType { public enum IntersectionType {
NONE, LINE, POLYGON NONE, LINE, POLYGON, TRIANGLES
} }
private final IntersectionType type; private final IntersectionType type;
...@@ -47,10 +48,30 @@ public class PolygonIntersection implements Serializable { ...@@ -47,10 +48,30 @@ public class PolygonIntersection implements Serializable {
private Polygon p1; private Polygon p1;
private Polygon p2; private Polygon p2;
private Triangle3d t1;
private Triangle3d t2;
public static PolygonIntersection none() { public static PolygonIntersection none() {
return new PolygonIntersection(IntersectionType.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) { public static PolygonIntersection lines(List<Segment3d> lines, Polygon p1, Polygon p2) {
PolygonIntersection poly = new PolygonIntersection(IntersectionType.LINE); PolygonIntersection poly = new PolygonIntersection(IntersectionType.LINE);
...@@ -75,6 +96,14 @@ public class PolygonIntersection implements Serializable { ...@@ -75,6 +96,14 @@ public class PolygonIntersection implements Serializable {
public Polygon getP2() { public Polygon getP2() {
return p2; return p2;
} }
public Triangle3d getT1() {
return t1;
}
public Triangle3d getT2() {
return t2;
}
private PolygonIntersection(IntersectionType type) { private PolygonIntersection(IntersectionType type) {
this.type = type; this.type = type;
......
...@@ -119,4 +119,13 @@ OpenFileDialog.loadFailed=Failed to load CityGML File ...@@ -119,4 +119,13 @@ OpenFileDialog.loadFailed=Failed to load CityGML File
MainWindow.memoryLabel=Memory: MainWindow.memoryLabel=Memory:
CheckDialog.checksReenabledAlert=Some checks have been reenabled so that other wanted checks can be executed\nSee the log for more information. CheckDialog.checksReenabledAlert=Some checks have been reenabled so that other wanted checks can be executed\nSee the log for more information.
MainWindow.availableLabel=Available: MainWindow.availableLabel=Available:
OpenFileDialog.lowMemoryLabel=Low Memory Consumption Mode OpenFileDialog.lowMemoryLabel=Low Memory Consumption Mode
\ No newline at end of file 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
...@@ -117,4 +117,13 @@ OpenFileDialog.loadFailed=Konnte CityGML Datei nicht laden ...@@ -117,4 +117,13 @@ OpenFileDialog.loadFailed=Konnte CityGML Datei nicht laden
MainWindow.memoryLabel=Speicher: 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 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: MainWindow.availableLabel=Verf\u00fcgbar:
OpenFileDialog.lowMemoryLabel=Reduzierter Speicherverbrauchsmodus OpenFileDialog.lowMemoryLabel=Reduzierter Speicherverbrauchsmodus
\ No newline at end of file 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
...@@ -27,19 +27,16 @@ import de.hft.stuttgart.citydoctor2.check.Check; ...@@ -27,19 +27,16 @@ import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.CheckError; import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.CheckId; import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.CheckResult; 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.GeometrySelfIntersection;
import de.hft.stuttgart.citydoctor2.check.Requirement; 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.ResultStatus;
import de.hft.stuttgart.citydoctor2.check.error.SolidSelfIntError; import de.hft.stuttgart.citydoctor2.check.error.SolidSelfIntError;
import de.hft.stuttgart.citydoctor2.checks.util.CollectionUtils; import de.hft.stuttgart.citydoctor2.checks.util.CollectionUtils;
import de.hft.stuttgart.citydoctor2.checks.util.SelfIntersectionUtil; 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.Geometry;
import de.hft.stuttgart.citydoctor2.datastructure.GeometryType; 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;
import de.hft.stuttgart.citydoctor2.utils.PolygonIntersection.IntersectionType;
/** /**
* Check for self intersecting solids * Check for self intersecting solids
...@@ -78,7 +75,8 @@ public class SolidSelfIntCheck extends Check { ...@@ -78,7 +75,8 @@ public class SolidSelfIntCheck extends Check {
return; return;
} }
CheckResult cr; CheckResult cr;
List<PolygonIntersection> intersections = SelfIntersectionUtil.doesSolidSelfIntersect2(g); List<PolygonIntersection> intersections = SelfIntersectionUtil.calculateSolidSelfIntersection(g);
// List<PolygonIntersection> intersections = SelfIntersectionUtil.doesSolidSelfIntersect2(g);
if (intersections.isEmpty()) { if (intersections.isEmpty()) {
cr = new CheckResult(this, ResultStatus.OK, null); cr = new CheckResult(this, ResultStatus.OK, null);
} else { } else {
......
...@@ -62,6 +62,7 @@ import de.hft.stuttgart.citydoctor2.math.Segment3d; ...@@ -62,6 +62,7 @@ import de.hft.stuttgart.citydoctor2.math.Segment3d;
import de.hft.stuttgart.citydoctor2.math.Triangle3d; import de.hft.stuttgart.citydoctor2.math.Triangle3d;
import de.hft.stuttgart.citydoctor2.math.Vector2d; import de.hft.stuttgart.citydoctor2.math.Vector2d;
import de.hft.stuttgart.citydoctor2.math.Vector3d; 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.JoglTesselator;
import de.hft.stuttgart.citydoctor2.tesselation.TesselatedPolygon; import de.hft.stuttgart.citydoctor2.tesselation.TesselatedPolygon;
import de.hft.stuttgart.citydoctor2.utils.PolygonIntersection; import de.hft.stuttgart.citydoctor2.utils.PolygonIntersection;
...@@ -75,15 +76,33 @@ import de.hft.stuttgart.citydoctor2.utils.PolygonIntersection.IntersectionType; ...@@ -75,15 +76,33 @@ import de.hft.stuttgart.citydoctor2.utils.PolygonIntersection.IntersectionType;
*/ */
public class SelfIntersectionUtil { public class SelfIntersectionUtil {
private static final Logger logger = LogManager.getLogger(SelfIntersectionUtil.class); private static final Logger logger = LogManager.getLogger(SelfIntersectionUtil.class);
private static final GeometryFactory factory = new GeometryFactory(new PrecisionModel(PrecisionModel.FLOATING)); private static final GeometryFactory factory = new GeometryFactory(new PrecisionModel(PrecisionModel.FLOATING));
private SelfIntersectionUtil() { 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) { public static GeometrySelfIntersection doesSolidSelfIntersect(Geometry g) {
return selfIntersectionJava(g); return selfIntersectionJava(g);
} }
...@@ -114,14 +133,15 @@ public class SelfIntersectionUtil { ...@@ -114,14 +133,15 @@ public class SelfIntersectionUtil {
return intersections; return intersections;
} }
private static void performEdgeSelfIntersection(List<PolygonIntersection> intersections, Map<Polygon, EdgePolygon> edgePolyMap, private static void performEdgeSelfIntersection(List<PolygonIntersection> intersections,
Polygon p1, Polygon p2) { Map<Polygon, EdgePolygon> edgePolyMap, Polygon p1, Polygon p2) {
EdgePolygon edgeP1 = edgePolyMap.get(p1); EdgePolygon edgeP1 = edgePolyMap.get(p1);
EdgePolygon edgeP2 = edgePolyMap.get(p2); 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()) { if (!results.isEmpty()) {
// at least one intersection happened // at least one intersection happened
for (PolygonPolygonIntersection result: results) { for (PolygonPolygonIntersection result : results) {
// Ensure that Intersection-Edge is not a Null-Line. // Ensure that Intersection-Edge is not a Null-Line.
// If it is a Null-Line, detected Intersection is a False-Positive. // If it is a Null-Line, detected Intersection is a False-Positive.
if (!result.getPolyLine().isNullLine()) { if (!result.getPolyLine().isNullLine()) {
......
...@@ -21,6 +21,7 @@ package de.hft.stuttgart.citydoctor2.checks.util; ...@@ -21,6 +21,7 @@ package de.hft.stuttgart.citydoctor2.checks.util;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.StringJoiner;
import de.hft.stuttgart.citydoctor2.datastructure.ConcretePolygon; import de.hft.stuttgart.citydoctor2.datastructure.ConcretePolygon;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry; import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
......
...@@ -43,6 +43,7 @@ import de.hft.stuttgart.citydoctor2.check.error.UnknownCheckError; ...@@ -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.Edge;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing; import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex; import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
import de.hft.stuttgart.citydoctor2.utils.PolygonIntersection;
import javafx.scene.paint.Color; import javafx.scene.paint.Color;
public class ListErrorVisitor implements ErrorVisitor { public class ListErrorVisitor implements ErrorVisitor {
...@@ -171,7 +172,11 @@ public class ListErrorVisitor implements ErrorVisitor { ...@@ -171,7 +172,11 @@ public class ListErrorVisitor implements ErrorVisitor {
@Override @Override
public void visit(SolidSelfIntError err) { 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 @Override
...@@ -208,22 +213,22 @@ public class ListErrorVisitor implements ErrorVisitor { ...@@ -208,22 +213,22 @@ public class ListErrorVisitor implements ErrorVisitor {
@Override @Override
public void visit(NotCeilingError err) { public void visit(NotCeilingError err) {
// nothing to display controller.highlight(err.getPolygon(), geom);
} }
@Override @Override
public void visit(NotFloorError err) { public void visit(NotFloorError err) {
// nothing to display controller.highlight(err.getPolygon(), geom);
} }
@Override @Override
public void visit(NotWallError err) { public void visit(NotWallError err) {
// nothing to display controller.highlight(err.getPolygon(), geom);
} }
@Override @Override
public void visit(NotGroundError err) { public void visit(NotGroundError err) {
// nothing to display controller.highlight(err.getPolygon(), geom);
} }
@Override @Override
......
...@@ -39,16 +39,23 @@ import de.hft.stuttgart.citydoctor2.check.error.SurfaceUnfragmentedError; ...@@ -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.DegeneratedRingError;
import de.hft.stuttgart.citydoctor2.check.error.TooFewPolygonsError; import de.hft.stuttgart.citydoctor2.check.error.TooFewPolygonsError;
import de.hft.stuttgart.citydoctor2.check.error.UnknownCheckError; 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.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.Polygon;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex; import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
import de.hft.stuttgart.citydoctor2.gui.CheckStatus; 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; import javafx.scene.control.TreeItem;
public class ErrorItemVisitor implements ErrorVisitor { public class ErrorItemVisitor implements ErrorVisitor {
private static final String NAME_OF_ATTRIBUTE = "Name of Attribute: "; private static String nameOfAttribute = Localization.getText("ErrorItemVisitor.nameOfAttribute") + ": ";
private static final String CHILD_ID = "ChildId: "; private static String childId = Localization.getText("ErrorItemVisitor.childId") + ": ";
private final TreeItem<Renderable> root; private final TreeItem<Renderable> root;
public ErrorItemVisitor(TreeItem<Renderable> root) { public ErrorItemVisitor(TreeItem<Renderable> root) {
...@@ -74,7 +81,7 @@ public class ErrorItemVisitor implements ErrorVisitor { ...@@ -74,7 +81,7 @@ public class ErrorItemVisitor implements ErrorVisitor {
@Override @Override
public void visit(MultipleConnectedComponentsError err) { public void visit(MultipleConnectedComponentsError err) {
for (int i = 0; i < err.getComponents().size(); i++) { 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); TreeItem<Renderable> textItem = new TreeItem<>(textNode);
root.getChildren().add(textItem); root.getChildren().add(textItem);
List<Polygon> component = err.getComponents().get(i); List<Polygon> component = err.getComponents().get(i);
...@@ -99,7 +106,7 @@ public class ErrorItemVisitor implements ErrorVisitor { ...@@ -99,7 +106,7 @@ public class ErrorItemVisitor implements ErrorVisitor {
TreeItem<Renderable> vertexItem = new TreeItem<>(vertexNode); TreeItem<Renderable> vertexItem = new TreeItem<>(vertexNode);
root.getChildren().add(vertexItem); root.getChildren().add(vertexItem);
for (int i = 0; i < err.getComponents().size(); i++) { 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); TreeItem<Renderable> textItem = new TreeItem<>(textNode);
root.getChildren().add(textItem); root.getChildren().add(textItem);
List<Polygon> component = err.getComponents().get(i); List<Polygon> component = err.getComponents().get(i);
...@@ -144,7 +151,7 @@ public class ErrorItemVisitor implements ErrorVisitor { ...@@ -144,7 +151,7 @@ public class ErrorItemVisitor implements ErrorVisitor {
@Override @Override
public void visit(UnknownCheckError err) { public void visit(UnknownCheckError err) {
// not displayed // not displayed
} }
@Override @Override
...@@ -159,11 +166,11 @@ public class ErrorItemVisitor implements ErrorVisitor { ...@@ -159,11 +166,11 @@ public class ErrorItemVisitor implements ErrorVisitor {
LinearRingNode ringNode = new LinearRingNode(err.getRing(), CheckStatus.NOT_CHECKED); LinearRingNode ringNode = new LinearRingNode(err.getRing(), CheckStatus.NOT_CHECKED);
TreeItem<Renderable> ringItem = new TreeItem<>(ringNode); TreeItem<Renderable> ringItem = new TreeItem<>(ringNode);
root.getChildren().add(ringItem); root.getChildren().add(ringItem);
VertexNode vertexNode = new VertexNode(err.getVertex1()); VertexNode vertexNode = new VertexNode(err.getVertex1());
TreeItem<Renderable> vertexItem = new TreeItem<>(vertexNode); TreeItem<Renderable> vertexItem = new TreeItem<>(vertexNode);
root.getChildren().add(vertexItem); root.getChildren().add(vertexItem);
vertexNode = new VertexNode(err.getVertex2()); vertexNode = new VertexNode(err.getVertex2());
vertexItem = new TreeItem<>(vertexNode); vertexItem = new TreeItem<>(vertexNode);
root.getChildren().add(vertexItem); root.getChildren().add(vertexItem);
...@@ -193,7 +200,7 @@ public class ErrorItemVisitor implements ErrorVisitor { ...@@ -193,7 +200,7 @@ public class ErrorItemVisitor implements ErrorVisitor {
LinearRingNode ringNode = new LinearRingNode(err.getRing(), CheckStatus.NOT_CHECKED); LinearRingNode ringNode = new LinearRingNode(err.getRing(), CheckStatus.NOT_CHECKED);
TreeItem<Renderable> ringItem = new TreeItem<>(ringNode); TreeItem<Renderable> ringItem = new TreeItem<>(ringNode);
root.getChildren().add(ringItem); root.getChildren().add(ringItem);
if (err.getRing().getGmlId().isGenerated()) { if (err.getRing().getGmlId().isGenerated()) {
PolygonNode polyNode = new PolygonNode(err.getRing().getParent(), CheckStatus.NOT_CHECKED); PolygonNode polyNode = new PolygonNode(err.getRing().getParent(), CheckStatus.NOT_CHECKED);
TreeItem<Renderable> polyItem = new TreeItem<>(polyNode); TreeItem<Renderable> polyItem = new TreeItem<>(polyNode);
...@@ -206,8 +213,9 @@ public class ErrorItemVisitor implements ErrorVisitor { ...@@ -206,8 +213,9 @@ public class ErrorItemVisitor implements ErrorVisitor {
PolygonNode polyNode = new PolygonNode(err.getPolygon(), CheckStatus.NOT_CHECKED); PolygonNode polyNode = new PolygonNode(err.getPolygon(), CheckStatus.NOT_CHECKED);
TreeItem<Renderable> polyItem = new TreeItem<>(polyNode); TreeItem<Renderable> polyItem = new TreeItem<>(polyNode);
root.getChildren().add(polyItem); 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); TreeItem<Renderable> textItem = new TreeItem<>(textNode);
root.getChildren().add(textItem); root.getChildren().add(textItem);
} }
...@@ -217,15 +225,16 @@ public class ErrorItemVisitor implements ErrorVisitor { ...@@ -217,15 +225,16 @@ public class ErrorItemVisitor implements ErrorVisitor {
PolygonNode polyNode = new PolygonNode(err.getPolygon(), CheckStatus.NOT_CHECKED); PolygonNode polyNode = new PolygonNode(err.getPolygon(), CheckStatus.NOT_CHECKED);
TreeItem<Renderable> polyItem = new TreeItem<>(polyNode); TreeItem<Renderable> polyItem = new TreeItem<>(polyNode);
root.getChildren().add(polyItem); root.getChildren().add(polyItem);
VertexNode vertexNode = new VertexNode(err.getVertex()); VertexNode vertexNode = new VertexNode(err.getVertex());
TreeItem<Renderable> vertexItem = new TreeItem<>(vertexNode); TreeItem<Renderable> vertexItem = new TreeItem<>(vertexNode);
root.getChildren().add(vertexItem); 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); TreeItem<Renderable> textItem = new TreeItem<>(textNode);
root.getChildren().add(textItem); root.getChildren().add(textItem);
} }
@Override @Override
...@@ -237,18 +246,54 @@ public class ErrorItemVisitor implements ErrorVisitor { ...@@ -237,18 +246,54 @@ public class ErrorItemVisitor implements ErrorVisitor {
@Override @Override
public void visit(SolidSelfIntError err) { public void visit(SolidSelfIntError err) {
PolygonNode polyNode1 = new PolygonNode(err.getIntersections().get(0).getP1(), CheckStatus.NOT_CHECKED); List<PolygonIntersection> intersections = err.getIntersections();
TreeItem<Renderable> polyItem1 = new TreeItem<>(polyNode1); for (int i = 0; i < intersections.size(); i++) {
root.getChildren().add(polyItem1); PolygonIntersection pi = intersections.get(i);
PolygonNode polyNode2 = new PolygonNode(err.getIntersections().get(0).getP2(), CheckStatus.NOT_CHECKED); TextNode intersectionNode = new TextNode(Localization.getText("ErrorItemVisitor.intersection") + " " + i);
TreeItem<Renderable> polyItem2 = new TreeItem<>(polyNode2); TreeItem<Renderable> intersectionItem = new TreeItem<>(intersectionNode);
root.getChildren().add(polyItem2); 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 @Override
public void visit(TooFewPolygonsError err) { public void visit(TooFewPolygonsError err) {
// not displayed // not displayed
} }
@Override @Override
...@@ -256,11 +301,11 @@ public class ErrorItemVisitor implements ErrorVisitor { ...@@ -256,11 +301,11 @@ public class ErrorItemVisitor implements ErrorVisitor {
LinearRingNode ringNode = new LinearRingNode(err.getRing(), CheckStatus.NOT_CHECKED); LinearRingNode ringNode = new LinearRingNode(err.getRing(), CheckStatus.NOT_CHECKED);
TreeItem<Renderable> ringItem = new TreeItem<>(ringNode); TreeItem<Renderable> ringItem = new TreeItem<>(ringNode);
root.getChildren().add(ringItem); root.getChildren().add(ringItem);
VertexNode vertexNode = new VertexNode(err.getVertex1()); VertexNode vertexNode = new VertexNode(err.getVertex1());
TreeItem<Renderable> vertexItem = new TreeItem<>(vertexNode); TreeItem<Renderable> vertexItem = new TreeItem<>(vertexNode);
root.getChildren().add(vertexItem); root.getChildren().add(vertexItem);
vertexNode = new VertexNode(err.getVertex2()); vertexNode = new VertexNode(err.getVertex2());
vertexItem = new TreeItem<>(vertexNode); vertexItem = new TreeItem<>(vertexNode);
root.getChildren().add(vertexItem); root.getChildren().add(vertexItem);
...@@ -272,11 +317,11 @@ public class ErrorItemVisitor implements ErrorVisitor { ...@@ -272,11 +317,11 @@ public class ErrorItemVisitor implements ErrorVisitor {
LinearRingNode ringNode = new LinearRingNode(err.getRing(), CheckStatus.NOT_CHECKED); LinearRingNode ringNode = new LinearRingNode(err.getRing(), CheckStatus.NOT_CHECKED);
TreeItem<Renderable> ringItem = new TreeItem<>(ringNode); TreeItem<Renderable> ringItem = new TreeItem<>(ringNode);
root.getChildren().add(ringItem); root.getChildren().add(ringItem);
EdgeNode edgeNode = new EdgeNode(err.getEdge1()); EdgeNode edgeNode = new EdgeNode(err.getEdge1());
TreeItem<Renderable> edgeItem = new TreeItem<>(edgeNode); TreeItem<Renderable> edgeItem = new TreeItem<>(edgeNode);
root.getChildren().add(edgeItem); root.getChildren().add(edgeItem);
EdgeNode edge2Node = new EdgeNode(err.getEdge2()); EdgeNode edge2Node = new EdgeNode(err.getEdge2());
TreeItem<Renderable> edge2Item = new TreeItem<>(edge2Node); TreeItem<Renderable> edge2Item = new TreeItem<>(edge2Node);
root.getChildren().add(edge2Item); root.getChildren().add(edge2Item);
...@@ -288,18 +333,18 @@ public class ErrorItemVisitor implements ErrorVisitor { ...@@ -288,18 +333,18 @@ public class ErrorItemVisitor implements ErrorVisitor {
@Override @Override
public void visit(PointTouchesEdgeError err) { 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); TreeItem<Renderable> textItem = new TreeItem<>(textNode);
root.getChildren().add(textItem); root.getChildren().add(textItem);
VertexNode vertexNode = new VertexNode(err.getVertex()); VertexNode vertexNode = new VertexNode(err.getVertex());
TreeItem<Renderable> vertexItem = new TreeItem<>(vertexNode); TreeItem<Renderable> vertexItem = new TreeItem<>(vertexNode);
root.getChildren().add(vertexItem); root.getChildren().add(vertexItem);
EdgeNode edgeNode = new EdgeNode(err.getEdge()); EdgeNode edgeNode = new EdgeNode(err.getEdge());
TreeItem<Renderable> edgeItem = new TreeItem<>(edgeNode); TreeItem<Renderable> edgeItem = new TreeItem<>(edgeNode);
root.getChildren().add(edgeItem); root.getChildren().add(edgeItem);
LinearRingNode ringNode = new LinearRingNode(err.getRing(), CheckStatus.NOT_CHECKED); LinearRingNode ringNode = new LinearRingNode(err.getRing(), CheckStatus.NOT_CHECKED);
TreeItem<Renderable> ringItem = new TreeItem<>(ringNode); TreeItem<Renderable> ringItem = new TreeItem<>(ringNode);
root.getChildren().add(ringItem); root.getChildren().add(ringItem);
...@@ -337,7 +382,7 @@ public class ErrorItemVisitor implements ErrorVisitor { ...@@ -337,7 +382,7 @@ public class ErrorItemVisitor implements ErrorVisitor {
public void visit(CheckError err) { public void visit(CheckError err) {
// not used // not used
} }
@Override @Override
public void visit(SchematronError err) { public void visit(SchematronError err) {
TextNode textNode = new TextNode(err.getErrorIdString()); TextNode textNode = new TextNode(err.getErrorIdString());
...@@ -347,17 +392,18 @@ public class ErrorItemVisitor implements ErrorVisitor { ...@@ -347,17 +392,18 @@ public class ErrorItemVisitor implements ErrorVisitor {
@Override @Override
public void visit(SurfaceUnfragmentedError err) { 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); TreeItem<Renderable> textItem = new TreeItem<>(textNode);
root.getChildren().add(textItem); root.getChildren().add(textItem);
} }
@Override @Override
public void visit(DegeneratedRingError err) { 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); TreeItem<Renderable> textItem = new TreeItem<>(textNode);
root.getChildren().add(textItem); root.getChildren().add(textItem);
LinearRingNode polyNode = new LinearRingNode(err.getRing(), CheckStatus.NOT_CHECKED); LinearRingNode polyNode = new LinearRingNode(err.getRing(), CheckStatus.NOT_CHECKED);
TreeItem<Renderable> polyItem = new TreeItem<>(polyNode); TreeItem<Renderable> polyItem = new TreeItem<>(polyNode);
root.getChildren().add(polyItem); root.getChildren().add(polyItem);
...@@ -366,11 +412,11 @@ public class ErrorItemVisitor implements ErrorVisitor { ...@@ -366,11 +412,11 @@ public class ErrorItemVisitor implements ErrorVisitor {
@Override @Override
public void visit(AttributeMissingError err) { public void visit(AttributeMissingError err) {
if (!err.getChildId().isEmpty()) { 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); TreeItem<Renderable> textItem = new TreeItem<>(textNode);
root.getChildren().add(textItem); 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); TreeItem<Renderable> nameItem = new TreeItem<>(nameNode);
root.getChildren().add(nameItem); root.getChildren().add(nameItem);
...@@ -379,23 +425,23 @@ public class ErrorItemVisitor implements ErrorVisitor { ...@@ -379,23 +425,23 @@ public class ErrorItemVisitor implements ErrorVisitor {
@Override @Override
public void visit(AttributeValueWrongError err) { public void visit(AttributeValueWrongError err) {
if (!err.getChildId().isEmpty()) { 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); TreeItem<Renderable> textItem = new TreeItem<>(textNode);
root.getChildren().add(textItem); 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); TreeItem<Renderable> nameItem = new TreeItem<>(nameNode);
root.getChildren().add(nameItem); root.getChildren().add(nameItem);
} }
@Override @Override
public void visit(AttributeInvalidError err) { public void visit(AttributeInvalidError err) {
if (!err.getChildId().isEmpty()) { 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); TreeItem<Renderable> textItem = new TreeItem<>(textNode);
root.getChildren().add(textItem); 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); TreeItem<Renderable> nameItem = new TreeItem<>(nameNode);
root.getChildren().add(nameItem); root.getChildren().add(nameItem);
} }
......
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" <project xmlns="http://maven.apache.org/POM/4.0.0">
> <modelVersion>4.0.0</modelVersion>
<modelVersion>4.0.0</modelVersion> <groupId>de.hft.stuttgart</groupId>
<groupId>de.hft.stuttgart</groupId> <artifactId>CityDoctorParent</artifactId>
<artifactId>CityDoctorParent</artifactId> <version>3.16.0</version>
<version>3.16.0</version> <packaging>pom</packaging>
<packaging>pom</packaging> <name>CityDoctorParent</name>
<name>CityDoctorParent</name> <properties>
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>17</maven.compiler.source>
<maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target>
<maven.compiler.target>17</maven.compiler.target> <log4j.version>2.18.0</log4j.version>
<log4j.version>2.18.0</log4j.version> <revision>${project.version}</revision>
<revision>${project.version}</revision> <nonMavenLibsPath>${project.baseUri}../non-maven-libs</nonMavenLibsPath>
<nonMavenLibsPath>${project.baseUri}../non-maven-libs</nonMavenLibsPath> <jre-version-short>17.0.10</jre-version-short>
<jre-version-short>17.0.10</jre-version-short> <jre-version>${jre-version-short}+13</jre-version>
<jre-version>${jre-version-short}+13</jre-version> <jfx-version>17.0.12</jfx-version>
<jfx-version>17.0.12</jfx-version> </properties>
</properties> <repositories>
<repositories> <repository>
<repository> <id>non-maven-libs</id>
<id>non-maven-libs</id> <url>${nonMavenLibsPath}</url>
<url>${nonMavenLibsPath}</url> </repository>
</repository> <repository>
<repository> <id>sonartype</id>
<id>sonartype</id> <url>https://oss.sonatype.org/content/repositories/snapshots/</url>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url> </repository>
</repository> </repositories>
</repositories> <build>
<build> <pluginManagement>
<pluginManagement> <plugins>
<plugins> <plugin>
<plugin> <groupId>org.apache.maven.plugins</groupId>
<groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId>
<artifactId>maven-surefire-plugin</artifactId> <version>2.22.0</version>
<version>2.22.0</version> <configuration>
<configuration> <testFailureIgnore>false</testFailureIgnore>
<testFailureIgnore>false</testFailureIgnore> <excludes>
<excludes> <exclude>**/SolidSelfIntCheckFalsePositiveBigMeshTest.java</exclude>
<exclude>**/SolidSelfIntCheckFalsePositiveBigMeshTest.java</exclude> </excludes>
</excludes> </configuration>
</configuration> </plugin>
</plugin> </plugins>
</plugins> </pluginManagement>
</pluginManagement> <plugins>
<plugins> <plugin>
<plugin> <artifactId>maven-compiler-plugin</artifactId>
<artifactId>maven-compiler-plugin</artifactId> <version>3.13.0</version>
<version>3.13.0</version> <configuration>
<configuration> <showWarnings>true</showWarnings>
<showWarnings>true</showWarnings> <showDeprecation>true</showDeprecation>
<showDeprecation>true</showDeprecation> </configuration>
</configuration> </plugin>
</plugin> <plugin>
<plugin> <groupId>org.codehaus.plexus</groupId>
<groupId>org.codehaus.plexus</groupId> <artifactId>plexus-compiler-api</artifactId>
<artifactId>plexus-compiler-api</artifactId> <version>2.15.0</version>
<version>2.15.0</version> </plugin>
</plugin> <plugin>
<plugin> <groupId>org.codehaus.plexus</groupId>
<groupId>org.codehaus.plexus</groupId> <artifactId>plexus-compiler-manager</artifactId>
<artifactId>plexus-compiler-manager</artifactId> <version>2.15.0</version>
<version>2.15.0</version> </plugin>
</plugin> <plugin>
<plugin> <groupId>org.codehaus.plexus</groupId>
<groupId>org.codehaus.plexus</groupId> <artifactId>plexus-compiler-eclipse</artifactId>
<artifactId>plexus-compiler-eclipse</artifactId> <version>2.15.0</version>
<version>2.15.0</version> </plugin>
</plugin> <plugin>
<plugin> <groupId>org.openjfx</groupId>
<groupId>org.openjfx</groupId> <artifactId>javafx-maven-plugin</artifactId>
<artifactId>javafx-maven-plugin</artifactId> <version>0.0.8</version>
<version>0.0.8</version> </plugin>
</plugin> </plugins>
</plugins> </build>
</build> <dependencyManagement>
<dependencyManagement> <dependencies>
<dependencies> <dependency>
<dependency> <groupId>org.openjfx</groupId>
<groupId>org.openjfx</groupId> <artifactId>javafx-controls</artifactId>
<artifactId>javafx-controls</artifactId> <version>${jfx-version}</version>
<version>${jfx-version}</version> </dependency>
</dependency> <dependency>
<dependency> <groupId>org.openjfx</groupId>
<groupId>org.openjfx</groupId> <artifactId>javafx-fxml</artifactId>
<artifactId>javafx-fxml</artifactId> <version>${jfx-version}</version>
<version>${jfx-version}</version> </dependency>
</dependency> <dependency>
<dependency> <groupId>org.openjfx</groupId>
<groupId>org.openjfx</groupId> <artifactId>javafx-swing</artifactId>
<artifactId>javafx-swing</artifactId> <version>${jfx-version}</version>
<version>${jfx-version}</version> </dependency>
</dependency> <dependency>
<dependency> <groupId>de.hft.stuttgart</groupId>
<groupId>de.hft.stuttgart</groupId> <artifactId>CityDoctorModel</artifactId>
<artifactId>CityDoctorModel</artifactId> <version>${revision}</version>
<version>${revision}</version> </dependency>
</dependency> <dependency>
<dependency> <groupId>de.hft.stuttgart</groupId>
<groupId>de.hft.stuttgart</groupId> <artifactId>CityDoctorAutoPro</artifactId>
<artifactId>CityDoctorAutoPro</artifactId> <version>${revision}</version>
<version>${revision}</version> </dependency>
</dependency> <dependency>
<dependency> <groupId>de.hft.stuttgart</groupId>
<groupId>de.hft.stuttgart</groupId> <artifactId>CityDoctorValidation</artifactId>
<artifactId>CityDoctorValidation</artifactId> <version>${revision}</version>
<version>${revision}</version> </dependency>
</dependency> <dependency>
<dependency> <groupId>de.hft.stuttgart</groupId>
<groupId>de.hft.stuttgart</groupId> <artifactId>CityDoctorGUI</artifactId>
<artifactId>CityDoctorGUI</artifactId> <version>${revision}</version>
<version>${revision}</version> </dependency>
</dependency> <dependency>
<dependency> <groupId>de.hft.stuttgart</groupId>
<groupId>de.hft.stuttgart</groupId> <artifactId>CityDoctorEdge</artifactId>
<artifactId>CityDoctorEdge</artifactId> <version>${revision}</version>
<version>${revision}</version> </dependency>
</dependency> <dependency>
<dependency> <groupId>de.hft.stuttgart</groupId>
<groupId>de.hft.stuttgart</groupId> <artifactId>CityDoctorCheckResult</artifactId>
<artifactId>CityDoctorCheckResult</artifactId> <version>${revision}</version>
<version>${revision}</version> </dependency>
</dependency> <dependency>
<dependency> <groupId>de.hft.stuttgart</groupId>
<groupId>de.hft.stuttgart</groupId> <artifactId>CityDoctorHealer</artifactId>
<artifactId>CityDoctorHealer</artifactId> <version>${revision}</version>
<version>${revision}</version> </dependency>
</dependency> <dependency>
<dependency> <groupId>net.sf.saxon</groupId>
<groupId>net.sf.saxon</groupId> <artifactId>Saxon-HE</artifactId>
<artifactId>Saxon-HE</artifactId> <version>12.2</version>
<version>12.2</version> </dependency>
</dependency> <dependency>
<dependency> <groupId>org.hibernate</groupId>
<groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId>
<artifactId>hibernate-core</artifactId> <version>5.6.9.Final</version>
<version>5.6.9.Final</version> </dependency>
</dependency> <dependency>
<dependency> <groupId>org.citygml4j</groupId>
<groupId>org.citygml4j</groupId> <artifactId>citygml4j-core</artifactId>
<artifactId>citygml4j-core</artifactId> <version>3.2.0</version>
<version>3.2.0</version> </dependency>
</dependency> <dependency>
<dependency> <groupId>org.citygml4j</groupId>
<groupId>org.citygml4j</groupId> <artifactId>citygml4j-xml</artifactId>
<artifactId>citygml4j-xml</artifactId> <version>3.2.0</version>
<version>3.2.0</version> </dependency>
</dependency> <dependency>
<dependency> <groupId>de.hft.stuttgart</groupId>
<groupId>de.hft.stuttgart</groupId> <artifactId>citygml4j-quality-ade</artifactId>
<artifactId>citygml4j-quality-ade</artifactId> <version>3.2.0</version>
<version>3.2.0</version> </dependency>
</dependency> <dependency>
<dependency> <groupId>org.apache.xmlgraphics</groupId>
<groupId>org.apache.xmlgraphics</groupId> <artifactId>fop</artifactId>
<artifactId>fop</artifactId> <version>2.7</version>
<version>2.7</version> </dependency>
</dependency> <dependency>
<dependency> <groupId>org.jdom</groupId>
<groupId>org.jdom</groupId> <artifactId>jdom2</artifactId>
<artifactId>jdom2</artifactId> <version>2.0.6.1</version>
<version>2.0.6.1</version> </dependency>
</dependency> <dependency>
<dependency> <groupId>junit</groupId>
<groupId>junit</groupId> <artifactId>junit</artifactId>
<artifactId>junit</artifactId> <version>4.13.2</version>
<version>4.13.2</version> <scope>test</scope>
<scope>test</scope> </dependency>
</dependency> <dependency>
<dependency> <groupId>org.jogamp.gluegen</groupId>
<groupId>org.jogamp.gluegen</groupId> <artifactId>gluegen-rt-main</artifactId>
<artifactId>gluegen-rt-main</artifactId> <version>2.3.2</version>
<version>2.3.2</version> </dependency>
</dependency> <dependency>
<dependency> <groupId>gov.nist.math</groupId>
<groupId>gov.nist.math</groupId> <artifactId>jama</artifactId>
<artifactId>jama</artifactId> <version>1.0.3</version>
<version>1.0.3</version> </dependency>
</dependency> <dependency>
<dependency> <groupId>org.jogamp.jogl</groupId>
<groupId>org.jogamp.jogl</groupId> <artifactId>jogl-all-main</artifactId>
<artifactId>jogl-all-main</artifactId> <version>2.3.2</version>
<version>2.3.2</version> </dependency>
</dependency> <dependency>
<dependency> <groupId>org.apache.logging.log4j</groupId>
<groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId>
<artifactId>log4j-api</artifactId> <version>${log4j.version}</version>
<version>${log4j.version}</version> </dependency>
</dependency> <dependency>
<dependency> <groupId>org.apache.logging.log4j</groupId>
<groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId>
<artifactId>log4j-core</artifactId> <version>${log4j.version}</version>
<version>${log4j.version}</version> </dependency>
</dependency> <dependency>
<dependency> <groupId>org.apache.logging.log4j</groupId>
<groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-jul</artifactId>
<artifactId>log4j-jul</artifactId> <version>${log4j.version}</version>
<version>${log4j.version}</version> </dependency>
</dependency> <dependency>
<dependency> <groupId>org.yaml</groupId>
<groupId>org.yaml</groupId> <artifactId>snakeyaml</artifactId>
<artifactId>snakeyaml</artifactId> <version>2.0</version>
<version>2.0</version> </dependency>
</dependency> <dependency>
<dependency> <groupId>org.apache.logging.log4j</groupId>
<groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j18-impl</artifactId>
<artifactId>log4j-slf4j18-impl</artifactId> <version>${log4j.version}</version>
<version>${log4j.version}</version> </dependency>
</dependency> <dependency>
<dependency> <groupId>org.locationtech.proj4j</groupId>
<groupId>org.locationtech.proj4j</groupId> <artifactId>proj4j</artifactId>
<artifactId>proj4j</artifactId> <version>1.1.5</version>
<version>1.1.5</version> </dependency>
</dependency> <dependency>
<dependency> <groupId>org.hibernate</groupId>
<groupId>org.hibernate</groupId> <artifactId>hibernate-search-orm</artifactId>
<artifactId>hibernate-search-orm</artifactId> <version>5.11.9.Final</version>
<version>5.11.9.Final</version> </dependency>
</dependency> <dependency>
<dependency> <groupId>org.locationtech.jts</groupId>
<groupId>org.locationtech.jts</groupId> <artifactId>jts-core</artifactId>
<artifactId>jts-core</artifactId> <version>1.20.0</version>
<version>1.19.0</version> </dependency>
</dependency> <dependency>
<dependency> <groupId>com.sun.xml.bind</groupId>
<groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-impl</artifactId>
<artifactId>jaxb-impl</artifactId> <version>2.3.3</version>
<version>2.3.3</version> </dependency>
</dependency> <dependency>
<dependency> <groupId>jakarta.xml.bind</groupId>
<groupId>jakarta.xml.bind</groupId> <artifactId>jakarta.xml.bind-api</artifactId>
<artifactId>jakarta.xml.bind-api</artifactId> <version>2.3.3</version>
<version>2.3.3</version> </dependency>
</dependency> <dependency>
</dependencies> <groupId>io.github.earcut4j</groupId>
</dependencyManagement> <artifactId>earcut4j</artifactId>
<dependencies> <version>2.2.2</version>
<dependency> </dependency>
<groupId>org.mockito</groupId> </dependencies>
<artifactId>mockito-core</artifactId> </dependencyManagement>
<version>4.6.1</version> <dependencies>
<scope>test</scope> <dependency>
</dependency> <groupId>org.mockito</groupId>
<dependency> <artifactId>mockito-core</artifactId>
<groupId>org.openjfx</groupId> <version>4.6.1</version>
<artifactId>javafx-controls</artifactId> <scope>test</scope>
<version>${jfx-version}</version> </dependency>
</dependency> <dependency>
<dependency> <groupId>org.openjfx</groupId>
<groupId>org.openjfx</groupId> <artifactId>javafx-controls</artifactId>
<artifactId>javafx-fxml</artifactId> <version>${jfx-version}</version>
<version>${jfx-version}</version> </dependency>
</dependency> <dependency>
<dependency> <groupId>org.openjfx</groupId>
<groupId>org.openjfx</groupId> <artifactId>javafx-fxml</artifactId>
<artifactId>javafx-swing</artifactId> <version>${jfx-version}</version>
<version>${jfx-version}</version> </dependency>
</dependency> <dependency>
</dependencies> <groupId>org.openjfx</groupId>
<modules> <artifactId>javafx-swing</artifactId>
<!--CityDoctor2 Core Modules--> <version>${jfx-version}</version>
<module>CityDoctorModel</module> </dependency>
<module>CityDoctorValidation</module> </dependencies>
<module>CityDoctorEdge</module> <modules>
<module>CityDoctorCheckResult</module> <!--CityDoctor2 Core Modules-->
<module>CityDoctorModel</module>
<module>CityDoctorValidation</module>
<module>CityDoctorEdge</module>
<module>CityDoctorCheckResult</module>
<!--CityDoctor2 Extension Modules--> <!--CityDoctor2 Extension Modules-->
<module>Extensions/CityDoctorGUI</module> <module>Extensions/CityDoctorGUI</module>
<!-- <!--
<module>Extensions/CityDoctorAutoPro</module> <module>Extensions/CityDoctorAutoPro</module>
<module>Extensions/CityDoctorHealer</module> <module>Extensions/CityDoctorHealer</module>
<module>Extensions/CityDoctorHealerGenetic</module> <module>Extensions/CityDoctorHealerGenetic</module>
<module>Extensions/CityDoctorHealerGUI</module> <module>Extensions/CityDoctorHealerGUI</module>
<module>Extensions/CityDoctorWebService</module> <module>Extensions/CityDoctorWebService</module>
--> -->
</modules> </modules>
</project> </project>
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment