diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..0419d7a6db915922de4149ec531059d8d5b86383 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +/CityDoctorParent/.idea/.gitignore +/CityDoctorParent/.idea/compiler.xml +/CityDoctorParent/.idea/encodings.xml +/CityDoctorParent/.idea/jarRepositories.xml +/CityDoctorParent/.idea/misc.xml +/CityDoctorParent/.idea/vcs.xml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 33fe14f5e7dd8c7b95ed9dd470b5e47e25267142..252fe8726ada5ea91a14947d9f5d6e39c5dcf4a1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -4,7 +4,7 @@ image: maven:3.8.6-eclipse-temurin-17 build: script: - cd CityDoctorParent - - mvn verify + - mvn verify -U artifacts: when: always reports: diff --git a/CityDoctorParent/.gitignore b/CityDoctorParent/.gitignore index 66cb48d523a405794bac7259ed6a730903572707..dc201f269b74b1d9b5aef476b53ab09d5394997f 100644 --- a/CityDoctorParent/.gitignore +++ b/CityDoctorParent/.gitignore @@ -303,3 +303,8 @@ gradle-app.setting *.hprof # End of https://www.toptal.com/developers/gitignore/api/gradle +/CityDoctorWebService/CityDoctorWebService.iml +/Extensions/CityDoctorWebService/CityDoctorWebService.iml +/.idea/codeStyles/codeStyleConfig.xml +/GUISettings.properties +/.idea/inspectionProfiles/Project_Default.xml diff --git a/CityDoctorParent/CityDoctorCheckResult/pom.xml b/CityDoctorParent/CityDoctorCheckResult/pom.xml index f4fba91224f9a516b0ec6bff47075c6b760fcbb4..ff20e0aacdf1d73dae748125c43a5b44d63f1642 100644 --- a/CityDoctorParent/CityDoctorCheckResult/pom.xml +++ b/CityDoctorParent/CityDoctorCheckResult/pom.xml @@ -1,6 +1,5 @@ - - 4.0.0 + 4.0.0 de.hft.stuttgart CityDoctorParent diff --git a/CityDoctorParent/CityDoctorCheckResult/src/main/java/de/hft/stuttgart/citydoctor2/checkresult/utility/CheckReportParseException.java b/CityDoctorParent/CityDoctorCheckResult/src/main/java/de/hft/stuttgart/citydoctor2/checkresult/utility/CheckReportParseException.java index b45c5ccc2c85bff75ee988fddccd918ff715678f..3433f79cf2171c2e0d137f37421cce48dc958b24 100644 --- a/CityDoctorParent/CityDoctorCheckResult/src/main/java/de/hft/stuttgart/citydoctor2/checkresult/utility/CheckReportParseException.java +++ b/CityDoctorParent/CityDoctorCheckResult/src/main/java/de/hft/stuttgart/citydoctor2/checkresult/utility/CheckReportParseException.java @@ -18,8 +18,11 @@ */ package de.hft.stuttgart.citydoctor2.checkresult.utility; +import java.io.Serial; + public class CheckReportParseException extends Exception { + @Serial private static final long serialVersionUID = 6043371305010386110L; public CheckReportParseException() { diff --git a/CityDoctorParent/CityDoctorCheckResult/src/main/java/de/hft/stuttgart/citydoctor2/checkresult/utility/CheckReportWriteException.java b/CityDoctorParent/CityDoctorCheckResult/src/main/java/de/hft/stuttgart/citydoctor2/checkresult/utility/CheckReportWriteException.java index 227d1e63674c2a5941712d9a78f32e59608dbc37..3fe4523f08038e4903954c89e3f327311b9585b4 100644 --- a/CityDoctorParent/CityDoctorCheckResult/src/main/java/de/hft/stuttgart/citydoctor2/checkresult/utility/CheckReportWriteException.java +++ b/CityDoctorParent/CityDoctorCheckResult/src/main/java/de/hft/stuttgart/citydoctor2/checkresult/utility/CheckReportWriteException.java @@ -18,8 +18,11 @@ */ package de.hft.stuttgart.citydoctor2.checkresult.utility; +import java.io.Serial; + public class CheckReportWriteException extends Exception { + @Serial private static final long serialVersionUID = 1769358555887675233L; public CheckReportWriteException() { diff --git a/CityDoctorParent/CityDoctorCheckResult/src/main/java/de/hft/stuttgart/citydoctor2/checkresult/utility/IndentationXmlStreamWriter.java b/CityDoctorParent/CityDoctorCheckResult/src/main/java/de/hft/stuttgart/citydoctor2/checkresult/utility/IndentationXmlStreamWriter.java index 6cdb2358cce6b279115a1801c9bb1dd7768b6695..3bd3ab8242dfc82e446def51b1f2cd8726e7b405 100644 --- a/CityDoctorParent/CityDoctorCheckResult/src/main/java/de/hft/stuttgart/citydoctor2/checkresult/utility/IndentationXmlStreamWriter.java +++ b/CityDoctorParent/CityDoctorCheckResult/src/main/java/de/hft/stuttgart/citydoctor2/checkresult/utility/IndentationXmlStreamWriter.java @@ -34,7 +34,7 @@ public class IndentationXmlStreamWriter implements XMLStreamWriter { private static final String INDENTATION = " "; - private XMLStreamWriter writer; + private final XMLStreamWriter writer; private int depth = -1; boolean sameElement = true; diff --git a/CityDoctorParent/CityDoctorEdge/pom.xml b/CityDoctorParent/CityDoctorEdge/pom.xml index 12b788e84d4979da49a200b407d90dd05fe05baa..50ff90cd1fdd1c476dba9e07a6c60e1e19634c9b 100644 --- a/CityDoctorParent/CityDoctorEdge/pom.xml +++ b/CityDoctorParent/CityDoctorEdge/pom.xml @@ -1,6 +1,5 @@ - - 4.0.0 + 4.0.0 de.hft.stuttgart CityDoctorParent diff --git a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/BaseEntity.java b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/BaseEntity.java index 1463393749a463b000ab6d4cb3b6901a66d04350..6f0b74a6f24de3b2d81d3768392220a615a291e5 100644 --- a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/BaseEntity.java +++ b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/BaseEntity.java @@ -1,65 +1,66 @@ -/*- - * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart - * - * This file is part of CityDoctor2. - * - * CityDoctor2 is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * CityDoctor2 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with CityDoctor2. If not, see . - */ -package de.hft.stuttgart.citydoctor2.edge; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -public class BaseEntity { - - private List parents = new ArrayList<>(2); - private List children = new ArrayList<>(2); - - public void addChild(BaseEntity e) { - children.add(e); - e.parents.add(this); - } - - @SuppressWarnings("unchecked") - public List getParents(Class clazz) { - Set result = new HashSet<>(); - for (BaseEntity b : parents) { - if (clazz.isAssignableFrom(b.getClass())) { - result.add((T) b); - } - } - return new ArrayList<>(result); - } - - @SuppressWarnings("unchecked") - public List getChildren(Class clazz) { - List result = new ArrayList<>(); - for (BaseEntity b : children) { - if (b.getClass() == clazz) { - result.add((T) b); - } - } - return result; - } - - public void removeChild(BaseEntity pEntity) { - children.remove(pEntity); - - // check for multiple relationships - pEntity.parents.remove(this); - } - -} +/*- + * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart + * + * This file is part of CityDoctor2. + * + * CityDoctor2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CityDoctor2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with CityDoctor2. If not, see . + */ +package de.hft.stuttgart.citydoctor2.edge; + + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class BaseEntity { + + private final List parents = new ArrayList<>(2); + private final List children = new ArrayList<>(2); + + public void addChild(BaseEntity e) { + children.add(e); + e.parents.add(this); + } + + @SuppressWarnings("unchecked") + public List getParents(Class clazz) { + Set result = new HashSet<>(); + for (BaseEntity b : parents) { + if (clazz.isAssignableFrom(b.getClass())) { + result.add((T) b); + } + } + return new ArrayList<>(result); + } + + @SuppressWarnings("unchecked") + public List getChildren(Class clazz) { + List result = new ArrayList<>(); + for (BaseEntity b : children) { + if (b.getClass() == clazz) { + result.add((T) b); + } + } + return result; + } + + public void removeChild(BaseEntity pEntity) { + children.remove(pEntity); + + // check for multiple relationships + pEntity.parents.remove(this); + } + +} diff --git a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/Box2d.java b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/Box2d.java index 3de1274d8421c53e05fc78d9528e1b4f276ecdef..e424985068384cdb9abfd603f9e5ec1c033670a9 100644 --- a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/Box2d.java +++ b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/Box2d.java @@ -20,8 +20,8 @@ package de.hft.stuttgart.citydoctor2.edge; public class Box2d { - private Point2d mMin; - private Point2d mMax; + private final Point2d mMin; + private final Point2d mMax; public Box2d(Point2d min, Point2d max) { mMin = min; diff --git a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/CDPolygonNs.java b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/CDPolygonNs.java index 4c2eff27dae9cf0a4d883016127a0af003242f96..240aa97c3ad2a0de0ae3a10b831ced272f0b32d3 100644 --- a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/CDPolygonNs.java +++ b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/CDPolygonNs.java @@ -1,127 +1,128 @@ -/*- - * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart - * - * This file is part of CityDoctor2. - * - * CityDoctor2 is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * CityDoctor2 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with CityDoctor2. If not, see . - */ -package de.hft.stuttgart.citydoctor2.edge; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import de.hft.stuttgart.citydoctor2.datastructure.LinearRing; -import de.hft.stuttgart.citydoctor2.datastructure.Polygon; -import de.hft.stuttgart.citydoctor2.math.MovedPolygon; -import de.hft.stuttgart.citydoctor2.math.MovedRing; -import de.hft.stuttgart.citydoctor2.math.Vector3d; - -public class CDPolygonNs extends PolygonNs { - - private List> innerHalfEdges = new ArrayList<>(); - - public static CDPolygonNs of(Polygon p, Map pointMap) { - List> loopCoordinates = new ArrayList<>(); - List edgeExtRing = createCoordinatesFromRing(pointMap, p.getExteriorRing().getVertices()); - loopCoordinates.add(edgeExtRing); - - for (LinearRing innerRing : p.getInnerRings()) { - List edgeInnerRing = createCoordinatesFromRing(pointMap, innerRing.getVertices()); - loopCoordinates.add(edgeInnerRing); - } - - List> halfEdges = new ArrayList<>(); - for (List ringCoordinates : loopCoordinates) { - List currHeList = createHalfEdgesFromCoordinates(ringCoordinates); - halfEdges.add(currHeList); - } - - return new CDPolygonNs(halfEdges, p); - } - - public static CDPolygonNs of(MovedPolygon mp, Map pointMap) { - List> loopCoordinates = new ArrayList<>(); - List edgeExtRing = createCoordinatesFromRing(pointMap, mp.getExteriorRing().getVertices()); - loopCoordinates.add(edgeExtRing); - - for (MovedRing innerRing : mp.getInnerRings()) { - List edgeInnerRing = createCoordinatesFromRing(pointMap, innerRing.getVertices()); - loopCoordinates.add(edgeInnerRing); - } - - List> halfEdges = new ArrayList<>(); - for (List ringCoordinates : loopCoordinates) { - List currHeList = createHalfEdgesFromCoordinates(ringCoordinates); - halfEdges.add(currHeList); - } - - return new CDPolygonNs(halfEdges, mp.getOriginal()); - } - - private static List createHalfEdgesFromCoordinates(List ringCoordinates) { - List currHeList = new ArrayList<>(); - HalfEdge prevHalfEdge = null; - for (int currCoordIndex = 1; currCoordIndex < ringCoordinates.size(); currCoordIndex++) { - int prevCoordIndex = currCoordIndex - 1; - Coordinate3d currCoord = ringCoordinates.get(currCoordIndex); - Coordinate3d prevCoord = ringCoordinates.get(prevCoordIndex); - HalfEdge e = new HalfEdge(prevCoord, currCoord); - if (prevHalfEdge != null) { - prevHalfEdge.setNext(e); - } - currHeList.add(e); - prevHalfEdge = e; - } - if (prevHalfEdge == null) { - throw new IllegalStateException("No half edges were created"); - } - Coordinate3d start = ringCoordinates.get(0); - Coordinate3d end = ringCoordinates.get(ringCoordinates.size() - 1); - HalfEdge e = new HalfEdge(end, start); - prevHalfEdge.setNext(e); - e.setNext(currHeList.get(0)); - currHeList.add(e); - return currHeList; - } - - private static List createCoordinatesFromRing(Map pointMap, - List vertices) { - List edgeRing = new ArrayList<>(); - for (int i = 0; i < vertices.size() - 1; i++) { - Vector3d v = vertices.get(i); - Coordinate3d c = pointMap.computeIfAbsent(v, key -> new Coordinate3d(key.getX(), key.getY(), key.getZ())); - edgeRing.add(c); - } - return edgeRing; - } - - public CDPolygonNs(List> halfEdges, Polygon original) { - super(halfEdges.get(0), original); - - for (int i = 1; i < halfEdges.size(); i++) { - List loopEdges = halfEdges.get(i); - for (HalfEdge e : loopEdges) { - addChild(e); - } - innerHalfEdges.add(loopEdges); - } - } - - public List> getInnerHalfEdges() { - return innerHalfEdges; - } - - -} +/*- + * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart + * + * This file is part of CityDoctor2. + * + * CityDoctor2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CityDoctor2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with CityDoctor2. If not, see . + */ +package de.hft.stuttgart.citydoctor2.edge; + + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import de.hft.stuttgart.citydoctor2.datastructure.LinearRing; +import de.hft.stuttgart.citydoctor2.datastructure.Polygon; +import de.hft.stuttgart.citydoctor2.math.MovedPolygon; +import de.hft.stuttgart.citydoctor2.math.MovedRing; +import de.hft.stuttgart.citydoctor2.math.Vector3d; + +public class CDPolygonNs extends PolygonNs { + + private final List> innerHalfEdges = new ArrayList<>(); + + public static CDPolygonNs of(Polygon p, Map pointMap) { + List> loopCoordinates = new ArrayList<>(); + List edgeExtRing = createCoordinatesFromRing(pointMap, p.getExteriorRing().getVertices()); + loopCoordinates.add(edgeExtRing); + + for (LinearRing innerRing : p.getInnerRings()) { + List edgeInnerRing = createCoordinatesFromRing(pointMap, innerRing.getVertices()); + loopCoordinates.add(edgeInnerRing); + } + + List> halfEdges = new ArrayList<>(); + for (List ringCoordinates : loopCoordinates) { + List currHeList = createHalfEdgesFromCoordinates(ringCoordinates); + halfEdges.add(currHeList); + } + + return new CDPolygonNs(halfEdges, p); + } + + public static CDPolygonNs of(MovedPolygon mp, Map pointMap) { + List> loopCoordinates = new ArrayList<>(); + List edgeExtRing = createCoordinatesFromRing(pointMap, mp.getExteriorRing().getVertices()); + loopCoordinates.add(edgeExtRing); + + for (MovedRing innerRing : mp.getInnerRings()) { + List edgeInnerRing = createCoordinatesFromRing(pointMap, innerRing.getVertices()); + loopCoordinates.add(edgeInnerRing); + } + + List> halfEdges = new ArrayList<>(); + for (List ringCoordinates : loopCoordinates) { + List currHeList = createHalfEdgesFromCoordinates(ringCoordinates); + halfEdges.add(currHeList); + } + + return new CDPolygonNs(halfEdges, mp.getOriginal()); + } + + private static List createHalfEdgesFromCoordinates(List ringCoordinates) { + List currHeList = new ArrayList<>(); + HalfEdge prevHalfEdge = null; + for (int currCoordIndex = 1; currCoordIndex < ringCoordinates.size(); currCoordIndex++) { + int prevCoordIndex = currCoordIndex - 1; + Coordinate3d currCoord = ringCoordinates.get(currCoordIndex); + Coordinate3d prevCoord = ringCoordinates.get(prevCoordIndex); + HalfEdge e = new HalfEdge(prevCoord, currCoord); + if (prevHalfEdge != null) { + prevHalfEdge.setNext(e); + } + currHeList.add(e); + prevHalfEdge = e; + } + if (prevHalfEdge == null) { + throw new IllegalStateException("No half edges were created"); + } + Coordinate3d start = ringCoordinates.get(0); + Coordinate3d end = ringCoordinates.get(ringCoordinates.size() - 1); + HalfEdge e = new HalfEdge(end, start); + prevHalfEdge.setNext(e); + e.setNext(currHeList.get(0)); + currHeList.add(e); + return currHeList; + } + + private static List createCoordinatesFromRing(Map pointMap, + List vertices) { + List edgeRing = new ArrayList<>(); + for (int i = 0; i < vertices.size() - 1; i++) { + Vector3d v = vertices.get(i); + Coordinate3d c = pointMap.computeIfAbsent(v, key -> new Coordinate3d(key.getX(), key.getY(), key.getZ())); + edgeRing.add(c); + } + return edgeRing; + } + + public CDPolygonNs(List> halfEdges, Polygon original) { + super(halfEdges.get(0), original); + + for (int i = 1; i < halfEdges.size(); i++) { + List loopEdges = halfEdges.get(i); + for (HalfEdge e : loopEdges) { + addChild(e); + } + innerHalfEdges.add(loopEdges); + } + } + + public List> getInnerHalfEdges() { + return innerHalfEdges; + } + + +} diff --git a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/Coordinate3d.java b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/Coordinate3d.java index 5a550e450c87775f12e957ec3d3a1fbb122221ea..1ff4564f5cc3d6fcd51ad7a2e3bcf4ea9361b49f 100644 --- a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/Coordinate3d.java +++ b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/Coordinate3d.java @@ -1,59 +1,60 @@ -/*- - * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart - * - * This file is part of CityDoctor2. - * - * CityDoctor2 is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * CityDoctor2 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with CityDoctor2. If not, see . - */ -package de.hft.stuttgart.citydoctor2.edge; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -public class Coordinate3d extends BaseEntity { - - private Point3d point; - - public Coordinate3d(Point3d point) { - this.point = point; - } - - public Coordinate3d(double x, double y, double z) { - this(new Point3d(x, y, z)); - } - - public Point3d getPoint() { - return point; - } - - public List getPolygons() { - List halfEdges = getParents(HalfEdge.class); - - Set polygons = new HashSet<>(); - for (HalfEdge he : halfEdges) { - List localPolygons = he.getParents(EdgePolygon.class); - polygons.addAll(localPolygons); - } - - return new ArrayList<>(polygons); - } - - @Override - public String toString() { - return "Coordinate3d [point=" + point + "]"; - } - -} +/*- + * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart + * + * This file is part of CityDoctor2. + * + * CityDoctor2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CityDoctor2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with CityDoctor2. If not, see . + */ +package de.hft.stuttgart.citydoctor2.edge; + + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class Coordinate3d extends BaseEntity { + + private final Point3d point; + + public Coordinate3d(Point3d point) { + this.point = point; + } + + public Coordinate3d(double x, double y, double z) { + this(new Point3d(x, y, z)); + } + + public Point3d getPoint() { + return point; + } + + public List getPolygons() { + List halfEdges = getParents(HalfEdge.class); + + Set polygons = new HashSet<>(); + for (HalfEdge he : halfEdges) { + List localPolygons = he.getParents(EdgePolygon.class); + polygons.addAll(localPolygons); + } + + return new ArrayList<>(polygons); + } + + @Override + public String toString() { + return "Coordinate3d [point=" + point + "]"; + } + +} diff --git a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/EdgePolygon.java b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/EdgePolygon.java index daf30108a49b338670e52913ae018af3cddccec8..f2872c3f7a02b0471aea6db9f1c43c0c2826ec0c 100644 --- a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/EdgePolygon.java +++ b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/EdgePolygon.java @@ -1,127 +1,120 @@ -/*- - * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart - * - * This file is part of CityDoctor2. - * - * CityDoctor2 is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * CityDoctor2 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with CityDoctor2. If not, see . - */ -package de.hft.stuttgart.citydoctor2.edge; - -import java.util.ArrayList; -import java.util.List; - -import de.hft.stuttgart.citydoctor2.datastructure.Polygon; - -public class EdgePolygon extends BaseEntity { - - private Polygon original; - private List halfEdges; - - public EdgePolygon(List halfEdges, Polygon original) { - for (HalfEdge he : halfEdges) { - addChild(he); - } - this.halfEdges = halfEdges; - this.original = original; - } - - public Polygon getOriginal() { - return original; - } - - public GmPlane getPlane() { - Point3d midPoint = getMidPoint(); - - List children = getChildren(HalfEdge.class); - Vector3d averageNormalVector = new Vector3d(0.0, 0.0, 0.0); - - for (HalfEdge he : children) { - - Point3d start = he.getStart().getPoint(); - Point3d end = he.getEnd().getPoint(); - - Vector3d mid2Start = start.minus(midPoint); - Vector3d mid2End = end.minus(midPoint); - - averageNormalVector = averageNormalVector.plus(mid2Start.cross(mid2End)); - } - - UnitVector3d normalVector = averageNormalVector.toUnitVector(); - return new GmPlane(midPoint, normalVector); - } - - private Point3d getMidPoint() { - Point3d midPoint = new Point3d(0, 0, 0); - List children = getChildren(HalfEdge.class); - - for (HalfEdge he : children) { - midPoint = midPoint.plus(he.getStart().getPoint()); - } - return (midPoint.div(children.size())); - } - - public List getHalfEdges() { - return halfEdges; - } - - public List getCoordinates() { - List coords = new ArrayList<>(); - for (HalfEdge he : halfEdges) { - coords.add(he.getStart()); - } -// HalfEdge firstHE = Objects.requireNonNull(getFirstHalfEdge()); -// HalfEdge currHE = firstHE; -// do { -// coords.add(currHE.getStart()); -// currHE = currHE.getNext(); -// } while (currHE != firstHE); - return coords; - } - - public HalfEdge getFirstHalfEdge() { - if (!halfEdges.isEmpty()) { - return halfEdges.get(0); - } - return null; - } - - /** - * Test whether the given point is lying in- or outside of the non self - * intersecting, planar polygon. It's believed, that point and polygon are lying - * in the same plane.
- *
- * It's assumed, that the polygon is non self intersecting and planar. - * Additionally it is assumed, that the point and the polygon lying in the same - * plane. The given point is projected on the plane of the polygon. If the point - * is lying on an edge of the polygon it's supposed that the point is inside of - * the polygon - * - * @param rcPoint The point that should be checked - * - * @return true, if the point is inside the polygon, false otherwise - * - */ - public boolean isPointInsidePolygon(Point3d rcPoint, double eps) { - // Project the coordinate of the point on the plane - GmPlane plane = getPlane(); - Point2d projectedPoint = plane.project(rcPoint); - Polygon2d pP = plane.projectOn2dPolygon(this); - return pP.isPointInsidePolygon(projectedPoint, eps); - } - - public int getNrHalfEdges() { - return halfEdges.size(); - } - -} +/*- + * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart + * + * This file is part of CityDoctor2. + * + * CityDoctor2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CityDoctor2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with CityDoctor2. If not, see . + */ +package de.hft.stuttgart.citydoctor2.edge; + + +import java.util.ArrayList; +import java.util.List; + +import de.hft.stuttgart.citydoctor2.datastructure.Polygon; + +public class EdgePolygon extends BaseEntity { + + private final Polygon original; + private final List halfEdges; + + public EdgePolygon(List halfEdges, Polygon original) { + for (HalfEdge he : halfEdges) { + addChild(he); + } + this.halfEdges = halfEdges; + this.original = original; + } + + public Polygon getOriginal() { + return original; + } + + public GmPlane getPlane() { + Point3d midPoint = getMidPoint(); + + List children = getChildren(HalfEdge.class); + Vector3d averageNormalVector = new Vector3d(0.0, 0.0, 0.0); + + for (HalfEdge he : children) { + + Point3d start = he.getStart().getPoint(); + Point3d end = he.getEnd().getPoint(); + + Vector3d mid2Start = start.minus(midPoint); + Vector3d mid2End = end.minus(midPoint); + + averageNormalVector = averageNormalVector.plus(mid2Start.cross(mid2End)); + } + + UnitVector3d normalVector = averageNormalVector.toUnitVector(); + return new GmPlane(midPoint, normalVector); + } + + private Point3d getMidPoint() { + Point3d midPoint = new Point3d(0, 0, 0); + List children = getChildren(HalfEdge.class); + + for (HalfEdge he : children) { + midPoint = midPoint.plus(he.getStart().getPoint()); + } + return (midPoint.div(children.size())); + } + + public List getHalfEdges() { + return halfEdges; + } + + public List getCoordinates() { + List coords = new ArrayList<>(); + for (HalfEdge he : halfEdges) { + coords.add(he.getStart()); + } + return coords; + } + + public HalfEdge getFirstHalfEdge() { + if (!halfEdges.isEmpty()) { + return halfEdges.get(0); + } + return null; + } + + /** + * Test whether the given point is lying inside the non-self- + * intersecting, planar polygon. It's believed, that point and polygon are lying + * in the same plane.
+ *
+ * It's assumed, that the polygon is non-self-intersecting and planar, and that the point is + * lying in the same plane. The given point is projected on the plane of the polygon. If the point is lying on an edge + * of the polygon, it is considered to be inside. + * + * @param rcPoint The point that should be checked + * + * @return true, if the point is inside the polygon, false otherwise + * + */ + public boolean isPointInsidePolygon(Point3d rcPoint, double eps) { + // Project the coordinate of the point on the plane + GmPlane plane = getPlane(); + Point2d projectedPoint = plane.project(rcPoint); + Polygon2d pP = plane.projectOn2dPolygon(this); + return pP.isPointInsidePolygon(projectedPoint, eps); + } + + public int getNrHalfEdges() { + return halfEdges.size(); + } + +} diff --git a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/Global.java b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/Global.java index d9db253ed466eefc091b91a3cd43bc7db8c09bd7..1d5762d5c8867b57ac2dba800428f80dd963c6ac 100644 --- a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/Global.java +++ b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/Global.java @@ -1,61 +1,60 @@ -/*- - * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart - * - * This file is part of CityDoctor2. - * - * CityDoctor2 is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * CityDoctor2 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with CityDoctor2. If not, see . - */ -package de.hft.stuttgart.citydoctor2.edge; - -import java.util.Comparator; - -public class Global { - - private static final double DBL_EPSILON = 2.2204460492503131e-16; - - private static double mZeroAngleCosinus = 1.0e-9; - private static double mTolVectorsParallel = 1e-9; - private static double mHighAccuracyTol = DBL_EPSILON * 5; - private static double mTolPointsEqual = 1e-3; - - private Global() { - } - - public static double getTolPointsEquals() { - return mTolPointsEqual; - } - - public static double getHighAccuracyTolerance() { - return mHighAccuracyTol; - } - - public static Comparator getDoubleTolCompare(double epsilon) { - return (v1, v2) -> { - double dif = v1 - v2; - if (Math.abs(dif) < epsilon) { - return 0; - } - return Double.compare(v1, v2); - }; - } - - public static double getZeroAngleCosinus() { - return mZeroAngleCosinus; - } - - public static double getTolVectorsParallel() { - return mTolVectorsParallel; - } - -} +/*- + * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart + * + * This file is part of CityDoctor2. + * + * CityDoctor2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CityDoctor2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with CityDoctor2. If not, see . + */ +package de.hft.stuttgart.citydoctor2.edge; + + +import java.util.Comparator; + +public class Global { + + private static final double DBL_EPSILON = 2.2204460492503131e-16; + + private static final double M_ZERO_ANGLE_COSINE = 1.0e-9; + private static final double M_TOL_VECTORS_PARALLEL = 1e-9; + private static final double M_HIGH_ACCURACY_TOL = DBL_EPSILON * 5; + private static final double M_TOL_POINTS_EQUAL = 1e-3; + + private Global() { + } + + public static double getTolPointsEquals() { + return M_TOL_POINTS_EQUAL; + } + + public static double getHighAccuracyTolerance() { + return M_HIGH_ACCURACY_TOL; + } + + public static Comparator getDoubleTolCompare(double epsilon) { + return (v1, v2) -> { + double dif = v1 - v2; + if (Math.abs(dif) < epsilon) { + return 0; + } + return Double.compare(v1, v2); + }; + } + + public static double getZeroAngleCosine() { return M_ZERO_ANGLE_COSINE; } + + public static double getTolVectorsParallel() { + return M_TOL_VECTORS_PARALLEL; + } + +} diff --git a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/GmBoundedStraight2d.java b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/GmBoundedStraight2d.java index 5e2bfd548311fb7400b971f2fe29fdf7ccf61ea6..ce47088448f36659ac1bc888c16fb09d7e08d873 100644 --- a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/GmBoundedStraight2d.java +++ b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/GmBoundedStraight2d.java @@ -1,71 +1,69 @@ -/*- - * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart - * - * This file is part of CityDoctor2. - * - * CityDoctor2 is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * CityDoctor2 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with CityDoctor2. If not, see . - */ -package de.hft.stuttgart.citydoctor2.edge; - -public class GmBoundedStraight2d extends GmStraight2d { - - private double length; - private Point2d target; - - public static GmBoundedStraight2d of(Point2d start, Vector2d dir) { - GmBoundedStraight2d straight = new GmBoundedStraight2d(start, dir); - straight.target = straight.getOrigin().plus(dir); - straight.length = dir.getLength(); - return straight; - } - - public static GmBoundedStraight2d of(Point2d from, Point2d to) { - Vector2d dir = to.minus(from); - GmBoundedStraight2d straight = new GmBoundedStraight2d(from, dir); - straight.target = to; - straight.length = dir.getLength(); - return straight; - } - - private GmBoundedStraight2d(Point2d start, Vector2d dir) { - super(start, dir); - } - - public Point2d getTarget() { - return target; - } - - public boolean isWithinBoundaries(double parameter, double eps) { - if (Math.abs(parameter) < eps) { - parameter = 0.0; - } - if (Math.abs(parameter - length) < eps) { - parameter = length; - } - - if (0 <= parameter && parameter <= length) { - return true; - } - return false; - } - - public double getLength() { - return length; - } - - public boolean isWithinBoundaries(double parameter) { - return isWithinBoundaries(parameter, Global.getHighAccuracyTolerance()); - } - -} +/*- + * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart + * + * This file is part of CityDoctor2. + * + * CityDoctor2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CityDoctor2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with CityDoctor2. If not, see . + */ +package de.hft.stuttgart.citydoctor2.edge; + + +public class GmBoundedStraight2d extends GmStraight2d { + + private double length; + private Point2d target; + + public static GmBoundedStraight2d of(Point2d start, Vector2d dir) { + GmBoundedStraight2d straight = new GmBoundedStraight2d(start, dir); + straight.target = straight.getOrigin().plus(dir); + straight.length = dir.getLength(); + return straight; + } + + public static GmBoundedStraight2d of(Point2d from, Point2d to) { + Vector2d dir = to.minus(from); + GmBoundedStraight2d straight = new GmBoundedStraight2d(from, dir); + straight.target = to; + straight.length = dir.getLength(); + return straight; + } + + private GmBoundedStraight2d(Point2d start, Vector2d dir) { + super(start, dir); + } + + public Point2d getTarget() { + return target; + } + + public boolean isWithinBoundaries(double parameter, double eps) { + if (Math.abs(parameter) < eps) { + parameter = 0.0; + } + if (Math.abs(parameter - length) < eps) { + parameter = length; + } + + return 0 <= parameter && parameter <= length; + } + + public double getLength() { + return length; + } + + public boolean isWithinBoundaries(double parameter) { + return isWithinBoundaries(parameter, Global.getHighAccuracyTolerance()); + } + +} diff --git a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/GmPlane.java b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/GmPlane.java index 39cbf5a5a5a469dce7dc291e1f55a93b66f21963..b5f2e1248bcf61a2a864343aaa7624c6e8271f9f 100644 --- a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/GmPlane.java +++ b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/GmPlane.java @@ -1,154 +1,156 @@ -/*- - * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart - * - * This file is part of CityDoctor2. - * - * CityDoctor2 is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * CityDoctor2 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with CityDoctor2. If not, see . - */ -package de.hft.stuttgart.citydoctor2.edge; - -import java.util.ArrayList; -import java.util.List; - -public class GmPlane { - - private Point3d x0; - - private UnitVector3d r1; - private UnitVector3d r2; - - private UnitVector3d n; - private double d; - - public GmPlane(Point3d point, UnitVector3d normalVector) { - x0 = point; - n = normalVector; - d = new Vector3d(point).dot(n); - - r1 = UnitVector3d.of(n.getZ(), n.getX(), n.getY()); - r2 = n.cross(r1).toUnitVector(); - - // r1 ist nicht in allen Faellen rechtwinklig zur Flaechennormalen - // daher nochmal eine neu Berechnung; - // ---------------------------------------------------------------- - r1 = n.cross(r2).toUnitVector(); - - } - - public double getDistance() { - return d; - } - - public Vector3d getNormal() { - return n; - } - - public Point3d evaluate(Point2d point) { - return evaluate(point.getX(), point.getY()); - } - - private Point3d evaluate(double x, double y) { - Vector3d vectorU = r1.mult(x); - Vector3d vectorV = r2.mult(y); - return new Point3d(x0.plus(vectorU).plus(vectorV)); - } - - public GmStraight2d projectOn2dStraight(GmStraight crStraight) { - Point2d start = project(crStraight.getOrigin()); - Point2d end = project(crStraight.getOrigin().plus(crStraight.getDir())); - return new GmStraight2d(start, end); - } - - public GmBoundedStraight2d projectOn2dStraight(GmBoundedStraight crBoundedStraight) { - Point2d start = project(crBoundedStraight.getOrigin()); - Point2d end = project(crBoundedStraight.getTarget()); - return GmBoundedStraight2d.of(start, end); - } - - public Point2d project(Point3d crPoint) { - GmStraight firstAxis = new GmStraight(x0, r1); - GmStraight secondAxis = new GmStraight(x0, r2); - - double u = firstAxis.project(crPoint).getParameter(); - double v = secondAxis.project(crPoint).getParameter(); - - return new Point2d(u, v); - } - - public GmStraight planeIntersection(GmPlane other) { - // get plane normals and distances - // ------------------------------- - Vector3d normal1 = getNormal(); - Vector3d normal2 = other.getNormal(); - double dist1 = getDistance(); - double dist2 = other.getDistance(); - - // planes (normal vectors) parallel? -> good bye - // --------------------------------------------- - if (Vector3d.areParallel(normal1, normal2) || Vector3d.areAntiParallel(normal1, normal2)) { - return null; // but rSuccess is false - } - - // get direction and origin for straight - // ------------------------------------- - Vector3d dir = normal1.cross(normal2); - - Matrix3d matrix = new Matrix3d(); - - matrix.set(0, 0, normal1.getX()); - matrix.set(0, 1, normal1.getY()); - matrix.set(0, 2, normal1.getZ()); - - matrix.set(1, 0, normal2.getX()); - matrix.set(1, 1, normal2.getY()); - matrix.set(1, 2, normal2.getZ()); - - matrix.set(2, 0, dir.getX()); - matrix.set(2, 1, dir.getY()); - matrix.set(2, 2, dir.getZ()); - - double[] b = new double[] { dist1, dist2, 0.0 }; - double[] org = new double[3]; - matrix.gauss(b, org); - - return new GmStraight(new Point3d(org), dir); - } - - public Polygon2d projectOn2dPolygon(EdgePolygon cpPolygon) { - HalfEdge startHE = cpPolygon.getFirstHalfEdge(); - HalfEdge currHE = startHE; - int numHEs = cpPolygon.getNrHalfEdges(); - Coordinate2d[] coords = new Coordinate2d[numHEs]; - int i = 0; - do { - Coordinate3d coord = currHE.getStart(); - Point2d p = project(coord.getPoint()); - coords[i++] = new Coordinate2d(p); - currHE = currHE.getNext(); - } while (currHE != startHE); - - List halfedges = new ArrayList<>(); - for (i = 0; i < numHEs; ++i) { - HalfEdge2d he = new HalfEdge2d(coords[i], coords[(i + 1) % (numHEs)]); - halfedges.add(he); - } - - return new Polygon2d(halfedges); - } - - public Point3d getPoint() { - return x0; - } - -} +/*- + * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart + * + * This file is part of CityDoctor2. + * + * CityDoctor2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CityDoctor2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with CityDoctor2. If not, see . + */ +package de.hft.stuttgart.citydoctor2.edge; + + +import java.util.ArrayList; +import java.util.List; + +public class GmPlane { + + private final Point3d x0; + + private final UnitVector3d r1; + private final UnitVector3d r2; + + private final UnitVector3d n; + private final double d; + + public GmPlane(Point3d point, UnitVector3d normalVector) { + x0 = point; + n = normalVector; + d = new Vector3d(point).dot(n); + + UnitVector3d r = UnitVector3d.of(n.getZ(), n.getX(), n.getY()); + r2 = n.cross(r).toUnitVector(); + + + // r is not always perpendicular to the plane's normal vector, + // recalculate using r2 + // ---------------------------------------------------------------- + r1 = n.cross(r2).toUnitVector(); + + } + + public double getDistance() { + return d; + } + + public Vector3d getNormal() { + return n; + } + + public Point3d evaluate(Point2d point) { + return evaluate(point.getX(), point.getY()); + } + + private Point3d evaluate(double x, double y) { + Vector3d vectorU = r1.mult(x); + Vector3d vectorV = r2.mult(y); + return new Point3d(x0.plus(vectorU).plus(vectorV)); + } + + public GmStraight2d projectOn2dStraight(GmStraight crStraight) { + Point2d start = project(crStraight.getOrigin()); + Point2d end = project(crStraight.getOrigin().plus(crStraight.getDir())); + return new GmStraight2d(start, end); + } + + public GmBoundedStraight2d projectOn2dStraight(GmBoundedStraight crBoundedStraight) { + Point2d start = project(crBoundedStraight.getOrigin()); + Point2d end = project(crBoundedStraight.getTarget()); + return GmBoundedStraight2d.of(start, end); + } + + public Point2d project(Point3d crPoint) { + GmStraight firstAxis = new GmStraight(x0, r1); + GmStraight secondAxis = new GmStraight(x0, r2); + + double u = firstAxis.project(crPoint).getParameter(); + double v = secondAxis.project(crPoint).getParameter(); + + return new Point2d(u, v); + } + + public GmStraight planeIntersection(GmPlane other) { + // get plane normals and distances + // ------------------------------- + Vector3d normal1 = getNormal(); + Vector3d normal2 = other.getNormal(); + double dist1 = getDistance(); + double dist2 = other.getDistance(); + + // planes (normal vectors) parallel? -> good bye + // --------------------------------------------- + if (Vector3d.areParallel(normal1, normal2) || Vector3d.areAntiParallel(normal1, normal2)) { + return null; // but rSuccess is false + } + + // get direction and origin for straight + // ------------------------------------- + Vector3d dir = normal1.cross(normal2); + + Matrix3d matrix = new Matrix3d(); + + matrix.set(0, 0, normal1.getX()); + matrix.set(0, 1, normal1.getY()); + matrix.set(0, 2, normal1.getZ()); + + matrix.set(1, 0, normal2.getX()); + matrix.set(1, 1, normal2.getY()); + matrix.set(1, 2, normal2.getZ()); + + matrix.set(2, 0, dir.getX()); + matrix.set(2, 1, dir.getY()); + matrix.set(2, 2, dir.getZ()); + + double[] b = new double[] { dist1, dist2, 0.0 }; + double[] org = new double[3]; + matrix.gauss(b, org); + + return new GmStraight(new Point3d(org), dir); + } + + public Polygon2d projectOn2dPolygon(EdgePolygon cpPolygon) { + HalfEdge startHE = cpPolygon.getFirstHalfEdge(); + HalfEdge currHE = startHE; + int numHEs = cpPolygon.getNrHalfEdges(); + Coordinate2d[] coords = new Coordinate2d[numHEs]; + int i = 0; + do { + Coordinate3d coord = currHE.getStart(); + Point2d p = project(coord.getPoint()); + coords[i++] = new Coordinate2d(p); + currHE = currHE.getNext(); + } while (currHE != startHE); + + List halfedges = new ArrayList<>(); + for (i = 0; i < numHEs; ++i) { + HalfEdge2d he = new HalfEdge2d(coords[i], coords[(i + 1) % (numHEs)]); + halfedges.add(he); + } + + return new Polygon2d(halfedges); + } + + public Point3d getPoint() { + return x0; + } + +} diff --git a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/GmStraight.java b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/GmStraight.java index 4c31926bb517b8af72b14ee4a5eca68deb9451c4..49f533960ead25a1f99a430547d5aab88a89237a 100644 --- a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/GmStraight.java +++ b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/GmStraight.java @@ -1,88 +1,85 @@ -/*- - * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart - * - * This file is part of CityDoctor2. - * - * CityDoctor2 is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * CityDoctor2 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with CityDoctor2. If not, see . - */ -package de.hft.stuttgart.citydoctor2.edge; - -public class GmStraight { - - private Point3d org; - private UnitVector3d dir; - - public GmStraight(Point3d org, Vector3d dir) { - this.org = org; - this.dir = dir.toUnitVector(); - } - - public GmStraight(Point3d org, UnitVector3d dir) { - this.org = org; - this.dir = dir; - } - - public ProjectedPoint3d project(Point3d origin) { - Vector3d v2Origin = origin.minus(org); - - double length = v2Origin.getLength(); - if (length < Global.getTolPointsEquals()) { - return new ProjectedPoint3d(origin, 0.0); - } - - double parameter = dir.dot(UnitVector3d.of(v2Origin)) * length; - Point3d foot = evaluate(parameter); - return new ProjectedPoint3d(foot, parameter); - } - - public Point3d evaluate(double param) { - return org.plus(dir.mult(param)); - } - - public UnitVector3d getDir() { - return dir; - } - - public boolean isColinear(GmStraight straight2, double angleEpsilon, double epsilon) { - UnitVector3d rDir1 = getDir(); - UnitVector3d rDir2 = straight2.getDir(); - - if ((!Vector3d.areParallel(rDir1, rDir2, angleEpsilon)) - && (!Vector3d.areAntiParallel(rDir1, rDir2, angleEpsilon))) { - - return false; - } - - Point3d rOrigin1 = getOrigin(); - - Point3d foot1 = straight2.project(rOrigin1).getPoint(); - if ((foot1.minus(rOrigin1)).getLength() > epsilon) { - return false; - } - - Point3d rOrigin2 = straight2.getOrigin(); - - Point3d foot2 = project(rOrigin2).getPoint(); - if ((foot2.minus(rOrigin2)).getLength() > epsilon) { - return false; - } - - return true; - } - - public Point3d getOrigin() { - return org; - } - -} +/*- + * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart + * + * This file is part of CityDoctor2. + * + * CityDoctor2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CityDoctor2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with CityDoctor2. If not, see . + */ +package de.hft.stuttgart.citydoctor2.edge; + + +public class GmStraight { + + private final Point3d org; + private final UnitVector3d dir; + + public GmStraight(Point3d org, Vector3d dir) { + this.org = org; + this.dir = dir.toUnitVector(); + } + + public GmStraight(Point3d org, UnitVector3d dir) { + this.org = org; + this.dir = dir; + } + + public ProjectedPoint3d project(Point3d origin) { + Vector3d v2Origin = origin.minus(org); + + double length = v2Origin.getLength(); + if (length < Global.getTolPointsEquals()) { + return new ProjectedPoint3d(origin, 0.0); + } + + double parameter = dir.dot(UnitVector3d.of(v2Origin)) * length; + Point3d foot = evaluate(parameter); + return new ProjectedPoint3d(foot, parameter); + } + + public Point3d evaluate(double param) { + return org.plus(dir.mult(param)); + } + + public UnitVector3d getDir() { + return dir; + } + + public boolean isCollinear(GmStraight straight2, double angleEpsilon, double epsilon) { + UnitVector3d rDir1 = getDir(); + UnitVector3d rDir2 = straight2.getDir(); + + if ((!Vector3d.areParallel(rDir1, rDir2, angleEpsilon)) + && (!Vector3d.areAntiParallel(rDir1, rDir2, angleEpsilon))) { + + return false; + } + + Point3d rOrigin1 = getOrigin(); + + Point3d foot1 = straight2.project(rOrigin1).getPoint(); + if ((foot1.minus(rOrigin1)).getLength() > epsilon) { + return false; + } + + Point3d rOrigin2 = straight2.getOrigin(); + + Point3d foot2 = project(rOrigin2).getPoint(); + return ((foot2.minus(rOrigin2)).getLength() <= epsilon); + } + + public Point3d getOrigin() { + return org; + } + +} diff --git a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/GmStraight2d.java b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/GmStraight2d.java index 341d6cbafe39497a7dc7950d7f83345e6a45f1a5..b81ea9b5cd9ee788d5902969524a0cbf98a27494 100644 --- a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/GmStraight2d.java +++ b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/GmStraight2d.java @@ -18,10 +18,12 @@ */ package de.hft.stuttgart.citydoctor2.edge; + public class GmStraight2d { - private Point2d origin; - private UnitVector2d direction; + private final Point2d origin; + private final UnitVector2d direction; + public GmStraight2d(Point2d org, UnitVector2d dir) { this.direction = dir; @@ -39,14 +41,13 @@ public class GmStraight2d { } /** - * Just intersects two GmStraights2d. - * + * Intersects this straight with another straight. *
*
- * If the two straights are parallel the method will return false, so the user - * has to determine, if the straight are just parallel or identical + * If the two straights are parallel, areParallel in the returned IntersectionResult will be true. + * This method will not differentiate between parallel and identical straights. * - * @param other First Straight + * @param other the other straight * * @return intersection result */ @@ -60,7 +61,7 @@ public class GmStraight2d { Vector2d r2Perpendicular = r2.getPerpendicularVector(); double diff = r1.dot(r2Perpendicular); - if (Math.abs(diff) < Global.getZeroAngleCosinus()) { + if (Math.abs(diff) < Global.getZeroAngleCosine()) { return GmStraight2dIntersectionResult.parallel(this, other); } else { double invR1DotPerpR2 = 1.0 / diff; diff --git a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/GmStraight2dIntersectionResult.java b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/GmStraight2dIntersectionResult.java index baf0385610bfb56c75f6851987b9836ee07976a1..00401f354e298c2b29975c21de53c4293f06aa54 100644 --- a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/GmStraight2dIntersectionResult.java +++ b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/GmStraight2dIntersectionResult.java @@ -1,69 +1,35 @@ -/*- - * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart - * - * This file is part of CityDoctor2. - * - * CityDoctor2 is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * CityDoctor2 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with CityDoctor2. If not, see . - */ -package de.hft.stuttgart.citydoctor2.edge; - -public class GmStraight2dIntersectionResult { - - private double paramHE; - private double paramInt; - - private GmStraight2d straightHE; - private GmStraight2d straightInt; - - private boolean areParallel; - - public static GmStraight2dIntersectionResult parallel(GmStraight2d s1, GmStraight2d s2) { - return new GmStraight2dIntersectionResult(0, 0, s1, s2, true); - } - - public static GmStraight2dIntersectionResult intersecting(double paramHE, double paramInt, GmStraight2d straightHE, - GmStraight2d straightInt) { - return new GmStraight2dIntersectionResult(paramHE, paramInt, straightHE, straightInt, false); - } - - private GmStraight2dIntersectionResult(double paramHE, double paramInt, GmStraight2d straightHE, - GmStraight2d straightInt, boolean areParallel) { - this.paramHE = paramHE; - this.paramInt = paramInt; - this.straightHE = straightHE; - this.straightInt = straightInt; - this.areParallel = areParallel; - } - - public double getParamHE() { - return paramHE; - } - - public double getParamInt() { - return paramInt; - } - - public GmStraight2d getStraightHE() { - return straightHE; - } - - public GmStraight2d getStraightInt() { - return straightInt; - } - - public boolean areParallel() { - return areParallel; - } - -} +/*- + * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart + * + * This file is part of CityDoctor2. + * + * CityDoctor2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CityDoctor2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with CityDoctor2. If not, see . + */ +package de.hft.stuttgart.citydoctor2.edge; + + +public record GmStraight2dIntersectionResult(double paramHE, double paramInt, GmStraight2d straightHE, + GmStraight2d straightInt, boolean areParallel) { + + public static GmStraight2dIntersectionResult parallel(GmStraight2d s1, GmStraight2d s2) { + return new GmStraight2dIntersectionResult(0, 0, s1, s2, true); + } + + public static GmStraight2dIntersectionResult intersecting(double paramHE, double paramInt, GmStraight2d straightHE, + GmStraight2d straightInt) { + return new GmStraight2dIntersectionResult(paramHE, paramInt, straightHE, straightInt, false); + } + + +} diff --git a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/HalfEdge.java b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/HalfEdge.java index 1aa87163dde95e57264bc5d79f3a9a266e607403..1494c95201cf22e777c28de380112ec4360c6da1 100644 --- a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/HalfEdge.java +++ b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/HalfEdge.java @@ -108,7 +108,7 @@ public class HalfEdge extends BaseEntity { HalfEdge pNextPartner = this.partner; while (pNextPartner != this) { if (pNextPartner == partner) { - logger.debug("(HalfEdge " + partner + " already exits in chain"); + logger.debug(String.format("(HalfEdge %s already exits in chain", partner)); return; } pNextPartner = pNextPartner.partner; @@ -141,7 +141,7 @@ public class HalfEdge extends BaseEntity { pPreviousPartner.partner = this; this.partner = partner; } else { - /** + /* * TODO : das riecht nach einer Ringverzeigerung : 3 Polygonraender treffen auf * einander */ diff --git a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/HalfEdge2d.java b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/HalfEdge2d.java index a7c332c1bd4ba636199580ac3218ebd64053aeca..0fdf766e4ac85bbc2a7243aa42deab83d34b5ea5 100644 --- a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/HalfEdge2d.java +++ b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/HalfEdge2d.java @@ -22,8 +22,8 @@ import java.util.List; public class HalfEdge2d extends BaseEntity { - private Coordinate2d start; - private Coordinate2d end; + private final Coordinate2d start; + private final Coordinate2d end; private HalfEdge2d partner; @@ -71,7 +71,7 @@ public class HalfEdge2d extends BaseEntity { return pPartner; } - private HalfEdge2d setPartner(HalfEdge2d pPartner) { + private void setPartner(HalfEdge2d pPartner) { if (partner != null) { if (pPartner != null) { throw new IllegalStateException("cannot overwrite existing partner-connection"); @@ -92,7 +92,6 @@ public class HalfEdge2d extends BaseEntity { } } } - return pPartner; } public HalfEdge2d getPartner() { diff --git a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/IntersectPlanarPolygons.java b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/IntersectPlanarPolygons.java index 9a6ddfc62609c5e8f4af8cc2186534c9ee2d7f07..290b264797fa972d9c75ca085a83326bd35b0c3e 100644 --- a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/IntersectPlanarPolygons.java +++ b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/IntersectPlanarPolygons.java @@ -82,20 +82,7 @@ public class IntersectPlanarPolygons { for (Interval in2 : intervals2) { if (in1.isOverlapping(in2)) { Interval overlap = in1.overlap(in2); - Point3d start = straight.evaluate(overlap.getStart()); - if (overlap.getLength() < Global.getHighAccuracyTolerance() * 1e6) { - checkAndAddRealIntersectionPoint(cpPolygon1, cpPolygon2, start, intersections, epsilon); - } else { - Point3d end = straight.evaluate(overlap.getEnd()); - PolyLine pPL = new PolyLine(new Coordinate3d(start), new Coordinate3d(end)); - - if (!isPolyLineASharedEdge(cpPolygon1, pPL)) { - PolygonPolygonIntersection pPPI = new PolygonPolygonIntersection(cpPolygon1, cpPolygon2, - pPL); - intersections.add(pPPI); - } - - } + handleIntersectionIntervalOverlap(cpPolygon1, cpPolygon2, straight, intersections, epsilon, overlap); } else if (Math.abs(in1.getStart() - in2.getEnd()) < Global.getHighAccuracyTolerance()) { // check if the overlaps with a tolerance (numeric errors) Point3d point = straight.evaluate(in1.getStart()); @@ -108,6 +95,25 @@ public class IntersectPlanarPolygons { } } + private static void handleIntersectionIntervalOverlap(EdgePolygon cpPolygon1, EdgePolygon cpPolygon2, + GmStraight straight, List intersections, double epsilon, Interval overlap) { + + Point3d start = straight.evaluate(overlap.getStart()); + if (overlap.getLength() < Global.getHighAccuracyTolerance() * 1e6) { + checkAndAddRealIntersectionPoint(cpPolygon1, cpPolygon2, start, intersections, epsilon); + } else { + Point3d end = straight.evaluate(overlap.getEnd()); + PolyLine pPL = new PolyLine(new Coordinate3d(start), new Coordinate3d(end)); + + if (!isPolyLineASharedEdge(cpPolygon1, pPL)) { + PolygonPolygonIntersection pPPI = new PolygonPolygonIntersection(cpPolygon1, cpPolygon2, + pPL); + intersections.add(pPPI); + } + + } + } + private static boolean isPolyLineASharedEdge(EdgePolygon p1, PolyLine polyLine) { // get coordinates of the poly line Point3d polyLineStart = polyLine.getStart().getPoint(); @@ -136,10 +142,12 @@ public class IntersectPlanarPolygons { /** * - * Checks if the given point is a "real" intersection point and add's it to the - * intersection segments member variable. Real means, that this point isn't - * shared by both polygons as corner point. - * + * Checks if the given point is a 'real' intersection point and adds it to the + * intersection segments member variable. 'Real' meaning, that this point isn't + * a shared corner point of both polygons. + * + * @param p1 First polygon + * @param p2 Second polygon * @param point A possible intersection point */ private static void checkAndAddRealIntersectionPoint(EdgePolygon p1, EdgePolygon p2, Point3d point, @@ -200,7 +208,6 @@ public class IntersectPlanarPolygons { * with the exception, that the straight and the half edges of the polygon will * be projected on the plane of the polygon, so the calculation of the * intersection will be reduced to a 2d problem. - * * The intersection intervals contains pairs of parameters from the intersection * straight. If an intersection between the straight and the polygon contains * only a point, the according interval will contain the same parameter twice @@ -239,7 +246,7 @@ public class IntersectPlanarPolygons { GmBoundedStraight heStraight = e.getStraight(); // Straights are colinear; checked in the handleEmdeddedEdges method - if (heStraight.isColinear(intersectingStraight, angleEpsilon, epsilon)) { + if (heStraight.isCollinear(intersectingStraight, angleEpsilon, epsilon)) { continue; } @@ -256,7 +263,7 @@ public class IntersectPlanarPolygons { // check if the straight of the HalfEdge is collinear to the intersection // straight; this might result in an embedded edge intersection result // TODO MW: really needed? this check is also made some lines above - if (heStraight.isColinear(intersectingStraight, angleEpsilon, epsilon)) { + if (heStraight.isCollinear(intersectingStraight, angleEpsilon, epsilon)) { currHESharesAPntWithTheOtherPolygon = false; } @@ -271,39 +278,7 @@ public class IntersectPlanarPolygons { GmBoundedStraight2d heStraight2d = polyPlane.projectOn2dStraight(heStraight); GmStraight2dIntersectionResult intersectionResult = heStraight2d.intersect(intersectingStraight2d); - if (intersectionResult.areParallel()) { - Vector2d dir = intersectingStraight2d.getDirection(); - Vector2d diffVec = heStraight2d.getOrigin().minus(intersectingStraight2d.getOrigin()); - double diffVecDotPerpDir = diffVec.dot(dir.getPerpendicularVector()); - - if (Math.abs(diffVecDotPerpDir) < Global.getZeroAngleCosinus()) { - // Straights are identical - Point2d p1 = heStraight2d.getOrigin(); - Point2d p2 = heStraight2d.getTarget(); - Point2d orig = intersectingStraight2d.getOrigin(); - - double[] params = new double[2]; - - if (Math.abs(dir.getX()) > Global.getHighAccuracyTolerance()) { - params[0] = (p1.getX() - orig.getX()) / dir.getX(); - params[1] = (p2.getX() - orig.getX()) / dir.getX(); - } else if (Math.abs(dir.getY()) > Global.getHighAccuracyTolerance()) { - params[0] = (p1.getY() - orig.getY()) / dir.getY(); - params[1] = (p2.getY() - orig.getY()) / dir.getY(); - } else { - throw new IllegalStateException( - "Directional vector of identical straights is equal to the zero vector " + dir); - } - - assignParameterToCorrectList(params[0], intersectionValues, intersectedPolygonPoints); - assignParameterToCorrectList(params[1], intersectionValues, intersectedPolygonPoints); - } - } else { - if (heStraight2d.isWithinBoundaries(intersectionResult.getParamHE(), 1e-9)) { - assignParameterToCorrectList(intersectionResult.getParamInt(), intersectionValues, - intersectedPolygonPoints); - } - } + analyseProjectedIntersection(intersectionResult, intersectingStraight2d, heStraight2d, intersectionValues, intersectedPolygonPoints); } processIntersectionIntervals(p, intersectingStraight, intersectionValues, intersectedPolygonPoints, @@ -312,6 +287,42 @@ public class IntersectPlanarPolygons { } + private static void analyseProjectedIntersection(GmStraight2dIntersectionResult intersectionResult, GmStraight2d intersectingStraight2d, GmBoundedStraight2d heStraight2d, TreeSet intersectionValues, TreeSet intersectedPolygonPoints) { + if (intersectionResult.areParallel()) { + Vector2d dir = intersectingStraight2d.getDirection(); + Vector2d diffVec = heStraight2d.getOrigin().minus(intersectingStraight2d.getOrigin()); + double diffVecDotPerpDir = diffVec.dot(dir.getPerpendicularVector()); + + if (Math.abs(diffVecDotPerpDir) < Global.getZeroAngleCosine()) { + // Straights are identical + Point2d p1 = heStraight2d.getOrigin(); + Point2d p2 = heStraight2d.getTarget(); + Point2d orig = intersectingStraight2d.getOrigin(); + + double[] params = new double[2]; + + if (Math.abs(dir.getX()) > Global.getHighAccuracyTolerance()) { + params[0] = (p1.getX() - orig.getX()) / dir.getX(); + params[1] = (p2.getX() - orig.getX()) / dir.getX(); + } else if (Math.abs(dir.getY()) > Global.getHighAccuracyTolerance()) { + params[0] = (p1.getY() - orig.getY()) / dir.getY(); + params[1] = (p2.getY() - orig.getY()) / dir.getY(); + } else { + throw new IllegalStateException( + "Directional vector of identical straights is equal to the zero vector " + dir); + } + + assignParameterToCorrectList(params[0], intersectionValues, intersectedPolygonPoints); + assignParameterToCorrectList(params[1], intersectionValues, intersectedPolygonPoints); + } + } else { + if (heStraight2d.isWithinBoundaries(intersectionResult.paramHE(), 1e-9)) { + assignParameterToCorrectList(intersectionResult.paramInt(), intersectionValues, + intersectedPolygonPoints); + } + } + } + /** * This methods computes the intervals of the intersection between the given * straight and polygon. It gets only parameters where the straight hits the @@ -350,45 +361,18 @@ public class IntersectPlanarPolygons { List valuesList = new ArrayList<>(intersectionValues); for (int i = 0; i < valuesList.size(); i++) { double i1 = valuesList.get(i); - i = i + 1; - if (i < valuesList.size()) { - double i2 = valuesList.get(i); + int j = i + 1; + if (j < valuesList.size()) { + double i2 = valuesList.get(j); // check if the double values are corner points of the polygon - boolean gotPolygonPoint = false; - if (intersectedPolygonPoints.contains(i1) || intersectedPolygonPoints.contains(i2)) { - gotPolygonPoint = true; - } - - if (gotPolygonPoint) { - // maybe an interval - // check if the point between the two parameters is inside the - // polygon or outside ( i.e. i1 and i2 are both corner points of - // a concave polygon, so the connection line don't need to lie - // inside the polygon ) - Point3d pnt = intersectingStraight.evaluate((i1 + i2) / 2); - if (pcPolygon.isPointInsidePolygon(pnt, 1e-9)) { - Interval newLineInt = new Interval(i1, i2); - // there is already at least one point interval present. We need - // to remove this first, otherwise we would get a normal interval - // and one or two point intervals at the end of the normal int. - Iterator intervalIterator = intersectionIntervals.iterator(); - while (intervalIterator.hasNext() && !intersectionIntervals.isEmpty()) { - for (Interval inter = intervalIterator.next(); intervalIterator - .hasNext(); inter = intervalIterator.next()) { - if (Math.abs(inter.getLength()) < Global.getHighAccuracyTolerance()) { - if (Math.abs(inter.getStart() - i1) < 1e-9 - || Math.abs(inter.getStart() - i2) < 1e-9) { - intervalIterator.remove(); - intervalIterator = intersectionIntervals.iterator(); - break; - } - } - } - } + boolean gotPolygonPoint = intersectedPolygonPoints.contains(i1) || + intersectedPolygonPoints.contains(i2); + if (gotPolygonPoint) { + Interval newLineInt = checkIntersectionInvervalPoints(pcPolygon, intersectingStraight, + intersectionIntervals, i1, i2); + if (newLineInt != null) { intersectionIntervals.add(newLineInt); - } else { - i--; } } else { intersectionIntervals.add(new Interval(i1, i2)); @@ -405,6 +389,37 @@ public class IntersectPlanarPolygons { } } + private static Interval checkIntersectionInvervalPoints(EdgePolygon pcPolygon, GmStraight intersectingStraight, List intersectionIntervals, double i1, double i2) { + // maybe an interval + // check if the point between the two parameters is inside the + // polygon or outside ( i.e. i1 and i2 are both corner points of + // a concave polygon, so the connection line don't need to lie + // inside the polygon ) + Point3d pnt = intersectingStraight.evaluate((i1 + i2) / 2); + if (pcPolygon.isPointInsidePolygon(pnt, 1e-9)) { + Interval newLineInt = new Interval(i1, i2); + // there is already at least one point interval present. We need + // to remove this first, otherwise we would get a normal interval + // and one or two point intervals at the end of the normal int. + Iterator intervalIterator = intersectionIntervals.iterator(); + while (intervalIterator.hasNext() && !intersectionIntervals.isEmpty()) { + for (Interval inter = intervalIterator.next(); intervalIterator + .hasNext(); inter = intervalIterator.next()) { + if (Math.abs(inter.getLength()) < Global.getHighAccuracyTolerance() && + (Math.abs(inter.getStart() - i1) < 1e-9 || Math.abs(inter.getStart() - i2) < 1e-9)) { + intervalIterator.remove(); + intervalIterator = intersectionIntervals.iterator(); + break; + } + + } + } + + return newLineInt; + } + return null; + } + /** * Util method. Checks if the given parameter has already been inserted as * intersection parameter. If this is true, the parameter will be added as @@ -444,46 +459,9 @@ public class IntersectPlanarPolygons { List heList = new ArrayList<>(p1.getHalfEdges()); heList.addAll(p2.getHalfEdges()); - List heListColinear = new ArrayList<>(); - for (HalfEdge he : heList) { - - if (null != he.getPartner()) { - // this half edge is shared by both polygons ==> no intersection - // NOTE: The issue of more than 2 half edges per edge is solved by - // circular pointer, so we have to cycle threw all partners - HalfEdge pStartHE = he; - HalfEdge pPartnerHE = pStartHE.getPartner(); - boolean bothPolysShareThisEdge = false; - while (pStartHE != pPartnerHE && !bothPolysShareThisEdge) { - if (pPartnerHE.getPolygon() == p1 || pPartnerHE.getPolygon() == p2) { - bothPolysShareThisEdge = true; - } - pPartnerHE = pPartnerHE.getPartner(); - } - if (bothPolysShareThisEdge) { - continue; - } - } - - GmBoundedStraight straightHe = he.getStraight(); - Point3d origin = straightHe.getOrigin(); - Point3d target = straightHe.getTarget(); - - boolean straightsAreColinear = IntersectPlanarPolygons.areStraightsColinear(straightHe, straight, epsilon, - angleEpsilon); - ProjectedPoint3d projPoint1 = straight.project(origin); - ProjectedPoint3d projPoint2 = straight.project(target); - - boolean originLiesOnIntStraight = projPoint1.getPoint().isAlmostEqual(origin, - PROJECTED_POINT_DISTANCE_EPSILON); - boolean targetLiesOnIntStraight = projPoint2.getPoint().isAlmostEqual(target, - PROJECTED_POINT_DISTANCE_EPSILON); - if (straightsAreColinear && (originLiesOnIntStraight || targetLiesOnIntStraight)) { - heListColinear.add(he); - } - } + List heListCollinear = getCollinearHalfEdgeList(p1, p2, straight, epsilon, angleEpsilon, heList); - for (HalfEdge he : heListColinear) { + for (HalfEdge he : heListCollinear) { // 1.2) determine if fully or partially or not at all embedded // create parameter interval of the first projected half edge Point3d startPoint1 = he.getStraight().getOrigin(); @@ -491,7 +469,7 @@ public class IntersectPlanarPolygons { ProjectedPoint3d projP1 = straight.project(startPoint1); ProjectedPoint3d projP2 = straight.project(endPoint1); Interval int1 = new Interval(projP1.getParameter(), projP2.getParameter()); - for (HalfEdge he2 : heListColinear) { + for (HalfEdge he2 : heListCollinear) { if (he == he2) { continue; } @@ -528,8 +506,63 @@ public class IntersectPlanarPolygons { } } - private static boolean areStraightsColinear(GmBoundedStraight straight1, GmStraight straight2, double epsilon, - double angleEpsilon) { + private static List getCollinearHalfEdgeList(EdgePolygon p1, EdgePolygon p2, GmStraight straight, double epsilon, double angleEpsilon, List heList) { + List heListCollinear = new ArrayList<>(); + for (HalfEdge he : heList) { + + if (isHalfEdgeSharedByPolygons(he, p1, p2)){ + // If the HalfEdge is shared, it is not collinear. + // Ignore it and continue with next HalfEdge. + continue; + } + + GmBoundedStraight straightHe = he.getStraight(); + Point3d origin = straightHe.getOrigin(); + Point3d target = straightHe.getTarget(); + + boolean straightsAreCollinear = IntersectPlanarPolygons.areStraightsCollinear(straightHe, straight, epsilon, + angleEpsilon); + ProjectedPoint3d projPoint1 = straight.project(origin); + ProjectedPoint3d projPoint2 = straight.project(target); + + boolean originLiesOnIntStraight = projPoint1.getPoint().isAlmostEqual(origin, + PROJECTED_POINT_DISTANCE_EPSILON); + boolean targetLiesOnIntStraight = projPoint2.getPoint().isAlmostEqual(target, + PROJECTED_POINT_DISTANCE_EPSILON); + if (straightsAreCollinear && (originLiesOnIntStraight || targetLiesOnIntStraight)) { + heListCollinear.add(he); + } + } + return heListCollinear; + } + + /** + * Checks whether a specific HalfEdge is shared by two EdgePolygons. + * + * + * @param he The HalfEdge in question + * @param p1 First Polygon + * @param p2 Second Polygon + * @return true if the HalfEdge is shared + */ + private static boolean isHalfEdgeSharedByPolygons(HalfEdge he, EdgePolygon p1, EdgePolygon p2) { + boolean bothPolysShareThisEdge = false; + if (he.getPartner() != null) { + // NOTE: The issue of more than 2 half edges per edge is solved by + // circular pointer, so we have to cycle threw all partners + HalfEdge pPartnerHE = he.getPartner(); + while (he != pPartnerHE && !bothPolysShareThisEdge) { + if (pPartnerHE.getPolygon() == p1 || pPartnerHE.getPolygon() == p2) { + bothPolysShareThisEdge = true; + } + pPartnerHE = pPartnerHE.getPartner(); + } + } + return bothPolysShareThisEdge; + } + + private static boolean areStraightsCollinear(GmBoundedStraight straight1, GmStraight straight2, double epsilon, + double angleEpsilon) { UnitVector3d rDir1 = straight1.getDir(); UnitVector3d rDir2 = straight2.getDir(); @@ -543,12 +576,9 @@ public class IntersectPlanarPolygons { ProjectedPoint3d foot1 = straight2.project(rOrigin); Point3d rTarget = straight1.getTarget(); ProjectedPoint3d foot2 = straight2.project(rTarget); - if ((foot1.getPoint().minus(rOrigin)).getLength() > epsilon - || (foot2.getPoint().minus(rTarget)).getLength() > epsilon) { - return false; - } - return true; - } + return !(((foot1.getPoint().minus(rOrigin)).getLength() > epsilon) + || ((foot2.getPoint().minus(rTarget)).getLength() > epsilon)); + } private static List handlePolygonsInSamePlane(GmPlane plane, EdgePolygon p1, EdgePolygon p2, double epsilon) { @@ -576,15 +606,7 @@ public class IntersectPlanarPolygons { Polygon2d poly2d1 = new Polygon2dNs(poly2dCoords1, true); Polygon2d poly2d2 = new Polygon2dNs(poly2dCoords2, true); - - List halfEdges = poly2d1.getHalfEdges(); - for (HalfEdge2d he : halfEdges) { - if (he.getPartner() == null) { - } - } - - halfEdges = poly2d2.getHalfEdges(); - + List result = new ArrayList<>(); List ppi2ds = IntersectPolygon2d.getIntersections(poly2d1, poly2d2, epsilon); for (Polygon2dPolygon2dInt ppi2d : ppi2ds) { diff --git a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/IntersectPolygonAndStraight2d.java b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/IntersectPolygonAndStraight2d.java index f9e486e74159d0723b8710a9369a3a9edf3268ec..80ab058a8b1eba6edb09f9abc519413536d40ad6 100644 --- a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/IntersectPolygonAndStraight2d.java +++ b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/IntersectPolygonAndStraight2d.java @@ -100,11 +100,11 @@ public class IntersectPolygonAndStraight2d { assignParameterToCorrectList(params[1], intersectionValues, intersectedPolygonPoints); } } else { - if (hEStraight.isWithinBoundaries(res.getParamHE())) { + if (hEStraight.isWithinBoundaries(res.paramHE())) { // Point2d pnt = mIntStraight.evaluate( paramInt ); // cout << "got ( " << pnt.getU() << ", " << pnt.getV() << " ) as int point with // param " << paramInt << endl; - assignParameterToCorrectList(res.getParamInt(), intersectionValues, intersectedPolygonPoints); + assignParameterToCorrectList(res.paramInt(), intersectionValues, intersectedPolygonPoints); } } } @@ -164,12 +164,10 @@ public class IntersectPolygonAndStraight2d { for (Double d : crIntersectedPolygonPoints) { boolean pntIsPartOfExistingInterval = false; for (Interval interval : mIntersectionIntervals) { - if (pntIsPartOfExistingInterval) { - break; - } - if (interval.getStart() == d || interval.getEnd() == d) { - pntIsPartOfExistingInterval = true; - } + if (interval.getStart() == d || interval.getEnd() == d) { + pntIsPartOfExistingInterval = true; + break; + } } // the current value is not part of an existing interval, so insert it diff --git a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/Interval.java b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/Interval.java index 2ca1f29189c527d96092c4ed0cf1f709a3c0b285..d0196e3321da09f8cc1151c565690596e48506a4 100644 --- a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/Interval.java +++ b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/Interval.java @@ -1,65 +1,66 @@ -/*- - * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart - * - * This file is part of CityDoctor2. - * - * CityDoctor2 is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * CityDoctor2 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with CityDoctor2. If not, see . - */ -package de.hft.stuttgart.citydoctor2.edge; - -public class Interval { - - private static final Interval INVALID_INTERVAL = new Interval(1, 0); - - private double start; - private double end; - - public Interval(double start, double end) { - this.start = start; - this.end = end; - } - - public Interval overlap(Interval other) { - if (isValid() && other.isValid() && isOverlapping(other)) { - return new Interval(Math.max(start, other.start), Math.min(end, other.end)); - } - return INVALID_INTERVAL; - } - - public boolean isOverlapping(Interval other) { - return !(end < other.start || other.end < start); - } - - public boolean isValid() { - return end >= start; - } - - public double getLength() { - return end - start; - } - - public double getStart() { - return start; - } - - public double getEnd() { - return end; - } - - @Override - public String toString() { - return "Interval [start=" + start + ", end=" + end + "]"; - } - -} +/*- + * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart + * + * This file is part of CityDoctor2. + * + * CityDoctor2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CityDoctor2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with CityDoctor2. If not, see . + */ +package de.hft.stuttgart.citydoctor2.edge; + + +public class Interval { + + private static final Interval INVALID_INTERVAL = new Interval(1, 0); + + private final double start; + private final double end; + + public Interval(double start, double end) { + this.start = start; + this.end = end; + } + + public Interval overlap(Interval other) { + if (isValid() && other.isValid() && isOverlapping(other)) { + return new Interval(Math.max(start, other.start), Math.min(end, other.end)); + } + return INVALID_INTERVAL; + } + + public boolean isOverlapping(Interval other) { + return !(end < other.start || other.end < start); + } + + public boolean isValid() { + return end >= start; + } + + public double getLength() { + return end - start; + } + + public double getStart() { + return start; + } + + public double getEnd() { + return end; + } + + @Override + public String toString() { + return "Interval [start=" + start + ", end=" + end + "]"; + } + +} diff --git a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/MeshSurface.java b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/MeshSurface.java index e6375dd5572cd573bc97025d477365bfda26d9db..8019cee2df9b305ab11330e7354528a6d7c50c2e 100644 --- a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/MeshSurface.java +++ b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/MeshSurface.java @@ -1,56 +1,48 @@ -/*- - * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart - * - * This file is part of CityDoctor2. - * - * CityDoctor2 is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * CityDoctor2 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with CityDoctor2. If not, see . - */ -package de.hft.stuttgart.citydoctor2.edge; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import de.hft.stuttgart.citydoctor2.datastructure.Geometry; -import de.hft.stuttgart.citydoctor2.datastructure.Polygon; -import de.hft.stuttgart.citydoctor2.math.MovedPolygon; -import de.hft.stuttgart.citydoctor2.math.Vector3d; - -public class MeshSurface { - - private List polygons; - - public static MeshSurface of(Geometry geom) { - List polygonList = new ArrayList<>(); - - Map pointMap = new HashMap<>(); - Vector3d moveBy = geom.calculateBoundingBox().getBox()[0]; - for (Polygon p : geom.getPolygons()) { - MovedPolygon mp = MovedPolygon.ofPolygon(p, moveBy); - CDPolygonNs poly = CDPolygonNs.of(mp, pointMap); - polygonList.add(poly); - } - return new MeshSurface(polygonList); - } - - public MeshSurface(List polygons) { - this.polygons = polygons; - } - - public List getPolygons() { - return polygons; - } - -} +/*- + * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart + * + * This file is part of CityDoctor2. + * + * CityDoctor2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CityDoctor2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with CityDoctor2. If not, see . + */ +package de.hft.stuttgart.citydoctor2.edge; + + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import de.hft.stuttgart.citydoctor2.datastructure.Geometry; +import de.hft.stuttgart.citydoctor2.datastructure.Polygon; +import de.hft.stuttgart.citydoctor2.math.MovedPolygon; +import de.hft.stuttgart.citydoctor2.math.Vector3d; + +public record MeshSurface(List polygons) { + + public static MeshSurface of(Geometry geom) { + List polygonList = new ArrayList<>(); + + Map pointMap = new HashMap<>(); + Vector3d moveBy = geom.calculateBoundingBox().getBox()[0]; + for (Polygon p : geom.getPolygons()) { + MovedPolygon mp = MovedPolygon.ofPolygon(p, moveBy); + CDPolygonNs poly = CDPolygonNs.of(mp, pointMap); + polygonList.add(poly); + } + return new MeshSurface(polygonList); + } + + +} diff --git a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/MeshSurfaceUtils.java b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/MeshSurfaceUtils.java index 9fb3a07df7250f9f16073cb249ef42fce72a1572..df3d951bc2ecaa02581b6c9b32432215399489f4 100644 --- a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/MeshSurfaceUtils.java +++ b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/MeshSurfaceUtils.java @@ -1,45 +1,46 @@ -/*- - * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart - * - * This file is part of CityDoctor2. - * - * CityDoctor2 is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * CityDoctor2 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with CityDoctor2. If not, see . - */ -package de.hft.stuttgart.citydoctor2.edge; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -public class MeshSurfaceUtils { - - public static List selfIntersects(MeshSurface ms, double epsilon, double angleEpsilon) { - Objects.requireNonNull(ms); - List polygons = ms.getPolygons(); - List intersections = new ArrayList<>(); - for (int i = 0; i < polygons.size() - 1; i++) { - EdgePolygon p1 = polygons.get(i); - for (int j = i + 1; j < polygons.size(); j++) { - EdgePolygon p2 = polygons.get(j); - List result = IntersectPlanarPolygons.intersectPolygons(p1, p2, epsilon, angleEpsilon); - intersections.addAll(result); - } - } - return intersections; - } - - private MeshSurfaceUtils() { - } - -} +/*- + * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart + * + * This file is part of CityDoctor2. + * + * CityDoctor2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CityDoctor2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with CityDoctor2. If not, see . + */ +package de.hft.stuttgart.citydoctor2.edge; + + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +public class MeshSurfaceUtils { + + public static List selfIntersects(MeshSurface ms, double epsilon, double angleEpsilon) { + Objects.requireNonNull(ms); + List polygons = ms.polygons(); + List intersections = new ArrayList<>(); + for (int i = 0; i < polygons.size() - 1; i++) { + EdgePolygon p1 = polygons.get(i); + for (int j = i + 1; j < polygons.size(); j++) { + EdgePolygon p2 = polygons.get(j); + List result = IntersectPlanarPolygons.intersectPolygons(p1, p2, epsilon, angleEpsilon); + intersections.addAll(result); + } + } + return intersections; + } + + private MeshSurfaceUtils() { + } + +} diff --git a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/Point2d.java b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/Point2d.java index ddf16acbf12dc8f3c11b6208f1b2a104cfd67e19..a9d9d4c924ecbbe0399f11cf4a5b006fc49943aa 100644 --- a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/Point2d.java +++ b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/Point2d.java @@ -20,8 +20,8 @@ package de.hft.stuttgart.citydoctor2.edge; public class Point2d { - private double x; - private double y; + private final double x; + private final double y; public Point2d(double x, double y) { this.x = x; diff --git a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/Point3d.java b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/Point3d.java index 858820dd1a76591da457620bf446d126c313d6c1..264c5836bbdf584974d18197d8cc56d6693cbee5 100644 --- a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/Point3d.java +++ b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/Point3d.java @@ -1,116 +1,117 @@ -/*- - * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart - * - * This file is part of CityDoctor2. - * - * CityDoctor2 is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * CityDoctor2 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with CityDoctor2. If not, see . - */ -package de.hft.stuttgart.citydoctor2.edge; - -public class Point3d { - - private double x; - private double y; - private double z; - - public Point3d(double x, double y, double z) { - this.x = x; - this.y = y; - this.z = z; - } - - public Point3d(double[] values) { - this(values[0], values[1], values[2]); - } - - public Point3d(Point3d p) { - this(p.getX(), p.getY(), p.getZ()); - } - - public boolean isAlmostEqual(Point3d origin, double eps) { - Vector3d vec = minus(origin); - double localEps = eps * eps; - if (localEps < Global.getHighAccuracyTolerance()) { - localEps = Global.getHighAccuracyTolerance(); - } - - return vec.getLength2() < localEps; - } - - public Vector3d minus(Point3d org) { - return new Vector3d(x - org.getX(), y - org.getY(), z - org.getZ()); - } - - public Point3d plus(Vector3d v) { - return new Point3d(x + v.getX(), y + v.getY(), z + v.getZ()); - } - - public double getX() { - return x; - } - - public double getY() { - return y; - } - - public double getZ() { - return z; - } - - public Point3d plus(Point3d point) { - return new Point3d(x + point.getX(), y + point.getY(), z + point.getZ()); - } - - public Point3d div(double d) { - return new Point3d(x / d, y /d, z / d); - } - - @Override - public String toString() { - return "Point3d [x=" + x + ", y=" + y + ", z=" + z + "]"; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - long temp; - temp = Double.doubleToLongBits(x); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(y); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(z); - result = prime * result + (int) (temp ^ (temp >>> 32)); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Point3d other = (Point3d) obj; - if (Double.doubleToLongBits(x) != Double.doubleToLongBits(other.x)) - return false; - if (Double.doubleToLongBits(y) != Double.doubleToLongBits(other.y)) - return false; - if (Double.doubleToLongBits(z) != Double.doubleToLongBits(other.z)) - return false; - return true; - } - -} +/*- + * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart + * + * This file is part of CityDoctor2. + * + * CityDoctor2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CityDoctor2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with CityDoctor2. If not, see . + */ +package de.hft.stuttgart.citydoctor2.edge; + + +public class Point3d { + + private final double x; + private final double y; + private final double z; + + public Point3d(double x, double y, double z) { + this.x = x; + this.y = y; + this.z = z; + } + + public Point3d(double[] values) { + this(values[0], values[1], values[2]); + } + + public Point3d(Point3d p) { + this(p.getX(), p.getY(), p.getZ()); + } + + public boolean isAlmostEqual(Point3d origin, double eps) { + Vector3d vec = minus(origin); + double localEps = eps * eps; + if (localEps < Global.getHighAccuracyTolerance()) { + localEps = Global.getHighAccuracyTolerance(); + } + + return vec.getLength2() < localEps; + } + + public Vector3d minus(Point3d org) { + return new Vector3d(x - org.getX(), y - org.getY(), z - org.getZ()); + } + + public Point3d plus(Vector3d v) { + return new Point3d(x + v.getX(), y + v.getY(), z + v.getZ()); + } + + public double getX() { + return x; + } + + public double getY() { + return y; + } + + public double getZ() { + return z; + } + + public Point3d plus(Point3d point) { + return new Point3d(x + point.getX(), y + point.getY(), z + point.getZ()); + } + + public Point3d div(double d) { + return new Point3d(x / d, y /d, z / d); + } + + @Override + public String toString() { + return "Point3d [x=" + x + ", y=" + y + ", z=" + z + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + long temp; + temp = Double.doubleToLongBits(x); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(y); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(z); + result = prime * result + (int) (temp ^ (temp >>> 32)); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Point3d other = (Point3d) obj; + if (Double.doubleToLongBits(x) != Double.doubleToLongBits(other.x)) + return false; + if (Double.doubleToLongBits(y) != Double.doubleToLongBits(other.y)) + return false; + if (Double.doubleToLongBits(z) != Double.doubleToLongBits(other.z)) + return false; + return true; + } + +} diff --git a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/PolyLine2d.java b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/PolyLine2d.java index 18d5d1105b342c999a5690de8f6ed3d4fdffeb98..3ac612d1159715d42c02ca0611b57183f4f6a878 100644 --- a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/PolyLine2d.java +++ b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/PolyLine2d.java @@ -23,7 +23,7 @@ import java.util.List; public class PolyLine2d extends BaseEntity { - private PolyLineSegment2d mpFirst; + private final PolyLineSegment2d mpFirst; private PolyLineSegment2d mpLast; public PolyLine2d(PolyLineSegment2d pStart) { diff --git a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/PolyLineSegment.java b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/PolyLineSegment.java index fd69514259e2a9cf5845526e8e625a2a9fe0058f..608f4391a5c4233e1c22889466ef7bdfa99ddc26 100644 --- a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/PolyLineSegment.java +++ b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/PolyLineSegment.java @@ -25,8 +25,8 @@ public class PolyLineSegment extends BaseEntity { private static final Logger logger = LogManager.getLogger(PolyLineSegment.class); - private Coordinate3d mpStart; - private Coordinate3d mpEnd; + private final Coordinate3d mpStart; + private final Coordinate3d mpEnd; private PolyLineSegment mpNext; diff --git a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/Polygon2d.java b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/Polygon2d.java index 46ed1e9d1354d2136a18f335a94da1485187e6f1..d03a2be70de2f61801178c1ed1dd8e49ee292a12 100644 --- a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/Polygon2d.java +++ b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/Polygon2d.java @@ -104,16 +104,14 @@ public class Polygon2d extends BaseEntity { point = halfEdge.getStart().getPoint(); - lowerU = (point.getX() < lowerU) ? point.getX() : lowerU; - lowerV = (point.getY() < lowerV) ? point.getY() : lowerV; + lowerU = Math.min(point.getX(), lowerU); + lowerV = Math.min(point.getY(), lowerV); - upperU = (point.getX() > upperU) ? point.getX() : upperU; - upperV = (point.getY() > upperV) ? point.getY() : upperV; + upperU = Math.max(point.getX(), upperU); + upperV = Math.max(point.getY(), upperV); } - Box2d box = new Box2d(new Point2d(lowerU, lowerV), new Point2d(upperU, upperV)); - - return box; + return new Box2d(new Point2d(lowerU, lowerV), new Point2d(upperU, upperV)); } public static void connectHalfEdges(List rHalfEdges) { diff --git a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/Polygon2dPolygon2dInt.java b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/Polygon2dPolygon2dInt.java index 9d8fe90550946211c8f3258dbb78c32749e1bd12..8495c98cbcbcd0166004e77799c2b85ea9c92e90 100644 --- a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/Polygon2dPolygon2dInt.java +++ b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/Polygon2dPolygon2dInt.java @@ -1,57 +1,58 @@ -/*- - * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart - * - * This file is part of CityDoctor2. - * - * CityDoctor2 is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * CityDoctor2 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with CityDoctor2. If not, see . - */ -package de.hft.stuttgart.citydoctor2.edge; - -public class Polygon2dPolygon2dInt { - - private Polygon2d mcpPolygon1; - private Polygon2d mcpPolygon2; - private PolyLine2d line; - private IntersectionType intType; - - public Polygon2dPolygon2dInt(Polygon2d mcpPolygon1, Polygon2d mcpPolygon2, PolyLine2d line, - IntersectionType intType) { - this.mcpPolygon1 = mcpPolygon1; - this.mcpPolygon2 = mcpPolygon2; - this.line = line; - this.intType = intType; - } - - public PolyLine2d getPolyLine2d() { - return line; - } - - public IntersectionType getIntType() { - return intType; - } - - public Polygon2d getPolygon1() { - return mcpPolygon1; - } - - public Polygon2d getPolygon2() { - return mcpPolygon2; - } - - @Override - public String toString() { - return "Polygon2dPolygon2dInt [mcpPolygon1=" + mcpPolygon1 + ", mcpPolygon2=" + mcpPolygon2 + ", line=" + line - + ", intType=" + intType + "]"; - } -} +/*- + * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart + * + * This file is part of CityDoctor2. + * + * CityDoctor2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CityDoctor2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with CityDoctor2. If not, see . + */ +package de.hft.stuttgart.citydoctor2.edge; + + +public class Polygon2dPolygon2dInt { + + private final Polygon2d mcpPolygon1; + private final Polygon2d mcpPolygon2; + private final PolyLine2d line; + private final IntersectionType intType; + + public Polygon2dPolygon2dInt(Polygon2d mcpPolygon1, Polygon2d mcpPolygon2, PolyLine2d line, + IntersectionType intType) { + this.mcpPolygon1 = mcpPolygon1; + this.mcpPolygon2 = mcpPolygon2; + this.line = line; + this.intType = intType; + } + + public PolyLine2d getPolyLine2d() { + return line; + } + + public IntersectionType getIntType() { + return intType; + } + + public Polygon2d getPolygon1() { + return mcpPolygon1; + } + + public Polygon2d getPolygon2() { + return mcpPolygon2; + } + + @Override + public String toString() { + return "Polygon2dPolygon2dInt [mcpPolygon1=" + mcpPolygon1 + ", mcpPolygon2=" + mcpPolygon2 + ", line=" + line + + ", intType=" + intType + "]"; + } +} diff --git a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/PolygonPolygonIntersection.java b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/PolygonPolygonIntersection.java index 8a44969f935716edaf182834fe9fffa9ade15184..e10bc11e799feb952012e4d9bd82af2292bd1658 100644 --- a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/PolygonPolygonIntersection.java +++ b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/PolygonPolygonIntersection.java @@ -1,61 +1,62 @@ -/*- - * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart - * - * This file is part of CityDoctor2. - * - * CityDoctor2 is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * CityDoctor2 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with CityDoctor2. If not, see . - */ -package de.hft.stuttgart.citydoctor2.edge; - -public class PolygonPolygonIntersection { - - private EdgePolygon p1; - private EdgePolygon p2; - private PolyLine polyLine; - private IntersectionType type; - - public PolygonPolygonIntersection(EdgePolygon p1, EdgePolygon p2, PolyLine polyLine, IntersectionType type) { - this.p1 = p1; - this.p2 = p2; - this.polyLine = polyLine; - this.type = type; - } - - public PolygonPolygonIntersection(EdgePolygon p1, EdgePolygon p2, PolyLine polyLine) { - this(p1, p2, polyLine, IntersectionType.NORMAL_INTERSECTION); - } - - public PolyLine getPolyLine() { - return polyLine; - } - - public IntersectionType getIntersectionType() { - return type; - } - - public EdgePolygon getPolygon1() { - return p1; - } - - public EdgePolygon getPolygon2() { - return p2; - } - - @Override - public String toString() { - return "PolygonPolygonIntersection [p1=" + p1 + ", p2=" + p2 + ", polyLine=" + polyLine + ", type=" + type - + "]"; - } - -} +/*- + * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart + * + * This file is part of CityDoctor2. + * + * CityDoctor2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CityDoctor2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with CityDoctor2. If not, see . + */ +package de.hft.stuttgart.citydoctor2.edge; + + +public class PolygonPolygonIntersection { + + private final EdgePolygon p1; + private final EdgePolygon p2; + private final PolyLine polyLine; + private final IntersectionType type; + + public PolygonPolygonIntersection(EdgePolygon p1, EdgePolygon p2, PolyLine polyLine, IntersectionType type) { + this.p1 = p1; + this.p2 = p2; + this.polyLine = polyLine; + this.type = type; + } + + public PolygonPolygonIntersection(EdgePolygon p1, EdgePolygon p2, PolyLine polyLine) { + this(p1, p2, polyLine, IntersectionType.NORMAL_INTERSECTION); + } + + public PolyLine getPolyLine() { + return polyLine; + } + + public IntersectionType getIntersectionType() { + return type; + } + + public EdgePolygon getPolygon1() { + return p1; + } + + public EdgePolygon getPolygon2() { + return p2; + } + + @Override + public String toString() { + return "PolygonPolygonIntersection [p1=" + p1 + ", p2=" + p2 + ", polyLine=" + polyLine + ", type=" + type + + "]"; + } + +} diff --git a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/ProjectedPoint3d.java b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/ProjectedPoint3d.java index c7f648d57945462b6e5b02f2d0d1c2cdac34ab39..6d45de606b2af3a300134867bcae68c52ae3f684 100644 --- a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/ProjectedPoint3d.java +++ b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/ProjectedPoint3d.java @@ -1,39 +1,40 @@ -/*- - * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart - * - * This file is part of CityDoctor2. - * - * CityDoctor2 is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * CityDoctor2 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with CityDoctor2. If not, see . - */ -package de.hft.stuttgart.citydoctor2.edge; - -public class ProjectedPoint3d { - - private Point3d point; - private double parameter; - - public ProjectedPoint3d(Point3d point, double d) { - this.point = point; - this.parameter = d; - } - - public Point3d getPoint() { - return point; - } - - public double getParameter() { - return parameter; - } - -} +/*- + * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart + * + * This file is part of CityDoctor2. + * + * CityDoctor2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CityDoctor2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with CityDoctor2. If not, see . + */ +package de.hft.stuttgart.citydoctor2.edge; + + +public class ProjectedPoint3d { + + private final Point3d point; + private final double parameter; + + public ProjectedPoint3d(Point3d point, double d) { + this.point = point; + this.parameter = d; + } + + public Point3d getPoint() { + return point; + } + + public double getParameter() { + return parameter; + } + +} diff --git a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/UnitVector3d.java b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/UnitVector3d.java index 6028a56b907fbd9222de7c15eb9cf1f2cfde9f81..8b84e4a51786d104153887103b673d940912f6f5 100644 --- a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/UnitVector3d.java +++ b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/UnitVector3d.java @@ -1,51 +1,46 @@ -/*- - * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart - * - * This file is part of CityDoctor2. - * - * CityDoctor2 is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * CityDoctor2 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with CityDoctor2. If not, see . - */ -package de.hft.stuttgart.citydoctor2.edge; - -public class UnitVector3d extends Vector3d { - - public static UnitVector3d of(Vector3d vec) { - UnitVector3d unitVec = new UnitVector3d(vec.getX(), vec.getY(), vec.getZ()); - unitVec.normalize(); - return unitVec; - } - - public static UnitVector3d of(double x, double y, double z) { - double length = Math.sqrt(x * x + y * y + z * z); - return new UnitVector3d(x / length, y / length, z / length); - } - - private UnitVector3d(double x, double y, double z) { - super(x, y, z); - } - - public double dot(UnitVector3d other) { - double scalar = getX() * other.getX() + getY() * other.getY() + getZ() * other.getZ(); - if (scalar > 1.0) { - return 1.0; - } - if (scalar < -1.0) { - return -1.0; - } - return scalar; - } - - - -} +/*- + * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart + * + * This file is part of CityDoctor2. + * + * CityDoctor2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CityDoctor2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with CityDoctor2. If not, see . + */ +package de.hft.stuttgart.citydoctor2.edge; + + +public class UnitVector3d extends Vector3d { + + public static UnitVector3d of(Vector3d vec) { + UnitVector3d unitVec = new UnitVector3d(vec.getX(), vec.getY(), vec.getZ()); + unitVec.normalize(); + return unitVec; + } + + public static UnitVector3d of(double x, double y, double z) { + double length = Math.sqrt(x * x + y * y + z * z); + return new UnitVector3d(x / length, y / length, z / length); + } + + private UnitVector3d(double x, double y, double z) { + super(x, y, z); + } + + public double dot(UnitVector3d other) { + double scalar = getX() * other.getX() + getY() * other.getY() + getZ() * other.getZ(); + return (scalar >= 0) ? Math.min(scalar, 1.0) : Math.max(scalar, -1.0); + } + + + +} diff --git a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/Vector2d.java b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/Vector2d.java index fb7de0651f76bc679d38d290d0e4c8556b865c73..4ff8e6ccc5d434f7ca2690f501463f8e0561e0ed 100644 --- a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/Vector2d.java +++ b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/Vector2d.java @@ -1,68 +1,70 @@ -/*- - * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart - * - * This file is part of CityDoctor2. - * - * CityDoctor2 is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * CityDoctor2 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with CityDoctor2. If not, see . - */ -package de.hft.stuttgart.citydoctor2.edge; - -public class Vector2d { - - private double x; - private double y; - - public Vector2d(double x, double y) { - this.x = x; - this.y = y; - } - - public Vector2d getPerpendicularVector() { - return new Vector2d(y, -x); - } - - public double dot(Vector2d other) { - return (getX() * other.getX() + getY() * other.getY()); - } - - public Vector2d mult(double scalar) { - return new Vector2d(x * scalar, y * scalar); - } - - public double getX() { - return x; - } - - public double getY() { - return y; - } - - public UnitVector2d normalize() { - return UnitVector2d.convertFrom(this); - } - - public double getLength() { - return Math.sqrt(getLength2()); - } - - public double getLength2() { - return x * x + y * y; - } - - @Override - public String toString() { - return "Vector2d [x=" + x + ", y=" + y + "]"; - } - -} +/*- + * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart + * + * This file is part of CityDoctor2. + * + * CityDoctor2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CityDoctor2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with CityDoctor2. If not, see . + */ +package de.hft.stuttgart.citydoctor2.edge; + + +public class Vector2d { + + private final double x; + private final double y; + + public Vector2d(double x, double y) { + this.x = x; + this.y = y; + } + + @SuppressWarnings("SuspiciousNameCombination") + public Vector2d getPerpendicularVector() { + return new Vector2d(y, -x); + } + + public double dot(Vector2d other) { + return (getX() * other.getX() + getY() * other.getY()); + } + + public Vector2d mult(double scalar) { + return new Vector2d(x * scalar, y * scalar); + } + + public double getX() { + return x; + } + + public double getY() { + return y; + } + + public UnitVector2d normalize() { + return UnitVector2d.convertFrom(this); + } + + public double getLength() { + return Math.sqrt(getLength2()); + } + + public double getLength2() { + return x * x + y * y; + } + + @Override + public String toString() { + return "Vector2d [x=" + x + ", y=" + y + "]"; + } + +} diff --git a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/Vector3d.java b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/Vector3d.java index 3e0edc3317ef993ddfa9b76fb0223698afe88da9..1e15f87d9ac0778fa915864288e8a79b1a4180b9 100644 --- a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/Vector3d.java +++ b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/Vector3d.java @@ -1,116 +1,117 @@ -/*- - * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart - * - * This file is part of CityDoctor2. - * - * CityDoctor2 is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * CityDoctor2 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with CityDoctor2. If not, see . - */ -package de.hft.stuttgart.citydoctor2.edge; - -import java.util.Arrays; - -public class Vector3d { - - private double[] val = new double[3]; - - public Vector3d(double x, double y, double z) { - val[0] = x; - val[1] = y; - val[2] = z; - } - - public Vector3d(Point3d point) { - this(point.getX(), point.getY(), point.getZ()); - } - - public double getLength() { - double value = val[0] * val[0] + val[1] * val[1] + val[2] * val[2]; - return Math.sqrt(value); - } - - public void normalize() { - double length = getLength(); - if (length < Global.getHighAccuracyTolerance()) { - val[0] = 0; - val[1] = 0; - val[2] = 0; - } else { - val[0] = val[0] /= length; - val[1] = val[1] /= length; - val[2] = val[2] /= length; - } - } - - public Vector3d cross(Vector3d crV2) { - return new Vector3d(getY() * crV2.getZ() - crV2.getY() * getZ(), getZ() * crV2.getX() - crV2.getZ() * getX(), - getX() * crV2.getY() - crV2.getX() * getY()); - } - - public UnitVector3d toUnitVector() { - return UnitVector3d.of(this); - } - - public Vector3d mult(double d) { - return new Vector3d(val[0] * d, val[1] * d, val[2] * d); - } - - public Vector3d plus(Vector3d other) { - return new Vector3d(getX() + other.getX(), getY() + other.getY(), getZ() + other.getZ()); - } - - public double getX() { - return val[0]; - } - - public double getY() { - return val[1]; - } - - public double getZ() { - return val[2]; - } - - public double getLength2() { - return val[0] * val[0] + val[1] * val[1] + val[2] * val[2]; - } - - public double dot(Vector3d crVector) { - return this.val[0] * crVector.getX() + this.val[1] * crVector.getY() + this.val[2] * crVector.getZ(); - } - - public static boolean areParallel(Vector3d crV1, Vector3d crV2, double angleEpsilon) { - return Math.abs((crV1.dot(crV2)) - (crV1.getLength() * crV2.getLength())) < angleEpsilon; - } - - public static boolean areAntiParallel(Vector3d crV1, Vector3d crV2, double angleEpsilon) { - return Math.abs((crV1.dot(crV2)) + (crV1.getLength() * crV2.getLength())) < angleEpsilon; - } - - public static boolean areAntiParallel(Vector3d rDir1, Vector3d rDir2) { - return areAntiParallel(rDir1, rDir2, Global.getTolVectorsParallel()); - } - - public static boolean areParallel(Vector3d rDir1, Vector3d rDir2) { - return areParallel(rDir1, rDir2, Global.getTolVectorsParallel()); - } - - public double[] toArray() { - return Arrays.copyOf(val, 3); - } - - @Override - public String toString() { - return "Vector3d [val=" + Arrays.toString(val) + "]"; - } -} +/*- + * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart + * + * This file is part of CityDoctor2. + * + * CityDoctor2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CityDoctor2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with CityDoctor2. If not, see . + */ +package de.hft.stuttgart.citydoctor2.edge; + + +import java.util.Arrays; + +public class Vector3d { + + private final double[] val = new double[3]; + + public Vector3d(double x, double y, double z) { + val[0] = x; + val[1] = y; + val[2] = z; + } + + public Vector3d(Point3d point) { + this(point.getX(), point.getY(), point.getZ()); + } + + public double getLength() { + double value = val[0] * val[0] + val[1] * val[1] + val[2] * val[2]; + return Math.sqrt(value); + } + + public void normalize() { + double length = getLength(); + if (length < Global.getHighAccuracyTolerance()) { + val[0] = 0; + val[1] = 0; + val[2] = 0; + } else { + val[0] /= length; + val[1] /= length; + val[2] /= length; + } + } + + public Vector3d cross(Vector3d crV2) { + return new Vector3d(getY() * crV2.getZ() - crV2.getY() * getZ(), getZ() * crV2.getX() - crV2.getZ() * getX(), + getX() * crV2.getY() - crV2.getX() * getY()); + } + + public UnitVector3d toUnitVector() { + return UnitVector3d.of(this); + } + + public Vector3d mult(double d) { + return new Vector3d(val[0] * d, val[1] * d, val[2] * d); + } + + public Vector3d plus(Vector3d other) { + return new Vector3d(getX() + other.getX(), getY() + other.getY(), getZ() + other.getZ()); + } + + public double getX() { + return val[0]; + } + + public double getY() { + return val[1]; + } + + public double getZ() { + return val[2]; + } + + public double getLength2() { + return val[0] * val[0] + val[1] * val[1] + val[2] * val[2]; + } + + public double dot(Vector3d crVector) { + return this.val[0] * crVector.getX() + this.val[1] * crVector.getY() + this.val[2] * crVector.getZ(); + } + + public static boolean areParallel(Vector3d crV1, Vector3d crV2, double angleEpsilon) { + return Math.abs((crV1.dot(crV2)) - (crV1.getLength() * crV2.getLength())) < angleEpsilon; + } + + public static boolean areAntiParallel(Vector3d crV1, Vector3d crV2, double angleEpsilon) { + return Math.abs((crV1.dot(crV2)) + (crV1.getLength() * crV2.getLength())) < angleEpsilon; + } + + public static boolean areAntiParallel(Vector3d rDir1, Vector3d rDir2) { + return areAntiParallel(rDir1, rDir2, Global.getTolVectorsParallel()); + } + + public static boolean areParallel(Vector3d rDir1, Vector3d rDir2) { + return areParallel(rDir1, rDir2, Global.getTolVectorsParallel()); + } + + public double[] toArray() { + return Arrays.copyOf(val, 3); + } + + @Override + public String toString() { + return "Vector3d [val=" + Arrays.toString(val) + "]"; + } +} diff --git a/CityDoctorParent/CityDoctorEdge/src/test/java/de/hft/stuttgart/citydoctor2/edge/IntersectionErrorsTest.java b/CityDoctorParent/CityDoctorEdge/src/test/java/de/hft/stuttgart/citydoctor2/edge/IntersectionErrorsTest.java index 0b6fbb00024451566be18f7c9041587ab32fa604..72d007be363db22f1bec1159bd6670768b59f6b2 100644 --- a/CityDoctorParent/CityDoctorEdge/src/test/java/de/hft/stuttgart/citydoctor2/edge/IntersectionErrorsTest.java +++ b/CityDoctorParent/CityDoctorEdge/src/test/java/de/hft/stuttgart/citydoctor2/edge/IntersectionErrorsTest.java @@ -103,11 +103,11 @@ public class IntersectionErrorsTest { } MeshSurface meshSurface = MeshSurface.of(geom); - List polygons = meshSurface.getPolygons(); + List polygons = meshSurface.polygons(); assertEquals(2, polygons.size()); - CDPolygonNs edgePoly1 = meshSurface.getPolygons().get(0); - CDPolygonNs edgePoly2 = meshSurface.getPolygons().get(1); + CDPolygonNs edgePoly1 = meshSurface.polygons().get(0); + CDPolygonNs edgePoly2 = meshSurface.polygons().get(1); List intersectPolygons = IntersectPlanarPolygons.intersectPolygons(edgePoly1, edgePoly2, 0.000001, 0.001); diff --git a/CityDoctorParent/CityDoctorEdge/src/test/java/de/hft/stuttgart/citydoctor2/edge/MeshSurfaceUtilsTest.java b/CityDoctorParent/CityDoctorEdge/src/test/java/de/hft/stuttgart/citydoctor2/edge/MeshSurfaceUtilsTest.java index 175609685a805b2900615100ac0c7c3fddadc220..9cee97c34730d80ce4258c6187cb8180dde52b3a 100644 --- a/CityDoctorParent/CityDoctorEdge/src/test/java/de/hft/stuttgart/citydoctor2/edge/MeshSurfaceUtilsTest.java +++ b/CityDoctorParent/CityDoctorEdge/src/test/java/de/hft/stuttgart/citydoctor2/edge/MeshSurfaceUtilsTest.java @@ -77,7 +77,7 @@ public class MeshSurfaceUtilsTest { ext.addVertex(v1); MeshSurface meshSurface = MeshSurface.of(geom); - List polygons = meshSurface.getPolygons(); + List polygons = meshSurface.polygons(); assertEquals(2, polygons.size()); CDPolygonNs edgePoly1 = polygons.get(0); List coordinates = edgePoly1.getCoordinates(); @@ -147,7 +147,7 @@ public class MeshSurfaceUtilsTest { List coordChildren = firstHalfEdge.getChildren(Coordinate3d.class); assertEquals(2, coordChildren.size()); - CDPolygonNs edgePoly2 = meshSurface.getPolygons().get(1); + CDPolygonNs edgePoly2 = meshSurface.polygons().get(1); List intersectPolygons = IntersectPlanarPolygons.intersectPolygons(edgePoly1, edgePoly2, 0.000001, 0.001); assertNotNull(intersectPolygons); @@ -195,11 +195,11 @@ public class MeshSurfaceUtilsTest { ext.addVertex(v6); MeshSurface meshSurface = MeshSurface.of(geom); - List polygons = meshSurface.getPolygons(); + List polygons = meshSurface.polygons(); assertEquals(2, polygons.size()); - CDPolygonNs edgePoly1 = meshSurface.getPolygons().get(0); - CDPolygonNs edgePoly2 = meshSurface.getPolygons().get(1); + CDPolygonNs edgePoly1 = meshSurface.polygons().get(0); + CDPolygonNs edgePoly2 = meshSurface.polygons().get(1); List intersectPolygons = IntersectPlanarPolygons.intersectPolygons(edgePoly1, edgePoly2, 0.000001, 0.001); assertNotNull(intersectPolygons); @@ -248,11 +248,11 @@ public class MeshSurfaceUtilsTest { ext.addVertex(v6); MeshSurface meshSurface = MeshSurface.of(geom); - List polygons = meshSurface.getPolygons(); + List polygons = meshSurface.polygons(); assertEquals(2, polygons.size()); - CDPolygonNs edgePoly1 = meshSurface.getPolygons().get(0); - CDPolygonNs edgePoly2 = meshSurface.getPolygons().get(1); + CDPolygonNs edgePoly1 = meshSurface.polygons().get(0); + CDPolygonNs edgePoly2 = meshSurface.polygons().get(1); List intersectPolygons = IntersectPlanarPolygons.intersectPolygons(edgePoly1, edgePoly2, 0.000001, 0.001); @@ -311,11 +311,11 @@ public class MeshSurfaceUtilsTest { ext.addVertex(v2); MeshSurface meshSurface = MeshSurface.of(geom); - List polygons = meshSurface.getPolygons(); + List polygons = meshSurface.polygons(); assertEquals(2, polygons.size()); - CDPolygonNs edgePoly1 = meshSurface.getPolygons().get(0); - CDPolygonNs edgePoly2 = meshSurface.getPolygons().get(1); + CDPolygonNs edgePoly1 = meshSurface.polygons().get(0); + CDPolygonNs edgePoly2 = meshSurface.polygons().get(1); List intersectPolygons = IntersectPlanarPolygons.intersectPolygons(edgePoly1, edgePoly2, 0.000001, 0.001); @@ -375,11 +375,11 @@ public class MeshSurfaceUtilsTest { ext.addVertex(v6); MeshSurface meshSurface = MeshSurface.of(geom); - List polygons = meshSurface.getPolygons(); + List polygons = meshSurface.polygons(); assertEquals(2, polygons.size()); - CDPolygonNs edgePoly1 = meshSurface.getPolygons().get(0); - CDPolygonNs edgePoly2 = meshSurface.getPolygons().get(1); + CDPolygonNs edgePoly1 = meshSurface.polygons().get(0); + CDPolygonNs edgePoly2 = meshSurface.polygons().get(1); List intersectPolygons = IntersectPlanarPolygons.intersectPolygons(edgePoly1, edgePoly2, 0.000001, 0.001); @@ -429,11 +429,11 @@ public class MeshSurfaceUtilsTest { ext.addVertex(v6); MeshSurface meshSurface = MeshSurface.of(geom); - List polygons = meshSurface.getPolygons(); + List polygons = meshSurface.polygons(); assertEquals(2, polygons.size()); - CDPolygonNs edgePoly1 = meshSurface.getPolygons().get(0); - CDPolygonNs edgePoly2 = meshSurface.getPolygons().get(1); + CDPolygonNs edgePoly1 = meshSurface.polygons().get(0); + CDPolygonNs edgePoly2 = meshSurface.polygons().get(1); List intersectPolygons = IntersectPlanarPolygons.intersectPolygons(edgePoly1, edgePoly2, 0.000001, 0.001); @@ -482,11 +482,11 @@ public class MeshSurfaceUtilsTest { ext.addVertex(v6); MeshSurface meshSurface = MeshSurface.of(geom); - List polygons = meshSurface.getPolygons(); + List polygons = meshSurface.polygons(); assertEquals(2, polygons.size()); - CDPolygonNs edgePoly1 = meshSurface.getPolygons().get(0); - CDPolygonNs edgePoly2 = meshSurface.getPolygons().get(1); + CDPolygonNs edgePoly1 = meshSurface.polygons().get(0); + CDPolygonNs edgePoly2 = meshSurface.polygons().get(1); DebugUtils.printGeoknechtPolygon(edgePoly1, edgePoly2); @@ -543,11 +543,11 @@ public class MeshSurfaceUtilsTest { ext.addVertex(v6); MeshSurface meshSurface = MeshSurface.of(geom); - List polygons = meshSurface.getPolygons(); + List polygons = meshSurface.polygons(); assertEquals(2, polygons.size()); - CDPolygonNs edgePoly1 = meshSurface.getPolygons().get(0); - CDPolygonNs edgePoly2 = meshSurface.getPolygons().get(1); + CDPolygonNs edgePoly1 = meshSurface.polygons().get(0); + CDPolygonNs edgePoly2 = meshSurface.polygons().get(1); List intersectPolygons = IntersectPlanarPolygons.intersectPolygons(edgePoly1, edgePoly2, 0.000001, 0.001); @@ -596,11 +596,11 @@ public class MeshSurfaceUtilsTest { ext.addVertex(v4); MeshSurface meshSurface = MeshSurface.of(geom); - List polygons = meshSurface.getPolygons(); + List polygons = meshSurface.polygons(); assertEquals(2, polygons.size()); - CDPolygonNs edgePoly1 = meshSurface.getPolygons().get(0); - CDPolygonNs edgePoly2 = meshSurface.getPolygons().get(1); + CDPolygonNs edgePoly1 = meshSurface.polygons().get(0); + CDPolygonNs edgePoly2 = meshSurface.polygons().get(1); DebugUtils.printGeoknechtPolygon(edgePoly1, edgePoly2); @@ -652,11 +652,11 @@ public class MeshSurfaceUtilsTest { ext.addVertex(v6); MeshSurface meshSurface = MeshSurface.of(geom); - List polygons = meshSurface.getPolygons(); + List polygons = meshSurface.polygons(); assertEquals(2, polygons.size()); - CDPolygonNs edgePoly1 = meshSurface.getPolygons().get(0); - CDPolygonNs edgePoly2 = meshSurface.getPolygons().get(1); + CDPolygonNs edgePoly1 = meshSurface.polygons().get(0); + CDPolygonNs edgePoly2 = meshSurface.polygons().get(1); List intersectPolygons = IntersectPlanarPolygons.intersectPolygons(edgePoly1, edgePoly2, 0.000001, 0.001); @@ -706,11 +706,11 @@ public class MeshSurfaceUtilsTest { ext.addVertex(v6); MeshSurface meshSurface = MeshSurface.of(geom); - List polygons = meshSurface.getPolygons(); + List polygons = meshSurface.polygons(); assertEquals(2, polygons.size()); - CDPolygonNs edgePoly1 = meshSurface.getPolygons().get(0); - CDPolygonNs edgePoly2 = meshSurface.getPolygons().get(1); + CDPolygonNs edgePoly1 = meshSurface.polygons().get(0); + CDPolygonNs edgePoly2 = meshSurface.polygons().get(1); List intersectPolygons = IntersectPlanarPolygons.intersectPolygons(edgePoly1, edgePoly2, 0.000001, 0.001); @@ -760,11 +760,11 @@ public class MeshSurfaceUtilsTest { ext.addVertex(v6); MeshSurface meshSurface = MeshSurface.of(geom); - List polygons = meshSurface.getPolygons(); + List polygons = meshSurface.polygons(); assertEquals(2, polygons.size()); - CDPolygonNs edgePoly1 = meshSurface.getPolygons().get(0); - CDPolygonNs edgePoly2 = meshSurface.getPolygons().get(1); + CDPolygonNs edgePoly1 = meshSurface.polygons().get(0); + CDPolygonNs edgePoly2 = meshSurface.polygons().get(1); List intersectPolygons = IntersectPlanarPolygons.intersectPolygons(edgePoly1, edgePoly2, 0.000001, 0.001); @@ -810,11 +810,11 @@ public class MeshSurfaceUtilsTest { ext.addVertex(v6); MeshSurface meshSurface = MeshSurface.of(geom); - List polygons = meshSurface.getPolygons(); + List polygons = meshSurface.polygons(); assertEquals(2, polygons.size()); - CDPolygonNs edgePoly1 = meshSurface.getPolygons().get(0); - CDPolygonNs edgePoly2 = meshSurface.getPolygons().get(1); + CDPolygonNs edgePoly1 = meshSurface.polygons().get(0); + CDPolygonNs edgePoly2 = meshSurface.polygons().get(1); List intersectPolygons = IntersectPlanarPolygons.intersectPolygons(edgePoly1, edgePoly2, 0.000001, 0.001); @@ -866,11 +866,11 @@ public class MeshSurfaceUtilsTest { ext.addVertex(v6); MeshSurface meshSurface = MeshSurface.of(geom); - List polygons = meshSurface.getPolygons(); + List polygons = meshSurface.polygons(); assertEquals(2, polygons.size()); - CDPolygonNs edgePoly1 = meshSurface.getPolygons().get(0); - CDPolygonNs edgePoly2 = meshSurface.getPolygons().get(1); + CDPolygonNs edgePoly1 = meshSurface.polygons().get(0); + CDPolygonNs edgePoly2 = meshSurface.polygons().get(1); List intersectPolygons = IntersectPlanarPolygons.intersectPolygons(edgePoly1, edgePoly2, 0.000001, 0.001); @@ -922,11 +922,11 @@ public class MeshSurfaceUtilsTest { ext.addVertex(v6); MeshSurface meshSurface = MeshSurface.of(geom); - List polygons = meshSurface.getPolygons(); + List polygons = meshSurface.polygons(); assertEquals(2, polygons.size()); - CDPolygonNs edgePoly1 = meshSurface.getPolygons().get(0); - CDPolygonNs edgePoly2 = meshSurface.getPolygons().get(1); + CDPolygonNs edgePoly1 = meshSurface.polygons().get(0); + CDPolygonNs edgePoly2 = meshSurface.polygons().get(1); List intersectPolygons = IntersectPlanarPolygons.intersectPolygons(edgePoly1, edgePoly2, 0.000001, 0.001); @@ -978,11 +978,11 @@ public class MeshSurfaceUtilsTest { ext.addVertex(v6); MeshSurface meshSurface = MeshSurface.of(geom); - List polygons = meshSurface.getPolygons(); + List polygons = meshSurface.polygons(); assertEquals(2, polygons.size()); - CDPolygonNs edgePoly1 = meshSurface.getPolygons().get(0); - CDPolygonNs edgePoly2 = meshSurface.getPolygons().get(1); + CDPolygonNs edgePoly1 = meshSurface.polygons().get(0); + CDPolygonNs edgePoly2 = meshSurface.polygons().get(1); List intersectPolygons = IntersectPlanarPolygons.intersectPolygons(edgePoly1, edgePoly2, 0.000001, 0.001); @@ -1049,11 +1049,11 @@ public class MeshSurfaceUtilsTest { ext.addVertex(v5); MeshSurface meshSurface = MeshSurface.of(geom); - List polygons = meshSurface.getPolygons(); + List polygons = meshSurface.polygons(); assertEquals(2, polygons.size()); - CDPolygonNs edgePoly1 = meshSurface.getPolygons().get(0); - CDPolygonNs edgePoly2 = meshSurface.getPolygons().get(1); + CDPolygonNs edgePoly1 = meshSurface.polygons().get(0); + CDPolygonNs edgePoly2 = meshSurface.polygons().get(1); List intersectPolygons = IntersectPlanarPolygons.intersectPolygons(edgePoly1, edgePoly2, 0.000001, 0.001); @@ -1110,11 +1110,11 @@ public class MeshSurfaceUtilsTest { ext.addVertex(v11); MeshSurface meshSurface = MeshSurface.of(geom); - List polygons = meshSurface.getPolygons(); + List polygons = meshSurface.polygons(); assertEquals(2, polygons.size()); - CDPolygonNs edgePoly1 = meshSurface.getPolygons().get(0); - CDPolygonNs edgePoly2 = meshSurface.getPolygons().get(1); + CDPolygonNs edgePoly1 = meshSurface.polygons().get(0); + CDPolygonNs edgePoly2 = meshSurface.polygons().get(1); List intersectPolygons = IntersectPlanarPolygons.intersectPolygons(edgePoly1, edgePoly2, 0.000001, 0.001); @@ -1173,11 +1173,11 @@ public class MeshSurfaceUtilsTest { ext.addVertex(v11); MeshSurface meshSurface = MeshSurface.of(geom); - List polygons = meshSurface.getPolygons(); + List polygons = meshSurface.polygons(); assertEquals(2, polygons.size()); - CDPolygonNs edgePoly1 = meshSurface.getPolygons().get(0); - CDPolygonNs edgePoly2 = meshSurface.getPolygons().get(1); + CDPolygonNs edgePoly1 = meshSurface.polygons().get(0); + CDPolygonNs edgePoly2 = meshSurface.polygons().get(1); List intersectPolygons = IntersectPlanarPolygons.intersectPolygons(edgePoly1, edgePoly2, 0.000001, 0.001); @@ -1238,11 +1238,11 @@ public class MeshSurfaceUtilsTest { ext.addVertex(v5); MeshSurface meshSurface = MeshSurface.of(geom); - List polygons = meshSurface.getPolygons(); + List polygons = meshSurface.polygons(); assertEquals(2, polygons.size()); - CDPolygonNs edgePoly1 = meshSurface.getPolygons().get(0); - CDPolygonNs edgePoly2 = meshSurface.getPolygons().get(1); + CDPolygonNs edgePoly1 = meshSurface.polygons().get(0); + CDPolygonNs edgePoly2 = meshSurface.polygons().get(1); List intersectPolygons = IntersectPlanarPolygons.intersectPolygons(edgePoly1, edgePoly2, 0.000001, 0.001); diff --git a/CityDoctorParent/CityDoctorModel/pom.xml b/CityDoctorParent/CityDoctorModel/pom.xml index 79f2c5ae86c9491f6fd25849e81322001f5f424d..6f0ba785b17d3a58d09cfe908bf87bbfa4743971 100644 --- a/CityDoctorParent/CityDoctorModel/pom.xml +++ b/CityDoctorParent/CityDoctorModel/pom.xml @@ -1,6 +1,5 @@ - - 4.0.0 + 4.0.0 de.hft.stuttgart CityDoctorParent diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/Check.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/Check.java index f45161ad9c7e321adc0088b0fc8f1d6cc1bfed83..f69575c2dfaceb14f56e75a88f0311741eb53ac0 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/Check.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/Check.java @@ -67,7 +67,7 @@ import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration; */ public abstract class Check { - private List> applicableToClasses = new ArrayList<>(2); + private final List> applicableToClasses = new ArrayList<>(2); @SuppressWarnings("unchecked") protected Check() { diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/CheckError.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/CheckError.java index 756e347c96c69e6a6727cca2ef17e497efff43e3..79567be1a6aa08d1644ebb0c556584fecd5a8b4e 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/CheckError.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/CheckError.java @@ -39,7 +39,7 @@ public interface CheckError extends Serializable { * * @return the error type */ - public ErrorType getType(); + public ErrorType getType(); /** * Getter for the error id @@ -79,7 +79,7 @@ public interface CheckError extends Serializable { * implementor of the error decides which information is written into the report * or shown on the GUI. * - * @param report + * @param report the ErrorReport. */ public void report(ErrorReport report); diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/CheckId.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/CheckId.java index 16b967ae36a7bcdc9ac74ae7641a357faab27f46..bcb0f822a9f81932c2a334de580307f14bb6b9c9 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/CheckId.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/CheckId.java @@ -18,12 +18,14 @@ */ package de.hft.stuttgart.citydoctor2.check; +import java.io.Serial; import java.io.Serializable; -public class CheckId implements Serializable { +public record CheckId(String name) implements Serializable { + @Serial private static final long serialVersionUID = -6267337828874296004L; - + public static final CheckId C_GE_R_TOO_FEW_POINTS = new CheckId("C_GE_R_TOO_FEW_POINTS"); public static final CheckId C_GE_R_NOT_CLOSED = new CheckId("C_GE_R_NOT_CLOSED"); public static final CheckId C_GE_S_MULTIPLE_CONNECTED_COMPONENTS = new CheckId( @@ -54,24 +56,7 @@ public class CheckId implements Serializable { public static final CheckId C_GE_S_NOT_CLOSED = new CheckId("C_GE_S_NOT_CLOSED"); public static final CheckId C_GE_P_ORIENTATION_RINGS_SAME = new CheckId("C_GE_P_ORIENTATION_RINGS_SAME"); public static final CheckId C_SE_POLYGON_WITHOUT_SURFACE = new CheckId("C_SE_POLYGON_WITHOUT_SURFACE"); - - private String name; - public CheckId(String name) { - this.name = name; - } - - public String getName() { - return name; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((name == null) ? 0 : name.hashCode()); - return result; - } @Override public boolean equals(Object obj) { @@ -83,12 +68,9 @@ public class CheckId implements Serializable { return false; CheckId other = (CheckId) obj; if (name == null) { - if (other.name != null) - return false; - } else if (!name.equals(other.name)) - return false; - return true; - } + return other.name == null; + } else return name.equals(other.name); + } @Override public String toString() { diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/CheckResult.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/CheckResult.java index 619ba97b806367831b970d1b1a1220435f492282..154d32c0664dde0cbe323403be9726575aadb942 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/CheckResult.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/CheckResult.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.check; +import java.io.Serial; import java.io.Serializable; /** @@ -29,6 +30,7 @@ import java.io.Serializable; */ public class CheckResult implements Serializable { + @Serial private static final long serialVersionUID = -8775678793477525693L; private final CheckId id; @@ -38,7 +40,7 @@ public class CheckResult implements Serializable { /** * Constructor for this container * - * @param c the check which produced this result + * @param id the check which produced this result * @param s the status of the result * @param err an optional error object */ @@ -66,15 +68,7 @@ public class CheckResult implements Serializable { @Override public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("CheckResult [id="); - builder.append(id); - builder.append(", status="); - builder.append(status); - builder.append(", error="); - builder.append(err); - builder.append("]"); - return builder.toString(); + return String.format("CheckResult [id=%s, status=%s, error=%s]", id, status, err); } } diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/Checkable.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/Checkable.java index 2786e8ed54857410cd49231edb35811db5012dbb..0ef96239da0577336379f1dd0d59828b221c1a50 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/Checkable.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/Checkable.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.check; +import java.io.Serial; import java.io.Serializable; import java.util.HashMap; import java.util.List; @@ -36,11 +37,12 @@ import de.hft.stuttgart.citydoctor2.datastructure.GmlId; */ public abstract class Checkable implements Serializable { + @Serial private static final long serialVersionUID = -1707871839265057882L; private static final Logger logger = LogManager.getLogger(Checkable.class); - private Map checkResults = new HashMap<>(); + private final Map checkResults = new HashMap<>(); private boolean isValidated = false; protected void setValidated(boolean validated) { diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/DefaultParameter.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/DefaultParameter.java index 2bb9aee3f9134f960d2e784fa82fa8081ce80817..0bf47aa7873d67aa04d5ea0e849ec8a627ed4595 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/DefaultParameter.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/DefaultParameter.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.check; +import java.io.Serial; import java.io.Serializable; /** @@ -30,11 +31,12 @@ import java.io.Serializable; */ public class DefaultParameter implements Serializable { + @Serial private static final long serialVersionUID = -4587211298078974066L; - private String name; - private String value; - private Unit unitType; + private final String name; + private final String value; + private final Unit unitType; public DefaultParameter(String name, String defaultValue, Unit unitType) { this.name = name; @@ -71,13 +73,7 @@ public class DefaultParameter implements Serializable { */ @Override public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("DefaultParameter [name="); - builder.append(name); - builder.append(", value="); - builder.append(value); - builder.append("]"); - return builder.toString(); + return "DefaultParameter [name=" + name + ", value=" + value + "]"; } } diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/ErrorId.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/ErrorId.java index 4b9045e2d81e957fc1f332bc5e563c4abec06c51..41d9b3f9a918da3fbd8325295deeab375d0ceaea 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/ErrorId.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/ErrorId.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.check; +import java.io.Serial; import java.io.Serializable; /** @@ -27,8 +28,9 @@ import java.io.Serializable; * @author Matthias Betz * */ -public class ErrorId implements Serializable { +public record ErrorId(String name) implements Serializable { + @Serial private static final long serialVersionUID = -2598466667746276560L; public static final ErrorId DEPENDENCIES_NOT_MET = new ErrorId("Dependencies_not_met"); @@ -65,11 +67,8 @@ public class ErrorId implements Serializable { public static final ErrorId GE_P_DEGENERATED_RING = new ErrorId("GE_P_DEGENERATED_POLYGON"); public static final ErrorId SE_POLYGON_WITHOUT_SURFACE = new ErrorId("SE_POLYGON_WITHOUT_SURFACE"); - private String name; - public ErrorId(String name) { - this.name = name; - } + @Override public int hashCode() { @@ -89,12 +88,9 @@ public class ErrorId implements Serializable { return false; ErrorId other = (ErrorId) obj; if (name == null) { - if (other.name != null) - return false; - } else if (!name.equals(other.name)) - return false; - return true; - } + return other.name == null; + } else return name.equals(other.name); + } @Override public String toString() { diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/GeometrySelfIntersection.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/GeometrySelfIntersection.java index dc0913a4bb57303184e747968f0b0ac7e9d73a48..2dedca96b1c8b5493c1396bdec1ec06691d6dcbc 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/GeometrySelfIntersection.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/GeometrySelfIntersection.java @@ -18,52 +18,17 @@ */ package de.hft.stuttgart.citydoctor2.check; +import java.io.Serial; import java.io.Serializable; import de.hft.stuttgart.citydoctor2.datastructure.Polygon; import de.hft.stuttgart.citydoctor2.math.Triangle3d; -public class GeometrySelfIntersection implements Serializable { +public record GeometrySelfIntersection(Polygon p1, Polygon p2, Triangle3d t1, Triangle3d t2) implements Serializable { + @Serial private static final long serialVersionUID = -6308847898942670140L; - - private Polygon p1; - private Polygon p2; - - private Triangle3d t1; - private Triangle3d t2; - public GeometrySelfIntersection(Polygon p1, Polygon p2, Triangle3d t1, Triangle3d t2) { - super(); - this.p1 = p1; - this.p2 = p2; - this.t1 = t1; - this.t2 = t2; - } - - public Polygon getP1() { - return p1; - } - - public void setP1(Polygon p1) { - this.p1 = p1; - } - - public Polygon getP2() { - return p2; - } - - public void setP2(Polygon p2) { - this.p2 = p2; - } - - public Triangle3d getT1() { - return t1; - } - - public Triangle3d getT2() { - return t2; - } @Override public String toString() { diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/HealingID.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/HealingID.java index 12e8d19fcc77f879444144819b0f72010015b5f9..b87ebbad7fc0afd4114d42b3038170cc2d0db107 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/HealingID.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/HealingID.java @@ -18,7 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.check; -public class HealingID { +public record HealingID(String idString) { public static final HealingID S_GEOMETRIC_SIMPLIFIER = new HealingID("S_GEOMETRIC_SIMPLIFIER"); public static final HealingID S_ALL_POLYGONS_WRONG_ORIENTATION = new HealingID("S_ALL_POLYGONS_WRONG_ORIENTATION"); @@ -37,12 +37,6 @@ public class HealingID { public static final HealingID P_NON_PLANAR_POLYGON_CPP = new HealingID("P_NON_PLANAR_POLYGON_CPP"); public static final HealingID S_NOT_CLOSED_CPP = new HealingID("S_NOT_CLOSED_CPP"); public static final HealingID SE_POLYGON_WITHOUT_SURFACE = new HealingID("SE_POLYGON_WITHOUT_SURFACE"); - - private String idString; - - public HealingID(String idString) { - this.idString = idString; - } @Override public String toString() { @@ -67,12 +61,9 @@ public class HealingID { return false; HealingID other = (HealingID) obj; if (idString == null) { - if (other.idString != null) - return false; - } else if (!idString.equals(other.idString)) - return false; - return true; - } + return other.idString == null; + } else return idString.equals(other.idString); + } diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/HealingMethod.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/HealingMethod.java index df909b774fda748f8085b99b0f72cfc041d824c5..ca4b61389f12353e1f5f6128761d8cc590a91d7a 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/HealingMethod.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/HealingMethod.java @@ -60,6 +60,7 @@ import de.hft.stuttgart.citydoctor2.check.error.UnknownCheckError; * @author Matthias Betz * */ +@SuppressWarnings("unused") public interface HealingMethod { @@ -68,7 +69,7 @@ public interface HealingMethod { default boolean visit(CheckError e, ModificationListener l) { return false; } - + default boolean visit(DegeneratedRingError e, ModificationListener l) { return false; } @@ -184,11 +185,11 @@ public interface HealingMethod { default boolean visit(NotGroundError err, ModificationListener l) { return false; } - - default boolean visit(SchematronError err, ModificationListener l) { + + default boolean visit(SchematronError err, ModificationListener l) { return false; } - + default boolean visit(SurfaceUnfragmentedError err, ModificationListener l) { return false; } diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/QualityAdeErrorVisitor.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/QualityAdeErrorVisitor.java index b9f67d61b8303ee5d282ffe3e4d67942a7eb16de..3a7e2dc795cac9e9c99a769416aa7d16fa33c53e 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/QualityAdeErrorVisitor.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/QualityAdeErrorVisitor.java @@ -91,7 +91,7 @@ import de.hft.stuttgart.quality.model.types.ValidationResult; public class QualityAdeErrorVisitor implements ErrorVisitor { - private ValidationResult res; + private final ValidationResult res; public QualityAdeErrorVisitor(ValidationResult res) { this.res = res; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/Requirement.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/Requirement.java index 82c76162a00c1559fd52d1873c9a023e021513e1..d9e4ff53ec791e2d8e39984504e8a2118a1e4601 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/Requirement.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/Requirement.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.check; +import java.io.Serial; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; @@ -25,6 +26,7 @@ import java.util.List; public class Requirement implements Serializable { + @Serial private static final long serialVersionUID = -590639811553512803L; private static final String DISTANCE_TOLERANCE = "distanceTolerance"; @@ -90,8 +92,8 @@ public class Requirement implements Serializable { } - private String id; - private RequirementType type; + private final String id; + private final RequirementType type; private List parameters; public Requirement(String id, RequirementType type) { @@ -126,12 +128,9 @@ public class Requirement implements Serializable { return false; Requirement other = (Requirement) obj; if (id == null) { - if (other.id != null) - return false; - } else if (!id.equals(other.id)) - return false; - return true; - } + return other.id == null; + } else return id.equals(other.id); + } @Override public String toString() { diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/Unit.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/Unit.java index 3a814275ee5feaa0d1898057da3f45a43833fbd8..9ea57be535d72ff4bee31e53444e55f53e34d6f3 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/Unit.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/Unit.java @@ -31,8 +31,8 @@ public enum Unit { KWH("kWh", "kWh"), METER("m", "m"), SQUARE_METER("m²", "m2"), CUBIC_METER("m³", "m3"), RADIAN(Localization.getText("Unit.Radian"), "rad"), NONE("", null), DEGREE(Localization.getText("Unit.Degree"), "deg"); - private String representation; - private String gmlRep; + private final String representation; + private final String gmlRep; private Unit(String rep, String gmlRep) { representation = rep; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/AllPolygonsWrongOrientationError.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/AllPolygonsWrongOrientationError.java index f14e95fc78a4262d7c1280eb93929245e67e7db9..38958e9dbda66088f299ab38e5b928d7b25115b3 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/AllPolygonsWrongOrientationError.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/AllPolygonsWrongOrientationError.java @@ -28,6 +28,8 @@ import de.hft.stuttgart.citydoctor2.check.ModificationListener; import de.hft.stuttgart.citydoctor2.datastructure.Geometry; import de.hft.stuttgart.citydoctor2.datastructure.GmlElement; +import java.io.Serial; + /** * Error when all polygons are oriented wrong. * @@ -36,9 +38,10 @@ import de.hft.stuttgart.citydoctor2.datastructure.GmlElement; */ public class AllPolygonsWrongOrientationError implements CheckError { + @Serial private static final long serialVersionUID = 2263993313732858840L; - private Geometry geom; + private final Geometry geom; public AllPolygonsWrongOrientationError(Geometry geom) { this.geom = geom; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/AttributeInvalidError.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/AttributeInvalidError.java index 33b7c24790e84e011521257149b0bcd84704b868..dbdab5b446abf50e2352aaf5a84ad750b1f14a5b 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/AttributeInvalidError.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/AttributeInvalidError.java @@ -28,15 +28,18 @@ import de.hft.stuttgart.citydoctor2.check.ModificationListener; import de.hft.stuttgart.citydoctor2.datastructure.CityObject; import de.hft.stuttgart.citydoctor2.datastructure.GmlElement; +import java.io.Serial; + public class AttributeInvalidError implements CheckError { + @Serial private static final long serialVersionUID = 346311592089394220L; public static final ErrorId ID = new ErrorId("SE_ATTRIBUTE_INVALID"); - private CityObject co; - private String childId; - private String nameOfAttribute; + private final CityObject co; + private final String childId; + private final String nameOfAttribute; public AttributeInvalidError(CityObject co, String childId, String nameOfAttribute) { this.co = co; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/AttributeMissingError.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/AttributeMissingError.java index de749958b883f824dafeee5653a4dcdd30e192e0..85f1c5b725226a7819ebc92698c50cb464adc8b8 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/AttributeMissingError.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/AttributeMissingError.java @@ -28,15 +28,18 @@ import de.hft.stuttgart.citydoctor2.check.ModificationListener; import de.hft.stuttgart.citydoctor2.datastructure.CityObject; import de.hft.stuttgart.citydoctor2.datastructure.GmlElement; +import java.io.Serial; + public class AttributeMissingError implements CheckError { + @Serial private static final long serialVersionUID = 185026674309965067L; public static final ErrorId ID = new ErrorId("SE_ATTRIBUTE_MISSING"); - private CityObject co; - private String childId; - private String nameOfAttribute; + private final CityObject co; + private final String childId; + private final String nameOfAttribute; public AttributeMissingError(CityObject co, String childId, String nameOfAttribute) { this.co = co; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/AttributeValueWrongError.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/AttributeValueWrongError.java index dd4d2b031f2368597cd3ff121549661ac7b57546..4eeb4e886ae55e78f6e09210912ce50ccc8f8972 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/AttributeValueWrongError.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/AttributeValueWrongError.java @@ -28,15 +28,18 @@ import de.hft.stuttgart.citydoctor2.check.ModificationListener; import de.hft.stuttgart.citydoctor2.datastructure.CityObject; import de.hft.stuttgart.citydoctor2.datastructure.GmlElement; +import java.io.Serial; + public class AttributeValueWrongError implements CheckError { + @Serial private static final long serialVersionUID = 6106964709204961560L; public static final ErrorId ID = new ErrorId("SE_ATTRIBUTE_WRONG_VALUE"); - private CityObject co; - private String childId; - private String nameOfAttribute; + private final CityObject co; + private final String childId; + private final String nameOfAttribute; public AttributeValueWrongError(CityObject co, String childId, String nameOfAttribute) { this.co = co; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/ConsecutivePointSameError.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/ConsecutivePointSameError.java index 687e128c6d652a9386331d3095a6414bc14bb3f1..0e93cc11dc4dbd84c53ffc64f53199349c2bfe1e 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/ConsecutivePointSameError.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/ConsecutivePointSameError.java @@ -29,6 +29,8 @@ import de.hft.stuttgart.citydoctor2.datastructure.GmlElement; import de.hft.stuttgart.citydoctor2.datastructure.LinearRing; import de.hft.stuttgart.citydoctor2.datastructure.Vertex; +import java.io.Serial; + /** * When two points are too close to each other and are consecutive in a linear * ring, this error is created. @@ -38,11 +40,12 @@ import de.hft.stuttgart.citydoctor2.datastructure.Vertex; */ public class ConsecutivePointSameError implements CheckError { + @Serial private static final long serialVersionUID = -6355935751554777494L; - private LinearRing lr; - private Vertex p1; - private Vertex p2; + private final LinearRing lr; + private final Vertex p1; + private final Vertex p2; public ConsecutivePointSameError(LinearRing lr, Vertex p1, Vertex p2) { this.lr = lr; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/DegeneratedRingError.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/DegeneratedRingError.java index 6af735ff79e6f18b3b37876457ce4f67d1260ea5..4735816b66fcc5474b8fe3f5a8e4d6d1d1302743 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/DegeneratedRingError.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/DegeneratedRingError.java @@ -28,11 +28,14 @@ import de.hft.stuttgart.citydoctor2.check.ModificationListener; import de.hft.stuttgart.citydoctor2.datastructure.GmlElement; import de.hft.stuttgart.citydoctor2.datastructure.LinearRing; +import java.io.Serial; + public class DegeneratedRingError implements CheckError { + @Serial private static final long serialVersionUID = 865493182529055651L; - private LinearRing lr; + private final LinearRing lr; public DegeneratedRingError(LinearRing lr) { this.lr = lr; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/DependenciesNotMetError.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/DependenciesNotMetError.java index c7f9bb6a3a6c2aff58431f9b54ab70b1e0c8f941..ae5ce785cf904fe0e19524e9792244c4370cccf0 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/DependenciesNotMetError.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/DependenciesNotMetError.java @@ -28,6 +28,8 @@ import de.hft.stuttgart.citydoctor2.check.HealingMethod; import de.hft.stuttgart.citydoctor2.check.ModificationListener; import de.hft.stuttgart.citydoctor2.datastructure.GmlElement; +import java.io.Serial; + /** * When a check checks if it can be executed but one or more dependency has * found an error this check can also not be executed. This error is created in @@ -39,9 +41,10 @@ import de.hft.stuttgart.citydoctor2.datastructure.GmlElement; */ public class DependenciesNotMetError implements CheckError { + @Serial private static final long serialVersionUID = -851655185949574160L; - private CheckId dependency; + private final CheckId dependency; public DependenciesNotMetError(CheckId dependency) { this.dependency = dependency; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/MultipleConnectedComponentsError.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/MultipleConnectedComponentsError.java index 1c8bea3106d4ad1966d2e4703cee072c616446e3..6edc7ae23965dce35a894e2a89b2e613b905ff9d 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/MultipleConnectedComponentsError.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/MultipleConnectedComponentsError.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.check.error; +import java.io.Serial; import java.util.List; import de.hft.stuttgart.citydoctor2.check.CheckError; @@ -40,10 +41,11 @@ import de.hft.stuttgart.citydoctor2.datastructure.Polygon; */ public class MultipleConnectedComponentsError implements CheckError { + @Serial private static final long serialVersionUID = 2152069835068857036L; - private Geometry geom; - private List> components; + private final Geometry geom; + private final List> components; public MultipleConnectedComponentsError(Geometry geom, List> components) { this.geom = geom; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NestedRingError.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NestedRingError.java index c39f57ae7635c52952adf706025b95962c0ff138..2f900dd52723ab4e9f5c2b9619362be725f3de26 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NestedRingError.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NestedRingError.java @@ -29,6 +29,8 @@ import de.hft.stuttgart.citydoctor2.datastructure.GmlElement; import de.hft.stuttgart.citydoctor2.datastructure.LinearRing; import de.hft.stuttgart.citydoctor2.datastructure.Polygon; +import java.io.Serial; + /** * If an inner ring is with in the boundaries of another, this error is created. * @@ -37,11 +39,12 @@ import de.hft.stuttgart.citydoctor2.datastructure.Polygon; */ public class NestedRingError implements CheckError { + @Serial private static final long serialVersionUID = -3396113374745830193L; - private Polygon p; - private LinearRing innerRing; - private LinearRing withinRing; + private final Polygon p; + private final LinearRing innerRing; + private final LinearRing withinRing; public NestedRingError(Polygon p, LinearRing innerRing, LinearRing withinRing) { this.p = p; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NonManifoldEdgeError.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NonManifoldEdgeError.java index de4662d1928a3093ea92c2be3d9dd7aa6980c431..47b7734214c70444149f2a4387095c6b876ced96 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NonManifoldEdgeError.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NonManifoldEdgeError.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.check.error; +import java.io.Serial; import java.util.List; import de.hft.stuttgart.citydoctor2.check.CheckError; @@ -39,10 +40,11 @@ import de.hft.stuttgart.citydoctor2.datastructure.GmlElement; */ public class NonManifoldEdgeError implements CheckError { + @Serial private static final long serialVersionUID = -6742948557014332402L; - private List edges; - private Geometry geom; + private final List edges; + private final Geometry geom; public NonManifoldEdgeError(Geometry geom, List edges) { this.edges = edges; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NonManifoldVertexError.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NonManifoldVertexError.java index a15f2ea45b5800761e01d8ef4a69d9358e1702e7..f9005c64db297940c072edfc653d5094ddd880e6 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NonManifoldVertexError.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NonManifoldVertexError.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.check.error; +import java.io.Serial; import java.util.List; import de.hft.stuttgart.citydoctor2.check.CheckError; @@ -41,11 +42,12 @@ import de.hft.stuttgart.citydoctor2.datastructure.Vertex; */ public class NonManifoldVertexError implements CheckError { + @Serial private static final long serialVersionUID = -3915669943428175777L; - private List> components; - private Geometry geom; - private Vertex v; + private final List> components; + private final Geometry geom; + private final Vertex v; public NonManifoldVertexError(Geometry geom, List> components, Vertex v) { this.geom = geom; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NonPlanarPolygonDistancePlaneError.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NonPlanarPolygonDistancePlaneError.java index b0014c7124e10a7323c065cd8f05b9e2996216d6..7cb1d2df03051fd21eaedeed104b860b83c30b35 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NonPlanarPolygonDistancePlaneError.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NonPlanarPolygonDistancePlaneError.java @@ -31,6 +31,8 @@ import de.hft.stuttgart.citydoctor2.datastructure.Vertex; import de.hft.stuttgart.citydoctor2.math.Plane; import de.hft.stuttgart.citydoctor2.utils.Localization; +import java.io.Serial; + /** * Error object for planarity errors containing the polygon, the regression * plane and the distance to the plane. @@ -40,12 +42,13 @@ import de.hft.stuttgart.citydoctor2.utils.Localization; */ public class NonPlanarPolygonDistancePlaneError implements CheckError { + @Serial private static final long serialVersionUID = -3504364055236383519L; - private Polygon p; - private double distance; - private Vertex v; - private Plane plane; + private final Polygon p; + private final double distance; + private final Vertex v; + private final Plane plane; public NonPlanarPolygonDistancePlaneError(Polygon p, double distance, Vertex v, Plane plane) { this.p = p; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NonPlanarPolygonNormalsDeviation.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NonPlanarPolygonNormalsDeviation.java index e77bee1869f4b2e9a1c6f0c40aa0f8e45f706e47..388a026b32dc09d5a3e3d6fbd5d97516ee0e6c46 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NonPlanarPolygonNormalsDeviation.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NonPlanarPolygonNormalsDeviation.java @@ -28,6 +28,8 @@ import de.hft.stuttgart.citydoctor2.check.ModificationListener; import de.hft.stuttgart.citydoctor2.datastructure.GmlElement; import de.hft.stuttgart.citydoctor2.datastructure.Polygon; +import java.io.Serial; + /** * When the normal of the triangles created from the triangulation of the * polygon have a too large angle between them, this error is created. @@ -37,10 +39,11 @@ import de.hft.stuttgart.citydoctor2.datastructure.Polygon; */ public class NonPlanarPolygonNormalsDeviation implements CheckError { + @Serial private static final long serialVersionUID = 69073161885265794L; - private Polygon p; - private double deviation; + private final Polygon p; + private final double deviation; public NonPlanarPolygonNormalsDeviation(Polygon p, double deviation) { this.p = p; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NotCeilingError.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NotCeilingError.java index 699ad8b8549224b53bd5c6490ec6559eb24ffbe2..6d13a67a4bd6b4c342f3d93a6ee701ecae1952f8 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NotCeilingError.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NotCeilingError.java @@ -29,6 +29,8 @@ import de.hft.stuttgart.citydoctor2.datastructure.BoundarySurface; import de.hft.stuttgart.citydoctor2.datastructure.GmlElement; import de.hft.stuttgart.citydoctor2.datastructure.Polygon; +import java.io.Serial; + /** * If a boundary surface is infact not a ceiling even though it was defined as * one. @@ -38,10 +40,10 @@ import de.hft.stuttgart.citydoctor2.datastructure.Polygon; */ public class NotCeilingError implements CheckError { + @Serial private static final long serialVersionUID = 6725904270389419696L; - - private BoundarySurface surface; - private Polygon p; + private final BoundarySurface surface; + private final Polygon p; public NotCeilingError(BoundarySurface bs, Polygon p) { surface = bs; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NotFloorError.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NotFloorError.java index 7f4aea9fef8998552dbe93807ce03a7032533607..07021937f1b72fade7a4a2b3469471231550c17b 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NotFloorError.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NotFloorError.java @@ -29,6 +29,8 @@ import de.hft.stuttgart.citydoctor2.datastructure.BoundarySurface; import de.hft.stuttgart.citydoctor2.datastructure.GmlElement; import de.hft.stuttgart.citydoctor2.datastructure.Polygon; +import java.io.Serial; + /** * When a boundary surface is not a floor even though it was defined as one. * @@ -37,10 +39,11 @@ import de.hft.stuttgart.citydoctor2.datastructure.Polygon; */ public class NotFloorError implements CheckError { + @Serial private static final long serialVersionUID = -3193557053834977449L; - private BoundarySurface surface; - private Polygon p; + private final BoundarySurface surface; + private final Polygon p; public NotFloorError(BoundarySurface bs, Polygon p) { surface = bs; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NotGroundError.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NotGroundError.java index 90395bcf61bf8e749472bcf9d3f65fe166e710db..834acf12a5082bfc20045c718c1d87dfc2b14a9e 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NotGroundError.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NotGroundError.java @@ -29,6 +29,8 @@ import de.hft.stuttgart.citydoctor2.datastructure.BoundarySurface; import de.hft.stuttgart.citydoctor2.datastructure.GmlElement; import de.hft.stuttgart.citydoctor2.datastructure.Polygon; +import java.io.Serial; + /** * If a boundary surface is not a ground surface even though it was defined as * one. @@ -38,10 +40,11 @@ import de.hft.stuttgart.citydoctor2.datastructure.Polygon; */ public class NotGroundError implements CheckError { + @Serial private static final long serialVersionUID = 8793224454858861221L; - private BoundarySurface surface; - private Polygon p; + private final BoundarySurface surface; + private final Polygon p; public NotGroundError(BoundarySurface bs, Polygon p) { surface = bs; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NotWallError.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NotWallError.java index 6eb0835f3a1d43f71e4943cde5dc6b8581d5e03b..88b59cf643f50387498c80b5878a8fde23f42e05 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NotWallError.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NotWallError.java @@ -30,6 +30,8 @@ import de.hft.stuttgart.citydoctor2.datastructure.GmlElement; import de.hft.stuttgart.citydoctor2.datastructure.Polygon; import de.hft.stuttgart.citydoctor2.math.Vector3d; +import java.io.Serial; + /** * if a boundary surface is not a wall even though it was defined as one. * @@ -38,11 +40,12 @@ import de.hft.stuttgart.citydoctor2.math.Vector3d; */ public class NotWallError implements CheckError { + @Serial private static final long serialVersionUID = 406429139625558232L; - private BoundarySurface surface; - private Polygon p; - private Vector3d normal; + private final BoundarySurface surface; + private final Polygon p; + private final Vector3d normal; public NotWallError(BoundarySurface bs, Polygon p, Vector3d normal) { surface = bs; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NullAreaError.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NullAreaError.java index e0bf8d9b5824f89b8270b3cefdb2e05db7c5f143..d3fdbe6e59052d2c2293ab0257fa69db2bf6013f 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NullAreaError.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NullAreaError.java @@ -28,6 +28,8 @@ import de.hft.stuttgart.citydoctor2.check.ModificationListener; import de.hft.stuttgart.citydoctor2.datastructure.GmlElement; import de.hft.stuttgart.citydoctor2.datastructure.LinearRing; +import java.io.Serial; + /** * When a linear ring has a near zero area this error is created. * @@ -36,9 +38,10 @@ import de.hft.stuttgart.citydoctor2.datastructure.LinearRing; */ public class NullAreaError implements CheckError { + @Serial private static final long serialVersionUID = 1358910429039553687L; - private LinearRing lr; + private final LinearRing lr; public NullAreaError(LinearRing lr) { this.lr = lr; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/PointTouchesEdgeError.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/PointTouchesEdgeError.java index a3295435496aaa4a51f472a2194f4a4f07934ea3..79cfb8799dd46f6eb5771ce907aa1bba721421e8 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/PointTouchesEdgeError.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/PointTouchesEdgeError.java @@ -30,6 +30,8 @@ import de.hft.stuttgart.citydoctor2.datastructure.GmlElement; import de.hft.stuttgart.citydoctor2.datastructure.LinearRing; import de.hft.stuttgart.citydoctor2.datastructure.Vertex; +import java.io.Serial; + /** * If a point of a linear ring touches an edge of the same ring it is considered * self intersecting and this error object is created. @@ -39,11 +41,12 @@ import de.hft.stuttgart.citydoctor2.datastructure.Vertex; */ public class PointTouchesEdgeError implements CheckError { + @Serial private static final long serialVersionUID = 3277456707271748954L; - private LinearRing lr; - private Edge e; - private Vertex v; + private final LinearRing lr; + private final Edge e; + private final Vertex v; public PointTouchesEdgeError(LinearRing lr, Edge e, Vertex v) { this.lr = lr; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/PolygonHoleOutsideError.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/PolygonHoleOutsideError.java index 13506ede91a5d03165e8c9ffc5a94881c10b502a..c290554fcdce6e86d56aa3dee68c76cc3f6d0c92 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/PolygonHoleOutsideError.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/PolygonHoleOutsideError.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.check.error; +import java.io.Serial; import java.util.List; import de.hft.stuttgart.citydoctor2.check.CheckError; @@ -40,10 +41,11 @@ import de.hft.stuttgart.citydoctor2.datastructure.Polygon; */ public class PolygonHoleOutsideError implements CheckError { + @Serial private static final long serialVersionUID = -4522153084655775231L; - private List holesOutside; - private Polygon p; + private final List holesOutside; + private final Polygon p; public PolygonHoleOutsideError(Polygon p, List holesOutside) { this.p = p; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/PolygonInteriorDisconnectedError.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/PolygonInteriorDisconnectedError.java index 47fa5c91ab484ad718690304599057e46bf4bc10..0cb0c51dd40ad3856092eba327805eaea6496135 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/PolygonInteriorDisconnectedError.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/PolygonInteriorDisconnectedError.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.check.error; +import java.io.Serial; import java.util.List; import de.hft.stuttgart.citydoctor2.check.CheckError; @@ -40,10 +41,11 @@ import de.hft.stuttgart.citydoctor2.datastructure.Polygon; */ public class PolygonInteriorDisconnectedError implements CheckError { + @Serial private static final long serialVersionUID = 511849016699842395L; - private Polygon p; - private List connectedRings; + private final Polygon p; + private final List connectedRings; public PolygonInteriorDisconnectedError(Polygon p, List connectedRings) { this.p = p; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/PolygonIntersectingRingsError.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/PolygonIntersectingRingsError.java index a23581f7bcfd52ff39c3e205996516f5dd74aa91..771fb1d59fca52e52e4f31ac7e088e54269417fd 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/PolygonIntersectingRingsError.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/PolygonIntersectingRingsError.java @@ -30,6 +30,8 @@ import de.hft.stuttgart.citydoctor2.datastructure.LinearRing; import de.hft.stuttgart.citydoctor2.datastructure.Polygon; import de.hft.stuttgart.citydoctor2.utils.SerializablePair; +import java.io.Serial; + /** * If the exterior ring and interior rings are intersecting each other, it * results in a polygon self intersection and this error is created. @@ -39,10 +41,11 @@ import de.hft.stuttgart.citydoctor2.utils.SerializablePair; */ public class PolygonIntersectingRingsError implements CheckError { + @Serial private static final long serialVersionUID = -7043521697085991901L; - private Polygon p; - private SerializablePair intersectingRings; + private final Polygon p; + private final SerializablePair intersectingRings; public PolygonIntersectingRingsError(Polygon p, SerializablePair intersectingRings) { this.p = p; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/PolygonSameOrientationError.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/PolygonSameOrientationError.java index fd4d6ecd9f6516a870036632d8ee1797a5bba6c0..3904d526e9f4919ff25b2d1e0af4a9970bcd88e8 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/PolygonSameOrientationError.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/PolygonSameOrientationError.java @@ -29,6 +29,8 @@ import de.hft.stuttgart.citydoctor2.datastructure.GmlElement; import de.hft.stuttgart.citydoctor2.datastructure.LinearRing; import de.hft.stuttgart.citydoctor2.datastructure.Polygon; +import java.io.Serial; + /** * If the interior rings have the same orientation as the exterior ring, this * error is created. @@ -38,10 +40,11 @@ import de.hft.stuttgart.citydoctor2.datastructure.Polygon; */ public class PolygonSameOrientationError implements CheckError { + @Serial private static final long serialVersionUID = -6192337889977667459L; - private Polygon p; - private LinearRing innerRing; + private final Polygon p; + private final LinearRing innerRing; public PolygonSameOrientationError(Polygon p, LinearRing inner) { this.p = p; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/PolygonWithoutSurfaceError.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/PolygonWithoutSurfaceError.java index c5c1ea1c371761818e72467b0bf3bf4d60f8eb88..d9bf0e694dc17d74fdb860e1699492cf7a10d5ca 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/PolygonWithoutSurfaceError.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/PolygonWithoutSurfaceError.java @@ -10,11 +10,14 @@ import de.hft.stuttgart.citydoctor2.check.ModificationListener; import de.hft.stuttgart.citydoctor2.datastructure.GmlElement; import de.hft.stuttgart.citydoctor2.datastructure.Polygon; +import java.io.Serial; + public class PolygonWithoutSurfaceError implements CheckError { + @Serial private static final long serialVersionUID = 2676579487514583105L; - private Polygon p; + private final Polygon p; public PolygonWithoutSurfaceError(Polygon polygon) { diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/PolygonWrongOrientationError.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/PolygonWrongOrientationError.java index 7c6ad0025d17a653a2d966b5a90fa5ec6005496c..10633e1f1233a979a08fff8e5108d796a4b8e4b9 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/PolygonWrongOrientationError.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/PolygonWrongOrientationError.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.check.error; +import java.io.Serial; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -44,10 +45,11 @@ import de.hft.stuttgart.citydoctor2.datastructure.Polygon; */ public class PolygonWrongOrientationError implements CheckError { + @Serial private static final long serialVersionUID = -3006643655816847097L; - private List edges; - private Geometry g; + private final List edges; + private final Geometry g; public PolygonWrongOrientationError(Geometry g, List edges) { this.edges = edges; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/RingDuplicatePointError.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/RingDuplicatePointError.java index 271eda62bc2c2b58d6afeaba55a8c141d7b2ac92..aaef3e1f283c4dbeee68a0591e357480ca1d2a19 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/RingDuplicatePointError.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/RingDuplicatePointError.java @@ -29,6 +29,8 @@ import de.hft.stuttgart.citydoctor2.datastructure.GmlElement; import de.hft.stuttgart.citydoctor2.datastructure.LinearRing; import de.hft.stuttgart.citydoctor2.datastructure.Vertex; +import java.io.Serial; + /** * When a point is repeated in a linear ring, but is not consecutive. This * results in a self intersection of the ring and this error object is created. @@ -38,11 +40,12 @@ import de.hft.stuttgart.citydoctor2.datastructure.Vertex; */ public class RingDuplicatePointError implements CheckError { + @Serial private static final long serialVersionUID = 7208982075173209953L; - private LinearRing r; - private Vertex v1; - private Vertex v2; + private final LinearRing r; + private final Vertex v1; + private final Vertex v2; public RingDuplicatePointError(LinearRing r, Vertex v1, Vertex v2) { this.r = r; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/RingEdgeIntersectionError.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/RingEdgeIntersectionError.java index e7fc78468b49848f6b3777420c56df3090fde4eb..45572d7cfcd87c3d5d2340940c440ef585ab3667 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/RingEdgeIntersectionError.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/RingEdgeIntersectionError.java @@ -30,6 +30,8 @@ import de.hft.stuttgart.citydoctor2.datastructure.GmlElement; import de.hft.stuttgart.citydoctor2.datastructure.LinearRing; import de.hft.stuttgart.citydoctor2.math.Vector3d; +import java.io.Serial; + /** * When two edges of the same linear ring are intersecting with each other this * error object is created. @@ -39,12 +41,13 @@ import de.hft.stuttgart.citydoctor2.math.Vector3d; */ public class RingEdgeIntersectionError implements CheckError { + @Serial private static final long serialVersionUID = 4923311259469198172L; - private Edge e1; - private Edge e2; - private Vector3d intersection; - private LinearRing lr; + private final Edge e1; + private final Edge e2; + private final Vector3d intersection; + private final LinearRing lr; public RingEdgeIntersectionError(LinearRing lr, Edge e1, Edge e2, Vector3d intersection) { if (e1 == null || e2 == null || lr == null || intersection == null) { diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/RingNotClosedError.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/RingNotClosedError.java index 0463d3c93c26ab3519c35d552b8b98a632abf8fa..80477a15caa367e77e2b988d5e4f800bb5bd13e9 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/RingNotClosedError.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/RingNotClosedError.java @@ -28,6 +28,8 @@ import de.hft.stuttgart.citydoctor2.check.ModificationListener; import de.hft.stuttgart.citydoctor2.datastructure.GmlElement; import de.hft.stuttgart.citydoctor2.datastructure.LinearRing; +import java.io.Serial; + /** * If the first and last point of a linear ring are not the same, this error is * created. @@ -37,9 +39,10 @@ import de.hft.stuttgart.citydoctor2.datastructure.LinearRing; */ public class RingNotClosedError implements CheckError { + @Serial private static final long serialVersionUID = 2554099996830579201L; - private LinearRing ring; + private final LinearRing ring; public RingNotClosedError(LinearRing ring) { this.ring = ring; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/RingTooFewPointsError.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/RingTooFewPointsError.java index b7a08a726bf9d7c800e7ecef67ae99aee8b56898..4922a454479602ca4b311c9aaaca753f6089f077 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/RingTooFewPointsError.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/RingTooFewPointsError.java @@ -28,6 +28,8 @@ import de.hft.stuttgart.citydoctor2.check.ModificationListener; import de.hft.stuttgart.citydoctor2.datastructure.GmlElement; import de.hft.stuttgart.citydoctor2.datastructure.LinearRing; +import java.io.Serial; + /** * If a linear ring has less than 4 distinct points, it is has too few points. * @@ -36,9 +38,10 @@ import de.hft.stuttgart.citydoctor2.datastructure.LinearRing; */ public class RingTooFewPointsError implements CheckError { + @Serial private static final long serialVersionUID = 7207518573842743261L; - private LinearRing lr; + private final LinearRing lr; public RingTooFewPointsError(LinearRing lr) { this.lr = lr; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/SchematronError.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/SchematronError.java index 8d5bde0bf0b19c32b5d2d2368ae28292bb8ce95b..a3dcf5103d05db077ba65f7e7d4ae2d91d3f4078 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/SchematronError.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/SchematronError.java @@ -27,14 +27,17 @@ import de.hft.stuttgart.citydoctor2.check.HealingMethod; import de.hft.stuttgart.citydoctor2.check.ModificationListener; import de.hft.stuttgart.citydoctor2.datastructure.GmlElement; +import java.io.Serial; + public class SchematronError implements CheckError { + @Serial private static final long serialVersionUID = -2964084500589868928L; - private String errorId; - private String gmlId; - private String childId; - private String nameOfAttribute; + private final String errorId; + private final String gmlId; + private final String childId; + private final String nameOfAttribute; public SchematronError(String errorId, String gmlId, String childId, String nameOfAttribute) { this.errorId = errorId; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/SolidNotClosedError.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/SolidNotClosedError.java index f0e7152c95082a5bbb6f69fcc5e35cfd99d868e0..f1b449be16a6ef4b9d493df915e8e2e4ba1c5101 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/SolidNotClosedError.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/SolidNotClosedError.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.check.error; +import java.io.Serial; import java.util.List; import de.hft.stuttgart.citydoctor2.check.CheckError; @@ -40,10 +41,11 @@ import de.hft.stuttgart.citydoctor2.datastructure.GmlElement; */ public class SolidNotClosedError implements CheckError { + @Serial private static final long serialVersionUID = 8256385219885788891L; - private List errorEdges; - private Geometry g; + private final List errorEdges; + private final Geometry g; public SolidNotClosedError(Geometry g, List errorEdges) { this.errorEdges = errorEdges; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/SolidSelfIntError.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/SolidSelfIntError.java index 63cc91c0b2ca99958c3f86dbfb5dc8b7c25f66b2..a679392549eb74807fe9467ff8e45c23a6da91f7 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/SolidSelfIntError.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/SolidSelfIntError.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.check.error; +import java.io.Serial; import java.util.List; import de.hft.stuttgart.citydoctor2.check.CheckError; @@ -39,11 +40,12 @@ import de.hft.stuttgart.citydoctor2.utils.PolygonIntersection; */ public class SolidSelfIntError implements CheckError { + @Serial private static final long serialVersionUID = -4479936555545861422L; - private Geometry g; + private final Geometry g; - private List intersections; + private final List intersections; public SolidSelfIntError(Geometry g, List intersections) { this.g = g; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/SurfaceUnfragmentedError.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/SurfaceUnfragmentedError.java index 16ceb6b34d7798c5f2917f0384991fe2c983325b..9236bf0daf4facc6cf7e1d46fc6be6984fffc269 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/SurfaceUnfragmentedError.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/SurfaceUnfragmentedError.java @@ -28,6 +28,8 @@ import de.hft.stuttgart.citydoctor2.check.ModificationListener; import de.hft.stuttgart.citydoctor2.datastructure.BoundarySurface; import de.hft.stuttgart.citydoctor2.datastructure.GmlElement; +import java.io.Serial; + /** * Container object for an unfragmented error * @@ -36,10 +38,11 @@ import de.hft.stuttgart.citydoctor2.datastructure.GmlElement; */ public class SurfaceUnfragmentedError implements CheckError { + @Serial private static final long serialVersionUID = 3146243879393474196L; - private BoundarySurface bs; - private double angleDeviation; + private final BoundarySurface bs; + private final double angleDeviation; public SurfaceUnfragmentedError(BoundarySurface bs, double angleDerivation) { this.bs = bs; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/TooFewPolygonsError.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/TooFewPolygonsError.java index 3b65d139ba36e7f2eaac71ee569dac000f6c58ce..4f0e8294708c7f0de08450e52b9e346ab21e9596 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/TooFewPolygonsError.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/TooFewPolygonsError.java @@ -28,6 +28,8 @@ import de.hft.stuttgart.citydoctor2.check.ModificationListener; import de.hft.stuttgart.citydoctor2.datastructure.Geometry; import de.hft.stuttgart.citydoctor2.datastructure.GmlElement; +import java.io.Serial; + /** * When a geometry has less than 4 polygons, it cannot form a valid solid. * @@ -36,9 +38,10 @@ import de.hft.stuttgart.citydoctor2.datastructure.GmlElement; */ public class TooFewPolygonsError implements CheckError { + @Serial private static final long serialVersionUID = 5800732409355221678L; - private Geometry g; + private final Geometry g; public TooFewPolygonsError(Geometry g) { this.g = g; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/UnknownCheckError.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/UnknownCheckError.java index b3702d9c58c69934b852aa63a1ff900c2987b8c5..403cefe18ed87f5f27d08c9d5c50c59342d57a4b 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/UnknownCheckError.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/UnknownCheckError.java @@ -30,6 +30,8 @@ import de.hft.stuttgart.citydoctor2.check.HealingMethod; import de.hft.stuttgart.citydoctor2.check.ModificationListener; import de.hft.stuttgart.citydoctor2.datastructure.GmlElement; +import java.io.Serial; + /** * This error is created when an unexpected exception is thrown by the code. * @@ -38,11 +40,12 @@ import de.hft.stuttgart.citydoctor2.datastructure.GmlElement; */ public class UnknownCheckError implements CheckError { + @Serial private static final long serialVersionUID = -6554097632341055596L; - private Checkable c; - private Exception e; - private CheckId checkId; + private final Checkable c; + private final Exception e; + private final CheckId checkId; public UnknownCheckError(Checkable c, Exception e, Check check) { this.c = c; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/AbstractBuilding.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/AbstractBuilding.java index 30630175f98b7525a5aa7acae055ee57b05fa101..e8e59dd74f8ed335186e625fc50aba1e7a5c1164 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/AbstractBuilding.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/AbstractBuilding.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.datastructure; +import java.io.Serial; import java.util.ArrayList; import java.util.List; @@ -47,12 +48,13 @@ import de.hft.stuttgart.citydoctor2.utils.Copyable; */ public abstract class AbstractBuilding extends CityObject { + @Serial private static final long serialVersionUID = -2196414503088741206L; private static final Logger logger = LogManager.getLogger(AbstractBuilding.class); - private List buildingInstallations = new ArrayList<>(2); - private List boundarySurfaceList = new ArrayList<>(); + private final List buildingInstallations = new ArrayList<>(2); + private final List boundarySurfaceList = new ArrayList<>(); private org.citygml4j.core.model.building.AbstractBuilding ab; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/BoundarySurface.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/BoundarySurface.java index a1187c5cd7d5322c0aa6de26c44ddba67525546e..13632ebc7d888230ec4650b938435bc9553a29c9 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/BoundarySurface.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/BoundarySurface.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.datastructure; +import java.io.Serial; import java.util.ArrayList; import java.util.List; @@ -42,12 +43,13 @@ import de.hft.stuttgart.citydoctor2.utils.Copyable; */ public class BoundarySurface extends CityObject { + @Serial private static final long serialVersionUID = 8793865135393496408L; private SurfaceFeatureType featureType; private BoundarySurfaceType type; - private List openings = new ArrayList<>(2); + private final List openings = new ArrayList<>(2); private CityObject parent; private AbstractThematicSurface gmlObject; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/BoundingBox.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/BoundingBox.java index 70ac0c223db8ee262f9d279d63ad92e7cd9547e6..62854cde7898b9eaae9deb715724ab0f3ca7a823 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/BoundingBox.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/BoundingBox.java @@ -32,7 +32,7 @@ import de.hft.stuttgart.citydoctor2.utils.BoundingBoxCalculator; */ public class BoundingBox { - private Vector3d[] bbox; + private final Vector3d[] bbox; /** * Creates an axis aligned bounding box containing all points of all polygons @@ -142,11 +142,7 @@ public class BoundingBox { public double getLongestSide() { double width = getWidth(); double depth = getDepth(); - if (width > depth) { - return width; - } else { - return depth; - } + return Math.max(width, depth); } /** diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/BridgeConstructiveElement.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/BridgeConstructiveElement.java index c3364e3f0338d5287bae90f7c8747a29cf579392..6a4bb82dd168220b9657b7cec737d211f605a09f 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/BridgeConstructiveElement.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/BridgeConstructiveElement.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.datastructure; +import java.io.Serial; import java.util.ArrayList; import java.util.List; @@ -47,10 +48,11 @@ public class BridgeConstructiveElement extends CityObject { private static final String CANNOT_ADD = "Cannot add "; + @Serial private static final long serialVersionUID = 7353233899458901155L; - private org.citygml4j.core.model.bridge.BridgeConstructiveElement gmlBridgeElement; - private List boundarySurfaceList = new ArrayList<>(); + private final org.citygml4j.core.model.bridge.BridgeConstructiveElement gmlBridgeElement; + private final List boundarySurfaceList = new ArrayList<>(); public BridgeConstructiveElement(org.citygml4j.core.model.bridge.BridgeConstructiveElement gmlObject) { diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/BridgeObject.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/BridgeObject.java index f0e0e2f19a61305d0576b91c02d4999a5b08aa9e..9ec8da311f2899b89fe8e5851e2ef7b3363b4108 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/BridgeObject.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/BridgeObject.java @@ -1,6 +1,6 @@ /*- * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart - * + * * This file is part of CityDoctor2. * * CityDoctor2 is free software: you can redistribute it and/or modify @@ -18,9 +18,13 @@ */ package de.hft.stuttgart.citydoctor2.datastructure; -import java.util.ArrayList; -import java.util.List; - +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.parser.ParserConfiguration; +import de.hft.stuttgart.citydoctor2.utils.CityGmlUtils; +import de.hft.stuttgart.citydoctor2.utils.CopyHandler; +import de.hft.stuttgart.citydoctor2.utils.Copyable; import org.citygml4j.core.model.bridge.AbstractBridge; import org.citygml4j.core.model.bridge.BridgeInstallation; import org.citygml4j.core.model.bridge.BridgeInstallationProperty; @@ -31,466 +35,425 @@ import org.xmlobjects.gml.model.geometry.aggregates.MultiSurfaceProperty; import org.xmlobjects.gml.model.geometry.primitives.Solid; import org.xmlobjects.gml.model.geometry.primitives.SolidProperty; -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.parser.ParserConfiguration; -import de.hft.stuttgart.citydoctor2.utils.CityGmlUtils; -import de.hft.stuttgart.citydoctor2.utils.CopyHandler; -import de.hft.stuttgart.citydoctor2.utils.Copyable; +import java.io.Serial; +import java.util.ArrayList; +import java.util.List; /** * Bridge representation object of CityGML bridge objects - * - * @author Matthias Betz * + * @author Matthias Betz */ public class BridgeObject extends CityObject { - private static final long serialVersionUID = 6301112640328373842L; - - public enum BridgeType { - BRIDGE, BRIDGE_PART - } - - private AbstractBridge ab; - private BridgeType type; - - private List parts = null; - - private List elements = null; - private List boundarySurfaces = new ArrayList<>(2); - private List bridgeInstallations = new ArrayList<>(2); - - public BridgeObject(BridgeType type, AbstractBridge ab) { - this.ab = ab; - this.type = type; - } - - @Override - public FeatureType getFeatureType() { - return FeatureType.BRIDGE; - } - - public List getConstructiveElements() { - if (elements == null) { - elements = new ArrayList<>(2); - } - return elements; - } - - public List getBridgeInstallations() { - return bridgeInstallations; - } - - @Override - public void reCreateGeometries(GeometryFactory factory, ParserConfiguration config) { - for (Geometry geom : getGeometries()) { - if (geom.getType() == GeometryType.MULTI_SURFACE) { - MultiSurface ms = CityGmlUtils.createMultiSurface(geom, factory, config); - setMultiSurfaceAccordingToLod(geom, ms); - } else { - Solid solid = CityGmlUtils.createSolid(geom, factory, config); - setSolidAccordingToLod(geom, solid); - } - } - for (BoundarySurface bs : boundarySurfaces) { - bs.reCreateGeometries(factory, config); - } - for (Installation bi : bridgeInstallations) { - bi.reCreateGeometries(factory, config); - } - if (parts != null) { - for (BridgeObject part : parts) { - part.reCreateGeometries(factory, config); - } - } - if (elements != null) { - for (BridgeConstructiveElement ele : elements) { - ele.reCreateGeometries(factory, config); - } - } - } - - private void setMultiSurfaceAccordingToLod(Geometry geom, MultiSurface ms) { - switch (geom.getLod()) { - case LOD1: - ab.getDeprecatedProperties().setLod1MultiSurface(new MultiSurfaceProperty(ms)); - break; - case LOD2: - ab.setLod2MultiSurface(new MultiSurfaceProperty(ms)); - break; - case LOD3: - ab.setLod3MultiSurface(new MultiSurfaceProperty(ms)); - break; - case LOD4: - ab.getDeprecatedProperties().setLod4MultiSurface(new MultiSurfaceProperty(ms)); - break; - default: - throw new IllegalStateException("Cannot add " + geom.getLod() + " multi surface to bridges"); - } - } - - private void setSolidAccordingToLod(Geometry geom, Solid solid) { - switch (geom.getLod()) { - case LOD1: - ab.setLod1Solid(new SolidProperty(solid)); - break; - case LOD2: - ab.setLod2Solid(new SolidProperty(solid)); - break; - case LOD3: - ab.setLod3Solid(new SolidProperty(solid)); - break; - case LOD4: - ab.getDeprecatedProperties().setLod4Solid(new SolidProperty(solid)); - break; - default: - throw new IllegalStateException("Cannot add " + geom.getLod() + " solid to bridges"); - } - } - - public void addBridgeInstallation(Installation coBi) { - bridgeInstallations.add(coBi); - coBi.setParent(this); - } - - @Override - public void clearAllContainedCheckResults() { - super.clearAllContainedCheckResults(); - for (BoundarySurface bs : boundarySurfaces) { - bs.clearAllContainedCheckResults(); - } - for (Installation bi : bridgeInstallations) { - bi.clearAllContainedCheckResults(); - } - if (parts != null) { - for (BridgeObject part : parts) { - part.clearAllContainedCheckResults(); - } - } - if (elements != null) { - for (BridgeConstructiveElement ele : elements) { - ele.clearAllContainedCheckResults(); - } - } - } - - @Override - public void collectContainedErrors(List errors) { - super.collectContainedErrors(errors); - for (BoundarySurface bs : boundarySurfaces) { - bs.collectContainedErrors(errors); - } - for (Installation bi : bridgeInstallations) { - bi.collectContainedErrors(errors); - } - if (parts != null) { - for (BridgeObject part : parts) { - part.collectContainedErrors(errors); - } - } - if (elements != null) { - for (BridgeConstructiveElement ele : elements) { - ele.collectContainedErrors(errors); - } - } - } - - @Override - public boolean containsAnyError() { - boolean hasError = super.containsAnyError(); - if (hasError) { - return true; - } - for (Installation bi : bridgeInstallations) { - if (bi.containsAnyError()) { - return true; - } - } - for (BoundarySurface bs : boundarySurfaces) { - if (bs.containsAnyError()) { - return true; - } - } - if (doPartsContainAnyError()) { - return true; - } - if (elements != null) { - for (BridgeConstructiveElement ele : elements) { - if (ele.containsAnyError()) { - return true; - } - } - } - return false; - } - - private boolean doPartsContainAnyError() { - if (parts != null) { - for (BridgeObject part : parts) { - if (part.containsAnyError()) { - return true; - } - } - } - return false; - } - - @Override - public boolean containsError(CheckId checkIdentifier) { - boolean hasError = super.containsError(checkIdentifier); - if (hasError) { - return true; - } - for (Installation bi : bridgeInstallations) { - if (bi.containsError(checkIdentifier)) { - return true; - } - } - for (BoundarySurface bs : boundarySurfaces) { - if (bs.containsError(checkIdentifier)) { - return true; - } - } - if (doPartsContainError(checkIdentifier)) { - return true; - } - if (elements != null) { - for (BridgeConstructiveElement ele : elements) { - if (ele.containsError(checkIdentifier)) { - return true; - } - } - } - return false; - } - - private boolean doPartsContainError(CheckId checkIdentifier) { - if (parts != null) { - for (BridgeObject part : parts) { - if (part.containsError(checkIdentifier)) { - return true; - } - } - } - return false; - } - - @Override - public void accept(Check c) { - super.accept(c); - if (c.canExecute(this)) { - c.check(this); - } - for (BoundarySurface bs : boundarySurfaces) { - bs.accept(c); - } - for (Installation bi : bridgeInstallations) { - bi.accept(c); - } - if (parts != null) { - for (BridgeObject part : parts) { - part.accept(c); - } - } - if (elements != null) { - for (BridgeConstructiveElement ele : elements) { - ele.accept(c); - } - } - } - - /** - * Getter method for type - * - * @return the type - */ - public BridgeType getType() { - return type; - } - - /** - * Setter Method for type - * - * @param type the type to set - */ - public void setType(BridgeType type) { - this.type = type; - } - - public void addBoundarySurface(BoundarySurface bs) { - boundarySurfaces.add(bs); - bs.setParent(this); - } - - @Override - public AbstractBridge getGmlObject() { - return ab; - } - - @Override - public void unsetGmlGeometries() { - ab.setLod1Solid(null); - ab.setLod2Solid(null); - ab.setLod3Solid(null); - ab.setLod2MultiSurface(null); - ab.setLod3MultiSurface(null); - ab.getDeprecatedProperties().setLod1MultiSurface(null); - ab.getDeprecatedProperties().setLod4MultiSurface(null); - ab.getDeprecatedProperties().setLod4Solid(null); - for (BoundarySurface bs : boundarySurfaces) { - bs.unsetGmlGeometries(); - } - for (Installation bi : bridgeInstallations) { - bi.unsetGmlGeometries(); - } - if (parts != null) { - for (BridgeObject part : parts) { - part.unsetGmlGeometries(); - } - } - if (elements != null) { - for (BridgeConstructiveElement ele : elements) { - ele.unsetGmlGeometries(); - } - } - } - - public void setGmlObject(AbstractBridge aBridge) { - ab = aBridge; - } - - @Override - public String toString() { - return "BridgeObject [type=" + type + ", id=" + getGmlId() + "]"; - } - - @Override - public void prepareForChecking() { - super.prepareForChecking(); - if (elements != null) { - for (BridgeConstructiveElement e : elements) { - e.prepareForChecking(); - } - } - if (parts != null) { - for (BridgeObject part : parts) { - part.prepareForChecking(); - } - } - for (BoundarySurface bs : boundarySurfaces) { - bs.prepareForChecking(); - } - for (Installation bi : bridgeInstallations) { - bi.prepareForChecking(); - } - } - - @Override - public void clearMetaInformation() { - super.clearMetaInformation(); - for (BoundarySurface bs : boundarySurfaces) { - bs.clearMetaInformation(); - } - for (Installation bi : bridgeInstallations) { - bi.clearMetaInformation(); - } - if (parts != null) { - for (BridgeObject part : parts) { - part.clearMetaInformation(); - } - } - if (elements != null) { - for (BridgeConstructiveElement ele : elements) { - ele.clearMetaInformation(); - } - } - } - - @Override - public void collectInstances(CopyHandler handler) { - super.collectInstances(handler); - for (BoundarySurface bs : boundarySurfaces) { - handler.addInstance(bs); - } - for (Installation bi : bridgeInstallations) { - handler.addInstance(bi); - } - if (parts != null) { - for (BridgeObject part : parts) { - handler.addInstance(part); - } - } - if (elements != null) { - for (BridgeConstructiveElement ele : elements) { - handler.addInstance(ele); - } - } - } - - public void anonymize() { - for (Geometry geom : getGeometries()) { - geom.anonymize(); - } - org.citygml4j.core.model.bridge.Bridge gmlB = new org.citygml4j.core.model.bridge.Bridge(); - gmlB.setId(GmlId.generateId().getGmlString()); - for (Installation bi : getBridgeInstallations()) { - bi.anonymize(); - gmlB.getBridgeInstallations().add(new BridgeInstallationProperty((BridgeInstallation) bi.getGmlObject())); - } - for (BoundarySurface bs : getBoundarySurfaces()) { - bs.anonymize(); - gmlB.addBoundary(new AbstractSpaceBoundaryProperty(bs.getGmlObject())); - } - this.ab = gmlB; - } - - - @Override - public void fillValues(Copyable original, CopyHandler handler) { - super.fillValues(original, handler); - BridgeObject originalBo = (BridgeObject) original; - for (BoundarySurface originalBs : originalBo.boundarySurfaces) { - boundarySurfaces.add(handler.getCopyInstance(originalBs)); - } - for (Installation originalBi : originalBo.bridgeInstallations) { - bridgeInstallations.add(handler.getCopyInstance(originalBi)); - } - if (originalBo.parts != null) { - for (BridgeObject part : originalBo.parts) { - getParts().add(handler.getCopyInstance(part)); - } - } - if (originalBo.elements != null) { - for (BridgeConstructiveElement ele : originalBo.elements) { - getConstructiveElements().add(handler.getCopyInstance(ele)); - } - } - } - - public List getBoundarySurfaces() { - return boundarySurfaces; - } - - public void addConstructiveElement(BridgeConstructiveElement element) { - getConstructiveElements().add(element); - } - - @Override - public Copyable createCopyInstance() { - return new BridgeObject(type, ab); - } - - public List getParts() { - if (parts == null) { - parts = new ArrayList<>(2); - } - return parts; - } - - public void addBridgePart(BridgeObject bPart) { - getParts().add(bPart); - } - + @Serial + private static final long serialVersionUID = 6301112640328373842L; + private final List parts = new ArrayList<>(2); + private final List elements = new ArrayList<>(2); + private final List boundarySurfaces = new ArrayList<>(2); + private final List bridgeInstallations = new ArrayList<>(2); + private AbstractBridge ab; + private BridgeType type; + public BridgeObject(BridgeType type, AbstractBridge ab) { + this.ab = ab; + this.type = type; + } + + @Override + public FeatureType getFeatureType() { + return FeatureType.BRIDGE; + } + + public List getConstructiveElements() { + return elements; + } + + public List getBridgeInstallations() { + return bridgeInstallations; + } + + @Override + public void reCreateGeometries(GeometryFactory factory, ParserConfiguration config) { + for (Geometry geom : getGeometries()) { + if (geom.getType() == GeometryType.MULTI_SURFACE) { + MultiSurface ms = CityGmlUtils.createMultiSurface(geom, factory, config); + setMultiSurfaceAccordingToLod(geom, ms); + } else { + Solid solid = CityGmlUtils.createSolid(geom, factory, config); + setSolidAccordingToLod(geom, solid); + } + } + for (BoundarySurface bs : boundarySurfaces) { + bs.reCreateGeometries(factory, config); + } + for (Installation bi : bridgeInstallations) { + bi.reCreateGeometries(factory, config); + } + for (BridgeObject part : parts) { + part.reCreateGeometries(factory, config); + } + for (BridgeConstructiveElement ele : elements) { + ele.reCreateGeometries(factory, config); + } + + } + + private void setMultiSurfaceAccordingToLod(Geometry geom, MultiSurface ms) { + switch (geom.getLod()) { + case LOD1: + ab.getDeprecatedProperties().setLod1MultiSurface(new MultiSurfaceProperty(ms)); + break; + case LOD2: + ab.setLod2MultiSurface(new MultiSurfaceProperty(ms)); + break; + case LOD3: + ab.setLod3MultiSurface(new MultiSurfaceProperty(ms)); + break; + case LOD4: + ab.getDeprecatedProperties().setLod4MultiSurface(new MultiSurfaceProperty(ms)); + break; + default: + throw new IllegalStateException("Cannot add " + geom.getLod() + " multi surface to bridges"); + } + } + + private void setSolidAccordingToLod(Geometry geom, Solid solid) { + switch (geom.getLod()) { + case LOD1: + ab.setLod1Solid(new SolidProperty(solid)); + break; + case LOD2: + ab.setLod2Solid(new SolidProperty(solid)); + break; + case LOD3: + ab.setLod3Solid(new SolidProperty(solid)); + break; + case LOD4: + ab.getDeprecatedProperties().setLod4Solid(new SolidProperty(solid)); + break; + default: + throw new IllegalStateException("Cannot add " + geom.getLod() + " solid to bridges"); + } + } + public void addBridgeInstallation(Installation coBi) { + bridgeInstallations.add(coBi); + coBi.setParent(this); + } + + @Override + public void clearAllContainedCheckResults() { + super.clearAllContainedCheckResults(); + for (BoundarySurface bs : boundarySurfaces) { + bs.clearAllContainedCheckResults(); + } + for (Installation bi : bridgeInstallations) { + bi.clearAllContainedCheckResults(); + } + for (BridgeObject part : parts) { + part.clearAllContainedCheckResults(); + } + for (BridgeConstructiveElement ele : elements) { + ele.clearAllContainedCheckResults(); + } + } + + @Override + public void collectContainedErrors(List errors) { + super.collectContainedErrors(errors); + for (BoundarySurface bs : boundarySurfaces) { + bs.collectContainedErrors(errors); + } + for (Installation bi : bridgeInstallations) { + bi.collectContainedErrors(errors); + } + for (BridgeObject part : parts) { + part.collectContainedErrors(errors); + } + for (BridgeConstructiveElement ele : elements) { + ele.collectContainedErrors(errors); + } + + } + + @Override + public boolean containsAnyError() { + boolean hasError = super.containsAnyError(); + if (hasError) { + return true; + } + for (Installation bi : bridgeInstallations) { + if (bi.containsAnyError()) { + return true; + } + } + for (BoundarySurface bs : boundarySurfaces) { + if (bs.containsAnyError()) { + return true; + } + } + if (doPartsContainAnyError()) { + return true; + } + for (BridgeConstructiveElement ele : elements) { + if (ele.containsAnyError()) { + return true; + } + } + return false; + } + + private boolean doPartsContainAnyError() { + + for (BridgeObject part : parts) { + if (part.containsAnyError()) { + return true; + } + } + return false; + } + + @Override + public boolean containsError(CheckId checkIdentifier) { + boolean hasError = super.containsError(checkIdentifier); + if (hasError) { + return true; + } + for (Installation bi : bridgeInstallations) { + if (bi.containsError(checkIdentifier)) { + return true; + } + } + for (BoundarySurface bs : boundarySurfaces) { + if (bs.containsError(checkIdentifier)) { + return true; + } + } + if (doPartsContainError(checkIdentifier)) { + return true; + } + for (BridgeConstructiveElement ele : elements) { + if (ele.containsError(checkIdentifier)) { + return true; + } + } + return false; + } + + private boolean doPartsContainError(CheckId checkIdentifier) { + + for (BridgeObject part : parts) { + if (part.containsError(checkIdentifier)) { + return true; + } + } + return false; + } + + @Override + public void accept(Check c) { + super.accept(c); + if (c.canExecute(this)) { + c.check(this); + } + for (BoundarySurface bs : boundarySurfaces) { + bs.accept(c); + } + for (Installation bi : bridgeInstallations) { + bi.accept(c); + } + for (BridgeObject part : parts) { + part.accept(c); + } + for (BridgeConstructiveElement ele : elements) { + ele.accept(c); + } + + } + + /** + * Getter method for type + * + * @return the type + */ + public BridgeType getType() { + return type; + } + + /** + * Setter Method for type + * + * @param type the type to set + */ + public void setType(BridgeType type) { + this.type = type; + } + + public void addBoundarySurface(BoundarySurface bs) { + boundarySurfaces.add(bs); + bs.setParent(this); + } + + @Override + public AbstractBridge getGmlObject() { + return ab; + } + + public void setGmlObject(AbstractBridge aBridge) { + ab = aBridge; + } + + @Override + public void unsetGmlGeometries() { + ab.setLod1Solid(null); + ab.setLod2Solid(null); + ab.setLod3Solid(null); + ab.setLod2MultiSurface(null); + ab.setLod3MultiSurface(null); + ab.getDeprecatedProperties().setLod1MultiSurface(null); + ab.getDeprecatedProperties().setLod4MultiSurface(null); + ab.getDeprecatedProperties().setLod4Solid(null); + for (BoundarySurface bs : boundarySurfaces) { + bs.unsetGmlGeometries(); + } + for (Installation bi : bridgeInstallations) { + bi.unsetGmlGeometries(); + } + for (BridgeObject part : parts) { + part.unsetGmlGeometries(); + } + for (BridgeConstructiveElement ele : elements) { + ele.unsetGmlGeometries(); + } + + } + + @Override + public String toString() { + return "BridgeObject [type=" + type + ", id=" + getGmlId() + "]"; + } + + @Override + public void prepareForChecking() { + super.prepareForChecking(); + + for (BridgeConstructiveElement e : elements) { + e.prepareForChecking(); + } + for (BridgeObject part : parts) { + part.prepareForChecking(); + } + for (BoundarySurface bs : boundarySurfaces) { + bs.prepareForChecking(); + } + for (Installation bi : bridgeInstallations) { + bi.prepareForChecking(); + } + } + + @Override + public void clearMetaInformation() { + super.clearMetaInformation(); + for (BoundarySurface bs : boundarySurfaces) { + bs.clearMetaInformation(); + } + for (Installation bi : bridgeInstallations) { + bi.clearMetaInformation(); + } + + for (BridgeObject part : parts) { + part.clearMetaInformation(); + } + + + for (BridgeConstructiveElement ele : elements) { + ele.clearMetaInformation(); + } + + } + + @Override + public void collectInstances(CopyHandler handler) { + super.collectInstances(handler); + for (BoundarySurface bs : boundarySurfaces) { + handler.addInstance(bs); + } + for (Installation bi : bridgeInstallations) { + handler.addInstance(bi); + } + + for (BridgeObject part : parts) { + handler.addInstance(part); + } + + + for (BridgeConstructiveElement ele : elements) { + handler.addInstance(ele); + } + + } + + public void anonymize() { + for (Geometry geom : getGeometries()) { + geom.anonymize(); + } + org.citygml4j.core.model.bridge.Bridge gmlB = new org.citygml4j.core.model.bridge.Bridge(); + gmlB.setId(GmlId.generateId().getGmlString()); + for (Installation bi : getBridgeInstallations()) { + bi.anonymize(); + gmlB.getBridgeInstallations().add(new BridgeInstallationProperty((BridgeInstallation) bi.getGmlObject())); + } + for (BoundarySurface bs : getBoundarySurfaces()) { + bs.anonymize(); + gmlB.addBoundary(new AbstractSpaceBoundaryProperty(bs.getGmlObject())); + } + this.ab = gmlB; + } + + @Override + public void fillValues(Copyable original, CopyHandler handler) { + super.fillValues(original, handler); + BridgeObject originalBo = (BridgeObject) original; + for (BoundarySurface originalBs : originalBo.boundarySurfaces) { + boundarySurfaces.add(handler.getCopyInstance(originalBs)); + } + for (Installation originalBi : originalBo.bridgeInstallations) { + bridgeInstallations.add(handler.getCopyInstance(originalBi)); + } + + for (BridgeObject part : originalBo.parts) { + getParts().add(handler.getCopyInstance(part)); + } + + + for (BridgeConstructiveElement ele : originalBo.elements) { + getConstructiveElements().add(handler.getCopyInstance(ele)); + } + + } + + public List getBoundarySurfaces() { + return boundarySurfaces; + } + + public void addConstructiveElement(BridgeConstructiveElement element) { + getConstructiveElements().add(element); + } + + @Override + public Copyable createCopyInstance() { + return new BridgeObject(type, ab); + } + + public List getParts() { + return parts; + } + + public void addBridgePart(BridgeObject bPart) { + getParts().add(bPart); + } + + public enum BridgeType { + BRIDGE, BRIDGE_PART + } + } diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Building.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Building.java index 4baf47729fa80717b016b4f7ad46ffa1ec0081d4..3acf2b120c7c084c1db473a5dc01ea9e7f26d27d 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Building.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Building.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.datastructure; +import java.io.Serial; import java.util.ArrayList; import java.util.List; @@ -35,9 +36,10 @@ import de.hft.stuttgart.citydoctor2.utils.Copyable; public class Building extends AbstractBuilding { + @Serial private static final long serialVersionUID = 588480113268630052L; - private List buildingParts = new ArrayList<>(2); + private final List buildingParts = new ArrayList<>(2); public List getBuildingParts() { return buildingParts; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/BuildingPart.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/BuildingPart.java index 1e59c22cf14e0cb8c1741271df490d0bdbfd8c0a..ad8a196e390de21d63ce6edc4a0fc85bd9fdf3c3 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/BuildingPart.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/BuildingPart.java @@ -21,8 +21,11 @@ package de.hft.stuttgart.citydoctor2.datastructure; import de.hft.stuttgart.citydoctor2.utils.CopyHandler; import de.hft.stuttgart.citydoctor2.utils.Copyable; +import java.io.Serial; + public class BuildingPart extends AbstractBuilding { + @Serial private static final long serialVersionUID = 8200322261958679163L; private Building parent; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/CityDoctorModel.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/CityDoctorModel.java index 36cc4084b140bb772a97eec06eb69d30ddbbf201..12fffe370cfeb0de503a0cf67e9c6e3a5e23400e 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/CityDoctorModel.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/CityDoctorModel.java @@ -30,6 +30,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Stream; import org.citygml4j.core.model.CityGMLVersion; @@ -53,17 +54,17 @@ import de.hft.stuttgart.quality.model.types.ValidationPlan; public class CityDoctorModel { private static final String COULD_NOT_FIND_FEATURE = "Could not find feature: "; - private List buildings; - private List vegetation; - private List bridges; - private List land; - private List roads; - private List water; + private final List buildings; + private final List vegetation; + private final List bridges; + private final List land; + private final List roads; + private final List water; private CityModel cModel; - private ParserConfiguration config; - private String fileName; - private File file; - private List globalErrors; + private final ParserConfiguration config; + private final String fileName; + private final File file; + private final List globalErrors; private boolean isValidated = false; private ValidationPlan plan; private CityGMLVersion cityGMLVersion; @@ -173,9 +174,9 @@ public class CityDoctorModel { return; } Map idMap = new LinkedHashMap<>(); - int counter = 0; + AtomicInteger counter = new AtomicInteger(0); for (Polygon poly : highestLod) { - counter = addRing(poly.getExteriorRing(), idMap, counter); + addRing(poly.getExteriorRing(), idMap, counter); } try (BufferedWriter writer = Files.newBufferedWriter(folder.toPath().resolve(co.getGmlId() + ".off"))) { @@ -209,14 +210,10 @@ public class CityDoctorModel { }); } - private int addRing(LinearRing ring, Map idMap, int counter) { + private void addRing(LinearRing ring, Map idMap, AtomicInteger counter) { for (Vertex v : ring.getVertices()) { - if (!idMap.containsKey(v)) { - idMap.put(v, counter); - counter++; - } + idMap.computeIfAbsent(v, k -> counter.getAndIncrement()); } - return counter; } public Set collectErrors() { diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/CityObject.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/CityObject.java index 58a3c0047954e4c421529571ed82d01214f93e24..1f45d0eba7808b5c7fc938b92bbd5d20328a7971 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/CityObject.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/CityObject.java @@ -18,8 +18,8 @@ */ package de.hft.stuttgart.citydoctor2.datastructure; +import java.io.Serial; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; import java.util.Objects; @@ -43,9 +43,10 @@ import de.hft.stuttgart.citydoctor2.utils.Copyable; */ public abstract class CityObject extends GmlElement { + @Serial private static final long serialVersionUID = 651712070755024188L; - private List geometryList = new ArrayList<>(); + private final List geometryList = new ArrayList<>(); /** * Recreates the CityGML4j geometry in this object. The CityGML4j geometry is @@ -83,23 +84,11 @@ public abstract class CityObject extends GmlElement { } public void removeGeometry(Lod lod) { - Iterator it = geometryList.iterator(); - while (it.hasNext()) { - Geometry next = it.next(); - if (next.getLod() == lod) { - it.remove(); - } - } + geometryList.removeIf(geom -> geom.getLod() == lod); } public void removeGeometry(Lod lod, GeometryType type) { - Iterator it = geometryList.iterator(); - while (it.hasNext()) { - Geometry next = it.next(); - if (next.getLod() == lod && next.getType() == type) { - it.remove(); - } - } + geometryList.removeIf(geom -> geom.getLod() == lod && geom.getType() == type); } public Geometry getHighestLodGeometry() { diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/ConcretePolygon.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/ConcretePolygon.java index ff9aad5afdc570e18145eaaf6f5591b7f7544346..c57113e2c3581b4baf46871fa43b389d3dff143a 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/ConcretePolygon.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/ConcretePolygon.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.datastructure; +import java.io.Serial; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -41,6 +42,7 @@ import de.hft.stuttgart.citydoctor2.utils.Copyable; */ public class ConcretePolygon extends Polygon { + @Serial private static final long serialVersionUID = -2208347892270418372L; private LinearRing exterior; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Edge.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Edge.java index 6a41fa7c51992382dd3e05241bce9c10122f1bf3..0aed3e21356634512a731e2a286dccb891a620a0 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Edge.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Edge.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.datastructure; +import java.io.Serial; import java.io.Serializable; import java.util.ArrayList; import java.util.List; @@ -33,10 +34,11 @@ import de.hft.stuttgart.citydoctor2.utils.Copyable; */ public class Edge implements Serializable, Copyable { + @Serial private static final long serialVersionUID = -504694863498128296L; - private List adjacentPolygons = new ArrayList<>(2); - private List adjacentRings = new ArrayList<>(2); + private final List adjacentPolygons = new ArrayList<>(2); + private final List adjacentRings = new ArrayList<>(2); private Vertex from; private Vertex to; @@ -78,16 +80,8 @@ public class Edge implements Serializable, Copyable { } private boolean isPointOfEdge(Vertex v0, Vertex edgePoint) { - if (v0.equals(edgePoint)) { - return true; - } -// for (Vertex v : v0.getNeighbors()) { -// if (v.equals(edgePoint)) { -// return true; -// } -// } - return false; - } + return v0.equals(edgePoint); + } public boolean formedByIgnoreDirection(Vertex v1, Vertex v2) { return (v1 == from && v2 == to) || (v1 == to && v2 == from); @@ -146,14 +140,9 @@ public class Edge implements Serializable, Copyable { return false; } if (to == null) { - if (other.to != null) { - return false; - } - } else if (!to.equals(other.to)) { - return false; - } - return true; - } + return other.to == null; + } else return to.equals(other.to); + } public void addAdjacentPolygon(Polygon p) { adjacentPolygons.add(p); diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/FeatureType.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/FeatureType.java index 9b6e7817a9392f716f08fe8aed6bd69d4c224147..c0cff7c5ba61a860b62e55de1a568c3e31ff1dfe 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/FeatureType.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/FeatureType.java @@ -27,6 +27,6 @@ package de.hft.stuttgart.citydoctor2.datastructure; public enum FeatureType { BUILDING, TRANSPORTATION, VEGETATION, BRIDGE, LAND, WATER, BOUNDARY_SURFACE, INSTALLATION, OPENING, - BUILDING_PART, BRIDGE_CONSTRUCTION_ELEMENT, BRIDGE_INSTALLATION; + BUILDING_PART, BRIDGE_CONSTRUCTION_ELEMENT, BRIDGE_INSTALLATION } diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Geometry.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Geometry.java index c662a92b65c8efbed9eccb3ae1f6829e040b81c8..3c3988c9bdd83c0029bc97853c1f976d856acd4c 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Geometry.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Geometry.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.datastructure; +import java.io.Serial; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -48,16 +49,17 @@ public class Geometry extends GmlElement { private static final String FAILED_REMOVING_POLYGON = "Removing polygon %s but polygon is not in geometry"; + @Serial private static final long serialVersionUID = 2539031030917731575L; - private static Random r = new Random(); + private static final Random r = new Random(); private GeometryType type; - private Lod lod; + private final Lod lod; private CityObject parent; - private List polygons = new ArrayList<>(2); + private final List polygons = new ArrayList<>(2); private List edges; private Map, Edge> edgeMap; private List vertices; @@ -153,7 +155,7 @@ public class Geometry extends GmlElement { } // only go to size -1 as ring should be closed for (int i = 0; i < ring.getVertices().size() - 1; i++) { - Vertex v0 = ring.getVertices().get(i + 0); + Vertex v0 = ring.getVertices().get(i); Vertex v1 = ring.getVertices().get(i + 1); Edge tempEdge = new Edge(v0, v1); Edge e = duplicacyMap.get(tempEdge); diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/GmlElement.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/GmlElement.java index a6d75ec5f558ba09d96f7c61925bd7ebaeca861d..f2c0229639463b13dce5c329e40578c4fae64045 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/GmlElement.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/GmlElement.java @@ -22,6 +22,8 @@ import de.hft.stuttgart.citydoctor2.check.Checkable; import de.hft.stuttgart.citydoctor2.utils.CopyHandler; import de.hft.stuttgart.citydoctor2.utils.Copyable; +import java.io.Serial; + /** * A general GML element that has a gml id * @@ -30,6 +32,7 @@ import de.hft.stuttgart.citydoctor2.utils.Copyable; */ public abstract class GmlElement extends Checkable implements Copyable { + @Serial private static final long serialVersionUID = -3242505393303017359L; private GmlId gmlId; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/GmlId.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/GmlId.java index 4c181011bb69b356d6269a8384fc927ac5fb9b8d..effc3cd7986c777da5cf75f4ea17596ffcb44c2c 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/GmlId.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/GmlId.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.datastructure; +import java.io.Serial; import java.io.Serializable; import java.util.concurrent.atomic.AtomicInteger; @@ -30,14 +31,15 @@ import java.util.concurrent.atomic.AtomicInteger; */ public class GmlId implements Serializable { + @Serial private static final long serialVersionUID = 4273817255150972966L; /* prefixes for generation */ private static final String GENERAL_GEN = "CityDoctor_%d_%d"; private static final AtomicInteger ID_COUNTER = new AtomicInteger(); - private String gmlString; - private boolean generated; + private final String gmlString; + private final boolean generated; public GmlId(String gmlId) { this(gmlId, false); @@ -85,14 +87,9 @@ public class GmlId implements Serializable { return false; } if (gmlString == null) { - if (other.gmlString != null) { - return false; - } - } else if (!gmlString.equals(other.gmlString)) { - return false; - } - return true; - } + return other.gmlString == null; + } else return gmlString.equals(other.gmlString); + } /** * Determines if the GML-ID was generated by CityDoctor or not. diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Installation.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Installation.java index e8e7473913c2bb1670e649a31181360c75afe7de..c7f485e2b3f7769222e912ae420a1341e5f2603f 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Installation.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Installation.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.datastructure; +import java.io.Serial; import java.util.ArrayList; import java.util.List; @@ -41,6 +42,7 @@ import de.hft.stuttgart.citydoctor2.utils.Copyable; public class Installation extends CityObject { + @Serial private static final long serialVersionUID = 1576237433322680191L; private List boundarySurfaces = new ArrayList<>(4); diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/LandObject.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/LandObject.java index 338415c80a284b843d37eb3ba2ce37d3339fb3bc..8c56fbfebe653700e1dec25d47d67bca1fe6630f 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/LandObject.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/LandObject.java @@ -29,6 +29,8 @@ import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration; import de.hft.stuttgart.citydoctor2.utils.CityGmlUtils; import de.hft.stuttgart.citydoctor2.utils.Copyable; +import java.io.Serial; + /** * Represents a land use CityGML object. * @@ -37,6 +39,7 @@ import de.hft.stuttgart.citydoctor2.utils.Copyable; */ public class LandObject extends CityObject { + @Serial private static final long serialVersionUID = 1887455662411087326L; private LandUse lu; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/LinearRing.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/LinearRing.java index 48f87b5ba9d977f78f613d15308c6bd36bac59d5..4261ddde2634415172b2cec2f71344f4007964f1 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/LinearRing.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/LinearRing.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.datastructure; +import java.io.Serial; import java.util.ArrayList; import java.util.List; @@ -38,12 +39,13 @@ import de.hft.stuttgart.citydoctor2.utils.Copyable; */ public class LinearRing extends GmlElement { + @Serial private static final long serialVersionUID = -2488180830514940722L; private LinearRingType type; private Polygon parent; - private List vertices = new ArrayList<>(); + private final List vertices = new ArrayList<>(); public enum LinearRingType { EXTERIOR, INTERIOR @@ -130,7 +132,7 @@ public class LinearRing extends GmlElement { public Vector3d calculateNormal() { double[] coords = new double[3]; for (int i = 0; i < vertices.size() - 1; i++) { - Vertex current = vertices.get(i + 0); + Vertex current = vertices.get(i); Vertex next = vertices.get(i + 1); coords[0] += (current.getZ() + next.getZ()) * (current.getY() - next.getY()); coords[1] += (current.getX() + next.getX()) * (current.getZ() - next.getZ()); diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/LinkedPolygon.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/LinkedPolygon.java index be036360e3d76c0dfead6403af5284b391b3a21e..c502b69d2dcff599006e3a35be45a91c71670836 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/LinkedPolygon.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/LinkedPolygon.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.datastructure; +import java.io.Serial; import java.util.List; import java.util.Map; @@ -39,6 +40,7 @@ import de.hft.stuttgart.citydoctor2.utils.Copyable; */ public class LinkedPolygon extends Polygon { + @Serial private static final long serialVersionUID = -4897578390280277931L; private Geometry parent; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Lod.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Lod.java index 1fa365d2903cdfffc6cbdde02fd0335665c796db..12eec058c2b0fd71152187c7d5eedde6bdada226 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Lod.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Lod.java @@ -28,7 +28,7 @@ public enum Lod { LOD0(0), LOD1(1), LOD2(2), LOD3(3), LOD4(4); - private int rank; + private final int rank; private Lod(int rank) { this.rank = rank; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Opening.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Opening.java index 9dac6ee3be00576bcb853c0229e92de58445c243..fe2d22808b7e8b4876b16cf471df723aa04d62a3 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Opening.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Opening.java @@ -30,6 +30,8 @@ import de.hft.stuttgart.citydoctor2.utils.CityGmlUtils; import de.hft.stuttgart.citydoctor2.utils.CopyHandler; import de.hft.stuttgart.citydoctor2.utils.Copyable; +import java.io.Serial; + /** * Represents an Opening suchs a window or Door in a surface of a feature. * Contains a reference to the boundary surface where this opening is embedded @@ -40,6 +42,7 @@ import de.hft.stuttgart.citydoctor2.utils.Copyable; */ public class Opening extends CityObject { + @Serial private static final long serialVersionUID = 6409303152284607944L; private BoundarySurface partOf; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Polygon.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Polygon.java index 010dac46f4b5785d08a5766c5213ecf11f462e21..48bdecf9484332cde5dc83300f5ac11199140d3d 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Polygon.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Polygon.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.datastructure; +import java.io.Serial; import java.util.List; import de.hft.stuttgart.citydoctor2.math.Vector3d; @@ -31,6 +32,7 @@ import de.hft.stuttgart.citydoctor2.tesselation.TesselatedPolygon; */ public abstract class Polygon extends GmlElement { + @Serial private static final long serialVersionUID = -613942946364706513L; public abstract Vector3d calculateNormalNormalized(); diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/ReliefObject.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/ReliefObject.java index 8fab1029fec8c81423569b1001f86da0259a8fc8..9cc7dea6e1f3222772f744411273e31683f21085 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/ReliefObject.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/ReliefObject.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.datastructure; +import java.io.Serial; import java.util.ArrayList; import java.util.List; @@ -33,11 +34,12 @@ import de.hft.stuttgart.citydoctor2.utils.Copyable; public class ReliefObject extends CityObject { + @Serial private static final long serialVersionUID = -9162169874426519903L; - private ReliefFeature feature; + private final ReliefFeature feature; - private List components = new ArrayList<>(); + private final List components = new ArrayList<>(); public ReliefObject(ReliefFeature feature) { this.feature = feature; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/SurfaceFeatureType.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/SurfaceFeatureType.java index 0dc7fcd24b593cf5a78d3acef15085a91a50d099..238a775543700b656178aed478c005bb04d7c91e 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/SurfaceFeatureType.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/SurfaceFeatureType.java @@ -26,6 +26,6 @@ package de.hft.stuttgart.citydoctor2.datastructure; */ public enum SurfaceFeatureType { - BUILDING, BRIDGE, TUNNEL; + BUILDING, BRIDGE, TUNNEL } diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/TinObject.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/TinObject.java index b06c1be88f6348a57b170f9d43b34dfced0ebf2d..03f5f1a556caf8933149824f7c6839b9dd6ad88d 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/TinObject.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/TinObject.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.datastructure; +import java.io.Serial; import java.util.ArrayList; import java.util.List; @@ -38,9 +39,10 @@ public class TinObject extends CityObject { private static final Logger logger = LogManager.getLogger(TinObject.class); + @Serial private static final long serialVersionUID = 1910744427384724422L; - private TINRelief gmlRelief; + private final TINRelief gmlRelief; public TinObject(TINRelief gmlRelief) { this.gmlRelief = gmlRelief; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/TransportationObject.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/TransportationObject.java index c0137cb86aab63f4002a82b06eb404ccc4c00d79..d3020ea53520707ece384ace8de109db8cb420c3 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/TransportationObject.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/TransportationObject.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.datastructure; +import java.io.Serial; import java.util.ArrayList; import java.util.List; @@ -46,6 +47,7 @@ import de.hft.stuttgart.citydoctor2.utils.Copyable; */ public class TransportationObject extends CityObject { + @Serial private static final long serialVersionUID = -2698907271726700390L; public enum TransportationType { @@ -53,8 +55,8 @@ public class TransportationObject extends CityObject { } private AbstractCityObject ato; - private List composesOf = new ArrayList<>(1); - private TransportationType type; + private final List composesOf = new ArrayList<>(1); + private final TransportationType type; public TransportationObject(TransportationType type) { this.type = type; @@ -234,11 +236,7 @@ public class TransportationObject extends CityObject { @Override public void unsetGmlGeometries() { switch (type) { - case ROAD: - case TRACK: - case RAILWAY: - case SQUARE: - case TRANSPORTATION_COMPLEX: + case ROAD, TRACK, RAILWAY, SQUARE,TRANSPORTATION_COMPLEX: AbstractTransportationSpace tc = (AbstractTransportationSpace) ato; tc.getDeprecatedProperties().setLod1MultiSurface(null); tc.setLod2MultiSurface(null); diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Vegetation.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Vegetation.java index 4fcd6398f6fe67e6346861f71147a6d898df834f..7e2d0924292a58f0915201f30caf42f2d17c0997 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Vegetation.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Vegetation.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.datastructure; +import java.io.Serial; import java.util.Collections; import org.citygml4j.core.model.core.AbstractCityObject; @@ -45,6 +46,7 @@ import de.hft.stuttgart.citydoctor2.utils.Copyable; */ public class Vegetation extends CityObject { + @Serial private static final long serialVersionUID = -5136358065541704146L; public enum VegetationType { @@ -52,7 +54,7 @@ public class Vegetation extends CityObject { } private AbstractVegetationObject citygmlVegetation; - private VegetationType type; + private final VegetationType type; public Vegetation(VegetationType type) { this.type = type; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Vertex.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Vertex.java index 6247226f0d1ffd100ccecddafae8d982df82bf8e..eb61ef7cd1a4d74126f2b0c26cbe37190abb12ed 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Vertex.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Vertex.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.datastructure; +import java.io.Serial; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -36,6 +37,7 @@ import de.hft.stuttgart.citydoctor2.utils.SerializablePair; */ public class Vertex extends Vector3d implements Copyable { + @Serial private static final long serialVersionUID = -5525361920397934892L; private List>> adjacentRings = new ArrayList<>(2); diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/WaterObject.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/WaterObject.java index b4681b0ba9b73e85969ea6904c1587382a167a5f..9a551a35aa6cd38ee583e407603281ede3ea497c 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/WaterObject.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/WaterObject.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.datastructure; +import java.io.Serial; import java.util.ArrayList; import java.util.List; @@ -41,10 +42,11 @@ import de.hft.stuttgart.citydoctor2.utils.Copyable; */ public class WaterObject extends CityObject { + @Serial private static final long serialVersionUID = -3821060595086337424L; private WaterBody gmlWater; - private List boundarySurfaceList = new ArrayList<>(); + private final List boundarySurfaceList = new ArrayList<>(); @Override public void reCreateGeometries(GeometryFactory factory, ParserConfiguration config) { diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/exceptions/CityDoctorWriteException.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/exceptions/CityDoctorWriteException.java index d6bb851c8b82ceca6e96e92ec87e3f06ba8dbd54..cba82c5777fa3902ca81c6da735f866607fa1691 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/exceptions/CityDoctorWriteException.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/exceptions/CityDoctorWriteException.java @@ -18,8 +18,11 @@ */ package de.hft.stuttgart.citydoctor2.exceptions; +import java.io.Serial; + public class CityDoctorWriteException extends Exception { + @Serial private static final long serialVersionUID = 2902212162405599516L; public CityDoctorWriteException() { diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/mapper/citygml3/Citygml3FeatureMapper.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/mapper/citygml3/Citygml3FeatureMapper.java index b07ad5edbc63badf4ab32a2ce5eca5068f067229..6b0cb62e8e7ebfb14a0674cd6f533c0b07bdabab 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/mapper/citygml3/Citygml3FeatureMapper.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/mapper/citygml3/Citygml3FeatureMapper.java @@ -114,14 +114,14 @@ public class Citygml3FeatureMapper extends ObjectWalker { private static final Logger logger = LogManager.getLogger(Citygml3FeatureMapper.class); - private CityDoctorModel model; + private final CityDoctorModel model; private Map polygonMap = new HashMap<>(); private List references = new ArrayList<>(); private Map vertexMap = new HashMap<>(); - private ParserConfiguration config; + private final ParserConfiguration config; - private double neighborDistance; + private final double neighborDistance; public Citygml3FeatureMapper(ParserConfiguration config, Path path) { this.config = config; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/mapper/citygml3/Citygml3GeometryMapper.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/mapper/citygml3/Citygml3GeometryMapper.java index edafa292ecf2a68e49f65efe451143a32ba6d093..f80fd0bba5bb9b367f0770c761385ce33fd1742a 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/mapper/citygml3/Citygml3GeometryMapper.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/mapper/citygml3/Citygml3GeometryMapper.java @@ -46,12 +46,12 @@ public class Citygml3GeometryMapper extends GeometryWalker { private static final Logger logger = LogManager.getLogger(Citygml3GeometryMapper.class); - private List polygons = new ArrayList<>(); + private final List polygons = new ArrayList<>(); private LinearRing currentRing = null; - private ParserConfiguration config; - private ProjCoordinate p1 = new ProjCoordinate(); - private ProjCoordinate p2 = new ProjCoordinate(); - private Map vertexMap; + private final ParserConfiguration config; + private final ProjCoordinate p1 = new ProjCoordinate(); + private final ProjCoordinate p2 = new ProjCoordinate(); + private final Map vertexMap; public Citygml3GeometryMapper(ParserConfiguration config, Map vertices) { this.config = config; @@ -62,7 +62,7 @@ public class Citygml3GeometryMapper extends GeometryWalker { public void visit(Polygon polygon) { parsePolygon(polygon.getId(), polygon.getExterior(), polygon.getInterior()); if (polygon.getExterior() == null) { - System.out.println("No exterior: " + polygon.getId()); + logger.warn(String.format("No exterior: %s" ,polygon.getId())); } } @@ -132,7 +132,7 @@ public class Citygml3GeometryMapper extends GeometryWalker { logger.warn("The number of coordinates for linear ring {} do not result in fully 3D points", id); } for (int i = 0; i < coordinates.size(); i = i + 3) { - double x = coordinates.get(i + 0); + double x = coordinates.get(i); double y = coordinates.get(i + 1); double z = coordinates.get(i + 2); createVertex(x, y, z); diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/mapper/citygml3/GMLValidationHandler.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/mapper/citygml3/GMLValidationHandler.java index 1236ced9f0c2c84501d93b22f74b6ef49b529121..b020d1069910f2067c07aecd52fa723edb18e2f9 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/mapper/citygml3/GMLValidationHandler.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/mapper/citygml3/GMLValidationHandler.java @@ -29,7 +29,7 @@ import org.xml.sax.SAXParseException; public class GMLValidationHandler implements ErrorHandler { private static final Logger logger = LogManager.getLogger(GMLValidationHandler.class); - private List messages = new ArrayList<>(); + private final List messages = new ArrayList<>(); @Override public void error(SAXParseException exception) { diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/mapper/citygml3/SurfaceMapper.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/mapper/citygml3/SurfaceMapper.java index 731362a5ae0cbb1077fa54819b25cbdb79e9f3df..d75534ac755fbc6b9a6d2fd308663cf2823ee271 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/mapper/citygml3/SurfaceMapper.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/mapper/citygml3/SurfaceMapper.java @@ -58,11 +58,11 @@ import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration; public class SurfaceMapper extends ObjectWalker { - private List surfaces = new ArrayList<>(); - private Map polygonMap; - private List references; - private Map vertexMap; - private ParserConfiguration config; + private final List surfaces = new ArrayList<>(); + private final Map polygonMap; + private final List references; + private final Map vertexMap; + private final ParserConfiguration config; public SurfaceMapper(Map polygonMap, List references, Map vertexMap, ParserConfiguration config) { diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/DistanceResult.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/DistanceResult.java index 29804c021855a487200884c435f0149f18f62f1d..5ecdb78b344d61fcd96d812ee4ef63f6250195e0 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/DistanceResult.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/DistanceResult.java @@ -20,33 +20,9 @@ package de.hft.stuttgart.citydoctor2.math; /** * Result of a distance calculation between two points - * - * @author Matthias Betz * + * @author Matthias Betz */ -public class DistanceResult { - - private Vector3d point1; - private Vector3d point2; - private double distance; - - public DistanceResult(Vector3d point1, Vector3d point2, double distance) { - super(); - this.point1 = point1; - this.point2 = point2; - this.distance = distance; - } - - public Vector3d getPoint1() { - return point1; - } - - public Vector3d getPoint2() { - return point2; - } - - public double getDistance() { - return distance; - } +public record DistanceResult(Vector3d point1, Vector3d point2, double distance) { } diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Edge2d.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Edge2d.java index a38eb2e8c519ee74b143992ddf8195408d1663ea..d7108d9f15a876e965397bbd6992575722e69030 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Edge2d.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Edge2d.java @@ -29,8 +29,8 @@ public class Edge2d { private static final double EPSILON = 0.0000001; private static final double ONE_MINUS_EPSILON = 1 - EPSILON; - private ProjectedVector2d a; - private ProjectedVector2d b; + private final ProjectedVector2d a; + private final ProjectedVector2d b; public Edge2d(ProjectedVector2d a, ProjectedVector2d b) { this.a = a; @@ -150,11 +150,8 @@ public class Edge2d { } else if (!a.equals(other.a)) return false; if (b == null) { - if (other.b != null) - return false; - } else if (!b.equals(other.b)) - return false; - return true; - } + return other.b == null; + } else return b.equals(other.b); + } } diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/IntersectionPoint2d.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/IntersectionPoint2d.java index 8471b7b8001fd6b970b8c86ffddb725ba79bc310..fced34e314bb8f47878c4aaee9ca39c3994c21dc 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/IntersectionPoint2d.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/IntersectionPoint2d.java @@ -20,31 +20,14 @@ package de.hft.stuttgart.citydoctor2.math; /** * Result of an intersection calculation - * - * @author Matthias Betz * + * @author Matthias Betz */ -public class IntersectionPoint2d { - - private Line2d line; - private double scalar; - - public IntersectionPoint2d(Line2d line, double scalar) { - super(); - this.line = line; - this.scalar = scalar; - } +public record IntersectionPoint2d(Line2d line, double scalar) { public Vector2d getIntersectionPoint() { - return line.getPoint().plus(line.getDirection().mult(scalar)); - } - - public Line2d getLine() { - return line; + return line.point().plus(line.direction().mult(scalar)); } - public double getScalar() { - return scalar; - } } diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Line2d.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Line2d.java index 60244f3fd96aedd57e673d45f044804957f93d1d..c0e3bd7ede6c5788fa1c4ff9a0668e6d30abfbbb 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Line2d.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Line2d.java @@ -24,22 +24,6 @@ package de.hft.stuttgart.citydoctor2.math; * @author Matthias Betz * */ -public class Line2d { - - private Vector2d p; - private Vector2d dir; - - public Line2d(Vector2d p, Vector2d dir) { - this.p = p; - this.dir = dir; - } - - public Vector2d getPoint() { - return p; - } - - public Vector2d getDirection() { - return dir; - } +public record Line2d(Vector2d point, Vector2d direction) { } diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Line3d.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Line3d.java index d237bd82b8d958dee6074b04e87e2457a31e6efa..679d99036696ba4cf669ada6efe267d936a1a3bf 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Line3d.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Line3d.java @@ -20,37 +20,13 @@ package de.hft.stuttgart.citydoctor2.math; /** * A line described by a point and a direction - * - * @author Matthias Betz * + * @author Matthias Betz */ -public class Line3d { +public record Line3d(Vector3d point, Vector3d direction) { public static final double EPSILON = 0.00001; - private Vector3d point; - private Vector3d direction; - - public Line3d(Vector3d point, Vector3d direction) { - super(); - this.point = point; - this.direction = direction; - } - - /** - * @return the point - */ - public Vector3d getPoint() { - return point; - } - - /** - * @return the direction - */ - public Vector3d getDirection() { - return direction; - } - public double distanceToPoint(Vector3d v) { double x = v.getX() - point.getX(); double y = v.getY() - point.getY(); diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Matrix3x3d.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Matrix3x3d.java index 5d751930d3fa8c7e04f56f907130beb5f7a16782..2fa33120affe68db857e88a7d47101806bf3dd25 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Matrix3x3d.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Matrix3x3d.java @@ -28,7 +28,7 @@ import java.util.Arrays; */ public class Matrix3x3d { - private double[][] values; + private final double[][] values; /** * Identity matrix @@ -123,10 +123,9 @@ public class Matrix3x3d { */ public Matrix3x3d transpose() { Matrix3x3d x = new Matrix3x3d(); - double[][] copyValues = x.values; - for (int i = 0; i < 3; i++) { + for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { - copyValues[j][i] = values[i][j]; + x.values[j][i] = values[i][j]; } } return x; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/MovedRing.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/MovedRing.java index 4be323fa6580574c7084a1c6fe9cea9a1b762406..d2763b3915c224874c65d72d86404a5ad572adc2 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/MovedRing.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/MovedRing.java @@ -32,7 +32,7 @@ import de.hft.stuttgart.citydoctor2.datastructure.Vertex; */ public class MovedRing { - private List vertices; + private final List vertices; private LinearRing original; public static MovedRing ofRing(LinearRing ring, Vector3d movedBy) { diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Plane.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Plane.java index c1d7eb96e95652c924d4807427195c55230cbbe9..d7b96a46c03c2619ad21c1f84cd5421fa8e9cc9a 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Plane.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Plane.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.math; +import java.io.Serial; import java.io.Serializable; import java.util.ArrayList; import java.util.List; @@ -35,13 +36,14 @@ import de.hft.stuttgart.citydoctor2.math.PlaneSegmentIntersection.Type; */ public class Plane implements Serializable { + @Serial private static final long serialVersionUID = 1602547402497943364L; private static final double EPSILON = 0.0001; - private UnitVector3d normal; - private Vector3d point; - private double d; + private final UnitVector3d normal; + private final Vector3d point; + private final double d; /** * Constructs a new plane from a normal vector and a reference point. @@ -51,12 +53,14 @@ public class Plane implements Serializable { */ public Plane(Vector3d normal, Vector3d p) { point = p; - this.normal = normal.normalize(); - d = this.normal.dot(point); - if (d < 0) { - this.normal = this.normal.invert(); - d = -d; + UnitVector3d normalVector = normal.normalize(); + double dot = normalVector.dot(point); + if (dot < 0) { + normalVector = normalVector.invert(); + dot = -dot; } + this.d = dot; + this.normal = normalVector; } public PlaneSegmentIntersection intersects(Segment3d s) { @@ -89,9 +93,7 @@ public class Plane implements Serializable { // intersection in segment // calculate intersection point Vector3d intersection = s.getPointA().plus(dir.mult(si)); - PlaneSegmentIntersection psi = new PlaneSegmentIntersection(Type.INTERSECTION_POINT); - psi.setPoint(intersection); - return psi; + return new PlaneSegmentIntersection(Type.INTERSECTION_POINT, intersection); } /** diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/PlaneSegmentIntersection.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/PlaneSegmentIntersection.java index 1aac9c31a26bce8fa0b0b10640bd79d7a8a8a535..3ac03b4c2c515d9014a72a7e72d40082d6621312 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/PlaneSegmentIntersection.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/PlaneSegmentIntersection.java @@ -30,21 +30,28 @@ public class PlaneSegmentIntersection { NO_INTERSECTION, IN_PLANE, INTERSECTION_POINT } - private Type type; - private Vector3d point; + private final Type type; + private final Vector3d point; - public PlaneSegmentIntersection(Type type) { + public PlaneSegmentIntersection(Type type, Vector3d point) { super(); this.type = type; + this.point = point; + } + + public PlaneSegmentIntersection(Type type){ + if (type == Type.INTERSECTION_POINT){ + throw new IllegalStateException("Tried creating a PlaneSegmentIntersection of type INTERSECTION_POINT" + + "without an intersection-point vector"); + } + this.type = type; + this.point = null; } public Vector3d getPoint() { return point; } - public void setPoint(Vector3d point) { - this.point = point; - } public Type getType() { return type; 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 48190e53ec00cffc7116ce0b39851574e1eab3ba..6ccf32f3eeb71c03ccf3d4b6efffcc7f98219594 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 @@ -33,8 +33,8 @@ import de.hft.stuttgart.citydoctor2.datastructure.Polygon; */ public class Polygon2d { - private Ring2d exterior; - private List innerRings; + private final Ring2d exterior; + private final List innerRings; public static Polygon2d withProjection(Polygon poly) { ProjectionAxis axis = ProjectionAxis.of(poly); diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/ProjectionAxis.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/ProjectionAxis.java index da8912fe3b670b0949d191750c2bd8a4b23923fa..15e0494f12c59a571871185d988f3f7b9c12b61e 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/ProjectionAxis.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/ProjectionAxis.java @@ -37,7 +37,7 @@ public class ProjectionAxis { private static final String DIVISOR_IS_0 = "Divisor is 0"; - private int[] axis; + private final int[] axis; public static ProjectionAxis of(Polygon p) { return getProjectionAxis(p.calculateNormal()); @@ -134,7 +134,7 @@ public class ProjectionAxis { double x = (d - b * y - c * z) / a; return new Vertex(x, y, z); } else { - throw new IllegalStateException("Unknown axis: " + axis); + throw new IllegalStateException("Unknown axis: " + Arrays.toString(axis)); } } diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Ray.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Ray.java index bd87a4eda2e4079b500ef4f908439b6dc6c20bda..fb1f5d9cd0722d0ba3d685ca5b1916cc07ffc37e 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Ray.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Ray.java @@ -33,8 +33,8 @@ public class Ray { public static final double EPSILON = 0.0001; - private Vector3d origin; - private UnitVector3d direction; + private final Vector3d origin; + private final UnitVector3d direction; public Ray(Vector3d origin, Vector3d direction) { this.origin = origin; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Ring2d.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Ring2d.java index 5982027bd6a176bcefcb49576c9c57082874d6b6..7df8278bf210df74e773c429e9df2fe484c2eb7f 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Ring2d.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Ring2d.java @@ -32,8 +32,8 @@ import de.hft.stuttgart.citydoctor2.datastructure.Vertex; */ public class Ring2d { - private List ringVertices; - private LinearRing original; + private final List ringVertices; + private final LinearRing original; public static Ring2d of(MovedRing movedRing) { return of(movedRing, ProjectionAxis.of(movedRing)); diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Segment2d.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Segment2d.java index d63cd8abe4cf601aa1aba840c8eb12f7148fc85f..b1bfd9a88c384e255503a8445c605d8f76575f55 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Segment2d.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Segment2d.java @@ -21,15 +21,15 @@ package de.hft.stuttgart.citydoctor2.math; /** * This class represents a line from a point to another point, it can be used to * calculate the intersection of two edges - * + * * @author Matthias Betz * */ public class Segment2d { private static final double EPSILON = 0.01; - private Vector2d p1; - private Vector2d p2; + private final Vector2d p1; + private final Vector2d p2; public Segment2d(Vector2d p1, Vector2d p2) { this.p1 = p1; @@ -51,7 +51,7 @@ public class Segment2d { double numeratora = (x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3); double numeratorb = (x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3); - + if (Math.abs(denominator) < EPSILON) { denominator = 0.0; } @@ -71,7 +71,7 @@ public class Segment2d { return ua > EPSILON && ua < (1 - EPSILON) && ub > EPSILON && ub < (1 - EPSILON); } } - + public boolean intersectsWithoutColinearity(Segment2d other) { double x1 = p1.getX(); double x2 = p2.getX(); @@ -89,7 +89,7 @@ public class Segment2d { if (Math.abs(denominator) < EPSILON) { denominator = 0.0; } - + if (denominator == 0) { // both numerators == 0 means, lines are coincident, otherwise parallel // parallel lines are not intersecting @@ -103,7 +103,7 @@ public class Segment2d { } } - + public Vector2d intersectionPoint(Segment2d other) { IntersectionPoint2d inter = calculateIntersection(other); if (inter == null) { @@ -111,7 +111,7 @@ public class Segment2d { } return inter.getIntersectionPoint(); } - + public IntersectionPoint2d calculateIntersection(Segment2d other) { double x1 = p1.getX(); double x2 = p2.getX(); @@ -122,14 +122,14 @@ public class Segment2d { double y2 = p2.getY(); double y3 = other.getP1().getY(); double y4 = other.getP2().getY(); - + double a1 = x2 - x1; double b1 = x4 - x3; double c1 = x3 - x1; double a2 = y2 - y1; double b2 = y4 - y3; double c2 = y3 - y1; - + double detA = b1 * a2 - a1 * b2; double detA1 = b1 * c2 - c1 * b2; double detA2 = a1 * c2 - c1 * a2; @@ -143,15 +143,13 @@ public class Segment2d { if (containsPoint(other.p2)) { return new IntersectionPoint2d(new Line2d(other.p2, new Vector2d()), 0); } - return null; - } else { - // parallel - return null; - } - } + } + // parallel + return null; + } double s = detA1 / detA; double t = detA2 / detA; - + if (s < 0 || s > 1 || t < 0 || t > 1) { // intersection on line but not on segment return null; @@ -160,7 +158,7 @@ public class Segment2d { Vector2d start = new Vector2d(x1, y1); return new IntersectionPoint2d(new Line2d(start, dir), s); } - + public boolean containsPoint(Vector2d p) { double xDir = p2.getX() - p1.getX(); if (xDir == 0) { diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Segment3d.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Segment3d.java index fd7befc82c74a92601db020fd5d4ec7b68f19ad5..87b6ebdd1e61938afae26d18bc48496b027a1716 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Segment3d.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Segment3d.java @@ -18,16 +18,18 @@ */ package de.hft.stuttgart.citydoctor2.math; +import java.io.Serial; import java.io.Serializable; /** * A bounded line between two points - * + * * @author Matthias Betz * */ public class Segment3d implements Serializable { + @Serial private static final long serialVersionUID = -506306945169934099L; private static final double PRECISION = 0.00000001; @@ -44,12 +46,12 @@ public class Segment3d implements Serializable { /** * calculates the distance from this segment to the other segment - * + * * @param otherSeg the other segment * @return the distance */ public double getDistance(Segment3d otherSeg) { - return getDistanceResult(otherSeg).getDistance(); + return getDistanceResult(otherSeg).distance(); } public DistanceResult getDistanceResult(Segment3d other) { diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Triangle2d.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Triangle2d.java index 4926bf23c85e22c6c031fe754e22f3055118d8bb..8c86ca780a9f252e1a04f9101b834e16899d7ca2 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Triangle2d.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Triangle2d.java @@ -20,15 +20,15 @@ package de.hft.stuttgart.citydoctor2.math; /** * A two dimensional triangle - * + * * @author Matthias Betz * */ public class Triangle2d { - private Vector2d p1; - private Vector2d p2; - private Vector2d p3; + private final Vector2d p1; + private final Vector2d p2; + private final Vector2d p3; private static final double EPSILON = 0; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Triangle3d.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Triangle3d.java index 420c24945502f62b42232c9c5d1c698ae653cfd6..96ec193dec6b4b0d350789937ec01f9991318abd 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Triangle3d.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Triangle3d.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.math; +import java.io.Serial; import java.io.Serializable; import de.hft.stuttgart.citydoctor2.tesselation.TesselatedPolygon; @@ -30,12 +31,13 @@ import de.hft.stuttgart.citydoctor2.tesselation.TesselatedPolygon; */ public class Triangle3d implements Serializable { + @Serial private static final long serialVersionUID = -6907333357794272435L; private static final double EPSILON = 0.0001; - private Vector3d p1; - private Vector3d p2; - private Vector3d p3; + private final Vector3d p1; + private final Vector3d p2; + private final Vector3d p3; private TesselatedPolygon partOf; @@ -154,8 +156,7 @@ public class Triangle3d implements Serializable { Vector3d a = p1; Vector3d b = p2; Vector3d c = p3; - Vector3d p = point; - return sameSide(p, a, b, c) && sameSide(p, b, a, c) && sameSide(p, c, a, b); + return sameSide(point, a, b, c) && sameSide(point, b, a, c) && sameSide(point, c, a, b); } private boolean sameSide(Vector3d p1, Vector3d p2, Vector3d a, Vector3d b) { @@ -248,14 +249,9 @@ public class Triangle3d implements Serializable { return false; } if (p3 == null) { - if (other.p3 != null) { - return false; - } - } else if (!p3.equals(other.p3)) { - return false; - } - return true; - } + return other.p3 == null; + } else return p3.equals(other.p3); + } @Override public String toString() { diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/UnitVector3d.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/UnitVector3d.java index 729be43fddcf443c1353022244b9a2eeee9297e0..33fe7722ce62c0c29834631f5832380a36f280fd 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/UnitVector3d.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/UnitVector3d.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.math; +import java.io.Serial; import java.util.Arrays; /** @@ -29,6 +30,7 @@ public class UnitVector3d extends Vector3d { private static final String UNIT_VECTOR_IS_IMMUTABLE = "Unit vector is immutable"; + @Serial private static final long serialVersionUID = -374685263673211587L; public static final UnitVector3d X_AXIS = new UnitVector3d(1, 0, 0); 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 7245a90afe08f21ef9dc6b52328f7d8f75a23858..ab5f495feea7441312bd8203cd10da69084d0488 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 @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.math; +import java.io.Serial; import java.io.Serializable; import java.util.Arrays; @@ -29,6 +30,7 @@ import java.util.Arrays; */ public class Vector3d implements Serializable { + @Serial private static final long serialVersionUID = 3495650092142761365L; private static final Vector3d ORIGIN = new Vector3d(); @@ -37,7 +39,7 @@ public class Vector3d implements Serializable { public static final int Y = 1; public static final int Z = 2; - private double[] coords; + private final double[] coords; public Vector3d() { this(0d, 0d, 0d); @@ -238,11 +240,9 @@ public class Vector3d implements Serializable { @Override public String toString() { final int maxLen = 5; - StringBuilder builder = new StringBuilder(); - builder.append("Vector3d [coords="); - builder.append(coords != null ? Arrays.toString(Arrays.copyOf(coords, Math.min(coords.length, maxLen))) : null); - builder.append("]"); - return builder.toString(); + return "Vector3d [coords=" + + (coords != null ? Arrays.toString(Arrays.copyOf(coords, Math.min(coords.length, maxLen))) : null) + + "]"; } @Override diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/graph/CycleNode.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/graph/CycleNode.java index 0df8c51ebb0e80149bcc83bed305ecd694ff5178..3a2d200be746b3ea7429ac736d722771dc6ec8bf 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/graph/CycleNode.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/graph/CycleNode.java @@ -44,7 +44,7 @@ public class CycleNode { private boolean visited = false; - private Set children; + private final Set children; public CycleNode(LinearRing value) { children = new HashSet<>(); @@ -92,7 +92,7 @@ public class CycleNode { if (lowlink == index) { List comps = new LinkedList<>(); - CycleNode w = null; + CycleNode w; do { w = s.pop(); w.onStack = false; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/graph/KDTree.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/graph/KDTree.java index 4ad2a16f89a83145e942e504d5190f78f988a051..798283721b4e3ea1092544497fd49398f551a2ff 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/graph/KDTree.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/graph/KDTree.java @@ -35,7 +35,7 @@ public class KDTree { private static final int K = 3; private Vertex location; - private int axis; + private final int axis; private KDTree left; private KDTree right; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/graph/PolygonGraph.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/graph/PolygonGraph.java index ca147be6b15ff48c1f353775c369881e9ffa8489..d5f2482afad13b986d25f16ab686c79fc8b6fe31 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/graph/PolygonGraph.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/graph/PolygonGraph.java @@ -38,21 +38,14 @@ import de.hft.stuttgart.citydoctor2.datastructure.Vertex; */ public class PolygonGraph { - private Map nodeMap; + private final Map nodeMap; public PolygonGraph() { nodeMap = new HashMap<>(); } private PolygonNode createOrGetNode(Polygon p) { - PolygonNode node = nodeMap.get(p); - if (node != null) { - return node; - } else { - node = new PolygonNode(p); - nodeMap.put(p, node); - return node; - } + return nodeMap.computeIfAbsent(p, PolygonNode::new); } public void addPolygonConnectionsFromVertex(Vertex v, Geometry geom) { @@ -92,7 +85,7 @@ public class PolygonGraph { List> components = new ArrayList<>(); for (PolygonNode node : nodeMap.values()) { - if (!node.visited()) { + if (node.isUnvisited()) { List component = new ArrayList<>(); Deque stack = new LinkedList<>(); stack.push(node); @@ -109,7 +102,7 @@ public class PolygonGraph { node.setVisited(true); component.add(node.getContent()); for (PolygonNode child : node.getChildren()) { - if (!child.visited()) { + if (child.isUnvisited()) { child.setVisited(true); stack.push(child); } diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/graph/PolygonNode.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/graph/PolygonNode.java index f62ced8485fb995e3b359d9c2eb8e217278361a0..3967f05637c0f3af2937e6ff3ccdaa893b802a1a 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/graph/PolygonNode.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/graph/PolygonNode.java @@ -31,8 +31,8 @@ import de.hft.stuttgart.citydoctor2.datastructure.Polygon; */ public class PolygonNode { - private Polygon content; - private Set children; + private final Polygon content; + private final Set children; private boolean visited = false; public PolygonNode(Polygon p) { @@ -56,8 +56,8 @@ public class PolygonNode { this.visited = b; } - public boolean visited() { - return visited; + public boolean isUnvisited() { + return !visited; } /* @@ -88,13 +88,9 @@ public class PolygonNode { return false; PolygonNode other = (PolygonNode) obj; if (content == null) { - if (other.content != null) - return false; - } else if (!content.equals(other.content)) { - return false; - } - return true; - } + return other.content == null; + } else return content.equals(other.content); + } @Override public String toString() { diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/parser/CityGmlParseException.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/parser/CityGmlParseException.java index 21089d79c3b7a51d66599cfe43a010149f182c81..70daf17c2b4fe445574b6bebc0048cf3703b6f16 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/parser/CityGmlParseException.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/parser/CityGmlParseException.java @@ -18,6 +18,8 @@ */ package de.hft.stuttgart.citydoctor2.parser; +import java.io.Serial; + /** * Exception when something went wrong while parsing the CityGML file. * @@ -26,6 +28,7 @@ package de.hft.stuttgart.citydoctor2.parser; */ public class CityGmlParseException extends Exception { + @Serial private static final long serialVersionUID = 8602390540552748135L; public CityGmlParseException() { diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/parser/CityGmlParser.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/parser/CityGmlParser.java index 873eea46a5145eae5bb9e1581c606c0721601fb3..0a83532669151c3ab1dea7e5bfdde3397c655384 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/parser/CityGmlParser.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/parser/CityGmlParser.java @@ -501,20 +501,14 @@ public class CityGmlParser { Matcher mURN = P_URN.matcher(srsName); // NOTE: Could use a HashMap if the switch/case becomes too long. if (mURN.find()) { - switch (mURN.group(1)) { - case "DE_DHDN_3GK2": - return CRS_FACTORY.createFromName("EPSG:31466"); - case "DE_DHDN_3GK3": - return CRS_FACTORY.createFromName("EPSG:31467"); - case "DE_DHDN_3GK4": - return CRS_FACTORY.createFromName("EPSG:31468"); - case "DE_DHDN_3GK5": - return CRS_FACTORY.createFromName("EPSG:31469"); - case "ETRS89_UTM32": - return CRS_FACTORY.createFromName("EPSG:25832"); - default: - return null; - } + return switch (mURN.group(1)) { + case "DE_DHDN_3GK2" -> CRS_FACTORY.createFromName("EPSG:31466"); + case "DE_DHDN_3GK3" -> CRS_FACTORY.createFromName("EPSG:31467"); + case "DE_DHDN_3GK4" -> CRS_FACTORY.createFromName("EPSG:31468"); + case "DE_DHDN_3GK5" -> CRS_FACTORY.createFromName("EPSG:31469"); + case "ETRS89_UTM32" -> CRS_FACTORY.createFromName("EPSG:25832"); + default -> null; + }; } if (srsName.equals("http://www.opengis.net/def/crs/EPSG/0/6697")) { return CRS_FACTORY.createFromParameters("EPSG:6697", "+proj=longlat +ellps=GRS80 +no_defs +axis=neu"); diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/parser/EnvelopeFoundException.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/parser/EnvelopeFoundException.java index 272ea080c35b2da4b22f22d8186a062093f02169..6b716f9f5b7fa51944b012d067c449e9114351fa 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/parser/EnvelopeFoundException.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/parser/EnvelopeFoundException.java @@ -20,6 +20,8 @@ package de.hft.stuttgart.citydoctor2.parser; import org.xml.sax.SAXException; +import java.io.Serial; + /** * To stop the SAXParser from further parsing when the relevant section has * already been found. @@ -29,6 +31,7 @@ import org.xml.sax.SAXException; */ public class EnvelopeFoundException extends SAXException { + @Serial private static final long serialVersionUID = -9188617211115043815L; public EnvelopeFoundException() { diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/parser/InvalidGmlFileException.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/parser/InvalidGmlFileException.java index 67ebcaf165c5be41846fb0a46c16ac32db59e56e..72cd592a58d53d6b824f7fe835e6426960f36b7e 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/parser/InvalidGmlFileException.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/parser/InvalidGmlFileException.java @@ -18,6 +18,8 @@ */ package de.hft.stuttgart.citydoctor2.parser; +import java.io.Serial; + /** * Used when an invalid CityGML file is found. * @@ -26,6 +28,7 @@ package de.hft.stuttgart.citydoctor2.parser; */ public class InvalidGmlFileException extends Exception { + @Serial private static final long serialVersionUID = 5490585939707730933L; public InvalidGmlFileException() { diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/parser/ObservedInputStream.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/parser/ObservedInputStream.java index 45a6ccf78a069acbeade053aca0bc78fbc11b618..a9c831fcc95b792dec5939ddeb781db779e128bf 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/parser/ObservedInputStream.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/parser/ObservedInputStream.java @@ -37,10 +37,10 @@ import java.util.ArrayList; public class ObservedInputStream extends FilterInputStream { /** List of registered progress listeners. */ - private ArrayList listeners = new ArrayList<>(); + private final ArrayList listeners = new ArrayList<>(); /** The number of bytes of the file to be read. */ - private long fileLength; + private final long fileLength; /** The number of bytes read so far. */ private long location; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/parser/ParserConfiguration.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/parser/ParserConfiguration.java index 9adff4c2529f6da90c492c2e1e34e303cfe157b2..3d88acfc5850598c59eee426773b2379d5be04e6 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/parser/ParserConfiguration.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/parser/ParserConfiguration.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.parser; +import java.io.Serial; import java.io.Serializable; import org.locationtech.proj4j.BasicCoordinateTransform; @@ -33,13 +34,14 @@ import org.locationtech.proj4j.CoordinateReferenceSystem; */ public class ParserConfiguration implements Serializable { + @Serial private static final long serialVersionUID = 6209047092991074661L; private static final CRSFactory CRS_FACTORY = new CRSFactory(); - private int roundingPlaces = 8; + private final int roundingPlaces ; - private boolean validate = false; + private final boolean validate; private transient BasicCoordinateTransform targetTransform = null; private transient BasicCoordinateTransform originalTransform = null; @@ -89,8 +91,8 @@ public class ParserConfiguration implements Serializable { } private void createCoordinateTransforms() { - CoordinateReferenceSystem tgtCrs = null; - CoordinateReferenceSystem crs = null; + CoordinateReferenceSystem tgtCrs ; + CoordinateReferenceSystem crs; synchronized (CRS_FACTORY) { tgtCrs = CRS_FACTORY.createFromParameters("Target", targetTransformString); crs = CRS_FACTORY.createFromParameters("Original", originalTransformString); 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 7311ed6f8d763fab86c694436349b49fa6c913e4..3f59db768d54a9dcb3c1cada8cf4f20572f8c982 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 @@ -36,7 +36,7 @@ import de.hft.stuttgart.citydoctor2.math.Vector3d; */ public class Primitive { - private static Logger logger = LogManager.getLogger(Primitive.class); + private static final Logger logger = LogManager.getLogger(Primitive.class); private static final double AREA_EPSILON = 0.00001; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/tesselation/TesselatedPolygon.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/tesselation/TesselatedPolygon.java index 09bfc77abcd7c9b99dd61f91f2c6fb947ee469ca..f150a08eb160da51b60c5b16827cd6a3d10e7683 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/tesselation/TesselatedPolygon.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/tesselation/TesselatedPolygon.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.tesselation; +import java.io.Serial; import java.io.Serializable; import java.util.ArrayList; import java.util.List; @@ -35,10 +36,11 @@ import de.hft.stuttgart.citydoctor2.math.Vector3d; */ public class TesselatedPolygon implements Serializable { + @Serial private static final long serialVersionUID = 3117655580899570369L; - private List triangles; - private Polygon original; + private final List triangles; + private final Polygon original; public TesselatedPolygon(List triangles, Polygon original) { this.triangles = triangles; @@ -54,7 +56,7 @@ public class TesselatedPolygon implements Serializable { } triangles = new ArrayList<>(); for (int i = 0; i < indices.size(); i = i + 3) { - Vector3d v1 = vertices.get(indices.get(i + 0)); + Vector3d v1 = vertices.get(indices.get(i)); Vector3d v2 = vertices.get(indices.get(i + 1)); Vector3d v3 = vertices.get(indices.get(i + 2)); triangles.add(new Triangle3d(v1, v2, v3, this)); diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/tesselation/TesselatedRing.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/tesselation/TesselatedRing.java index 1bdc0d04cfb6d2c10e01fc697ec5893fa102f1e0..98e8d7c86fe0d0d7ec9a54a558c4a1a4f785e8bf 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/tesselation/TesselatedRing.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/tesselation/TesselatedRing.java @@ -34,8 +34,8 @@ import de.hft.stuttgart.citydoctor2.math.Vector3d; */ public class TesselatedRing { - private List triangles; - private LinearRing ring; + private final List triangles; + private final LinearRing ring; public TesselatedRing(List triangles, LinearRing ring) { this.ring = ring; @@ -48,7 +48,7 @@ public class TesselatedRing { } triangles = new ArrayList<>(); for (int i = 0; i < indices.size(); i = i + 3) { - Vector3d v1 = vertices.get(indices.get(i + 0)); + Vector3d v1 = vertices.get(indices.get(i)); Vector3d v2 = vertices.get(indices.get(i + 1)); Vector3d v3 = vertices.get(indices.get(i + 2)); triangles.add(new Triangle3d(v1, v2, v3)); diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/tesselation/TesselationException.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/tesselation/TesselationException.java index d479cea1625a8d90cd43745f72577f42235d9df5..e11cfb9f3a14c57c2d576cd968516733dedd20af 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/tesselation/TesselationException.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/tesselation/TesselationException.java @@ -18,6 +18,8 @@ */ package de.hft.stuttgart.citydoctor2.tesselation; +import java.io.Serial; + /** * Thrown when something went wrong with the tesselation process. * @@ -43,6 +45,7 @@ public class TesselationException extends RuntimeException { super(cause); } + @Serial private static final long serialVersionUID = -2010522579830781136L; public TesselationException(String message) { diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/Copy.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/Copy.java index 5880b76a90024965b878e04161d2ecb9b0d5ff71..390c3807b5119b8b174e3e31533a4622ae8941b2 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/Copy.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/Copy.java @@ -18,6 +18,10 @@ */ package de.hft.stuttgart.citydoctor2.utils; +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -26,6 +30,8 @@ import java.io.ObjectOutputStream; public class Copy { + private static final Logger logger = LogManager.getLogger(Copy.class); + private Copy() { } @@ -41,16 +47,11 @@ public class Copy { ByteArrayInputStream in = new ByteArrayInputStream(byteArray); ObjectInputStream ois = new ObjectInputStream(in); return (T) ois.readObject(); - } catch (IOException e) { - e.printStackTrace(); - } catch (ClassNotFoundException e) { - e.printStackTrace(); + } catch (IOException | ClassNotFoundException e) { + logger.log(Level.ERROR, e.getMessage(), e); } throw new IllegalStateException(); -// CopyHandler handler = new CopyHandler(); -// return handler.copy(original); - } } diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/CopyHandler.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/CopyHandler.java index 84743d0683649f4def08a0a829fc91929e4719d9..ae9943975ff1c06233805f7a90b8c87a390fb736 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/CopyHandler.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/CopyHandler.java @@ -29,8 +29,8 @@ import java.util.Set; public class CopyHandler { - private Set toBeDoneInstances = new HashSet<>(); - private Map finishedInstances = new IdentityHashMap<>(); + private final Set toBeDoneInstances = new HashSet<>(); + private final Map finishedInstances = new IdentityHashMap<>(); @SuppressWarnings("unchecked") public T copy(T original) { diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/Localization.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/Localization.java index 595b9ad998b411ac5c824524a346f9f63e42cded..f4486f44ad8cdeef0401a9855782a38e8b45856b 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/Localization.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/Localization.java @@ -30,7 +30,7 @@ public class Localization { public static final String VERSION = "CityDoctorValidation.Version"; - private static ResourceBundle bundle; + private static final ResourceBundle bundle; static { bundle = ResourceBundle.getBundle("CityDoctorLocalization"); diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/Pair.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/Pair.java index fd0a10178d78bce00685b7e01b4bd52b9193e9bd..1c50917f44e77db9ec9993a790520699873ac2dc 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/Pair.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/Pair.java @@ -28,8 +28,8 @@ package de.hft.stuttgart.citydoctor2.utils; */ public class Pair { - private A a; - private B b; + private final A a; + private final B b; public Pair(A a, B b) { this.a = a; @@ -78,14 +78,9 @@ public class Pair { return false; } if (b == null) { - if (other.b != null) { - return false; - } - } else if (!b.equals(other.b)) { - return false; - } - return true; - } + return other.b == null; + } else return b.equals(other.b); + } @Override public String toString() { 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 f603763a016930c389c6c6d4e65ad2a8fc0d993e..62f9b877aea4dd7857f0120beaba8c943b58d5db 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 @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.utils; +import java.io.Serial; import java.io.Serializable; import java.util.List; @@ -33,13 +34,14 @@ import de.hft.stuttgart.citydoctor2.math.Segment3d; */ public class PolygonIntersection implements Serializable { + @Serial private static final long serialVersionUID = -6301963226688351725L; public enum IntersectionType { NONE, LINE, POLYGON } - private IntersectionType type; + private final IntersectionType type; private List lines; private ConcretePolygon polygon; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/QualityADEUtils.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/QualityADEUtils.java index 8824b9fc7fa3e346baa14c7cfe3fc3ff5ded1145..65c669f7fad76d6b21aa12a362792ee5b48bcbf6 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/QualityADEUtils.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/QualityADEUtils.java @@ -85,54 +85,39 @@ public class QualityADEUtils { } public static de.hft.stuttgart.quality.model.enums.ErrorId mapErrorIdToAdeId(ErrorId key) { - switch (key.getIdString()) { - case "GE_R_NOT_CLOSED": - return de.hft.stuttgart.quality.model.enums.ErrorId.GE_R_NOT_CLOSED; - case "GE_R_TOO_FEW_POINTS": - return de.hft.stuttgart.quality.model.enums.ErrorId.GE_R_TOO_FEW_POINTS; - case "GE_R_CONSECUTIVE_POINTS_SAME": - return de.hft.stuttgart.quality.model.enums.ErrorId.GE_R_CONSECUTIVE_POINTS_SAME; - case "GE_R_SELF_INTERSECTION": - return de.hft.stuttgart.quality.model.enums.ErrorId.GE_R_SELF_INTERSECTION; - case "GE_P_NON_PLANAR_POLYGON_NORMALS_DEVIATION": - return de.hft.stuttgart.quality.model.enums.ErrorId.GE_P_NON_PLANAR_POLYGON_NORMALS_DEVIATION; - case "GE_P_NON_PLANAR_POLYGON_DISTANCE_PLANE": - return de.hft.stuttgart.quality.model.enums.ErrorId.GE_P_NON_PLANAR_POLYGON_DISTANCE_PLANE; - case "GE_P_INTERIOR_DISCONNECTED": - return de.hft.stuttgart.quality.model.enums.ErrorId.GE_P_INTERIOR_DISCONNECTED; - case "GE_P_INTERSECTING_RINGS": - return de.hft.stuttgart.quality.model.enums.ErrorId.GE_P_INTERSECTING_RINGS; - case "GE_P_HOLE_OUTSIDE": - return de.hft.stuttgart.quality.model.enums.ErrorId.GE_P_HOLE_OUTSIDE; - case "GE_P_ORIENTATION_RINGS_SAME": - return de.hft.stuttgart.quality.model.enums.ErrorId.GE_P_ORIENTATION_RINGS_SAME; - case "GE_P_INNER_RINGS_NESTED": - return de.hft.stuttgart.quality.model.enums.ErrorId.GE_P_INNER_RINGS_NESTED; - case "GE_S_TOO_FEW_POLYGONS": - return de.hft.stuttgart.quality.model.enums.ErrorId.GE_S_TOO_FEW_POLYGONS; - case "GE_S_NOT_CLOSED": - return de.hft.stuttgart.quality.model.enums.ErrorId.GE_S_NOT_CLOSED; - case "GE_S_NON_MANIFOLD_EDGE": - return de.hft.stuttgart.quality.model.enums.ErrorId.GE_S_NON_MANIFOLD_EDGE; - case "GE_S_POLYGON_WRONG_ORIENTATION": - return de.hft.stuttgart.quality.model.enums.ErrorId.GE_S_POLYGON_WRONG_ORIENTATION; - case "GE_S_ALL_POLYGONS_WRONG_ORIENTATION": - return de.hft.stuttgart.quality.model.enums.ErrorId.GE_S_ALL_POLYGONS_WRONG_ORIENTATION; - case "GE_S_NON_MANIFOLD_VERTEX": - return de.hft.stuttgart.quality.model.enums.ErrorId.GE_S_NON_MANIFOLD_VERTEX; - case "GE_S_SELF_INTERSECTION": - return de.hft.stuttgart.quality.model.enums.ErrorId.GE_S_SELF_INTERSECTION; - case "GE_S_MULTIPLE_CONNECTED_COMPONENTS": - return de.hft.stuttgart.quality.model.enums.ErrorId.GE_S_MULTIPLE_CONNECTED_COMPONENTS; - case "SE_ATTRIBUTE_WRONG_VALUE": - return de.hft.stuttgart.quality.model.enums.ErrorId.SE_ATTRIBUTE_WRONG_VALUE; - case "SE_ATTRIBUTE_MISSING": - return de.hft.stuttgart.quality.model.enums.ErrorId.SE_ATTRIBUTE_MISSING; - case "SE_ATTRIBUTE_INVALID": - return de.hft.stuttgart.quality.model.enums.ErrorId.SE_ATTRIBUTE_INVALID; - default: - return null; - } + return switch (key.getIdString()) { + case "GE_R_NOT_CLOSED" -> de.hft.stuttgart.quality.model.enums.ErrorId.GE_R_NOT_CLOSED; + case "GE_R_TOO_FEW_POINTS" -> de.hft.stuttgart.quality.model.enums.ErrorId.GE_R_TOO_FEW_POINTS; + case "GE_R_CONSECUTIVE_POINTS_SAME" -> + de.hft.stuttgart.quality.model.enums.ErrorId.GE_R_CONSECUTIVE_POINTS_SAME; + case "GE_R_SELF_INTERSECTION" -> de.hft.stuttgart.quality.model.enums.ErrorId.GE_R_SELF_INTERSECTION; + case "GE_P_NON_PLANAR_POLYGON_NORMALS_DEVIATION" -> + de.hft.stuttgart.quality.model.enums.ErrorId.GE_P_NON_PLANAR_POLYGON_NORMALS_DEVIATION; + case "GE_P_NON_PLANAR_POLYGON_DISTANCE_PLANE" -> + de.hft.stuttgart.quality.model.enums.ErrorId.GE_P_NON_PLANAR_POLYGON_DISTANCE_PLANE; + case "GE_P_INTERIOR_DISCONNECTED" -> + de.hft.stuttgart.quality.model.enums.ErrorId.GE_P_INTERIOR_DISCONNECTED; + case "GE_P_INTERSECTING_RINGS" -> de.hft.stuttgart.quality.model.enums.ErrorId.GE_P_INTERSECTING_RINGS; + case "GE_P_HOLE_OUTSIDE" -> de.hft.stuttgart.quality.model.enums.ErrorId.GE_P_HOLE_OUTSIDE; + case "GE_P_ORIENTATION_RINGS_SAME" -> + de.hft.stuttgart.quality.model.enums.ErrorId.GE_P_ORIENTATION_RINGS_SAME; + case "GE_P_INNER_RINGS_NESTED" -> de.hft.stuttgart.quality.model.enums.ErrorId.GE_P_INNER_RINGS_NESTED; + case "GE_S_TOO_FEW_POLYGONS" -> de.hft.stuttgart.quality.model.enums.ErrorId.GE_S_TOO_FEW_POLYGONS; + case "GE_S_NOT_CLOSED" -> de.hft.stuttgart.quality.model.enums.ErrorId.GE_S_NOT_CLOSED; + case "GE_S_NON_MANIFOLD_EDGE" -> de.hft.stuttgart.quality.model.enums.ErrorId.GE_S_NON_MANIFOLD_EDGE; + case "GE_S_POLYGON_WRONG_ORIENTATION" -> + de.hft.stuttgart.quality.model.enums.ErrorId.GE_S_POLYGON_WRONG_ORIENTATION; + case "GE_S_ALL_POLYGONS_WRONG_ORIENTATION" -> + de.hft.stuttgart.quality.model.enums.ErrorId.GE_S_ALL_POLYGONS_WRONG_ORIENTATION; + case "GE_S_NON_MANIFOLD_VERTEX" -> de.hft.stuttgart.quality.model.enums.ErrorId.GE_S_NON_MANIFOLD_VERTEX; + case "GE_S_SELF_INTERSECTION" -> de.hft.stuttgart.quality.model.enums.ErrorId.GE_S_SELF_INTERSECTION; + case "GE_S_MULTIPLE_CONNECTED_COMPONENTS" -> + de.hft.stuttgart.quality.model.enums.ErrorId.GE_S_MULTIPLE_CONNECTED_COMPONENTS; + case "SE_ATTRIBUTE_WRONG_VALUE" -> de.hft.stuttgart.quality.model.enums.ErrorId.SE_ATTRIBUTE_WRONG_VALUE; + case "SE_ATTRIBUTE_MISSING" -> de.hft.stuttgart.quality.model.enums.ErrorId.SE_ATTRIBUTE_MISSING; + case "SE_ATTRIBUTE_INVALID" -> de.hft.stuttgart.quality.model.enums.ErrorId.SE_ATTRIBUTE_INVALID; + default -> null; + }; } } diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/SerializablePair.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/SerializablePair.java index 01c315bf2e9df6a19e767530668ab8467701941d..b9d970bfd2889cc2c01bf4175372ff369bc2223f 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/SerializablePair.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/SerializablePair.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.utils; +import java.io.Serial; import java.io.Serializable; /** @@ -30,10 +31,11 @@ import java.io.Serializable; */ public class SerializablePair implements Serializable { + @Serial private static final long serialVersionUID = -5307944001963352647L; - private A a; - private B b; + private final A a; + private final B b; public SerializablePair(A a, B b) { this.a = a; @@ -82,14 +84,9 @@ public class SerializablePair im return false; } if (b == null) { - if (other.b != null) { - return false; - } - } else if (!b.equals(other.b)) { - return false; - } - return true; - } + return other.b == null; + } else return b.equals(other.b); + } @Override public String toString() { diff --git a/CityDoctorParent/CityDoctorValidation/pom.xml b/CityDoctorParent/CityDoctorValidation/pom.xml index 4acf6a4554612a563e0de5352ef7b0a1734c2c71..c646cbfd940a137923cfc5c297b1575cbed434bf 100644 --- a/CityDoctorParent/CityDoctorValidation/pom.xml +++ b/CityDoctorParent/CityDoctorValidation/pom.xml @@ -1,6 +1,5 @@ - - 4.0.0 + 4.0.0 de.hft.stuttgart CityDoctorParent @@ -65,7 +64,11 @@ net.sf.saxon Saxon-HE - + + org.yaml + snakeyaml + + diff --git a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/Checker.java b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/Checker.java index 99c30d82e0acc13d3e1eeb75e6bd832a99dcd382..2e33ed82d319293fbc67ffcd3472e71b41311d33 100644 --- a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/Checker.java +++ b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/Checker.java @@ -43,7 +43,6 @@ import javax.xml.transform.Source; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; -import javax.xml.transform.URIResolver; import javax.xml.transform.dom.DOMResult; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.sax.SAXResult; @@ -105,8 +104,8 @@ public class Checker { private List includeFilters; private List excludeFilters; - private Checks checkConfig; - private CityDoctorModel model; + private final Checks checkConfig; + private final CityDoctorModel model; public Checker(CityDoctorModel model) { this(ValidationConfiguration.loadStandardValidationConfig(), model); @@ -131,7 +130,6 @@ public class Checker { * given or this checker has not validated anything, nothing is done. * * @param xmlOutput the output file location for the XML report. Can be null. - * @param model the model for which the report is written. */ public void writeXmlReport(String xmlOutput) { if (!model.isValidated() || xmlOutput == null) { @@ -316,8 +314,7 @@ public class Checker { handleInputFilter(filter); if (excludeFilters != null) { for (Filter f : excludeFilters) { - if (f instanceof TypeFilter) { - TypeFilter tf = (TypeFilter) f; + if (f instanceof TypeFilter tf) { FeatureType type = tf.getType(); TopLevelFeatureType tlft = mapToTopLevelFeatureType(type); if (tlft == null) { @@ -392,22 +389,15 @@ public class Checker { } private TopLevelFeatureType mapToTopLevelFeatureType(FeatureType type) { - switch (type) { - case BRIDGE: - return TopLevelFeatureType.BRIDGE; - case BUILDING: - return TopLevelFeatureType.BUILDING; - case LAND: - return TopLevelFeatureType.LAND; - case TRANSPORTATION: - return TopLevelFeatureType.TRANSPORTATION; - case VEGETATION: - return TopLevelFeatureType.VEGETATION; - case WATER: - return TopLevelFeatureType.WATER; - default: - return null; - } + return switch (type) { + case BRIDGE -> TopLevelFeatureType.BRIDGE; + case BUILDING -> TopLevelFeatureType.BUILDING; + case LAND -> TopLevelFeatureType.LAND; + case TRANSPORTATION -> TopLevelFeatureType.TRANSPORTATION; + case VEGETATION -> TopLevelFeatureType.VEGETATION; + case WATER -> TopLevelFeatureType.WATER; + default -> null; + }; } private RequirementId mapToRequirement(String requirementName) { @@ -445,13 +435,7 @@ public class Checker { transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); transformerFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); - transformerFactory.setURIResolver(new URIResolver() { - - @Override - public Source resolve(String href, String base) throws TransformerException { - return new StreamSource(Checker.class.getResourceAsStream(href)); - } - }); + transformerFactory.setURIResolver((href, base) -> new StreamSource(Checker.class.getResourceAsStream(href))); Source dsdlXslSource = new StreamSource(Checker.class.getResourceAsStream("iso_dsdl_include.xsl")); Transformer dsdlXslTransformer = transformerFactory.newTransformer(dsdlXslSource); @@ -706,14 +690,14 @@ public class Checker { if (logger.isDebugEnabled()) { logger.debug(Localization.getText("Checker.checkFeature"), co); } - for (int i = 0; i < execLayers.size(); i++) { - for (Check check : execLayers.get(i)) { - if (logger.isTraceEnabled()) { - logger.trace(Localization.getText("Checker.executeCheck"), check.getCheckId()); - } - co.accept(check); - } - } + for (List execLayer : execLayers) { + for (Check check : execLayer) { + if (logger.isTraceEnabled()) { + logger.trace(Localization.getText("Checker.executeCheck"), check.getCheckId()); + } + co.accept(check); + } + } } public static List> buildExecutionLayers(List checks) { diff --git a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/EqualsIgnoreCaseFilter.java b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/EqualsIgnoreCaseFilter.java index 53287178ac9326f693b078a83e53c89b0ad56fd4..4e05bc352aa07d1c7b228304d3a6d8d117a84294 100644 --- a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/EqualsIgnoreCaseFilter.java +++ b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/EqualsIgnoreCaseFilter.java @@ -30,7 +30,7 @@ import de.hft.stuttgart.citydoctor2.datastructure.CityObject; */ public class EqualsIgnoreCaseFilter implements Filter { - private String id; + private final String id; public EqualsIgnoreCaseFilter(String id) { Objects.requireNonNull(id); diff --git a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/ExcludeFilterConfiguration.java b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/ExcludeFilterConfiguration.java index 4f4dd363511397d0aac6190215254b4e4fcf9d25..f1fdae9177337c64c2955bff647507282609d541 100644 --- a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/ExcludeFilterConfiguration.java +++ b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/ExcludeFilterConfiguration.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.check; +import java.io.Serial; import java.io.Serializable; import java.util.ArrayList; import java.util.List; @@ -26,6 +27,7 @@ import de.hft.stuttgart.citydoctor2.datastructure.FeatureType; public class ExcludeFilterConfiguration implements Serializable { + @Serial private static final long serialVersionUID = 5308380997654048837L; private List types; diff --git a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/Filter.java b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/Filter.java index b62078c76cf39a32e50701e0bd43680e8443f94b..52fa62d363d8b0837cd525f3c89f12782d63a7bf 100644 --- a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/Filter.java +++ b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/Filter.java @@ -27,6 +27,7 @@ import de.hft.stuttgart.citydoctor2.datastructure.CityObject; * @author Matthias Betz * */ +@FunctionalInterface public interface Filter { /** diff --git a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/FilterConfiguration.java b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/FilterConfiguration.java index 090199e8bfc1950a3800f1264fe1026363eb94b7..d46c73547db1cf7e7811d95724d0b3dbc513ef1b 100644 --- a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/FilterConfiguration.java +++ b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/FilterConfiguration.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.check; +import java.io.Serial; import java.io.Serializable; /** @@ -29,6 +30,7 @@ import java.io.Serializable; */ public class FilterConfiguration implements Serializable { + @Serial private static final long serialVersionUID = 3344890310114546998L; private ExcludeFilterConfiguration exclude; diff --git a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/IncludeFilterConfiguration.java b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/IncludeFilterConfiguration.java index 7506645eb36538d346640ba2d941fb75ed1d5c84..762c27c49749fec48fee21689f92ff83b258f78b 100644 --- a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/IncludeFilterConfiguration.java +++ b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/IncludeFilterConfiguration.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.check; +import java.io.Serial; import java.io.Serializable; import java.util.ArrayList; import java.util.List; @@ -34,6 +35,7 @@ import de.hft.stuttgart.citydoctor2.datastructure.FeatureType; */ public class IncludeFilterConfiguration implements Serializable { + @Serial private static final long serialVersionUID = 1840264505629236113L; private List types; diff --git a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/PatternFilter.java b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/PatternFilter.java index 78c60173e74578e673de8aac222ff082e5d96673..b8025ebf36bacfd45c673de835cb8eccfa08bfa0 100644 --- a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/PatternFilter.java +++ b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/PatternFilter.java @@ -24,7 +24,7 @@ import de.hft.stuttgart.citydoctor2.datastructure.CityObject; public class PatternFilter implements Filter { - private Pattern pattern; + private final Pattern pattern; public PatternFilter(String patternString) { pattern = Pattern.compile(patternString); diff --git a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/RequirementConfiguration.java b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/RequirementConfiguration.java index 696bfc666c16f9d88912f98da0edd3510d378161..4815af947814595bfb09d4235c3cd6f15542fc86 100644 --- a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/RequirementConfiguration.java +++ b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/RequirementConfiguration.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.check; +import java.io.Serial; import java.io.Serializable; import java.util.HashMap; import java.util.Map; @@ -31,6 +32,7 @@ import java.util.Map; */ public class RequirementConfiguration implements Serializable { + @Serial private static final long serialVersionUID = -1258195428669813888L; private boolean enabled; diff --git a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/StreamCityGmlConsumer.java b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/StreamCityGmlConsumer.java index aa7fb99465f5e0ab886cbf3cf1fe67e52e9e295a..2ebf44dfe45bbb947316a1c2b0465b145680d13b 100644 --- a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/StreamCityGmlConsumer.java +++ b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/StreamCityGmlConsumer.java @@ -63,22 +63,22 @@ public class StreamCityGmlConsumer implements CityGmlConsumer { private static final Logger logger = LogManager.getLogger(StreamCityGmlConsumer.class); - private Checker c; - private XmlStreamReporter xmlReporter; - private PdfStreamReporter pdfReporter; - private SvrlContentHandler handler; - private Map errorCount; - private GeometryFactory gmlFactory; - private ValidationConfiguration config; - private Statistics statistics; - private FeatureStatistics buildingStatistics; - private FeatureStatistics bridgeStatistics; - private FeatureStatistics transportationStatistics; - private FeatureStatistics vegetationStatistics; - private FeatureStatistics landStatistics; - private FeatureStatistics waterStatistics; - private Validation val; - private FeatureCheckedListener l; + private final Checker c; + private final XmlStreamReporter xmlReporter; + private final PdfStreamReporter pdfReporter; + private final SvrlContentHandler handler; + private final Map errorCount; + private final GeometryFactory gmlFactory; + private final ValidationConfiguration config; + private final Statistics statistics; + private final FeatureStatistics buildingStatistics; + private final FeatureStatistics bridgeStatistics; + private final FeatureStatistics transportationStatistics; + private final FeatureStatistics vegetationStatistics; + private final FeatureStatistics landStatistics; + private final FeatureStatistics waterStatistics; + private final Validation val; + private final FeatureCheckedListener l; public StreamCityGmlConsumer(Checker c, XmlStreamReporter xmlReporter, PdfStreamReporter pdfReporter, SvrlContentHandler handler, ValidationConfiguration config, FeatureCheckedListener l) { @@ -92,7 +92,7 @@ public class StreamCityGmlConsumer implements CityGmlConsumer { gmlFactory = GeometryFactory.newInstance(); val = new Validation(); - val.setId("CD" + UUID.randomUUID().toString()); + val.setId("CD" + UUID.randomUUID()); val.setValidationDate(ZonedDateTime.now()); val.setValidationSoftware("CityDoctor " + Localization.getText(Localization.VERSION)); statistics = new Statistics(); @@ -182,7 +182,7 @@ public class StreamCityGmlConsumer implements CityGmlConsumer { } val.setStatistics(new StatisticsProperty(statistics)); ValidationPlan validationPlan = c.createValidationPlan(); - validationPlan.setId("CD_PLAN_" + UUID.randomUUID().toString()); + validationPlan.setId("CD_PLAN_" + UUID.randomUUID()); cm.getFeatureMembers().add(new AbstractFeatureProperty(validationPlan)); val.setValidationPlan(new Reference(validationPlan)); diff --git a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/TypeFilter.java b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/TypeFilter.java index f0f2d531b26278976fa899e7c21629daf2396591..8cf2c364a2682e3a81c288da9193d448a206135a 100644 --- a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/TypeFilter.java +++ b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/TypeFilter.java @@ -21,27 +21,28 @@ package de.hft.stuttgart.citydoctor2.check; import de.hft.stuttgart.citydoctor2.datastructure.CityObject; import de.hft.stuttgart.citydoctor2.datastructure.FeatureType; + /** * Filters the feature type of features - * - * @author Matthias Betz * + * @author Matthias Betz */ public class TypeFilter implements Filter { - private FeatureType type; + private final FeatureType type; + + public TypeFilter(FeatureType type) { + this.type = type; + } + + @Override + public boolean matches(CityObject co) { + return co.getFeatureType() == type; + } - public TypeFilter(FeatureType type) { - this.type = type; - } - public FeatureType getType() { return type; } - @Override - public boolean matches(CityObject co) { - return co.getFeatureType() == type; - } } diff --git a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/ValidationConfiguration.java b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/ValidationConfiguration.java index 68b0f47134501d03d0515d55c21ca956d5493ad1..dec4e67068556520fc746b0919a1c2610ab61e4e 100644 --- a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/ValidationConfiguration.java +++ b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/ValidationConfiguration.java @@ -18,14 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.check; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStream; -import java.io.Serializable; +import java.io.*; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; @@ -33,6 +26,7 @@ import java.util.Map.Entry; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.LoaderOptions; import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.constructor.Constructor; import org.yaml.snakeyaml.nodes.Tag; @@ -55,6 +49,7 @@ public class ValidationConfiguration implements Serializable { public static final String CHECK_FOR_SOLID_XML = "checkForSolid.xml"; private static final String NUMBER_OF_ROUNDING_PLACES_DEFAULT = "8"; private static final String MIN_VERTEX_DISTANCE_DEFAULT = "0.0001"; + @Serial private static final long serialVersionUID = -8020055032177740646L; private static final Logger logger = LogManager.getLogger(ValidationConfiguration.class); @@ -72,7 +67,7 @@ public class ValidationConfiguration implements Serializable { } public static ValidationConfiguration loadValidationConfig(InputStream stream) { - Yaml yaml = new Yaml(new Constructor(ValidationConfiguration.class)); + Yaml yaml = new Yaml(new Constructor(ValidationConfiguration.class, new LoaderOptions())); ValidationConfiguration config = yaml.load(stream); config.validateConfiguration(); return config; @@ -104,9 +99,9 @@ public class ValidationConfiguration implements Serializable { DumperOptions options = new DumperOptions(); options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); options.setPrettyFlow(true); - Representer rep = new ValidationConfigurationRepresenter(); + Representer rep = new ValidationConfigurationRepresenter(options); rep.addClassTag(ValidationConfiguration.class, Tag.MAP); - Yaml yaml = new Yaml(rep, options); + Yaml yaml = new Yaml(rep); try (BufferedWriter bw = new BufferedWriter(new FileWriter(f))) { yaml.dump(this, bw); } @@ -178,9 +173,9 @@ public class ValidationConfiguration implements Serializable { return cConfig; }); } - globalParameters.computeIfAbsent(GlobalParameters.MIN_VERTEX_DISTANCE, k -> MIN_VERTEX_DISTANCE_DEFAULT); - globalParameters.computeIfAbsent(GlobalParameters.NUMBER_OF_ROUNDING_PLACES, - k -> NUMBER_OF_ROUNDING_PLACES_DEFAULT); + globalParameters.putIfAbsent(GlobalParameters.MIN_VERTEX_DISTANCE, MIN_VERTEX_DISTANCE_DEFAULT); + globalParameters.putIfAbsent(GlobalParameters.NUMBER_OF_ROUNDING_PLACES, + NUMBER_OF_ROUNDING_PLACES_DEFAULT); } public int getNumberOfRoundingPlaces() { diff --git a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/ValidationConfigurationRepresenter.java b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/ValidationConfigurationRepresenter.java index 3d05e856251b37edb5ee742f236545e89e881918..2dff997c8a74afa5249d40eb558f42929047b9b2 100644 --- a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/ValidationConfigurationRepresenter.java +++ b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/ValidationConfigurationRepresenter.java @@ -18,6 +18,7 @@ */ package de.hft.stuttgart.citydoctor2.check; +import org.yaml.snakeyaml.DumperOptions; import org.yaml.snakeyaml.introspector.Property; import org.yaml.snakeyaml.nodes.CollectionNode; import org.yaml.snakeyaml.nodes.MappingNode; @@ -35,7 +36,11 @@ import org.yaml.snakeyaml.representer.Representer; * */ public class ValidationConfigurationRepresenter extends Representer { - + + public ValidationConfigurationRepresenter(DumperOptions options) { + super(options); + } + @Override protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) { diff --git a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/CheckPrototype.java b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/CheckPrototype.java index 452990549743529330ed19ed1fffb8a4338ea4b3..c397d127edaec27cc8a563547e4ab51f5115ea08 100644 --- a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/CheckPrototype.java +++ b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/CheckPrototype.java @@ -38,7 +38,7 @@ import de.hft.stuttgart.citydoctor2.check.RequirementType; */ public class CheckPrototype { - private Check c; + private final Check c; public CheckPrototype(Check c) { this.c = c; diff --git a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/Checks.java b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/Checks.java index aa9ce41d27dedf7c13283001b25a0fceb639592c..65db44d653cf5de2de802960d175a2a30073587b 100644 --- a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/Checks.java +++ b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/Checks.java @@ -69,12 +69,12 @@ public class Checks { private static final Logger logger = LogManager.getLogger(Checks.class); - private static List checkPrototypes; - private static Map prototypeMap; + private static final List checkPrototypes; + private static final Map prototypeMap; private static Map availableRequirements; - private Map checkMap; + private final Map checkMap; static { checkPrototypes = new ArrayList<>(); diff --git a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/SvrlContentHandler.java b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/SvrlContentHandler.java index 5995b28bba8d8f89181799b17c5c3c3d4208ca6a..f4d88c2f544ade9917c1fc7abfd2649a4bf292f0 100644 --- a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/SvrlContentHandler.java +++ b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/SvrlContentHandler.java @@ -45,8 +45,8 @@ public class SvrlContentHandler implements ContentHandler { private StringBuilder buffer; - private Map> featureErrors; - private List generalErrors; + private final Map> featureErrors; + private final List generalErrors; public SvrlContentHandler() { featureErrors = new HashMap<>(); @@ -65,22 +65,23 @@ public class SvrlContentHandler implements ContentHandler { public void setDocumentLocator(Locator locator) { // not needed } - + @SuppressWarnings("RedundantThrows") @Override public void startDocument() throws SAXException { // not needed } - @Override + @SuppressWarnings("RedundantThrows") + @Override public void endDocument() throws SAXException { // not needed } - + @SuppressWarnings("RedundantThrows") @Override public void startPrefixMapping(String prefix, String uri) throws SAXException { // not needed } - + @SuppressWarnings("RedundantThrows") @Override public void endPrefixMapping(String prefix) throws SAXException { // not needed @@ -132,17 +133,17 @@ public class SvrlContentHandler implements ContentHandler { buffer.append(ch, start, length); } } - + @SuppressWarnings("RedundantThrows") @Override public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException { // not needed } - + @SuppressWarnings("RedundantThrows") @Override public void processingInstruction(String target, String data) throws SAXException { // not needed } - + @SuppressWarnings("RedundantThrows") @Override public void skippedEntity(String name) throws SAXException { // not needed diff --git a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/geometry/RingSelfIntCheck.java b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/geometry/RingSelfIntCheck.java index 560e7d549aa62568d99a31934f56c41825fe8577..1788939047f0539f857a7755e4bf1bafaa575cbc 100644 --- a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/geometry/RingSelfIntCheck.java +++ b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/geometry/RingSelfIntCheck.java @@ -124,9 +124,9 @@ public class RingSelfIntCheck extends Check { Segment3d s1 = new Segment3d(e1.getFrom(), e1.getTo()); Segment3d s2 = new Segment3d(e2.getFrom(), e2.getTo()); DistanceResult dr = s1.getDistanceResult(s2); - if (dr.getDistance() < epsilon) { + if (dr.distance() < epsilon) { // intersection - CheckError err = new RingEdgeIntersectionError(lr, e1, e2, dr.getPoint1()); + CheckError err = new RingEdgeIntersectionError(lr, e1, e2, dr.point1()); CheckResult cr = new CheckResult(this, ResultStatus.ERROR, err); lr.addCheckResult(cr); return; 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..e8ecafd80579e0e3fa4dfe17fdd1538ef8028b9b 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 @@ -34,12 +34,9 @@ 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 diff --git a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/util/FeatureCheckedListener.java b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/util/FeatureCheckedListener.java index 3f66dbdb1e3fd318eae97fc7050da0487451f510..8c46a86393c891ea5477c7040e666db97f82ebb3 100644 --- a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/util/FeatureCheckedListener.java +++ b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/util/FeatureCheckedListener.java @@ -26,6 +26,7 @@ import de.hft.stuttgart.citydoctor2.datastructure.CityObject; * @author Matthias Betz * */ +@FunctionalInterface public interface FeatureCheckedListener { public void featureChecked(CityObject co); 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 30369f82f16859ac97c90ecc688e45edda123f0d..a68b0b4b5fc5b8926cb52ca9064aa47d0a14880f 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 @@ -78,7 +78,7 @@ public class SelfIntersectionUtil { private static final Logger logger = LogManager.getLogger(SelfIntersectionUtil.class); - private static GeometryFactory factory = new GeometryFactory(new PrecisionModel(PrecisionModel.FLOATING)); + private static final GeometryFactory factory = new GeometryFactory(new PrecisionModel(PrecisionModel.FLOATING)); private SelfIntersectionUtil() { @@ -93,7 +93,7 @@ public class SelfIntersectionUtil { List intersections = new ArrayList<>(); MeshSurface meshSurface = MeshSurface.of(g); Map edgePolyMap = new IdentityHashMap<>(); - for (EdgePolygon poly : meshSurface.getPolygons()) { + for (EdgePolygon poly : meshSurface.polygons()) { edgePolyMap.put(poly.getOriginal(), poly); } for (int i = 0; i < polygons.size() - 1; i++) { @@ -213,12 +213,10 @@ public class SelfIntersectionUtil { // intersection is only an edge, not a polygon // edge intersections are allowed return PolygonIntersection.none(); - } else if (intersection instanceof GeometryCollection) { - GeometryCollection col = (GeometryCollection) intersection; + } else if (intersection instanceof GeometryCollection col) { for (int i = 0; i < col.getNumGeometries(); i++) { org.locationtech.jts.geom.Geometry interGeom = col.getGeometryN(i); - if (interGeom instanceof org.locationtech.jts.geom.Polygon) { - org.locationtech.jts.geom.Polygon intPoly = (org.locationtech.jts.geom.Polygon) interGeom; + if (interGeom instanceof org.locationtech.jts.geom.Polygon intPoly) { ConcretePolygon poly = convertToPolygon(plane1, projectionAxis, intPoly); return PolygonIntersection.polygon(poly, p1.getOriginal(), p2.getOriginal()); } @@ -226,8 +224,7 @@ public class SelfIntersectionUtil { // no polygon in collection, so no intersection return PolygonIntersection.none(); } - if (intersection instanceof org.locationtech.jts.geom.Polygon) { - org.locationtech.jts.geom.Polygon intPoly = (org.locationtech.jts.geom.Polygon) intersection; + if (intersection instanceof org.locationtech.jts.geom.Polygon intPoly) { ConcretePolygon poly = convertToPolygon(plane1, projectionAxis, intPoly); return PolygonIntersection.polygon(poly, p1.getOriginal(), p2.getOriginal()); } else { @@ -412,7 +409,7 @@ public class SelfIntersectionUtil { Triangle3d t2 = p2.getTriangles().get(p2Index); if (t1.doesIntersect(t2)) { logger.trace("{} intersects {}", t1, t2); - logger.trace("{} intersects {}", t1.getPartOf().getOriginal().getGmlId(), + logger.trace("GML-ID: {} intersects {}", t1.getPartOf().getOriginal().getGmlId(), t2.getPartOf().getOriginal().getGmlId()); return new GeometrySelfIntersection(t1.getPartOf().getOriginal(), t2.getPartOf().getOriginal(), t1, t2); diff --git a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/parameter/ArgumentParser.java b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/parameter/ArgumentParser.java index d8d3b03b70fb8fc76da017121cafea24abfd4507..80bdfd3c815e3793f35de1e845c8d0c6e1cc0f89 100644 --- a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/parameter/ArgumentParser.java +++ b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/parameter/ArgumentParser.java @@ -52,22 +52,20 @@ public class ArgumentParser { HashMap> params = new HashMap<>(); List options = null; - for (int i = 0; i < args.length; i++) { - final String a = args[i]; - - if (a.charAt(0) == '-') { - if (a.length() < 2) { - ErrorHandler.printHelpAndTerminate("Error while parsing argument " + a); - } - String flag = a.substring(1).toLowerCase(); - options = new ArrayList<>(); - params.put(flag, options); - } else if (options != null) { - options.add(a); - } else { - ErrorHandler.printHelpAndTerminate("Illegal parameter usage at " + a); - } - } + for (final String a : args) { + if (a.charAt(0) == '-') { + if (a.length() < 2) { + ErrorHandler.printHelpAndTerminate("Error while parsing argument " + a); + } + String flag = a.substring(1).toLowerCase(); + options = new ArrayList<>(); + params.put(flag, options); + } else if (options != null) { + options.add(a); + } else { + ErrorHandler.printHelpAndTerminate("Illegal parameter usage at " + a); + } + } return params; } diff --git a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/reporting/ErrorStatisticsCollector.java b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/reporting/ErrorStatisticsCollector.java index 33b2d9922672ab835885b044ec2abcda347aa128..c4e7a731f7d7969845bd77ff4dd2bff1f1fa9d35 100644 --- a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/reporting/ErrorStatisticsCollector.java +++ b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/reporting/ErrorStatisticsCollector.java @@ -31,7 +31,7 @@ import java.util.concurrent.atomic.AtomicInteger; */ public class ErrorStatisticsCollector { - private Map errorCounts = new HashMap<>(); + private final Map errorCounts = new HashMap<>(); public void addError(String errorName) { AtomicInteger numErrors = errorCounts.get(errorName); diff --git a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/reporting/XmlStreamErrorHandler.java b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/reporting/XmlStreamErrorHandler.java index d30c786954255be2fa7e0fada82570d80b239996..e6e3d4431a206e125a12e61ad057c831e4f18790 100644 --- a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/reporting/XmlStreamErrorHandler.java +++ b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/reporting/XmlStreamErrorHandler.java @@ -56,8 +56,8 @@ import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration; */ public class XmlStreamErrorHandler implements ErrorReport { - private ErrorDetails details; - private BasicCoordinateTransform originalTransform; + private final ErrorDetails details; + private final BasicCoordinateTransform originalTransform; public XmlStreamErrorHandler(ParserConfiguration config) { originalTransform = config.getOriginalTransform(); diff --git a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/reporting/XmlStreamReporter.java b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/reporting/XmlStreamReporter.java index 82fd142d918a562eaff3411d8515fcae3b1be014..20cb31e5a7754a27a34e9d352b56b69e95b08f4b 100644 --- a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/reporting/XmlStreamReporter.java +++ b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/reporting/XmlStreamReporter.java @@ -74,11 +74,11 @@ public class XmlStreamReporter implements StreamReporter { private static final Logger logger = LogManager.getLogger(XmlStreamReporter.class); - private OutputStream output; + private final OutputStream output; - private CheckReport report; - private Map reportMap; - private ValidationConfiguration config; + private final CheckReport report; + private final Map reportMap; + private final ValidationConfiguration config; public XmlStreamReporter(OutputStream output, String fileName, ValidationConfiguration config) { this.output = output; @@ -141,18 +141,18 @@ public class XmlStreamReporter implements StreamReporter { @Override public void report(CityObject co) { - if (co instanceof Building) { - reportBuilding((Building) co); - } else if (co instanceof Vegetation) { - reportVegetation((Vegetation) co); - } else if (co instanceof TransportationObject) { - reportTrans((TransportationObject) co); - } else if (co instanceof BridgeObject) { - reportBridge((BridgeObject) co); - } else if (co instanceof WaterObject) { - reportWater((WaterObject) co); - } else if (co instanceof LandObject) { - reportLand((LandObject) co); + if (co instanceof Building bu) { + reportBuilding(bu); + } else if (co instanceof Vegetation ve) { + reportVegetation(ve); + } else if (co instanceof TransportationObject to) { + reportTrans(to); + } else if (co instanceof BridgeObject bo) { + reportBridge(bo); + } else if (co instanceof WaterObject wo) { + reportWater(wo); + } else if (co instanceof LandObject lo) { + reportLand(lo); } else { throw new IllegalStateException("Not reportable CityObject found: " + co.getClass().getSimpleName()); } @@ -240,26 +240,10 @@ public class XmlStreamReporter implements StreamReporter { @Override public void finishReport() throws CheckReportWriteException { GlobalStatistics stats = new GlobalStatistics(); - GlobalErrorStatistics globErrStats = new GlobalErrorStatistics(); - globErrStats - .setNumErrorBridgeObjects(getNumberOfErrorFeatures(report.getValidationResults().getBridgeReports())); - globErrStats.setNumErrorBuildings(getNumberOfErrorFeatures(report.getValidationResults().getBuildingReports())); - globErrStats.setNumErrorLandObjects(getNumberOfErrorFeatures(report.getValidationResults().getLandReports())); - globErrStats.setNumErrorTransportation( - getNumberOfErrorFeatures(report.getValidationResults().getTransportationReports())); - globErrStats - .setNumErrorVegetation(getNumberOfErrorFeatures(report.getValidationResults().getVegetationReports())); - globErrStats.setNumErrorWaterObjects(getNumberOfErrorFeatures(report.getValidationResults().getWaterReports())); - stats.setGlobalErrorStats(globErrStats); - ModelStatistics modelStats = new ModelStatistics(); - modelStats.setNumBridgeObjects(report.getValidationResults().getBridgeReports().size()); - modelStats.setNumBuildings(report.getValidationResults().getBuildingReports().size()); - modelStats.setNumLandObjects(report.getValidationResults().getLandReports().size()); - modelStats.setNumTransportation(report.getValidationResults().getTransportationReports().size()); - modelStats.setNumVegetation(report.getValidationResults().getVegetationReports().size()); - modelStats.setNumWaterObjects(report.getValidationResults().getWaterReports().size()); - stats.setModelStats(modelStats); + stats.setGlobalErrorStats(getReportGlobalErrorStatistics()); + + stats.setModelStats(getReportModelStatistics()); ErrorStatisticsCollector globalErrorCount = new ErrorStatisticsCollector(); @@ -279,6 +263,31 @@ public class XmlStreamReporter implements StreamReporter { report.saveAs(output); } + private ModelStatistics getReportModelStatistics() { + ModelStatistics modelStats = new ModelStatistics(); + modelStats.setNumBridgeObjects(report.getValidationResults().getBridgeReports().size()); + modelStats.setNumBuildings(report.getValidationResults().getBuildingReports().size()); + modelStats.setNumLandObjects(report.getValidationResults().getLandReports().size()); + modelStats.setNumTransportation(report.getValidationResults().getTransportationReports().size()); + modelStats.setNumVegetation(report.getValidationResults().getVegetationReports().size()); + modelStats.setNumWaterObjects(report.getValidationResults().getWaterReports().size()); + return modelStats; + } + + private GlobalErrorStatistics getReportGlobalErrorStatistics() { + GlobalErrorStatistics globErrStats = new GlobalErrorStatistics(); + globErrStats + .setNumErrorBridgeObjects(getNumberOfErrorFeatures(report.getValidationResults().getBridgeReports())); + globErrStats.setNumErrorBuildings(getNumberOfErrorFeatures(report.getValidationResults().getBuildingReports())); + globErrStats.setNumErrorLandObjects(getNumberOfErrorFeatures(report.getValidationResults().getLandReports())); + globErrStats.setNumErrorTransportation( + getNumberOfErrorFeatures(report.getValidationResults().getTransportationReports())); + globErrStats + .setNumErrorVegetation(getNumberOfErrorFeatures(report.getValidationResults().getVegetationReports())); + globErrStats.setNumErrorWaterObjects(getNumberOfErrorFeatures(report.getValidationResults().getWaterReports())); + return globErrStats; + } + private void createStatistics(ErrorStatisticsCollector globalErrorCount, List reports) { for (FeatureReport fReport : reports) { if (fReport.getErrors().isEmpty()) { diff --git a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/reporting/pdf/CodeBlock.java b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/reporting/pdf/CodeBlock.java index 8624a127fa7097dbbdc1889568b2e97ee7a036be..f204f2b667f6720e23ff07e6bcdaf9f3b828b9ff 100644 --- a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/reporting/pdf/CodeBlock.java +++ b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/reporting/pdf/CodeBlock.java @@ -31,8 +31,8 @@ public class CodeBlock { private static final String BLOCK = "block"; - private Element codeBlockContainer; - private Element codeBlockElement; + private final Element codeBlockContainer; + private final Element codeBlockElement; private Element currentLine; diff --git a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/reporting/pdf/PdfErrorHandler.java b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/reporting/pdf/PdfErrorHandler.java index 41cf9b2223147fc8a81dba3b3f22b6870b2d79a9..655912a7296bbc8a6481f9634841482519be022d 100644 --- a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/reporting/pdf/PdfErrorHandler.java +++ b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/reporting/pdf/PdfErrorHandler.java @@ -48,8 +48,8 @@ public class PdfErrorHandler implements ErrorReport { private static final String ATTRIBUTE_KEY_COLOR = "#7F007F"; private static final String ATTRIBUTE_VALUE_COLOR = "#2A00FF"; - private Section section; - private ParserConfiguration config; + private final Section section; + private final ParserConfiguration config; public PdfErrorHandler(Section section, ParserConfiguration config) { this.config = config; diff --git a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/reporting/pdf/PdfStreamReporter.java b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/reporting/pdf/PdfStreamReporter.java index f1488ee77666a080064be70085b8ff32e1fd610e..f1f5374e7a0060b74c689fcd1806e0ae2f8dc389 100644 --- a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/reporting/pdf/PdfStreamReporter.java +++ b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/reporting/pdf/PdfStreamReporter.java @@ -72,14 +72,14 @@ public class PdfStreamReporter implements StreamReporter { private static final String WARNING_COLOR = "yellow"; private static final String OK_COLOR = "green"; - private PdfReport report; - private OutputStream outFile; + private final PdfReport report; + private final OutputStream outFile; - private Map errorStatistics; - private ValidationConfiguration config; + private final Map errorStatistics; + private final ValidationConfiguration config; - private Section statistics; - private Section vr; + private final Section statistics; + private final Section vr; private Section buildings; private int numErrorBuildings; @@ -107,7 +107,7 @@ public class PdfStreamReporter implements StreamReporter { private Section globalErrors; - private Map sectionMap = new HashMap<>(); + private final Map sectionMap = new HashMap<>(); public PdfStreamReporter(OutputStream pdfOutputFile, String fileName, ValidationConfiguration config) { this.config = config; @@ -393,21 +393,7 @@ public class PdfStreamReporter implements StreamReporter { @Override public void finishReport() throws CheckReportWriteException { if (buildings != null) { - for (Section s : buildings.getSubSections()) { - if (!s.hasErrors()) { - numOkBuildings++; - // building has no errors, no table - continue; - } - numErrorBuildings++; - Table t = new Table(2); - t.setTableColumnWidth(75, 25); - t.setTitle("Error", "Count"); - for (Entry e : s.getStats().getErrorCounts().entrySet()) { - t.addRow(e.getKey(), e.getValue().toString()); - } - s.addTable(1, t); - } + countFinishedReportBuildings(); } int numBuildings = numErrorBuildings + numOkBuildings; if (numBuildings > 0) { @@ -446,6 +432,24 @@ public class PdfStreamReporter implements StreamReporter { report.save(outFile); } + private void countFinishedReportBuildings() { + for (Section s : buildings.getSubSections()) { + if (!s.hasErrors()) { + numOkBuildings++; + // building has no errors, no table + continue; + } + numErrorBuildings++; + Table t = new Table(2); + t.setTableColumnWidth(75, 25); + t.setTitle("Error", "Count"); + for (Entry e : s.getStats().getErrorCounts().entrySet()) { + t.addRow(e.getKey(), e.getValue().toString()); + } + s.addTable(1, t); + } + } + @Override public void reportGlobalError(CheckError err) { AtomicInteger errorCount = errorStatistics.computeIfAbsent(err.getErrorId(), k -> new AtomicInteger(0)); diff --git a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/reporting/pdf/Section.java b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/reporting/pdf/Section.java index 9f39236fb4df5712441fc614e9bac92971f8076d..9c2e1ee2c3572aa399371ba571d82d1a3a732398 100644 --- a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/reporting/pdf/Section.java +++ b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/reporting/pdf/Section.java @@ -50,15 +50,15 @@ public class Section { private static final AtomicInteger S_COUNTER = new AtomicInteger(0); - private Element tocBlock; - private Element contentBlock; + private final Element tocBlock; + private final Element contentBlock; - private Element headlineBlock; + private final Element headlineBlock; private String linkId; private List
subSections; - private int depth; + private final int depth; // attributes for error reporting private ErrorStatisticsCollector stats; diff --git a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/reporting/pdf/Table.java b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/reporting/pdf/Table.java index faa2f72bbfbeda235c0c811cbf463d29e8366841..dd9d1e73b2ac716ed38ec4d165762957375c183c 100644 --- a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/reporting/pdf/Table.java +++ b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/reporting/pdf/Table.java @@ -30,13 +30,13 @@ public class Table { private static final String TABLE_HEADER_COLOR = "#58ACFA"; - private Element tableBlock; + private final Element tableBlock; - private Element tableHeader; - private Element tableBody; - private Element tableElement; + private final Element tableHeader; + private final Element tableBody; + private final Element tableElement; - private int columns; + private final int columns; public Table(int columns) { this.columns = columns; @@ -101,13 +101,13 @@ public class Table { private Element createTableRow(String... content) { Element tableRow = new Element("table-row", PdfReport.FO_NS); - for (int i = 0; i < content.length; i++) { - Element tableCell = new Element("table-cell", PdfReport.FO_NS); - tableRow.addContent(tableCell); - tableCell.addContent(PdfReport.createTextElement(content[i])); - tableCell.setAttribute("padding", "3pt 3pt 3pt 3pt"); - PdfReport.applySolidBorder(tableCell); - } + for (String s : content) { + Element tableCell = new Element("table-cell", PdfReport.FO_NS); + tableRow.addContent(tableCell); + tableCell.addContent(PdfReport.createTextElement(s)); + tableCell.setAttribute("padding", "3pt 3pt 3pt 3pt"); + PdfReport.applySolidBorder(tableCell); + } return tableRow; } diff --git a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/check/ValidationConfigurationTest.java b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/check/ValidationConfigurationTest.java index 514917ee88c546044c33f5f24a6a70d8e773fbaa..003dda319c5896eeb399a72558b5bd1aa74146a0 100644 --- a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/check/ValidationConfigurationTest.java +++ b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/check/ValidationConfigurationTest.java @@ -18,12 +18,6 @@ */ package de.hft.stuttgart.citydoctor2.check; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - import java.io.FileNotFoundException; import org.junit.Test; @@ -31,6 +25,13 @@ import org.junit.Test; import de.hft.stuttgart.citydoctor2.datastructure.FeatureType; import de.hft.stuttgart.quality.model.enums.RequirementId; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + public class ValidationConfigurationTest { @Test @@ -70,4 +71,21 @@ public class ValidationConfigurationTest { assertTrue(includeFilter.getTypes().contains(FeatureType.VEGETATION)); } + @Test + public void testVulnerableConfig() throws FileNotFoundException{ + String file = "src/test/resources/testConfigVulnerability.yml"; + ValidationConfiguration config = null; + try { + config = ValidationConfiguration.loadValidationConfig(file); + assertNotNull(config); + fail("Config with Vulnerability should not be successfully loaded"); + } catch (FileNotFoundException e){ + // Rethrow FNFE + throw e; + } catch (Exception e) { + // Bad config was not loaded + assertNull(config); + } + } + } diff --git a/CityDoctorParent/CityDoctorValidation/src/test/resources/testConfigVulnerability.yml b/CityDoctorParent/CityDoctorValidation/src/test/resources/testConfigVulnerability.yml new file mode 100644 index 0000000000000000000000000000000000000000..8d3f824efe1563bdfdb585d47420b21a93a9e2ca --- /dev/null +++ b/CityDoctorParent/CityDoctorValidation/src/test/resources/testConfigVulnerability.yml @@ -0,0 +1,3 @@ +globalParameters: !!globalTag + + diff --git a/CityDoctorParent/Extensions/CityDoctorAutoPro/CreateJNIHeader.bat b/CityDoctorParent/Extensions/CityDoctorAutoPro/CreateJNIHeader.bat new file mode 100644 index 0000000000000000000000000000000000000000..9a1151eb50e427749d97c0a6828a7881493d6789 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorAutoPro/CreateJNIHeader.bat @@ -0,0 +1,9 @@ +set CLASSPATH=.\target\classes;..\CityDoctorModel\target\classes;..\CityDoctorHealer\target\classes +set PATH="c:\Program Files (x86)\Java\jdk1.8.0_25\bin" +javah -jni de.hft.stuttgart.citydoctor2.connect.edge.AutoPro +javah -jni de.hft.stuttgart.citydoctor2.connect.edge.AutoProSettingsExport +javah -jni de.hft.stuttgart.citydoctor2.connect.edge.AutoProSettingsGeneral +javah -jni de.hft.stuttgart.citydoctor2.connect.edge.AutoProSettingsBool +javah -jni de.hft.stuttgart.citydoctor2.connect.edge.AutoProSettingsMerge +javah -jni de.hft.stuttgart.citydoctor2.connect.edge.AutoProSettingsAdvancedSweep +pause diff --git a/CityDoctorParent/Extensions/CityDoctorAutoPro/pom.xml b/CityDoctorParent/Extensions/CityDoctorAutoPro/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..bedcda1ba5969275ff5de40f0ebb2f3f7eec3e2b --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorAutoPro/pom.xml @@ -0,0 +1,55 @@ + + 4.0.0 + + de.hft.stuttgart + CityDoctorParent + 3.14.1 + ../../pom.xml + + CityDoctorAutoPro + CityDoctorAutoPro + Automated Simplification Algorithms + + + jakarta.xml.bind + jakarta.xml.bind-api + + + com.sun.xml.bind + jaxb-impl + runtime + + + de.hft.stuttgart + CityDoctorModel + + + de.hft.stuttgart + CityDoctorValidation + + + de.hft.stuttgart + CityDoctorHealer + + + org.apache.logging.log4j + log4j-api + + + junit + junit + test + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + + \ No newline at end of file diff --git a/CityDoctorParent/Extensions/CityDoctorAutoPro/src/main/java/de/hft/stuttgart/citydoctor2/connect/edge/AutoPro.java b/CityDoctorParent/Extensions/CityDoctorAutoPro/src/main/java/de/hft/stuttgart/citydoctor2/connect/edge/AutoPro.java new file mode 100644 index 0000000000000000000000000000000000000000..2593c8eb09586a5b4a1ff6b00347d2c8ddab5035 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorAutoPro/src/main/java/de/hft/stuttgart/citydoctor2/connect/edge/AutoPro.java @@ -0,0 +1,153 @@ +package de.hft.stuttgart.citydoctor2.connect.edge; + +import de.hft.stuttgart.citydoctor2.connect.edge.CppFeature; +import de.hft.stuttgart.citydoctor2.connect.edge.CppReferenceHandlingBase; +import de.hft.stuttgart.citydoctor2.connect.edge.NativeException; +import de.hft.stuttgart.citydoctor2.connect.edge.NativePointerCastException; + +/** + * + * @author PiR + * @version 1.0 + * + */ +public class AutoPro extends CppReferenceHandlingBase +{ + + // ----- native methods + // create and release stored C++ polygon check object + private native long createCppAutoPro() + throws OutOfMemoryError; + private native void disposeCppAutoPro(long ptrToCppAutoPro) + throws NativePointerCastException; + + // native methods + + private native boolean addFeature(long ptrToCppAutoPro, long ptrToCppFeature) + throws NativeException, IllegalArgumentException; + + private native boolean setSettingsExport(long ptrToCppAutoPro, long ptrToCppSettings) + throws NativeException, IllegalArgumentException; + + private native boolean setSettingsGeneral(long ptrToCppAutoPro, long ptrToCppSettings) + throws NativeException, IllegalArgumentException; + + private native boolean setSettingsBool(long ptrToCppAutoPro, long ptrToCppSettings) + throws NativeException, IllegalArgumentException; + + private native boolean setSettingsMerge(long ptrToCppAutoPro, long ptrToCppSettings) + throws NativeException, IllegalArgumentException; + + private native boolean setSettingsAdvancedSweep(long ptrToCppAutoPro, long ptrToCppSettings) + throws NativeException, IllegalArgumentException; + + private native boolean applyAutoProMethods(long ptrToCppAutoPro) + throws NativeException, IllegalArgumentException; + + public native long getHealResult(long ptrToCppAutoPro, long ptrToCppFeature) + throws NativeException, IllegalArgumentException; + + /** + * Constructor that gets a VPDFeature. All check method will be invoked on this feature. + * Remember to use the createCppObject method + * @param feature All check methods will use the data of this feature + * + * @see {@link createCppObject} {@link disposeCppObject} + */ + public AutoPro() + { + } + + + /** + * Creates an C++ object to use the native methods. + * + * @throws IllegalStateException + * Thrown if the encapsulated "long-Pointer" isn't 0 + * @throws NativeOutOfMemoryException + * If there is no more memory on the native side + * + * @see {@link disposeCppObject} + * @see de.hft.stuttgart.citydoctor.connect.edGe.CppReferenceHandlingBase#createCppObject() + */ + public void createCppObject() + throws OutOfMemoryError, IllegalStateException + { + if ( 0L != ptrToCppObject) + { + throw new IllegalStateException("Can't create new C++ object, there is allready one!"); + } + // Maybe an exception is thrown and there should be no crap in ptrToCppObject + long tmpPointer = createCppAutoPro(); + + ptrToCppObject = tmpPointer; + } + + + @Override + public void disposeCppObject() + throws NativePointerCastException + { + if ( 0L != ptrToCppObject) + { + disposeCppAutoPro(this.ptrToCppObject); + ptrToCppObject = 0x0; + } + } + + public void ap_addFeature(CppFeature feature) + throws NativeException, IllegalArgumentException + { + checkNullPointer(); + addFeature(ptrToCppObject, feature.ptrToCppObject); + } + + public void ap_setSettingsExport(AutoProSettingsExport settings) + throws NativeException, IllegalArgumentException + { + checkNullPointer(); + setSettingsExport(ptrToCppObject, settings.ptrToCppObject); + } + + public void ap_setSettingsGeneral(AutoProSettingsGeneral settings) + throws NativeException, IllegalArgumentException + { + checkNullPointer(); + setSettingsGeneral(ptrToCppObject, settings.ptrToCppObject); + } + + public void ap_setSettingsBool(AutoProSettingsBool settings) + throws NativeException, IllegalArgumentException + { + checkNullPointer(); + setSettingsBool(ptrToCppObject, settings.ptrToCppObject); + } + + public void ap_setSettingsMerge(AutoProSettingsMerge settings) + throws NativeException, IllegalArgumentException + { + checkNullPointer(); + setSettingsMerge(ptrToCppObject, settings.ptrToCppObject); + } + + public void ap_setSettingsAdvancedSweep(AutoProSettingsAdvancedSweep settings) + throws NativeException, IllegalArgumentException + { + checkNullPointer(); + setSettingsAdvancedSweep(ptrToCppObject, settings.ptrToCppObject); + } + + public void ap_applyAutoProMethods() + throws NativeException, IllegalArgumentException + { + checkNullPointer(); + applyAutoProMethods(ptrToCppObject); + } + + public long ap_getHealResult(CppFeature feature) { + checkNullPointer(); + return getHealResult(ptrToCppObject, feature.ptrToCppObject); + } + + +} diff --git a/CityDoctorParent/Extensions/CityDoctorAutoPro/src/main/java/de/hft/stuttgart/citydoctor2/connect/edge/AutoProSettingsAdvancedSweep.java b/CityDoctorParent/Extensions/CityDoctorAutoPro/src/main/java/de/hft/stuttgart/citydoctor2/connect/edge/AutoProSettingsAdvancedSweep.java new file mode 100644 index 0000000000000000000000000000000000000000..9c761732df318dd3e2e9ca459133548f4911f30d --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorAutoPro/src/main/java/de/hft/stuttgart/citydoctor2/connect/edge/AutoProSettingsAdvancedSweep.java @@ -0,0 +1,324 @@ +package de.hft.stuttgart.citydoctor2.connect.edge; + + +import de.hft.stuttgart.citydoctor2.connect.edge.CppReferenceHandlingBase; +import de.hft.stuttgart.citydoctor2.connect.edge.NativePointerCastException; + +public class AutoProSettingsAdvancedSweep extends CppReferenceHandlingBase { + private native long createCppClass( + + boolean advancedSweep_General_printInfo, + boolean advancedSweep_General_printFilterReasonInfo, + boolean advancedSweep_General_exportIntermediateStages, + double advancedSweep_General_minEdgeLength, + double advancedSweep_General_maxEdgeLength, + double advancedSweep_General_minDistToSweep, + + boolean advancedSweep_Planarity_Use, + boolean advancedSweep_Planarity_IgnoreMultiplePoints, + double advancedSweep_Planarity_PlanarityTolerance, + + boolean advancedSweep_SweepPlane_Use, + boolean advancedSweep_SweepPlane_PushOnly, + boolean advancedSweep_SweepPlane_PullOnly, + boolean advancedSweep_SweepPlane_ShortestEdgeFirst, + boolean advancedSweep_SweepPlane_SmallestFaceFirst, + boolean advancedSweep_SweepPlane_SmallestDistFirst, + + boolean advancedSweep_SweepRotate_Use, + double advancedSweep_SweepRotate_maxAngle, + boolean advancedSweep_SweepRotate_SmallestDistFirst, + boolean advancedSweep_SweepRotate_SmallestAngleFirst, + boolean advancedSweep_SweepRotate_SmallestFaceFirst + + ) + throws OutOfMemoryError; + + private native void disposeCppClass(long ptrToCppAutoPro) + throws NativePointerCastException; + + private boolean advancedSweep_General_printInfo; + private boolean advancedSweep_General_printFilterReasonInfo; + private boolean advancedSweep_General_exportIntermediateStages; + private double advancedSweep_General_minEdgeLength; + private double advancedSweep_General_maxEdgeLength; + private double advancedSweep_General_minDistToSweep; + + private boolean advancedSweep_Planarity_Use; + private boolean advancedSweep_Planarity_IgnoreMultiplePoints; + private double advancedSweep_Planarity_PlanarityTolerance; + + private boolean advancedSweep_SweepPlane_Use; + private boolean advancedSweep_SweepPlane_PushOnly; + private boolean advancedSweep_SweepPlane_PullOnly; + private boolean advancedSweep_SweepPlane_ShortestEdgeFirst; + private boolean advancedSweep_SweepPlane_SmallestFaceFirst; + private boolean advancedSweep_SweepPlane_SmallestDistFirst; + + private boolean advancedSweep_SweepRotate_Use; + private double advancedSweep_SweepRotate_maxAngle; + private boolean advancedSweep_SweepRotate_SmallestDistFirst; + private boolean advancedSweep_SweepRotate_SmallestAngleFirst; + private boolean advancedSweep_SweepRotate_SmallestFaceFirst; + + public AutoProSettingsAdvancedSweep() { + + set_advancedSweep_General_printInfo(false); + set_advancedSweep_General_printFilterReasonInfo(false); + set_advancedSweep_General_exportIntermediateStages(false); + set_advancedSweep_General_minEdgeLength(2.0); + set_advancedSweep_General_maxEdgeLength(5.0); + set_advancedSweep_General_minDistToSweep(0); + + set_advancedSweep_Planarity_Use(false); + set_advancedSweep_Planarity_IgnoreMultiplePoints(false); + set_advancedSweep_Planarity_PlanarityTolerance(0.001); + + set_advancedSweep_SweepPlane_Use(false); + set_advancedSweep_SweepPlane_PushOnly(false); + set_advancedSweep_SweepPlane_PullOnly(false); + set_advancedSweep_SweepPlane_ShortestEdgeFirst(false); + set_advancedSweep_SweepPlane_SmallestFaceFirst(false); + set_advancedSweep_SweepPlane_SmallestDistFirst(false); + + set_advancedSweep_SweepRotate_Use(false); + set_advancedSweep_SweepRotate_maxAngle(10); + set_advancedSweep_SweepRotate_SmallestDistFirst(false); + set_advancedSweep_SweepRotate_SmallestAngleFirst(false); + set_advancedSweep_SweepRotate_SmallestFaceFirst(false); + + } + + /** + * Creates an C++ feature object + * + * @throws IllegalStateException + * Thrown if the encapsulated "long-Pointer" isn't 0 + * @throws NativeOutOfMemoryException + * If there is no more memory on the native side + * + * @see {@link disposeCppObject} + * @see de.hft.stuttgart.citydoctor.connect.edGe.CppReferenceHandlingBase#createCppObject() + */ + public void createCppObject() throws IllegalStateException, + OutOfMemoryError { + if (0L != ptrToCppObject) { + throw new IllegalStateException( + "Can't create new C++ object, there is allready one!"); + } + // Maybe an exception is thrown + long tmpPointer = createCppClass( + is_advancedSweep_General_printInfo(), + is_advancedSweep_General_printFilterReasonInfo(), + is_advancedSweep_General_exportIntermediateStages(), + get_advancedSweep_General_minEdgeLength(), + get_advancedSweep_General_maxEdgeLength(), + get_advancedSweep_General_minDistToSweep(), + + + is_advancedSweep_Planarity_Use(), + is_advancedSweep_Planarity_IgnoreMultiplePoints(), + get_advancedSweep_Planarity_PlanarityTolerance(), + + is_advancedSweep_SweepPlane_Use(), + is_advancedSweep_SweepPlane_PushOnly(), + is_advancedSweep_SweepPlane_PullOnly(), + is_advancedSweep_SweepPlane_ShortestEdgeFirst(), + is_advancedSweep_SweepPlane_SmallestFaceFirst(), + is_advancedSweep_SweepPlane_SmallestDistFirst(), + + is_advancedSweep_SweepRotate_Use(), + get_advancedSweep_SweepRotate_maxAngle(), + is_advancedSweep_SweepRotate_SmallestDistFirst(), + is_advancedSweep_SweepRotate_SmallestAngleFirst(), + is_advancedSweep_SweepRotate_SmallestFaceFirst() + + + ); + ptrToCppObject = tmpPointer; + } + + @Override + public void disposeCppObject() throws NativePointerCastException { + if (0L != ptrToCppObject) { + disposeCppClass(ptrToCppObject); + ptrToCppObject = 0L; + } + } + + + + + + + public void set_advancedSweep_General_printInfo(boolean advancedSweep_General_printInfo) + { + this.advancedSweep_General_printInfo = advancedSweep_General_printInfo; + } + public void set_advancedSweep_General_printFilterReasonInfo(boolean advancedSweep_General_printFilterReasonInfo) + { + this.advancedSweep_General_printFilterReasonInfo = advancedSweep_General_printFilterReasonInfo; + } + public void set_advancedSweep_General_exportIntermediateStages(boolean advancedSweep_General_exportIntermediateStages) + { + this.advancedSweep_General_exportIntermediateStages = advancedSweep_General_exportIntermediateStages; + } + public void set_advancedSweep_General_minEdgeLength(double advancedSweep_General_minEdgeLength) + { + this.advancedSweep_General_minEdgeLength = advancedSweep_General_minEdgeLength; + } + public void set_advancedSweep_General_maxEdgeLength(double advancedSweep_General_maxEdgeLength) + { + this.advancedSweep_General_maxEdgeLength = advancedSweep_General_maxEdgeLength; + } + public void set_advancedSweep_General_minDistToSweep(double advancedSweep_General_minDistToSweep) + { + this.advancedSweep_General_minDistToSweep = advancedSweep_General_minDistToSweep; + } + + + public void set_advancedSweep_Planarity_Use(boolean advancedSweep_Planarity_Use) + { + this.advancedSweep_Planarity_Use = advancedSweep_Planarity_Use; + } + public void set_advancedSweep_Planarity_IgnoreMultiplePoints(boolean advancedSweep_Planarity_IgnoreMultiplePoints) + { + this.advancedSweep_Planarity_IgnoreMultiplePoints = advancedSweep_Planarity_IgnoreMultiplePoints; + } + public void set_advancedSweep_Planarity_PlanarityTolerance(double advancedSweep_Planarity_PlanarityTolerance) + { + this.advancedSweep_Planarity_PlanarityTolerance = advancedSweep_Planarity_PlanarityTolerance; + } + + public void set_advancedSweep_SweepPlane_Use(boolean advancedSweep_SweepPlane_Use) + { + this.advancedSweep_SweepPlane_Use = advancedSweep_SweepPlane_Use; + } + public void set_advancedSweep_SweepPlane_PushOnly(boolean advancedSweep_SweepPlane_PushOnly) + { + this.advancedSweep_SweepPlane_PushOnly = advancedSweep_SweepPlane_PushOnly; + } + public void set_advancedSweep_SweepPlane_PullOnly(boolean advancedSweep_SweepPlane_PullOnly) + { + this.advancedSweep_SweepPlane_PullOnly = advancedSweep_SweepPlane_PullOnly; + } + public void set_advancedSweep_SweepPlane_ShortestEdgeFirst(boolean advancedSweep_SweepPlane_ShortestEdgeFirst) + { + this.advancedSweep_SweepPlane_ShortestEdgeFirst = advancedSweep_SweepPlane_ShortestEdgeFirst; + } + public void set_advancedSweep_SweepPlane_SmallestFaceFirst(boolean advancedSweep_SweepPlane_SmallestFaceFirst) + { + this.advancedSweep_SweepPlane_SmallestFaceFirst = advancedSweep_SweepPlane_SmallestFaceFirst; + } + public void set_advancedSweep_SweepPlane_SmallestDistFirst(boolean advancedSweep_SweepPlane_SmallestDistFirst) + { + this.advancedSweep_SweepPlane_SmallestDistFirst = advancedSweep_SweepPlane_SmallestDistFirst; + } + + public void set_advancedSweep_SweepRotate_Use(boolean advancedSweep_SweepRotate_Use) + { + this.advancedSweep_SweepRotate_Use = advancedSweep_SweepRotate_Use; + } + public void set_advancedSweep_SweepRotate_maxAngle(double advancedSweep_SweepRotate_maxAngle) + { + this.advancedSweep_SweepRotate_maxAngle = advancedSweep_SweepRotate_maxAngle; + } + public void set_advancedSweep_SweepRotate_SmallestDistFirst(boolean advancedSweep_SweepRotate_SmallestDistFirst) + { + this.advancedSweep_SweepRotate_SmallestDistFirst = advancedSweep_SweepRotate_SmallestDistFirst; + } + public void set_advancedSweep_SweepRotate_SmallestAngleFirst(boolean advancedSweep_SweepRotate_SmallestAngleFirst) + { + this.advancedSweep_SweepRotate_SmallestAngleFirst = advancedSweep_SweepRotate_SmallestAngleFirst; + } + public void set_advancedSweep_SweepRotate_SmallestFaceFirst(boolean advancedSweep_SweepRotate_SmallestFaceFirst) + { + this.advancedSweep_SweepRotate_SmallestFaceFirst = advancedSweep_SweepRotate_SmallestFaceFirst; + } + + public boolean is_advancedSweep_General_printInfo() + { + return this.advancedSweep_General_printInfo; + } + public boolean is_advancedSweep_General_printFilterReasonInfo() + { + return this.advancedSweep_General_printFilterReasonInfo; + } + public boolean is_advancedSweep_General_exportIntermediateStages() + { + return this.advancedSweep_General_exportIntermediateStages; + } + public double get_advancedSweep_General_minEdgeLength() + { + return this.advancedSweep_General_minEdgeLength; + } + public double get_advancedSweep_General_maxEdgeLength() + { + return this.advancedSweep_General_maxEdgeLength; + } + public double get_advancedSweep_General_minDistToSweep() + { + return this.advancedSweep_General_minDistToSweep; + } + + public boolean is_advancedSweep_Planarity_Use() + { + return this.advancedSweep_Planarity_Use; + } + public boolean is_advancedSweep_Planarity_IgnoreMultiplePoints() + { + return this.advancedSweep_Planarity_IgnoreMultiplePoints; + } + public double get_advancedSweep_Planarity_PlanarityTolerance() + { + return this.advancedSweep_Planarity_PlanarityTolerance; + } + + public boolean is_advancedSweep_SweepPlane_Use() + { + return this.advancedSweep_SweepPlane_Use; + } + public boolean is_advancedSweep_SweepPlane_PushOnly() + { + return this.advancedSweep_SweepPlane_PushOnly; + } + public boolean is_advancedSweep_SweepPlane_PullOnly() + { + return this.advancedSweep_SweepPlane_PullOnly; + } + public boolean is_advancedSweep_SweepPlane_ShortestEdgeFirst() + { + return this.advancedSweep_SweepPlane_ShortestEdgeFirst; + } + public boolean is_advancedSweep_SweepPlane_SmallestFaceFirst() + { + return this.advancedSweep_SweepPlane_SmallestFaceFirst; + } + public boolean is_advancedSweep_SweepPlane_SmallestDistFirst() + { + return this.advancedSweep_SweepPlane_SmallestDistFirst; + } + + public boolean is_advancedSweep_SweepRotate_Use() + { + return this.advancedSweep_SweepRotate_Use; + } + public double get_advancedSweep_SweepRotate_maxAngle() + { + return this.advancedSweep_SweepRotate_maxAngle; + } + public boolean is_advancedSweep_SweepRotate_SmallestDistFirst() + { + return this.advancedSweep_SweepRotate_SmallestDistFirst; + } + public boolean is_advancedSweep_SweepRotate_SmallestAngleFirst() + { + return this.advancedSweep_SweepRotate_SmallestAngleFirst; + } + public boolean is_advancedSweep_SweepRotate_SmallestFaceFirst() + { + return this.advancedSweep_SweepRotate_SmallestFaceFirst; + } + + +} diff --git a/CityDoctorParent/Extensions/CityDoctorAutoPro/src/main/java/de/hft/stuttgart/citydoctor2/connect/edge/AutoProSettingsBool.java b/CityDoctorParent/Extensions/CityDoctorAutoPro/src/main/java/de/hft/stuttgart/citydoctor2/connect/edge/AutoProSettingsBool.java new file mode 100644 index 0000000000000000000000000000000000000000..700dfb692b107358aedbfe38b90231c6fe3f5731 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorAutoPro/src/main/java/de/hft/stuttgart/citydoctor2/connect/edge/AutoProSettingsBool.java @@ -0,0 +1,140 @@ +package de.hft.stuttgart.citydoctor2.connect.edge; + + + +import de.hft.stuttgart.citydoctor2.connect.edge.CppReferenceHandlingBase; +import de.hft.stuttgart.citydoctor2.connect.edge.NativePointerCastException; + +public class AutoProSettingsBool extends CppReferenceHandlingBase { + private native long createCppClass( + + boolean useBool, + boolean printBoolInfo, + boolean exportIntermediateStages, + boolean useMinkowski, + boolean printMinkowskiInfo, + double minkowksiCubeSize, + boolean rotateMinkowskiCube + + ) + throws OutOfMemoryError; + + private native void disposeCppClass(long ptrToCppAutoPro) + throws NativePointerCastException; + + private boolean useBool; + private boolean printBoolInfo; + private boolean exportIntermediateStages; + private boolean useMinkowski; + private boolean printMinkowskiInfo; + private double minkowskiCubeSize; + private boolean rotateMinkowskiCube; + + + public AutoProSettingsBool() { + + setUseBool(false); + setPrintBoolInfo(false); + setExportIntermediateStages(false); + setUseMinkowski(false); + setPrintMinkowskiInfo(false); + setMinkowskiCubeSize(2.2); + setRotateMinkowskiCube(false); + + } + + /** + * Creates an C++ feature object + * + * @throws IllegalStateException + * Thrown if the encapsulated "long-Pointer" isn't 0 + * @throws NativeOutOfMemoryException + * If there is no more memory on the native side + * + * @see {@link disposeCppObject} + * @see de.hft.stuttgart.citydoctor.connect.edGe.CppReferenceHandlingBase#createCppObject() + */ + public void createCppObject() throws IllegalStateException, + OutOfMemoryError { + if (0L != ptrToCppObject) { + throw new IllegalStateException( + "Can't create new C++ object, there is allready one!"); + } + // Maybe an exception is thrown + long tmpPointer = createCppClass( + isUseBool(), + isPrintBoolInfo(), + isExportIntermediateStages(), + isUseMinkowski(), + isPrintMinkowskiInfo(), + getMinkowskiCubeSize(), + isRotateMinkowskiCube() + ); + ptrToCppObject = tmpPointer; + } + + @Override + public void disposeCppObject() throws NativePointerCastException { + if (0L != ptrToCppObject) { + disposeCppClass(ptrToCppObject); + ptrToCppObject = 0L; + } + } + + public void setUseBool(boolean useBool) { + this.useBool = useBool; + } + + public void setPrintBoolInfo(boolean printBoolInfo) { + this.printBoolInfo = printBoolInfo; + } + + public void setExportIntermediateStages(boolean exportIntermediateStages) { + this.exportIntermediateStages = exportIntermediateStages; + } + + public void setUseMinkowski(boolean useMinkowski) { + this.useMinkowski = useMinkowski; + } + + public void setPrintMinkowskiInfo(boolean printMinkowskiInfo) { + this.printMinkowskiInfo = printMinkowskiInfo; + } + + public void setMinkowskiCubeSize(double minkowskiCubeSize) { + this.minkowskiCubeSize = minkowskiCubeSize; + } + public void setRotateMinkowskiCube(boolean rotateMinkowskiCube) { + this.rotateMinkowskiCube = rotateMinkowskiCube; + } + + + public boolean isUseBool() { + return useBool; + } + + public boolean isPrintBoolInfo() { + return printBoolInfo; + } + + + public boolean isExportIntermediateStages() { + return exportIntermediateStages; + } + + public boolean isUseMinkowski() { + return useMinkowski; + } + + public boolean isPrintMinkowskiInfo() { + return printMinkowskiInfo; + } + + public double getMinkowskiCubeSize() { + return minkowskiCubeSize; + } + public boolean isRotateMinkowskiCube() { + return rotateMinkowskiCube; + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorAutoPro/src/main/java/de/hft/stuttgart/citydoctor2/connect/edge/AutoProSettingsExport.java b/CityDoctorParent/Extensions/CityDoctorAutoPro/src/main/java/de/hft/stuttgart/citydoctor2/connect/edge/AutoProSettingsExport.java new file mode 100644 index 0000000000000000000000000000000000000000..b9af7fe34705508072b6d45c94eb528b72ef4920 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorAutoPro/src/main/java/de/hft/stuttgart/citydoctor2/connect/edge/AutoProSettingsExport.java @@ -0,0 +1,301 @@ +package de.hft.stuttgart.citydoctor2.connect.edge; + + + +import de.hft.stuttgart.citydoctor2.connect.edge.CppReferenceHandlingBase; +import de.hft.stuttgart.citydoctor2.connect.edge.NativePointerCastException; + +public class AutoProSettingsExport extends CppReferenceHandlingBase { + private native long createCppClass( + + boolean exportMesh, + String meshFileName, + String meshFilePath, + + boolean exportIV, + String ivFileName, + String ivFilePath, + + boolean exportSTEP, + String stepFileName, + String stepFilePath, + + boolean exportCityGML, + String cityGMLFileName, + String cityGMLFilePath, + + boolean exportValidBuildingsOnly, + boolean moveBuildingsToOrigin, + boolean exportIntermediateStagesComplete, + boolean oneSolidPerBuilding, + + double minDistToOrigin_X, + double minDistToOrigin_Y, + double minDistToOrigin_Z + + + ) + throws OutOfMemoryError; + + private native void disposeCppClass(long ptrToCppAutoPro) + throws NativePointerCastException; + + + private boolean exportMesh; + private String meshFileName; + private String meshFilePath; + + private boolean exportIV; + private String ivFileName; + private String ivFilePath; + + private boolean exportSTEP; + private String stepFileName; + private String stepFilePath; + + private boolean exportCityGML; + private String cityGMLFileName; + private String cityGMLFilePath; + + private boolean exportValidBuildingsOnly; + private boolean moveBuildingsToOrigin; + private boolean exportIntermediateStagesComplete; + private boolean oneSolidPerBuilding; + + double minDistToOrigin_X; + double minDistToOrigin_Y; + double minDistToOrigin_Z; + + public AutoProSettingsExport() { + + setExportMesh(false); + setMeshFileName(""); + setMeshFilePath(""); + + setExportIV(false); + setIVFileName(""); + setIVFilePath(""); + + setExportSTEP(false); + setSTEPFileName(""); + setSTEPFilePath(""); + + setExportCityGML(false); + setCityGMLFileName(""); + setCityGMLFilePath(""); + + setExportValidBuildingsOnly(false); + setMoveBuildingsToOrigin(false); + setExportIntermediateStagesComplete(false); + setExportStepWithOneSolidPerBuilding(false); + + setMinDistToOrigin_X(0); + setMinDistToOrigin_Y(0); + setMinDistToOrigin_Z(0); + + } + + /** + * Creates an C++ feature object + * + * @throws IllegalStateException + * Thrown if the encapsulated "long-Pointer" isn't 0 + * @throws NativeOutOfMemoryException + * If there is no more memory on the native side + * + * @see {@link disposeCppObject} + * @see de.hft.stuttgart.citydoctor.connect.edGe.CppReferenceHandlingBase#createCppObject() + */ + public void createCppObject() throws IllegalStateException, + OutOfMemoryError { + if (0L != ptrToCppObject) { + throw new IllegalStateException( + "Can't create new C++ object, there is allready one!"); + } + // Maybe an exception is thrown + long tmpPointer = createCppClass( + isExportMesh(), + getMeshFileName(), + getMeshFilePath(), + isExportIV(), + getIVFileName(), + getIVFilePath(), + isExportSTEP(), + getSTEPFileName(), + getSTEPFilePath(), + isExportCityGML(), + getCityGMLFileName(), + getCityGMLFilePath(), + getExportValidBuildingsOnly(), + getMoveBuildingsToOrigin(), + getExportIntermediateStagesComplete(), + getExportStepWithOneSolidPerBuilding(), + getMinDistToOrigin_X(), + getMinDistToOrigin_Y(), + getMinDistToOrigin_Z() + ); + ptrToCppObject = tmpPointer; + } + + @Override + public void disposeCppObject() throws NativePointerCastException { + if (0L != ptrToCppObject) { + disposeCppClass(ptrToCppObject); + ptrToCppObject = 0L; + } + } + + + public void setExportMesh(boolean exportMesh) { + this.exportMesh = exportMesh; + } + + public void setMeshFileName(String meshFileName) { + this.meshFileName = meshFileName; + } + + public void setMeshFilePath (String meshFilePath) { + this.meshFilePath = meshFilePath; + } + + public void setExportIV(boolean exportIV) { + this.exportIV = exportIV; + } + + public void setIVFileName(String ivFileName) { + this.ivFileName = ivFileName; + } + + public void setIVFilePath (String ivFilePath) { + this.ivFilePath = ivFilePath; + } + + public void setExportSTEP(boolean exportSTEP) { + this.exportSTEP = exportSTEP; + } + + public void setSTEPFileName(String stepFileName) { + this.stepFileName = stepFileName; + } + + public void setSTEPFilePath (String stepFilePath) { + this.stepFilePath = stepFilePath; + } + + public void setExportCityGML(boolean exportCityGML) { + this.exportCityGML = exportCityGML; + } + + public void setCityGMLFileName(String cityGMLFileName) { + this.cityGMLFileName = cityGMLFileName; + } + + public void setCityGMLFilePath(String cityGMLFilePath) { + this.cityGMLFilePath = cityGMLFilePath; + } + + public void setExportValidBuildingsOnly(boolean exportValidBuildingsOnly) { + this.exportValidBuildingsOnly = exportValidBuildingsOnly; + } + + public void setMoveBuildingsToOrigin(boolean moveBuildingsToOrigin) { + this.moveBuildingsToOrigin = moveBuildingsToOrigin; + } + + public void setExportIntermediateStagesComplete(boolean exportIntermediateStagesComplete) { + this.exportIntermediateStagesComplete = exportIntermediateStagesComplete; + } + + public void setExportStepWithOneSolidPerBuilding(boolean oneSolidPerBuilding) { + this.oneSolidPerBuilding = oneSolidPerBuilding; + } + + public void setMinDistToOrigin_X(double minDistToOrigin_X) { + this.minDistToOrigin_X = minDistToOrigin_X; + } + + public void setMinDistToOrigin_Y(double minDistToOrigin_Y) { + this.minDistToOrigin_Y = minDistToOrigin_Y; + } + + public void setMinDistToOrigin_Z(double minDistToOrigin_Z) { + this.minDistToOrigin_Z = minDistToOrigin_Z; + } + + + public boolean isExportMesh() { + return exportMesh; + } + + public String getMeshFileName() { + return meshFileName; + } + + public String getMeshFilePath () { + return meshFilePath; + } + + public boolean isExportIV() { + return exportIV; + } + + public String getIVFileName() { + return ivFileName; + } + + public String getIVFilePath () { + return ivFilePath; + } + + public boolean isExportSTEP() { + return exportSTEP; + } + + public String getSTEPFileName() { + return stepFileName; + } + + public String getSTEPFilePath () { + return stepFilePath; + } + + public boolean isExportCityGML() { + return exportCityGML; + } + + public String getCityGMLFileName() { + return cityGMLFileName; + } + + public String getCityGMLFilePath() { + return cityGMLFilePath; + } + + public boolean getExportValidBuildingsOnly() { + return exportValidBuildingsOnly; + } + + public boolean getMoveBuildingsToOrigin() { + return moveBuildingsToOrigin; + } + + public boolean getExportIntermediateStagesComplete() { + return exportIntermediateStagesComplete; + } + + public boolean getExportStepWithOneSolidPerBuilding() { + return oneSolidPerBuilding; + } + + public double getMinDistToOrigin_X() { + return minDistToOrigin_X; + } + + public double getMinDistToOrigin_Y() { + return minDistToOrigin_Y; + } + + public double getMinDistToOrigin_Z() { + return minDistToOrigin_Z; + } +} diff --git a/CityDoctorParent/Extensions/CityDoctorAutoPro/src/main/java/de/hft/stuttgart/citydoctor2/connect/edge/AutoProSettingsGeneral.java b/CityDoctorParent/Extensions/CityDoctorAutoPro/src/main/java/de/hft/stuttgart/citydoctor2/connect/edge/AutoProSettingsGeneral.java new file mode 100644 index 0000000000000000000000000000000000000000..17531850b0179c73d361ce8e8af5c1cf6d2d4d9a --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorAutoPro/src/main/java/de/hft/stuttgart/citydoctor2/connect/edge/AutoProSettingsGeneral.java @@ -0,0 +1,173 @@ +package de.hft.stuttgart.citydoctor2.connect.edge; + + +import de.hft.stuttgart.citydoctor2.connect.edge.CppReferenceHandlingBase; +import de.hft.stuttgart.citydoctor2.connect.edge.NativePointerCastException; + +public class AutoProSettingsGeneral extends CppReferenceHandlingBase { + private native long createCppClass( + boolean printBuildingInfo, + boolean printStatus, + boolean printSmallestAngle, + boolean printNumberOFSmallAngles, + double smallAngleTolerance, + boolean printShortestEdge, + boolean printNumberOfShortEdges, + double shortEdgesTolerance, + boolean printVolume, + boolean printNumberOfFacesAndVertices + ) + throws OutOfMemoryError; + + private native void disposeCppClass(long ptrToCppAutoPro) + throws NativePointerCastException; + + + private boolean printBuildingInfo; + private boolean printStatus; + private boolean printSmallestAngle; + private boolean printNumberOfSmallAngles; + private double smallAngleTolerance; + private boolean printShortestEdge; + private boolean printNumberOfShortEdges; + private double shortEdgesTolerance; + private boolean printVolume; + private boolean printNumberOfFacesAndVertices; + + public AutoProSettingsGeneral() { + + setPrintBuildingInfo(false); + setPrintStatus(false); + setPrintSmallestAngle(false); + setPrintNumberOfSmallAngles(false); + setSmallAngleTolerance(0.1); + setPrintShortestEdge(false); + setPrintNumberOfShortEdges(false); + setShortEdgesTolerance(0.1); + setPrintVolume(false); + setPrintNumberOfFacesAndVertices(false); + + } + + /** + * Creates an C++ feature object + * + * @throws IllegalStateException + * Thrown if the encapsulated "long-Pointer" isn't 0 + * @throws NativeOutOfMemoryException + * If there is no more memory on the native side + * + * @see {@link disposeCppObject} + * @see de.hft.stuttgart.citydoctor.connect.edGe.CppReferenceHandlingBase#createCppObject() + */ + public void createCppObject() throws IllegalStateException, + OutOfMemoryError { + if (0L != ptrToCppObject) { + throw new IllegalStateException( + "Can't create new C++ object, there is allready one!"); + } + // Maybe an exception is thrown + long tmpPointer = createCppClass( + isPrintBuildingInfo(), + isPrintStatus(), + isPrintSmallestAngle(), + isPrintNumberOfSmallAngles(), + getSmallAngleTolerance(), + isPrintShortestEdge(), + isPrintNumberOfShortEdges(), + getShortEdgesTolerance(), + isPrintVolume(), + isPrintNumberOfFacesAndVertices() + ); + ptrToCppObject = tmpPointer; + } + + @Override + public void disposeCppObject() throws NativePointerCastException { + if (0L != ptrToCppObject) { + disposeCppClass(ptrToCppObject); + ptrToCppObject = 0L; + } + } + + public void setPrintBuildingInfo(boolean printBuildingInfo) { + this.printBuildingInfo = printBuildingInfo; + } + + public void setPrintStatus(boolean printStatus) { + this.printStatus = printStatus; + } + + public void setPrintSmallestAngle(boolean printSmallestAngle) { + this.printSmallestAngle = printSmallestAngle; + } + + public void setPrintNumberOfSmallAngles(boolean printNumberOfSmallAngles) { + this.printNumberOfSmallAngles = printNumberOfSmallAngles; + } + + public void setSmallAngleTolerance(double smallAngleTolerance) { + this.smallAngleTolerance = smallAngleTolerance; + } + + public void setPrintShortestEdge(boolean printShortestEdge) { + this.printShortestEdge = printShortestEdge; + } + + public void setPrintNumberOfShortEdges(boolean printNumberOfShortEdges) { + this.printNumberOfShortEdges = printNumberOfShortEdges; + } + + public void setShortEdgesTolerance(double shortEdgesTolerance) { + this.shortEdgesTolerance = shortEdgesTolerance; + } + + public void setPrintVolume(boolean printVolume) { + this.printVolume = printVolume; + } + + public void setPrintNumberOfFacesAndVertices(boolean printNumberOfFacesAndVertices) { + this.printNumberOfFacesAndVertices = printNumberOfFacesAndVertices; + } + + public boolean isPrintBuildingInfo() { + return printBuildingInfo; + } + + public boolean isPrintStatus() { + return printStatus; + } + + public boolean isPrintSmallestAngle() { + return printSmallestAngle; + } + + public boolean isPrintNumberOfSmallAngles() { + return printNumberOfSmallAngles; + } + + public double getSmallAngleTolerance() { + return smallAngleTolerance; + } + + public boolean isPrintShortestEdge() { + return printShortestEdge; + } + + public boolean isPrintNumberOfShortEdges() { + return printNumberOfShortEdges; + } + + public double getShortEdgesTolerance() { + return shortEdgesTolerance; + } + + public boolean isPrintVolume() { + return printVolume; + } + + public boolean isPrintNumberOfFacesAndVertices() { + return printNumberOfFacesAndVertices; + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorAutoPro/src/main/java/de/hft/stuttgart/citydoctor2/connect/edge/AutoProSettingsMerge.java b/CityDoctorParent/Extensions/CityDoctorAutoPro/src/main/java/de/hft/stuttgart/citydoctor2/connect/edge/AutoProSettingsMerge.java new file mode 100644 index 0000000000000000000000000000000000000000..5cbca22f45bc5d020a4c82bdcf7d1cd6cd773608 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorAutoPro/src/main/java/de/hft/stuttgart/citydoctor2/connect/edge/AutoProSettingsMerge.java @@ -0,0 +1,112 @@ +package de.hft.stuttgart.citydoctor2.connect.edge; + + + +import de.hft.stuttgart.citydoctor2.connect.edge.CppReferenceHandlingBase; +import de.hft.stuttgart.citydoctor2.connect.edge.NativePointerCastException; + +public class AutoProSettingsMerge extends CppReferenceHandlingBase { + private native long createCppClass( + boolean useMerge, + boolean exportIntermediateStages, + boolean printMergeInfo, + double eps_PointEquality, + double eps_Parallelity + ) + throws OutOfMemoryError; + + private native void disposeCppClass(long ptrToCppAutoPro) + throws NativePointerCastException; + + private boolean useMerge; + private boolean exportIntermediateStages; + private boolean printMergeInfo; + private double eps_PointEquality; + private double eps_Parallelity; + + public AutoProSettingsMerge() { + setUseMerge(false); + setExportIntermediateStages(false); + setPrintMergeInfo(false); + setEps_PointEquality(0.01); + setEps_Parallelity(0.01); + } + + /** + * Creates an C++ feature object + * + * @throws IllegalStateException + * Thrown if the encapsulated "long-Pointer" isn't 0 + * @throws NativeOutOfMemoryException + * If there is no more memory on the native side + * + * @see {@link disposeCppObject} + * @see de.hft.stuttgart.citydoctor.connect.edGe.CppReferenceHandlingBase#createCppObject() + */ + public void createCppObject() throws IllegalStateException, + OutOfMemoryError { + if (0L != ptrToCppObject) { + throw new IllegalStateException( + "Can't create new C++ object, there is allready one!"); + } + // Maybe an exception is thrown + long tmpPointer = createCppClass( + isUseMerge(), + isExportIntermediateStages(), + isPrintMergeInfo(), + getEps_PointEquality(), + getEps_Parallelity() + ); + ptrToCppObject = tmpPointer; + } + + @Override + public void disposeCppObject() throws NativePointerCastException { + if (0L != ptrToCppObject) { + disposeCppClass(ptrToCppObject); + ptrToCppObject = 0L; + } + } + + public void setUseMerge(boolean useMerge) { + this.useMerge = useMerge; + } + + public void setExportIntermediateStages(boolean exportIntermediateStages) { + this.exportIntermediateStages = exportIntermediateStages; + } + + public void setPrintMergeInfo(boolean printMergeInfo) { + this.printMergeInfo = printMergeInfo; + } + + public void setEps_PointEquality(double eps_PointEquality) { + this.eps_PointEquality = eps_PointEquality; + } + + public void setEps_Parallelity(double eps_Parallelity) { + this.eps_Parallelity = eps_Parallelity; + } + + + public boolean isUseMerge() { + return useMerge; + } + + public boolean isExportIntermediateStages() { + return exportIntermediateStages; + } + + public boolean isPrintMergeInfo() { + return printMergeInfo; + } + + public double getEps_PointEquality() { + return eps_PointEquality; + } + + public double getEps_Parallelity() { + return eps_Parallelity; + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorAutoPro/src/main/java/de/hft/stuttgart/citydoctor2/gui/AutoProWindow.java b/CityDoctorParent/Extensions/CityDoctorAutoPro/src/main/java/de/hft/stuttgart/citydoctor2/gui/AutoProWindow.java new file mode 100644 index 0000000000000000000000000000000000000000..08a586a541a96b1fe68e490a1b1e0fb3f08a9242 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorAutoPro/src/main/java/de/hft/stuttgart/citydoctor2/gui/AutoProWindow.java @@ -0,0 +1,2899 @@ +/** -------------------------------------------------- + * Hochschule fuer Technik Stuttgart + * Fachbereich Vermessung , Informatik und Mathematik + * Schellingstr . 24 + * D - 70174 Stuttgart + * + * Projekt CityDoktor + * + * Copyright (c) 2011 HFT Stuttgart. All rights reserved. + * HFT Stuttgart and its licensors retain all intellectual property and + * proprietary rights in and to this software and related documentation. + * Any use, reproduction, disclosure, or distribution of this software + * and related documentation without an express license agreement from + * HFT Stuttgart is strictly prohibited. + * + * Please refer to the applicable HFT Stuttgart end user license agreement (EULA) + * associated with this source code for terms and conditions that govern + * your use of this HFT Stuttgart software. + * + * @author PiR + * @version 1.0 + * created: 17.12.2017 + */ +package de.hft.stuttgart.citydoctor2.gui; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Font; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.io.IOException; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.swing.GroupLayout; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JDialog; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JSlider; +import javax.swing.JTextField; +import javax.swing.border.Border; +import javax.swing.border.LineBorder; +import javax.swing.border.TitledBorder; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.filechooser.FileFilter; + +import de.hft.stuttgart.citydoctor2.CppInitializer; +import de.hft.stuttgart.citydoctor2.connect.edge.AutoPro; +import de.hft.stuttgart.citydoctor2.connect.edge.AutoProSettingsAdvancedSweep; +import de.hft.stuttgart.citydoctor2.connect.edge.AutoProSettingsBool; +import de.hft.stuttgart.citydoctor2.connect.edge.AutoProSettingsExport; +import de.hft.stuttgart.citydoctor2.connect.edge.AutoProSettingsGeneral; +import de.hft.stuttgart.citydoctor2.connect.edge.AutoProSettingsMerge; +import de.hft.stuttgart.citydoctor2.connect.edge.CppFeature; +import de.hft.stuttgart.citydoctor2.connect.edge.CppHealResult; +import de.hft.stuttgart.citydoctor2.connect.edge.NativeException; +import de.hft.stuttgart.citydoctor2.connect.edge.NativePointerCastException; +//import de.hft.stuttgart.citydoctor2.CityDoctorDataStream; +//import de.hft.stuttgart.citydoctor2.CityDoctorValidationStreamLite; +import de.hft.stuttgart.citydoctor2.datastructure.Building; +import de.hft.stuttgart.citydoctor2.datastructure.Installation; +import de.hft.stuttgart.citydoctor2.datastructure.BuildingPart; +import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel; +import de.hft.stuttgart.citydoctor2.datastructure.CityObject; +import de.hft.stuttgart.citydoctor2.datastructure.Geometry; +import de.hft.stuttgart.citydoctor2.datastructure.Vertex; + +class DoubleJSlider extends JSlider { + + private static final long serialVersionUID = 1L; + final int scale; + + public DoubleJSlider(int min, int max, int value, int scale) { + super(min, max, value); + this.scale = scale; + } + + public double getScaledValue() { + return ((double)super.getValue()) / this.scale; + } +} + + +class FileInfo { + + String filePath; + String fileName; + String fileType; + + public FileInfo(String path, String name, String fileType) { + this.filePath = path; + this.fileName = name; + this.fileType = fileType; + } + + public FileInfo() { + this.filePath = ""; + this.fileName = ""; + this.fileType = ""; + } + + public void setPath(String path) { + this.filePath = path; + } + + public String getPath() { + return this.filePath; + } + + public void setName(String name) { + this.fileName = name; + } + + public String getName() { + return this.fileName; + } + + public void setType(String fileType) { + this.fileType = fileType; + } + + public String getType() { + return this.fileType; + } + + public String getString() { + return this.filePath + this.fileName + this.fileType; + } + +} + +public class AutoProWindow extends JDialog implements ItemListener { + + // Variable fuer Serialisierung + private static final long serialVersionUID = 2626132909887065227L; + + JCheckBox MeshExportCheckBox; + private JTextField MeshExportTextField; + private JButton MeshExportJButton; + private FileInfo meshFileInfo = new FileInfo(".\\_meshFiles\\", "MeshObject", ".iv"); + + JCheckBox IVExportCheckBox; + private JTextField IVExportTextField; + private JButton IVExportJButton; + private FileInfo ivFileInfo = new FileInfo(".\\_ivFiles\\", "IVObject", ".iv"); + + JCheckBox STEPExportCheckBox; + private JTextField STEPExportTextField; + private JButton STEPExportJButton; + private FileInfo stepFileInfo = new FileInfo(".\\_stepFiles\\", "STEPObject", ".stp"); + + JCheckBox GMLExportCheckBox; + private JTextField GMLExportTextField; + private JButton GMLExportJButton; + private FileInfo gmlFileInfo = new FileInfo(".\\_gmlFiles\\", "CityGMLObject", ".gml"); + + JCheckBox exportValidBuildingsOnlyCheckBox; + JCheckBox moveBuildingBlockToOriginCheckBox; + JCheckBox exportIntermediateStagesCompleteCheckBox; + JCheckBox exportStepWithOneSolidPerBuilding; + double minDistToOrigin_X; + double minDistToOrigin_Y; + double minDistToOrigin_Z; + + JCheckBox printBuildingInfoCheckBox; + JCheckBox printStatusCheckBox; + + JCheckBox printAllCheckBox; + JCheckBox printSmallestAngleCheckBox; + JCheckBox printNumberOfSmallAnglesCheckBox; + JTextField smallAngleToleranceTextField; + double smallAngleTolerance; + JCheckBox printShortestEdgeCheckBox; + JCheckBox printNumberOfShortEdgesCheckBox; + JTextField shortEdgesToleranceTextField; + double shortEdgesTolerance; + JCheckBox printVolumeCheckBox; + JCheckBox printNumberOfFacesAndVerticesCheckBox; + + JCheckBox boolCheckBox; + JCheckBox printBoolInfoCheckBox; + JCheckBox boolMinkowski_exportIntermediateStagesCheckBox; + JCheckBox minkowskiCheckBox; + JCheckBox printMinkowskiInfoCheckBox; + JLabel minkowskiCubeLabel; + DoubleJSlider minkowskiCubeSlider; + JTextField minkowskiCubeTextField; + JCheckBox rotateMinkowskiCube; + + JCheckBox mergeCheckBox; + JCheckBox merge_exportIntermediateStagesCheckBox; + JCheckBox printMergeInfoCheckBox; + JLabel eps_PointEqualityLabel; + DoubleJSlider eps_PointEqualitySlider; + JTextField eps_PointEqualityTextField; + JLabel eps_ParallelityLabel; + DoubleJSlider eps_ParallelitySlider; + JTextField eps_ParallelityTextField; + + JCheckBox advancedSweep_General_printInfoCheckBox; + JCheckBox advancedSweep_General_printFilterReasonInfoCheckBox; + JCheckBox advancedSweep_General_exportIntermediateStagesCheckBox; + JLabel advancedSweep_General_minEdgeLengthLabel; + DoubleJSlider advancedSweep_General_minEdgeLengthSlider; + JTextField advancedSweep_General_minEdgeLengthTextField; + JLabel advancedSweep_General_maxEdgeLengthLabel; + DoubleJSlider advancedSweep_General_maxEdgeLengthSlider; + JTextField advancedSweep_General_maxEdgeLengthTextField; + JLabel advancedSweep_General_minDistToSweepLabel; + DoubleJSlider advancedSweep_General_minDistToSweepSlider; + JTextField advancedSweep_General_minDistToSweepTextField; + + JCheckBox advancedSweep_Planarity_Use_CheckBox; + JCheckBox advancedSweep_Planarity_IgnoreMultiplePoints_CheckBox; + JLabel advancedSweep_Planarity_PlanarityTolerance_SweepLabel; + DoubleJSlider advancedSweep_Planarity_PlanarityTolerance_SweepSlider; + JTextField advancedSweep_Planarity_PlanarityTolerance_TextField; + + JCheckBox advancedSweep_SweepPlane_Use_CheckBox; + JCheckBox advancedSweep_SweepPlane_PushOnly_CheckBox; + JCheckBox advancedSweep_SweepPlane_PullOnly_CheckBox; + JCheckBox advancedSweep_SweepPlane_ShortestEdgeFirst_CheckBox; + JCheckBox advancedSweep_SweepPlane_SmallestFaceFirst_CheckBox; + JCheckBox advancedSweep_SweepPlane_SmallestDistFirst_CheckBox; + + JCheckBox advancedSweep_SweepRotate_Use_CheckBox; + JLabel advancedSweep_SweepRotate_maxAngleLabel; + DoubleJSlider advancedSweep_SweepRotate_maxAngleSlider; + JTextField advancedSweep_SweepRotate_maxAngleTextField; + JCheckBox advancedSweep_SweepRotate_MinDistFirst_CheckBox; + JCheckBox advancedSweep_SweepRotate_MinAngleFirst_CheckBox; + JCheckBox advancedSweep_SweepRotate_SmallestFaceFirst_CheckBox; + + CityDoctorModel model; + + + private final int stdBtnHeight = 25; + private final int stdBtnWidth = 300; + + // UV MinPoint als Attribut, da auch ausserhalb von setBuildigunstoOrigin darauf zugegriffen weden soll + Vertex minPoint; + + private void doClicksLeft() // Method for preadjusting settings + { + + IVExportCheckBox.doClick(); + STEPExportCheckBox.doClick(); + //exportValidBuildingsOnlyCheckBox.doClick(); + + moveBuildingBlockToOriginCheckBox.doClick(); + //printBuildingInfoCheckBox.doClick(); + printStatusCheckBox.doClick(); + + //printAllCheckBox.doClick(); + //exportIntermediateStagesCompleteCheckBox.doClick(); + + } + + private void doClicksRight() // Method for preadjusting settings + { + + //boolCheckBox.doClick(); + //minkowskiCheckBox.doClick(); + mergeCheckBox.doClick(); + //advancedSweep_Planarity_Use_CheckBox.doClick(); + advancedSweep_SweepPlane_Use_CheckBox.doClick(); + //advancedSweep_SweepRotate_Use_CheckBox.doClick(); + + //printBoolInfoCheckBox.doClick(); + //printMinkowskiInfoCheckBox.doClick(); + //printMergeInfoCheckBox.doClick(); + //advancedSweep_General_printInfoCheckBox.doClick(); + + rotateMinkowskiCube.doClick(); + //boolMinkowski_exportIntermediateStagesCheckBox.doClick(); + //merge_exportIntermediateStagesCheckBox.doClick(); + //advancedSweep_General_exportIntermediateStagesCheckBox.doClick(); + + //advancedSweep_General_printFilterReasonInfoCheckBox.doClick(); + //advancedSweep_Planarity_IgnoreMultiplePoints_CheckBox.doClick(); + //advancedSweep_SweepPlane_PullOnly_CheckBox.doClick(); + //advancedSweep_SweepPlane_PushOnly_CheckBox.doClick(); + + } + + public AutoProWindow(CityDoctorModel model) { + CppInitializer.initCpp(); + this.model = model; + + // ########################## + // Einstellungen des Fensters + // ########################## + int width = 1000; + int height = 800; + + this.setSize(width, height); + // das Fenster soll zentriert sein + int x = 0, y = 0; + // TODO : !!! + /* + if (mainWindow != null) { + x = ((mainWindow.getWidth() / 2) - (width / 2)) + mainWindow.getX(); + y = ((mainWindow.getHeight() / 2) - (height / 2)) + + mainWindow.getY(); + } + */ + this.setLocation(x, y); + + this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + this.setTitle(CDAutoProGuiMessages + .getString("AutoProWindow.PreferencesWindowTitle")); //$NON-NLS-1$ + this.setModal(true); + + // ------------------------------------------------------------------------- + + // Das Fenster aus Splitter und Buttons zusammenbauen + Container contentPane = this.getContentPane(); + contentPane.setLayout(new BorderLayout()); + + JPanel leftPanel = createLeftPanel(); + contentPane.add(leftPanel, BorderLayout.WEST); + + JPanel rightPanel = createRightPanel(); + contentPane.add(rightPanel, BorderLayout.EAST); + + JPanel bottomPanel = createBottomPanel(); + contentPane.add(bottomPanel, BorderLayout.SOUTH); + + } + + /** + * Diese Methode schließt das Fenster. + */ + private void close() { + this.dispose(); + } + + /** @throws FileNotFoundException + */ + private void startCppAutoProMethods() throws FileNotFoundException { + + List buildings = this.model.getBuildings(); + + List geometryList = getAllGeometriesOfSelectedBuildings(buildings); + setBuildingsToOrigin(geometryList); + + AutoPro autopro = new AutoPro(); + autopro.createCppObject(); + + // fill information for AutoProSettings + AutoProSettingsExport autoProSettingsExport = new AutoProSettingsExport(); + autoProSettingsExport.setExportMesh(MeshExportCheckBox.isSelected()); + autoProSettingsExport.setMeshFileName(meshFileInfo.getName()); + autoProSettingsExport.setMeshFilePath(meshFileInfo.getPath()); + autoProSettingsExport.setExportIV(IVExportCheckBox.isSelected()); + autoProSettingsExport.setIVFileName(ivFileInfo.getName()); + autoProSettingsExport.setIVFilePath(ivFileInfo.getPath()); + autoProSettingsExport.setExportSTEP(STEPExportCheckBox.isSelected()); + autoProSettingsExport.setSTEPFileName(stepFileInfo.getName()); + autoProSettingsExport.setSTEPFilePath(stepFileInfo.getPath()); + autoProSettingsExport.setExportCityGML(false/*GMLExportCheckBox.isSelected()*/); + autoProSettingsExport.setCityGMLFileName(gmlFileInfo.getName()); + autoProSettingsExport.setCityGMLFilePath(gmlFileInfo.getPath()); + autoProSettingsExport.setExportValidBuildingsOnly(exportValidBuildingsOnlyCheckBox.isSelected()); + autoProSettingsExport.setMoveBuildingsToOrigin(moveBuildingBlockToOriginCheckBox.isSelected()); + autoProSettingsExport.setExportIntermediateStagesComplete(exportIntermediateStagesCompleteCheckBox.isSelected()); + autoProSettingsExport.setExportStepWithOneSolidPerBuilding(exportStepWithOneSolidPerBuilding.isSelected()); + autoProSettingsExport.setMinDistToOrigin_X(minDistToOrigin_X); + autoProSettingsExport.setMinDistToOrigin_Y(minDistToOrigin_Y); + autoProSettingsExport.setMinDistToOrigin_Z(minDistToOrigin_Z); + autoProSettingsExport.createCppObject(); + + AutoProSettingsGeneral autoProSettingsGeneral = new AutoProSettingsGeneral(); + autoProSettingsGeneral.setPrintBuildingInfo(printBuildingInfoCheckBox.isSelected()); + autoProSettingsGeneral.setPrintStatus(printStatusCheckBox.isSelected()); + autoProSettingsGeneral.setPrintSmallestAngle(printSmallestAngleCheckBox.isSelected()); + autoProSettingsGeneral.setPrintNumberOfSmallAngles(printNumberOfSmallAnglesCheckBox.isSelected()); + autoProSettingsGeneral.setSmallAngleTolerance(smallAngleTolerance); + autoProSettingsGeneral.setPrintShortestEdge(printShortestEdgeCheckBox.isSelected()); + autoProSettingsGeneral.setPrintNumberOfShortEdges(printNumberOfShortEdgesCheckBox.isSelected()); + autoProSettingsGeneral.setShortEdgesTolerance(shortEdgesTolerance); + autoProSettingsGeneral.setPrintVolume(printVolumeCheckBox.isSelected()); + autoProSettingsGeneral.setPrintNumberOfFacesAndVertices(printNumberOfFacesAndVerticesCheckBox.isSelected()); + autoProSettingsGeneral.createCppObject(); + + AutoProSettingsBool autoProSettingsBool = new AutoProSettingsBool(); + autoProSettingsBool.setUseBool(boolCheckBox.isSelected()); + autoProSettingsBool.setPrintBoolInfo(printBoolInfoCheckBox.isSelected()); + autoProSettingsBool.setUseMinkowski(minkowskiCheckBox.isSelected()); + autoProSettingsBool.setPrintMinkowskiInfo(printMinkowskiInfoCheckBox.isSelected()); + autoProSettingsBool.setMinkowskiCubeSize(minkowskiCubeSlider.getScaledValue()); + autoProSettingsBool.setExportIntermediateStages(boolMinkowski_exportIntermediateStagesCheckBox.isSelected()); + autoProSettingsBool.setRotateMinkowskiCube(rotateMinkowskiCube.isSelected()); + autoProSettingsBool.createCppObject(); + + AutoProSettingsMerge autoProSettingsMerge = new AutoProSettingsMerge(); + autoProSettingsMerge.setUseMerge(mergeCheckBox.isSelected()); + autoProSettingsMerge.setExportIntermediateStages(merge_exportIntermediateStagesCheckBox.isSelected()); + autoProSettingsMerge.setPrintMergeInfo(printMergeInfoCheckBox.isSelected()); + autoProSettingsMerge.setEps_PointEquality(eps_PointEqualitySlider.getScaledValue()); + autoProSettingsMerge.setEps_Parallelity(eps_ParallelitySlider.getScaledValue()); + autoProSettingsMerge.createCppObject(); + + + AutoProSettingsAdvancedSweep autoProSettingsAdvancedSweep = new AutoProSettingsAdvancedSweep(); + autoProSettingsAdvancedSweep.set_advancedSweep_General_printInfo( advancedSweep_General_printInfoCheckBox.isSelected()); + autoProSettingsAdvancedSweep.set_advancedSweep_General_printFilterReasonInfo( advancedSweep_General_printFilterReasonInfoCheckBox.isSelected()); + autoProSettingsAdvancedSweep.set_advancedSweep_General_exportIntermediateStages( advancedSweep_General_exportIntermediateStagesCheckBox.isSelected()); + autoProSettingsAdvancedSweep.set_advancedSweep_General_minEdgeLength( advancedSweep_General_minEdgeLengthSlider.getScaledValue()); + autoProSettingsAdvancedSweep.set_advancedSweep_General_maxEdgeLength( advancedSweep_General_maxEdgeLengthSlider.getScaledValue()); + autoProSettingsAdvancedSweep.set_advancedSweep_General_minDistToSweep( advancedSweep_General_minDistToSweepSlider.getScaledValue()); + + autoProSettingsAdvancedSweep.set_advancedSweep_Planarity_Use( advancedSweep_Planarity_Use_CheckBox.isSelected()); + autoProSettingsAdvancedSweep.set_advancedSweep_Planarity_IgnoreMultiplePoints( advancedSweep_Planarity_IgnoreMultiplePoints_CheckBox.isSelected()); + autoProSettingsAdvancedSweep.set_advancedSweep_Planarity_PlanarityTolerance( advancedSweep_Planarity_PlanarityTolerance_SweepSlider.getScaledValue()); + + autoProSettingsAdvancedSweep.set_advancedSweep_SweepPlane_Use( advancedSweep_SweepPlane_Use_CheckBox.isSelected()); + autoProSettingsAdvancedSweep.set_advancedSweep_SweepPlane_PushOnly( advancedSweep_SweepPlane_PushOnly_CheckBox.isSelected()); + autoProSettingsAdvancedSweep.set_advancedSweep_SweepPlane_PullOnly( advancedSweep_SweepPlane_PullOnly_CheckBox.isSelected()); + autoProSettingsAdvancedSweep.set_advancedSweep_SweepPlane_ShortestEdgeFirst( advancedSweep_SweepPlane_ShortestEdgeFirst_CheckBox.isSelected()); + autoProSettingsAdvancedSweep.set_advancedSweep_SweepPlane_SmallestFaceFirst( advancedSweep_SweepPlane_SmallestFaceFirst_CheckBox.isSelected()); + autoProSettingsAdvancedSweep.set_advancedSweep_SweepPlane_SmallestDistFirst( advancedSweep_SweepPlane_SmallestDistFirst_CheckBox.isSelected()); + + autoProSettingsAdvancedSweep.set_advancedSweep_SweepRotate_Use( advancedSweep_SweepRotate_Use_CheckBox.isSelected()); + autoProSettingsAdvancedSweep.set_advancedSweep_SweepRotate_maxAngle( advancedSweep_SweepRotate_maxAngleSlider.getScaledValue()); + autoProSettingsAdvancedSweep.set_advancedSweep_SweepRotate_SmallestDistFirst( advancedSweep_SweepRotate_MinDistFirst_CheckBox.isSelected()); + autoProSettingsAdvancedSweep.set_advancedSweep_SweepRotate_SmallestAngleFirst( advancedSweep_SweepRotate_MinAngleFirst_CheckBox.isSelected()); + autoProSettingsAdvancedSweep.set_advancedSweep_SweepRotate_SmallestFaceFirst( advancedSweep_SweepRotate_SmallestFaceFirst_CheckBox.isSelected()); + + autoProSettingsAdvancedSweep.createCppObject(); + + // end fill information for AutoProSettings + + System.out.println(" " + geometryList.size() + " geometry features counted"); + + List features = new ArrayList<>(); + for(Geometry geometry: geometryList) + { + + try { + String gmlId_string = geometry.getGmlId().getGmlString(); + CppFeature feature = new CppFeature( gmlId_string); + feature.setGeometry( geometry ); + feature.setLoD(geometry.getLod()); + features.add(feature); + autopro.ap_addFeature(feature); + } catch (IllegalStateException e) { + // Auto-generated catch block + e.printStackTrace(); + } catch (NativePointerCastException e) { + // Auto-generated catch block + e.printStackTrace(); + } catch (IllegalArgumentException e) { + // Auto-generated catch block + e.printStackTrace(); + } catch (NativeException e) { + // Auto-generated catch block + e.printStackTrace(); + } + } + + try { + + autopro.ap_setSettingsExport(autoProSettingsExport); + autopro.ap_setSettingsGeneral(autoProSettingsGeneral); + autopro.ap_setSettingsBool(autoProSettingsBool); + autopro.ap_setSettingsMerge(autoProSettingsMerge); + autopro.ap_setSettingsAdvancedSweep(autoProSettingsAdvancedSweep); + + //autopro.ap_setSettings(autoProSettings); + autopro.ap_applyAutoProMethods(); + + + + + + + Map geometryMap = new HashMap<>(); + for (Geometry geom : geometryList) { + geometryMap.put(geom.getGmlId().getGmlString(), geom); + } + for (CppFeature feature : features) { + + long healResult = autopro.ap_getHealResult(feature); + + //long healResult = feature.getHealResult(); + if (healResult == 0) { + feature.disposeCppObject(); + continue; + } + System.out.println("merge changes into geometry "); + + CppHealResult res = new CppHealResult(healResult); + String gmlId = feature.getType(); + Geometry geometry = geometryMap.get(gmlId); + res.mergeIntoGeometry(geometry); + if (geometry.getPolygons().isEmpty()) { + CityObject parent = geometry.getParent(); + parent.getGeometries().remove(geometry); + if (parent instanceof BuildingPart && parent.getGeometries().isEmpty()) { + BuildingPart part = (BuildingPart) parent; + Building building = part.getParent(); + building.getBuildingParts().remove(part); + if (building.getBuildingParts().isEmpty() && building.getGeometries().isEmpty()) { + model.getBuildings().remove(building); + } + } else if (parent instanceof Building && parent.getGeometries().isEmpty()) { + Building building = (Building) parent; + if (building.getBuildingParts().isEmpty()) { + model.getBuildings().remove(building); + } + } + } + feature.disposeCppObject(); + } + + autopro.disposeCppObject(); + + } catch (IllegalStateException e) { + // Auto-generated catch block + e.printStackTrace(); + } catch (NativePointerCastException e) { + // Auto-generated catch block + e.printStackTrace(); + } catch (IllegalArgumentException e) { + // Auto-generated catch block + e.printStackTrace(); + } catch (NativeException e) { + // Auto-generated catch block + e.printStackTrace(); + } + + + // UV + // Hier ist der Step-Export abgeschlossen + // Translationsvektor an die Datei STEPObject_End.stp anhängen + //System.out.println("Translationsvektor " + minPoint.getX()+ " " + minPoint.getY() + " " +minPoint.getZ()); + + String text = "/*" + "Translationsvektor " + minPoint.getX()+ " " + minPoint.getY() + " " +minPoint.getZ() + "*/"; + String destination = stepFileInfo.getPath() +"STEPObject_End.stp"; + //System.out.println(destination); + + try { + FileWriter fw = new FileWriter(destination, true); // true: öffnen zum Anhängen von weiteren Zeilen + BufferedWriter ausgabe = new BufferedWriter(fw); + ausgabe.write(text); + ausgabe.newLine(); + ausgabe.close(); + + } catch (IOException e1) { + System.out.println("Couldn't open "+ destination); + } + + } + + private void setBuildingsToOrigin(List geometryList) + { + //UV + //Vertex minPoint = new Vertex(Double.MAX_VALUE ,Double.MAX_VALUE ,Double.MAX_VALUE , false); + // Jetzt als Attribut der Klasse + minPoint = new Vertex(Double.MAX_VALUE ,Double.MAX_VALUE ,Double.MAX_VALUE); + minDistToOrigin_X = Double.MAX_VALUE; + minDistToOrigin_Y = Double.MAX_VALUE; + minDistToOrigin_Z = Double.MAX_VALUE; + + + for(Geometry geometry: geometryList) + { + Collection vertexCollection = geometry.getVertices(); + for (Vertex vertex : vertexCollection) { + if (minPoint.getX() > vertex.getX()) + { + minPoint.setX(vertex.getX()); + minDistToOrigin_X = vertex.getX(); + } + if (minPoint.getY() > vertex.getY()) + { + minPoint.setY(vertex.getY()); + minDistToOrigin_Y = vertex.getY(); + } + if (minPoint.getZ() > vertex.getZ()) + { + minPoint.setZ(vertex.getZ()); + minDistToOrigin_Z = vertex.getZ(); + } + } + } + + // UV 200609 + // Ausgabe Translationsvektor + // System.out.println("Translationsvektor " + minPoint.getX()+ " " + minPoint.getY() + " " +minPoint.getZ()); + // + + for(Geometry geometry: geometryList) + { + Collection vertexCollection = geometry.getVertices(); + for (Vertex vertex : vertexCollection) { + vertex.setX(vertex.getX()-minPoint.getX()); + vertex.setY(vertex.getY()-minPoint.getY()); + vertex.setZ(vertex.getZ()-minPoint.getZ()); + } + } + } + + private List getAllGeometriesOfSelectedBuildings(List buildings) + { + + List geometryList = new ArrayList(); + + for (Building building : buildings) + { + + if (0 != building.getGeometries().size() ) + { + for(Geometry geometry : building.getGeometries()) + { + Geometry geometryCopy = geometry; + geometryCopy.setGmlId(building.getGmlId()); + geometryList.add(geometryCopy); + } + } + else if(0 != building.getBuildingParts().size()) + { + for(BuildingPart buildingPart: building.getBuildingParts()) + { + for(Geometry geometry : buildingPart.getGeometries()) + { + Geometry geometryCopy = geometry; + geometryCopy.setGmlId(buildingPart.getGmlId()); + geometryList.add(geometryCopy); + } + } + } + else if(0 != building.getBuildingInstallations().size()) + { + for(Installation buildingInstallation: building.getBuildingInstallations()) + { + for(Geometry geometry : buildingInstallation.getGeometries()) + { + Geometry geometryCopy = geometry; + geometryCopy.setGmlId(buildingInstallation.getGmlId()); + geometryList.add(geometryCopy); + } + } + } + else + { + System.out.println("WARNING : start : no GeometryList for this Building"); + } + } + + return geometryList; + } + + private JPanel createLeftPanel() { + JPanel panel = new JPanel(); + panel.setAlignmentX(TOP_ALIGNMENT); + + // create panels + JPanel exportMeshPanel = createExportMeshPanel(); + JPanel exportIVPanel = createExportIVPanel(); + JPanel exportSTEPPanel = createExportSTEPPanel(); + JPanel exportGMLPanel = createExportGMLPanel(); + JPanel exportSettingsPanel = createExportSettingsPanel(); + JPanel printInfoPanel = createPrintInfoPanel(); + JPanel comparisonPanel = createComparisonPanel(); + + doClicksLeft(); + + // create layout + GridBagLayout gbl = new GridBagLayout(); + panel.setLayout(gbl); + + // anchor the panel in the top left corner + GridBagConstraints c = new GridBagConstraints(); + c.fill = GridBagConstraints.HORIZONTAL; + c.gridx = 0; + c.gridy = 0; + c.anchor = GridBagConstraints.FIRST_LINE_START; + // create some distance to the panel above and below + c.insets = new Insets(10, 0, 10, 0); + + c.gridx = 0; + c.gridy = 1; + // create some distance to the panel below + c.insets = new Insets(0, 0, 10, 0); + panel.add(exportMeshPanel, c); + + c.gridx = 0; + c.gridy = 2; + // create some distance to the panel below + c.insets = new Insets(0, 0, 10, 0); + panel.add(exportIVPanel, c); + + c.gridx = 0; + c.gridy = 3; + // create some distance to the panel below + c.insets = new Insets(0, 0, 10, 0); + panel.add(exportSTEPPanel, c); + +/* + c.gridx = 0; + c.gridy = 4; + // create some distance to the panel below + c.insets = new Insets(0, 0, 10, 0); + panel.add(exportGMLPanel, c); +*/ + + c.gridx = 0; + c.gridy = 5; + // create some distance to the panel below + c.insets = new Insets(0, 0, 10, 0); + panel.add(exportSettingsPanel, c); + + c.gridx = 0; + c.gridy = 6; + // create some distance to the panel below + c.insets = new Insets(0, 0, 10, 0); + panel.add(printInfoPanel, c); + + c.gridx = 0; + c.gridy = 7; + // create some distance to the panel below + c.insets = new Insets(0, 0, 10, 0); + panel.add(comparisonPanel, c); + + return panel; + } + + private JPanel createRightPanel() { + JPanel panel = new JPanel(); + panel.setAlignmentX(TOP_ALIGNMENT); + panel.setAlignmentY(LEFT_ALIGNMENT); + + // create panels + JPanel useBoolPanel = createBoolPanel(); + JPanel useMergePanel = createMergePanel(); + JPanel useAdvancedSweepPanel_General = createAdvancedSweepPanel_General(); + JPanel useAdvancedSweepPanel_Planarity = createAdvancedSweepPanel_Planarity(); + JPanel useAdvancedSweepPanel_SweepPlane = createAdvancedSweepPanel_SweepPlane(); + JPanel useAdvancedSweepPanel_SweepRotate = createAdvancedSweepPanel_SweepRotate(); + + doClicksRight(); + + // create layout + GridBagLayout gbl = new GridBagLayout(); + panel.setLayout(gbl); + + // anchor the panel in the top left corner + GridBagConstraints c = new GridBagConstraints(); + c.fill = GridBagConstraints.HORIZONTAL; + c.gridx = 0; + c.gridy = 0; + c.anchor = GridBagConstraints.FIRST_LINE_START; + // create some distance to the panel above and below + c.insets = new Insets(10, 0, 10, 0); + + + c.gridx = 0; + c.gridy = 1; + // create some distance to the panel below + c.insets = new Insets(0, 0, 10, 0); + panel.add(useBoolPanel, c); + + c.gridx = 0; + c.gridy = 2; + // create some distance to the panel below + c.insets = new Insets(0, 0, 10, 0); + panel.add(useMergePanel, c); +/* + c.gridx = 0; + c.gridy = 3; + // create some distance to the panel below + c.insets = new Insets(0, 0, 10, 0); + panel.add(useSweepPlanePanel, c); +*/ + + c.gridx = 0; + c.gridy = 5; + // create some distance to the panel below + c.insets = new Insets(0, 0, 10, 0); + panel.add(useAdvancedSweepPanel_General, c); + + c.gridx = 0; + c.gridy = 6; + // create some distance to the panel below + c.insets = new Insets(0, 0, 10, 0); + panel.add(useAdvancedSweepPanel_Planarity, c); + + c.gridx = 0; + c.gridy = 7; + // create some distance to the panel below + c.insets = new Insets(0, 0, 10, 0); + panel.add(useAdvancedSweepPanel_SweepPlane, c); + + c.gridx = 0; + c.gridy = 8; + // create some distance to the panel below + c.insets = new Insets(0, 0, 10, 0); + panel.add(useAdvancedSweepPanel_SweepRotate, c); + + + return panel; + } + + private JPanel createBottomPanel() { + JPanel panel = new JPanel(); + panel.setAlignmentX(TOP_ALIGNMENT); + panel.setAlignmentY(LEFT_ALIGNMENT); + + // create panels + JPanel executeButtonPanel = createExecuteButtonPanel(); + + // create layout + GridBagLayout gbl = new GridBagLayout(); + panel.setLayout(gbl); + + // anchor the panel in the top left corner + GridBagConstraints c = new GridBagConstraints(); + c.fill = GridBagConstraints.HORIZONTAL; + c.gridx = 0; + c.gridy = 0; + c.anchor = GridBagConstraints.FIRST_LINE_START; + // create some distance to the panel above and below + c.insets = new Insets(10, 0, 10, 0); + + + c.gridx = 0; + c.gridy = 1; + c.insets = new Insets(0, 0, 0, 0); + panel.add(executeButtonPanel, c); + + return panel; + } + + private JPanel createExportMeshPanel() { + // panel with surrounding border + JPanel exportMeshPanel = new JPanel(); + exportMeshPanel.setBorder(createTitledBorder(CDAutoProGuiMessages + .getString("AutoProWindow.exportMeshPanel"))); + + // ----------------------------- CONTENT ----------------------------- + // -------------------------------------------------------------------- + // Mesh Export Check Box + // -------------------------------------------------------------------- + MeshExportCheckBox = new JCheckBox( + CDAutoProGuiMessages.getString("AutoProWindow.exportMeshButtonTitle")); + MeshExportCheckBox.setToolTipText(CDAutoProGuiMessages + .getString("AutoProWindow.exportMeshButtonDescription")); + MeshExportCheckBox.setSelected(false); + + MeshExportCheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (((JCheckBox) e.getSource()).isSelected()) { + MeshExportTextField.setEnabled(true); + MeshExportJButton.setEnabled(true); + } else { + MeshExportTextField.setEnabled(false); + MeshExportJButton.setEnabled(false); + } + } + }); + + // -------------------------------------------------------------------- + // optional filename text field + // -------------------------------------------------------------------- + + MeshExportTextField = new JTextField(); + MeshExportTextField + .setToolTipText(CDAutoProGuiMessages + .getString("AutoProWindow.meshExportFileNameDescription")); + MeshExportTextField.setText(meshFileInfo.getString()); + MeshExportTextField.setEnabled(false); + + MeshExportTextField.addKeyListener(new KeyAdapter(){ + @Override + public void keyReleased(KeyEvent ke) { + if(ke.getKeyCode() == KeyEvent.VK_ENTER) + { + MeshExportTextField.setText(" Please Use The Button on the right ->"); + } + } + }); + + // -------------------------------------------------------------------- + // optional file search button + // -------------------------------------------------------------------- + MeshExportJButton = new JButton("Set Path and Name"); + MeshExportJButton + .setToolTipText(CDAutoProGuiMessages + .getString("AutoProWindow.meshExportPathDescription")); + MeshExportJButton.setEnabled(false); + + MeshExportJButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + meshFileInfo = saveFileDialog( + ".iv", + "IV (*.iv)", + "Speicher Mesh unter ..."); + if (null != meshFileInfo.getPath()) { + MeshExportTextField.setText(meshFileInfo.getString()); + } + } + }); + + // -------------------------------------------------------------------- + // create layout + // -------------------------------------------------------------------- + GroupLayout panelLayout = new GroupLayout(exportMeshPanel); + exportMeshPanel.setLayout(panelLayout); + + panelLayout.setHorizontalGroup(panelLayout + .createSequentialGroup() + .addGap(7) + // make the left side of the component align the buttons of the + // above check related panel + .addGroup( + panelLayout + .createParallelGroup( + GroupLayout.Alignment.LEADING) + .addComponent(MeshExportCheckBox)) + .addGroup( + panelLayout + .createParallelGroup( + GroupLayout.Alignment.LEADING) + .addComponent(MeshExportTextField)) + .addGap(10) + // pushes the file searchbuttons away + .addGroup( + panelLayout + .createParallelGroup( + GroupLayout.Alignment.LEADING) + .addComponent(MeshExportJButton)).addGap(10)); + + panelLayout.setVerticalGroup(panelLayout + .createSequentialGroup() + .addGap(10) + // get some space between border and components + .addGroup( + panelLayout + .createParallelGroup( + GroupLayout.Alignment.BASELINE) + .addComponent(MeshExportCheckBox) + .addComponent(MeshExportTextField) + .addComponent(MeshExportJButton)) + ); + + return exportMeshPanel; + } + + private JPanel createExportIVPanel() { + // panel with surrounding border + JPanel exportIVPanel = new JPanel(); + exportIVPanel.setBorder(createTitledBorder(CDAutoProGuiMessages + .getString("AutoProWindow.exportIVPanel"))); + + // ----------------------------- CONTENT ----------------------------- + // -------------------------------------------------------------------- + // IV Export Check Box + // -------------------------------------------------------------------- + IVExportCheckBox = new JCheckBox( + CDAutoProGuiMessages.getString("AutoProWindow.exportIVButtonTitle")); + IVExportCheckBox.setToolTipText(CDAutoProGuiMessages + .getString("AutoProWindow.exportIVButtonDescription")); + IVExportCheckBox.setSelected(false); + + IVExportCheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (((JCheckBox) e.getSource()).isSelected()) { + IVExportTextField.setEnabled(true); + IVExportJButton.setEnabled(true); + } else { + IVExportTextField.setEnabled(false); + IVExportJButton.setEnabled(false); + } + } + }); + + + // -------------------------------------------------------------------- + // optional filename text field + // -------------------------------------------------------------------- + IVExportTextField = new JTextField(); + IVExportTextField + .setToolTipText(CDAutoProGuiMessages + .getString("AutoProWindow.ivExportFileNameDescription")); + IVExportTextField.setText(ivFileInfo.getString()); + IVExportTextField.setEnabled(false); + + IVExportTextField.addKeyListener(new KeyAdapter(){ + @Override + public void keyReleased(KeyEvent ke) { + if(ke.getKeyCode() == KeyEvent.VK_ENTER) + { + IVExportTextField.setText(" Please Use The Button on the right ->"); + } + } + }); + + // -------------------------------------------------------------------- + // optional file search button + // -------------------------------------------------------------------- + IVExportJButton = new JButton("Set Path and Name"); + IVExportJButton + .setToolTipText(CDAutoProGuiMessages + .getString("AutoProWindow.ivExportPathDescription")); + IVExportJButton.setEnabled(false); + + IVExportJButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + ivFileInfo = saveFileDialog( + ".iv", + "IV (*.iv)", + "Speicher BRep Modell unter ..."); + if (null != ivFileInfo.getPath()) { + IVExportTextField.setText(ivFileInfo.getString()); + } + } + }); + + + // -------------------------------------------------------------------- + // create layout + // -------------------------------------------------------------------- + GroupLayout panelLayout = new GroupLayout(exportIVPanel); + exportIVPanel.setLayout(panelLayout); + + panelLayout.setHorizontalGroup(panelLayout + .createSequentialGroup() + .addGap(7) + // make the left side of the component align the buttons of the + // above check related panel + .addGroup( + panelLayout + .createParallelGroup( + GroupLayout.Alignment.LEADING) + .addComponent(IVExportCheckBox)) + .addGroup( + panelLayout + .createParallelGroup( + GroupLayout.Alignment.LEADING) + .addComponent(IVExportTextField)) + .addGap(10) + // pushes the file searchbuttons away + .addGroup( + panelLayout + .createParallelGroup( + GroupLayout.Alignment.LEADING) + .addComponent(IVExportJButton)).addGap(10)); + + panelLayout.setVerticalGroup(panelLayout + .createSequentialGroup() + .addGap(10) + // get some space between border and components + .addGroup( + panelLayout + .createParallelGroup( + GroupLayout.Alignment.BASELINE) + .addComponent(IVExportCheckBox) + .addComponent(IVExportTextField) + .addComponent(IVExportJButton)) + ); + + return exportIVPanel; + } + + private JPanel createExportSTEPPanel() { + // panel with surrounding border + JPanel exportSTEPPanel = new JPanel(); + exportSTEPPanel.setBorder(createTitledBorder(CDAutoProGuiMessages + .getString("AutoProWindow.exportSTEPPanel"))); + + // ----------------------------- CONTENT ----------------------------- + // -------------------------------------------------------------------- + // STEP Export Check Box + // -------------------------------------------------------------------- + STEPExportCheckBox = new JCheckBox( + CDAutoProGuiMessages.getString("AutoProWindow.exportSTEPButtonTitle")); + STEPExportCheckBox.setToolTipText(CDAutoProGuiMessages + .getString("AutoProWindow.exportSTEPButtonDescription")); + STEPExportCheckBox.setSelected(false); + + STEPExportCheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (((JCheckBox) e.getSource()).isSelected()) { + STEPExportTextField.setEnabled(true); + STEPExportJButton.setEnabled(true); + } else { + STEPExportTextField.setEnabled(false); + STEPExportJButton.setEnabled(false); + } + } + }); + + // -------------------------------------------------------------------- + // optional filename text field + // -------------------------------------------------------------------- + STEPExportTextField = new JTextField(); + STEPExportTextField + .setToolTipText(CDAutoProGuiMessages + .getString("AutoProWindow.stepExportFileNameDescription")); + STEPExportTextField.setText(stepFileInfo.getString()); + STEPExportTextField.setEnabled(false); + + STEPExportTextField.addKeyListener(new KeyAdapter(){ + @Override + public void keyReleased(KeyEvent ke) { + if(ke.getKeyCode() == KeyEvent.VK_ENTER) + { + STEPExportTextField.setText(" Please Use The Button on the right ->"); + } + } + }); + + // -------------------------------------------------------------------- + // optional file search button + // -------------------------------------------------------------------- + STEPExportJButton = new JButton("Set Path and Name"); + STEPExportJButton + .setToolTipText(CDAutoProGuiMessages + .getString("AutoProWindow.stepExportPathDescription")); + STEPExportJButton.setEnabled(false); + + STEPExportJButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + stepFileInfo = saveFileDialog( + ".stp", + "STEP (*.stp)", + "Speicher STEP Modell unter ..."); + if (null != stepFileInfo.getPath()) { + STEPExportTextField.setText(stepFileInfo.getString()); + } + } + }); + + // -------------------------------------------------------------------- + // create layout + // -------------------------------------------------------------------- + GroupLayout panelLayout = new GroupLayout(exportSTEPPanel); + exportSTEPPanel.setLayout(panelLayout); + + panelLayout.setHorizontalGroup(panelLayout + .createSequentialGroup() + .addGap(7) + // make the left side of the component align the buttons of the + // above check related panel + .addGroup( + panelLayout + .createParallelGroup( + GroupLayout.Alignment.LEADING) + .addComponent(STEPExportCheckBox)) + .addGroup( + panelLayout + .createParallelGroup( + GroupLayout.Alignment.LEADING) + .addComponent(STEPExportTextField)) + .addGap(10) + // pushes the file searchbuttons away + .addGroup( + panelLayout + .createParallelGroup( + GroupLayout.Alignment.LEADING) + .addComponent(STEPExportJButton)).addGap(10)); + + panelLayout.setVerticalGroup(panelLayout + .createSequentialGroup() + .addGap(10) + // get some space between border and components + .addGroup( + panelLayout + .createParallelGroup( + GroupLayout.Alignment.BASELINE) + .addComponent(STEPExportCheckBox) + .addComponent(STEPExportTextField) + .addComponent(STEPExportJButton)) + ); + + return exportSTEPPanel; + } + + private JPanel createExportGMLPanel() { + // panel with surrounding border + JPanel exportGMLPanel = new JPanel(); + exportGMLPanel.setBorder(createTitledBorder(CDAutoProGuiMessages + .getString("AutoProWindow.exportGMLPanel"))); + + // ----------------------------- CONTENT ----------------------------- + // -------------------------------------------------------------------- + // cityGML Export Check Box + // -------------------------------------------------------------------- + GMLExportCheckBox = new JCheckBox( + CDAutoProGuiMessages.getString("AutoProWindow.exportGMLButtonTitle")); + GMLExportCheckBox.setToolTipText(CDAutoProGuiMessages + .getString("AutoProWindow.exportGMLButtonDescription")); + GMLExportCheckBox.setSelected(false); + + GMLExportCheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (((JCheckBox) e.getSource()).isSelected()) { + GMLExportTextField.setEnabled(true); + GMLExportJButton.setEnabled(true); + } else { + GMLExportTextField.setEnabled(false); + GMLExportJButton.setEnabled(false); + } + } + }); + + // -------------------------------------------------------------------- + // optional filename text field + // -------------------------------------------------------------------- + GMLExportTextField = new JTextField(); + GMLExportTextField + .setToolTipText(CDAutoProGuiMessages + .getString("AutoProWindow.gmlExportFileNameDescription")); + GMLExportTextField.setText(gmlFileInfo.getString()); + GMLExportTextField.setEnabled(false); + + GMLExportTextField.addKeyListener(new KeyAdapter(){ + @Override + public void keyReleased(KeyEvent ke) { + if(ke.getKeyCode() == KeyEvent.VK_ENTER) + { + GMLExportTextField.setText(" Please Use The Button on the right ->"); + } + } + }); + + // -------------------------------------------------------------------- + // optional file search button + // -------------------------------------------------------------------- + GMLExportJButton = new JButton("Set Path and Name"); + GMLExportJButton + .setToolTipText(CDAutoProGuiMessages + .getString("AutoProWindow.gmlExportPathDescription")); + GMLExportJButton.setEnabled(false); + + GMLExportJButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + gmlFileInfo = saveFileDialog( + ".gml", + "GML (*.gml)", + "Speicher CityGML Modell unter ..."); + if (null != gmlFileInfo.getPath()) { + GMLExportTextField.setText(gmlFileInfo.getString()); + } + } + }); + + // -------------------------------------------------------------------- + // create layout + // -------------------------------------------------------------------- + GroupLayout panelLayout = new GroupLayout(exportGMLPanel); + exportGMLPanel.setLayout(panelLayout); + + panelLayout.setHorizontalGroup(panelLayout + .createSequentialGroup() + .addGap(7) + // make the left side of the component align the buttons of the + // above check related panel + .addGroup( + panelLayout + .createParallelGroup( + GroupLayout.Alignment.LEADING) + .addComponent(GMLExportCheckBox)) + .addGroup( + panelLayout + .createParallelGroup( + GroupLayout.Alignment.LEADING) + .addComponent(GMLExportTextField)) + .addGap(10) + // pushes the file searchbuttons away + .addGroup( + panelLayout + .createParallelGroup( + GroupLayout.Alignment.LEADING) + .addComponent(GMLExportJButton)).addGap(10)); + + panelLayout.setVerticalGroup(panelLayout + .createSequentialGroup() + .addGap(10) + // get some space between border and components + .addGroup( + panelLayout + .createParallelGroup( + GroupLayout.Alignment.BASELINE) + .addComponent(GMLExportCheckBox) + .addComponent(GMLExportTextField) + .addComponent(GMLExportJButton)) + ); + + return exportGMLPanel; + } + + private JPanel createExportSettingsPanel() { + // panel with surrounding border + JPanel exportSettingsPanel = new JPanel(); + exportSettingsPanel.setBorder(createTitledBorder(CDAutoProGuiMessages + .getString("AutoProWindow.exportSettingsPanel"))); + + // ----------------------------- CONTENT ----------------------------- + + // -------------------------------------------------------------------- + // create export only valid buildings Check Box + // -------------------------------------------------------------------- + + exportValidBuildingsOnlyCheckBox = new JCheckBox("valid only"); + exportValidBuildingsOnlyCheckBox.setToolTipText("export only valid buildings"); + exportValidBuildingsOnlyCheckBox.setEnabled(true); + + // -------------------------------------------------------------------- + // create move buildings to Origin Check Box + // -------------------------------------------------------------------- + + moveBuildingBlockToOriginCheckBox = new JCheckBox("move Building to Origin"); + moveBuildingBlockToOriginCheckBox.setToolTipText("move Building to Origin"); + moveBuildingBlockToOriginCheckBox.setEnabled(true); + + // -------------------------------------------------------------------- + // create export intermediate stages Check Box + // -------------------------------------------------------------------- + + exportIntermediateStagesCompleteCheckBox = new JCheckBox("export Intermediate Stages"); + exportIntermediateStagesCompleteCheckBox.setToolTipText("export Intermediate Stages "); + exportIntermediateStagesCompleteCheckBox.setEnabled(true); + exportIntermediateStagesCompleteCheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (((JCheckBox) e.getSource()).isSelected()) { + + } else { + advancedSweep_General_exportIntermediateStagesCheckBox.setSelected(false); + } + } + }); + + // -------------------------------------------------------------------- + // create export intermediate stages Check Box + // -------------------------------------------------------------------- + + exportStepWithOneSolidPerBuilding = new JCheckBox("One Solid Per Building"); + exportStepWithOneSolidPerBuilding.setToolTipText("export Step Files with one Solid per Building"); + exportStepWithOneSolidPerBuilding.setEnabled(true); + + + // -------------------------------------------------------------------- + // create layout + // -------------------------------------------------------------------- + GroupLayout panelLayout = new GroupLayout(exportSettingsPanel); + exportSettingsPanel.setLayout(panelLayout); + + panelLayout.setHorizontalGroup(panelLayout.createSequentialGroup() + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(exportValidBuildingsOnlyCheckBox) + .addComponent(moveBuildingBlockToOriginCheckBox) + .addComponent(exportIntermediateStagesCompleteCheckBox) + .addComponent(exportStepWithOneSolidPerBuilding) + ) + ); + + panelLayout.setVerticalGroup(panelLayout.createSequentialGroup() + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(exportValidBuildingsOnlyCheckBox) + ) + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(moveBuildingBlockToOriginCheckBox) + ) + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(exportIntermediateStagesCompleteCheckBox) + ) + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(exportStepWithOneSolidPerBuilding) + ) + ); + + + return exportSettingsPanel; + } + + private JPanel createPrintInfoPanel() { + // panel with surrounding border + JPanel printInfoPanel = new JPanel(); + printInfoPanel.setBorder(createTitledBorder(CDAutoProGuiMessages + .getString("AutoProWindow.printInfoPanel"))); + + // ----------------------------- CONTENT ----------------------------- + + // -------------------------------------------------------------------- + // create Check Box and TextFields + // -------------------------------------------------------------------- + + printBuildingInfoCheckBox = new JCheckBox("Print Building"); + printBuildingInfoCheckBox.setToolTipText("Print Building"); + printBuildingInfoCheckBox.setEnabled(true); + + printStatusCheckBox = new JCheckBox("Print Status"); + printStatusCheckBox.setToolTipText("Print Status"); + printStatusCheckBox.setEnabled(true); + + // -------------------------------------------------------------------- + // create layout + // -------------------------------------------------------------------- + GroupLayout panelLayout = new GroupLayout(printInfoPanel); + printInfoPanel.setLayout(panelLayout); + + panelLayout.setHorizontalGroup(panelLayout.createSequentialGroup() + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(printBuildingInfoCheckBox) + ) + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(printStatusCheckBox) + ) + ); + + panelLayout.setVerticalGroup(panelLayout.createSequentialGroup() + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(printBuildingInfoCheckBox) + .addComponent(printStatusCheckBox) + ) + ); + + + + return printInfoPanel; + } + + private JPanel createComparisonPanel() { + // panel with surrounding border + JPanel comparisonPanel = new JPanel(); + comparisonPanel.setBorder(createTitledBorder(CDAutoProGuiMessages + .getString("AutoProWindow.comparisonPanel"))); + + // ----------------------------- CONTENT ----------------------------- + + // -------------------------------------------------------------------- + // create Check Box and TextFields + // -------------------------------------------------------------------- + + printAllCheckBox = new JCheckBox("Print all"); + printAllCheckBox.setToolTipText("Print all"); + printAllCheckBox.setEnabled(true); + + printAllCheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (((JCheckBox) e.getSource()).isSelected()) { + printSmallestAngleCheckBox.setSelected(true); + printNumberOfSmallAnglesCheckBox.setSelected(true); + printShortestEdgeCheckBox.setSelected(true); + printNumberOfShortEdgesCheckBox.setSelected(true); + printVolumeCheckBox.setSelected(true); + printNumberOfFacesAndVerticesCheckBox.setSelected(true); + } else { + printSmallestAngleCheckBox.setSelected(false); + printNumberOfSmallAnglesCheckBox.setSelected(false); + printShortestEdgeCheckBox.setSelected(false); + printNumberOfShortEdgesCheckBox.setSelected(false); + printVolumeCheckBox.setSelected(false); + printNumberOfFacesAndVerticesCheckBox.setSelected(false); + } + } + }); + + printSmallestAngleCheckBox = new JCheckBox("Print smallest angle"); + printSmallestAngleCheckBox.setToolTipText("Print smallest angle between two edges to JAVA console"); + printSmallestAngleCheckBox.setEnabled(true); + + printNumberOfSmallAnglesCheckBox = new JCheckBox("Print number of small angles"); + printNumberOfSmallAnglesCheckBox.setToolTipText("Print number of small angles to JAVA console"); + printNumberOfSmallAnglesCheckBox.setEnabled(true); + + final DecimalFormat dfSmallAngleTol = new DecimalFormat("0.###"); + smallAngleTolerance = 10; + smallAngleToleranceTextField = new JTextField(); + smallAngleToleranceTextField.setToolTipText("angles between two edges smaller than this value (angle in degrees) are printed to JAVA console (DON'T FORGET TO PRESS ENTER)"); + smallAngleToleranceTextField.setEnabled(true); + smallAngleToleranceTextField.setText(dfSmallAngleTol.format(smallAngleTolerance)); + + smallAngleToleranceTextField.addKeyListener(new KeyAdapter(){ + @Override + public void keyReleased(KeyEvent ke) { + if(ke.getKeyCode() == KeyEvent.VK_ENTER) + { + String typed = smallAngleToleranceTextField.getText(); + if(typed.matches("\\d+(\\.\\d*)?")) { + double value = Double.parseDouble(typed); + smallAngleTolerance = value; + } + else if (typed.matches("\\d+(\\,\\d*)?")) { + double value = Double.parseDouble(typed.replace(',','.')); + smallAngleTolerance = value; + return; + } + else + { + return; + } + } + } + }); + + printShortestEdgeCheckBox = new JCheckBox("Print shortest edge"); + printShortestEdgeCheckBox.setToolTipText("Print shortest edge to Java console"); + printShortestEdgeCheckBox.setEnabled(true); + + printNumberOfShortEdgesCheckBox = new JCheckBox("Print number of short edges"); + printNumberOfShortEdgesCheckBox.setToolTipText("Print number of short edges to JAVA console"); + printNumberOfShortEdgesCheckBox.setEnabled(true); + + final DecimalFormat dfShortEdgeTol = new DecimalFormat("0.###"); + shortEdgesTolerance = 2.0; + shortEdgesToleranceTextField = new JTextField(); + shortEdgesToleranceTextField.setToolTipText("edges smaller than this value (size in meter) are printed to JAVA console (DON'T FORGET TO PRESS ENTER)"); + shortEdgesToleranceTextField.setEnabled(true); + shortEdgesToleranceTextField.setText(dfShortEdgeTol.format(shortEdgesTolerance)); + + + shortEdgesToleranceTextField.addKeyListener(new KeyAdapter(){ + @Override + public void keyReleased(KeyEvent ke) { + if(ke.getKeyCode() == KeyEvent.VK_ENTER) + { + String typed = shortEdgesToleranceTextField.getText(); + if(typed.matches("\\d+(\\.\\d*)?")) { + double value = Double.parseDouble(typed); + shortEdgesTolerance = value; + } + else if (typed.matches("\\d+(\\,\\d*)?")) { + double value = Double.parseDouble(typed.replace(',','.')); + shortEdgesTolerance = value; + return; + } + else + { + return; + } + } + } + }); + + printVolumeCheckBox = new JCheckBox("Print volume"); + printVolumeCheckBox.setToolTipText("Print volume of building(s) to JAVA console"); + printVolumeCheckBox.setEnabled(true); + + printNumberOfFacesAndVerticesCheckBox = new JCheckBox("Print number of faces and vertices "); + printNumberOfFacesAndVerticesCheckBox.setToolTipText("Print the number of faces and vertices for each building before and after the simplification"); + printNumberOfFacesAndVerticesCheckBox.setEnabled(true); + + // -------------------------------------------------------------------- + // create layout + // -------------------------------------------------------------------- + GroupLayout panelLayout = new GroupLayout(comparisonPanel); + comparisonPanel.setLayout(panelLayout); + + panelLayout.setHorizontalGroup(panelLayout.createSequentialGroup() + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(printAllCheckBox) + .addComponent(printSmallestAngleCheckBox) + .addComponent(printShortestEdgeCheckBox) + .addComponent(printVolumeCheckBox) + ) + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + //.addComponent(NULL) + .addComponent(printNumberOfSmallAnglesCheckBox) + .addComponent(printNumberOfShortEdgesCheckBox) + .addComponent(printNumberOfFacesAndVerticesCheckBox) + ) + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + //.addComponent(NULL) + .addComponent(smallAngleToleranceTextField) + .addComponent(shortEdgesToleranceTextField) + //.addComponent(NULL) + ) + ); + + panelLayout.setVerticalGroup(panelLayout.createSequentialGroup() + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(printAllCheckBox) + //.addComponent(NULL) + //.addComponent(NULL) + ) + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(printSmallestAngleCheckBox) + .addComponent(printNumberOfSmallAnglesCheckBox) + .addComponent(smallAngleToleranceTextField) + ) + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(printShortestEdgeCheckBox) + .addComponent(printNumberOfShortEdgesCheckBox) + .addComponent(shortEdgesToleranceTextField) + ) + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(printVolumeCheckBox) + .addComponent(printNumberOfFacesAndVerticesCheckBox) + //.addComponent(NULL) + ) + ); + + + + return comparisonPanel; + } + + private JPanel createBoolPanel() { + // panel with surrounding border + JPanel boolPanel = new JPanel(); + boolPanel.setBorder(createTitledBorder(CDAutoProGuiMessages + .getString("AutoProWindow.boolPanel"))); + + // ----------------------------- CONTENT ----------------------------- + // -------------------------------------------------------------------- + // use bool Check Box + // -------------------------------------------------------------------- + boolCheckBox = new JCheckBox( + CDAutoProGuiMessages.getString("AutoProWindow.boolButtonTitle")); + boolCheckBox.setToolTipText(CDAutoProGuiMessages + .getString("AutoProWindow.boolButtonDescription")); + boolCheckBox.setSelected(false); + + boolCheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (((JCheckBox) e.getSource()).isSelected()) { + printBoolInfoCheckBox.setEnabled(true); + } else { + printBoolInfoCheckBox.setEnabled(false); + } + } + }); + + // -------------------------------------------------------------------- + // print bool info Check Box + // -------------------------------------------------------------------- + printBoolInfoCheckBox = new JCheckBox( + CDAutoProGuiMessages.getString("AutoProWindow.boolInfoButtonTitle")); + printBoolInfoCheckBox.setToolTipText(CDAutoProGuiMessages + .getString("AutoProWindow.boolInfoButtonDescription")); + printBoolInfoCheckBox.setSelected(false); + printBoolInfoCheckBox.setEnabled(false); + + // -------------------------------------------------------------------- + // use minkowski Check Box + // -------------------------------------------------------------------- + minkowskiCheckBox = new JCheckBox( + CDAutoProGuiMessages.getString("AutoProWindow.minkowskiButtonTitle")); + minkowskiCheckBox.setToolTipText(CDAutoProGuiMessages + .getString("AutoProWindow.minkowskiButtonDescription")); + minkowskiCheckBox.setSelected(false); + + minkowskiCheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (((JCheckBox) e.getSource()).isSelected()) { + printMinkowskiInfoCheckBox.setEnabled(true); + minkowskiCubeLabel.setEnabled(true); + minkowskiCubeSlider.setEnabled(true); + minkowskiCubeTextField.setEnabled(true); + rotateMinkowskiCube.setEnabled(true); + } else { + printMinkowskiInfoCheckBox.setEnabled(false); + minkowskiCubeLabel.setEnabled(false); + minkowskiCubeSlider.setEnabled(false); + minkowskiCubeTextField.setEnabled(false); + rotateMinkowskiCube.setEnabled(false); + } + } + }); + + // -------------------------------------------------------------------- + // print minkowski info Check Box + // -------------------------------------------------------------------- + printMinkowskiInfoCheckBox = new JCheckBox( + CDAutoProGuiMessages.getString("AutoProWindow.minkowskiInfoButtonTitle")); + printMinkowskiInfoCheckBox.setToolTipText(CDAutoProGuiMessages + .getString("AutoProWindow.minkowskiInfoButtonDescription")); + printMinkowskiInfoCheckBox.setSelected(false); + printMinkowskiInfoCheckBox.setEnabled(false); + + + // -------------------------------------------------------------------- + // minkowskiCubeSize label, slider and text field + // -------------------------------------------------------------------- + + minkowskiCubeLabel = new JLabel("minkowskiCube Size"); + minkowskiCubeLabel.setEnabled(false); + + final DecimalFormat dfMinkowskiCube = new DecimalFormat("0.#"); + + minkowskiCubeSlider = new DoubleJSlider(1, 50, 20, 10); + minkowskiCubeSlider.setToolTipText(CDAutoProGuiMessages + .getString("AutoProWindow.minkowskiCubeSliderDescription")); + minkowskiCubeSlider.setMinorTickSpacing(10); + minkowskiCubeSlider.setPaintTicks(true); + minkowskiCubeSlider.setEnabled(false); + + minkowskiCubeTextField = new JTextField(); + minkowskiCubeTextField + .setToolTipText(CDAutoProGuiMessages + .getString("AutoProWindow.minkowskiCubeDescription")); + minkowskiCubeTextField.setEnabled(false); + minkowskiCubeTextField.setText(dfMinkowskiCube.format(minkowskiCubeSlider.getScaledValue())); + + + minkowskiCubeSlider.addChangeListener(new ChangeListener(){ + @Override + public void stateChanged(ChangeEvent e) { + minkowskiCubeTextField.setText(dfMinkowskiCube.format(minkowskiCubeSlider.getScaledValue())); + } + }); + minkowskiCubeTextField.addKeyListener(new KeyAdapter(){ + @Override + public void keyReleased(KeyEvent ke) { + if(ke.getKeyCode() == KeyEvent.VK_ENTER) + { + String typed = minkowskiCubeTextField.getText(); + if(typed.matches("\\d+(\\.\\d*)?")) { + double value = Double.parseDouble(typed)*minkowskiCubeSlider.scale; + minkowskiCubeSlider.setValue((int)value); + } + else if (typed.matches("\\d+(\\,\\d*)?")) { + double value = Double.parseDouble(typed.replace(',','.'))*minkowskiCubeSlider.scale; + minkowskiCubeSlider.setValue((int)value); + return; + } + else + { + return; + } + } + } + }); + + // -------------------------------------------------------------------- + // export intermediate stages Check Box + // -------------------------------------------------------------------- + boolMinkowski_exportIntermediateStagesCheckBox = new JCheckBox( + CDAutoProGuiMessages.getString("AutoProWindow.boolMinkowski_exportIntermediateStagesCheckBoxButtonTitle")); + boolMinkowski_exportIntermediateStagesCheckBox.setToolTipText(CDAutoProGuiMessages + .getString("AutoProWindow.boolMinkowski_exportIntermediateStagesCheckBoxButtonDescription")); + + + + // -------------------------------------------------------------------- + // rotate Minkowski Cube Check Box + // -------------------------------------------------------------------- + rotateMinkowskiCube = new JCheckBox("rotateMinkowskiCube"); + rotateMinkowskiCube.setToolTipText("rotates the Minkowski-Cube corresponding to the biggest wallface if selcted"); + + + + // -------------------------------------------------------------------- + // create layout + // -------------------------------------------------------------------- + GroupLayout panelLayout = new GroupLayout(boolPanel); + boolPanel.setLayout(panelLayout); + + panelLayout.setHorizontalGroup(panelLayout.createSequentialGroup() + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(boolCheckBox) + .addComponent(minkowskiCheckBox) + .addComponent(minkowskiCubeLabel) + ) + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(boolMinkowski_exportIntermediateStagesCheckBox) + .addComponent(rotateMinkowskiCube) + .addComponent(minkowskiCubeSlider) + ) + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(printBoolInfoCheckBox) + .addComponent(printMinkowskiInfoCheckBox) + .addComponent(minkowskiCubeTextField) + ) + ); + + panelLayout.setVerticalGroup(panelLayout.createSequentialGroup() + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(boolCheckBox) + .addComponent(boolMinkowski_exportIntermediateStagesCheckBox) + .addComponent(printBoolInfoCheckBox) + ) + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(minkowskiCheckBox) + .addComponent(rotateMinkowskiCube) + .addComponent(printMinkowskiInfoCheckBox) + ) + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(minkowskiCubeLabel) + .addComponent(minkowskiCubeSlider) + .addComponent(minkowskiCubeTextField) + ) + ); + + return boolPanel; + } + + private JPanel createMergePanel() { + // panel with surrounding border + JPanel mergePanel = new JPanel(); + mergePanel.setBorder(createTitledBorder(CDAutoProGuiMessages + .getString("AutoProWindow.mergePanel"))); + + // ----------------------------- CONTENT ----------------------------- + // -------------------------------------------------------------------- + // use merge Check Box + // -------------------------------------------------------------------- + mergeCheckBox = new JCheckBox( + CDAutoProGuiMessages.getString("AutoProWindow.mergeButtonTitle")); + mergeCheckBox.setToolTipText(CDAutoProGuiMessages + .getString("AutoProWindow.mergeButtonDescription")); + mergeCheckBox.setSelected(false); + + mergeCheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (((JCheckBox) e.getSource()).isSelected()) { + printMergeInfoCheckBox.setEnabled(true); + merge_exportIntermediateStagesCheckBox.setEnabled(true); + eps_PointEqualityLabel.setEnabled(true); + eps_PointEqualitySlider.setEnabled(true); + eps_PointEqualityTextField.setEnabled(true); + eps_ParallelityLabel.setEnabled(true); + eps_ParallelitySlider.setEnabled(true); + eps_ParallelityTextField.setEnabled(true); + } else { + printMergeInfoCheckBox.setEnabled(false); + merge_exportIntermediateStagesCheckBox.setEnabled(false); + eps_PointEqualityLabel.setEnabled(false); + eps_PointEqualitySlider.setEnabled(false); + eps_PointEqualityTextField.setEnabled(false); + eps_ParallelityLabel.setEnabled(false); + eps_ParallelitySlider.setEnabled(false); + eps_ParallelityTextField.setEnabled(false); + } + } + }); + + // -------------------------------------------------------------------- + // export intermediate stages Check Box + // -------------------------------------------------------------------- + + merge_exportIntermediateStagesCheckBox = new JCheckBox( + CDAutoProGuiMessages.getString("AutoProWindow.merge_exportIntermediateStagesCheckBoxButtonTitle")); + merge_exportIntermediateStagesCheckBox.setToolTipText(CDAutoProGuiMessages + .getString("AutoProWindow.merge_exportIntermediateStagesCheckBoxButtonDescription")); + merge_exportIntermediateStagesCheckBox.setEnabled(false); + + // -------------------------------------------------------------------- + // print merge info Check Box + // -------------------------------------------------------------------- + printMergeInfoCheckBox = new JCheckBox( + CDAutoProGuiMessages.getString("AutoProWindow.mergeInfoButtonTitle")); + printMergeInfoCheckBox.setToolTipText(CDAutoProGuiMessages + .getString("AutoProWindow.mergeInfoButtonDescription")); + printMergeInfoCheckBox.setSelected(false); + + // -------------------------------------------------------------------- + // eps_PointEquality label, slider and text field + // -------------------------------------------------------------------- + + eps_PointEqualityLabel = new JLabel("Point Equality Tolerance"); + eps_PointEqualityLabel.setEnabled(false); + + final DecimalFormat dfAngleTol_PE = new DecimalFormat("0.###"); + + eps_PointEqualitySlider = new DoubleJSlider(0, 1000, 20, 1000); + eps_PointEqualitySlider.setToolTipText(CDAutoProGuiMessages + .getString("AutoProWindow.eps_PointEqualitySliderDescription")); + eps_PointEqualitySlider.setMinorTickSpacing(100); + eps_PointEqualitySlider.setPaintTicks(true); + eps_PointEqualitySlider.setEnabled(false); + + eps_PointEqualityTextField = new JTextField(); + eps_PointEqualityTextField + .setToolTipText(CDAutoProGuiMessages + .getString("AutoProWindow.eps_PointEqualityDescription")); + eps_PointEqualityTextField.setEnabled(false); + eps_PointEqualityTextField.setText(dfAngleTol_PE.format(eps_PointEqualitySlider.getScaledValue())); + + + eps_PointEqualitySlider.addChangeListener(new ChangeListener(){ + @Override + public void stateChanged(ChangeEvent e) { + eps_PointEqualityTextField.setText(dfAngleTol_PE.format(eps_PointEqualitySlider.getScaledValue())); + } + }); + eps_PointEqualityTextField.addKeyListener(new KeyAdapter(){ + @Override + public void keyReleased(KeyEvent ke) { + if(ke.getKeyCode() == KeyEvent.VK_ENTER) + { + String typed = eps_PointEqualityTextField.getText(); + if(typed.matches("\\d+(\\.\\d*)?")) { + double value = Double.parseDouble(typed)*eps_PointEqualitySlider.scale; + eps_PointEqualitySlider.setValue((int)value); + } + else if (typed.matches("\\d+(\\,\\d*)?")) { + double value = Double.parseDouble(typed.replace(',','.'))*eps_PointEqualitySlider.scale; + eps_PointEqualitySlider.setValue((int)value); + return; + } + else + { + return; + } + } + } + }); + + // -------------------------------------------------------------------- + // eps_Parallelity label, slider and text field + // -------------------------------------------------------------------- + + eps_ParallelityLabel = new JLabel("Parallelity Tolerance"); + eps_ParallelityLabel.setEnabled(false); + + + final DecimalFormat dfAngleTol_P = new DecimalFormat("0.###"); + + eps_ParallelitySlider = new DoubleJSlider(0, 1000, 10, 1000); + eps_ParallelitySlider.setToolTipText(CDAutoProGuiMessages + .getString("AutoProWindow.eps_ParallelitySliderDescription")); + eps_ParallelitySlider.setMinorTickSpacing(100); + eps_ParallelitySlider.setPaintTicks(true); + eps_ParallelitySlider.setEnabled(false); + + eps_ParallelityTextField = new JTextField(); + eps_ParallelityTextField + .setToolTipText(CDAutoProGuiMessages + .getString("AutoProWindow.eps_ParallelityDescription")); + eps_ParallelityTextField.setEnabled(false); + eps_ParallelityTextField.setText(dfAngleTol_P.format(eps_ParallelitySlider.getScaledValue())); + + eps_ParallelitySlider.addChangeListener(new ChangeListener(){ + @Override + public void stateChanged(ChangeEvent e) { + eps_ParallelityTextField.setText(dfAngleTol_P.format(eps_ParallelitySlider.getScaledValue())); + } + }); + eps_ParallelityTextField.addKeyListener(new KeyAdapter(){ + @Override + public void keyReleased(KeyEvent ke) { + if(ke.getKeyCode() == KeyEvent.VK_ENTER) + { + String typed = eps_ParallelityTextField.getText(); + if(typed.matches("\\d+(\\.\\d*)?")) { + double value = Double.parseDouble(typed)*eps_ParallelitySlider.scale; + eps_ParallelitySlider.setValue((int)value); + } + else if (typed.matches("\\d+(\\,\\d*)?")) { + double value = Double.parseDouble(typed.replace(',','.'))*eps_ParallelitySlider.scale; + eps_ParallelitySlider.setValue((int)value); + return; + } + else + { + return; + } + } + } + }); + + // -------------------------------------------------------------------- + // create layout + // -------------------------------------------------------------------- + GroupLayout panelLayout = new GroupLayout(mergePanel); + mergePanel.setLayout(panelLayout); + + panelLayout.setHorizontalGroup(panelLayout.createSequentialGroup() + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(mergeCheckBox) + .addComponent(eps_PointEqualityLabel) + .addComponent(eps_ParallelityLabel) + ) + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(merge_exportIntermediateStagesCheckBox) + .addComponent(eps_PointEqualitySlider) + .addComponent(eps_ParallelitySlider) + ) + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(printMergeInfoCheckBox) + .addComponent(eps_PointEqualityTextField) + .addComponent(eps_ParallelityTextField) + ) + ); + + panelLayout.setVerticalGroup(panelLayout.createSequentialGroup() + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(mergeCheckBox) + .addComponent(merge_exportIntermediateStagesCheckBox) + .addComponent(printMergeInfoCheckBox) + ) + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(eps_PointEqualityLabel) + .addComponent(eps_PointEqualitySlider) + .addComponent(eps_PointEqualityTextField) + ) + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(eps_ParallelityLabel) + .addComponent(eps_ParallelitySlider) + .addComponent(eps_ParallelityTextField) + ) + ); + + return mergePanel; + } + + private JPanel createAdvancedSweepPanel_General() { + // panel with surrounding border + JPanel advancedSweepPanel_General = new JPanel(); + advancedSweepPanel_General.setBorder(createTitledBorder("Advanced Sweep - General Settings")); + + + // -------------------------------------------------------------------- + // create print info Check Box + // -------------------------------------------------------------------- + + advancedSweep_General_printInfoCheckBox = new JCheckBox("Print Sweep info"); + advancedSweep_General_printInfoCheckBox.setToolTipText("Print Sweep info into JAVA terminal"); + advancedSweep_General_printInfoCheckBox.setEnabled(true); + advancedSweep_General_printInfoCheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (((JCheckBox) e.getSource()).isSelected()) { + advancedSweep_General_printFilterReasonInfoCheckBox.setEnabled(true); + } else { + advancedSweep_General_printFilterReasonInfoCheckBox.setEnabled(false); + advancedSweep_General_printFilterReasonInfoCheckBox.setSelected(false); + } + } + }); + // -------------------------------------------------------------------- + // create print info Check Box + // -------------------------------------------------------------------- + + advancedSweep_General_printFilterReasonInfoCheckBox = new JCheckBox("Print Filter Reasons info"); + advancedSweep_General_printFilterReasonInfoCheckBox.setToolTipText("prints the reason why faces cannot by sweep faces"); + advancedSweep_General_printFilterReasonInfoCheckBox.setEnabled(false); + + + // -------------------------------------------------------------------- + // create Label for export intermediate stages + // -------------------------------------------------------------------- + + advancedSweep_General_exportIntermediateStagesCheckBox = new JCheckBox("export stages"); + advancedSweep_General_exportIntermediateStagesCheckBox.setToolTipText("exports the intermediate stages within the sweep algorithms"); + advancedSweep_General_exportIntermediateStagesCheckBox.setEnabled(true); + advancedSweep_General_exportIntermediateStagesCheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (((JCheckBox) e.getSource()).isSelected()) { + exportIntermediateStagesCompleteCheckBox.setSelected(true); + } + } + }); + + // -------------------------------------------------------------------- + // write minEdgeLength Slider + // -------------------------------------------------------------------- + + final DecimalFormat dfMinEdge = new DecimalFormat("0.###"); + + + advancedSweep_General_minEdgeLengthLabel = new JLabel("Min Edge Length"); + + advancedSweep_General_minEdgeLengthSlider = new DoubleJSlider(0, 500, 200, 100); + advancedSweep_General_minEdgeLengthSlider.setToolTipText("after the sweep there shouldn't be no edge left smaller that this value (size in meter)"); + advancedSweep_General_minEdgeLengthSlider.setMinorTickSpacing(100); + advancedSweep_General_minEdgeLengthSlider.setPaintTicks(true); + advancedSweep_General_minEdgeLengthSlider.setEnabled(true); + + advancedSweep_General_minEdgeLengthTextField = new JTextField(); + advancedSweep_General_minEdgeLengthTextField.setToolTipText("after the sweep there shouldn't be no edge left smaller that this value (size in meter)"); + advancedSweep_General_minEdgeLengthTextField.setEnabled(true); + advancedSweep_General_minEdgeLengthTextField.setText(dfMinEdge.format(advancedSweep_General_minEdgeLengthSlider.getScaledValue())); + + advancedSweep_General_minEdgeLengthSlider.addChangeListener(new ChangeListener(){ + @Override + public void stateChanged(ChangeEvent e) { + advancedSweep_General_minEdgeLengthTextField.setText(dfMinEdge.format(advancedSweep_General_minEdgeLengthSlider.getScaledValue())); + } + }); + advancedSweep_General_minEdgeLengthTextField.addKeyListener(new KeyAdapter(){ + @Override + public void keyReleased(KeyEvent ke) { + if(ke.getKeyCode() == KeyEvent.VK_ENTER) + { + String typed = advancedSweep_General_minEdgeLengthTextField.getText(); + if(typed.matches("\\d+(\\.\\d*)?")) { + double value = Double.parseDouble(typed)*advancedSweep_General_minEdgeLengthSlider.scale; + advancedSweep_General_minEdgeLengthSlider.setValue((int)value); + } + else if (typed.matches("\\d+(\\,\\d*)?")) { + double value = Double.parseDouble(typed.replace(',','.'))*advancedSweep_General_minEdgeLengthSlider.scale; + advancedSweep_General_minEdgeLengthSlider.setValue((int)value); + return; + } + else + { + return; + } + } + } + }); + + + // -------------------------------------------------------------------- + // write maxEdgeLength Slider + // -------------------------------------------------------------------- + + final DecimalFormat dfMaxEdge = new DecimalFormat("0.###"); + + advancedSweep_General_maxEdgeLengthLabel = new JLabel("Max Edge Length"); + + advancedSweep_General_maxEdgeLengthSlider = new DoubleJSlider(0, 2000, 500, 100); + advancedSweep_General_maxEdgeLengthSlider.setToolTipText("sweep is not allowed if an edge longer than this would completely dissapear (size in meter)"); + advancedSweep_General_maxEdgeLengthSlider.setMinorTickSpacing(100); + advancedSweep_General_maxEdgeLengthSlider.setPaintTicks(true); + advancedSweep_General_maxEdgeLengthSlider.setEnabled(true); + + advancedSweep_General_maxEdgeLengthTextField = new JTextField(); + advancedSweep_General_maxEdgeLengthTextField.setToolTipText("sweep is not allowed if an edge longer than this would completely dissapear (size in meter)"); + advancedSweep_General_maxEdgeLengthTextField.setEnabled(true); + advancedSweep_General_maxEdgeLengthTextField.setText(dfMaxEdge.format(advancedSweep_General_maxEdgeLengthSlider.getScaledValue())); + + advancedSweep_General_maxEdgeLengthSlider.addChangeListener(new ChangeListener(){ + @Override + public void stateChanged(ChangeEvent e) { + advancedSweep_General_maxEdgeLengthTextField.setText(dfMinEdge.format(advancedSweep_General_maxEdgeLengthSlider.getScaledValue())); + } + }); + advancedSweep_General_maxEdgeLengthTextField.addKeyListener(new KeyAdapter(){ + @Override + public void keyReleased(KeyEvent ke) { + if(ke.getKeyCode() == KeyEvent.VK_ENTER) + { + String typed = advancedSweep_General_maxEdgeLengthTextField.getText(); + if(typed.matches("\\d+(\\.\\d*)?")) { + double value = Double.parseDouble(typed)*advancedSweep_General_maxEdgeLengthSlider.scale; + advancedSweep_General_maxEdgeLengthSlider.setValue((int)value); + } + else if (typed.matches("\\d+(\\,\\d*)?")) { + double value = Double.parseDouble(typed.replace(',','.'))*advancedSweep_General_maxEdgeLengthSlider.scale; + advancedSweep_General_maxEdgeLengthSlider.setValue((int)value); + return; + } + else + { + return; + } + } + } + }); + + + // -------------------------------------------------------------------- + // write minDistToSweep Slider + // -------------------------------------------------------------------- + + final DecimalFormat dfMinDist = new DecimalFormat("0.####"); + + + advancedSweep_General_minDistToSweepLabel = new JLabel("Min Dist"); + + advancedSweep_General_minDistToSweepSlider = new DoubleJSlider(0, 10000, 1, 10000); + advancedSweep_General_minDistToSweepSlider.setToolTipText("No Sweep, if sweep would be less than this value (size in meter)"); + advancedSweep_General_minDistToSweepSlider.setMinorTickSpacing(10000); + advancedSweep_General_minDistToSweepSlider.setPaintTicks(true); + advancedSweep_General_minDistToSweepSlider.setEnabled(true); + + advancedSweep_General_minDistToSweepTextField = new JTextField(); + advancedSweep_General_minDistToSweepTextField.setToolTipText("No Sweep, if sweep would be less than this value (size in meter)"); + advancedSweep_General_minDistToSweepTextField.setEnabled(true); + advancedSweep_General_minDistToSweepTextField.setText(dfMinDist.format(advancedSweep_General_minDistToSweepSlider.getScaledValue())); + + advancedSweep_General_minDistToSweepSlider.addChangeListener(new ChangeListener(){ + @Override + public void stateChanged(ChangeEvent e) { + advancedSweep_General_minDistToSweepTextField.setText(dfMinDist.format(advancedSweep_General_minDistToSweepSlider.getScaledValue())); + } + }); + advancedSweep_General_minDistToSweepTextField.addKeyListener(new KeyAdapter(){ + @Override + public void keyReleased(KeyEvent ke) { + if(ke.getKeyCode() == KeyEvent.VK_ENTER) + { + String typed = advancedSweep_General_minDistToSweepTextField.getText(); + if(typed.matches("\\d+(\\.\\d*)?")) { + double value = Double.parseDouble(typed)*advancedSweep_General_minDistToSweepSlider.scale; + advancedSweep_General_minDistToSweepSlider.setValue((int)value); + } + else if (typed.matches("\\d+(\\,\\d*)?")) { + double value = Double.parseDouble(typed.replace(',','.'))*advancedSweep_General_minDistToSweepSlider.scale; + advancedSweep_General_minDistToSweepSlider.setValue((int)value); + return; + } + else + { + return; + } + } + } + }); + + + + // -------------------------------------------------------------------- + // create layout + // -------------------------------------------------------------------- + GroupLayout panelLayout = new GroupLayout(advancedSweepPanel_General); + advancedSweepPanel_General.setLayout(panelLayout); + + panelLayout.setHorizontalGroup(panelLayout.createSequentialGroup() + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(advancedSweep_General_printInfoCheckBox) + .addComponent(advancedSweep_General_minEdgeLengthLabel) + .addComponent(advancedSweep_General_maxEdgeLengthLabel) + .addComponent(advancedSweep_General_minDistToSweepLabel) + ) + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(advancedSweep_General_printFilterReasonInfoCheckBox) + .addComponent(advancedSweep_General_minEdgeLengthSlider) + .addComponent(advancedSweep_General_maxEdgeLengthSlider) + .addComponent(advancedSweep_General_minDistToSweepSlider) + ) + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(advancedSweep_General_exportIntermediateStagesCheckBox) + .addComponent(advancedSweep_General_minEdgeLengthTextField) + .addComponent(advancedSweep_General_maxEdgeLengthTextField) + .addComponent(advancedSweep_General_minDistToSweepTextField) + ) + ); + + panelLayout.setVerticalGroup(panelLayout.createSequentialGroup() + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(advancedSweep_General_printInfoCheckBox) + .addComponent(advancedSweep_General_printFilterReasonInfoCheckBox) + .addComponent(advancedSweep_General_exportIntermediateStagesCheckBox) + ) + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(advancedSweep_General_minEdgeLengthLabel) + .addComponent(advancedSweep_General_minEdgeLengthSlider) + .addComponent(advancedSweep_General_minEdgeLengthTextField) + ) + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(advancedSweep_General_maxEdgeLengthLabel) + .addComponent(advancedSweep_General_maxEdgeLengthSlider) + .addComponent(advancedSweep_General_maxEdgeLengthTextField) + ) + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(advancedSweep_General_minDistToSweepLabel) + .addComponent(advancedSweep_General_minDistToSweepSlider) + .addComponent(advancedSweep_General_minDistToSweepTextField) + ) + ); + + + return advancedSweepPanel_General; + } + + private JPanel createAdvancedSweepPanel_Planarity() { + // panel with surrounding border + JPanel advancedSweepPanel_Planarity = new JPanel(); + advancedSweepPanel_Planarity.setBorder(createTitledBorder("Advanced Sweep Settings - Planarity")); + + // ----------------------------- CONTENT ----------------------------- + + // -------------------------------------------------------------------- + // use Planarity Check Box + // -------------------------------------------------------------------- + advancedSweep_Planarity_Use_CheckBox = new JCheckBox("Use Planarity"); + advancedSweep_Planarity_Use_CheckBox.setToolTipText("Use planarity Algorithm"); + advancedSweep_Planarity_Use_CheckBox.setSelected(false); + + advancedSweep_Planarity_Use_CheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (((JCheckBox) e.getSource()).isSelected()) { + advancedSweep_Planarity_IgnoreMultiplePoints_CheckBox.setEnabled(true); + advancedSweep_Planarity_PlanarityTolerance_SweepLabel.setEnabled(true); + advancedSweep_Planarity_PlanarityTolerance_SweepSlider.setEnabled(true); + advancedSweep_Planarity_PlanarityTolerance_TextField.setEnabled(true); + } else { + advancedSweep_Planarity_IgnoreMultiplePoints_CheckBox.setEnabled(false); + advancedSweep_Planarity_PlanarityTolerance_SweepLabel.setEnabled(false); + advancedSweep_Planarity_PlanarityTolerance_SweepSlider.setEnabled(false); + advancedSweep_Planarity_PlanarityTolerance_TextField.setEnabled(false); + } + } + }); + + + + // -------------------------------------------------------------------- + // create ignore multiple Points CheckBox + // -------------------------------------------------------------------- + + advancedSweep_Planarity_IgnoreMultiplePoints_CheckBox = new JCheckBox("Ignore Mult Points"); + advancedSweep_Planarity_IgnoreMultiplePoints_CheckBox.setToolTipText("If unselected the target plane will be created through fixpoints"); + advancedSweep_Planarity_IgnoreMultiplePoints_CheckBox.setSelected(false); + advancedSweep_Planarity_IgnoreMultiplePoints_CheckBox.setEnabled(false); + + + // -------------------------------------------------------------------- + // write planarity Tolerance Slider + // -------------------------------------------------------------------- + + final DecimalFormat dfTolerance = new DecimalFormat("0.############"); + + advancedSweep_Planarity_PlanarityTolerance_SweepLabel = new JLabel("Planarity Tolerance"); + + advancedSweep_Planarity_PlanarityTolerance_SweepSlider = new DoubleJSlider(0, 1000000000, 1, 1000000000); + advancedSweep_Planarity_PlanarityTolerance_SweepSlider.setToolTipText("Planarity Tolerance (size in meter)"); + advancedSweep_Planarity_PlanarityTolerance_SweepSlider.setMinorTickSpacing(1000000000); + advancedSweep_Planarity_PlanarityTolerance_SweepSlider.setPaintTicks(true); + advancedSweep_Planarity_PlanarityTolerance_SweepSlider.setEnabled(false); + + advancedSweep_Planarity_PlanarityTolerance_TextField = new JTextField(); + advancedSweep_Planarity_PlanarityTolerance_TextField.setToolTipText("Planarity Tolerance (size in meter)"); + advancedSweep_Planarity_PlanarityTolerance_TextField.setEnabled(false); + advancedSweep_Planarity_PlanarityTolerance_TextField.setText(dfTolerance.format(advancedSweep_Planarity_PlanarityTolerance_SweepSlider.getScaledValue())); + + advancedSweep_Planarity_PlanarityTolerance_SweepSlider.addChangeListener(new ChangeListener(){ + @Override + public void stateChanged(ChangeEvent e) { + advancedSweep_Planarity_PlanarityTolerance_TextField.setText(dfTolerance.format(advancedSweep_Planarity_PlanarityTolerance_SweepSlider.getScaledValue())); + } + }); + advancedSweep_Planarity_PlanarityTolerance_TextField.addKeyListener(new KeyAdapter(){ + @Override + public void keyReleased(KeyEvent ke) { + if(ke.getKeyCode() == KeyEvent.VK_ENTER) + { + String typed = advancedSweep_Planarity_PlanarityTolerance_TextField.getText(); + if(typed.matches("\\d+(\\.\\d*)?")) { + double value = Double.parseDouble(typed)*advancedSweep_Planarity_PlanarityTolerance_SweepSlider.scale; + advancedSweep_Planarity_PlanarityTolerance_SweepSlider.setValue((int)value); + } + else if (typed.matches("\\d+(\\,\\d*)?")) { + double value = Double.parseDouble(typed.replace(',','.'))*advancedSweep_Planarity_PlanarityTolerance_SweepSlider.scale; + advancedSweep_Planarity_PlanarityTolerance_SweepSlider.setValue((int)value); + return; + } + else + { + return; + } + } + } + }); + + + // -------------------------------------------------------------------- + // create layout + // -------------------------------------------------------------------- + GroupLayout panelLayout = new GroupLayout(advancedSweepPanel_Planarity); + advancedSweepPanel_Planarity.setLayout(panelLayout); + + panelLayout.setHorizontalGroup(panelLayout.createSequentialGroup() + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(advancedSweep_Planarity_Use_CheckBox) + .addComponent(advancedSweep_Planarity_PlanarityTolerance_SweepLabel) + ) + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(advancedSweep_Planarity_IgnoreMultiplePoints_CheckBox) + .addComponent(advancedSweep_Planarity_PlanarityTolerance_SweepSlider) + ) + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + //.addComponent(null) + .addComponent(advancedSweep_Planarity_PlanarityTolerance_TextField) + ) + ); + + panelLayout.setVerticalGroup(panelLayout.createSequentialGroup() + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(advancedSweep_Planarity_Use_CheckBox) + .addComponent(advancedSweep_Planarity_IgnoreMultiplePoints_CheckBox) + //.addComponent(null) + ) + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(advancedSweep_Planarity_PlanarityTolerance_SweepLabel) + .addComponent(advancedSweep_Planarity_PlanarityTolerance_SweepSlider) + .addComponent(advancedSweep_Planarity_PlanarityTolerance_TextField) + ) + ); + + + return advancedSweepPanel_Planarity; + } + + private JPanel createAdvancedSweepPanel_SweepPlane() { + // panel with surrounding border + JPanel advancedSweepPanel_SweepPlane = new JPanel(); + advancedSweepPanel_SweepPlane.setBorder(createTitledBorder("Advanced Sweep Settings - SweepPlane")); + + // ----------------------------- CONTENT ----------------------------- + + // -------------------------------------------------------------------- + // use Planarity Check Box + // -------------------------------------------------------------------- + advancedSweep_SweepPlane_Use_CheckBox = new JCheckBox("Use SweepPlane"); + advancedSweep_SweepPlane_Use_CheckBox.setToolTipText("Use SweepPlane Algorithm"); + advancedSweep_SweepPlane_Use_CheckBox.setSelected(false); + + advancedSweep_SweepPlane_Use_CheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (((JCheckBox) e.getSource()).isSelected()) { + advancedSweep_SweepPlane_PushOnly_CheckBox.setEnabled(true); + advancedSweep_SweepPlane_PullOnly_CheckBox.setEnabled(true); + advancedSweep_SweepPlane_ShortestEdgeFirst_CheckBox.setEnabled(true); + advancedSweep_SweepPlane_SmallestFaceFirst_CheckBox.setEnabled(true); + advancedSweep_SweepPlane_SmallestDistFirst_CheckBox.setEnabled(true); + } else { + advancedSweep_SweepPlane_PushOnly_CheckBox.setEnabled(false); + advancedSweep_SweepPlane_PullOnly_CheckBox.setEnabled(false); + advancedSweep_SweepPlane_ShortestEdgeFirst_CheckBox.setEnabled(false); + advancedSweep_SweepPlane_SmallestFaceFirst_CheckBox.setEnabled(false); + advancedSweep_SweepPlane_SmallestDistFirst_CheckBox.setEnabled(false); + } + } + }); + + + + // -------------------------------------------------------------------- + // create push only CheckBox + // -------------------------------------------------------------------- + + advancedSweep_SweepPlane_PushOnly_CheckBox = new JCheckBox("Push Only"); + advancedSweep_SweepPlane_PushOnly_CheckBox.setToolTipText("faces will only be pushed into the geometry"); + advancedSweep_SweepPlane_PushOnly_CheckBox.setSelected(false); + advancedSweep_SweepPlane_PushOnly_CheckBox.setEnabled(false); + advancedSweep_SweepPlane_PushOnly_CheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (((JCheckBox) e.getSource()).isSelected()) { + advancedSweep_SweepPlane_PullOnly_CheckBox.setSelected(false); + } + } + }); + + + // -------------------------------------------------------------------- + // create pull only CheckBox + // -------------------------------------------------------------------- + + advancedSweep_SweepPlane_PullOnly_CheckBox = new JCheckBox("Pull Only"); + advancedSweep_SweepPlane_PullOnly_CheckBox.setToolTipText("faces will only be pulled out of the geometry"); + advancedSweep_SweepPlane_PullOnly_CheckBox.setSelected(false); + advancedSweep_SweepPlane_PullOnly_CheckBox.setEnabled(false); + advancedSweep_SweepPlane_PullOnly_CheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (((JCheckBox) e.getSource()).isSelected()) { + advancedSweep_SweepPlane_PushOnly_CheckBox.setSelected(false); + } + } + }); + + // -------------------------------------------------------------------- + // create shortest edge first CheckBox + // -------------------------------------------------------------------- + + advancedSweep_SweepPlane_ShortestEdgeFirst_CheckBox = new JCheckBox("Shortest Edge First"); + advancedSweep_SweepPlane_ShortestEdgeFirst_CheckBox.setToolTipText("Shortest Edge First"); + advancedSweep_SweepPlane_ShortestEdgeFirst_CheckBox.setSelected(false); + advancedSweep_SweepPlane_ShortestEdgeFirst_CheckBox.setEnabled(false); + advancedSweep_SweepPlane_ShortestEdgeFirst_CheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (((JCheckBox) e.getSource()).isSelected()) { + advancedSweep_SweepPlane_SmallestFaceFirst_CheckBox.setSelected(false); + advancedSweep_SweepPlane_SmallestDistFirst_CheckBox.setSelected(false); + } + } + }); + + // -------------------------------------------------------------------- + // create smallest face first CheckBox + // -------------------------------------------------------------------- + + advancedSweep_SweepPlane_SmallestFaceFirst_CheckBox = new JCheckBox("Smallest Face First"); + advancedSweep_SweepPlane_SmallestFaceFirst_CheckBox.setToolTipText("Smallest Face First"); + advancedSweep_SweepPlane_SmallestFaceFirst_CheckBox.setSelected(false); + advancedSweep_SweepPlane_SmallestFaceFirst_CheckBox.setEnabled(false); + advancedSweep_SweepPlane_SmallestFaceFirst_CheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (((JCheckBox) e.getSource()).isSelected()) { + advancedSweep_SweepPlane_ShortestEdgeFirst_CheckBox.setSelected(false); + advancedSweep_SweepPlane_SmallestDistFirst_CheckBox.setSelected(false); + } + } + }); + + + // -------------------------------------------------------------------- + // create smallest distance first CheckBox + // -------------------------------------------------------------------- + + advancedSweep_SweepPlane_SmallestDistFirst_CheckBox = new JCheckBox("Smallest Dist First"); + advancedSweep_SweepPlane_SmallestDistFirst_CheckBox.setToolTipText("Smallest Dist First"); + advancedSweep_SweepPlane_SmallestDistFirst_CheckBox.setSelected(false); + advancedSweep_SweepPlane_SmallestDistFirst_CheckBox.setEnabled(false); + advancedSweep_SweepPlane_SmallestDistFirst_CheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (((JCheckBox) e.getSource()).isSelected()) { + advancedSweep_SweepPlane_ShortestEdgeFirst_CheckBox.setSelected(false); + advancedSweep_SweepPlane_SmallestFaceFirst_CheckBox.setSelected(false); + } + } + }); + + + + // -------------------------------------------------------------------- + // create layout + // -------------------------------------------------------------------- + GroupLayout panelLayout = new GroupLayout(advancedSweepPanel_SweepPlane); + advancedSweepPanel_SweepPlane.setLayout(panelLayout); + + panelLayout.setHorizontalGroup(panelLayout.createSequentialGroup() + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(advancedSweep_SweepPlane_Use_CheckBox) + .addComponent(advancedSweep_SweepPlane_PushOnly_CheckBox) + .addComponent(advancedSweep_SweepPlane_ShortestEdgeFirst_CheckBox) + ) + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + //.addComponent(null) + .addComponent(advancedSweep_SweepPlane_PullOnly_CheckBox) + .addComponent(advancedSweep_SweepPlane_SmallestFaceFirst_CheckBox) + ) + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + //.addComponent(null) + //.addComponent(null) + .addComponent(advancedSweep_SweepPlane_SmallestDistFirst_CheckBox) + ) + ); + + panelLayout.setVerticalGroup(panelLayout.createSequentialGroup() + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(advancedSweep_SweepPlane_Use_CheckBox) + //.addComponent(null) + //.addComponent(null) + ) + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(advancedSweep_SweepPlane_PushOnly_CheckBox) + .addComponent(advancedSweep_SweepPlane_PullOnly_CheckBox) + //.addComponent(null) + ) + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(advancedSweep_SweepPlane_ShortestEdgeFirst_CheckBox) + .addComponent(advancedSweep_SweepPlane_SmallestFaceFirst_CheckBox) + .addComponent(advancedSweep_SweepPlane_SmallestDistFirst_CheckBox) + ) + ); + + + return advancedSweepPanel_SweepPlane; + } + + private JPanel createAdvancedSweepPanel_SweepRotate() { + // panel with surrounding border + JPanel advancedSweepPanel_SweepRotate = new JPanel(); + advancedSweepPanel_SweepRotate.setBorder(createTitledBorder("Advanced Sweep Settings - SweepRotate")); + + // ----------------------------- CONTENT ----------------------------- + + // -------------------------------------------------------------------- + // use Planarity Check Box + // -------------------------------------------------------------------- + advancedSweep_SweepRotate_Use_CheckBox = new JCheckBox("Use SweepRotate"); + advancedSweep_SweepRotate_Use_CheckBox.setToolTipText("Use SweepRotate Algorithm"); + advancedSweep_SweepRotate_Use_CheckBox.setSelected(false); + + + advancedSweep_SweepRotate_Use_CheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (((JCheckBox) e.getSource()).isSelected()) { + advancedSweep_SweepRotate_MinDistFirst_CheckBox.setEnabled(true); + advancedSweep_SweepRotate_MinAngleFirst_CheckBox.setEnabled(true); + advancedSweep_SweepRotate_SmallestFaceFirst_CheckBox.setEnabled(true); + } else { + advancedSweep_SweepRotate_MinDistFirst_CheckBox.setEnabled(false); + advancedSweep_SweepRotate_MinAngleFirst_CheckBox.setEnabled(false); + advancedSweep_SweepRotate_SmallestFaceFirst_CheckBox.setEnabled(false); + } + } + }); + + + + // -------------------------------------------------------------------- + // write max Angle Slider + // -------------------------------------------------------------------- + + final DecimalFormat dfAngle = new DecimalFormat("0.####"); + + + advancedSweep_SweepRotate_maxAngleLabel = new JLabel("Min Angle"); + + advancedSweep_SweepRotate_maxAngleSlider = new DoubleJSlider(0, 600, 100, 10); + advancedSweep_SweepRotate_maxAngleSlider.setToolTipText("Sweep rotate, if angle between two edges is lower than this value (angle in degrees)"); + advancedSweep_SweepRotate_maxAngleSlider.setMinorTickSpacing(100); + advancedSweep_SweepRotate_maxAngleSlider.setPaintTicks(true); + advancedSweep_SweepRotate_maxAngleSlider.setEnabled(true); + + advancedSweep_SweepRotate_maxAngleTextField = new JTextField(); + advancedSweep_SweepRotate_maxAngleTextField.setToolTipText("Sweep rotate, if angle between two edges is lower than this value (angle in degrees)"); + advancedSweep_SweepRotate_maxAngleTextField.setEnabled(true); + advancedSweep_SweepRotate_maxAngleTextField.setText(dfAngle.format(advancedSweep_SweepRotate_maxAngleSlider.getScaledValue())); + + advancedSweep_SweepRotate_maxAngleSlider.addChangeListener(new ChangeListener(){ + @Override + public void stateChanged(ChangeEvent e) { + advancedSweep_SweepRotate_maxAngleTextField.setText(dfAngle.format(advancedSweep_SweepRotate_maxAngleSlider.getScaledValue())); + } + }); + advancedSweep_SweepRotate_maxAngleTextField.addKeyListener(new KeyAdapter(){ + @Override + public void keyReleased(KeyEvent ke) { + if(ke.getKeyCode() == KeyEvent.VK_ENTER) + { + String typed = advancedSweep_SweepRotate_maxAngleTextField.getText(); + if(typed.matches("\\d+(\\.\\d*)?")) { + double value = Double.parseDouble(typed)*advancedSweep_SweepRotate_maxAngleSlider.scale; + advancedSweep_SweepRotate_maxAngleSlider.setValue((int)value); + } + else if (typed.matches("\\d+(\\,\\d*)?")) { + double value = Double.parseDouble(typed.replace(',','.'))*advancedSweep_SweepRotate_maxAngleSlider.scale; + advancedSweep_SweepRotate_maxAngleSlider.setValue((int)value); + return; + } + else + { + return; + } + } + } + }); + + // -------------------------------------------------------------------- + // create min dist first CheckBox + // -------------------------------------------------------------------- + + advancedSweep_SweepRotate_MinDistFirst_CheckBox = new JCheckBox("Min. Distance First"); + advancedSweep_SweepRotate_MinDistFirst_CheckBox.setToolTipText("Minimal Distance First"); + advancedSweep_SweepRotate_MinDistFirst_CheckBox.setSelected(false); + advancedSweep_SweepRotate_MinDistFirst_CheckBox.setEnabled(false); + advancedSweep_SweepRotate_MinDistFirst_CheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (((JCheckBox) e.getSource()).isSelected()) { + advancedSweep_SweepRotate_MinAngleFirst_CheckBox.setSelected(false); + advancedSweep_SweepRotate_SmallestFaceFirst_CheckBox.setSelected(false); + } + } + }); + + // -------------------------------------------------------------------- + // create min angle first CheckBox + // -------------------------------------------------------------------- + + advancedSweep_SweepRotate_MinAngleFirst_CheckBox = new JCheckBox("Min. Angle First"); + advancedSweep_SweepRotate_MinAngleFirst_CheckBox.setToolTipText("Minimal Angle First"); + advancedSweep_SweepRotate_MinAngleFirst_CheckBox.setSelected(false); + advancedSweep_SweepRotate_MinAngleFirst_CheckBox.setEnabled(false); + advancedSweep_SweepRotate_MinAngleFirst_CheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (((JCheckBox) e.getSource()).isSelected()) { + advancedSweep_SweepRotate_MinDistFirst_CheckBox.setSelected(false); + advancedSweep_SweepRotate_SmallestFaceFirst_CheckBox.setSelected(false); + } + } + }); + + // -------------------------------------------------------------------- + // create smallest face first CheckBox + // -------------------------------------------------------------------- + + advancedSweep_SweepRotate_SmallestFaceFirst_CheckBox = new JCheckBox("Smallest Face First"); + advancedSweep_SweepRotate_SmallestFaceFirst_CheckBox.setToolTipText("Smallest Face First"); + advancedSweep_SweepRotate_SmallestFaceFirst_CheckBox.setSelected(false); + advancedSweep_SweepRotate_SmallestFaceFirst_CheckBox.setEnabled(false); + advancedSweep_SweepRotate_SmallestFaceFirst_CheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (((JCheckBox) e.getSource()).isSelected()) { + advancedSweep_SweepRotate_MinDistFirst_CheckBox.setSelected(false); + advancedSweep_SweepRotate_MinAngleFirst_CheckBox.setSelected(false); + } + } + }); + + + // -------------------------------------------------------------------- + // create layout + // -------------------------------------------------------------------- + GroupLayout panelLayout = new GroupLayout(advancedSweepPanel_SweepRotate); + advancedSweepPanel_SweepRotate.setLayout(panelLayout); + + panelLayout.setHorizontalGroup(panelLayout.createSequentialGroup() + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(advancedSweep_SweepRotate_Use_CheckBox) + .addComponent(advancedSweep_SweepRotate_maxAngleLabel) + .addComponent(advancedSweep_SweepRotate_MinAngleFirst_CheckBox) + ) + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + //.addComponent(NULL) + .addComponent(advancedSweep_SweepRotate_maxAngleSlider) + .addComponent(advancedSweep_SweepRotate_MinDistFirst_CheckBox) + ) + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + //.addComponent(NULL) + .addComponent(advancedSweep_SweepRotate_maxAngleTextField) + .addComponent(advancedSweep_SweepRotate_SmallestFaceFirst_CheckBox) + ) + ); + + panelLayout.setVerticalGroup(panelLayout.createSequentialGroup() + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(advancedSweep_SweepRotate_Use_CheckBox) + //.addComponent(NULL) + //.addComponent(NULL) + ) + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(advancedSweep_SweepRotate_maxAngleLabel) + .addComponent(advancedSweep_SweepRotate_maxAngleSlider) + .addComponent(advancedSweep_SweepRotate_maxAngleTextField) + ) + .addGroup(panelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(advancedSweep_SweepRotate_MinAngleFirst_CheckBox) + .addComponent(advancedSweep_SweepRotate_MinDistFirst_CheckBox) + .addComponent(advancedSweep_SweepRotate_SmallestFaceFirst_CheckBox) + ) + ); + + + return advancedSweepPanel_SweepRotate; + } + + private JPanel createExecuteButtonPanel() { + JPanel executePanel = new JPanel(new FlowLayout()); + + JButton execBtn = new JButton( + CDAutoProGuiMessages.getString("AutoProWindow.OkButtonLabel")); + execBtn.setMinimumSize(new Dimension(stdBtnWidth, stdBtnHeight)); + execBtn.setMaximumSize(new Dimension(stdBtnWidth, stdBtnHeight)); + execBtn.setPreferredSize(new Dimension(stdBtnWidth, stdBtnHeight)); + + execBtn.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + try { + startCppAutoProMethods(); + } catch (FileNotFoundException e1) { + // Auto-generated catch block + e1.printStackTrace(); + } + close(); + + } + }); + + executePanel.add(execBtn); + + JButton cancelBtn = new JButton( + CDAutoProGuiMessages.getString("AutoProWindow.CancelButtonLabel")); + cancelBtn.setMinimumSize(new Dimension(stdBtnWidth, stdBtnHeight)); + cancelBtn.setMaximumSize(new Dimension(stdBtnWidth, stdBtnHeight)); + cancelBtn.setPreferredSize(new Dimension(stdBtnWidth, stdBtnHeight)); + cancelBtn.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + close(); + } + }); + + executePanel.add(cancelBtn); + + return executePanel; + } + + // NOTE: this is a hack, to provide the file type and the description for + // the inner FileFilter class in the saveFileDialog method + private String currSaveTypeDescription; + private String currSaveFileType; + + + /** + * @param The target file type + * @param The description of the the file type + * @param The dialog title + * @return The FileInfo with absolute path, name and type for the selected file + */ + private FileInfo saveFileDialog(String fileType, String typeDescription, + String dialogTitle) { + if (!fileType.startsWith(".")) + fileType = "." + fileType; + currSaveFileType = fileType; + currSaveTypeDescription = typeDescription; + JFileChooser fileChooser = new JFileChooser(new File(".")); + fileChooser.setDialogTitle(dialogTitle); + fileChooser.setAcceptAllFileFilterUsed(false); + fileChooser.setFileFilter(new FileFilter() { + + @Override + public String getDescription() { + return currSaveTypeDescription; + } + + @Override + public boolean accept(File f) { + return f.isDirectory() + || f.getName().toLowerCase().endsWith(currSaveFileType); + } + }); + + int userSelection = fileChooser.showSaveDialog(this); + + if (userSelection == JFileChooser.APPROVE_OPTION) { + + FileInfo fileInfo = new FileInfo(); + fileInfo.setType(fileType); + String filename = fileChooser.getSelectedFile().getName(); + if (filename.endsWith(fileType)) + { + int pos = filename.lastIndexOf("."); + if (pos > 0) { + filename = filename.substring(0, pos); + } + } + fileInfo.setName(filename); + String absolutePath = fileChooser.getSelectedFile().getAbsolutePath(); + fileInfo.setPath(absolutePath.substring(0,absolutePath.lastIndexOf(File.separator)) + "\\"); + + return fileInfo; + } else + return null; + } + + private TitledBorder createTitledBorder(String heading) { + Border baseBorder = new LineBorder(Color.GRAY); // to have a gray border + Font headingFont = new Font("Arial", Font.BOLD + Font.ITALIC, 13); + TitledBorder finalBorder = new TitledBorder(baseBorder, heading, + TitledBorder.DEFAULT_POSITION, + TitledBorder.DEFAULT_JUSTIFICATION, headingFont, + Color.DARK_GRAY); + return finalBorder; + } + + /** + * test + * + * @param args + */ + public static void main(String[] args) { + AutoProWindow v = new AutoProWindow(null); + v.setVisible(true); + } + + @Override + public void itemStateChanged(ItemEvent paramItemEvent) { + // Auto-generated method stub + + } +} diff --git a/CityDoctorParent/Extensions/CityDoctorAutoPro/src/main/java/de/hft/stuttgart/citydoctor2/gui/CDAutoProGuiMessages.java b/CityDoctorParent/Extensions/CityDoctorAutoPro/src/main/java/de/hft/stuttgart/citydoctor2/gui/CDAutoProGuiMessages.java new file mode 100644 index 0000000000000000000000000000000000000000..317f2654430ba8f85befc8bcae1f3067a3246219 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorAutoPro/src/main/java/de/hft/stuttgart/citydoctor2/gui/CDAutoProGuiMessages.java @@ -0,0 +1,58 @@ +/** -------------------------------------------------- + * Hochschule fuer Technik Stuttgart + * Fachbereich Vermessung , Informatik und Mathematik + * Schellingstr . 24 + * D - 70174 Stuttgart + * + * Projekt CityDoktor + * + * Copyright (c) 2011 HFT Stuttgart. All rights reserved. + * HFT Stuttgart and its licensors retain all intellectual property and + * proprietary rights in and to this software and related documentation. + * Any use, reproduction, disclosure, or distribution of this software + * and related documentation without an express license agreement from + * HFT Stuttgart is strictly prohibited. + * + * Please refer to the applicable HFT Stuttgart end user license agreement (EULA) + * associated with this source code for terms and conditions that govern + * your use of this HFT Stuttgart software. + * + * @author PiR + * @version 1.0 + * created: 17.12.2017 + */ + + +package de.hft.stuttgart.citydoctor2.gui; + +import java.util.Locale; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +/** + * Diese Klasse ermoeglicht den Zugriff auf das ResourceBundle mit den + * lokalisierten Strings. + * + */ +public class CDAutoProGuiMessages { + private static final String BUNDLE_NAME = "de.hft.stuttgart.citydoctor2.gui.cdautoproguimessages"; //$NON-NLS-1$ + + private CDAutoProGuiMessages() { + } + + /** + * Diese Methode laedt einen String aus dem ResourceBundle. + * + * @param key der Schluessel des Strings + * @return der String + */ + public static String getString(String key) { + ResourceBundle RESOURCE_BUNDLE = ResourceBundle + .getBundle(BUNDLE_NAME, Locale.getDefault()); + try { + return RESOURCE_BUNDLE.getString(key); + } catch (MissingResourceException e) { + return '!' + key + '!'; + } + } +} diff --git a/CityDoctorParent/Extensions/CityDoctorAutoPro/src/main/java/de/hft/stuttgart/citydoctor2/gui/cdautoproguimessages.properties b/CityDoctorParent/Extensions/CityDoctorAutoPro/src/main/java/de/hft/stuttgart/citydoctor2/gui/cdautoproguimessages.properties new file mode 100644 index 0000000000000000000000000000000000000000..1ad0bb3c5c14974e63a2894b75ab260783fffe25 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorAutoPro/src/main/java/de/hft/stuttgart/citydoctor2/gui/cdautoproguimessages.properties @@ -0,0 +1,83 @@ +CityDoctorAutoProFrame.WindowTitle=CityDoctor Automated Processing Tool +CityDoctorAutoProFrame.autoProActionTitle=Automated Processing +CityDoctorAutoProFrame.autoProActionText=Automated Processing + +AutoProWindow.PreferencesWindowTitle = Automated Processing Window + +// EXPORT + +AutoProWindow.exportMeshPanel = export Mesh File via CPP (only original model can be printed) +AutoProWindow.exportMeshButtonTitle = export Mesh +AutoProWindow.exportMeshButtonDescription = export Mesh File via CPP +AutoProWindow.meshExportFileNameDescription = Hier kann optional der Name fuer die Mesh Datei angegeben werden +AutoProWindow.meshExportPathDescription = Hier kann optional der Speicherort fuer die Mesh Datei angegeben werden +AutoProWindow.exportMeshReportDialogTitle = Export Mesh File to... + +AutoProWindow.exportIVPanel = export IV File via CPP +AutoProWindow.exportIVButtonTitle = export IV +AutoProWindow.exportIVButtonDescription = export IV File via CPP +AutoProWindow.ivExportFileNameDescription = Hier kann optional der Name fuer die IV Datei angegeben werden +AutoProWindow.ivExportPathDescription = Hier kann optional der Speicherort fuer die IV Datei angegeben werden +AutoProWindow.exportIVReportDialogTitle = Export IV File to... + +AutoProWindow.exportSTEPPanel = export STEP File via CPP +AutoProWindow.exportSTEPButtonTitle = export STEP +AutoProWindow.exportSTEPButtonDescription = export STEP File via CPP +AutoProWindow.stepExportFileNameDescription = Hier kann optional der Name fuer die STEP Datei angegeben werden +AutoProWindow.stepExportPathDescription = Hier kann optional der Speicherort fuer die STEP Datei angegeben werden +AutoProWindow.exportSTEPReportDialogTitle = Export STEP File to... + +AutoProWindow.exportGMLPanel = export CityGML File via CPP +AutoProWindow.exportGMLButtonTitle = export CityGML +AutoProWindow.exportGMLButtonDescription = export CityGML File via CPP +AutoProWindow.gmlExportFileNameDescription = Hier kann optional der Name fuer die CityGML Datei angegeben werden +AutoProWindow.gmlExportPathDescription = Hier kann optional der Speicherort fuer die CityGML Datei angegeben werden +AutoProWindow.exportGMLReportDialogTitle = Export CityGML File to... + +AutoProWindow.exportSettingsPanel = General Setting for Export + +// + +AutoProWindow.printInfoPanel = General Print Info Settings +AutoProWindow.comparisonPanel = Print Settings for validation/comparison + + +// BOOL + +AutoProWindow.boolPanel = Bool and Minkowski settings +AutoProWindow.boolButtonTitle = use Bool +AutoProWindow.boolButtonDescription = uses CGALs union operator to merge houses +AutoProWindow.boolInfoButtonTitle = Print Bool info +AutoProWindow.boolInfoButtonDescription = Print Bool info into JAVA terminal + +AutoProWindow.minkowskiPanel = Minkowski settings +AutoProWindow.minkowskiButtonTitle = use Minkowski +AutoProWindow.minkowskiButtonDescription = uses CGALs minkowski operations +AutoProWindow.minkowskiInfoButtonTitle = Print Minkowski info +AutoProWindow.minkowskiInfoButtonDescription = Print Minkowski info into JAVA terminal +AutoProWindow.minkowskiCubeDescription = Sets the size of the minkowski cube (size in meter) +AutoProWindow.minkowskiCubeSliderDescription = Sets the size of the minkowski cube (size in meter) + +AutoProWindow.boolMinkowski_exportIntermediateStagesCheckBoxButtonTitle = export intermediate stages +AutoProWindow.boolMinkowski_exportIntermediateStagesCheckBoxButtonDescription = if selected writes the intermediate stages of the algorithm to .iv and .step + +// MERGE + +AutoProWindow.mergePanel = Merge settings +AutoProWindow.mergeButtonTitle = use Merge +AutoProWindow.mergeButtonDescription = merges parallel, connected faces and edges and collapses degenerated faces and edges +AutoProWindow.merge_exportIntermediateStagesCheckBoxButtonTitle = export intermediate stages +AutoProWindow.merge_exportIntermediateStagesCheckBoxButtonDescription = if selected writes the intermediate stages of the algorithm to .iv and .step +AutoProWindow.mergeInfoButtonTitle = Print Merge info +AutoProWindow.mergeInfoButtonDescription = Print Merge info into JAVA terminal +AutoProWindow.eps_PointEqualitySliderDescription = Point Equality Tolerance (size in meter) +AutoProWindow.eps_PointEqualityDescription = if an edge is shorter than this tolerance the edge degenerates to a vertex +AutoProWindow.eps_ParallelitySliderDescription = Parallelity Tolerance (angle in degrees) +AutoProWindow.eps_ParallelityDescription = two vectors v1, v2 or planes (v are the planes' normal) are (anti-)parallel if |(v1 % v2) - (v1.length * v1.length)| < eps + + +// OK CANCEL + +AutoProWindow.OkButtonLabel = DO IT +AutoProWindow.CancelButtonLabel = Cancel + diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/.gitignore b/CityDoctorParent/Extensions/CityDoctorGUI/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..b2e3a6160ece70ea7d930af3f0b50adebc6027ee --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/.gitignore @@ -0,0 +1,2 @@ +GUISettings.properties +/.gradle/ diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/checkForSolid.xml b/CityDoctorParent/Extensions/CityDoctorGUI/checkForSolid.xml new file mode 100644 index 0000000000000000000000000000000000000000..165be4b93a9ff20c46214ca77738bc3b8dda9546 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/checkForSolid.xml @@ -0,0 +1,14 @@ + + + + + + + + ||||SE_ATTRIBUTE_MISSING||any solid + + + ||||SE_ATTRIBUTE_MISSING||any solid + + + diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/pom.xml b/CityDoctorParent/Extensions/CityDoctorGUI/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..3ef9ad508c7de50cd3af5ce5785b9dc897af4cbd --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/pom.xml @@ -0,0 +1,189 @@ + + 4.0.0 + + de.hft.stuttgart + CityDoctorParent + 3.14.1 + ../../pom.xml + + CityDoctorGUI + CityDoctorGUI + Graphical User Interface for CityDoctor + + + + org.apache.maven.plugins + maven-jar-plugin + 3.2.0 + + + + + + de.hft.stuttgart + CityDoctorModel + + + de.hft.stuttgart + CityDoctorValidation + + + org.apache.logging.log4j + log4j-api + + + org.apache.logging.log4j + log4j-core + + + junit + junit + test + + + org.apache.logging.log4j + log4j-slf4j18-impl + + + + + create-binaries + + jre-${jre-version-short}-full + ${win-jre} + ${win-jre}.jre + + + + + com.googlecode.maven-download-plugin + download-maven-plugin + 1.7.0 + + + downloadWindowsJre + install + + wget + + + https://download.bell-sw.com/java/${jre-version}/bellsoft-jre${jre-version}-windows-amd64-full.zip + false + ${project.build.directory}/jre/jre-win + win-runtime.zip + + + + downloadLinuxJre + install + + wget + + + https://download.bell-sw.com/java/${jre-version}/bellsoft-jre${jre-version}-linux-amd64-full.tar.gz + false + ${project.build.directory}/jre/jre-lin + lin-runtime.tar.gz + + + + downloadMacJre + install + + wget + + + https://download.bell-sw.com/java/${jre-version}/bellsoft-jre${jre-version}-macos-amd64-full.zip + false + ${project.build.directory}/jre/jre-mac + mac-runtime.zip + + + + + + org.apache.maven.plugins + maven-antrun-plugin + 3.1.0 + + + unpack + install + + + + + + + + + run + + + + + + maven-assembly-plugin + + false + + + + create-archive-no-runtime + install + + single + + + ${project.artifactId}-${project.version}-no-runtime + + ${project.basedir}/src/assembly/no_runtime/assembly.xml + + + + + create-archive-win + install + + single + + + ${project.artifactId}-${project.version}-win + + ${project.basedir}/src/assembly/win/assembly.xml + + + + + create-archive-lin + install + + single + + + ${project.artifactId}-${project.version}-lin + + ${project.basedir}/src/assembly/lin/assembly.xml + + + + + create-archive-mac + install + + single + + + ${project.artifactId}-${project.version}-mac + + ${project.basedir}/src/assembly/mac/assembly.xml + + + + + + + + + + \ No newline at end of file diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/assembly/common/checkForSolid.xml b/CityDoctorParent/Extensions/CityDoctorGUI/src/assembly/common/checkForSolid.xml new file mode 100644 index 0000000000000000000000000000000000000000..165be4b93a9ff20c46214ca77738bc3b8dda9546 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/assembly/common/checkForSolid.xml @@ -0,0 +1,14 @@ + + + + + + + + ||||SE_ATTRIBUTE_MISSING||any solid + + + ||||SE_ATTRIBUTE_MISSING||any solid + + + diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/assembly/lin/assembly.xml b/CityDoctorParent/Extensions/CityDoctorGUI/src/assembly/lin/assembly.xml new file mode 100644 index 0000000000000000000000000000000000000000..169bf5e5bbbd48c8942c14c2350d8f949a6fe1e7 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/assembly/lin/assembly.xml @@ -0,0 +1,42 @@ + + zip + + zip + + false + + + app + + + + + ${project.basedir}/src/assembly/lin + / + + start.sh + + true + + + ${project.basedir}/src/assembly/common + / + + checkForSolid.xml + + false + + + ${project.build.directory}/jre/jre-lin/runtime/${lin-jre}/ + + /runtime + + **/* + + false + + + \ No newline at end of file diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/assembly/lin/start.sh b/CityDoctorParent/Extensions/CityDoctorGUI/src/assembly/lin/start.sh new file mode 100644 index 0000000000000000000000000000000000000000..7066c344eb2e03374306ed7d4516f62581120c98 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/assembly/lin/start.sh @@ -0,0 +1,2 @@ +#!/bin/sh +./runtime/bin/java -classpath app/*:plugin/* de.hft.stuttgart.citydoctor2.gui.CityDoctorGUIStarter \ No newline at end of file diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/assembly/mac/assembly.xml b/CityDoctorParent/Extensions/CityDoctorGUI/src/assembly/mac/assembly.xml new file mode 100644 index 0000000000000000000000000000000000000000..59ea8a6f5c8acfd6b5860aaea385b09cfb307834 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/assembly/mac/assembly.xml @@ -0,0 +1,42 @@ + + zip + + zip + + false + + + app + + + + + ${project.basedir}/src/assembly/lin + / + + start.sh + + true + + + ${project.basedir}/src/assembly/common + / + + checkForSolid.xml + + false + + + ${project.build.directory}/jre/jre-mac/runtime/${mac-jre}/ + + /runtime + + **/* + + false + + + \ No newline at end of file diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/assembly/no_runtime/assembly.xml b/CityDoctorParent/Extensions/CityDoctorGUI/src/assembly/no_runtime/assembly.xml new file mode 100644 index 0000000000000000000000000000000000000000..fd5f0a71f80fcf82fffbb35f1aecacd61f123df0 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/assembly/no_runtime/assembly.xml @@ -0,0 +1,34 @@ + + zip + + zip + + false + + + app + + + + + ${project.basedir}/src/assembly/no_runtime + / + + start.bat + start.sh + + true + + + ${project.basedir}/src/assembly/common + / + + checkForSolid.xml + + false + + + \ No newline at end of file diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/assembly/no_runtime/start.bat b/CityDoctorParent/Extensions/CityDoctorGUI/src/assembly/no_runtime/start.bat new file mode 100644 index 0000000000000000000000000000000000000000..2da095db9a6421abef9c6263ecb05a336f16d340 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/assembly/no_runtime/start.bat @@ -0,0 +1,2 @@ +java -classpath app/*;plugins/* de.hft.stuttgart.citydoctor2.gui.CityDoctorGUIStarter +pause \ No newline at end of file diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/assembly/no_runtime/start.sh b/CityDoctorParent/Extensions/CityDoctorGUI/src/assembly/no_runtime/start.sh new file mode 100644 index 0000000000000000000000000000000000000000..a8f20ec0a66c56da48b1afe96b8c45bc359fe802 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/assembly/no_runtime/start.sh @@ -0,0 +1,2 @@ +#!/bin/sh +java -classpath app/*:plugin/* de.hft.stuttgart.citydoctor2.gui.CityDoctorGUIStarter \ No newline at end of file diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/assembly/win/assembly.xml b/CityDoctorParent/Extensions/CityDoctorGUI/src/assembly/win/assembly.xml new file mode 100644 index 0000000000000000000000000000000000000000..8a74907cbd0bf43f735a291f30d9ca047023846c --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/assembly/win/assembly.xml @@ -0,0 +1,42 @@ + + zip + + zip + + false + + + app + + + + + ${project.basedir}/src/assembly/win + / + + start.bat + + true + + + ${project.basedir}/src/assembly/common + / + + checkForSolid.xml + + false + + + ${project.build.directory}/jre/jre-win/runtime/${win-jre}/ + + /runtime + + **/* + + false + + + \ No newline at end of file diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/assembly/win/start.bat b/CityDoctorParent/Extensions/CityDoctorGUI/src/assembly/win/start.bat new file mode 100644 index 0000000000000000000000000000000000000000..70d8a6ab346514831a9b5426a9e3f2e85fe66acf --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/assembly/win/start.bat @@ -0,0 +1,2 @@ +"runtime/bin/java.exe" -classpath app/*;plugins/* de.hft.stuttgart.citydoctor2.gui.CityDoctorGUIStarter +pause \ No newline at end of file diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/AboutDialog.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/AboutDialog.java new file mode 100644 index 0000000000000000000000000000000000000000..b45b3421ca61c6b43c2efd222e4553063a5c5a7b --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/AboutDialog.java @@ -0,0 +1,101 @@ +package de.hft.stuttgart.citydoctor2.gui; + +import java.io.IOException; +import java.io.InputStream; + +import de.hft.stuttgart.citydoctor2.utils.Localization; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.layout.VBox; +import javafx.stage.Modality; +import javafx.stage.Stage; +import javafx.stage.StageStyle; +import javafx.stage.Window; + +public class AboutDialog { + + @FXML + private ImageView logoView; + + @FXML + private ImageView beuthView; + + @FXML + private ImageView minisView; + + @FXML + private ImageView hftView; + + @FXML + private Button closeBtn; + + @FXML + private Label cdLabel; + + private Stage stage; + + public AboutDialog(Window parent) throws IOException { + FXMLLoader loader = new FXMLLoader(AboutDialog.class.getResource("AboutDialog.fxml")); + loader.setController(this); + VBox box = loader.load(); + + + stage = new Stage(StageStyle.UTILITY); + stage.setTitle(Localization.getText("AboutDialog.title")); + stage.setResizable(false); + Scene scene = new Scene(box); + stage.setScene(scene); + stage.initOwner(parent); + stage.initModality(Modality.APPLICATION_MODAL); + } + + public void initialize() { + String developedBy = Localization.getText("AboutDialog.developedBy"); + String contact = Localization.getText("AboutDialog.contact"); + closeBtn.setText(Localization.getText("AboutDialog.closeBtn")); + cdLabel.setText("CityDoctor Version " + Localization.getText(Localization.VERSION) + "\n\n" + + developedBy + ":\n" + + "Hochschule für Technik\n" + + "Beuth Hochschule Berlin\n\n" + + contact + ":\n" + + "Matthias Betz\n" + + "matthias.betz@hft-stuttgart.de"); + + + closeBtn.setOnAction(ae -> hide()); + try { + try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/CityDoctor-Logo-rot_klein.png")) { + Image img = new Image(inStream); + logoView.setImage(img); + } + try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/hft_logo.png")) { + Image img = new Image(inStream); + hftView.setImage(img); + } + try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/Beuth-Logo_basis.png")) { + Image img = new Image(inStream); + beuthView.setImage(img); + } + try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/BMBF_Logo.png")) { + Image img = new Image(inStream); + minisView.setImage(img); + } + } catch (IOException e) { + // ignore close exception + } + } + + public void show() { + stage.show(); + } + + public void hide() { + stage.hide(); + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/CheckDialog.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/CheckDialog.java new file mode 100644 index 0000000000000000000000000000000000000000..ca7e0915106f8d75ad914a01dec8154e5a0a8e39 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/CheckDialog.java @@ -0,0 +1,592 @@ +package de.hft.stuttgart.citydoctor2.gui; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import de.hft.stuttgart.citydoctor2.check.DefaultParameter; +import de.hft.stuttgart.citydoctor2.check.FilterConfiguration; +import de.hft.stuttgart.citydoctor2.check.GlobalParameters; +import de.hft.stuttgart.citydoctor2.check.Requirement; +import de.hft.stuttgart.citydoctor2.check.RequirementConfiguration; +import de.hft.stuttgart.citydoctor2.check.RequirementType; +import de.hft.stuttgart.citydoctor2.check.Unit; +import de.hft.stuttgart.citydoctor2.check.ValidationConfiguration; +import de.hft.stuttgart.citydoctor2.checks.Checks; +import de.hft.stuttgart.citydoctor2.gui.tree.TreeRequirement; +import de.hft.stuttgart.citydoctor2.utils.Localization; +import javafx.application.Platform; +import javafx.event.Event; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.control.ProgressBar; +import javafx.scene.control.ScrollPane; +import javafx.scene.control.Tab; +import javafx.scene.control.TabPane; +import javafx.scene.control.TableColumn; +import javafx.scene.control.TableView; +import javafx.scene.control.TextField; +import javafx.scene.control.TreeItem; +import javafx.scene.control.TreeTableColumn; +import javafx.scene.control.TreeTableView; +import javafx.scene.control.cell.CheckBoxTreeTableCell; +import javafx.scene.control.cell.PropertyValueFactory; +import javafx.scene.control.cell.TextFieldTableCell; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.layout.VBox; +import javafx.stage.FileChooser; +import javafx.stage.FileChooser.ExtensionFilter; +import javafx.stage.Modality; +import javafx.stage.Stage; +import javafx.stage.Window; +import javafx.util.StringConverter; +import javafx.util.converter.DefaultStringConverter; + +public class CheckDialog { + + private static final String NUMBER_OF_ROUNDING_PLACES = "numberOfRoundingPlaces"; + + private static final Logger logger = LogManager.getLogger(CheckDialog.class); + + private static final String CHECK_ENABLED = Localization.getText("CheckDialog.checkEnabled"); + private static final String NAME = Localization.getText("CheckDialog.checkName"); + private static final String VALUE = Localization.getText("CheckDialog.parameterValue"); + private static final String UNIT = Localization.getText("CheckDialog.parameterUnit"); + + private Stage stage; + + @FXML + private TreeTableView geometricTable; + + @FXML + private TreeTableView semanticTable; + + @FXML + private TableView globalParametersTable; + + @FXML + private ScrollPane scrollPane; + + @FXML + private Button cancelBtn; + + @FXML + private Button checkBtn; + + @FXML + private ProgressBar progress; + + @FXML + private Tab filterTab; + + @FXML + private TabPane tabPane; + + @FXML + private Button loadBtn; + + @FXML + private ImageView loadView; + + @FXML + private Button saveBtn; + + @FXML + private ImageView saveView; + + @FXML + private Button selectBtn; + + @FXML + private TextField schematronField; + + @FXML + private Tab checksTab; + + @FXML + private Label globalParametersLabel; + + @FXML + private Label availableChecksLabel; + + @FXML + private Label geometricChecksLabel; + + @FXML + private Label semanticChecksLabel; + + @FXML + private Label schematronFileLabel; + + private CityDoctorController controller; + private FilterPane filterPane; + private MainWindow window; + + public CheckDialog(MainWindow window, Window parent, CityDoctorController controller) throws IOException { + this.window = window; + this.controller = controller; + + FXMLLoader loader = new FXMLLoader(CheckDialog.class.getResource("CheckDialog.fxml")); + loader.setController(this); + VBox box = loader.load(); + + stage = new Stage(); + stage.getIcons().add(new Image(MainWindow.class.getResourceAsStream("icons/CityDoctor-Logo-rot_klein.jpg"))); + Scene scene = new Scene(box); + stage.setScene(scene); + stage.initOwner(parent); + stage.initModality(Modality.APPLICATION_MODAL); + stage.setTitle(Localization.getText("CheckDialog.title")); + } + + public void initialize() { + createEnableColumn(geometricTable); + createNameColumn(geometricTable); + createValueColumn(geometricTable); + createUnitColumn(geometricTable); + + createEnableColumn(semanticTable); + createNameColumn(semanticTable); + createValueColumn(semanticTable); + createUnitColumn(semanticTable); + + checksTab.setText(Localization.getText("CheckDialog.checksTab")); + filterTab.setText(Localization.getText("CheckDialog.filterTab")); + globalParametersLabel.setText(Localization.getText("CheckDialog.globalParametersLabel")); + availableChecksLabel.setText(Localization.getText("CheckDialog.availableChecksLabel")); + geometricChecksLabel.setText(Localization.getText("CheckDialog.geometricChecksLabel")); + semanticChecksLabel.setText(Localization.getText("CheckDialog.semanticChecksLabel")); + schematronFileLabel.setText(Localization.getText("CheckDialog.schematronFileLabel")); + selectBtn.setText(Localization.getText("CheckDialog.selectBtn")); + checkBtn.setText(Localization.getText("CheckDialog.checkBtn")); + cancelBtn.setText(Localization.getText("CheckDialog.cancelBtn")); + + List> columns = globalParametersTable.getColumns(); + TableColumn nameCol = new TableColumn<>(NAME); + columns.add(nameCol); + nameCol.setMinWidth(200); + nameCol.setPrefWidth(325); + nameCol.setCellValueFactory(new PropertyValueFactory<>("name")); + + setupValueColumns(columns); + + TableColumn unitCol = new TableColumn<>(UNIT); + columns.add(unitCol); + unitCol.setMinWidth(50); + unitCol.setPrefWidth(75); + unitCol.setMaxWidth(100); + unitCol.setEditable(false); + unitCol.setCellValueFactory(new PropertyValueFactory<>("unit")); + unitCol.setCellFactory(TextFieldTableCell.forTableColumn(new StringConverter() { + + @Override + public String toString(Unit object) { + return object.getRepresentation(); + } + + @Override + public Unit fromString(String string) { + return Unit.valueOf(string); + } + })); + + loadImages(); + + setupSelectButton(); + setupSaveButton(); + setupLoadButton(); + + populateTreeWithChecks(geometricTable, RequirementType.GEOMETRY, true); + populateTreeWithChecks(semanticTable, RequirementType.SEMANTIC, false); + + globalParametersTable.getItems().add(new GlobalParameter(NUMBER_OF_ROUNDING_PLACES, "8", Unit.NONE)); + globalParametersTable.getItems().add(new GlobalParameter("minVertexDistance", "0.0001", Unit.METER)); + + cancelBtn.setOnAction(ea -> stage.close()); + setupCheckButton(); + + tabPane.getSelectionModel().selectedIndexProperty().addListener((v, old, newV) -> { + if (newV.intValue() == 1 && filterPane == null) { + try { + getFilterPane(); + } catch (IOException e) { + window.showExceptionDialog(e); + } + } + }); + + schematronField.setText(ValidationConfiguration.CHECK_FOR_SOLID_XML); + } + + private void setupValueColumns(List> columns) { + TableColumn valueCol = new TableColumn<>(VALUE); + columns.add(valueCol); + valueCol.setMinWidth(150); + valueCol.setPrefWidth(200); + valueCol.setEditable(true); + valueCol.setCellValueFactory(new PropertyValueFactory<>("value")); + valueCol.setCellFactory(column -> new TableEditCell(new DefaultStringConverter()) { + @Override + public void updateItem(String item, boolean empty) { + super.updateItem(item, empty); + if (!empty && item != null) { + GlobalParameter row = (GlobalParameter) getTableRow().getItem(); + if (row == null) { + return; + } + row.setValue(item); + if (NUMBER_OF_ROUNDING_PLACES.equals(row.getName())) { + setEditable(false); + } + } + } + }); + } + + private void setupSelectButton() { + selectBtn.setOnAction(ae -> { + FileChooser chooser = new FileChooser(); + List extensions = new ArrayList<>(); + extensions.add("*.xml"); + String schematronFiles = Localization.getText("CheckDialog.schematronFiles"); + chooser.getExtensionFilters().add(new ExtensionFilter(schematronFiles, extensions)); + File dir = new File(Settings.get(Settings.LAST_OPEN_FOLDER, "")); + if (dir.exists() && dir.isDirectory()) { + chooser.setInitialDirectory(dir); + } + String schematronChooserTitle = Localization.getText("CheckDialog.schematronChooserTitle"); + chooser.setTitle(schematronChooserTitle); + File file = chooser.showOpenDialog(stage); + if (file != null) { + schematronField.setText(file.getAbsolutePath()); + } + }); + } + + private void setupLoadButton() { + loadBtn.setOnAction(ae -> { + FileChooser fc = new FileChooser(); + String validationConfiguration = Localization.getText("CheckDialog.validationConfiguration"); + fc.getExtensionFilters().add(new ExtensionFilter(validationConfiguration, "*.yml")); + File dir = new File(Settings.get(Settings.LAST_OPEN_FOLDER, "")); + if (dir.exists() && dir.isDirectory()) { + fc.setInitialDirectory(dir); + } else { + Settings.set(Settings.LAST_OPEN_FOLDER, ""); + } + File f = fc.showOpenDialog(stage); + if (f != null) { + Settings.set(Settings.LAST_OPEN_FOLDER, f.getParent()); + try { + ValidationConfiguration config = ValidationConfiguration.loadValidationConfig(f.getAbsolutePath()); + applyConfig(config); + } catch (IOException e) { + window.showExceptionDialog(e); + } + } + + }); + } + + private void setupSaveButton() { + saveBtn.setOnAction(ae -> { + ValidationConfiguration config = createConfig(); + FileChooser fc = new FileChooser(); + fc.getExtensionFilters() + .add(new ExtensionFilter(Localization.getText("CheckDialog.validationConfiguration"), "*.yml")); + File dir = new File(Settings.get(Settings.LAST_OPEN_FOLDER, "")); + if (dir.exists() && dir.isDirectory()) { + fc.setInitialDirectory(dir); + } else { + Settings.set(Settings.LAST_OPEN_FOLDER, ""); + } + File f = fc.showSaveDialog(stage); + if (f != null) { + Settings.set(Settings.LAST_OPEN_FOLDER, f.getParent()); + try { + config.saveAs(f); + } catch (IOException e) { + window.showExceptionDialog(e); + } + } + }); + } + + private void applyConfig(ValidationConfiguration config) throws IOException { + FilterConfiguration filter = config.getFilter(); + if (filter != null) { + getFilterPane().applyFilterConfig(filter); + } + Map checks = config.getRequirements(); + for (Entry e : checks.entrySet()) { + for (TreeItem ti : geometricTable.getRoot().getChildren()) { + applyCheckConfig(e, ti); + } + } + globalParametersTable.getItems().clear(); + globalParametersTable.getItems().add(new GlobalParameter(GlobalParameters.NUMBER_OF_ROUNDING_PLACES, + config.getNumberOfRoundingPlacesAsString(), Unit.NONE)); + globalParametersTable.getItems().add(new GlobalParameter(GlobalParameters.MIN_VERTEX_DISTANCE, + config.getMinVertexDistanceAsString(), Unit.METER)); + schematronField.setText(config.getSchematronFilePath()); + } + + private FilterPane getFilterPane() throws IOException { + if (filterPane == null) { + filterPane = new FilterPane(); + Platform.runLater(() -> filterTab.setContent(filterPane.getPane())); + } + return filterPane; + } + + private void applyCheckConfig(Entry e, TreeItem ti) { + Requirement r = ti.getValue().getRequirement(); + RequirementConfiguration cConfig = e.getValue(); + if (r.getId().equals(e.getKey())) { + ti.getValue().getEnabledProperty().set(cConfig.isEnabled()); + for (Entry paramEntry : cConfig.getParameters().entrySet()) { + String name = paramEntry.getKey(); + String value = paramEntry.getValue(); + for (TreeItem configItem : ti.getChildren()) { + TreeRequirement parameterCheck = configItem.getValue(); + if (name.equals(parameterCheck.getNameProperty().getValue())) { + parameterCheck.setValue(value); + } + } + } + } + } + + private boolean collectCheckConfiguration(ValidationConfiguration config) { + collectCheckInformationFromTree(config, geometricTable); + collectCheckInformationFromTree(config, semanticTable); + config.setSchematronFilePathInGlobalParameters(schematronField.getText()); + config.setMinVertexDistanceInGlobalParameters( + Double.parseDouble(globalParametersTable.getItems().get(1).getValue())); + // check if everything is okay with the configuration + config.validateConfiguration(); + return true; + } + + private void collectCheckInformationFromTree(ValidationConfiguration config, TreeTableView table) { + for (TreeItem ti : table.getRoot().getChildren()) { + Requirement r = ti.getValue().getRequirement(); + if (ti.getValue().getEnabledProperty().getValue()) { + RequirementConfiguration cc = config.getRequirements().get(r.getId()); + cc.setEnabled(ti.getValue().isEnabled()); + // collect parameters + collectParameters(cc, ti); + } else { + config.getRequirements().get(r.getId()).setEnabled(false); + } + } + } + + private void loadImages() { + try { + try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/openFolderIcon.png")) { + Image img = new Image(inStream); + loadView.setImage(img); + } + try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/save.png")) { + Image img = new Image(inStream); + saveView.setImage(img); + } + } catch (IOException e) { + // ignore close exception + } + } + + private void setupCheckButton() { + checkBtn.setOnAction(ea -> { + ValidationConfiguration config = createConfig(); + checkBtn.setDisable(true); + cancelBtn.setDisable(true); + stage.setOnCloseRequest(Event::consume); + Thread t = new Thread(() -> { + try { + if (logger.isInfoEnabled()) { + String startingChecks = Localization.getText("CheckDialog.startingChecks"); + logger.info(startingChecks); + } + controller.startChecks(config, progress::setProgress); + if (logger.isInfoEnabled()) { + String checksDone = Localization.getText("CheckDialog.checksDone"); + logger.info(checksDone); + } + } catch (Exception e) { + if (logger.isErrorEnabled()) { + String failedChecks = Localization.getText("CheckDialog.failedChecks"); + logger.error(failedChecks, e); + } + Platform.runLater(() -> { + ExceptionDialog dialog = new ExceptionDialog(); + dialog.show(e); + }); + } finally { + Platform.runLater(() -> { + checkBtn.setDisable(false); + cancelBtn.setDisable(false); + stage.setOnCloseRequest(null); + stage.close(); + }); + } + }); + t.start(); + }); + } + + private ValidationConfiguration createConfig() { + ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig(); + config.setMinVertexDistanceInGlobalParameters( + Double.parseDouble(globalParametersTable.getItems().get(1).getValue())); + if (filterPane != null) { + config.setFilter(filterPane.getConfiguration()); + } + collectCheckConfiguration(config); + if (schematronField.getText().isEmpty()) { + return config; + } + File f = new File(schematronField.getText()); + if (!f.exists() || f.isDirectory() && logger.isWarnEnabled()) { + String schematronFileNotExisting = Localization.getText("CheckDialog.schematronFileNotExisting"); + logger.warn(schematronFileNotExisting); + } else { + config.setSchematronFilePathInGlobalParameters(schematronField.getText()); + } + return config; + } + + private void collectParameters(RequirementConfiguration cc, TreeItem ti) { + Map parameters = new HashMap<>(); + for (TreeItem paramTi : ti.getChildren()) { + String name = paramTi.getValue().getNameProperty().getValue(); + String value = paramTi.getValue().getValueProperty().getValue(); + parameters.put(name, value); + } + cc.setParameters(parameters); + } + + private void createEnableColumn(TreeTableView view) { + TreeTableColumn enableColumn = new TreeTableColumn<>(CHECK_ENABLED); + view.getColumns().add(enableColumn); + enableColumn.setCellValueFactory(param -> { + TreeRequirement check = param.getValue().getValue(); + if (check != null) { + return check.getEnabledProperty(); + } + return null; + }); + + StringConverter converter = new StringConverter<>() { + + @Override + public String toString(Boolean object) { + return " "; + } + + @Override + public Boolean fromString(String string) { + return Boolean.parseBoolean(string); + } + }; + + enableColumn.setCellFactory(list -> new CheckBoxTreeTableCell(null, converter) { + + @Override + public void updateItem(Boolean item, boolean empty) { + super.updateItem(item, empty); + if (empty || item == null) { + setGraphic(null); + setText(null); + } + } + }); + } + + private void createNameColumn(TreeTableView view) { + TreeTableColumn nameColumn = new TreeTableColumn<>(NAME); + nameColumn.setEditable(false); + view.getColumns().add(nameColumn); + nameColumn.setCellValueFactory(param -> { + if (param.getValue().getValue() != null) { + return param.getValue().getValue().getNameProperty(); + } + return null; + }); + } + + private void createValueColumn(TreeTableView view) { + TreeTableColumn valueColumn = new TreeTableColumn<>(VALUE); + view.getColumns().add(valueColumn); + valueColumn.setCellValueFactory(param -> { + if (param.getValue().getValue() != null) { + return param.getValue().getValue().getValueProperty(); + } + return null; + }); + valueColumn.setCellFactory(col -> new TreeEditCell<>(new DefaultStringConverter())); + valueColumn.setPrefWidth(100); + } + + private void createUnitColumn(TreeTableView view) { + TreeTableColumn unitColumn = new TreeTableColumn<>(UNIT); + unitColumn.setEditable(false); + view.getColumns().add(unitColumn); + unitColumn.setCellValueFactory(param -> { + if (param.getValue().getValue() != null) { + return param.getValue().getValue().getUnitProperty(); + } + return null; + }); + } + + private void populateTreeWithChecks(TreeTableView view, RequirementType type, boolean enabled) { + view.setRoot(new TreeItem<>()); + List requirements = new ArrayList<>(Checks.getAvailableRequirements().values()); + Collections.sort(requirements, (r1, r2) -> r1.getId().compareTo(r2.getId())); + for (Requirement r : requirements) { + if (r.getType() != type) { + continue; + } + TreeRequirement treeCheck = new TreeRequirement(r); + treeCheck.setEnabled(enabled); + TreeItem ti = new TreeItem<>(treeCheck); + view.getRoot().getChildren().add(ti); + for (DefaultParameter dp : r.getDefaultParameter()) { + TreeItem dpTi = new TreeItem<>(new TreeRequirement(dp)); + ti.getChildren().add(dpTi); + } + ti.setExpanded(true); + } + } + + public void show() { + Platform.runLater(() -> { + if (controller.getCurrentConfig() != null) { + for (GlobalParameter parameter : globalParametersTable.getItems()) { + if (parameter.getName().equals(NUMBER_OF_ROUNDING_PLACES)) { + parameter.setValue("" + controller.getCurrentConfig().getNumberOfRoundingPlaces()); + } + } + } + globalParametersTable.refresh(); + progress.setProgress(0d); + stage.showAndWait(); + }); + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/CheckStatus.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/CheckStatus.java new file mode 100644 index 0000000000000000000000000000000000000000..615a77d0418797e036f1ea00b7490e280b5b13bd --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/CheckStatus.java @@ -0,0 +1,7 @@ +package de.hft.stuttgart.citydoctor2.gui; + +public enum CheckStatus { + + ERROR, OK, NOT_CHECKED + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/CityDoctorController.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/CityDoctorController.java new file mode 100644 index 0000000000000000000000000000000000000000..fd85e67db65bbf57fc142263858d24f31084ad0f --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/CityDoctorController.java @@ -0,0 +1,1086 @@ +package de.hft.stuttgart.citydoctor2.gui; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.StringJoiner; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Function; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.citygml4j.core.model.core.CityModel; +import org.xml.sax.SAXParseException; + +import de.hft.stuttgart.citydoctor2.check.CheckError; +import de.hft.stuttgart.citydoctor2.check.Checker; +import de.hft.stuttgart.citydoctor2.check.ErrorId; +import de.hft.stuttgart.citydoctor2.check.ValidationConfiguration; +import de.hft.stuttgart.citydoctor2.check.error.SchematronError; +import de.hft.stuttgart.citydoctor2.datastructure.BoundarySurface; +import de.hft.stuttgart.citydoctor2.datastructure.BridgeConstructiveElement; +import de.hft.stuttgart.citydoctor2.datastructure.BridgeObject; +import de.hft.stuttgart.citydoctor2.datastructure.Building; +import de.hft.stuttgart.citydoctor2.datastructure.Installation; +import de.hft.stuttgart.citydoctor2.datastructure.BuildingPart; +import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel; +import de.hft.stuttgart.citydoctor2.datastructure.CityObject; +import de.hft.stuttgart.citydoctor2.datastructure.FeatureType; +import de.hft.stuttgart.citydoctor2.datastructure.Geometry; +import de.hft.stuttgart.citydoctor2.datastructure.LandObject; +import de.hft.stuttgart.citydoctor2.datastructure.Opening; +import de.hft.stuttgart.citydoctor2.datastructure.ReliefObject; +import de.hft.stuttgart.citydoctor2.datastructure.TinObject; +import de.hft.stuttgart.citydoctor2.datastructure.TransportationObject; +import de.hft.stuttgart.citydoctor2.datastructure.Vegetation; +import de.hft.stuttgart.citydoctor2.exceptions.CityDoctorWriteException; +import de.hft.stuttgart.citydoctor2.gui.table.ErrorStat; +import de.hft.stuttgart.citydoctor2.gui.tree.AllBoundarySurfacesNode; +import de.hft.stuttgart.citydoctor2.gui.tree.AllBridgeConstructiveElementsNode; +import de.hft.stuttgart.citydoctor2.gui.tree.AllBridgePartsNode; +import de.hft.stuttgart.citydoctor2.gui.tree.AllBridgesNode; +import de.hft.stuttgart.citydoctor2.gui.tree.AllInstallationsNode; +import de.hft.stuttgart.citydoctor2.gui.tree.AllBuildingPartsNode; +import de.hft.stuttgart.citydoctor2.gui.tree.AllBuildingsNode; +import de.hft.stuttgart.citydoctor2.gui.tree.AllOpeningsNode; +import de.hft.stuttgart.citydoctor2.gui.tree.AllTerrainNode; +import de.hft.stuttgart.citydoctor2.gui.tree.AllTinNode; +import de.hft.stuttgart.citydoctor2.gui.tree.AllTransportationNode; +import de.hft.stuttgart.citydoctor2.gui.tree.AllVegetationNode; +import de.hft.stuttgart.citydoctor2.gui.tree.AllWaterNode; +import de.hft.stuttgart.citydoctor2.gui.tree.BoundarySurfaceNode; +import de.hft.stuttgart.citydoctor2.gui.tree.BridgeConstructiveElementNode; +import de.hft.stuttgart.citydoctor2.gui.tree.BridgeNode; +import de.hft.stuttgart.citydoctor2.gui.tree.InstallationNode; +import de.hft.stuttgart.citydoctor2.gui.tree.BuildingNode; +import de.hft.stuttgart.citydoctor2.gui.tree.BuildingPartNode; +import de.hft.stuttgart.citydoctor2.gui.tree.ButtonRenderable; +import de.hft.stuttgart.citydoctor2.gui.tree.CityObjectNode; +import de.hft.stuttgart.citydoctor2.gui.tree.GeometryNode; +import de.hft.stuttgart.citydoctor2.gui.tree.LandUseNode; +import de.hft.stuttgart.citydoctor2.gui.tree.OpeningNode; +import de.hft.stuttgart.citydoctor2.gui.tree.ReliefNode; +import de.hft.stuttgart.citydoctor2.gui.tree.Renderable; +import de.hft.stuttgart.citydoctor2.gui.tree.TinNode; +import de.hft.stuttgart.citydoctor2.gui.tree.VegetationNode; +import de.hft.stuttgart.citydoctor2.mapper.citygml3.GMLValidationHandler; +import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException; +import de.hft.stuttgart.citydoctor2.parser.CityGmlParser; +import de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException; +import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration; +import de.hft.stuttgart.citydoctor2.parser.ProgressListener; +import de.hft.stuttgart.citydoctor2.utils.Localization; +import javafx.application.Platform; +import javafx.scene.chart.XYChart.Data; +import javafx.scene.chart.XYChart.Series; +import javafx.scene.control.ButtonType; +import javafx.scene.control.Dialog; +import javafx.scene.control.TreeItem; +import javafx.scene.control.TreeView; +import javafx.stage.FileChooser; +import javafx.stage.FileChooser.ExtensionFilter; + +public class CityDoctorController { + + private static final int MAX_FEATURES_PER_CHUNK = 200; + + private static final Logger logger = LogManager.getLogger(CityDoctorController.class); + + private MainWindow mainWindow; + + private CityDoctorModel model; + private ParserConfiguration currentConfig; + private String sourceFile; + + private Checker currentChecker; + + private HighlightController highlightController; + private Renderer renderer; + + private AtomicInteger buildingChunkNr = new AtomicInteger(0); + private AtomicInteger vegetationChunkNr = new AtomicInteger(0); + private AtomicInteger transportationChunkNr = new AtomicInteger(0); + private AtomicInteger bridgeChunkNr = new AtomicInteger(0); + private AtomicInteger waterChunkNr = new AtomicInteger(0); + private AtomicInteger landChunkNr = new AtomicInteger(0); + + public CityDoctorController(MainWindow mainWindow, HighlightController highlightController, Renderer renderer) { + this.mainWindow = mainWindow; + this.highlightController = highlightController; + this.renderer = renderer; + } + + public void loadCityGml(String path, int numberOfRoundingPlaces, ProgressListener l, boolean useValidation) + throws CityGmlParseException, InvalidGmlFileException { + loadCityGml(path, numberOfRoundingPlaces, l, useValidation, false); + } + + public void loadCityGml(String path, int numberOfRoundingPlaces, ProgressListener l, boolean useValidation, + boolean lowMemory) throws CityGmlParseException, InvalidGmlFileException { + try { + Platform.runLater(() -> { + mainWindow.getOpenBtn().setDisable(true); + mainWindow.getWriteReportButton().setDisable(true); + mainWindow.getMeshGroup().getChildren().clear(); + + clearTrees(); + mainWindow.resetSearchBar(); + mainWindow.resetFilterComboBox(); + }); + currentChecker = null; + currentConfig = new ParserConfiguration(numberOfRoundingPlaces, useValidation, lowMemory); + GMLValidationHandler handler = null; + List validationIssues = new ArrayList<>(); + if (useValidation) { + handler = new GMLValidationHandler() { + @Override + public void error(SAXParseException exception) { + if (exception.getLineNumber() >= 0) { + String s = "In line " + exception.getLineNumber() + ":"; + validationIssues.add(s); + } + validationIssues.add(exception.getMessage()); + } + + @Override + public void warning(SAXParseException exception) { + error(exception); + } + + @Override + public void fatalError(SAXParseException exception) { + error(exception); + } + }; + } + model = CityGmlParser.parseCityGmlFile(path, currentConfig, l, handler); + if (!validationIssues.isEmpty()) { + StringJoiner sj = new StringJoiner("\n"); + validationIssues.stream().forEach(sj::add); + throw new InvalidGmlFileException(sj.toString()); + } + mainWindow.getClickHandler().setConfig(currentConfig); + sourceFile = path; + renderer.reset(); + Platform.runLater(() -> { + mainWindow.addFileNameToTitle(path); + mainWindow.getCheckButton().setDisable(false); + mainWindow.getLod1Btn().setDisable(false); + mainWindow.getLod2Btn().setDisable(false); + mainWindow.getLod3Btn().setDisable(false); + mainWindow.getLod4Btn().setDisable(false); + mainWindow.getWorldBtn().setDisable(false); + mainWindow.getSaveBtn().setDisable(false); + buildTrees(); + }); + } finally { + Platform.runLater(() -> mainWindow.getOpenBtn().setDisable(false)); + } + } + + public void buildTrees() { + resetFeatureChunks(); + buildBuildings(model); + buildVegetation(model.getVegetation()); + buildTransportation(model.getTransportation()); + buildBridges(model); + buildWater(model); + buildLand(model); + } + + private void resetFeatureChunks() { + buildingChunkNr.set(0); + vegetationChunkNr.set(0); + transportationChunkNr.set(0); + bridgeChunkNr.set(0); + waterChunkNr.set(0); + landChunkNr.set(0); + } + + private void buildLand(CityDoctorModel model) { + if (model.getLand().isEmpty()) { + return; + } + TreeView landView = mainWindow.getTerrainView(); + TreeItem landRoot = new TreeItem<>(new AllTerrainNode(model.getLand())); + landRoot.setExpanded(true); + landView.setRoot(landRoot); + buildLandFromList(model.getLand(), landView.getRoot()); + addMoreButtonIfNecessary(model.getLand(), landView, landRoot, landChunkNr); + } + + private void buildLandFromList(List list, TreeItem root) { + int landChunk = landChunkNr.get(); + for (int i = landChunk * MAX_FEATURES_PER_CHUNK; i < (landChunk + 1) * MAX_FEATURES_PER_CHUNK + && i < list.size(); i++) { + CityObject land = list.get(i); + Renderable node; + if (land instanceof ReliefObject relief) { + node = new ReliefNode(relief); + } else if (land instanceof TinObject tin) { + node = new TinNode(tin); + } else { + node = new LandUseNode((LandObject) land); + } + TreeItem item = new TreeItem<>(node); + item.setExpanded(true); + root.getChildren().add(item); + createGeometryNodes(land, item); + if (land instanceof ReliefObject relief) { + createTinNodes(relief, item); + } + } + } + + private void createTinNodes(ReliefObject relief, TreeItem item) { + if (relief.getComponents().isEmpty()) { + return; + } + AllTinNode allTinText = new AllTinNode(relief.getComponents()); + TreeItem allBpsTextItem = new TreeItem<>(allTinText); + item.getChildren().add(allBpsTextItem); + + for (TinObject tin : relief.getComponents()) { + TinNode tinNode = new TinNode(tin); + TreeItem tinNodeItem = new TreeItem<>(tinNode); + tinNodeItem.setExpanded(true); + allBpsTextItem.getChildren().add(tinNodeItem); + createGeometryNodes(tin, tinNodeItem); + } + } + + private void buildWater(CityDoctorModel model) { + if (model.getWater().isEmpty()) { + return; + } + TreeView waterView = mainWindow.getWaterView(); + TreeItem waterRoot = new TreeItem<>(new AllWaterNode(model.getWater())); + waterRoot.setExpanded(true); + waterView.setRoot(waterRoot); + buildTreeFromList(model.getWater(), waterView.getRoot(), waterChunkNr); + addMoreButtonIfNecessary(model.getWater(), waterView, waterRoot, waterChunkNr); + } + + private void buildBridges(CityDoctorModel model) { + if (model.getBridges().isEmpty()) { + return; + } + TreeView bridgeView = mainWindow.getBridgeView(); + TreeItem bridgeRoot = new TreeItem<>(new AllBridgesNode(model.getBridges())); + bridgeRoot.setExpanded(true); + bridgeView.setRoot(bridgeRoot); + buildBridgeTreeFromList(model.getBridges(), bridgeView.getRoot()); + addMoreButtonIfNecessary(model.getBridges(), bridgeView, bridgeRoot, bridgeChunkNr); + } + + private void buildTransportation(List trans) { + if (trans.isEmpty()) { + return; + } + TreeView transView = mainWindow.getTransportationView(); + TreeItem transRoot = new TreeItem<>(new AllTransportationNode(model.getTransportation())); + transRoot.setExpanded(true); + transView.setRoot(transRoot); + buildTreeFromList(trans, transView.getRoot(), transportationChunkNr); + addMoreButtonIfNecessary(trans, transView, transRoot, transportationChunkNr); + } + + private void buildVegetation(List veg) { + if (veg.isEmpty()) { + return; + } + TreeView vegetationsView = mainWindow.getVegetationView(); + TreeItem vegRoot = new TreeItem<>(new AllVegetationNode(model.getVegetation())); + vegRoot.setExpanded(true); + vegetationsView.setRoot(vegRoot); + buildTreeFromListWithProducer(veg, vegetationsView.getRoot(), vegetationChunkNr, VegetationNode::new); + addMoreButtonIfNecessary(veg, vegetationsView, vegRoot, vegetationChunkNr); + } + + private void addMoreButtonIfNecessary(List list, TreeView view, + TreeItem root, AtomicInteger chunkCounter) { + if ((chunkCounter.get() + 1) * MAX_FEATURES_PER_CHUNK < list.size()) { + Runnable run = new Runnable() { + public void run() { + // 29 is the height of one item + int numberOfDisplayedItems = (int) (view.getHeight() / 29); + int selectedIndex = view.getSelectionModel().getSelectedIndex(); + // remove button node + root.getChildren().remove(root.getChildren().size() - 1); + chunkCounter.incrementAndGet(); + int visibleFeatures = countVisibleNodes(view); + buildTreeFromList(list, root, chunkCounter); + updateTree(root); + if (selectedIndex >= 0) { + view.getSelectionModel().select(selectedIndex); + } + if ((chunkCounter.get() + 1) * MAX_FEATURES_PER_CHUNK < list.size()) { + root.getChildren().add(new TreeItem<>(new ButtonRenderable(this))); + } + view.scrollTo(visibleFeatures - numberOfDisplayedItems + 1); + } + }; + // add button for expansion + root.getChildren().add(new TreeItem<>(new ButtonRenderable(run))); + } + } + + private void buildBuildings(CityDoctorModel model) { + if (model.getBuildings().isEmpty()) { + return; + } + TreeView buildingsView = mainWindow.getBuildingsView(); + TreeItem root = new TreeItem<>(new AllBuildingsNode(model.getBuildings())); + root.setExpanded(true); + buildBuildingTreeFromList(model.getBuildings(), root); + addMoreButtonToBuildingsIfNecessary(model.getBuildings(), buildingsView, root, buildingChunkNr); + buildingsView.setRoot(root); + } + + private void addMoreButtonToBuildingsIfNecessary(List list, TreeView view, + TreeItem root, AtomicInteger chunkCounter) { + if ((chunkCounter.get() + 1) * MAX_FEATURES_PER_CHUNK < list.size()) { + Runnable run = new Runnable() { + public void run() { + // 29 is the height of one item + int numberOfDisplayedItems = (int) (view.getHeight() / 29); + int selectedIndex = view.getSelectionModel().getSelectedIndex(); + // remove button node + root.getChildren().remove(root.getChildren().size() - 1); + chunkCounter.getAndIncrement(); + int visibleFeatures = countVisibleNodes(view); + buildBuildingTreeFromList(list, root); + updateTree(root); + if (selectedIndex >= 0) { + view.getSelectionModel().select(selectedIndex); + } + if ((chunkCounter.get() + 1) * MAX_FEATURES_PER_CHUNK < list.size()) { + root.getChildren().add(new TreeItem<>(new ButtonRenderable(this))); + } + view.scrollTo(visibleFeatures - numberOfDisplayedItems + 1); + } + }; + // add button for expansion + root.getChildren().add(new TreeItem<>(new ButtonRenderable(run))); + } + } + + private static int countVisibleNodes(TreeView view) { + return countVisibleNodes(view.getRoot()) + 1; + } + + private static int countVisibleNodes(TreeItem root) { + int visibleFeatures = root.getChildren().size(); + for (TreeItem child : root.getChildren()) { + if (!child.getChildren().isEmpty() && child.isExpanded()) { + visibleFeatures += countVisibleNodes(child); + } + } + return visibleFeatures; + } + + private void buildTreeFromList(List cos, TreeItem root, + AtomicInteger chunkCounter) { + int chunk = chunkCounter.get(); + for (int i = chunk * MAX_FEATURES_PER_CHUNK; i < (chunk + 1) * MAX_FEATURES_PER_CHUNK && i < cos.size(); i++) { + CityObject co = cos.get(i); + CityObjectNode node = new CityObjectNode(co); + TreeItem nodeItem = new TreeItem<>(node); + nodeItem.setExpanded(true); + root.getChildren().add(nodeItem); + createGeometryNodes(co, nodeItem); + } + } + + private void buildTreeFromListWithProducer(List cos, TreeItem root, + AtomicInteger chunkCounter, Function nodeProducer) { + int chunk = chunkCounter.get(); + for (int i = chunk * MAX_FEATURES_PER_CHUNK; i < (chunk + 1) * MAX_FEATURES_PER_CHUNK && i < cos.size(); i++) { + T co = cos.get(i); + Renderable node = nodeProducer.apply(co); + TreeItem nodeItem = new TreeItem<>(node); + nodeItem.setExpanded(true); + root.getChildren().add(nodeItem); + createGeometryNodes(co, nodeItem); + } + } + + private void clearTrees() { + mainWindow.getBuildingsView().setRoot(null); + mainWindow.getVegetationView().setRoot(null); + mainWindow.getTransportationView().setRoot(null); + mainWindow.getBridgeView().setRoot(null); + mainWindow.getWaterView().setRoot(null); + mainWindow.getTerrainView().setRoot(null); + mainWindow.getErrorTree().getRoot().getChildren().clear(); + mainWindow.getGlobalErrorsView().getItems().clear(); + clearGeometryTrees(); + } + + private void clearGeometryTrees() { + highlightController.clearHighlights(); + mainWindow.getPolygonsView().getRoot().getChildren().clear(); + mainWindow.getEdgeView().getRoot().getChildren().clear(); + mainWindow.getVertexView().getRoot().getChildren().clear(); + } + + private void buildBuildingTreeFromList(List list, TreeItem root) { + int buildingChunk = buildingChunkNr.get(); + for (int i = buildingChunk * MAX_FEATURES_PER_CHUNK; i < (buildingChunk + 1) * MAX_FEATURES_PER_CHUNK + && i < list.size(); i++) { + Building b = list.get(i); + BuildingNode node = new BuildingNode(b); + TreeItem item = new TreeItem<>(node); + item.setExpanded(true); + root.getChildren().add(item); + createGeometryNodes(b, item); + createBoundarySurfaceNodes(b.getBoundarySurfaces(), item); + createBuildingInstallationNodes(b, item); + createBuildingPartNodes(b, item); + } + } + + private void buildBridgeTreeFromList(List list, TreeItem root) { + int bridgeChunk = bridgeChunkNr.get(); + for (int i = bridgeChunk * MAX_FEATURES_PER_CHUNK; i < (bridgeChunk + 1) * MAX_FEATURES_PER_CHUNK + && i < list.size(); i++) { + BridgeObject bridge = list.get(i); + BridgeNode node = new BridgeNode(bridge); + TreeItem item = new TreeItem<>(node); + item.setExpanded(true); + root.getChildren().add(item); + createGeometryNodes(bridge, item); + createBoundarySurfaceNodes(bridge.getBoundarySurfaces(), item); + createBridgeInstallationNodes(bridge, item); + createConstructiveElementsNodes(bridge, item); + createBridgePartNodes(bridge, item); + } + + } + + private void createBridgeInstallationNodes(BridgeObject bridge, TreeItem root) { + createInstallationNodes(bridge.getBridgeInstallations(), root); + } + + private void createConstructiveElementsNodes(BridgeObject bridge, TreeItem item) { + if (bridge.getConstructiveElements().isEmpty()) { + return; + } + AllBridgeConstructiveElementsNode allBceNode = new AllBridgeConstructiveElementsNode( + bridge.getConstructiveElements()); + TreeItem allBceNodeTextItem = new TreeItem<>(allBceNode); + item.getChildren().add(allBceNodeTextItem); + + for (BridgeConstructiveElement bce : bridge.getConstructiveElements()) { + BridgeConstructiveElementNode bceNode = new BridgeConstructiveElementNode(bce); + TreeItem bpNodeItem = new TreeItem<>(bceNode); + bpNodeItem.setExpanded(true); + allBceNodeTextItem.getChildren().add(bpNodeItem); + createGeometryNodes(bce, bpNodeItem); + createBoundarySurfaceNodes(bce.getBoundarySurfaces(), bpNodeItem); + } + } + + private void createBridgePartNodes(BridgeObject bridge, TreeItem item) { + if (bridge.getParts().isEmpty()) { + return; + } + AllBridgePartsNode allBpsText = new AllBridgePartsNode(bridge.getParts()); + TreeItem allBpsTextItem = new TreeItem<>(allBpsText); + item.getChildren().add(allBpsTextItem); + + for (BridgeObject bp : bridge.getParts()) { + BridgeNode bpNode = new BridgeNode(bp); + TreeItem bpNodeItem = new TreeItem<>(bpNode); + bpNodeItem.setExpanded(true); + allBpsTextItem.getChildren().add(bpNodeItem); + createGeometryNodes(bp, bpNodeItem); + createBoundarySurfaceNodes(bp.getBoundarySurfaces(), bpNodeItem); + } + } + + private void createBuildingInstallationNodes(Building ab, TreeItem root) { + createInstallationNodes(ab.getBuildingInstallations(), root); + } + + private void createInstallationNodes(List installations, TreeItem root) { + if (installations.isEmpty()) { + return; + } + + AllInstallationsNode allBiNode = new AllInstallationsNode(installations); + TreeItem allBpsTextItem = new TreeItem<>(allBiNode); + root.getChildren().add(allBpsTextItem); + for (Installation bi : installations) { + InstallationNode biNode = new InstallationNode(bi); + TreeItem biItem = new TreeItem<>(biNode); + biItem.setExpanded(true); + allBpsTextItem.getChildren().add(biItem); + createGeometryNodes(bi, biItem); + createBoundarySurfaceNodes(bi.getBoundarySurfaces(), biItem); + } + } + + private void createBoundarySurfaceNodes(List bsList, TreeItem root) { + if (bsList.isEmpty()) { + return; + } + AllBoundarySurfacesNode allBsText = new AllBoundarySurfacesNode(bsList); + TreeItem allBpsTextItem = new TreeItem<>(allBsText); + root.getChildren().add(allBpsTextItem); + + allBpsTextItem.getChildren().add(new TreeItem<>()); + + allBpsTextItem.expandedProperty().addListener((obs, old, newV) -> { + if (Boolean.TRUE.equals(newV) && allBpsTextItem.getChildren().size() == 1) { + Platform.runLater(() -> { + allBpsTextItem.getChildren().clear(); + for (BoundarySurface bs : bsList) { + BoundarySurfaceNode bsText = new BoundarySurfaceNode(bs); + TreeItem bsTextItem = new TreeItem<>(bsText); + bsTextItem.setExpanded(true); + allBpsTextItem.getChildren().add(bsTextItem); + createGeometryNodes(bs, bsTextItem); + createOpeningNodes(bs.getOpenings(), bsTextItem); + } + updateTree(allBpsTextItem); + }); + } + }); + } + + private void createOpeningNodes(List openings, TreeItem root) { + if (openings == null || openings.isEmpty()) { + return; + } + AllOpeningsNode allOpeningsNode = new AllOpeningsNode(openings); + TreeItem allOpeningsItem = new TreeItem<>(allOpeningsNode); + for (Opening o : openings) { + OpeningNode openingNode = new OpeningNode(o); + TreeItem openingsItem = new TreeItem<>(openingNode); + allOpeningsItem.getChildren().add(openingsItem); + } + root.getChildren().add(allOpeningsItem); + } + + private void createBuildingPartNodes(Building ab, TreeItem item) { + if (ab.getBuildingParts().isEmpty()) { + return; + } + AllBuildingPartsNode allBpsText = new AllBuildingPartsNode(ab.getBuildingParts()); + TreeItem allBpsTextItem = new TreeItem<>(allBpsText); + item.getChildren().add(allBpsTextItem); + + for (BuildingPart bp : ab.getBuildingParts()) { + BuildingPartNode bpNode = new BuildingPartNode(bp); + TreeItem bpNodeItem = new TreeItem<>(bpNode); + bpNodeItem.setExpanded(true); + allBpsTextItem.getChildren().add(bpNodeItem); + createGeometryNodes(bp, bpNodeItem); + createBoundarySurfaceNodes(bp.getBoundarySurfaces(), bpNodeItem); + } + } + + private void createGeometryNodes(CityObject co, TreeItem item) { + for (Geometry geom : co.getGeometries()) { + GeometryNode geomNode = new GeometryNode(geom); + TreeItem geomItem = new TreeItem<>(geomNode); + item.getChildren().add(geomItem); + } + } + + public void startChecks(ValidationConfiguration config, ProgressListener l) { + if (model == null) { + logger.warn(Localization.getText("CityDoctorController.noDatamodel")); + return; + } + if (sourceFile == null) { + logger.warn(Localization.getText("CityDoctorController.noSourceFile")); + return; + } + try { + Platform.runLater(() -> { + mainWindow.getCheckButton().setDisable(true); + mainWindow.getErrorTree().getRoot().getChildren().clear(); + mainWindow.getGlobalErrorsView().getItems().clear(); + }); + config.setNumberOfRoundingPlacesInGlobalParameters(currentConfig.getNumberOfRoundingPlaces()); + config.setParserConfig(currentConfig); + currentChecker = new Checker(config, model); + currentChecker.runChecks(l); + + Platform.runLater(() -> { + // apply check results to tree views + updateFeatureTrees(); + updateTree(mainWindow.getPolygonsView().getRoot()); + for (CheckError e : model.getGlobalErrors()) { + if (e instanceof SchematronError se) { + mainWindow.getGlobalErrorsView().getItems().add(se.getErrorIdString()); + } + } + renderer.refresh(); + mainWindow.getWriteReportButton().setDisable(false); + }); + } finally { + Platform.runLater(() -> mainWindow.getCheckButton().setDisable(false)); + } + } + + void updateFeatureTrees() { + updateTree(mainWindow.getBuildingsView().getRoot()); + updateTree(mainWindow.getVegetationView().getRoot()); + updateTree(mainWindow.getBridgeView().getRoot()); + updateTree(mainWindow.getTerrainView().getRoot()); + updateTree(mainWindow.getTransportationView().getRoot()); + updateTree(mainWindow.getWaterView().getRoot()); + renderer.updateErrors(); + } + + private void updateTree(TreeItem root) { + if (root == null) { + return; + } + for (TreeItem item : root.getChildren()) { + updateItem(item); + } + } + + private void updateItem(TreeItem item) { + if (item.getValue() == null) { + return; + } + item.getValue().refreshTextColor(); + for (TreeItem child : item.getChildren()) { + updateItem(child); + } + } + + public void writePdfReport(File pdfFile) { + if (currentChecker == null) { + return; + } + currentChecker.writePdfReport(pdfFile.getAbsolutePath()); + } + + public void writeXmlReport(File xmlFile) { + if (currentChecker == null) { + return; + } + currentChecker.writeXmlReport(xmlFile.getAbsolutePath()); + } + + private Map getErrorStats() { + Map stats = new HashMap<>(); + addErrorStats(stats, model.getBridges()); + addErrorStats(stats, model.getBuildings()); + addErrorStats(stats, model.getLand()); + addErrorStats(stats, model.getTransportation()); + addErrorStats(stats, model.getVegetation()); + addErrorStats(stats, model.getWater()); + return stats; + } + + private void addErrorStats(Map stats, List cos) { + List errors = new ArrayList<>(); + for (CityObject co : cos) { + co.collectContainedErrors(errors); + } + Set filteredErrors = new HashSet<>(errors); + for (CheckError error : filteredErrors) { + ErrorStat stat = stats.computeIfAbsent(error.getErrorId(), ErrorStat::new); + stat.incrementCount(); + } + } + + public void export(Building b) { + if (model == null) { + return; + } + CityDoctorModel newModel = new CityDoctorModel(model.getParserConfig(), model.getFile()); + newModel.setCityModel(new CityModel()); + newModel.addBuilding(b); + + FileChooser fc = new FileChooser(); + fc.getExtensionFilters().add(new ExtensionFilter("CityGML", "*.gml")); + fc.getExtensionFilters().add(new ExtensionFilter("OFF - Object File Format", "*.off")); + File dir = new File(Settings.get(Settings.LAST_OPEN_FOLDER, "")); + if (dir.exists() && dir.isDirectory()) { + fc.setInitialDirectory(dir); + } else { + Settings.set(Settings.LAST_OPEN_FOLDER, ""); + } + File f = fc.showSaveDialog(mainWindow.getMainStage()); + if (f != null) { + Settings.set(Settings.LAST_OPEN_FOLDER, f.getParent()); + try { + + newModel.saveAs(f.getAbsolutePath(), true); + } catch (CityDoctorWriteException e) { + logger.error(e); + } + } + } + + public void showWorld() { + if (model != null) { + renderer.render(model); + } + } + + public void storeModel(File f, boolean saveQualityAde) throws CityDoctorWriteException { + if (model == null) { + return; + } + model.saveAs(f.getAbsolutePath(), saveQualityAde); + } + + public void searchFeature(String searchString, FeatureType selectedTab) { + if (model == null || searchString == null || searchString.trim().isEmpty()) { + return; + } + mainWindow.unselectEverything(); + resetFeatureChunks(); + if (selectedTab == FeatureType.BUILDING) { + List foundBuildings = filterFeatures(searchString, model.getBuildings()); + TreeView buildingsView = mainWindow.getBuildingsView(); + TreeItem root = buildingsView.getRoot(); + root.getChildren().clear(); + buildBuildingTreeFromList(foundBuildings, root); + updateTree(root); + addMoreButtonToBuildingsIfNecessary(foundBuildings, buildingsView, root, buildingChunkNr); + } else { + TreeView view; + List cos; + AtomicInteger chunkCounter; + switch (selectedTab) { + case VEGETATION: + view = mainWindow.getVegetationView(); + cos = filterFeatures(searchString, model.getVegetation()); + chunkCounter = vegetationChunkNr; + break; + case BRIDGE: + view = mainWindow.getBridgeView(); + cos = filterFeatures(searchString, model.getBridges()); + chunkCounter = bridgeChunkNr; + break; + case TRANSPORTATION: + view = mainWindow.getTransportationView(); + cos = filterFeatures(searchString, model.getTransportation()); + chunkCounter = transportationChunkNr; + break; + case WATER: + view = mainWindow.getWaterView(); + cos = filterFeatures(searchString, model.getWater()); + chunkCounter = waterChunkNr; + break; + case LAND: + view = mainWindow.getTerrainView(); + cos = filterFeatures(searchString, model.getLand()); + chunkCounter = landChunkNr; + break; + default: + throw new IllegalStateException("Unknown selected feature tab"); + } + TreeItem root = view.getRoot(); + root.getChildren().clear(); + buildTreeFromList(cos, root, chunkCounter); + updateTree(root); + addMoreButtonIfNecessary(cos, view, root, chunkCounter); + } + } + + private List filterFeatures(String searchString, List features) { + List foundFeatures = new ArrayList<>(); + for (T t : features) { + if (t.getGmlId().getGmlString().contains(searchString)) { + foundFeatures.add(t); + } + } + return foundFeatures; + } + + public void resetSearch(FeatureType selectedTab) { + if (model == null) { + return; + } + resetFeatureChunks(); + if (selectedTab == FeatureType.BUILDING) { + // buildings are handled differently, because of surface and building + // installations + TreeItem root = mainWindow.getBuildingsView().getRoot(); + if (root != null) { + root.getChildren().clear(); + buildBuildingTreeFromList(model.getBuildings(), root); + updateTree(root); + addMoreButtonToBuildingsIfNecessary(model.getBuildings(), mainWindow.getBuildingsView(), root, + buildingChunkNr); + } + } else { + TreeView view; + List cos; + AtomicInteger chunkCounter; + switch (selectedTab) { + case VEGETATION: + view = mainWindow.getVegetationView(); + cos = model.getVegetation(); + chunkCounter = vegetationChunkNr; + break; + case BRIDGE: + view = mainWindow.getBridgeView(); + cos = model.getBridges(); + chunkCounter = bridgeChunkNr; + break; + case TRANSPORTATION: + view = mainWindow.getTransportationView(); + cos = model.getTransportation(); + chunkCounter = transportationChunkNr; + break; + case WATER: + view = mainWindow.getWaterView(); + cos = model.getWater(); + chunkCounter = waterChunkNr; + break; + case LAND: + view = mainWindow.getTerrainView(); + cos = model.getLand(); + chunkCounter = landChunkNr; + break; + default: + throw new IllegalStateException("Unknown selected feature tab"); + } + TreeItem root = view.getRoot(); + root.getChildren().clear(); + buildTreeFromList(cos, root, chunkCounter); + updateTree(root); + addMoreButtonIfNecessary(cos, view, root, chunkCounter); + } + } + + public Series createErrorSeries() { + Series series = new Series<>(); + if (model == null) { + return series; + } + Map errorStats = getErrorStats(); + for (ErrorStat es : errorStats.values()) { + series.getData().add(new Data<>(es.getErrorId().toString(), es.getCount())); + } + return series; + } + + public String getFileName() { + return model.getFileName(); + } + + public void fillTreeViewWithErrorBuildings() { + TreeView buildingsView = mainWindow.getBuildingsView(); + TreeItem root = buildingsView.getRoot(); + if (model == null) { + return; + } + if (root == null) { + return; + } + mainWindow.resetSearchBar(); + root.getChildren().clear(); + List errorBuildings = new ArrayList<>(); + for (Building b : model.getBuildings()) { + if (b.containsAnyError()) { + errorBuildings.add(b); + } + } + resetFeatureChunks(); + buildBuildingTreeFromList(errorBuildings, root); + updateTree(root); + addMoreButtonToBuildingsIfNecessary(errorBuildings, buildingsView, root, buildingChunkNr); + } + + public void fillTreeViewWithErrorVegetation() { + if (model == null) { + return; + } + fillTreeViewWithErrorCityObjects(mainWindow.getVegetationView(), model.getVegetation(), vegetationChunkNr); + } + + public void fillTreeViewWithErrorBridges() { + if (model == null) { + return; + } + fillTreeViewWithErrorCityObjects(mainWindow.getBridgeView(), model.getBridges(), bridgeChunkNr); + } + + public void fillTreeViewWithErrorLand() { + if (model == null) { + return; + } + fillTreeViewWithErrorCityObjects(mainWindow.getTerrainView(), model.getLand(), landChunkNr); + } + + public void fillTreeViewWithErrorTransportation() { + if (model == null) { + return; + } + fillTreeViewWithErrorCityObjects(mainWindow.getTransportationView(), model.getTransportation(), + transportationChunkNr); + } + + public void fillTreeViewWithErrorWater() { + if (model == null) { + return; + } + fillTreeViewWithErrorCityObjects(mainWindow.getWaterView(), model.getWater(), waterChunkNr); + } + + private void fillTreeViewWithErrorCityObjects(TreeView treeView, List objects, + AtomicInteger chunkCounter) { + TreeItem root = treeView.getRoot(); + if (root == null) { + return; + } + mainWindow.resetSearchBar(); + root.getChildren().clear(); + List errorObjects = new ArrayList<>(); + for (CityObject co : objects) { + if (co.containsAnyError()) { + errorObjects.add(co); + } + } + buildTreeFromList(errorObjects, root, chunkCounter); + updateTree(root); + addMoreButtonIfNecessary(errorObjects, treeView, root, chunkCounter); + } + + public void fillTreeViewFromFeatures(FeatureType selectedTab) { + if (model == null) { + return; + } + mainWindow.resetSearchBar(); + switch (selectedTab) { + case BUILDING: + buildBuildings(model); + updateTree(mainWindow.getBuildingsView().getRoot()); + break; + case VEGETATION: + buildVegetation(model.getVegetation()); + updateTree(mainWindow.getVegetationView().getRoot()); + break; + case BRIDGE: + buildBridges(model); + updateTree(mainWindow.getBridgeView().getRoot()); + break; + case LAND: + buildLand(model); + updateTree(mainWindow.getTerrainView().getRoot()); + break; + case TRANSPORTATION: + buildTransportation(model.getTransportation()); + updateTree(mainWindow.getTransportationView().getRoot()); + break; + case WATER: + buildWater(model); + updateTree(mainWindow.getWaterView().getRoot()); + break; + default: + throw new IllegalStateException(); + } + } + + public CityDoctorModel getModel() { + return model; + } + + public void showView(View v) { + v.fireOnShowEvent(model, currentChecker, mainWindow); + } + + public void askAndSave() { + boolean saveWithQualityAde = true; + if (model.isValidated()) { + ButtonType yesBtn = ButtonType.YES; + ButtonType noBtn = ButtonType.NO; + Dialog dialog = new Dialog<>(); + dialog.setTitle("Save with QualityADE?"); + dialog.setContentText("Save with QualityADE information?"); + dialog.getDialogPane().getButtonTypes().add(yesBtn); + dialog.getDialogPane().getButtonTypes().add(noBtn); + + Optional result = dialog.showAndWait(); + if (result.isPresent() && result.get() == ButtonType.NO) { + saveWithQualityAde = false; + } + } + + FileChooser fc = new FileChooser(); + fc.getExtensionFilters().add(new ExtensionFilter("CityGML", "*.gml")); + fc.getExtensionFilters().add(new ExtensionFilter("OFF - Object File Format", "*.off")); + File dir = new File(Settings.get(Settings.LAST_OPEN_FOLDER, "")); + if (dir.exists() && dir.isDirectory()) { + fc.setInitialDirectory(dir); + } else { + Settings.set(Settings.LAST_OPEN_FOLDER, ""); + } + File f = fc.showSaveDialog(mainWindow.getMainStage()); + if (f != null) { + Settings.set(Settings.LAST_OPEN_FOLDER, f.getParent()); + try { + storeModel(f, saveWithQualityAde); + } catch (CityDoctorWriteException e) { + mainWindow.showExceptionDialog(e); + } + } + } + + public void delete(TreeItem selectedItem) { + if (model == null) { + return; + } + Renderable render = selectedItem.getValue(); + if (render instanceof BuildingNode node) { + model.getBuildings().remove(node.getBuilding()); + mainWindow.getBuildingsView().getRoot().getChildren().remove(selectedItem); + } + + } + + public void errorFilterIndexChanged(Number newV) { + mainWindow.getMeshGroup().getChildren().clear(); + mainWindow.unselectEverything(); + if (newV.intValue() == 0) { + fillTreeViewFromFeatures(mainWindow.getSelectedTab()); + } else if (newV.intValue() == 1) { + switch (mainWindow.getSelectedTab()) { + case BUILDING: + fillTreeViewWithErrorBuildings(); + break; + case VEGETATION: + fillTreeViewWithErrorVegetation(); + break; + case BRIDGE: + fillTreeViewWithErrorBridges(); + break; + case LAND: + fillTreeViewWithErrorLand(); + break; + case TRANSPORTATION: + fillTreeViewWithErrorTransportation(); + break; + case WATER: + fillTreeViewWithErrorWater(); + break; + default: + throw new IllegalStateException("Unknown selected feature tab: " + mainWindow.getSelectedTab()); + } + } else { + throw new IllegalStateException("Unknown filter index selected: " + newV); + } + } + + public ParserConfiguration getCurrentConfig() { + return currentConfig; + } +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/CityDoctorGUIStarter.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/CityDoctorGUIStarter.java new file mode 100644 index 0000000000000000000000000000000000000000..e15c9f7710c1a3e114f71576e604bf701080d411 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/CityDoctorGUIStarter.java @@ -0,0 +1,27 @@ +/*- + * Copyright 2022 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart + * + * This file is part of CityDoctor2. + * + * CityDoctor2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CityDoctor2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with CityDoctor2. If not, see . + */ +package de.hft.stuttgart.citydoctor2.gui; + +public class CityDoctorGUIStarter { + + public static void main(String[] args) { + MainWindow.main(args); + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/ClickDispatcher.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/ClickDispatcher.java new file mode 100644 index 0000000000000000000000000000000000000000..bff71d11596a2122f2fe770881b8b4b3d068a2ae --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/ClickDispatcher.java @@ -0,0 +1,9 @@ +package de.hft.stuttgart.citydoctor2.gui; + +import javafx.scene.input.MouseEvent; + +public interface ClickDispatcher { + + public void click(MouseEvent me, ClickHandler handler); + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/ClickHandler.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/ClickHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..1211ca93786f26c382b598fcea9578f6c4853135 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/ClickHandler.java @@ -0,0 +1,13 @@ +package de.hft.stuttgart.citydoctor2.gui; + +import de.hft.stuttgart.citydoctor2.datastructure.Polygon; +import de.hft.stuttgart.citydoctor2.datastructure.Vertex; +import javafx.scene.input.MouseEvent; + +public interface ClickHandler { + + public void onPolygonClick(Polygon p, MouseEvent me); + + public void onVertexClick(Vertex v, MouseEvent me); + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/ExceptionDialog.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/ExceptionDialog.java new file mode 100644 index 0000000000000000000000000000000000000000..56d6b8d4c45deaeb7e2773beef078607c65b9b1a --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/ExceptionDialog.java @@ -0,0 +1,56 @@ +package de.hft.stuttgart.citydoctor2.gui; + +import java.io.PrintWriter; +import java.io.StringWriter; + +import de.hft.stuttgart.citydoctor2.utils.Localization; +import javafx.scene.control.Alert; +import javafx.scene.control.Alert.AlertType; +import javafx.scene.control.Label; +import javafx.scene.control.TextArea; +import javafx.scene.layout.GridPane; +import javafx.scene.layout.Priority; + +public class ExceptionDialog { + + private Alert alert; + + private TextArea textArea; + + public ExceptionDialog() { + alert = new Alert(AlertType.ERROR); + alert.setTitle("Exception Dialog"); + alert.getDialogPane().setPrefWidth(800); + Label label = new Label(Localization.getText("ExceptionDialog.stacktrace")); + + textArea = new TextArea(); + textArea.setEditable(false); + textArea.setWrapText(true); + + textArea.setMaxWidth(Double.MAX_VALUE); + textArea.setMaxHeight(Double.MAX_VALUE); + GridPane.setVgrow(textArea, Priority.ALWAYS); + GridPane.setHgrow(textArea, Priority.ALWAYS); + + GridPane expContent = new GridPane(); + expContent.setMaxWidth(Double.MAX_VALUE); + expContent.add(label, 0, 0); + expContent.add(textArea, 0, 1); + + // Set expandable Exception into the dialog pane. + alert.getDialogPane().setExpandableContent(expContent); + } + + public void show(Throwable ex) { + // Create expandable Exception. + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + ex.printStackTrace(pw); + String exceptionText = sw.toString(); + textArea.setText(exceptionText); + alert.setContentText(ex.getMessage()); + alert.setHeaderText(ex.getClass().getSimpleName()); + alert.showAndWait(); + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/FilterPane.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/FilterPane.java new file mode 100644 index 0000000000000000000000000000000000000000..a82b30adc0d15402e66d0dcfee8c1ba0cc972fba --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/FilterPane.java @@ -0,0 +1,305 @@ +package de.hft.stuttgart.citydoctor2.gui; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +import de.hft.stuttgart.citydoctor2.check.ExcludeFilterConfiguration; +import de.hft.stuttgart.citydoctor2.check.FilterConfiguration; +import de.hft.stuttgart.citydoctor2.check.IncludeFilterConfiguration; +import de.hft.stuttgart.citydoctor2.datastructure.FeatureType; +import de.hft.stuttgart.citydoctor2.gui.filter.TypeFilterSelection; +import de.hft.stuttgart.citydoctor2.utils.Localization; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.control.Button; +import javafx.scene.control.ComboBox; +import javafx.scene.control.ScrollPane; +import javafx.scene.control.TextField; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.layout.HBox; +import javafx.scene.layout.VBox; + +public class FilterPane { + + @FXML + private VBox inclFeatureBox; + + @FXML + private ImageView addInclFeatureView; + + @FXML + private VBox inclMatchBox; + + @FXML + private ImageView addInclMatchView; + + @FXML + private Button addInclFeatureBtn; + + @FXML + private Button addInclMatchBtn; + + @FXML + private VBox exclFeatureBox; + + @FXML + private ImageView addExclFeatureView; + + @FXML + private VBox exclMatchBox; + + @FXML + private ImageView addExclMatchView; + + @FXML + private Button addExclFeatureBtn; + + @FXML + private Button addExclMatchBtn; + + private ScrollPane pane; + private Image deleteImg; + + private List> includeTypeBoxes = new ArrayList<>(); + private List includeMatcherFields = new ArrayList<>(); + + private List excludeMatcherFields = new ArrayList<>(); + + private List> excludeTypeBoxes = new ArrayList<>(); + + private List availableFilters; + + public FilterPane() throws IOException { + FXMLLoader fxmlLoader = new FXMLLoader(FilterPane.class.getResource("FilterPane.fxml")); + fxmlLoader.setController(this); + pane = fxmlLoader.load(); + } + + public void initialize() { + loadImages(); + + availableFilters = new ArrayList<>(); + availableFilters.add(new TypeFilterSelection(FeatureType.BUILDING, Localization.getText("FilterPane.buildings"))); + availableFilters.add(new TypeFilterSelection(FeatureType.BRIDGE, Localization.getText("FilterPane.bridges"))); + availableFilters.add(new TypeFilterSelection(FeatureType.LAND, Localization.getText("FilterPane.landUse"))); + availableFilters.add(new TypeFilterSelection(FeatureType.TRANSPORTATION, Localization.getText("FilterPane.transportation"))); + availableFilters.add(new TypeFilterSelection(FeatureType.VEGETATION, Localization.getText("FilterPane.vegetation"))); + availableFilters.add(new TypeFilterSelection(FeatureType.WATER, Localization.getText("FilterPane.water"))); + setupIncludeFeatureButton(); + setupIncludeMatchButton(); + setupExcludeFeatureButton(); + setupExcludeMatchButton(); + } + + private void setupExcludeMatchButton() { + addExclMatchBtn.setOnAction(ae -> addExcludeMatchField()); + } + + private TextField addExcludeMatchField() { + TextField tf = new TextField(); + tf.setPrefWidth(400); + excludeMatcherFields.add(tf); + + HBox box = new HBox(10); + box.getChildren().add(tf); + + ImageView imgView = new ImageView(deleteImg); + imgView.setFitHeight(25); + imgView.setFitWidth(25); + box.getChildren().add(imgView); + imgView.setOnMouseClicked(me2 -> { + excludeMatcherFields.remove(tf); + exclMatchBox.getChildren().remove(box); + }); + + exclMatchBox.getChildren().add(box); + return tf; + } + + private void setupExcludeFeatureButton() { + addExclFeatureBtn.setOnAction(ae -> addExcludeTypeFilterBox()); + } + + private ComboBox addExcludeTypeFilterBox() { + ComboBox cBox = new ComboBox<>(); + cBox.setPrefWidth(400); + cBox.getItems().addAll(availableFilters); + cBox.getSelectionModel().select(0); + excludeTypeBoxes.add(cBox); + + HBox box = new HBox(10); + box.getChildren().add(cBox); + + ImageView imgView = new ImageView(deleteImg); + imgView.setFitHeight(25); + imgView.setFitWidth(25); + box.getChildren().add(imgView); + imgView.setOnMouseClicked(me2 -> { + excludeTypeBoxes.remove(cBox); + exclFeatureBox.getChildren().remove(box); + }); + + exclFeatureBox.getChildren().add(box); + return cBox; + } + + private void setupIncludeMatchButton() { + addInclMatchBtn.setOnAction(ae -> addIncludeMatchField()); + } + + private TextField addIncludeMatchField() { + TextField tf = new TextField(); + tf.setPrefWidth(400); + includeMatcherFields.add(tf); + + HBox box = new HBox(10); + box.getChildren().add(tf); + + ImageView imgView = new ImageView(deleteImg); + imgView.setFitHeight(25); + imgView.setFitWidth(25); + box.getChildren().add(imgView); + imgView.setOnMouseClicked(me2 -> { + includeMatcherFields.remove(tf); + inclMatchBox.getChildren().remove(box); + }); + + inclMatchBox.getChildren().add(box); + return tf; + } + + public void applyFilterConfig(FilterConfiguration filter) { + includeMatcherFields.clear(); + inclMatchBox.getChildren().clear(); + includeTypeBoxes.clear(); + inclFeatureBox.getChildren().clear(); + + excludeMatcherFields.clear(); + exclMatchBox.getChildren().clear(); + excludeTypeBoxes.clear(); + exclFeatureBox.getChildren().clear(); + applyExcludeFilters(filter); + applyIncludeFilters(filter); + } + + private void applyIncludeFilters(FilterConfiguration filter) { + IncludeFilterConfiguration include = filter.getInclude(); + if (include != null) { + for (String s : include.getIds()) { + addIncludeMatchField().setText(s); + } + for (FeatureType type : include.getTypes()) { + ComboBox box = addIncludeTypeFilterBox(); + for (TypeFilterSelection tfs : box.getItems()) { + if (tfs.getType() == type) { + box.getSelectionModel().select(tfs); + } + } + } + } + } + + private void applyExcludeFilters(FilterConfiguration filter) { + ExcludeFilterConfiguration exclude = filter.getExclude(); + if (exclude != null) { + for (String s : exclude.getIds()) { + addExcludeMatchField().setText(s); + } + for (FeatureType type : exclude.getTypes()) { + ComboBox box = addExcludeTypeFilterBox(); + for (TypeFilterSelection tfs : box.getItems()) { + if (tfs.getType() == type) { + box.getSelectionModel().select(tfs); + } + } + } + } + } + + private void setupIncludeFeatureButton() { + addInclFeatureBtn.setOnAction(ae -> addIncludeTypeFilterBox()); + } + + private ComboBox addIncludeTypeFilterBox() { + ComboBox cBox = new ComboBox<>(); + cBox.setPrefWidth(400); + cBox.getItems().addAll(availableFilters); + cBox.getSelectionModel().select(0); + includeTypeBoxes.add(cBox); + + HBox box = new HBox(10); + box.getChildren().add(cBox); + + ImageView imgView = new ImageView(deleteImg); + imgView.setFitHeight(25); + imgView.setFitWidth(25); + box.getChildren().add(imgView); + imgView.setOnMouseClicked(me2 -> { + includeTypeBoxes.remove(cBox); + inclFeatureBox.getChildren().remove(box); + }); + + inclFeatureBox.getChildren().add(box); + return cBox; + } + + public FilterConfiguration getConfiguration() { + IncludeFilterConfiguration includeFilters = new IncludeFilterConfiguration(); + List featureTypes = new ArrayList<>(); + for (ComboBox box : includeTypeBoxes) { + featureTypes.add(box.getSelectionModel().getSelectedItem().getType()); + } + includeFilters.setTypes(featureTypes); + + List ids = new ArrayList<>(); + for (TextField tf : includeMatcherFields) { + ids.add(tf.getText()); + } + includeFilters.setIds(ids); + + ExcludeFilterConfiguration excludeFilters = new ExcludeFilterConfiguration(); + + List excludeFeatureTypes = new ArrayList<>(); + for (ComboBox box : excludeTypeBoxes) { + excludeFeatureTypes.add(box.getSelectionModel().getSelectedItem().getType()); + } + excludeFilters.setTypes(excludeFeatureTypes); + + List excludeIds = new ArrayList<>(); + for (TextField tf : excludeMatcherFields) { + excludeIds.add(tf.getText()); + } + excludeFilters.setIds(excludeIds); + + + FilterConfiguration fConfig = new FilterConfiguration(); + fConfig.setInclude(includeFilters); + fConfig.setExclude(excludeFilters); + return fConfig; + } + + private void loadImages() { + try { + try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/Add.png")) { + Image img = new Image(inStream); + addInclFeatureView.setImage(img); + addInclMatchView.setImage(img); + addExclFeatureView.setImage(img); + addExclMatchView.setImage(img); + } + try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/Delete.png")) { + deleteImg = new Image(inStream); + } + } catch (IOException e) { + // ignore close exception + } + } + + public ScrollPane getPane() { + return pane; + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/GlobalParameter.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/GlobalParameter.java new file mode 100644 index 0000000000000000000000000000000000000000..8ba75e983917cd303d28225acf2686ca8770a2b0 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/GlobalParameter.java @@ -0,0 +1,102 @@ +/*- + * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart + * + * This file is part of CityDoctor2. + * + * CityDoctor2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CityDoctor2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with CityDoctor2. If not, see . + */ +package de.hft.stuttgart.citydoctor2.gui; + +import java.io.Serial; +import java.io.Serializable; + +import de.hft.stuttgart.citydoctor2.check.Unit; + +public class GlobalParameter implements Serializable { + + @Serial + private static final long serialVersionUID = 1423983452743345752L; + + private String name; + private String value; + private Unit unit; + + public GlobalParameter(String name, String value, Unit unit) { + super(); + this.name = name; + this.value = value; + this.unit = unit; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((unit == null) ? 0 : unit.hashCode()); + result = prime * result + ((value == null) ? 0 : value.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + GlobalParameter other = (GlobalParameter) obj; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (unit != other.unit) + return false; + if (value == null) { + return other.value == null; + } else return value.equals(other.value); + } + + @Override + public String toString() { + return "GlobalParameter [name=" + name + ", value=" + value + ", unit=" + unit + "]"; + } + + public Unit getUnit() { + return unit; + } + + public void setUnit(Unit unit) { + this.unit = unit; + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/HighlightController.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/HighlightController.java new file mode 100644 index 0000000000000000000000000000000000000000..be979f5b14c2b06420ab187798effdb02d1c35cf --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/HighlightController.java @@ -0,0 +1,222 @@ +package de.hft.stuttgart.citydoctor2.gui; + +import java.util.List; + +import de.hft.stuttgart.citydoctor2.datastructure.Edge; +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.datastructure.LinearRing.LinearRingType; +import de.hft.stuttgart.citydoctor2.math.Triangle3d; +import de.hft.stuttgart.citydoctor2.math.Vector3d; +import javafx.application.Platform; +import javafx.geometry.Point3D; +import javafx.scene.Group; +import javafx.scene.Node; +import javafx.scene.paint.Color; +import javafx.scene.paint.PhongMaterial; +import javafx.scene.shape.Cylinder; +import javafx.scene.shape.Sphere; +import javafx.scene.transform.Rotate; +import javafx.scene.transform.Translate; + +public class HighlightController { + + + private double scale; + private Group points; + private Group edges; + + private Group highlights; + + public HighlightController(Group world) { + highlights = new Group(); + points = new Group(); + edges = new Group(); + highlights.getChildren().add(edges); + highlights.getChildren().add(points); + Platform.runLater(() -> world.getChildren().add(highlights)); + } + + public void clearHighlights() { + points.getChildren().clear(); + edges.getChildren().clear(); + } + + public void changeScaling(double translateZ) { + scale = Math.abs(translateZ); + scale = Math.min(150, scale); + scale = Math.max(10, scale); + scale = scale * 0.01; + for (Node n : points.getChildren()) { + n.setScaleX(scale); + n.setScaleY(scale); + n.setScaleZ(scale); + } + double edgeSize = scale / 10; + for (Node n : edges.getChildren()) { + if (n instanceof Cylinder cy) { + cy.setRadius(edgeSize); + } + } + } + + public void highlight(Polygon p, TriangulatedGeometry currentTriGeom) { + clearHighlights(); + addHighlight(p, currentTriGeom, Color.RED, Color.BLUE); + } + + private void addHighlight(Polygon p, TriangulatedGeometry currentTriGeom, Color extColor, Color intColor) { + if (currentTriGeom == null || p == null) { + return; + } + addHighlight(p.getExteriorRing(), currentTriGeom, extColor); + for (LinearRing intRing : p.getInnerRings()) { + addHighlight(intRing, currentTriGeom, intColor); + } + } + + public void highlight(LinearRing ring, TriangulatedGeometry currentTriGeom) { + clearHighlights(); + if (ring.getType() == LinearRingType.EXTERIOR) { + addHighlight(ring, currentTriGeom, Color.RED); + } else { + addHighlight(ring, currentTriGeom, Color.BLUE); + } + } + + public void highlight(List rings, TriangulatedGeometry currentTriGeom) { + clearHighlights(); + for (LinearRing lr : rings) { + if (lr.getType() == LinearRingType.EXTERIOR) { + addHighlight(lr, currentTriGeom, Color.RED); + } else { + addHighlight(lr, currentTriGeom, Color.BLUE); + } + } + } + + private void addHighlight(LinearRing ring, TriangulatedGeometry currentTriGeom, Color pointColor) { + if (currentTriGeom == null || ring == null) { + return; + } + Vector3d movedBy = currentTriGeom.getMovedBy(); + for (Vertex v : ring.getVertices()) { + highlightPoint(movedBy, v, pointColor); + } + for (int i = 0; i < ring.getVertices().size() - 1; i++) { + Vertex v1 = ring.getVertices().get(i); + Vertex v2 = ring.getVertices().get(i + 1); + highlightEdge(v1, v2, movedBy); + } + } + + public void highlight(Edge e, TriangulatedGeometry currentTriGeom) { + clearHighlights(); + addHighlight(e, currentTriGeom); + } + + private void addHighlight(Edge e, TriangulatedGeometry currentTriGeom) { + if (currentTriGeom == null || e == null) { + return; + } + Vector3d movedBy = currentTriGeom.getMovedBy(); + highlightEdge(e.getFrom(), e.getTo(), movedBy); + highlightPoint(movedBy, e.getFrom(), Color.RED); + highlightPoint(movedBy, e.getTo(), Color.RED); + } + + public void highlight(Vertex v, TriangulatedGeometry currentTriGeom) { + clearHighlights(); + addHighlight(v, currentTriGeom, Color.RED); + } + + public void addHighlight(Vertex v, TriangulatedGeometry currentTriGeom, Color c) { + if (currentTriGeom == null || v == null) { + return; + } + Vector3d movedBy = currentTriGeom.getMovedBy(); + highlightPoint(movedBy, v, c); + } + + private void highlightPoint(Vector3d movedBy, Vertex v, Color color) { + Sphere sp = new Sphere(0.5); + sp.setMaterial(new PhongMaterial(color)); + sp.setTranslateX(v.getX() - movedBy.getX()); + sp.setTranslateY(v.getY() - movedBy.getY()); + sp.setTranslateZ(v.getZ() - movedBy.getZ()); + sp.setScaleX(scale); + sp.setScaleY(scale); + sp.setScaleZ(scale); + + sp.setUserData(new VertexClickDispatcher(v)); + + points.getChildren().add(sp); + } + + private void highlightEdge(Vector3d v1, Vector3d v2, Vector3d movedBy) { + Point3D origin = new Point3D(v1.getX() - movedBy.getX(), v1.getY() - movedBy.getY(), + v1.getZ() - movedBy.getZ()); + Point3D target = new Point3D(v2.getX() - movedBy.getX(), v2.getY() - movedBy.getY(), + v2.getZ() - movedBy.getZ()); + + Point3D yAxis = new Point3D(0, 1, 0); + Point3D diff = target.subtract(origin); + double height = diff.magnitude(); + + Point3D mid = target.midpoint(origin); + Translate moveToMidpoint = new Translate(mid.getX(), mid.getY(), mid.getZ()); + + Point3D axisOfRotation = diff.crossProduct(yAxis); + double angle = Math.acos(diff.normalize().dotProduct(yAxis)); + Rotate rotateAroundCenter = new Rotate(-Math.toDegrees(angle), axisOfRotation); + + Cylinder cy = new Cylinder(scale / 10, height); + cy.setMaterial(new PhongMaterial(Color.ORANGE)); + cy.getTransforms().addAll(moveToMidpoint, rotateAroundCenter); + edges.getChildren().add(cy); + } + + public void highlightEdges(List errorEdges, TriangulatedGeometry currentTriGeom) { + clearHighlights(); + for (Edge e : errorEdges) { + addHighlight(e, currentTriGeom); + } + } + + public void highlightPolygons(List> components, TriangulatedGeometry currentTriGeom) { + clearHighlights(); + for (int i = 0; i < components.size(); i++) { + Color extColor; + Color intColor = switch (i % 3) { + case 1 -> { + extColor = Color.GREEN; + yield Color.YELLOW; + } + case 2 -> { + extColor = Color.BROWN; + yield Color.VIOLET; + } + default -> { + extColor = Color.RED; + yield Color.BLUE; + } + }; + // select some color pairs for exterior and inner rings + List component = components.get(i); + for (Polygon p : component) { + addHighlight(p, currentTriGeom, extColor, intColor); + } + } + } + + public void addHighlight(Polygon p, TriangulatedGeometry currentTriGeom) { + addHighlight(p, currentTriGeom, Color.RED, Color.BLUE); + } + + public void highlight(Triangle3d t, TriangulatedGeometry currentTriGeom) { + highlightEdge(t.getP1(), t.getP2(), currentTriGeom.getMovedBy()); + highlightEdge(t.getP2(), t.getP3(), currentTriGeom.getMovedBy()); + highlightEdge(t.getP3(), t.getP1(), currentTriGeom.getMovedBy()); + } +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/LanguageSelectorCell.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/LanguageSelectorCell.java new file mode 100644 index 0000000000000000000000000000000000000000..0d9a928f0c9f2200a1a251d29839368a71dc6dfb --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/LanguageSelectorCell.java @@ -0,0 +1,49 @@ +/*- + * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart + * + * This file is part of CityDoctor2. + * + * CityDoctor2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CityDoctor2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with CityDoctor2. If not, see . + */ +package de.hft.stuttgart.citydoctor2.gui; + +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +import javafx.scene.control.ListCell; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; + +public class LanguageSelectorCell extends ListCell { + + private static Map imageCache = new HashMap<>(); + + @Override + protected void updateItem(Locale item, boolean empty) { + super.updateItem(item, empty); + if (item == null || empty) { + setGraphic(null); + } else { + String country = item.getLanguage().toLowerCase(Locale.US); + Image iconRef = imageCache.computeIfAbsent(country, key -> { + String iconPath = "icons/icon_" + country + ".png"; + return new Image(MainWindow.class.getResourceAsStream(iconPath)); + }); + ImageView iconImageView = new ImageView(iconRef); + setGraphic(iconImageView); + } + } + +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..65b7cc10bb7303e0d841cd22335782c29af9fb17 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/ListErrorVisitor.java @@ -0,0 +1,263 @@ +package de.hft.stuttgart.citydoctor2.gui; + +import java.util.ArrayList; +import java.util.List; + +import de.hft.stuttgart.citydoctor2.check.CheckError; +import de.hft.stuttgart.citydoctor2.check.ErrorVisitor; +import de.hft.stuttgart.citydoctor2.check.error.AllPolygonsWrongOrientationError; +import de.hft.stuttgart.citydoctor2.check.error.AttributeInvalidError; +import de.hft.stuttgart.citydoctor2.check.error.AttributeMissingError; +import de.hft.stuttgart.citydoctor2.check.error.AttributeValueWrongError; +import de.hft.stuttgart.citydoctor2.check.error.ConsecutivePointSameError; +import de.hft.stuttgart.citydoctor2.check.error.DependenciesNotMetError; +import de.hft.stuttgart.citydoctor2.check.error.MultipleConnectedComponentsError; +import de.hft.stuttgart.citydoctor2.check.error.NestedRingError; +import de.hft.stuttgart.citydoctor2.check.error.NonManifoldEdgeError; +import de.hft.stuttgart.citydoctor2.check.error.NonManifoldVertexError; +import de.hft.stuttgart.citydoctor2.check.error.NonPlanarPolygonDistancePlaneError; +import de.hft.stuttgart.citydoctor2.check.error.NonPlanarPolygonNormalsDeviation; +import de.hft.stuttgart.citydoctor2.check.error.NotCeilingError; +import de.hft.stuttgart.citydoctor2.check.error.NotFloorError; +import de.hft.stuttgart.citydoctor2.check.error.NotGroundError; +import de.hft.stuttgart.citydoctor2.check.error.NotWallError; +import de.hft.stuttgart.citydoctor2.check.error.NullAreaError; +import de.hft.stuttgart.citydoctor2.check.error.PointTouchesEdgeError; +import de.hft.stuttgart.citydoctor2.check.error.PolygonHoleOutsideError; +import de.hft.stuttgart.citydoctor2.check.error.PolygonInteriorDisconnectedError; +import de.hft.stuttgart.citydoctor2.check.error.PolygonIntersectingRingsError; +import de.hft.stuttgart.citydoctor2.check.error.PolygonSameOrientationError; +import de.hft.stuttgart.citydoctor2.check.error.PolygonWithoutSurfaceError; +import de.hft.stuttgart.citydoctor2.check.error.PolygonWrongOrientationError; +import de.hft.stuttgart.citydoctor2.check.error.RingDuplicatePointError; +import de.hft.stuttgart.citydoctor2.check.error.RingEdgeIntersectionError; +import de.hft.stuttgart.citydoctor2.check.error.RingNotClosedError; +import de.hft.stuttgart.citydoctor2.check.error.RingTooFewPointsError; +import de.hft.stuttgart.citydoctor2.check.error.SchematronError; +import de.hft.stuttgart.citydoctor2.check.error.SolidNotClosedError; +import de.hft.stuttgart.citydoctor2.check.error.SolidSelfIntError; +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.Edge; +import de.hft.stuttgart.citydoctor2.datastructure.LinearRing; +import de.hft.stuttgart.citydoctor2.datastructure.Vertex; +import javafx.scene.paint.Color; + +public class ListErrorVisitor implements ErrorVisitor { + + private HighlightController controller; + private TriangulatedGeometry geom; + + public ListErrorVisitor(HighlightController controller) { + this.controller = controller; + } + + public void setGeometry(TriangulatedGeometry geom) { + this.geom = geom; + } + + @Override + public void visit(PolygonHoleOutsideError err) { + List highlightedRings = new ArrayList<>(); + highlightedRings.add(err.getPolygon().getExteriorRing()); + highlightedRings.addAll(err.getHolesOutside()); + controller.highlight(highlightedRings, geom); + } + + @Override + public void visit(NonManifoldEdgeError err) { + controller.highlightEdges(err.getEdges(), geom); + } + + @Override + public void visit(MultipleConnectedComponentsError err) { + controller.highlightPolygons(err.getComponents(), geom); + } + + @Override + public void visit(NestedRingError err) { + List highlightedRings = new ArrayList<>(); + highlightedRings.add(err.getPolygon().getExteriorRing()); + highlightedRings.add(err.getInnerRing()); + controller.highlight(highlightedRings, geom); + } + + @Override + public void visit(NonManifoldVertexError err) { + controller.highlightPolygons(err.getComponents(), geom); + controller.addHighlight(err.getVertex(), geom, Color.BLUEVIOLET); + } + + @Override + public void visit(PolygonWrongOrientationError err) { + controller.highlightEdges(err.getEdges(), geom); + } + + @Override + public void visit(PolygonSameOrientationError err) { + List highlightedRings = new ArrayList<>(); + highlightedRings.add(err.getPolygon().getExteriorRing()); + highlightedRings.add(err.getInnerRing()); + controller.highlight(highlightedRings, geom); + } + + @Override + public void visit(SolidNotClosedError err) { + controller.highlightEdges(err.getErrorEdges(), geom); + } + + @Override + public void visit(DependenciesNotMetError err) { + // don't display + } + + @Override + public void visit(UnknownCheckError err) { + // don't display + } + + @Override + public void visit(RingNotClosedError err) { + controller.highlight(err.getRing(), geom); + } + + @Override + public void visit(ConsecutivePointSameError err) { + controller.highlight(err.getRing(), geom); + controller.addHighlight(err.getVertex1(), geom, Color.BLACK); + controller.addHighlight(err.getVertex2(), geom, Color.BLACK); + } + + @Override + public void visit(AllPolygonsWrongOrientationError err) { + // don't display + } + + @Override + public void visit(PolygonInteriorDisconnectedError err) { + controller.highlight(err.getConnectedRings(), geom); + } + + @Override + public void visit(NullAreaError err) { + // don't display + } + + @Override + public void visit(RingTooFewPointsError err) { + controller.highlight(err.getRing(), geom); + } + + @Override + public void visit(NonPlanarPolygonNormalsDeviation err) { + controller.highlight(err.getPolygon(), geom); + } + + @Override + public void visit(NonPlanarPolygonDistancePlaneError err) { + controller.highlight(err.getPolygon(), geom); + controller.addHighlight(err.getVertex(), geom, Color.BLACK); + } + + @Override + public void visit(PolygonIntersectingRingsError err) { + List rings = new ArrayList<>(); + rings.add(err.getIntersectingRings().getValue0()); + rings.add(err.getIntersectingRings().getValue1()); + controller.highlight(rings, geom); + } + + @Override + public void visit(SolidSelfIntError err) { + // nothing to display for now + } + + @Override + public void visit(TooFewPolygonsError err) { + // don't display + } + + @Override + public void visit(RingDuplicatePointError err) { + controller.highlight(err.getRing(), geom); + controller.addHighlight(err.getVertex1(), geom, Color.BLACK); + controller.addHighlight(err.getVertex2(), geom, Color.BLACK); + } + + @Override + public void visit(RingEdgeIntersectionError err) { + List list = new ArrayList<>(); + list.add(err.getEdge1()); + list.add(err.getEdge2()); + controller.highlightEdges(list, geom); + controller.addHighlight(new Vertex(err.getIntersection()), geom, Color.BLACK); + } + + @Override + public void visit(PointTouchesEdgeError err) { + controller.highlight(err.getEdge(), geom); + controller.addHighlight(err.getVertex(), geom, Color.BLACK); + } + + @Override + public void visit(CheckError err) { + // nothing to display + } + + @Override + public void visit(NotCeilingError err) { + // nothing to display + } + + @Override + public void visit(NotFloorError err) { + // nothing to display + } + + @Override + public void visit(NotWallError err) { + // nothing to display + } + + @Override + public void visit(NotGroundError err) { + // nothing to display + } + + @Override + public void visit(SchematronError err) { + // nothing to display + } + + @Override + public void visit(SurfaceUnfragmentedError err) { + // nothing to display + } + + @Override + public void visit(DegeneratedRingError err) { + controller.highlight(err.getRing(), geom); + } + + @Override + public void visit(AttributeMissingError err) { + // nothing to display + } + + @Override + public void visit(AttributeValueWrongError err) { + // nothing to display + } + + @Override + public void visit(AttributeInvalidError err) { + // nothing to display + } + + @Override + public void visit(PolygonWithoutSurfaceError err) { + controller.highlight(err.getPolygon(), geom); + } +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/LoadingInfoDialog.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/LoadingInfoDialog.java new file mode 100644 index 0000000000000000000000000000000000000000..fb5064cce5e63b0066b99c08e1e5a54a1aa2561f --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/LoadingInfoDialog.java @@ -0,0 +1,38 @@ +package de.hft.stuttgart.citydoctor2.gui; + +import java.io.IOException; + +import javafx.fxml.FXMLLoader; +import javafx.scene.Scene; +import javafx.scene.layout.VBox; +import javafx.stage.Modality; +import javafx.stage.Stage; +import javafx.stage.StageStyle; +import javafx.stage.Window; + +public class LoadingInfoDialog { + + private Stage stage; + + public LoadingInfoDialog(Window parent) throws IOException { + FXMLLoader loader = new FXMLLoader(LoadingInfoDialog.class.getResource("CreateRenderDataDialog.fxml")); + loader.setController(this); + VBox box = loader.load(); + + stage = new Stage(StageStyle.UNDECORATED); + Scene scene = new Scene(box); + scene.setFill(null); + stage.setScene(scene); + stage.initOwner(parent); + stage.initModality(Modality.APPLICATION_MODAL); + } + + public void show() { + stage.show(); + } + + public void hide() { + stage.hide(); + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/MainToolBar.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/MainToolBar.java new file mode 100644 index 0000000000000000000000000000000000000000..9ad3a38b058bcfc3b45b6b62f20bb4302effe78e --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/MainToolBar.java @@ -0,0 +1,349 @@ +package de.hft.stuttgart.citydoctor2.gui; + +import java.io.IOException; +import java.io.InputStream; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import de.hft.stuttgart.citydoctor2.gui.tree.Renderable; +import de.hft.stuttgart.citydoctor2.utils.Localization; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.control.Button; +import javafx.scene.control.Tab; +import javafx.scene.control.TabPane; +import javafx.scene.control.ToggleButton; +import javafx.scene.control.Tooltip; +import javafx.scene.control.TreeView; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.layout.HBox; +import javafx.stage.Stage; + +public class MainToolBar { + + private static final Logger logger = LogManager.getLogger(MainToolBar.class); + + @FXML + private Button saveBtn; + + @FXML + private ImageView saveView; + + @FXML + private Button openBtn; + + @FXML + private ImageView openImageView; + + @FXML + private Button checkBtn; + + @FXML + private ImageView checkImageView; + + @FXML + private Button showWorldBtn; + + @FXML + private ImageView showWorldImageView; + + @FXML + private Button schematronBtn; + + @FXML + private ImageView schematronImgView; + + @FXML + private ToggleButton lod1Btn; + + @FXML + private ImageView lod1View; + + @FXML + private ToggleButton lod2Btn; + + @FXML + private ImageView lod2View; + + @FXML + private ToggleButton lod3Btn; + + @FXML + private ImageView lod3View; + + @FXML + private ToggleButton lod4Btn; + + @FXML + private ImageView lod4View; + + @FXML + private Button aboutBtn; + + @FXML + private ImageView aboutImgView; + + @FXML + private ToggleButton gridButton; + + @FXML + private ToggleButton cullingButton; + + @FXML + private ImageView cullingImageView; + + @FXML + private ImageView gridImageView; + + @FXML + private Button reportBtn; + + @FXML + private ImageView reportImageView; + + private OpenFileDialog fileDialog; + private CheckDialog checkDialog; + private WriteReportDialog writeDialog; + private AboutDialog aboutDialog; + + private CityDoctorController controller; + private TabPane featurePane; + private Stage stage; + private Renderer renderer; + private MainWindow mainWindow; + + private HBox toolBar; + + public MainToolBar(Stage stage, CityDoctorController controller, TabPane featurePane, Renderer renderer, + MainWindow mainWindow) throws IOException { + this.controller = controller; + this.featurePane = featurePane; + this.renderer = renderer; + this.stage = stage; + this.mainWindow = mainWindow; + + FXMLLoader loader = new FXMLLoader(MainToolBar.class.getResource("MainToolBar.fxml")); + loader.setController(this); + toolBar = loader.load(); + + fileDialog = new OpenFileDialog(stage, controller); + } + + public void initialize() { + openBtn.setOnAction(ae -> fileDialog.show()); + + setupSaveBtn(); + setupCheckButton(); + setupLodButtons(); + setupAboutButton(); + setupReportButton(); + + loadImages(); + + gridButton.setOnAction(ae -> renderer.showWireFrame(gridButton.isSelected())); + gridButton.setTooltip(new Tooltip(Localization.getText("MainToolBar.wireframe"))); + cullingButton.setOnAction(ae -> renderer.enableCulling(cullingButton.isSelected())); + cullingButton.setTooltip(new Tooltip(Localization.getText("MainToolBar.culling"))); + + showWorldBtn.setOnAction(ar -> { + Tab selectedItem = featurePane.getSelectionModel().getSelectedItem(); + if (selectedItem.getContent() instanceof TreeView) { + @SuppressWarnings("unchecked") + TreeView content = (TreeView) selectedItem.getContent(); + content.getSelectionModel().clearSelection(); + } + controller.showWorld(); + }); + } + + private void loadImages() { + try { + try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/openFolderIcon.png")) { + Image img = new Image(inStream); + openImageView.setImage(img); + } + try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/check32x32.png")) { + Image img = new Image(inStream); + checkImageView.setImage(img); + } + try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/wireframe32x32.png")) { + Image img = new Image(inStream); + gridImageView.setImage(img); + } + try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/Culling.png")) { + Image img = new Image(inStream); + cullingImageView.setImage(img); + } + try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/error_stat32x32.png")) { + Image img = new Image(inStream); + reportImageView.setImage(img); + } + try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/scene.png")) { + Image img = new Image(inStream); + showWorldImageView.setImage(img); + } + try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/lod1_32x32.png")) { + Image img = new Image(inStream); + lod1View.setImage(img); + } + try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/lod2_32x32.png")) { + Image img = new Image(inStream); + lod2View.setImage(img); + } + try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/lod3_32x32.png")) { + Image img = new Image(inStream); + lod3View.setImage(img); + } + try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/lod4_32x32.png")) { + Image img = new Image(inStream); + lod4View.setImage(img); + } + try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/about.png")) { + Image img = new Image(inStream); + aboutImgView.setImage(img); + } + try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/save.png")) { + Image img = new Image(inStream); + saveView.setImage(img); + } + } catch (IOException e) { + // ignore close exception + } + } + + private void setupReportButton() { + reportBtn.setDisable(true); + reportBtn.setTooltip(new Tooltip(Localization.getText("MainToolBar.writeReports"))); + reportBtn.setOnAction(ae -> { + if (writeDialog == null) { + try { + writeDialog = new WriteReportDialog(stage, controller, mainWindow); + } catch (IOException e) { + logger.catching(e); + mainWindow.showExceptionDialog(e); + } + } + if (writeDialog != null) { + // writeDialog can be null if creation of said dialog fails + writeDialog.show(); + } + }); + } + + private void setupAboutButton() { + aboutBtn.setOnAction(ae -> { + if (aboutDialog == null) { + try { + aboutDialog = new AboutDialog(stage); + aboutDialog.show(); + } catch (IOException e) { + logger.error("Could not load about dialog.", e); + } + } else { + aboutDialog.show(); + } + }); + } + + private void setupLodButtons() { + lod1Btn.setOnAction(ae -> { + if (lod1Btn.isSelected()) { + renderer.enableLod1(); + } else { + renderer.disableLod1(); + } + }); + lod2Btn.setOnAction(ae -> { + if (lod2Btn.isSelected()) { + renderer.enableLod2(); + } else { + renderer.disableLod2(); + } + }); + lod3Btn.setOnAction(ae -> { + if (lod3Btn.isSelected()) { + renderer.enableLod3(); + } else { + renderer.disableLod3(); + } + }); + lod4Btn.setOnAction(ae -> { + if (lod4Btn.isSelected()) { + renderer.enableLod4(); + } else { + renderer.disableLod4(); + } + }); + } + + private void setupSaveBtn() { + saveBtn.setOnAction(ae -> controller.askAndSave()); + } + + private void setupCheckButton() { + checkBtn.setDisable(true); + checkBtn.setTooltip(new Tooltip(Localization.getText("MainToolBar.executeChecks"))); + checkBtn.setOnAction(ae -> { + if (checkDialog == null) { + try { + checkDialog = new CheckDialog(mainWindow, stage, controller); + } catch (IOException e) { + mainWindow.showExceptionDialog(e); + logger.catching(e); + } + } + checkDialog.show(); + }); + } + + public Button getCheckButton() { + return checkBtn; + } + + public ToggleButton getGridButton() { + return gridButton; + } + + public ToggleButton getCullingButton() { + return cullingButton; + } + + public Button getWriteReportButton() { + return reportBtn; + } + + public ToggleButton getLod1Btn() { + return lod1Btn; + } + + public ToggleButton getLod2Btn() { + return lod2Btn; + } + + public ToggleButton getLod3Btn() { + return lod3Btn; + } + + public ToggleButton getLod4Btn() { + return lod4Btn; + } + + public Button getWorldBtn() { + return showWorldBtn; + } + + public Button getSaveBtn() { + return saveBtn; + } + + public HBox getToolBar() { + return toolBar; + } + + public Button getOpenBtn() { + return openBtn; + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/MainWindow.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/MainWindow.java new file mode 100644 index 0000000000000000000000000000000000000000..3b9aaf6697eff703c2b85deabcb8a54a2525c1c7 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/MainWindow.java @@ -0,0 +1,978 @@ +package de.hft.stuttgart.citydoctor2.gui; + +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.List; +import java.util.Locale; +import java.util.Optional; +import java.util.Timer; +import java.util.TimerTask; + +import javax.imageio.ImageIO; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import de.hft.stuttgart.citydoctor2.CityDoctorValidation; +import de.hft.stuttgart.citydoctor2.check.ValidationConfiguration; +import de.hft.stuttgart.citydoctor2.datastructure.BoundingBox; +import de.hft.stuttgart.citydoctor2.datastructure.FeatureType; +import de.hft.stuttgart.citydoctor2.gui.logger.GuiLogger; +import de.hft.stuttgart.citydoctor2.gui.tree.BuildingNode; +import de.hft.stuttgart.citydoctor2.gui.tree.Renderable; +import de.hft.stuttgart.citydoctor2.gui.tree.RenderableTreeCell; +import de.hft.stuttgart.citydoctor2.parameter.ArgumentParser; +import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException; +import de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException; +import de.hft.stuttgart.citydoctor2.parser.ProgressListener; +import de.hft.stuttgart.citydoctor2.utils.Localization; +import javafx.application.Application; +import javafx.application.Platform; +import javafx.beans.value.ChangeListener; +import javafx.embed.swing.SwingFXUtils; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.AmbientLight; +import javafx.scene.Group; +import javafx.scene.Node; +import javafx.scene.PerspectiveCamera; +import javafx.scene.Scene; +import javafx.scene.SceneAntialiasing; +import javafx.scene.SubScene; +import javafx.scene.control.Alert; +import javafx.scene.control.Alert.AlertType; +import javafx.scene.control.Button; +import javafx.scene.control.ButtonType; +import javafx.scene.control.ComboBox; +import javafx.scene.control.ContextMenu; +import javafx.scene.control.Label; +import javafx.scene.control.ListCell; +import javafx.scene.control.ListView; +import javafx.scene.control.MenuItem; +import javafx.scene.control.ProgressBar; +import javafx.scene.control.RadioButton; +import javafx.scene.control.SplitPane; +import javafx.scene.control.Tab; +import javafx.scene.control.TabPane; +import javafx.scene.control.TextArea; +import javafx.scene.control.TextField; +import javafx.scene.control.ToggleButton; +import javafx.scene.control.ToggleGroup; +import javafx.scene.control.ToolBar; +import javafx.scene.control.TreeItem; +import javafx.scene.control.TreeView; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.image.WritableImage; +import javafx.scene.input.Dragboard; +import javafx.scene.input.MouseButton; +import javafx.scene.input.MouseEvent; +import javafx.scene.input.TransferMode; +import javafx.scene.layout.BorderPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Pane; +import javafx.scene.layout.Priority; +import javafx.scene.paint.Color; +import javafx.scene.transform.Rotate; +import javafx.stage.Stage; + +public class MainWindow extends Application { + + private static final Logger logger = LogManager.getLogger(MainWindow.class); + + private static final double CAMERA_TRANSLATE_Z = -100.0; + private static final double CAMERA_INITIAL_X_ANGLE = 20.0; + private static final double CAMERA_INITIAL_Y_ANGLE = 120.0; + + @FXML + private TreeView buildingsView; + + @FXML + private TreeView vegetationView; + + @FXML + private TreeView transView; + + @FXML + private TreeView bridgeView; + + @FXML + private TreeView waterView; + + @FXML + private TreeView terrainView; + + @FXML + private TreeView polygonView; + + @FXML + private TreeView edgeView; + + @FXML + private TreeView vertexView; + + @FXML + private Pane meshView; + + @FXML + private SplitPane mainContainer; + + @FXML + private TabPane detailsTabPane; + + @FXML + private TabPane featurePane; + + @FXML + private TextField searchField; + + @FXML + private TreeView errorView; + + @FXML + private Button clearBtn; + + @FXML + private Button searchBtn; + + @FXML + private ToggleButton allButton; + + @FXML + private ToggleButton errorButton; + + @FXML + private ComboBox showCityObjectsCombo; + + @FXML + private HBox viewPane; + + @FXML + private ListView globalErrorsView; + + @FXML + private BorderPane mainPane; + + @FXML + private HBox viewButtonBox; + + @FXML + private ComboBox languageSelector; + + @FXML + private Tab buildingsTab; + + @FXML + private Tab vegetationTab; + + @FXML + private Tab transportationTab; + + @FXML + private Tab bridgeTab; + + @FXML + private Tab waterTab; + + @FXML + private Tab terrainTab; + + @FXML + private Tab errorsTab; + + @FXML + private Tab polygonsTab; + + @FXML + private Tab edgesTab; + + @FXML + private Tab verticesTab; + + @FXML + private Tab logTab; + + @FXML + private Tab globalErrorsTab; + + @FXML + private Label viewLabel; + + @FXML + private Label showLabel; + + @FXML + private Label searchLabel; + + @FXML + private Label memoryLabel; + + @FXML + private ProgressBar memoryBar; + + @FXML + private Label memoryConsumptionLabel; + + @FXML + private Label availableLabel; + + private Group meshGroup; + + private Group world; + private PerspectiveCamera camera; + private Rotate cameraXRotation = new Rotate(); + private Rotate cameraZRotation = new Rotate(); + + private double dragX; + private double dragY; + + private double cameraXRot = CAMERA_INITIAL_X_ANGLE; + private double cameraYRot = CAMERA_INITIAL_Y_ANGLE; + private double translateZ = CAMERA_TRANSLATE_Z; + private double[] clickStart = new double[2]; + + @FXML + private TextArea logArea; + + @FXML + private ToolBar viewBar; + + private Stage stage; + private ExceptionDialog exceptionDialog; + + private Renderer renderer; + private CityDoctorController controller; + private HighlightController highlightController; + + private FeatureType selectedTab = FeatureType.BUILDING; + + private MainToolBar mainToolBar; + private SubScene geomScene; + + private static boolean loadFileAtStartup = false; + private static String inputFile; + private static String xmlOutput; + private static String pdfOutput; + private static ValidationConfiguration config; + + private VertexClickHandler clickHandler; + + private ChangeListener filterChangeListener; + + public static void main(String[] args) { + setLocaleFromSettings(); + ArgumentParser argParser = new ArgumentParser(args); + inputFile = CityDoctorValidation.getInputFile(argParser, true); + if (inputFile != null) { + loadFileAtStartup = true; + xmlOutput = CityDoctorValidation.getXmlOutput(argParser); + pdfOutput = CityDoctorValidation.getPdfOutput(argParser); + try { + config = CityDoctorValidation.getValidationConfig(argParser, true); + } catch (FileNotFoundException e) { + Platform.runLater(() -> { + List configFiles = argParser.getValues("config"); + Alert alert = new Alert(AlertType.ERROR); + alert.setContentText(Localization.getText("MainWindow.missingConfig") + configFiles); + alert.showAndWait(); + }); + System.exit(4); + } + } + Application.launch(args); + } + + private static void setLocaleFromSettings() { + String localeString = Settings.get(Settings.LANGUAGE); + if (localeString != null) { + try { + Locale loc = new Locale(localeString); + Locale.setDefault(loc); + } catch (Exception e) { + logger.warn("Could not set language to {}, using system language", localeString); + } + } + } + + @Override + public void start(Stage stage) throws IOException { + this.stage = stage; + stage.getIcons().add(new Image(MainWindow.class.getResourceAsStream("icons/citydoctor_logo.png"))); + FXMLLoader loader = new FXMLLoader(MainWindow.class.getResource("MainWindow.fxml")); + loader.setController(this); + BorderPane bp = loader.load(); + highlightController = new HighlightController(world); + renderer = new Renderer(this, highlightController); + clickHandler = new VertexClickHandler(errorView, renderer, stage); + controller = new CityDoctorController(this, highlightController, renderer); + mainToolBar = new MainToolBar(stage, controller, featurePane, renderer, this); + viewPane.getChildren().add(mainToolBar.getToolBar()); + HBox.setHgrow(mainToolBar.getToolBar(), Priority.ALWAYS); + + ValidationView valView = new ValidationView(this, controller); + ViewRegistration.registerView(valView); + setupViews(valView); + + createLanguageSelector(); + setLabelsInCorrectLanguage(); + + Scene scene = new Scene(bp, 1280, 800); + createDropTarget(scene, valView); + String version = Localization.getText(Localization.VERSION); + stage.setTitle("CityDoctor " + version); + stage.setScene(scene); + stage.show(); + checkForStartupLoading(); + + memoryBar.setOnMouseClicked(me -> System.gc()); + Timer timer = new Timer(true); + // check memory every second + TimerTask task = new TimerTask() { + + Runtime runtime = Runtime.getRuntime(); + + @Override + public void run() { + long totalMemory = runtime.totalMemory(); + long freeMemory = runtime.freeMemory(); + long usedMemory = totalMemory - freeMemory; + double percentage = usedMemory / (double) totalMemory; + if (totalMemory / 1024 / 1024 >= 1024) { + // gb + double totalMemoryGb = totalMemory / (1024d * 1024d * 1024d); + double usedMemoryGb = usedMemory / (1024d * 1024d * 1024d); + String memoryString = String.format("%.1f GB / %.1f GB", usedMemoryGb, totalMemoryGb); + Platform.runLater(() -> { + memoryConsumptionLabel.setText(memoryString); + memoryBar.setProgress(percentage); + }); + } else if (totalMemory / 1024 >= 1024) { + // mb + double totalMemoryMb = totalMemory / (1024d * 1024d); + double usedMemoryMb = usedMemory / (1024d * 1024d); + String memoryString = String.format("%.1f MB / %.1f MB", usedMemoryMb, totalMemoryMb); + Platform.runLater(() -> { + memoryConsumptionLabel.setText(memoryString); + memoryBar.setProgress(percentage); + }); + } + } + }; + timer.schedule(task, 0, 1000); + } + + private void createDropTarget(Scene scene, ValidationView valView) { + setDragOverInteraction(scene, valView); + scene.setOnDragDropped(event -> { + if (ViewRegistration.getCurrentActiveView() != valView) { + return; + } + Dragboard db = event.getDragboard(); + boolean success = false; + if (db.hasFiles() && db.getFiles().size() == 1) { + File f = db.getFiles().get(0); + Thread t = new Thread(() -> { + try { + controller.loadCityGml(f.getAbsolutePath(), 8, (ProgressListener) null, false); + } catch (Exception e) { + if (logger.isErrorEnabled()) { + logger.error(Localization.getText("OpenFileDialog.loadFailed"), e); + } + Platform.runLater(() -> { + ExceptionDialog exDialog = new ExceptionDialog(); + exDialog.show(e); + }); + } + }); + t.start(); + success = true; + } + // let the source know whether the string was successfully transferred and used + event.setDropCompleted(success); + + event.consume(); + }); + } + + private void setDragOverInteraction(Scene scene, ValidationView valView) { + scene.setOnDragOver(event -> { + if (ViewRegistration.getCurrentActiveView() != valView) { + return; + } + if (event.getGestureSource() != scene && event.getDragboard().hasFiles() + && event.getDragboard().getFiles().size() == 1) { + // allow for both copying and moving, whatever user chooses + event.acceptTransferModes(TransferMode.LINK); + } + event.consume(); + }); + } + + private void setLabelsInCorrectLanguage() { + buildingsTab.setText(Localization.getText("MainWindow.buildingsTab")); + vegetationTab.setText(Localization.getText("MainWindow.vegetationTab")); + transportationTab.setText(Localization.getText("MainWindow.transportationTab")); + bridgeTab.setText(Localization.getText("MainWindow.bridgeTab")); + waterTab.setText(Localization.getText("MainWindow.waterTab")); + terrainTab.setText(Localization.getText("MainWindow.terrainTab")); + viewLabel.setText(Localization.getText("MainWindow.viewLabel")); + showLabel.setText(Localization.getText("MainWindow.showLabel")); + searchLabel.setText(Localization.getText("MainWindow.searchLabel")); + searchBtn.setText(Localization.getText("MainWindow.searchBtn")); + clearBtn.setText(Localization.getText("MainWindow.clearBtn")); + errorsTab.setText(Localization.getText("MainWindow.errorsTab")); + polygonsTab.setText(Localization.getText("MainWindow.polygonsTab")); + edgesTab.setText(Localization.getText("MainWindow.edgesTab")); + verticesTab.setText(Localization.getText("MainWindow.verticesTab")); + logTab.setText(Localization.getText("MainWindow.logTab")); + globalErrorsTab.setText(Localization.getText("MainWindow.globalErrorsTab")); + memoryLabel.setText(Localization.getText("MainWindow.memoryLabel")); + availableLabel.setText(String.format("%s %.1f GB", Localization.getText("MainWindow.availableLabel"), + Runtime.getRuntime().maxMemory() / 1024d / 1024d / 1024d)); + } + + private void createLanguageSelector() { + languageSelector.setButtonCell(new LanguageSelectorCell()); + languageSelector.setCellFactory(view -> new LanguageSelectorCell()); + languageSelector.getItems().add(Locale.GERMAN); + languageSelector.getItems().add(Locale.ENGLISH); + if (Locale.getDefault().getLanguage().equals(Locale.GERMAN.getLanguage())) { + languageSelector.getSelectionModel().select(Locale.GERMAN); + } else if (Locale.getDefault().getLanguage().equals(Locale.ENGLISH.getLanguage())) { + languageSelector.getSelectionModel().select(Locale.ENGLISH); + } else { + languageSelector.getSelectionModel().select(Locale.ENGLISH); + Settings.set(Settings.LANGUAGE, Locale.ENGLISH.getLanguage()); + } + languageSelector.getSelectionModel().selectedItemProperty().addListener((obs, oldV, newV) -> { + Alert alert = new Alert(AlertType.CONFIRMATION, Localization.getText("MainWindow.languageChange"), + ButtonType.OK); + alert.showAndWait(); + Settings.set(Settings.LANGUAGE, newV.getLanguage()); + }); + } + + private void checkForStartupLoading() { + if (loadFileAtStartup) { + logger.info(Localization.getText("MainWindow.loadGivenFile")); + Thread t = new Thread(() -> { + try { + // wait a bit for the gui to show + Thread.sleep(500); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + try { + controller.loadCityGml(inputFile, config.getNumberOfRoundingPlaces(), null, + config.isXmlValidation()); + logger.info(Localization.getText("MainWindow.finishedLoading")); + logger.info(Localization.getText("MainWindow.checking")); + controller.startChecks(config, null); + if (xmlOutput != null) { + logger.info(Localization.getText("MainWindow.writeXml")); + controller.writeXmlReport(new File(xmlOutput)); + logger.info(Localization.getText("MainWindow.finishedXml")); + } + if (pdfOutput != null) { + logger.info(Localization.getText("MainWindow.writePdf")); + controller.writePdfReport(new File(pdfOutput)); + logger.info(Localization.getText("MainWindow.finishedPdf")); + } + } catch (CityGmlParseException | InvalidGmlFileException e) { + logger.error(Localization.getText("MainWindow.loadFailed"), e.getMessage()); + } + }); + t.start(); + } + } + + private void setupViews(ValidationView valView) { + ToggleGroup group = new ToggleGroup(); + for (View v : ViewRegistration.getRegisteredViews()) { + + RadioButton radioButton = new RadioButton(); + radioButton.getStyleClass().remove("radio-button"); + radioButton.getStyleClass().add("toggle-button"); + ImageView view = new ImageView(v.getViewLogo()); + view.setFitHeight(32); + view.setFitWidth(32); + radioButton.setGraphic(view); + group.getToggles().add(radioButton); + if (v == valView) { + ViewRegistration.setCurrentActiveView(valView); + group.selectToggle(radioButton); + } + viewButtonBox.getChildren().add(radioButton); + radioButton.selectedProperty().addListener((obs, oldV, newV) -> { + if (Boolean.TRUE.equals(newV)) { + showView(v); + ViewRegistration.setCurrentActiveView(v); + } else { + v.onHide(); + } + }); + } + } + + private void showView(View v) { + viewPane.getChildren().clear(); + controller.showView(v); + Optional toolbar = v.getToolbar(); + if (toolbar.isPresent()) { + viewPane.getChildren().add(toolbar.get()); + HBox.setHgrow(toolbar.get(), Priority.ALWAYS); + } else { + HBox placeHolderToolbar = new HBox(); + placeHolderToolbar.setMaxHeight(Double.MAX_VALUE); + viewPane.getChildren().add(placeHolderToolbar); + HBox.setHgrow(placeHolderToolbar, Priority.ALWAYS); + } + mainPane.setCenter(v.getMainScreen()); + } + + public void initialize() { + GuiLogger.setTextArea(logArea); + + loadFrameConfig(); + + setup3dView(); + setupTrees(); + + setupSearchField(); + setupSearchButtons(); + + setupShowCityComboBox(); + + detailsTabPane.getSelectionModel().selectedIndexProperty() + .addListener((ov, oldI, newI) -> Platform.runLater(() -> { + if (newI.intValue() == 0 && errorView.getSelectionModel().getSelectedItem() != null) { + // the first tab is selected, meaning the error tab + // redisplay the selected error + errorView.getSelectionModel().getSelectedItem().getValue().visit(renderer); + } + })); + } + + private void setupShowCityComboBox() { + showCityObjectsCombo.getItems().addAll(Localization.getText("MainWindow.all"), + Localization.getText("MainWindow.withErrors")); + showCityObjectsCombo.getSelectionModel().selectFirst(); + + showCityObjectsCombo.setCellFactory(param -> new ListCell<>() { + @Override + public void updateItem(String item, boolean empty) { + super.updateItem(item, empty); + if (item != null) { + setText(item); + if (item.contentEquals(Localization.getText("MainWindow.withErrors"))) { + setTextFill(Color.RED); + } + } else { + setText(null); + } + } + }); + + filterChangeListener = setupFilterSelectionListener(); + showCityObjectsCombo.getSelectionModel().selectedIndexProperty().addListener(filterChangeListener); + } + + public void resetFilterComboBox() { + showCityObjectsCombo.getSelectionModel().selectedIndexProperty().removeListener(filterChangeListener); + showCityObjectsCombo.getSelectionModel().selectFirst(); + showCityObjectsCombo.getSelectionModel().selectedIndexProperty().addListener(filterChangeListener); + } + + private ChangeListener setupFilterSelectionListener() { + return (obs, oldV, newV) -> controller.errorFilterIndexChanged(newV); + } + + private void setupSearchButtons() { + searchBtn.setOnAction(ae -> controller.searchFeature(searchField.getText(), selectedTab)); + clearBtn.setOnAction(ae -> { + if (searchField.getText().isEmpty()) { + // do not reset search if nothing has bee searched + return; + } + controller.resetSearch(selectedTab); + searchField.setText(""); + }); + } + + private void setupSearchField() { + searchField.textProperty().addListener((obs, oldV, newV) -> { + if (newV.isEmpty()) { + controller.resetSearch(selectedTab); + } + }); + featurePane.getSelectionModel().selectedIndexProperty().addListener((obs, oldV, newV) -> { + if (!searchField.getText().isEmpty()) { + resetSearchBar(); + controller.resetSearch(selectedTab); + } + int index = newV.intValue(); + switch (index) { + case 0: + selectedTab = FeatureType.BUILDING; + break; + case 1: + selectedTab = FeatureType.VEGETATION; + break; + case 2: + selectedTab = FeatureType.TRANSPORTATION; + break; + case 3: + selectedTab = FeatureType.BRIDGE; + break; + case 4: + selectedTab = FeatureType.WATER; + break; + case 5: + selectedTab = FeatureType.LAND; + break; + default: + throw new IllegalStateException("Unknown tab index: " + index); + } + }); + } + + public void resetSearchBar() { + searchField.setText(""); + } + + private void loadFrameConfig() { + stage.setMaximized(Boolean.valueOf(Settings.get(Settings.MAXIMIZED, Boolean.FALSE.toString()))); + stage.maximizedProperty() + .addListener((obs, oldV, newV) -> Settings.set(Settings.MAXIMIZED, Boolean.toString(newV))); + + String widthString = Settings.get(Settings.FRAME_WIDTH); + if (widthString != null) { + stage.setWidth(Double.parseDouble(widthString)); + } + stage.widthProperty().addListener( + (obs, oldV, newV) -> Settings.set(Settings.FRAME_WIDTH, Double.toString(newV.doubleValue()))); + + String heightString = Settings.get(Settings.FRAME_HEIGHT); + if (heightString != null) { + stage.setHeight(Double.parseDouble(heightString)); + } + stage.heightProperty().addListener( + (obs, oldV, newV) -> Settings.set(Settings.FRAME_HEIGHT, Double.toString(newV.doubleValue()))); + } + + public void showExceptionDialog(Throwable e) { + if (exceptionDialog == null) { + exceptionDialog = new ExceptionDialog(); + } + exceptionDialog.show(e); + } + + private void setupTrees() { + setupSelectListener(errorView); + errorView.setRoot(new TreeItem<>()); + errorView.setCellFactory(param -> new RenderableTreeCell()); + + buildingsView.setShowRoot(true); + setupSelectListener(buildingsView); + buildingsView.setCellFactory(param -> new RenderableTreeCell()); + ContextMenu cMenu = new ContextMenu(); + MenuItem mi = new MenuItem(Localization.getText("MainWindow.export")); + mi.setOnAction(ea -> { + Renderable render = buildingsView.getSelectionModel().getSelectedItem().getValue(); + if (render instanceof BuildingNode node) { + controller.export(node.getBuilding()); + } + }); + cMenu.getItems().add(mi); + + MenuItem deleteMi = new MenuItem("Delete"); + deleteMi.setOnAction(ae -> controller.delete(buildingsView.getSelectionModel().getSelectedItem())); + cMenu.getItems().add(deleteMi); + + buildingsView.setContextMenu(cMenu); + + vegetationView.setShowRoot(true); + setupSelectListener(vegetationView); + vegetationView.setCellFactory(param -> new RenderableTreeCell()); + + transView.setShowRoot(true); + setupSelectListener(transView); + transView.setCellFactory(param -> new RenderableTreeCell()); + + bridgeView.setShowRoot(true); + setupSelectListener(bridgeView); + bridgeView.setCellFactory(param -> new RenderableTreeCell()); + + waterView.setShowRoot(true); + setupSelectListener(waterView); + waterView.setCellFactory(param -> new RenderableTreeCell()); + + terrainView.setShowRoot(true); + setupSelectListener(terrainView); + terrainView.setCellFactory(param -> new RenderableTreeCell()); + + setupSelectListener(vertexView); + vertexView.setRoot(new TreeItem<>()); + vertexView.setCellFactory(param -> new RenderableTreeCell()); + + setupSelectListener(polygonView); + polygonView.setRoot(new TreeItem<>()); + polygonView.setCellFactory(param -> new RenderableTreeCell()); + + setupSelectListener(edgeView); + edgeView.setRoot(new TreeItem<>()); + edgeView.setCellFactory(param -> new RenderableTreeCell()); + } + + private void setupSelectListener(TreeView view) { + view.getSelectionModel().selectedItemProperty().addListener((obs, oldI, newI) -> { + if (newI != null) { + newI.getValue().visit(renderer); + } + }); + } + + private void setup3dView() { + Group root = new Group(); + geomScene = new SubScene(root, 500, 300, true, SceneAntialiasing.BALANCED); + geomScene.heightProperty().bind(meshView.heightProperty()); + geomScene.widthProperty().bind(meshView.widthProperty()); + geomScene.setFill(Color.AZURE); + meshView.getChildren().add(geomScene); + + geomScene.addEventFilter(MouseEvent.MOUSE_PRESSED, me -> { + clickStart[0] = me.getScreenX(); + clickStart[1] = me.getScreenY(); + }); + + geomScene.addEventFilter(MouseEvent.MOUSE_RELEASED, me -> { + if (Math.abs(clickStart[0] - me.getScreenX()) > 3 || Math.abs(clickStart[1] - me.getScreenY()) > 3) { + // skip when mouse moved too much + return; + } + Node node = me.getPickResult().getIntersectedNode(); + if (node != null) { + Object o = node.getUserData(); + if (o instanceof ClickDispatcher cd) { + cd.click(me, clickHandler); + } + } + }); + + world = new Group(); + root.getChildren().add(world); + meshGroup = new Group(); + world.getChildren().add(meshGroup); + + AmbientLight al = new AmbientLight(Color.WHITE); + root.getChildren().add(al); + + buildCamera(); + cameraXRotation.setAxis(Rotate.X_AXIS); + cameraZRotation.setAxis(Rotate.Z_AXIS); + world.getTransforms().add(cameraXRotation); + world.getTransforms().add(cameraZRotation); + root.getChildren().add(camera); + geomScene.setCamera(camera); + + setupMeshViewControls(); + } + + private void setupMeshViewControls() { + meshView.setOnMousePressed(me -> { + if (me.getButton() == MouseButton.PRIMARY) { + dragX = me.getScreenX(); + dragY = me.getScreenY(); + } + }); + + meshView.setOnScroll(se -> { + if (se.getDeltaY() < 0) { + translateZ += translateZ * 0.05; + } else { + translateZ -= translateZ * 0.05; + } + camera.setTranslateZ(translateZ); + highlightController.changeScaling(translateZ); + }); + + meshView.setOnMouseDragged(me -> { + if (me.getButton() == MouseButton.PRIMARY) { + double deltaX = me.getScreenX() - dragX; + double deltaY = me.getScreenY() - dragY; + dragX = me.getScreenX(); + dragY = me.getScreenY(); + + cameraXRot += (deltaX / 3d) % 360; + cameraYRot += (deltaY / 3d) % 360; + + cameraZRotation.setAngle(cameraXRot); + cameraXRotation.setAngle(cameraYRot); + } + }); + } + + private void buildCamera() { + camera = new PerspectiveCamera(true); + camera.setNearClip(0.1); + camera.setFarClip(10000d); + camera.setTranslateZ(translateZ); + cameraZRotation.setAngle(cameraXRot); + cameraXRotation.setAngle(cameraYRot); + } + + public void addFileNameToTitle(String fileName) { + String version = Localization.getText(Localization.VERSION); + stage.setTitle("CityDoctor " + version + " - " + fileName); + } + + public TreeView getBuildingsView() { + return buildingsView; + } + + public TreeView getVegetationView() { + return vegetationView; + } + + public TreeView getTransportationView() { + return transView; + } + + public TreeView getBridgeView() { + return bridgeView; + } + + public TreeView getWaterView() { + return waterView; + } + + public TreeView getTerrainView() { + return terrainView; + } + + public TreeView getPolygonsView() { + return polygonView; + } + + public TreeView getEdgeView() { + return edgeView; + } + + public TreeView getVertexView() { + return vertexView; + } + + public Button getCheckButton() { + return mainToolBar.getCheckButton(); + } + + public ToggleButton getGridButton() { + return mainToolBar.getGridButton(); + } + + public Group getMeshGroup() { + return meshGroup; + } + + public ToggleButton getCullingButton() { + return mainToolBar.getCullingButton(); + } + + public Button getWriteReportButton() { + return mainToolBar.getWriteReportButton(); + } + + public TreeView getErrorTree() { + return errorView; + } + + public Stage getMainStage() { + return stage; + } + + public void unselectEverything() { + buildingsView.getSelectionModel().clearSelection(); + vegetationView.getSelectionModel().clearSelection(); + transView.getSelectionModel().clearSelection(); + waterView.getSelectionModel().clearSelection(); + terrainView.getSelectionModel().clearSelection(); + bridgeView.getSelectionModel().clearSelection(); + polygonView.getSelectionModel().clearSelection(); + edgeView.getSelectionModel().clearSelection(); + vertexView.getSelectionModel().clearSelection(); + errorView.getSelectionModel().clearSelection(); + } + + public ToggleButton getLod1Btn() { + return mainToolBar.getLod1Btn(); + } + + public ToggleButton getLod2Btn() { + return mainToolBar.getLod2Btn(); + } + + public ToggleButton getLod3Btn() { + return mainToolBar.getLod3Btn(); + } + + public ToggleButton getLod4Btn() { + return mainToolBar.getLod4Btn(); + } + + public Button getWorldBtn() { + return mainToolBar.getWorldBtn(); + } + + public Button getSaveBtn() { + return mainToolBar.getSaveBtn(); + } + + public SplitPane getMainContainer() { + return mainContainer; + } + + public ListView getGlobalErrorsView() { + return globalErrorsView; + } + + public void takeViewScreenshot() throws IOException { + WritableImage snapshot = geomScene.snapshot(null, null); + File outputFile = new File("img.png"); + BufferedImage bImage = SwingFXUtils.fromFXImage(snapshot, null); + ImageIO.write(bImage, "png", outputFile); + } + + public void zoomOutForBoundingBox(BoundingBox b) { + double longestSide = b.getDiagonalLength() * 0.4; + double d = longestSide / Math.tan(Math.toRadians(30) / 2); + translateZ = -d; + camera.setTranslateZ(translateZ); + highlightController.changeScaling(-translateZ); + } + + public MainToolBar getMainToolbar() { + return mainToolBar; + } + + public void clearHighlights() { + highlightController.clearHighlights(); + } + + public CityDoctorController getController() { + return controller; + } + + public Button getOpenBtn() { + return mainToolBar.getOpenBtn(); + } + + public VertexClickHandler getClickHandler() { + return clickHandler; + } + + public FeatureType getSelectedTab() { + return selectedTab; + } +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/ModelProvider.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/ModelProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..83d7be1787754334ec39ce32a27663641de38870 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/ModelProvider.java @@ -0,0 +1,17 @@ +package de.hft.stuttgart.citydoctor2.gui; + +import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel; + +public class ModelProvider { + + private CityDoctorController controller; + + public ModelProvider(CityDoctorController controller) { + this.controller = controller; + } + + public CityDoctorModel getModel() { + return controller.getModel(); + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/OpenFileDialog.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/OpenFileDialog.java new file mode 100644 index 0000000000000000000000000000000000000000..ccd3d586809ad7c7b71539836a351b747421627c --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/OpenFileDialog.java @@ -0,0 +1,204 @@ +package de.hft.stuttgart.citydoctor2.gui; + +import java.io.File; +import java.io.IOException; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import de.hft.stuttgart.citydoctor2.utils.Localization; +import javafx.application.Platform; +import javafx.event.Event; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.scene.control.CheckBox; +import javafx.scene.control.Label; +import javafx.scene.control.ProgressBar; +import javafx.scene.control.TextField; +import javafx.scene.control.TextFormatter; +import javafx.scene.control.TitledPane; +import javafx.scene.image.Image; +import javafx.scene.input.KeyCode; +import javafx.scene.input.KeyEvent; +import javafx.scene.layout.VBox; +import javafx.stage.FileChooser; +import javafx.stage.FileChooser.ExtensionFilter; +import javafx.stage.Modality; +import javafx.stage.Stage; +import javafx.stage.Window; + +public class OpenFileDialog { + + private static final Logger logger = LogManager.getLogger(OpenFileDialog.class); + + private Stage stage; + + @FXML + private Button loadBtn; + + @FXML + private Button cancelBtn; + + @FXML + private Button selectBtn; + + @FXML + private TextField precisionField; + + @FXML + private TextField pathField; + + @FXML + private ProgressBar progress; + + @FXML + private CheckBox useValidationBox; + + @FXML + private Label fileLabel; + + @FXML + private TitledPane settingsPane; + + @FXML + private Label roundingPlacesLabel; + + @FXML + private Label xmlValidationLabel; + + @FXML + private Label lowMemoryLabel; + + @FXML + private CheckBox lowMemoryBox; + + private CityDoctorController controller; + private ExceptionDialog exDialog; + private FileChooser fc; + + public OpenFileDialog(Window parent, CityDoctorController controller) throws IOException { + FXMLLoader loader = new FXMLLoader(OpenFileDialog.class.getResource("OpenFileDialog.fxml")); + loader.setController(this); + VBox box = loader.load(); + this.controller = controller; + stage = new Stage(); + stage.getIcons().add(new Image(MainWindow.class.getResourceAsStream("icons/CityDoctor-Logo-rot_klein.jpg"))); + stage.setScene(new Scene(box)); + stage.initOwner(parent); + stage.initModality(Modality.APPLICATION_MODAL); + stage.setTitle("Open File"); + stage.getScene().addEventFilter(KeyEvent.KEY_PRESSED, (KeyEvent event) -> { + if (event.getCode() == KeyCode.ESCAPE) { + stage.close(); + } + }); + } + + public void initialize() { + cancelBtn.setOnAction(ae -> stage.close()); + setupPrecisionField(); + setupLoadButton(); + setupSelectButton(); + applyLanguageToControls(); + } + + private void applyLanguageToControls() { + fileLabel.setText(Localization.getText("OpenFileDialog.fileLabel")); + selectBtn.setText(Localization.getText("OpenFileDialog.selectBtn")); + loadBtn.setText(Localization.getText("OpenFileDialog.loadBtn")); + settingsPane.setText(Localization.getText("OpenFileDialog.settingsPane")); + roundingPlacesLabel.setText(Localization.getText("OpenFileDialog.roundingPlacesLabel")); + xmlValidationLabel.setText(Localization.getText("OpenFileDialog.xmlValidationLabel")); + cancelBtn.setText(Localization.getText("OpenFileDialog.cancelBtn")); + lowMemoryLabel.setText(Localization.getText("OpenFileDialog.lowMemoryLabel")); + } + + private void setupSelectButton() { + selectBtn.setOnAction(ae -> { + if (fc == null) { + fc = new FileChooser(); + fc.setTitle(Localization.getText("OpenFileDialog.select")); + fc.getExtensionFilters().add(new ExtensionFilter("GML/XML", "*.gml", "*.xml")); + fc.getExtensionFilters().add(new ExtensionFilter(Localization.getText("MainWindow.all"), "*.*")); + } + File dir = new File(Settings.get(Settings.LAST_OPEN_FOLDER, "")); + if (dir.exists() && dir.isDirectory()) { + fc.setInitialDirectory(dir); + } else { + String userDir = System.getProperty("user.dir"); + Settings.set(Settings.LAST_OPEN_FOLDER, userDir); + fc.setInitialDirectory(new File(userDir)); + } + File f = fc.showOpenDialog(stage); + if (f != null) { + Settings.set(Settings.LAST_OPEN_FOLDER, f.getParent()); + pathField.setText(f.getAbsolutePath()); + } + }); + } + + private void setupLoadButton() { + loadBtn.setOnAction(ae -> { + int numberOfRoundingPlaces = Integer.parseInt(precisionField.getText()); + boolean useValidation = useValidationBox.isSelected(); + boolean lowMemory = lowMemoryBox.isSelected(); + String path = pathField.getText(); + cancelBtn.setDisable(true); + loadBtn.setDisable(true); + pathField.setDisable(true); + selectBtn.setDisable(true); + stage.setOnCloseRequest(Event::consume); + Thread t = new Thread(() -> { + try { + controller.loadCityGml(path, numberOfRoundingPlaces, progress::setProgress, useValidation, + lowMemory); + Platform.runLater(() -> stage.close()); + } catch (Exception e) { + if (logger.isErrorEnabled()) { + logger.error(Localization.getText("OpenFileDialog.loadFailed"), e); + } + Platform.runLater(() -> { + if (exDialog == null) { + exDialog = new ExceptionDialog(); + } + exDialog.show(e); + }); + } finally { + selectBtn.setDisable(false); + pathField.setDisable(false); + cancelBtn.setDisable(false); + loadBtn.setDisable(false); + stage.setOnCloseRequest(null); + } + }); + t.start(); + }); + } + + private void setupPrecisionField() { + TextFormatter formatter = new TextFormatter<>(change -> { + if (!change.isContentChange()) { + return change; + } + + String text = change.getControlNewText(); + try { + Integer.parseInt(text); + return change; + } catch (NumberFormatException e) { + return null; + } + }); + precisionField.setTextFormatter(formatter); + } + + public void show() { + Platform.runLater(() -> { + progress.setProgress(0d); + stage.showAndWait(); + }); + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/PolygonClickDispatcher.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/PolygonClickDispatcher.java new file mode 100644 index 0000000000000000000000000000000000000000..7bbecfd01b0c2102f7522eeb355660be657ab394 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/PolygonClickDispatcher.java @@ -0,0 +1,19 @@ +package de.hft.stuttgart.citydoctor2.gui; + +import de.hft.stuttgart.citydoctor2.datastructure.Polygon; +import javafx.scene.input.MouseEvent; + +public class PolygonClickDispatcher implements ClickDispatcher { + + private Polygon p; + + public PolygonClickDispatcher(Polygon p) { + this.p = p; + } + + @Override + public void click(MouseEvent me, ClickHandler handler) { + handler.onPolygonClick(p, me); + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/Renderer.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/Renderer.java new file mode 100644 index 0000000000000000000000000000000000000000..91d542d0e80495ebc11b19611fdc5d64755ec69a --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/Renderer.java @@ -0,0 +1,780 @@ +package de.hft.stuttgart.citydoctor2.gui; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import de.hft.stuttgart.citydoctor2.check.CheckError; +import de.hft.stuttgart.citydoctor2.check.Checkable; +import de.hft.stuttgart.citydoctor2.datastructure.AbstractBuilding; +import de.hft.stuttgart.citydoctor2.datastructure.BoundarySurface; +import de.hft.stuttgart.citydoctor2.datastructure.BoundingBox; +import de.hft.stuttgart.citydoctor2.datastructure.BridgeConstructiveElement; +import de.hft.stuttgart.citydoctor2.datastructure.BridgeObject; +import de.hft.stuttgart.citydoctor2.datastructure.Building; +import de.hft.stuttgart.citydoctor2.datastructure.Installation; +import de.hft.stuttgart.citydoctor2.datastructure.BuildingPart; +import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel; +import de.hft.stuttgart.citydoctor2.datastructure.CityObject; +import de.hft.stuttgart.citydoctor2.datastructure.ConcretePolygon; +import de.hft.stuttgart.citydoctor2.datastructure.Edge; +import de.hft.stuttgart.citydoctor2.datastructure.Geometry; +import de.hft.stuttgart.citydoctor2.datastructure.LinearRing; +import de.hft.stuttgart.citydoctor2.datastructure.Lod; +import de.hft.stuttgart.citydoctor2.datastructure.Opening; +import de.hft.stuttgart.citydoctor2.datastructure.Polygon; +import de.hft.stuttgart.citydoctor2.datastructure.ReliefObject; +import de.hft.stuttgart.citydoctor2.datastructure.TinObject; +import de.hft.stuttgart.citydoctor2.datastructure.TransportationObject; +import de.hft.stuttgart.citydoctor2.datastructure.Vegetation; +import de.hft.stuttgart.citydoctor2.datastructure.Vertex; +import de.hft.stuttgart.citydoctor2.datastructure.WaterObject; +import de.hft.stuttgart.citydoctor2.gui.filter.ViewFilter; +import de.hft.stuttgart.citydoctor2.gui.tree.EdgeNode; +import de.hft.stuttgart.citydoctor2.gui.tree.ErrorItemVisitor; +import de.hft.stuttgart.citydoctor2.gui.tree.ErrorNode; +import de.hft.stuttgart.citydoctor2.gui.tree.LinearRingNode; +import de.hft.stuttgart.citydoctor2.gui.tree.PolygonNode; +import de.hft.stuttgart.citydoctor2.gui.tree.Renderable; +import de.hft.stuttgart.citydoctor2.gui.tree.VertexNode; +import de.hft.stuttgart.citydoctor2.math.Triangle3d; +import javafx.application.Platform; +import javafx.scene.control.TreeItem; +import javafx.scene.paint.Color; +import javafx.scene.shape.CullFace; +import javafx.scene.shape.DrawMode; + +public class Renderer { + + private static final Logger logger = LogManager.getLogger(Renderer.class); + + private TriangulatedGeometry currentTriGeom; + private Geometry currentGeometry; + + private CullFace currentCulling = CullFace.BACK; + private DrawMode currentDrawMode = DrawMode.FILL; + + private MainWindow mainWindow; + private HighlightController highlightController; + private ListErrorVisitor errVisitor; + + private LoadingInfoDialog loadingDialog; + + private List lodFilters = new ArrayList<>(); + + private Runnable refresher; + private Runnable errorUpdater; + + public Renderer(MainWindow mainWindow, HighlightController highlightController) throws IOException { + this.mainWindow = mainWindow; + this.highlightController = highlightController; + loadingDialog = new LoadingInfoDialog(mainWindow.getMainStage()); + errVisitor = new ListErrorVisitor(highlightController); + setupLodFilters(); + } + + private void setupLodFilters() { + lodFilters.add(new ViewFilter() { + + @Override + public boolean useGeometry(CityObject co, Geometry geom) { + return geom.getLod() == Lod.LOD1; + } + + }); + lodFilters.add(new ViewFilter() { + + @Override + public boolean useGeometry(CityObject co, Geometry geom) { + return geom.getLod() == Lod.LOD2; + } + + }); + lodFilters.add(new ViewFilter() { + + @Override + public boolean useGeometry(CityObject co, Geometry geom) { + return geom.getLod() == Lod.LOD3; + } + + }); + lodFilters.add(new ViewFilter() { + + @Override + protected boolean useGeometry(CityObject co, Geometry geom) { + return geom.getLod() == Lod.LOD0; + } + + }); + lodFilters.add(new ViewFilter() { + + @Override + public boolean useGeometry(CityObject co, Geometry geom) { + return geom.getLod() == Lod.LOD4; + } + }); + } + + public void enableLod1() { + lodFilters.get(0).enable(); + if (refresher != null) { + refresher.run(); + } + } + + public void disableLod1() { + lodFilters.get(0).disable(); + if (refresher != null) { + refresher.run(); + } + } + + public void enableLod2() { + lodFilters.get(1).enable(); + if (refresher != null) { + refresher.run(); + } + } + + public void disableLod2() { + lodFilters.get(1).disable(); + if (refresher != null) { + refresher.run(); + } + } + + public void enableLod3() { + lodFilters.get(2).enable(); + if (refresher != null) { + refresher.run(); + } + } + + public void disableLod3() { + lodFilters.get(2).disable(); + if (refresher != null) { + refresher.run(); + } + } + + public void enableLod4() { + lodFilters.get(3).enable(); + if (refresher != null) { + refresher.run(); + } + } + + public void disableLod4() { + lodFilters.get(3).disable(); + if (refresher != null) { + refresher.run(); + } + } + + public void render(Building building) { + refresher = () -> { + Set setupBuildingPolygons = setupBuildingPolygons(building); + mainWindow.zoomOutForBoundingBox(BoundingBox.of(setupBuildingPolygons)); + render(setupBuildingPolygons); + Platform.runLater(() -> { + errorUpdater = () -> displayErrors(building); + errorUpdater.run(); + }); + }; + refresher.run(); + } + + private Set setupBuildingPolygons(Building b) { + Set polygons = new HashSet<>(); + addPolygons(b, polygons); + for (BoundarySurface bs : b.getBoundarySurfaces()) { + addPolygons(bs, polygons); + for (Opening op : bs.getOpenings()) { + addPolygons(op, polygons); + } + } + for (Installation bi : b.getBuildingInstallations()) { + addPolygons(bi, polygons); + for (BoundarySurface bs : bi.getBoundarySurfaces()) { + addPolygons(bs, polygons); + for (Opening op : bs.getOpenings()) { + addPolygons(op, polygons); + } + } + } + for (BuildingPart bp : b.getBuildingParts()) { + polygons.addAll(setupBuildingPartPolygons(bp)); + } + return polygons; + } + + public void render(BuildingPart bp) { + refresher = () -> { + Set setupBuildingPartPolygons = setupBuildingPartPolygons(bp); + mainWindow.zoomOutForBoundingBox(BoundingBox.of(setupBuildingPartPolygons)); + render(setupBuildingPartPolygons); + Platform.runLater(() -> { + errorUpdater = () -> displayErrors(bp); + errorUpdater.run(); + }); + }; + refresher.run(); + } + + private Set setupBuildingPartPolygons(BuildingPart bp) { + Set polygons = new HashSet<>(); + addPolygons(bp, polygons); + for (BoundarySurface bs : bp.getBoundarySurfaces()) { + addPolygons(bs, polygons); + for (Opening op : bs.getOpenings()) { + addPolygons(op, polygons); + } + } + for (Installation bi : bp.getBuildingInstallations()) { + addPolygons(bi, polygons); + for (BoundarySurface bs : bi.getBoundarySurfaces()) { + addPolygons(bs, polygons); + for (Opening op : bs.getOpenings()) { + addPolygons(op, polygons); + } + } + } + return polygons; + } + + public void render(BridgeObject bridge) { + refresher = () -> { + Set setupBridgePolygons = setupBridgePolygons(bridge); + mainWindow.zoomOutForBoundingBox(BoundingBox.of(setupBridgePolygons)); + render(setupBridgePolygons); + Platform.runLater(() -> { + errorUpdater = () -> displayErrors(bridge); + errorUpdater.run(); + }); + }; + refresher.run(); + } + + private Set setupBridgePolygons(BridgeObject bridge) { + Set polygons = new HashSet<>(); + addPolygons(bridge, polygons); + for (BoundarySurface bs : bridge.getBoundarySurfaces()) { + addPolygons(bs, polygons); + } + for (BridgeConstructiveElement consElement : bridge.getConstructiveElements()) { + addPolygons(consElement, polygons); + for (BoundarySurface bs : consElement.getBoundarySurfaces()) { + addPolygons(bs, polygons); + } + } + for (Installation inst : bridge.getBridgeInstallations()) { + addPolygons(inst, polygons); + for (BoundarySurface bs : inst.getBoundarySurfaces()) { + addPolygons(bs, polygons); + } + } + return polygons; + } + + public void render(CityObject co) { + refresher = () -> { + Set setupCityObjectPolygons = setupCityObjectPolygons(co); + mainWindow.zoomOutForBoundingBox(BoundingBox.of(setupCityObjectPolygons)); + render(setupCityObjectPolygons); + Platform.runLater(() -> { + errorUpdater = () -> displayErrors(co); + errorUpdater.run(); + }); + }; + refresher.run(); + } + + public void render(ReliefObject relief) { + refresher = () -> { + Set setupCityObjectPolygons = setupReliefPolygons(relief); + mainWindow.zoomOutForBoundingBox(BoundingBox.of(setupCityObjectPolygons)); + render(setupCityObjectPolygons); + Platform.runLater(() -> { + errorUpdater = () -> displayErrors(relief); + errorUpdater.run(); + }); + }; + refresher.run(); + } + + private Set setupReliefPolygons(ReliefObject relief) { + Set polygons = new HashSet<>(); + addPolygons(relief, polygons); + for (TinObject tin : relief.getComponents()) { + addPolygons(tin, polygons); + } + return polygons; + } + + public void render(Installation bi) { + refresher = () -> { + Set setupCityObjectPolygons = setupBuildingInstallationPolygons(bi); + mainWindow.zoomOutForBoundingBox(BoundingBox.of(setupCityObjectPolygons)); + render(setupCityObjectPolygons); + Platform.runLater(() -> { + errorUpdater = () -> displayErrors(bi); + errorUpdater.run(); + }); + }; + refresher.run(); + } + + private Set setupBuildingInstallationPolygons(Installation bi) { + Set polygons = new HashSet<>(); + addPolygons(bi, polygons); + for (BoundarySurface bs : bi.getBoundarySurfaces()) { + addPolygons(bs, polygons); + for (Opening op : bs.getOpenings()) { + addPolygons(op, polygons); + } + } + return polygons; + } + + public void render(BoundarySurface bs) { + refresher = () -> { + Set setupBoundarySurfacePolygons = setupBoundarySurfacePolygons(bs); + mainWindow.zoomOutForBoundingBox(BoundingBox.of(setupBoundarySurfacePolygons)); + render(setupBoundarySurfacePolygons); + Platform.runLater(() -> { + errorUpdater = () -> displayErrors(bs); + errorUpdater.run(); + }); + }; + refresher.run(); + } + + private Set setupBoundarySurfacePolygons(BoundarySurface bs) { + Set polygons = new HashSet<>(); + addPolygons(bs, polygons); + for (Opening op : bs.getOpenings()) { + addPolygons(op, polygons); + } + return polygons; + } + + private Set setupCityObjectPolygons(CityObject co) { + Set polygons = new HashSet<>(); + addPolygons(co, polygons); + return polygons; + } + + private void addPolygons(CityObject co, Set polygons) { + for (Geometry geom : co.getGeometries()) { + boolean used = false; + for (ViewFilter filter : lodFilters) { + if (filter.allowedToUse(co, geom)) { + used = true; + break; + } + } + if (used) { + addConcretePolygons(polygons, geom); + } + } + } + + private void displayErrors(Checkable c) { + if (!c.isValidated()) { + return; + } + List errors = new ArrayList<>(); + c.collectContainedErrors(errors); + + // filter out duplicate errors (polygon can be contained in multiple geometries) + Set errorSet = new HashSet<>(errors); + for (CheckError err : errorSet) { + ErrorNode node = new ErrorNode(err); + TreeItem errItem = new TreeItem<>(node); + ErrorItemVisitor visitor = new ErrorItemVisitor(errItem); + err.accept(visitor); + mainWindow.getErrorTree().getRoot().getChildren().add(errItem); + + } + } + + public void render(Geometry geom) { + refresher = () -> { + Platform.runLater(this::clearGeometryTrees); + currentTriGeom = TriangulatedGeometry.of(geom); + if (geom.getEdges() == null && currentGeometry != null) { + // if there are no edges available low memory mode is enabled + // clear the old geometry of all meta information + currentGeometry.clearMetaInformation(); + } + errVisitor.setGeometry(currentTriGeom); + Platform.runLater(() -> { + setupRenderState(); + if (geom.getEdges() == null) { + // create edges and vertices so they can be listed in the gui + geom.prepareForChecking(); + // remember the geometry, so it can be cleared if another is displayed + currentGeometry = geom; + } + addGeometryDataToView(geom); + mainWindow.zoomOutForBoundingBox(BoundingBox.of(geom.getPolygons())); + errorUpdater = () -> displayErrors(geom); + errorUpdater.run(); + }); + }; + refresher.run(); + } + + private void addGeometryDataToView(Geometry geom) { + for (Polygon p : geom.getPolygons()) { + addPolygonToView(p); + } + for (Edge e : geom.getEdges()) { + addEdgeToView(e); + } + for (Vertex v : geom.getVertices()) { + addVertexToView(v); + } + } + + private void addVertexToView(Vertex v) { + Renderable cf = new VertexNode(v); + TreeItem ti = new TreeItem<>(cf); + mainWindow.getVertexView().getRoot().getChildren().add(ti); + } + + private void addEdgeToView(Edge e) { + EdgeNode cf = new EdgeNode(e); + TreeItem ti = new TreeItem<>(cf); + mainWindow.getEdgeView().getRoot().getChildren().add(ti); + } + + private void addPolygonToView(Polygon p) { + CheckStatus cs = determineCheckStatus(p); + PolygonNode cf = new PolygonNode(p, cs); + TreeItem ti = new TreeItem<>(cf); + mainWindow.getPolygonsView().getRoot().getChildren().add(ti); + + // add linear rings + CheckStatus csRing = determineCheckStatus(p.getExteriorRing()); + Renderable ccRing = new LinearRingNode(p.getExteriorRing(), csRing); + TreeItem tiRing = new TreeItem<>(ccRing); + ti.getChildren().add(tiRing); + + for (Vertex v : p.getExteriorRing().getVertices()) { + VertexNode vn = new VertexNode(v); + TreeItem tiV = new TreeItem<>(vn); + tiRing.getChildren().add(tiV); + } + + for (LinearRing lr : p.getInnerRings()) { + CheckStatus csInteriorRing = determineCheckStatus(lr); + Renderable ccInteriorRing = new LinearRingNode(lr, csInteriorRing); + TreeItem tiInteriorRing = new TreeItem<>(ccInteriorRing); + ti.getChildren().add(tiInteriorRing); + for (Vertex v : lr.getVertices()) { + VertexNode vn = new VertexNode(v); + TreeItem tiV = new TreeItem<>(vn); + tiRing.getChildren().add(tiV); + } + } + } + + private CheckStatus determineCheckStatus(Checkable c) { + if (!c.isValidated()) { + return CheckStatus.NOT_CHECKED; + } + if (c.containsAnyError()) { + return CheckStatus.ERROR; + } + return CheckStatus.OK; + } + + private void render(Collection polygons) { + Platform.runLater(this::clearGeometryTrees); + currentTriGeom = TriangulatedGeometry.of(polygons); + errVisitor.setGeometry(currentTriGeom); + setupRenderState(); + } + + private void clearGeometryTrees() { + highlightController.clearHighlights(); + mainWindow.getErrorTree().getRoot().getChildren().clear(); + mainWindow.getPolygonsView().getRoot().getChildren().clear(); + mainWindow.getEdgeView().getRoot().getChildren().clear(); + mainWindow.getVertexView().getRoot().getChildren().clear(); + } + + public void renderBuildings(List objects) { + errorUpdater = null; + refresher = () -> { + Platform.runLater(() -> { + loadingDialog.show(); + clearGeometryTrees(); + }); + Thread t = new Thread(() -> { + Set polygons = new HashSet<>(); + for (Building b : objects) { + collectPolygons(polygons, b); + for (BuildingPart bp : b.getBuildingParts()) { + collectPolygons(polygons, bp); + } + } + currentTriGeom = TriangulatedGeometry.of(polygons); + errVisitor.setGeometry(currentTriGeom); + Platform.runLater(() -> { + setupRenderState(); + mainWindow.zoomOutForBoundingBox(BoundingBox.of(polygons)); + loadingDialog.hide(); + }); + }); + t.setUncaughtExceptionHandler((thread, e) -> { + Platform.runLater(() -> loadingDialog.hide()); + logger.catching(e); + }); + t.start(); + }; + refresher.run(); + } + + public void render(CityDoctorModel model) { + errorUpdater = null; + refresher = () -> { + Platform.runLater(() -> { + loadingDialog.show(); + clearGeometryTrees(); + }); + Thread t = new Thread(() -> { + currentTriGeom = TriangulatedGeometry.of(model, lodFilters); + errVisitor.setGeometry(currentTriGeom); + Platform.runLater(() -> { + setupRenderState(); + mainWindow.zoomOutForBoundingBox(BoundingBox.of(model)); + loadingDialog.hide(); + }); + }); + t.setUncaughtExceptionHandler((thread, e) -> { + Platform.runLater(() -> loadingDialog.hide()); + logger.catching(e); + }); + t.start(); + }; + refresher.run(); + } + + public void renderVegetation(List vegetation) { + renderCityObjects(vegetation, Color.LIGHTGREEN); + } + + public void renderTransportation(List transportation) { + renderCityObjects(transportation, Color.YELLOW); + } + + public void renderBridges(List bridges) { + renderCityObjects(bridges, Color.CORAL); + } + + public void renderWater(List water) { + renderCityObjects(water, Color.LIGHTSKYBLUE); + } + + public void renderTerrain(List land) { + renderLandObjects(land, Color.BROWN); + } + + private void renderLandObjects(List cos, Color baseColor) { + errorUpdater = null; + refresher = () -> { + Platform.runLater(() -> { + loadingDialog.show(); + clearGeometryTrees(); + }); + Thread t = new Thread(() -> { + Set polygons = new HashSet<>(); + for (CityObject co : cos) { + addPolygons(co, polygons); + if (co instanceof ReliefObject) { + ReliefObject relief = (ReliefObject) co; + for (TinObject tin : relief.getComponents()) { + addPolygons(tin, polygons); + } + } + } + currentTriGeom = TriangulatedGeometry.of(polygons, baseColor); + errVisitor.setGeometry(currentTriGeom); + Platform.runLater(() -> { + setupRenderState(); + mainWindow.zoomOutForBoundingBox(BoundingBox.of(polygons)); + loadingDialog.hide(); + }); + }); + t.setUncaughtExceptionHandler((thread, e) -> Platform.runLater(() -> loadingDialog.hide())); + t.start(); + }; + refresher.run(); + } + + public void renderCityObjects(List cos, Color baseColor) { + errorUpdater = null; + refresher = () -> { + Platform.runLater(() -> { + loadingDialog.show(); + clearGeometryTrees(); + }); + Thread t = new Thread(() -> { + Set polygons = new HashSet<>(); + for (CityObject co : cos) { + addPolygons(co, polygons); + } + currentTriGeom = TriangulatedGeometry.of(polygons, baseColor); + errVisitor.setGeometry(currentTriGeom); + Platform.runLater(() -> { + setupRenderState(); + mainWindow.zoomOutForBoundingBox(BoundingBox.of(polygons)); + loadingDialog.hide(); + }); + }); + t.setUncaughtExceptionHandler((thread, e) -> Platform.runLater(() -> loadingDialog.hide())); + t.start(); + }; + refresher.run(); + } + + private void collectPolygons(Set polygons, AbstractBuilding ab) { + addPolygons(ab, polygons); + for (Installation bi : ab.getBuildingInstallations()) { + addPolygons(bi, polygons); + for (BoundarySurface bs : bi.getBoundarySurfaces()) { + addPolygons(bs, polygons); + for (Opening o : bs.getOpenings()) { + addPolygons(o, polygons); + } + } + } + for (BoundarySurface bs : ab.getBoundarySurfaces()) { + addPolygons(bs, polygons); + for (Opening o : bs.getOpenings()) { + addPolygons(o, polygons); + } + } + } + + private void addConcretePolygons(Set polygons, Geometry geom) { + for (Polygon p : geom.getPolygons()) { + polygons.add(p.getOriginal()); + } + } + + private void setupRenderState() { + currentTriGeom.setCullFace(currentCulling); + currentTriGeom.setDrawMode(currentDrawMode); + Platform.runLater(() -> { + mainWindow.getMeshGroup().getChildren().clear(); + mainWindow.getMeshGroup().getChildren().addAll(currentTriGeom.getMeshes()); + }); + mainWindow.getGridButton().setDisable(false); + mainWindow.getCullingButton().setDisable(false); + } + + public void showWireFrame(boolean show) { + if (currentTriGeom != null) { + if (show) { + currentDrawMode = DrawMode.LINE; + } else { + currentDrawMode = DrawMode.FILL; + } + currentTriGeom.setDrawMode(currentDrawMode); + } + } + + public void enableCulling(boolean enable) { + if (currentTriGeom != null) { + if (enable) { + currentCulling = CullFace.BACK; + } else { + currentCulling = CullFace.NONE; + } + currentTriGeom.setCullFace(currentCulling); + } + } + + public void clearCurrentRender() { + // don't render anything + Platform.runLater(() -> { + mainWindow.getMeshGroup().getChildren().clear(); + clearGeometryTrees(); + }); + } + + public void highlight(Polygon p) { + highlightController.highlight(p, currentTriGeom); + } + + public void highlight(LinearRing lr) { + highlightController.highlight(lr, currentTriGeom); + } + + public void highlight(Edge e) { + highlightController.highlight(e, currentTriGeom); + } + + public void highlight(Vertex v) { + highlightController.highlight(v, currentTriGeom); + } + + public void highlight(List highlightedRings) { + highlightController.highlight(highlightedRings, currentTriGeom); + } + + public void highlightEdges(List edges) { + highlightController.highlightEdges(edges, currentTriGeom); + } + + public void highlightPolygons(List> components) { + highlightController.highlightPolygons(components, currentTriGeom); + } + + public void addHighlight(Vertex vertex, Color c) { + highlightController.addHighlight(vertex, currentTriGeom, c); + } + + public void highlight(CheckError err) { + err.accept(errVisitor); + } + + public void refresh() { + if (refresher != null) { + refresher.run(); + } + } + + public void updateErrors() { + if (errorUpdater != null) { + errorUpdater.run(); + } + } + + public void clearHighlights() { + highlightController.clearHighlights(); + } + + public void addHighlight(Polygon p) { + highlightController.addHighlight(p, currentTriGeom); + } + + public void addHighlight(Triangle3d t) { + highlightController.highlight(t, currentTriGeom); + } + + public void reset() { + errorUpdater = null; + refresher = null; + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/Settings.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/Settings.java new file mode 100644 index 0000000000000000000000000000000000000000..0ce59586ac091a76e2cae9d5e55c504b123a9968 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/Settings.java @@ -0,0 +1,66 @@ +package de.hft.stuttgart.citydoctor2.gui; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Properties; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class Settings { + + private static final Logger logger = LogManager.getLogger(Settings.class); + + public static final String LAST_OPEN_FOLDER = "lastOpenFolder"; + public static final String MAXIMIZED = "maximized"; + public static final String FRAME_HEIGHT = "frameHeight"; + public static final String FRAME_WIDTH = "frameWidth"; + public static final String FRAME_X = "frameX"; + public static final String FRAME_Y = "frameY"; + public static final String LANGUAGE = "language"; + + private static Properties props; + + static { + props = new Properties(); + + File propFile = new File("GUISettings.properties"); + if (propFile.exists()) { + try (BufferedReader bis = new BufferedReader(new FileReader(propFile))) { + props.load(bis); + } catch (IOException e) { + logger.error("Failed to load settings", e); + } + } + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + try (BufferedWriter bw = new BufferedWriter(new FileWriter(propFile))) { + props.store(bw, "GUI configuration"); + } catch (IOException e) { + logger.error("Failed to save settings", e); + } + })); + } + + private Settings() { + + } + + public static String get(String name) { + return props.getProperty(name); + } + + public static void set(String name, String value) { + props.setProperty(name, value); + } + + public static String get(String name, String defaultV) { + return props.getProperty(name, defaultV); + } + + + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/TableEditCell.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/TableEditCell.java new file mode 100644 index 0000000000000000000000000000000000000000..8ff2dc80dd1afdd7e307a167839ce6ffe18dbbb2 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/TableEditCell.java @@ -0,0 +1,148 @@ +/*- + * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart + * + * This file is part of CityDoctor2. + * + * CityDoctor2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CityDoctor2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with CityDoctor2. If not, see . + */ +package de.hft.stuttgart.citydoctor2.gui; + +import javafx.event.Event; +import javafx.scene.control.ContentDisplay; +import javafx.scene.control.TableCell; +import javafx.scene.control.TableColumn; +import javafx.scene.control.TableColumn.CellEditEvent; +import javafx.scene.control.TablePosition; +import javafx.scene.control.TableView; +import javafx.scene.control.TextField; +import javafx.scene.input.KeyCode; +import javafx.scene.input.KeyEvent; +import javafx.util.StringConverter; + +public class TableEditCell extends TableCell { + + // Text field for editing + private final TextField textField = new TextField(); + + // Converter for converting the text in the text field to the user type, and + // vice-versa: + private final StringConverter converter; + + public TableEditCell(StringConverter converter) { + this.converter = converter; + + itemProperty().addListener((obx, oldItem, newItem) -> { + if (newItem == null) { + setText(null); + } else { + setText(converter.toString(newItem)); + } + }); + setGraphic(textField); + setContentDisplay(ContentDisplay.TEXT_ONLY); + + textField.setOnAction(evt -> commitEdit(this.converter.fromString(textField.getText()))); + textField.focusedProperty().addListener((obs, wasFocused, isNowFocused) -> { + if (Boolean.FALSE.equals(isNowFocused)) { + commitEdit(this.converter.fromString(textField.getText())); + } + }); + textField.addEventFilter(KeyEvent.KEY_PRESSED, event -> { + if (event.getCode() == KeyCode.ESCAPE) { + textField.setText(converter.toString(getItem())); + cancelEdit(); + event.consume(); + } else if (event.getCode() == KeyCode.RIGHT) { + getTableView().getSelectionModel().selectRightCell(); + event.consume(); + } else if (event.getCode() == KeyCode.LEFT) { + getTableView().getSelectionModel().selectLeftCell(); + event.consume(); + } else if (event.getCode() == KeyCode.UP) { + getTableView().getSelectionModel().selectAboveCell(); + event.consume(); + } else if (event.getCode() == KeyCode.DOWN) { + getTableView().getSelectionModel().selectBelowCell(); + event.consume(); + } + }); + } + + /** + * Convenience converter that does nothing (converts Strings to themselves and + * vice-versa...). + */ + public static final StringConverter IDENTITY_CONVERTER = new StringConverter<>() { + + @Override + public String toString(String object) { + return object; + } + + @Override + public String fromString(String string) { + return string; + } + + }; + + /** + * Convenience method for creating an EditCell for a String value. + * + * @return + */ + public static TableEditCell createStringEditCell() { + return new TableEditCell<>(IDENTITY_CONVERTER); + } + + // set the text of the text field and display the graphic + @Override + public void startEdit() { + super.startEdit(); + textField.setText(converter.toString(getItem())); + setContentDisplay(ContentDisplay.GRAPHIC_ONLY); + textField.requestFocus(); + } + + // revert to text display + @Override + public void cancelEdit() { + super.cancelEdit(); + setContentDisplay(ContentDisplay.TEXT_ONLY); + } + + // commits the edit. Update property if possible and revert to text display + @Override + public void commitEdit(T item) { + + // This block is necessary to support commit on losing focus, because the + // baked-in mechanism + // sets our editing state to false before we can intercept the loss of focus. + // The default commitEdit(...) method simply bails if we are not editing... + if (!isEditing() && !item.equals(getItem())) { + TableView table = getTableView(); + if (table != null) { + TableColumn column = getTableColumn(); + CellEditEvent event = new CellEditEvent<>(table, + new TablePosition<>(table, getIndex(), column), TableColumn.editCommitEvent(), item); + Event.fireEvent(column, event); + } + } + + super.commitEdit(item); + + setContentDisplay(ContentDisplay.TEXT_ONLY); + } + +} \ No newline at end of file diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/TreeEditCell.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/TreeEditCell.java new file mode 100644 index 0000000000000000000000000000000000000000..dcc526340999ee26bf429fc9a1cad2c8f1f31e98 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/TreeEditCell.java @@ -0,0 +1,121 @@ +/*- + * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart + * + * This file is part of CityDoctor2. + * + * CityDoctor2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CityDoctor2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with CityDoctor2. If not, see . + */ +package de.hft.stuttgart.citydoctor2.gui; + +import javafx.event.Event; +import javafx.scene.control.ContentDisplay; +import javafx.scene.control.TextField; +import javafx.scene.control.TreeTableCell; +import javafx.scene.control.TreeTableColumn; +import javafx.scene.control.TreeTableColumn.CellEditEvent; +import javafx.scene.control.TreeTablePosition; +import javafx.scene.control.TreeTableView; +import javafx.scene.input.KeyCode; +import javafx.scene.input.KeyEvent; +import javafx.util.StringConverter; + +public class TreeEditCell extends TreeTableCell { + + // Text field for editing + private final TextField textField = new TextField(); + + // Converter for converting the text in the text field to the user type, and + // vice-versa: + private final StringConverter converter; + + public TreeEditCell(StringConverter converter) { + this.converter = converter; + + itemProperty().addListener((obx, oldItem, newItem) -> { + if (newItem == null) { + setText(null); + } else { + setText(converter.toString(newItem)); + } + }); + setGraphic(textField); + setContentDisplay(ContentDisplay.TEXT_ONLY); + + textField.setOnAction(evt -> commitEdit(this.converter.fromString(textField.getText()))); + textField.focusedProperty().addListener((obs, wasFocused, isNowFocused) -> { + if (Boolean.FALSE.equals(isNowFocused)) { + commitEdit(this.converter.fromString(textField.getText())); + } + }); + textField.addEventFilter(KeyEvent.KEY_PRESSED, event -> { + if (event.getCode() == KeyCode.ESCAPE) { + textField.setText(converter.toString(getItem())); + cancelEdit(); + event.consume(); + } else if (event.getCode() == KeyCode.RIGHT) { + getTreeTableView().getSelectionModel().selectRightCell(); + event.consume(); + } else if (event.getCode() == KeyCode.LEFT) { + getTreeTableView().getSelectionModel().selectLeftCell(); + event.consume(); + } else if (event.getCode() == KeyCode.UP) { + getTreeTableView().getSelectionModel().selectAboveCell(); + event.consume(); + } else if (event.getCode() == KeyCode.DOWN) { + getTreeTableView().getSelectionModel().selectBelowCell(); + event.consume(); + } + }); + } + + // set the text of the text field and display the graphic + @Override + public void startEdit() { + super.startEdit(); + textField.setText(converter.toString(getItem())); + setContentDisplay(ContentDisplay.GRAPHIC_ONLY); + textField.requestFocus(); + } + + // revert to text display + @Override + public void cancelEdit() { + super.cancelEdit(); + setContentDisplay(ContentDisplay.TEXT_ONLY); + } + + // commits the edit. Update property if possible and revert to text display + @Override + public void commitEdit(T item) { + + // This block is necessary to support commit on losing focus, because the + // baked-in mechanism + // sets our editing state to false before we can intercept the loss of focus. + // The default commitEdit(...) method simply bails if we are not editing... + if (!isEditing() && !item.equals(getItem())) { + TreeTableView table = getTreeTableView(); + if (table != null) { + TreeTableColumn column = getTableColumn(); + CellEditEvent event = new CellEditEvent<>(table, + new TreeTablePosition<>(table, getIndex(), column), TreeTableColumn.editCommitEvent(), item); + Event.fireEvent(column, event); + } + } + + super.commitEdit(item); + + setContentDisplay(ContentDisplay.TEXT_ONLY); + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/TriangulatedGeometry.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/TriangulatedGeometry.java new file mode 100644 index 0000000000000000000000000000000000000000..b5501944074fb09b5a793ddbc021a5c34b713813 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/TriangulatedGeometry.java @@ -0,0 +1,334 @@ +package de.hft.stuttgart.citydoctor2.gui; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import de.hft.stuttgart.citydoctor2.datastructure.BoundarySurface; +import de.hft.stuttgart.citydoctor2.datastructure.BoundarySurfaceType; +import de.hft.stuttgart.citydoctor2.datastructure.Building; +import de.hft.stuttgart.citydoctor2.datastructure.Installation; +import de.hft.stuttgart.citydoctor2.datastructure.BuildingPart; +import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel; +import de.hft.stuttgart.citydoctor2.datastructure.CityObject; +import de.hft.stuttgart.citydoctor2.datastructure.Geometry; +import de.hft.stuttgart.citydoctor2.datastructure.Opening; +import de.hft.stuttgart.citydoctor2.datastructure.OpeningType; +import de.hft.stuttgart.citydoctor2.datastructure.Polygon; +import de.hft.stuttgart.citydoctor2.gui.filter.ViewFilter; +import de.hft.stuttgart.citydoctor2.math.Triangle3d; +import de.hft.stuttgart.citydoctor2.math.UnitVector3d; +import de.hft.stuttgart.citydoctor2.math.Vector3d; +import de.hft.stuttgart.citydoctor2.tesselation.TesselatedPolygon; +import javafx.scene.paint.Color; +import javafx.scene.paint.PhongMaterial; +import javafx.scene.shape.CullFace; +import javafx.scene.shape.DrawMode; +import javafx.scene.shape.MeshView; +import javafx.scene.shape.TriangleMesh; +import javafx.scene.shape.VertexFormat; + +public class TriangulatedGeometry { + + private static final PhongMaterial GRID_MAT = new PhongMaterial(Color.BLACK); + + // random vector for calculating normal angles, for color determination + private static final UnitVector3d AXIS = new Vector3d(19, 0.8, 1.5).normalize(); + + private Vector3d movedBy; + private List meshes; + private List materials; + + public static TriangulatedGeometry of(Geometry geom) { + return of(geom.getPolygons()); + } + + public static TriangulatedGeometry of(Collection polygons, Color basePolygonColor) { + TriangulatedGeometry triGeom = new TriangulatedGeometry(); + triGeom.materials = new ArrayList<>(); + triGeom.meshes = new ArrayList<>(); + List points = new ArrayList<>(); + for (Polygon p : polygons) { + points.addAll(p.getExteriorRing().getVertices()); + } + triGeom.movedBy = triGeom.findCenter(points); + + addPolygonDataToTriGeom(polygons, basePolygonColor, triGeom); + return triGeom; + } + + private static void addPolygonDataToTriGeom(Collection polygons, Color basePolygonColor, + TriangulatedGeometry triGeom) { + for (Polygon p : polygons) { + TesselatedPolygon tp = p.tesselate(); + TriangleMesh triMesh = new TriangleMesh(VertexFormat.POINT_TEXCOORD); + Map indexMap = new HashMap<>(); + List vertices = new ArrayList<>(); + int index = 0; + for (Triangle3d t : tp.getTriangles()) { + index = triGeom.filterDuplicates(triMesh, indexMap, vertices, index, t.getP1()); + index = triGeom.filterDuplicates(triMesh, indexMap, vertices, index, t.getP2()); + index = triGeom.filterDuplicates(triMesh, indexMap, vertices, index, t.getP3()); + } + + for (Vector3d point : vertices) { + float x = (float) (point.getX() - triGeom.movedBy.getX()); + float y = (float) (point.getY() - triGeom.movedBy.getY()); + float z = (float) (point.getZ() - triGeom.movedBy.getZ()); + triMesh.getPoints().addAll(x, y, z); + } + triMesh.getTexCoords().addAll(0, 0); + + MeshView view = new MeshView(triMesh); + view.setUserData(new PolygonClickDispatcher(p)); + + PhongMaterial mat = triGeom.calculateMaterial(p, basePolygonColor); + triGeom.materials.add(mat); + triGeom.meshes.add(view); + } + } + + public static TriangulatedGeometry of(CityDoctorModel model, List filters) { + List points = new ArrayList<>(); + addPointsFromBuildings(model.getBuildings(), points); + addPointsFromCityObject(model.getBridges(), points); + addPointsFromCityObject(model.getLand(), points); + addPointsFromCityObject(model.getTransportation(), points); + addPointsFromCityObject(model.getVegetation(), points); + addPointsFromCityObject(model.getWater(), points); + + TriangulatedGeometry triGeom = new TriangulatedGeometry(); + triGeom.materials = new ArrayList<>(); + triGeom.meshes = new ArrayList<>(); + triGeom.movedBy = triGeom.findCenter(points); + + addPolygonDataFromBuildings(model.getBuildings(), triGeom, filters); + addPolygonDataFromCityObjects(model.getBridges(), triGeom, Color.CORAL, filters); + addPolygonDataFromCityObjects(model.getLand(), triGeom, Color.BROWN, filters); + addPolygonDataFromCityObjects(model.getTransportation(), triGeom, Color.YELLOW, filters); + addPolygonDataFromCityObjects(model.getVegetation(), triGeom, Color.LIGHTGREEN, filters); + addPolygonDataFromCityObjects(model.getWater(), triGeom, Color.LIGHTSKYBLUE, filters); + + return triGeom; + } + + private static void addPolygonDataFromBuildings(List buildings, TriangulatedGeometry triGeom, List filters) { + for (Building b : buildings) { + addPolygonData(b, triGeom, Color.WHITE, filters); + addPolygonDataFromBoundarySurfaces(b.getBoundarySurfaces(), triGeom, filters); + addPolygonDataFromCityObjects(b.getBuildingInstallations(), triGeom, Color.WHITE, filters); + for (Installation bi : b.getBuildingInstallations()) { + addPolygonDataFromCityObjects(bi.getBoundarySurfaces(), triGeom, Color.WHITE, filters); + } + for (BuildingPart bp : b.getBuildingParts()) { + addPolygonData(bp, triGeom, Color.WHITE, filters); + addPolygonDataFromBoundarySurfaces(bp.getBoundarySurfaces(), triGeom, filters); + addPolygonDataFromCityObjects(bp.getBuildingInstallations(), triGeom, Color.WHITE, filters); + } + } + } + + private static void addPolygonDataFromBoundarySurfaces(List boundarySurfaces, + TriangulatedGeometry triGeom, List filters) { + for (BoundarySurface bs : boundarySurfaces) { + addPolygonData(bs, triGeom, Color.WHITE, filters); + for (Opening o : bs.getOpenings()) { + addPolygonData(o, triGeom, Color.WHITE, filters); + } + } + } + + private static void addPolygonDataFromCityObjects(List cos, + TriangulatedGeometry triGeom, Color color, List filters) { + for (CityObject co : cos) { + addPolygonData(co, triGeom, color, filters); + } + } + + private static void addPolygonData(CityObject co, TriangulatedGeometry triGeom, Color color, List filters) { + for (Geometry geom : co.getGeometries()) { + if (isGeometryFiltered(co, geom, filters)) { + continue; + } + List polygons = new ArrayList<>(); + for (Polygon p : geom.getPolygons()) { + if (p.isLink()) { + continue; + } + polygons.add(p); + } + addPolygonDataToTriGeom(polygons, color, triGeom); + } + } + + private static boolean isGeometryFiltered(CityObject co, Geometry geom, List filters) { + for (ViewFilter filter : filters) { + if (filter.allowedToUse(co, geom)) { + return false; + } + } + return true; + } + + private static void addPointsFromBuildings(List buildings, List points) { + for (Building b : buildings) { + addPoints(b, points); + for (BuildingPart bp : b.getBuildingParts()) { + addPoints(bp, points); + addPointsFromCityObject(bp.getBoundarySurfaces(), points); + addPointsFromCityObject(bp.getBuildingInstallations(), points); + } + addPointsFromCityObject(b.getBoundarySurfaces(), points); + addPointsFromCityObject(b.getBuildingInstallations(), points); + } + } + + private static void addPointsFromCityObject(List cos, List points) { + for (CityObject co : cos) { + addPoints(co, points); + } + } + + private static void addPoints(CityObject co, List points) { + for (Geometry geom : co.getGeometries()) { + for (Polygon p : geom.getPolygons()) { + if (p.isLink()) { + continue; + } + points.addAll(p.getExteriorRing().getVertices()); + } + } + } + + public static TriangulatedGeometry of(Collection polygons) { + return of(polygons, Color.WHITE); + } + + private int filterDuplicates(TriangleMesh triMesh, Map indexMap, List vertices, + int index, Vector3d v) { + Integer vertexIndex = indexMap.get(v); + if (vertexIndex == null) { + indexMap.put(v, index); + vertices.add(v); + vertexIndex = index; + index++; + } + triMesh.getFaces().addAll(vertexIndex, 0); + return index; + } + + private PhongMaterial calculateMaterial(Polygon p, Color baseColor) { + Vector3d normal = p.calculateNormalNormalized(); + + BoundarySurface bs = p.getPartOfSurface(); + if (bs != null) { + if (bs.getType() == BoundarySurfaceType.ROOF) { + baseColor = Color.RED; + } else if (bs.getType() == BoundarySurfaceType.GROUND) { + baseColor = Color.KHAKI; + } + } + + baseColor = determineColorDependingOnParentType(p, baseColor); + + double cos = normal.dot(AXIS); + double acos = Math.acos(cos); + // normalize to range [0.3, 0.9] + acos = acos / Math.PI; + acos = acos * 0.6 + 0.3; + + Color derivedColor = baseColor.deriveColor(0, 1.0, acos, 1.0); + return new PhongMaterial(derivedColor); + } + + private Color determineColorDependingOnParentType(Polygon p, Color baseColor) { + p = p.getOriginal(); + Polygon p1 = p.getLinkedFromPolygon(); + baseColor = changeBaseColorIfPolygonHasOpeningParent(p1, baseColor); + baseColor = changeBaseColorIfPolygonHasOpeningParent(p, baseColor); + return baseColor; + } + + private Color changeBaseColorIfPolygonHasOpeningParent(Polygon p, Color baseColor) { + if (p == null) { + return baseColor; + } + CityObject parent = p.getParent().getParent(); + if (parent instanceof Opening op) { + if (op.getType() == OpeningType.DOOR) { + baseColor = Color.ORANGE; + } else { + baseColor = Color.TEAL; + } + } + return baseColor; + } + + private Vector3d findCenter(List points) { + double xMin = Double.MAX_VALUE; + double yMin = Double.MAX_VALUE; + double zMin = Double.MAX_VALUE; + + double xMax = Double.NEGATIVE_INFINITY; + double yMax = Double.NEGATIVE_INFINITY; + double zMax = Double.NEGATIVE_INFINITY; + + for (Vector3d point : points) { + if (point.getX() < xMin) { + xMin = point.getX(); + } + if (point.getX() > xMax) { + xMax = point.getX(); + } + if (point.getY() < yMin) { + yMin = point.getY(); + } + if (point.getY() > yMax) { + yMax = point.getY(); + } + if (point.getZ() < zMin) { + zMin = point.getZ(); + } + if (point.getZ() > zMax) { + zMax = point.getZ(); + } + } + + // center + double x = (xMax - xMin) / 2 + xMin; + double y = (yMax - yMin) / 2 + yMin; + double z = (zMax - zMin) / 2 + zMin; + return new Vector3d(x, y, z); + } + + public Vector3d getMovedBy() { + return movedBy; + } + + public void setCullFace(CullFace currentCulling) { + for (MeshView mesh : meshes) { + mesh.setCullFace(currentCulling); + } + } + + public void setDrawMode(DrawMode currentDrawMode) { + if (currentDrawMode == DrawMode.LINE) { + for (MeshView mesh : meshes) { + mesh.setDrawMode(currentDrawMode); + mesh.setMaterial(GRID_MAT); + } + } else if (currentDrawMode == DrawMode.FILL) { + for (int i = 0; i < meshes.size(); i++) { + MeshView mesh = meshes.get(i); + mesh.setDrawMode(currentDrawMode); + mesh.setMaterial(materials.get(i)); + } + } + } + + public List getMeshes() { + return meshes; + } +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/ValidationView.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/ValidationView.java new file mode 100644 index 0000000000000000000000000000000000000000..2699d1c712ff1fb855e98c88b71d84c92f2d264f --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/ValidationView.java @@ -0,0 +1,77 @@ +package de.hft.stuttgart.citydoctor2.gui; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Optional; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import de.hft.stuttgart.citydoctor2.check.Checker; +import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel; +import javafx.application.Platform; +import javafx.scene.Node; +import javafx.scene.image.Image; +import javafx.scene.layout.HBox; + +public class ValidationView extends View { + + private static final Logger logger = LogManager.getLogger(ValidationView.class); + + private Image viewLogo; + private MainWindow mainWindow; + private CityDoctorController controller; + + public ValidationView(MainWindow mainWindow, CityDoctorController controller) { + this.mainWindow = mainWindow; + this.controller = controller; + try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/error_stat32x32.png")) { + viewLogo = new Image(inStream); + } catch (IOException e) { + logger.catching(e); + } + } + + @Override + public Node getMainScreen() { + return mainWindow.getMainContainer(); + } + + @Override + public Optional getToolbar() { + return Optional.of(mainWindow.getMainToolbar().getToolBar()); + } + + @Override + public void onHide() { + Platform.runLater(() -> { + mainWindow.unselectEverything(); + mainWindow.getMeshGroup().getChildren().clear(); + mainWindow.clearHighlights(); + mainWindow.getErrorTree().getRoot().getChildren().clear(); + mainWindow.getPolygonsView().getRoot().getChildren().clear(); + mainWindow.getVertexView().getRoot().getChildren().clear(); + mainWindow.getEdgeView().getRoot().getChildren().clear(); + }); + } + + @Override + public void onShow(CityDoctorModel model, Checker checker) { + if (model == null) { + return; + } + controller.buildTrees(); + controller.updateFeatureTrees(); + } + + @Override + public Image getViewLogo() { + return viewLogo; + } + + @Override + public void initializeView(MainWindow mainWindow) { + // already initialized + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/VertexClickDispatcher.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/VertexClickDispatcher.java new file mode 100644 index 0000000000000000000000000000000000000000..010e631215ddbe408f7c1ae5d91fc04bdf68b006 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/VertexClickDispatcher.java @@ -0,0 +1,19 @@ +package de.hft.stuttgart.citydoctor2.gui; + +import de.hft.stuttgart.citydoctor2.datastructure.Vertex; +import javafx.scene.input.MouseEvent; + +public class VertexClickDispatcher implements ClickDispatcher { + + private Vertex v; + + public VertexClickDispatcher(Vertex v) { + this.v = v; + } + + @Override + public void click(MouseEvent me, ClickHandler handler) { + handler.onVertexClick(v, me); + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/VertexClickHandler.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/VertexClickHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..19395273dc96ea3a564ad93a598637bc276a02ce --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/VertexClickHandler.java @@ -0,0 +1,71 @@ +package de.hft.stuttgart.citydoctor2.gui; + +import org.locationtech.proj4j.ProjCoordinate; + +import de.hft.stuttgart.citydoctor2.datastructure.Polygon; +import de.hft.stuttgart.citydoctor2.datastructure.Vertex; +import de.hft.stuttgart.citydoctor2.gui.tree.Renderable; +import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration; +import javafx.scene.control.ContextMenu; +import javafx.scene.control.CustomMenuItem; +import javafx.scene.control.Label; +import javafx.scene.control.MenuItem; +import javafx.scene.control.TreeView; +import javafx.scene.input.MouseButton; +import javafx.scene.input.MouseEvent; +import javafx.stage.Stage; + +public class VertexClickHandler implements ClickHandler { + + private TreeView errorView; + private Renderer renderer; + private Stage stage; + private ParserConfiguration config; + + public VertexClickHandler(TreeView errorView, Renderer renderer, Stage stage) { + this.errorView = errorView; + this.renderer = renderer; + this.stage = stage; + } + + public void setConfig(ParserConfiguration config) { + this.config = config; + } + + @Override + public void onPolygonClick(Polygon p, MouseEvent me) { + if (me.getButton() == MouseButton.PRIMARY) { + errorView.getSelectionModel().clearSelection(); + renderer.highlight(p); + } else if (me.getButton() == MouseButton.SECONDARY) { + MenuItem mi = new MenuItem(p.getGmlId().getGmlString()); + ContextMenu cMenu = new ContextMenu(mi); + cMenu.show(stage, me.getScreenX(), me.getScreenY()); + } + } + + @Override + public void onVertexClick(Vertex v, MouseEvent me) { + if (me.getButton() == MouseButton.SECONDARY) { + MenuItem mi1 = new CustomMenuItem(new Label("Vertex")); + double x = v.getX(); + double y = v.getY(); + if (config.getOriginalTransform() != null) { + ProjCoordinate p1 = new ProjCoordinate(); + ProjCoordinate p2 = new ProjCoordinate(); + p1.x = v.getX(); + p1.y = v.getY(); + config.getOriginalTransform().transform(p1, p2); + x = p2.x; + y = p2.y; + } + + MenuItem mi2 = new MenuItem("x = " + x); + MenuItem mi3 = new MenuItem("y = " + y); + MenuItem mi4 = new MenuItem("z = " + v.getZ()); + ContextMenu cMenu = new ContextMenu(mi1, mi2, mi3, mi4); + cMenu.show(stage, me.getScreenX(), me.getScreenY()); + } + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/View.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/View.java new file mode 100644 index 0000000000000000000000000000000000000000..71f6ce4369bf41f7fb44e10d3d6c06fe9b2738e6 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/View.java @@ -0,0 +1,32 @@ +package de.hft.stuttgart.citydoctor2.gui; + +import java.util.Optional; + +import de.hft.stuttgart.citydoctor2.check.Checker; +import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel; +import javafx.scene.Node; +import javafx.scene.image.Image; +import javafx.scene.layout.HBox; + +public abstract class View { + + private boolean firstTime = true; + + public abstract Optional getToolbar(); + public abstract Node getMainScreen(); + public abstract Image getViewLogo(); + + public abstract void initializeView(MainWindow mainWindow); + + public void fireOnShowEvent(CityDoctorModel model, Checker checker, MainWindow mainWindow) { + if (firstTime) { + firstTime = false; + initializeView(mainWindow); + } + onShow(model, checker); + } + + public abstract void onHide(); + public abstract void onShow(CityDoctorModel model, Checker checker); + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/ViewRegistration.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/ViewRegistration.java new file mode 100644 index 0000000000000000000000000000000000000000..9161d18006988119e3a04d027e7983b312f3cceb --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/ViewRegistration.java @@ -0,0 +1,31 @@ +package de.hft.stuttgart.citydoctor2.gui; + +import java.util.LinkedHashSet; +import java.util.Set; + +public class ViewRegistration { + + private static Set registeredViews = new LinkedHashSet<>(); + private static View currentActiveView; + + private ViewRegistration() { + // only static use + } + + public static void registerView(View v) { + registeredViews.add(v); + } + + public static Set getRegisteredViews() { + return registeredViews; + } + + static void setCurrentActiveView(View v) { + currentActiveView = v; + } + + public static View getCurrentActiveView() { + return currentActiveView; + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/WriteReportDialog.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/WriteReportDialog.java new file mode 100644 index 0000000000000000000000000000000000000000..0d34f1718af831d3d4041ccdcbd236cdc272f8d9 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/WriteReportDialog.java @@ -0,0 +1,262 @@ +package de.hft.stuttgart.citydoctor2.gui; + +import java.io.File; +import java.io.IOException; + +import javax.imageio.ImageIO; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import de.hft.stuttgart.citydoctor2.utils.Localization; +import javafx.application.Platform; +import javafx.embed.swing.SwingFXUtils; +import javafx.event.Event; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.Scene; +import javafx.scene.SnapshotParameters; +import javafx.scene.chart.BarChart; +import javafx.scene.chart.CategoryAxis; +import javafx.scene.chart.NumberAxis; +import javafx.scene.chart.XYChart; +import javafx.scene.control.Button; +import javafx.scene.control.CheckBox; +import javafx.scene.control.Label; +import javafx.scene.control.TextField; +import javafx.scene.image.Image; +import javafx.scene.image.WritableImage; +import javafx.scene.layout.VBox; +import javafx.stage.FileChooser; +import javafx.stage.FileChooser.ExtensionFilter; +import javafx.stage.Modality; +import javafx.stage.Stage; +import javafx.util.StringConverter; + +public class WriteReportDialog { + + private static Logger logger = LogManager.getLogger(WriteReportDialog.class); + + private Stage stage; + private CityDoctorController controller; + private MainWindow mainWindow; + + @FXML + private CheckBox pdfCheckBox; + + @FXML + private TextField pdfFileField; + + @FXML + private Button selectPdfBtn; + + @FXML + private CheckBox xmlCheckBox; + + @FXML + private TextField xmlFileField; + + @FXML + private Button selectXmlFile; + + @FXML + private Button cancelBtn; + + @FXML + private Button writeBtn; + + @FXML + private BarChart barChart; + + @FXML + private Button saveImageBtn; + + @FXML + private Label errorStatisticsLabel; + + public WriteReportDialog(Stage parent, CityDoctorController controller, MainWindow mainWindow) throws IOException { + FXMLLoader loader = new FXMLLoader(WriteReportDialog.class.getResource("WriteReportDialog.fxml")); + loader.setController(this); + VBox box = loader.load(); + this.controller = controller; + this.mainWindow = mainWindow; + stage = new Stage(); + stage.getIcons().add(new Image(MainWindow.class.getResourceAsStream("icons/CityDoctor-Logo-rot_klein.jpg"))); + stage.setScene(new Scene(box)); + stage.initOwner(parent); + stage.initModality(Modality.APPLICATION_MODAL); + stage.setTitle("Write Reports"); + stage.setOnHidden(we -> barChart.getData().clear()); + setMaximumWidthOfBarChartColumns(); + } + + private void setMaximumWidthOfBarChartColumns() { + double maxBarWidth = 40; + double minCategoryGap = 10; + + // setting maximum width of columns in bar chart + // from https://stackoverflow.com/questions/27302875/set-bar-chart-column-width-size + stage.getScene().widthProperty().addListener((obs, n, n1) -> { + if (barChart.getData().isEmpty()) + return; + + setCategoryWidthWhenWindowIsBigger(maxBarWidth, n, n1); + if (n != null && (n1.doubleValue() < n.doubleValue()) && barChart.getCategoryGap() > minCategoryGap) { + double barWidth; + CategoryAxis xAxis = (CategoryAxis) barChart.getXAxis(); + do { + double catSpace = xAxis.getCategorySpacing(); + double avilableBarSpace = catSpace - (minCategoryGap + barChart.getBarGap()); + barWidth = Math.min(maxBarWidth, + (avilableBarSpace / barChart.getData().size()) - barChart.getBarGap()); + avilableBarSpace = (barWidth + barChart.getBarGap()) * barChart.getData().size(); + barChart.setCategoryGap(catSpace - avilableBarSpace - barChart.getBarGap()); + } while (barWidth < maxBarWidth && barChart.getCategoryGap() > minCategoryGap); + } + }); + } + + private void setCategoryWidthWhenWindowIsBigger(double maxBarWidth, Number n, Number n1) { + if (n != null && (n1.doubleValue() > n.doubleValue())) { + double barWidth; + CategoryAxis xAxis = (CategoryAxis) barChart.getXAxis(); + do { + double catSpace = xAxis.getCategorySpacing(); + double avilableBarSpace = catSpace - (barChart.getCategoryGap() + barChart.getBarGap()); + barWidth = (avilableBarSpace / barChart.getData().size()) - barChart.getBarGap(); + if (barWidth > maxBarWidth) { + avilableBarSpace = (maxBarWidth + barChart.getBarGap()) * barChart.getData().size(); + barChart.setCategoryGap(catSpace - avilableBarSpace - barChart.getBarGap()); + } + } while (barWidth > maxBarWidth); + } + } + + public void initialize() { + writeBtn.setText(Localization.getText("WriteReportDialog.writeBtn")); + cancelBtn.setText(Localization.getText("WriteReportDialog.cancelBtn")); + errorStatisticsLabel.setText(Localization.getText("WriteReportDialog.errorStatisticsLabel")); + saveImageBtn.setText(Localization.getText("WriteReportDialog.saveImageBtn")); + selectPdfBtn.setText(Localization.getText("WriteReportDialog.selectPdfBtn")); + selectXmlFile.setText(Localization.getText("WriteReportDialog.selectXmlFile")); + barChart.getXAxis().setLabel(Localization.getText("WriteReportDialog.xAxisLabel")); + barChart.getYAxis().setLabel(Localization.getText("WriteReportDialog.yAxisLabel")); + + // formatter to display only whole numbers + NumberAxis yAxis = (NumberAxis) barChart.getYAxis(); + yAxis.setTickLabelFormatter(new StringConverter<>() { + + @Override + public String toString(Number object) { + if (object.doubleValue() % 1 < 0.00000001) { + return String.valueOf(object.intValue()); + } else { + return ""; + } + } + + @Override + public Number fromString(String string) { + return Integer.parseInt(string); + } + }); + saveImageBtn.setOnAction(ae -> { + FileChooser chooser = new FileChooser(); + chooser.setInitialDirectory(new File(".")); + chooser.getExtensionFilters().add(new ExtensionFilter("PNG-Image", "*.png")); + String fName = controller.getFileName(); + fName = fName.substring(0, fName.lastIndexOf('.')); + chooser.setInitialFileName(fName + "_errors.png"); + File imageFile = chooser.showSaveDialog(stage); + if (imageFile != null) { + WritableImage snapshot = barChart.snapshot(new SnapshotParameters(), null); + try { + ImageIO.write(SwingFXUtils.fromFXImage(snapshot, null), "png", imageFile); + } catch (IOException e) { + logger.error("Failed to save image", e); + mainWindow.showExceptionDialog(e); + } + } + }); + + pdfCheckBox.selectedProperty().addListener((obs, oldV, newV) -> { + selectPdfBtn.setDisable(!newV); + pdfFileField.setDisable(!newV); + }); + + xmlCheckBox.selectedProperty().addListener((obs, oldV, newV) -> { + selectXmlFile.setDisable(!newV); + xmlFileField.setDisable(!newV); + }); + + selectPdfBtn.setOnAction(ae -> { + FileChooser chooser = new FileChooser(); + chooser.setTitle("Select PDF File"); + chooser.getExtensionFilters().add(new ExtensionFilter("PDF-Files", ".pdf")); + File pdfFile = chooser.showSaveDialog(stage); + if (pdfFile != null) { + pdfFileField.setText(pdfFile.getAbsolutePath()); + } + }); + + selectXmlFile.setOnAction(ae -> { + FileChooser chooser = new FileChooser(); + chooser.setTitle("Select XML File"); + chooser.getExtensionFilters().add(new ExtensionFilter("XML-Files", ".xml")); + File xmlFile = chooser.showSaveDialog(stage); + if (xmlFile != null) { + xmlFileField.setText(xmlFile.getAbsolutePath()); + } + }); + + initWriteButton(); + + cancelBtn.setOnAction(ae -> stage.close()); + } + + private void initWriteButton() { + writeBtn.setOnAction(ae -> { + stage.setOnCloseRequest(Event::consume); + cancelBtn.setDisable(true); + writeBtn.setDisable(true); + Thread t = new Thread(() -> { + try { + if (pdfCheckBox.isSelected()) { + String file = pdfFileField.getText(); + File pdfFile = new File(file); + File parentFile = pdfFile.getParentFile(); + if (parentFile != null) { + parentFile.mkdirs(); + } + controller.writePdfReport(pdfFile); + } + if (xmlCheckBox.isSelected()) { + String file = xmlFileField.getText(); + File xmlFile = new File(file); + File parentFile = xmlFile.getParentFile(); + if (parentFile != null) { + parentFile.mkdirs(); + } + controller.writeXmlReport(xmlFile); + } + } finally { + Platform.runLater(() -> { + stage.setOnCloseRequest(null); + cancelBtn.setDisable(false); + writeBtn.setDisable(false); + stage.close(); + }); + } + }); + t.start(); + }); + } + + public void show() { + XYChart.Series series = controller.createErrorSeries(); + barChart.getData().clear(); + barChart.getData().add(series); + stage.show(); + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/filter/TypeFilterSelection.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/filter/TypeFilterSelection.java new file mode 100644 index 0000000000000000000000000000000000000000..c791145418e6ea29172019ad22e845dd0e00a811 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/filter/TypeFilterSelection.java @@ -0,0 +1,24 @@ +package de.hft.stuttgart.citydoctor2.gui.filter; + +import de.hft.stuttgart.citydoctor2.datastructure.FeatureType; + +public class TypeFilterSelection { + + private final FeatureType type; + private final String name; + + public TypeFilterSelection(FeatureType type, String name) { + this.type = type; + this.name = name; + } + + public FeatureType getType() { + return type; + } + + @Override + public String toString() { + return name; + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/filter/ViewFilter.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/filter/ViewFilter.java new file mode 100644 index 0000000000000000000000000000000000000000..7211f547f27c35ed4fe66e3eec1f69746868333d --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/filter/ViewFilter.java @@ -0,0 +1,35 @@ +package de.hft.stuttgart.citydoctor2.gui.filter; + +import de.hft.stuttgart.citydoctor2.datastructure.CityObject; +import de.hft.stuttgart.citydoctor2.datastructure.Geometry; + +public abstract class ViewFilter { + + private boolean enabled = true; + + protected abstract boolean useGeometry(CityObject co, Geometry geom); + + public boolean allowedToUse(CityObject co, Geometry geom) { + if (!enabled) { + return false; + } + return useGeometry(co, geom); + } + + public boolean isEnabled() { + return enabled; + } + + public void enable() { + enabled = true; + } + + public void disable() { + enabled = false; + } + + public void setEnable(boolean enabled) { + this.enabled = enabled; + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/logger/GuiLogger.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/logger/GuiLogger.java new file mode 100644 index 0000000000000000000000000000000000000000..7ce8fa4027bd243a6442ea8c4e5f5ebf1c359d23 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/logger/GuiLogger.java @@ -0,0 +1,104 @@ +package de.hft.stuttgart.citydoctor2.gui.logger; + +import java.io.Serializable; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +import org.apache.logging.log4j.core.Filter; +import org.apache.logging.log4j.core.Layout; +import org.apache.logging.log4j.core.LogEvent; +import org.apache.logging.log4j.core.appender.AbstractAppender; +import org.apache.logging.log4j.core.config.Property; +import org.apache.logging.log4j.core.config.plugins.Plugin; +import org.apache.logging.log4j.core.config.plugins.PluginAttribute; +import org.apache.logging.log4j.core.config.plugins.PluginElement; +import org.apache.logging.log4j.core.config.plugins.PluginFactory; +import org.apache.logging.log4j.core.layout.PatternLayout; + +import javafx.application.Platform; +import javafx.scene.control.TextArea; + +@Plugin(name="GuiLogger", category="Core", elementType="appender", printObject=true) +public class GuiLogger extends AbstractAppender { + + private static TextArea area; + + private final ReadWriteLock rwLock = new ReentrantReadWriteLock(); + private final Lock readLock = rwLock.readLock(); + + private static final int CAPACITY = 20000; + + private final StringBuilder buffer = new StringBuilder(CAPACITY); + private Thread daemonLoggerThread; + private boolean dirty = false; + + public static void setTextArea(TextArea area) { + GuiLogger.area = area; + } + + @PluginFactory + public static GuiLogger createAppender( + @PluginAttribute("name") String name, + @PluginAttribute("ignoreExceptions") boolean ignoreExceptions, + @PluginElement("Layout") Layout layout, + @PluginElement("Filter") final Filter filter) { + if (name == null) { + LOGGER.error("No name provided for GuiLogger"); + return null; + } + if (layout == null) { + layout = PatternLayout.createDefaultLayout(); + } + GuiLogger guiLogger = new GuiLogger(name, filter, layout, ignoreExceptions, new Property[0]); + guiLogger.daemonLoggerThread = new Thread(() -> { + while (!Thread.interrupted()) { + if (guiLogger.dirty) { + Platform.runLater(() -> { + // set text doesn't scroll + // workaround with clear -> append + area.clear(); + area.appendText(guiLogger.buffer.toString()); + }); + guiLogger.dirty = false; + } + try { + Thread.sleep(200); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + }); + guiLogger.daemonLoggerThread.setDaemon(true); + guiLogger.daemonLoggerThread.start(); + return guiLogger; + } + + protected GuiLogger(String name, Filter filter, Layout layout, boolean ignoreExceptions, + Property[] properties) { + super(name, filter, layout, ignoreExceptions, properties); + } + + @Override + public void append(LogEvent event) { + if (area == null) { + return; + } + readLock.lock(); + try { + String s = new String(getLayout().toByteArray(event)); + int capacityLeft = CAPACITY - buffer.length(); + if (capacityLeft < s.length()) { + int delete = s.length() - capacityLeft; + buffer.delete(0, delete - 1); + } + buffer.append(s); + dirty = true; + } finally { + readLock.unlock(); + } + } + + + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/table/ErrorStat.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/table/ErrorStat.java new file mode 100644 index 0000000000000000000000000000000000000000..0d38ee2517c8eb7163b48cd65c5d0213a553a4e1 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/table/ErrorStat.java @@ -0,0 +1,59 @@ +package de.hft.stuttgart.citydoctor2.gui.table; + +import de.hft.stuttgart.citydoctor2.check.ErrorId; +import javafx.beans.property.IntegerProperty; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleIntegerProperty; +import javafx.beans.property.SimpleObjectProperty; + +public class ErrorStat { + + private final SimpleObjectProperty errorId = new SimpleObjectProperty<>(); + private final SimpleIntegerProperty count = new SimpleIntegerProperty(); + + public ErrorStat(ErrorId errorId) { + this(errorId, 0); + } + + public ErrorStat(ErrorId errorId, int count) { + this.errorId.set(errorId); + this.count.set(count); + } + + public int getCount() { + return count.get(); + } + + public IntegerProperty getCountProperty() { + return count; + } + + public ObjectProperty getErrorIdProperty() { + return errorId; + } + + public void setCount(int count) { + this.count.set(count); + } + + public void incrementCount() { + count.set(count.get() + 1); + } + + public ErrorId getErrorId() { + return errorId.get(); + } + + public void setErrorId(ErrorId errorId) { + this.errorId.set(errorId); + } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return "ErrorStat [errorId=" + errorId + ", count=" + count + "]"; + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AllBoundarySurfacesNode.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AllBoundarySurfacesNode.java new file mode 100644 index 0000000000000000000000000000000000000000..422d84a2e34933cb76e32687e1717f920818a06c --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AllBoundarySurfacesNode.java @@ -0,0 +1,46 @@ +package de.hft.stuttgart.citydoctor2.gui.tree; + +import java.util.List; + +import de.hft.stuttgart.citydoctor2.datastructure.BoundarySurface; +import de.hft.stuttgart.citydoctor2.gui.CheckStatus; +import de.hft.stuttgart.citydoctor2.gui.Renderer; + +public class AllBoundarySurfacesNode extends Renderable { + + private final List boundarySurfaces; + + public AllBoundarySurfacesNode(List boundarySurfaces) { + this.boundarySurfaces = boundarySurfaces; + } + + @Override + public String getText() { + return "Boundary Surfaces"; + } + + @Override + public void visit(Renderer renderer) { + renderer.clearCurrentRender(); + } + + @Override + public void refreshTextColor() { + boolean isValidated = false; + for (BoundarySurface bs : boundarySurfaces) { + if (bs.isValidated()) { + isValidated = true; + } + if (bs.containsAnyError()) { + setStatus(CheckStatus.ERROR); + return; + } + } + if (isValidated) { + setStatus(CheckStatus.OK); + } else { + setStatus(CheckStatus.NOT_CHECKED); + } + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AllBridgeConstructiveElementsNode.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AllBridgeConstructiveElementsNode.java new file mode 100644 index 0000000000000000000000000000000000000000..0f0bbd3378d9fbe1091ae2131f3b26e53363950a --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AllBridgeConstructiveElementsNode.java @@ -0,0 +1,64 @@ +/*- + * Copyright 2022 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart + * + * This file is part of CityDoctor2. + * + * CityDoctor2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CityDoctor2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with CityDoctor2. If not, see . + */ +package de.hft.stuttgart.citydoctor2.gui.tree; + +import java.util.List; + +import de.hft.stuttgart.citydoctor2.datastructure.BridgeConstructiveElement; +import de.hft.stuttgart.citydoctor2.gui.CheckStatus; +import de.hft.stuttgart.citydoctor2.gui.Renderer; + +public class AllBridgeConstructiveElementsNode extends Renderable { + + private final List constructiveElements; + + public AllBridgeConstructiveElementsNode(List constructiveElements) { + this.constructiveElements = constructiveElements; + } + + @Override + public String getText() { + return "Constructive Elements"; + } + + @Override + public void visit(Renderer renderer) { + renderer.clearCurrentRender(); + } + + @Override + public void refreshTextColor() { + boolean isValidated = false; + for (BridgeConstructiveElement bce : constructiveElements) { + if (bce.isValidated()) { + isValidated = true; + } + if (bce.containsAnyError()) { + setStatus(CheckStatus.ERROR); + return; + } + } + if (isValidated) { + setStatus(CheckStatus.OK); + } else { + setStatus(CheckStatus.NOT_CHECKED); + } + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AllBridgePartsNode.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AllBridgePartsNode.java new file mode 100644 index 0000000000000000000000000000000000000000..199651d566b40baad68f144310eb7c268f182e27 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AllBridgePartsNode.java @@ -0,0 +1,64 @@ +/*- + * Copyright 2022 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart + * + * This file is part of CityDoctor2. + * + * CityDoctor2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CityDoctor2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with CityDoctor2. If not, see . + */ +package de.hft.stuttgart.citydoctor2.gui.tree; + +import java.util.List; + +import de.hft.stuttgart.citydoctor2.datastructure.BridgeObject; +import de.hft.stuttgart.citydoctor2.gui.CheckStatus; +import de.hft.stuttgart.citydoctor2.gui.Renderer; + +public class AllBridgePartsNode extends Renderable { + + private final List bridgeParts; + + public AllBridgePartsNode(List bridgeParts) { + this.bridgeParts = bridgeParts; + } + + @Override + public String getText() { + return "Bridge Parts"; + } + + @Override + public void visit(Renderer renderer) { + renderer.clearCurrentRender(); + } + + @Override + public void refreshTextColor() { + boolean wasChecked = false; + for (BridgeObject bp : bridgeParts) { + if (bp.isValidated()) { + wasChecked = true; + if (bp.containsAnyError()) { + setStatus(CheckStatus.ERROR); + return; + } + } + } + if (wasChecked) { + setStatus(CheckStatus.OK); + } else { + setStatus(CheckStatus.NOT_CHECKED); + } + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AllBridgesNode.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AllBridgesNode.java new file mode 100644 index 0000000000000000000000000000000000000000..7ee41d69f7f23abacd662f72ab07616fa0b0d5dd --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AllBridgesNode.java @@ -0,0 +1,30 @@ +package de.hft.stuttgart.citydoctor2.gui.tree; + +import java.util.List; + +import de.hft.stuttgart.citydoctor2.datastructure.BridgeObject; +import de.hft.stuttgart.citydoctor2.gui.Renderer; + +public class AllBridgesNode extends Renderable { + + private final List bridges; + + public AllBridgesNode(List bridges) { + this.bridges = bridges; + } + + @Override + public void refreshTextColor() { + // no color changes + } + + @Override + public String getText() { + return "Bridges"; + } + + @Override + public void visit(Renderer renderer) { + renderer.renderBridges(bridges); + } +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AllBuildingPartsNode.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AllBuildingPartsNode.java new file mode 100644 index 0000000000000000000000000000000000000000..55699c1ef69d1c5d7bd6940734701db955d50386 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AllBuildingPartsNode.java @@ -0,0 +1,46 @@ +package de.hft.stuttgart.citydoctor2.gui.tree; + +import java.util.List; + +import de.hft.stuttgart.citydoctor2.datastructure.BuildingPart; +import de.hft.stuttgart.citydoctor2.gui.CheckStatus; +import de.hft.stuttgart.citydoctor2.gui.Renderer; + +public class AllBuildingPartsNode extends Renderable { + + private final List buildingParts; + + public AllBuildingPartsNode(List buildingParts) { + this.buildingParts = buildingParts; + } + + @Override + public String getText() { + return "Building Parts"; + } + + @Override + public void visit(Renderer renderer) { + renderer.clearCurrentRender(); + } + + @Override + public void refreshTextColor() { + boolean wasChecked = false; + for (BuildingPart bp : buildingParts) { + if (bp.isValidated()) { + wasChecked = true; + if (bp.containsAnyError()) { + setStatus(CheckStatus.ERROR); + return; + } + } + } + if (wasChecked) { + setStatus(CheckStatus.OK); + } else { + setStatus(CheckStatus.NOT_CHECKED); + } + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AllBuildingsNode.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AllBuildingsNode.java new file mode 100644 index 0000000000000000000000000000000000000000..7f1c620b28b29aa03ac47a25eddbc596d27c506b --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AllBuildingsNode.java @@ -0,0 +1,31 @@ +package de.hft.stuttgart.citydoctor2.gui.tree; + +import java.util.List; + +import de.hft.stuttgart.citydoctor2.datastructure.Building; +import de.hft.stuttgart.citydoctor2.gui.Renderer; + +public class AllBuildingsNode extends Renderable { + + private final List buildings; + + public AllBuildingsNode(List buildings) { + this.buildings = buildings; + } + + @Override + public void refreshTextColor() { + // no color changes + } + + @Override + public String getText() { + return "Buildings"; + } + + @Override + public void visit(Renderer renderer) { + renderer.renderBuildings(buildings); + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AllInstallationsNode.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AllInstallationsNode.java new file mode 100644 index 0000000000000000000000000000000000000000..192a58d9c655fefb5e7c5b44c8a912766e9553e6 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AllInstallationsNode.java @@ -0,0 +1,46 @@ +package de.hft.stuttgart.citydoctor2.gui.tree; + +import java.util.List; + +import de.hft.stuttgart.citydoctor2.datastructure.Installation; +import de.hft.stuttgart.citydoctor2.gui.CheckStatus; +import de.hft.stuttgart.citydoctor2.gui.Renderer; + +public class AllInstallationsNode extends Renderable { + + private final List buildingInstallations; + + public AllInstallationsNode(List bis) { + this.buildingInstallations = bis; + } + + @Override + public String getText() { + return "Building Installations"; + } + + @Override + public void visit(Renderer renderer) { + renderer.clearCurrentRender(); + } + + @Override + public void refreshTextColor() { + boolean wasChecked = false; + for (Installation bp : buildingInstallations) { + if (bp.isValidated()) { + wasChecked = true; + if (bp.containsAnyError()) { + setStatus(CheckStatus.ERROR); + return; + } + } + } + if (wasChecked) { + setStatus(CheckStatus.OK); + } else { + setStatus(CheckStatus.NOT_CHECKED); + } + } + +} \ No newline at end of file diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AllOpeningsNode.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AllOpeningsNode.java new file mode 100644 index 0000000000000000000000000000000000000000..6a1979df32e11e1fb51c01b47d412707c5045e3a --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AllOpeningsNode.java @@ -0,0 +1,38 @@ +package de.hft.stuttgart.citydoctor2.gui.tree; + +import java.util.List; + +import de.hft.stuttgart.citydoctor2.datastructure.Opening; +import de.hft.stuttgart.citydoctor2.gui.CheckStatus; +import de.hft.stuttgart.citydoctor2.gui.Renderer; + +public class AllOpeningsNode extends Renderable { + + private final List openings; + + public AllOpeningsNode(List openings) { + this.openings = openings; + } + + @Override + public void refreshTextColor() { + for (Opening bp : openings) { + if (bp.containsAnyError()) { + setStatus(CheckStatus.ERROR); + return; + } + } + setStatus(CheckStatus.OK); + } + + @Override + public String getText() { + return "Openings"; + } + + @Override + public void visit(Renderer renderer) { + renderer.clearCurrentRender(); + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AllTerrainNode.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AllTerrainNode.java new file mode 100644 index 0000000000000000000000000000000000000000..61a8eb3f24ab26bae5d7ed4038b3d1784c9e053d --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AllTerrainNode.java @@ -0,0 +1,31 @@ +package de.hft.stuttgart.citydoctor2.gui.tree; + +import java.util.List; + +import de.hft.stuttgart.citydoctor2.datastructure.CityObject; +import de.hft.stuttgart.citydoctor2.gui.Renderer; + +public class AllTerrainNode extends Renderable { + + private final List land; + + public AllTerrainNode(List land) { + this.land = land; + } + + @Override + public void refreshTextColor() { + // no use + } + + @Override + public String getText() { + return "Terrain"; + } + + @Override + public void visit(Renderer renderer) { + renderer.renderTerrain(land); + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AllTinNode.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AllTinNode.java new file mode 100644 index 0000000000000000000000000000000000000000..59bfa3af1220a94dc73c216d31217dccb8d4b0ca --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AllTinNode.java @@ -0,0 +1,49 @@ +/*- + * Copyright 2022 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart + * + * This file is part of CityDoctor2. + * + * CityDoctor2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CityDoctor2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with CityDoctor2. If not, see . + */ +package de.hft.stuttgart.citydoctor2.gui.tree; + +import java.util.List; + +import de.hft.stuttgart.citydoctor2.datastructure.TinObject; +import de.hft.stuttgart.citydoctor2.gui.Renderer; + +public class AllTinNode extends Renderable { + + public AllTinNode(List components) { + // TODO Auto-generated constructor stub + } + + @Override + public void refreshTextColor() { + // TODO Auto-generated method stub + + } + + @Override + public String getText() { + return "Components"; + } + + @Override + public void visit(Renderer renderer) { + // TODO Auto-generated method stub + + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AllTransportationNode.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AllTransportationNode.java new file mode 100644 index 0000000000000000000000000000000000000000..d72e7dcb2cb30c74c6d9615f4ce5e1784e8807a7 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AllTransportationNode.java @@ -0,0 +1,31 @@ +package de.hft.stuttgart.citydoctor2.gui.tree; + +import java.util.List; + +import de.hft.stuttgart.citydoctor2.datastructure.TransportationObject; +import de.hft.stuttgart.citydoctor2.gui.Renderer; + +public class AllTransportationNode extends Renderable { + + private final List transportation; + + public AllTransportationNode(List transportation) { + this.transportation = transportation; + } + + @Override + public void refreshTextColor() { + // no use + } + + @Override + public String getText() { + return "Transportation"; + } + + @Override + public void visit(Renderer renderer) { + renderer.renderTransportation(transportation); + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AllVegetationNode.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AllVegetationNode.java new file mode 100644 index 0000000000000000000000000000000000000000..7911341c79ee9fa053f350b7d17be6444e12b89d --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AllVegetationNode.java @@ -0,0 +1,31 @@ +package de.hft.stuttgart.citydoctor2.gui.tree; + +import java.util.List; + +import de.hft.stuttgart.citydoctor2.datastructure.Vegetation; +import de.hft.stuttgart.citydoctor2.gui.Renderer; + +public class AllVegetationNode extends Renderable { + + private final List vegetation; + + public AllVegetationNode(List vegetation) { + this.vegetation = vegetation; + } + + @Override + public void refreshTextColor() { + // no use + } + + @Override + public String getText() { + return "Vegetation"; + } + + @Override + public void visit(Renderer renderer) { + renderer.renderVegetation(vegetation); + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AllWaterNode.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AllWaterNode.java new file mode 100644 index 0000000000000000000000000000000000000000..3143d5895d660123588b285ed5d3ec3ea0cd0d39 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AllWaterNode.java @@ -0,0 +1,31 @@ +package de.hft.stuttgart.citydoctor2.gui.tree; + +import java.util.List; + +import de.hft.stuttgart.citydoctor2.datastructure.WaterObject; +import de.hft.stuttgart.citydoctor2.gui.Renderer; + +public class AllWaterNode extends Renderable { + + private final List water; + + public AllWaterNode(List water) { + this.water = water; + } + + @Override + public void refreshTextColor() { + // no use + } + + @Override + public String getText() { + return "Water"; + } + + @Override + public void visit(Renderer renderer) { + renderer.renderWater(water); + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/BoundarySurfaceNode.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/BoundarySurfaceNode.java new file mode 100644 index 0000000000000000000000000000000000000000..581bc2e94f566dfb09a2f5d127fe22babe40703c --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/BoundarySurfaceNode.java @@ -0,0 +1,35 @@ +package de.hft.stuttgart.citydoctor2.gui.tree; + +import de.hft.stuttgart.citydoctor2.datastructure.BoundarySurface; +import de.hft.stuttgart.citydoctor2.gui.CheckStatus; +import de.hft.stuttgart.citydoctor2.gui.Renderer; + +public class BoundarySurfaceNode extends Renderable { + + private final BoundarySurface bs; + + public BoundarySurfaceNode(BoundarySurface bs) { + this.bs = bs; + } + + @Override + public String getText() { + return bs.getGmlId().getGmlString() + " [" + bs.getType() + "]"; + } + + @Override + public void visit(Renderer renderer) { + renderer.render(bs); + } + + @Override + public void refreshTextColor() { + if (!bs.isValidated()) { + setStatus(CheckStatus.NOT_CHECKED); + } else if (bs.containsAnyError()) { + setStatus(CheckStatus.ERROR); + } else { + setStatus(CheckStatus.OK); + } + } +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/BridgeConstructiveElementNode.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/BridgeConstructiveElementNode.java new file mode 100644 index 0000000000000000000000000000000000000000..d3f839dedd068f07b3a5e02ec3e104beb087b810 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/BridgeConstructiveElementNode.java @@ -0,0 +1,54 @@ +/*- + * Copyright 2023 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart + * + * This file is part of CityDoctor2. + * + * CityDoctor2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CityDoctor2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with CityDoctor2. If not, see . + */ +package de.hft.stuttgart.citydoctor2.gui.tree; + +import de.hft.stuttgart.citydoctor2.datastructure.BridgeConstructiveElement; +import de.hft.stuttgart.citydoctor2.gui.CheckStatus; +import de.hft.stuttgart.citydoctor2.gui.Renderer; + +public class BridgeConstructiveElementNode extends Renderable { + + private final BridgeConstructiveElement bce; + + public BridgeConstructiveElementNode(BridgeConstructiveElement bce) { + this.bce = bce; + } + + @Override + public String getText() { + return bce.getGmlId().getGmlString(); + } + + @Override + public void visit(Renderer renderer) { + renderer.render(bce); + } + + @Override + public void refreshTextColor() { + if (!bce.isValidated()) { + setStatus(CheckStatus.NOT_CHECKED); + } else if (bce.containsAnyError()) { + setStatus(CheckStatus.ERROR); + } else { + setStatus(CheckStatus.OK); + } + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/BridgeNode.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/BridgeNode.java new file mode 100644 index 0000000000000000000000000000000000000000..7f37c11584c6e26db2d0b1f05f96117256029a41 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/BridgeNode.java @@ -0,0 +1,55 @@ +/*- + * Copyright 2022 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart + * + * This file is part of CityDoctor2. + * + * CityDoctor2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CityDoctor2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with CityDoctor2. If not, see . + */ +package de.hft.stuttgart.citydoctor2.gui.tree; + +import de.hft.stuttgart.citydoctor2.datastructure.BridgeObject; +import de.hft.stuttgart.citydoctor2.gui.CheckStatus; +import de.hft.stuttgart.citydoctor2.gui.Renderer; + +public class BridgeNode extends Renderable { + + private final BridgeObject bridge; + + public BridgeNode(BridgeObject bridge) { + this.bridge = bridge; + } + + @Override + public String getText() { + return bridge.getGmlId().getGmlString(); + } + + @Override + public void visit(Renderer renderer) { + renderer.render(bridge); + } + + @Override + public void refreshTextColor() { + if (!bridge.isValidated()) { + setStatus(CheckStatus.NOT_CHECKED); + } else if (bridge.containsAnyError()) { + setStatus(CheckStatus.ERROR); + } else { + setStatus(CheckStatus.OK); + } + } + + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/BuildingNode.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/BuildingNode.java new file mode 100644 index 0000000000000000000000000000000000000000..f01e81f05f97f51ac6a2e464684e43b3cf9d2618 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/BuildingNode.java @@ -0,0 +1,40 @@ +package de.hft.stuttgart.citydoctor2.gui.tree; + +import de.hft.stuttgart.citydoctor2.datastructure.Building; +import de.hft.stuttgart.citydoctor2.gui.CheckStatus; +import de.hft.stuttgart.citydoctor2.gui.Renderer; + +public class BuildingNode extends Renderable { + + private final Building building; + + public BuildingNode(Building building) { + this.building = building; + } + + @Override + public String getText() { + return building.getGmlId().getGmlString(); + } + + public Building getBuilding() { + return building; + } + + @Override + public void visit(Renderer renderer) { + renderer.render(building); + } + + @Override + public void refreshTextColor() { + if (!building.isValidated()) { + setStatus(CheckStatus.NOT_CHECKED); + } else if (building.containsAnyError()) { + setStatus(CheckStatus.ERROR); + } else { + setStatus(CheckStatus.OK); + } + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/BuildingPartNode.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/BuildingPartNode.java new file mode 100644 index 0000000000000000000000000000000000000000..4c9b5e263d8464f94c23ae7ac705e06d5bedddea --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/BuildingPartNode.java @@ -0,0 +1,36 @@ +package de.hft.stuttgart.citydoctor2.gui.tree; + +import de.hft.stuttgart.citydoctor2.datastructure.BuildingPart; +import de.hft.stuttgart.citydoctor2.gui.CheckStatus; +import de.hft.stuttgart.citydoctor2.gui.Renderer; + +public class BuildingPartNode extends Renderable { + + private final BuildingPart bp; + + public BuildingPartNode(BuildingPart bp) { + this.bp = bp; + } + + @Override + public String getText() { + return bp.getGmlId().getGmlString(); + } + + @Override + public void visit(Renderer renderer) { + renderer.render(bp); + } + + @Override + public void refreshTextColor() { + if (!bp.isValidated()) { + setStatus(CheckStatus.NOT_CHECKED); + } else if (bp.containsAnyError()) { + setStatus(CheckStatus.ERROR); + } else { + setStatus(CheckStatus.OK); + } + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/ButtonRenderable.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/ButtonRenderable.java new file mode 100644 index 0000000000000000000000000000000000000000..0ed23ea0a8f918912a1a6be4e89189425dc5fd6c --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/ButtonRenderable.java @@ -0,0 +1,50 @@ +/*- + * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart + * + * This file is part of CityDoctor2. + * + * CityDoctor2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CityDoctor2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with CityDoctor2. If not, see . + */ +package de.hft.stuttgart.citydoctor2.gui.tree; + +import de.hft.stuttgart.citydoctor2.gui.Renderer; + +public class ButtonRenderable extends Renderable { + + private final Runnable run; + + public ButtonRenderable(Runnable run) { + this.run = run; + } + + public void run() { + run.run(); + } + + @Override + public void refreshTextColor() { + // nothing to do + } + + @Override + public String getText() { + return null; + } + + @Override + public void visit(Renderer renderer) { + // nothing to render + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/CityObjectNode.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/CityObjectNode.java new file mode 100644 index 0000000000000000000000000000000000000000..7d662a6da7cb1373e7f35fae6082a8ad83e45f78 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/CityObjectNode.java @@ -0,0 +1,36 @@ +package de.hft.stuttgart.citydoctor2.gui.tree; + +import de.hft.stuttgart.citydoctor2.datastructure.CityObject; +import de.hft.stuttgart.citydoctor2.gui.CheckStatus; +import de.hft.stuttgart.citydoctor2.gui.Renderer; + +public class CityObjectNode extends Renderable { + + private final CityObject co; + + public CityObjectNode(CityObject co) { + this.co = co; + } + + @Override + public void refreshTextColor() { + if (!co.isValidated()) { + setStatus(CheckStatus.NOT_CHECKED); + } else if (co.containsAnyError()) { + setStatus(CheckStatus.ERROR); + } else { + setStatus(CheckStatus.OK); + } + } + + @Override + public String getText() { + return co.getGmlId().getGmlString(); + } + + @Override + public void visit(Renderer renderer) { + renderer.render(co); + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/Displayable.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/Displayable.java new file mode 100644 index 0000000000000000000000000000000000000000..b626dd0f98cfa6f976882ce4b01419f19bb69341 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/Displayable.java @@ -0,0 +1,9 @@ +package de.hft.stuttgart.citydoctor2.gui.tree; + +import de.hft.stuttgart.citydoctor2.gui.CityDoctorController; + +public interface Displayable { + + public void visitForDisplaying(CityDoctorController controller); + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/EdgeNode.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/EdgeNode.java new file mode 100644 index 0000000000000000000000000000000000000000..af9a2858015afa00ee49c993fa4a499a40dc89e5 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/EdgeNode.java @@ -0,0 +1,62 @@ +package de.hft.stuttgart.citydoctor2.gui.tree; + +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; + +import de.hft.stuttgart.citydoctor2.datastructure.Edge; +import de.hft.stuttgart.citydoctor2.datastructure.Vertex; +import de.hft.stuttgart.citydoctor2.gui.Renderer; + +public class EdgeNode extends Renderable { + + private static final DecimalFormat nf; + + static { + DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(); + dfs.setDecimalSeparator('.'); + nf = new DecimalFormat("#.####", dfs); + } + + private static final String SEPERATOR = ", "; + private final Edge e; + private String text; + + public EdgeNode(Edge e) { + this.e = e; + } + + @Override + public void refreshTextColor() { + // not used + } + + @Override + public String getText() { + if (text == null) { + StringBuilder sb = new StringBuilder(); + sb.append("Edge from ["); + Vertex from = e.getFrom(); + sb.append(nf.format(from.getX())); + sb.append(SEPERATOR); + sb.append(nf.format(from.getY())); + sb.append(SEPERATOR); + sb.append(nf.format(from.getZ())); + sb.append("] to ["); + Vertex to = e.getTo(); + sb.append(nf.format(to.getX())); + sb.append(SEPERATOR); + sb.append(nf.format(to.getY())); + sb.append(SEPERATOR); + sb.append(nf.format(to.getZ())); + sb.append("]"); + text = sb.toString(); + } + return text; + } + + @Override + public void visit(Renderer renderer) { + renderer.highlight(e); + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/ErrorCell.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/ErrorCell.java new file mode 100644 index 0000000000000000000000000000000000000000..c75dd1a6ed3e7ca6c80776ce1d256f89bda033df --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/ErrorCell.java @@ -0,0 +1,20 @@ +package de.hft.stuttgart.citydoctor2.gui.tree; + +import de.hft.stuttgart.citydoctor2.check.CheckError; +import javafx.scene.control.cell.TextFieldTreeCell; + +public class ErrorCell extends TextFieldTreeCell { + + @Override + public void updateItem(CheckError item, boolean empty) { + super.updateItem(item, empty); + + if (empty || item == null) { + setText(null); + setGraphic(null); + } else { + setText(item.getErrorId().toString()); + } + } + +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..52fb5a4b8b7051712e9952ff103884ee1f859520 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/ErrorItemVisitor.java @@ -0,0 +1,410 @@ +package de.hft.stuttgart.citydoctor2.gui.tree; + +import java.util.List; + +import de.hft.stuttgart.citydoctor2.check.CheckError; +import de.hft.stuttgart.citydoctor2.check.ErrorVisitor; +import de.hft.stuttgart.citydoctor2.check.error.AllPolygonsWrongOrientationError; +import de.hft.stuttgart.citydoctor2.check.error.AttributeInvalidError; +import de.hft.stuttgart.citydoctor2.check.error.AttributeMissingError; +import de.hft.stuttgart.citydoctor2.check.error.AttributeValueWrongError; +import de.hft.stuttgart.citydoctor2.check.error.ConsecutivePointSameError; +import de.hft.stuttgart.citydoctor2.check.error.DependenciesNotMetError; +import de.hft.stuttgart.citydoctor2.check.error.MultipleConnectedComponentsError; +import de.hft.stuttgart.citydoctor2.check.error.NestedRingError; +import de.hft.stuttgart.citydoctor2.check.error.NonManifoldEdgeError; +import de.hft.stuttgart.citydoctor2.check.error.NonManifoldVertexError; +import de.hft.stuttgart.citydoctor2.check.error.NonPlanarPolygonDistancePlaneError; +import de.hft.stuttgart.citydoctor2.check.error.NonPlanarPolygonNormalsDeviation; +import de.hft.stuttgart.citydoctor2.check.error.NotCeilingError; +import de.hft.stuttgart.citydoctor2.check.error.NotFloorError; +import de.hft.stuttgart.citydoctor2.check.error.NotGroundError; +import de.hft.stuttgart.citydoctor2.check.error.NotWallError; +import de.hft.stuttgart.citydoctor2.check.error.NullAreaError; +import de.hft.stuttgart.citydoctor2.check.error.PointTouchesEdgeError; +import de.hft.stuttgart.citydoctor2.check.error.PolygonHoleOutsideError; +import de.hft.stuttgart.citydoctor2.check.error.PolygonInteriorDisconnectedError; +import de.hft.stuttgart.citydoctor2.check.error.PolygonIntersectingRingsError; +import de.hft.stuttgart.citydoctor2.check.error.PolygonSameOrientationError; +import de.hft.stuttgart.citydoctor2.check.error.PolygonWithoutSurfaceError; +import de.hft.stuttgart.citydoctor2.check.error.PolygonWrongOrientationError; +import de.hft.stuttgart.citydoctor2.check.error.RingDuplicatePointError; +import de.hft.stuttgart.citydoctor2.check.error.RingEdgeIntersectionError; +import de.hft.stuttgart.citydoctor2.check.error.RingNotClosedError; +import de.hft.stuttgart.citydoctor2.check.error.RingTooFewPointsError; +import de.hft.stuttgart.citydoctor2.check.error.SchematronError; +import de.hft.stuttgart.citydoctor2.check.error.SolidNotClosedError; +import de.hft.stuttgart.citydoctor2.check.error.SolidSelfIntError; +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.Edge; +import de.hft.stuttgart.citydoctor2.datastructure.Polygon; +import de.hft.stuttgart.citydoctor2.datastructure.Vertex; +import de.hft.stuttgart.citydoctor2.gui.CheckStatus; +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 final TreeItem root; + + public ErrorItemVisitor(TreeItem root) { + this.root = root; + } + + @Override + public void visit(PolygonHoleOutsideError err) { + PolygonNode polyNode = new PolygonNode(err.getPolygon(), CheckStatus.NOT_CHECKED); + TreeItem polyItem = new TreeItem<>(polyNode); + root.getChildren().add(polyItem); + } + + @Override + public void visit(NonManifoldEdgeError err) { + for (Edge e : err.getEdges()) { + EdgeNode edgeNode = new EdgeNode(e); + TreeItem edgeItem = new TreeItem<>(edgeNode); + root.getChildren().add(edgeItem); + } + } + + @Override + public void visit(MultipleConnectedComponentsError err) { + for (int i = 0; i < err.getComponents().size(); i++) { + TextNode textNode = new TextNode("Component " + i); + TreeItem textItem = new TreeItem<>(textNode); + root.getChildren().add(textItem); + List component = err.getComponents().get(i); + for (Polygon p : component) { + PolygonNode polyNode = new PolygonNode(p, CheckStatus.NOT_CHECKED); + TreeItem polyItem = new TreeItem<>(polyNode); + textItem.getChildren().add(polyItem); + } + } + } + + @Override + public void visit(NestedRingError err) { + PolygonNode polyNode = new PolygonNode(err.getPolygon(), CheckStatus.NOT_CHECKED); + TreeItem polyItem = new TreeItem<>(polyNode); + root.getChildren().add(polyItem); + } + + @Override + public void visit(NonManifoldVertexError err) { + VertexNode vertexNode = new VertexNode(err.getVertex()); + TreeItem vertexItem = new TreeItem<>(vertexNode); + root.getChildren().add(vertexItem); + for (int i = 0; i < err.getComponents().size(); i++) { + TextNode textNode = new TextNode("Component " + i); + TreeItem textItem = new TreeItem<>(textNode); + root.getChildren().add(textItem); + List component = err.getComponents().get(i); + for (Polygon p : component) { + PolygonNode polyNode = new PolygonNode(p, CheckStatus.NOT_CHECKED); + TreeItem polyItem = new TreeItem<>(polyNode); + textItem.getChildren().add(polyItem); + } + } + } + + @Override + public void visit(PolygonWrongOrientationError err) { + for (Edge e : err.getEdges()) { + EdgeNode edgeNode = new EdgeNode(e); + TreeItem edgeItem = new TreeItem<>(edgeNode); + root.getChildren().add(edgeItem); + } + } + + @Override + public void visit(PolygonSameOrientationError err) { + PolygonNode polyNode = new PolygonNode(err.getPolygon(), CheckStatus.NOT_CHECKED); + TreeItem polyItem = new TreeItem<>(polyNode); + root.getChildren().add(polyItem); + } + + @Override + public void visit(SolidNotClosedError err) { + for (Edge e : err.getErrorEdges()) { + EdgeNode edgeNode = new EdgeNode(e); + TreeItem edgeItem = new TreeItem<>(edgeNode); + root.getChildren().add(edgeItem); + } + } + + @Override + public void visit(DependenciesNotMetError err) { + // not displayed + } + + @Override + public void visit(UnknownCheckError err) { + // not displayed + + } + + @Override + public void visit(RingNotClosedError err) { + LinearRingNode ringNode = new LinearRingNode(err.getRing(), CheckStatus.NOT_CHECKED); + TreeItem ringItem = new TreeItem<>(ringNode); + root.getChildren().add(ringItem); + } + + @Override + public void visit(ConsecutivePointSameError err) { + LinearRingNode ringNode = new LinearRingNode(err.getRing(), CheckStatus.NOT_CHECKED); + TreeItem ringItem = new TreeItem<>(ringNode); + root.getChildren().add(ringItem); + + VertexNode vertexNode = new VertexNode(err.getVertex1()); + TreeItem vertexItem = new TreeItem<>(vertexNode); + root.getChildren().add(vertexItem); + + vertexNode = new VertexNode(err.getVertex2()); + vertexItem = new TreeItem<>(vertexNode); + root.getChildren().add(vertexItem); + } + + @Override + public void visit(AllPolygonsWrongOrientationError err) { + // not displayed + } + + @Override + public void visit(PolygonInteriorDisconnectedError err) { + PolygonNode polyNode = new PolygonNode(err.getPolygon(), CheckStatus.NOT_CHECKED); + TreeItem polyItem = new TreeItem<>(polyNode); + root.getChildren().add(polyItem); + } + + @Override + public void visit(NullAreaError err) { + LinearRingNode ringNode = new LinearRingNode(err.getRing(), CheckStatus.NOT_CHECKED); + TreeItem ringItem = new TreeItem<>(ringNode); + root.getChildren().add(ringItem); + } + + @Override + public void visit(RingTooFewPointsError err) { + LinearRingNode ringNode = new LinearRingNode(err.getRing(), CheckStatus.NOT_CHECKED); + TreeItem ringItem = new TreeItem<>(ringNode); + root.getChildren().add(ringItem); + + if (err.getRing().getGmlId().isGenerated()) { + PolygonNode polyNode = new PolygonNode(err.getRing().getParent(), CheckStatus.NOT_CHECKED); + TreeItem polyItem = new TreeItem<>(polyNode); + ringItem.getChildren().add(polyItem); + } + } + + @Override + public void visit(NonPlanarPolygonNormalsDeviation err) { + PolygonNode polyNode = new PolygonNode(err.getPolygon(), CheckStatus.NOT_CHECKED); + TreeItem polyItem = new TreeItem<>(polyNode); + root.getChildren().add(polyItem); + + TextNode textNode = new TextNode("Deviation: " + err.getDeviation()); + TreeItem textItem = new TreeItem<>(textNode); + root.getChildren().add(textItem); + } + + @Override + public void visit(NonPlanarPolygonDistancePlaneError err) { + PolygonNode polyNode = new PolygonNode(err.getPolygon(), CheckStatus.NOT_CHECKED); + TreeItem polyItem = new TreeItem<>(polyNode); + root.getChildren().add(polyItem); + + VertexNode vertexNode = new VertexNode(err.getVertex()); + TreeItem vertexItem = new TreeItem<>(vertexNode); + root.getChildren().add(vertexItem); + + TextNode textNode = new TextNode("Distance: " + err.getDistance() + "m"); + TreeItem textItem = new TreeItem<>(textNode); + root.getChildren().add(textItem); + + } + + @Override + public void visit(PolygonIntersectingRingsError err) { + PolygonNode polyNode = new PolygonNode(err.getPolygon(), CheckStatus.NOT_CHECKED); + TreeItem polyItem = new TreeItem<>(polyNode); + root.getChildren().add(polyItem); + } + + @Override + public void visit(SolidSelfIntError err) { + PolygonNode polyNode1 = new PolygonNode(err.getIntersections().get(0).getP1(), CheckStatus.NOT_CHECKED); + TreeItem polyItem1 = new TreeItem<>(polyNode1); + root.getChildren().add(polyItem1); + PolygonNode polyNode2 = new PolygonNode(err.getIntersections().get(0).getP2(), CheckStatus.NOT_CHECKED); + TreeItem polyItem2 = new TreeItem<>(polyNode2); + root.getChildren().add(polyItem2); + } + + @Override + public void visit(TooFewPolygonsError err) { + // not displayed + + } + + @Override + public void visit(RingDuplicatePointError err) { + LinearRingNode ringNode = new LinearRingNode(err.getRing(), CheckStatus.NOT_CHECKED); + TreeItem ringItem = new TreeItem<>(ringNode); + root.getChildren().add(ringItem); + + VertexNode vertexNode = new VertexNode(err.getVertex1()); + TreeItem vertexItem = new TreeItem<>(vertexNode); + root.getChildren().add(vertexItem); + + vertexNode = new VertexNode(err.getVertex2()); + vertexItem = new TreeItem<>(vertexNode); + root.getChildren().add(vertexItem); + + } + + @Override + public void visit(RingEdgeIntersectionError err) { + LinearRingNode ringNode = new LinearRingNode(err.getRing(), CheckStatus.NOT_CHECKED); + TreeItem ringItem = new TreeItem<>(ringNode); + root.getChildren().add(ringItem); + + EdgeNode edgeNode = new EdgeNode(err.getEdge1()); + TreeItem edgeItem = new TreeItem<>(edgeNode); + root.getChildren().add(edgeItem); + + EdgeNode edge2Node = new EdgeNode(err.getEdge2()); + TreeItem edge2Item = new TreeItem<>(edge2Node); + root.getChildren().add(edge2Item); + + VertexNode vertexNode = new VertexNode(new Vertex(err.getIntersection())); + TreeItem vertexItem = new TreeItem<>(vertexNode); + root.getChildren().add(vertexItem); + } + + @Override + public void visit(PointTouchesEdgeError err) { + TextNode textNode = new TextNode("Point touches edge"); + TreeItem textItem = new TreeItem<>(textNode); + root.getChildren().add(textItem); + + VertexNode vertexNode = new VertexNode(err.getVertex()); + TreeItem vertexItem = new TreeItem<>(vertexNode); + root.getChildren().add(vertexItem); + + EdgeNode edgeNode = new EdgeNode(err.getEdge()); + TreeItem edgeItem = new TreeItem<>(edgeNode); + root.getChildren().add(edgeItem); + + LinearRingNode ringNode = new LinearRingNode(err.getRing(), CheckStatus.NOT_CHECKED); + TreeItem ringItem = new TreeItem<>(ringNode); + root.getChildren().add(ringItem); + } + + @Override + public void visit(NotCeilingError err) { + PolygonNode polyNode = new PolygonNode(err.getPolygon(), CheckStatus.NOT_CHECKED); + TreeItem polyItem = new TreeItem<>(polyNode); + root.getChildren().add(polyItem); + } + + @Override + public void visit(NotFloorError err) { + PolygonNode polyNode = new PolygonNode(err.getPolygon(), CheckStatus.NOT_CHECKED); + TreeItem polyItem = new TreeItem<>(polyNode); + root.getChildren().add(polyItem); + } + + @Override + public void visit(NotWallError err) { + PolygonNode polyNode = new PolygonNode(err.getPolygon(), CheckStatus.NOT_CHECKED); + TreeItem polyItem = new TreeItem<>(polyNode); + root.getChildren().add(polyItem); + } + + @Override + public void visit(NotGroundError err) { + PolygonNode polyNode = new PolygonNode(err.getPolygon(), CheckStatus.NOT_CHECKED); + TreeItem polyItem = new TreeItem<>(polyNode); + root.getChildren().add(polyItem); + } + + @Override + public void visit(CheckError err) { + // not used + } + + @Override + public void visit(SchematronError err) { + TextNode textNode = new TextNode(err.getErrorIdString()); + TreeItem textItem = new TreeItem<>(textNode); + root.getChildren().add(textItem); + } + + @Override + public void visit(SurfaceUnfragmentedError err) { + TextNode textNode = new TextNode("Deviation: " + err.getAngleDeviation()); + TreeItem textItem = new TreeItem<>(textNode); + root.getChildren().add(textItem); + } + + @Override + public void visit(DegeneratedRingError err) { + TextNode textNode = new TextNode("Type: degenerated ring"); + TreeItem textItem = new TreeItem<>(textNode); + root.getChildren().add(textItem); + + LinearRingNode polyNode = new LinearRingNode(err.getRing(), CheckStatus.NOT_CHECKED); + TreeItem polyItem = new TreeItem<>(polyNode); + root.getChildren().add(polyItem); + } + + @Override + public void visit(AttributeMissingError err) { + if (!err.getChildId().isEmpty()) { + TextNode textNode = new TextNode(CHILD_ID + err.getChildId()); + TreeItem textItem = new TreeItem<>(textNode); + root.getChildren().add(textItem); + } + TextNode nameNode = new TextNode(NAME_OF_ATTRIBUTE + err.getNameOfAttribute()); + TreeItem nameItem = new TreeItem<>(nameNode); + root.getChildren().add(nameItem); + + } + + @Override + public void visit(AttributeValueWrongError err) { + if (!err.getChildId().isEmpty()) { + TextNode textNode = new TextNode(CHILD_ID + err.getChildId()); + TreeItem textItem = new TreeItem<>(textNode); + root.getChildren().add(textItem); + } + TextNode nameNode = new TextNode(NAME_OF_ATTRIBUTE + err.getNameOfAttribute()); + TreeItem nameItem = new TreeItem<>(nameNode); + root.getChildren().add(nameItem); + } + + @Override + public void visit(AttributeInvalidError err) { + if (!err.getChildId().isEmpty()) { + TextNode textNode = new TextNode(CHILD_ID + err.getChildId()); + TreeItem textItem = new TreeItem<>(textNode); + root.getChildren().add(textItem); + } + TextNode nameNode = new TextNode(NAME_OF_ATTRIBUTE + err.getNameOfAttribute()); + TreeItem nameItem = new TreeItem<>(nameNode); + root.getChildren().add(nameItem); + } + + @Override + public void visit(PolygonWithoutSurfaceError err) { + PolygonNode polyNode = new PolygonNode(err.getPolygon(), CheckStatus.NOT_CHECKED); + TreeItem polyItem = new TreeItem<>(polyNode); + root.getChildren().add(polyItem); + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/ErrorNode.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/ErrorNode.java new file mode 100644 index 0000000000000000000000000000000000000000..a3757cc31f0ac3328afcb099c0cc43bf47e60b35 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/ErrorNode.java @@ -0,0 +1,29 @@ +package de.hft.stuttgart.citydoctor2.gui.tree; + +import de.hft.stuttgart.citydoctor2.check.CheckError; +import de.hft.stuttgart.citydoctor2.gui.Renderer; + +public class ErrorNode extends Renderable { + + private final CheckError err; + + public ErrorNode(CheckError e) { + this.err = e; + } + + @Override + public void refreshTextColor() { + // not used + } + + @Override + public String getText() { + return err.getErrorId().toString(); + } + + @Override + public void visit(Renderer renderer) { + renderer.highlight(err); + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/GeometryNode.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/GeometryNode.java new file mode 100644 index 0000000000000000000000000000000000000000..2cb4ce79f082774d898bcb3fa4fa57429ee71481 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/GeometryNode.java @@ -0,0 +1,49 @@ +package de.hft.stuttgart.citydoctor2.gui.tree; + +import de.hft.stuttgart.citydoctor2.datastructure.Geometry; +import de.hft.stuttgart.citydoctor2.gui.CheckStatus; +import de.hft.stuttgart.citydoctor2.gui.Renderer; + +public class GeometryNode extends Renderable { + + private final Geometry geom; + private final String text; + + public GeometryNode(Geometry geom) { + this.geom = geom; + StringBuilder sb = new StringBuilder(); + sb.append("Geometry ["); + sb.append(geom.getType()); + sb.append(", "); + sb.append(geom.getLod()); + if (geom.getGmlId().isGenerated()) { + sb.append("]"); + } else { + sb.append("] "); + sb.append(geom.getGmlId()); + } + text = sb.toString(); + } + + @Override + public void refreshTextColor() { + if (!geom.isValidated()) { + setStatus(CheckStatus.NOT_CHECKED); + } else if (geom.containsAnyError()) { + setStatus(CheckStatus.ERROR); + } else { + setStatus(CheckStatus.OK); + } + } + + @Override + public String getText() { + return text; + } + + @Override + public void visit(Renderer renderer) { + renderer.render(geom); + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/InstallationNode.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/InstallationNode.java new file mode 100644 index 0000000000000000000000000000000000000000..ffe009db7d5b80250dbbf82a7de7810a5f3de1ad --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/InstallationNode.java @@ -0,0 +1,35 @@ +package de.hft.stuttgart.citydoctor2.gui.tree; + +import de.hft.stuttgart.citydoctor2.datastructure.Installation; +import de.hft.stuttgart.citydoctor2.gui.CheckStatus; +import de.hft.stuttgart.citydoctor2.gui.Renderer; + +public class InstallationNode extends Renderable { + + private final Installation bi; + + public InstallationNode(Installation bi) { + this.bi = bi; + } + + @Override + public String getText() { + return bi.getGmlId().getGmlString(); + } + + @Override + public void visit(Renderer renderer) { + renderer.render(bi); + } + + @Override + public void refreshTextColor() { + if (!bi.isValidated()) { + setStatus(CheckStatus.NOT_CHECKED); + } else if (bi.containsAnyError()) { + setStatus(CheckStatus.ERROR); + } else { + setStatus(CheckStatus.OK); + } + } +} \ No newline at end of file diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/LandUseNode.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/LandUseNode.java new file mode 100644 index 0000000000000000000000000000000000000000..443829780723fa92a4825759f1b3ce06640ad41e --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/LandUseNode.java @@ -0,0 +1,54 @@ +/*- + * Copyright 2022 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart + * + * This file is part of CityDoctor2. + * + * CityDoctor2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CityDoctor2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with CityDoctor2. If not, see . + */ +package de.hft.stuttgart.citydoctor2.gui.tree; + +import de.hft.stuttgart.citydoctor2.datastructure.LandObject; +import de.hft.stuttgart.citydoctor2.gui.CheckStatus; +import de.hft.stuttgart.citydoctor2.gui.Renderer; + +public class LandUseNode extends Renderable { + + private final LandObject landUse; + + public LandUseNode(LandObject landUse) { + this.landUse = landUse; + } + + @Override + public void refreshTextColor() { + if (!landUse.isValidated()) { + setStatus(CheckStatus.NOT_CHECKED); + } else if (landUse.containsAnyError()) { + setStatus(CheckStatus.ERROR); + } else { + setStatus(CheckStatus.OK); + } + } + + @Override + public String getText() { + return "[LandUse] " + landUse.getGmlId().getGmlString(); + } + + @Override + public void visit(Renderer renderer) { + renderer.render(landUse); + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/LinearRingNode.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/LinearRingNode.java new file mode 100644 index 0000000000000000000000000000000000000000..ac1f4f83853ba0bfe2c6ef1da72256e7f662670c --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/LinearRingNode.java @@ -0,0 +1,41 @@ +package de.hft.stuttgart.citydoctor2.gui.tree; + +import de.hft.stuttgart.citydoctor2.datastructure.LinearRing; +import de.hft.stuttgart.citydoctor2.gui.CheckStatus; +import de.hft.stuttgart.citydoctor2.gui.Renderer; + +public class LinearRingNode extends Renderable { + + private final LinearRing lr; + private String text; + + public LinearRingNode(LinearRing lr, CheckStatus cs) { + this.lr = lr; + setStatus(cs); + } + + @Override + public void refreshTextColor() { + if (!lr.isValidated()) { + setStatus(CheckStatus.NOT_CHECKED); + } else if (lr.containsAnyError()) { + setStatus(CheckStatus.ERROR); + } else { + setStatus(CheckStatus.OK); + } + } + + @Override + public String getText() { + if (text == null) { + text = "Linear Ring (" + lr.getType().toString() + ") " + lr.getGmlId().getGmlString(); + } + return text; + } + + @Override + public void visit(Renderer renderer) { + renderer.highlight(lr); + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/OpeningNode.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/OpeningNode.java new file mode 100644 index 0000000000000000000000000000000000000000..c0e425ab545530fb6c02647499f1a07ea289a113 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/OpeningNode.java @@ -0,0 +1,36 @@ +package de.hft.stuttgart.citydoctor2.gui.tree; + +import de.hft.stuttgart.citydoctor2.datastructure.Opening; +import de.hft.stuttgart.citydoctor2.gui.CheckStatus; +import de.hft.stuttgart.citydoctor2.gui.Renderer; + +public class OpeningNode extends Renderable { + + private final Opening opening; + + public OpeningNode(Opening o) { + opening = o; + } + + @Override + public void refreshTextColor() { + if (!opening.isValidated()) { + setStatus(CheckStatus.NOT_CHECKED); + } else if (opening.containsAnyError()) { + setStatus(CheckStatus.ERROR); + } else { + setStatus(CheckStatus.OK); + } + } + + @Override + public String getText() { + return "Opening [" + opening.getGmlId() + ", " + opening.getType() + "]"; + } + + @Override + public void visit(Renderer renderer) { + renderer.render(opening); + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/PolygonNode.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/PolygonNode.java new file mode 100644 index 0000000000000000000000000000000000000000..768c4d070e5e3e5666e0c1218d5a0a37dab32595 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/PolygonNode.java @@ -0,0 +1,41 @@ +package de.hft.stuttgart.citydoctor2.gui.tree; + +import de.hft.stuttgart.citydoctor2.datastructure.Polygon; +import de.hft.stuttgart.citydoctor2.gui.CheckStatus; +import de.hft.stuttgart.citydoctor2.gui.Renderer; + +public class PolygonNode extends Renderable { + + private final Polygon p; + private String text; + + public PolygonNode(Polygon p, CheckStatus cs) { + this.p = p; + setStatus(cs); + } + + @Override + public void refreshTextColor() { + if (!p.isValidated()) { + setStatus(CheckStatus.NOT_CHECKED); + } else if (p.containsAnyError()) { + setStatus(CheckStatus.ERROR); + } else { + setStatus(CheckStatus.OK); + } + } + + @Override + public String getText() { + if (text == null) { + text = "Polygon " + p.getGmlId().getGmlString(); + } + return text; + } + + @Override + public void visit(Renderer renderer) { + renderer.highlight(p); + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/ReliefNode.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/ReliefNode.java new file mode 100644 index 0000000000000000000000000000000000000000..199d3dfa637ad5aaeb470471a687942ba6fe751c --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/ReliefNode.java @@ -0,0 +1,55 @@ +/*- + * Copyright 2022 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart + * + * This file is part of CityDoctor2. + * + * CityDoctor2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CityDoctor2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with CityDoctor2. If not, see . + */ +package de.hft.stuttgart.citydoctor2.gui.tree; + +import de.hft.stuttgart.citydoctor2.datastructure.ReliefObject; +import de.hft.stuttgart.citydoctor2.gui.CheckStatus; +import de.hft.stuttgart.citydoctor2.gui.Renderer; + +public class ReliefNode extends Renderable { + + private final ReliefObject relief; + + public ReliefNode(ReliefObject relief) { + this.relief = relief; + } + + + @Override + public void refreshTextColor() { + if (!relief.isValidated()) { + setStatus(CheckStatus.NOT_CHECKED); + } else if (relief.containsAnyError()) { + setStatus(CheckStatus.ERROR); + } else { + setStatus(CheckStatus.OK); + } + } + + @Override + public String getText() { + return "[ReliefFeature] " + relief.getGmlId().getGmlString(); + } + + @Override + public void visit(Renderer renderer) { + renderer.render(relief); + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/Renderable.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/Renderable.java new file mode 100644 index 0000000000000000000000000000000000000000..12426a9e94d6d6dbeebaf413e39c1744d263f084 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/Renderable.java @@ -0,0 +1,34 @@ +package de.hft.stuttgart.citydoctor2.gui.tree; + +import de.hft.stuttgart.citydoctor2.gui.CheckStatus; +import de.hft.stuttgart.citydoctor2.gui.Renderer; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleObjectProperty; + +public abstract class Renderable { + + private final ObjectProperty statusProperty = new SimpleObjectProperty<>(); + + /** + * @return the status + */ + public CheckStatus getStatus() { + return statusProperty.getValue(); + } + + /** + * @param status the status to set + */ + public void setStatus(CheckStatus status) { + statusProperty.set(status); + } + + public ObjectProperty getStatusProperty() { + return statusProperty; + } + + public abstract void refreshTextColor(); + public abstract String getText(); + public abstract void visit(Renderer renderer); + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/RenderableTreeCell.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/RenderableTreeCell.java new file mode 100644 index 0000000000000000000000000000000000000000..611e1bcded9f444786d9029800b2643f4e123ee3 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/RenderableTreeCell.java @@ -0,0 +1,57 @@ +package de.hft.stuttgart.citydoctor2.gui.tree; + +import de.hft.stuttgart.citydoctor2.gui.CheckStatus; +import javafx.application.Platform; +import javafx.beans.value.ChangeListener; +import javafx.scene.control.Button; +import javafx.scene.control.TreeCell; +import javafx.scene.paint.Color; + +public class RenderableTreeCell extends TreeCell { + + private Renderable currentCheckable = null; + private ChangeListener listener; + + @Override + protected void updateItem(Renderable item, boolean empty) { + super.updateItem(item, empty); + if (!empty && item != null) { + if (item instanceof ButtonRenderable renderable) { + Button b = new Button("More ..."); + b.setMaxWidth(Double.MAX_VALUE); + setText(null); + setGraphic(b); + b.setOnAction(ae -> renderable.run()); + return; + } + updateColor(item.getStatus()); + setText(item.getText()); + setGraphic(null); + if (currentCheckable != item) { + if (listener != null) { + // remove old Listener + item.getStatusProperty().removeListener(listener); + } + // only add listener to the status property once + listener = (obs, oldV, newV) -> Platform.runLater(() -> updateColor(newV)); + item.getStatusProperty().addListener(listener); + currentCheckable = item; + } + } else { + setTextFill(Color.BLACK); + setText(null); + setGraphic(null); + } + } + + private void updateColor(CheckStatus status) { + if (status == CheckStatus.OK) { + setTextFill(Color.GREEN); + } else if (status == CheckStatus.ERROR) { + setTextFill(Color.RED); + } else { + setTextFill(Color.BLACK); + } + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/TextNode.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/TextNode.java new file mode 100644 index 0000000000000000000000000000000000000000..d050e7682a4d075a2eef857e7c7c1c83548b9458 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/TextNode.java @@ -0,0 +1,28 @@ +package de.hft.stuttgart.citydoctor2.gui.tree; + +import de.hft.stuttgart.citydoctor2.gui.Renderer; + +public class TextNode extends Renderable { + + private final String text; + + public TextNode(String text) { + this.text = text; + } + + @Override + public void refreshTextColor() { + // don't refresh anything + } + + @Override + public String getText() { + return text; + } + + @Override + public void visit(Renderer renderer) { + // not used + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/TinNode.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/TinNode.java new file mode 100644 index 0000000000000000000000000000000000000000..123d1dd4659bc34240b397e38cb743d32d7507ef --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/TinNode.java @@ -0,0 +1,55 @@ +/*- + * Copyright 2022 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart + * + * This file is part of CityDoctor2. + * + * CityDoctor2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CityDoctor2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with CityDoctor2. If not, see . + */ +package de.hft.stuttgart.citydoctor2.gui.tree; + +import de.hft.stuttgart.citydoctor2.datastructure.TinObject; +import de.hft.stuttgart.citydoctor2.gui.CheckStatus; +import de.hft.stuttgart.citydoctor2.gui.Renderer; + +public class TinNode extends Renderable { + + private final TinObject tin; + + public TinNode(TinObject tin) { + this.tin = tin; + } + + + @Override + public void refreshTextColor() { + if (!tin.isValidated()) { + setStatus(CheckStatus.NOT_CHECKED); + } else if (tin.containsAnyError()) { + setStatus(CheckStatus.ERROR); + } else { + setStatus(CheckStatus.OK); + } + } + + @Override + public String getText() { + return "[TINRelief] " + tin.getGmlId().getGmlString(); + } + + @Override + public void visit(Renderer renderer) { + renderer.render(tin); + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/TreeRequirement.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/TreeRequirement.java new file mode 100644 index 0000000000000000000000000000000000000000..b43403fc3cb237a07a452c740065cdb1e4367bcd --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/TreeRequirement.java @@ -0,0 +1,67 @@ +package de.hft.stuttgart.citydoctor2.gui.tree; + +import de.hft.stuttgart.citydoctor2.check.DefaultParameter; +import de.hft.stuttgart.citydoctor2.check.Requirement; +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.value.ObservableValue; + +public class TreeRequirement { + + private BooleanProperty enabled; + private final ObservableValue name; + private SimpleStringProperty value; + private final ObservableValue unit; + + private Requirement r; + + public TreeRequirement(Requirement r) { + this.r = r; + enabled = new SimpleBooleanProperty(true); + name = new SimpleStringProperty(r.getId()); + unit = new SimpleStringProperty(); + } + + public TreeRequirement(DefaultParameter dp) { + name = new SimpleStringProperty(dp.getName()); + value = new SimpleStringProperty(dp.getValue()); + unit = new SimpleStringProperty(dp.getUnitType().getRepresentation()); + } + + public void setEnabled(boolean enabled) { + this.enabled.set(enabled); + } + + public ObservableValue getUnitProperty() { + return unit; + } + + /** + * @return the enabled + */ + public BooleanProperty getEnabledProperty() { + return enabled; + } + + public ObservableValue getNameProperty() { + return name; + } + + public ObservableValue getValueProperty() { + return value; + } + + public void setValue(String value) { + this.value.setValue(value); + } + + public Requirement getRequirement() { + return r; + } + + public boolean isEnabled() { + return enabled.get(); + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/VegetationNode.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/VegetationNode.java new file mode 100644 index 0000000000000000000000000000000000000000..9a30d5d926a1397fb6552a203782aadd8bdb9976 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/VegetationNode.java @@ -0,0 +1,56 @@ +/*- + * Copyright 2022 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart + * + * This file is part of CityDoctor2. + * + * CityDoctor2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CityDoctor2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with CityDoctor2. If not, see . + */ +package de.hft.stuttgart.citydoctor2.gui.tree; + +import de.hft.stuttgart.citydoctor2.datastructure.Vegetation; +import de.hft.stuttgart.citydoctor2.gui.CheckStatus; +import de.hft.stuttgart.citydoctor2.gui.Renderer; + +public class VegetationNode extends Renderable { + + private final Vegetation veg; + private final String text; + + public VegetationNode(Vegetation veg) { + this.veg = veg; + text = "[" + veg.getVegetationType() + "] " + veg.getGmlId().getGmlString(); + } + + @Override + public void refreshTextColor() { + if (!veg.isValidated()) { + setStatus(CheckStatus.NOT_CHECKED); + } else if (veg.containsAnyError()) { + setStatus(CheckStatus.ERROR); + } else { + setStatus(CheckStatus.OK); + } + } + + @Override + public String getText() { + return text; + } + + @Override + public void visit(Renderer renderer) { + renderer.render(veg); + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/VertexNode.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/VertexNode.java new file mode 100644 index 0000000000000000000000000000000000000000..c22b28cc3f01c200bf9aecb7fc6f8b6c86364aca --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/VertexNode.java @@ -0,0 +1,46 @@ +package de.hft.stuttgart.citydoctor2.gui.tree; + +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; + +import de.hft.stuttgart.citydoctor2.datastructure.Vertex; +import de.hft.stuttgart.citydoctor2.gui.Renderer; + +public class VertexNode extends Renderable { + + private static final DecimalFormat nf; + + static { + DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(); + dfs.setDecimalSeparator('.'); + nf = new DecimalFormat("#.########", dfs); + } + + private static final String SEPERATOR = ", "; + private final Vertex v; + private String text; + + public VertexNode(Vertex v) { + this.v = v; + } + + @Override + public void refreshTextColor() { + // not used + } + + @Override + public String getText() { + if (text == null) { + text = "Vertex [" + nf.format(v.getX()) + SEPERATOR + + nf.format(v.getY()) + SEPERATOR + nf.format(v.getZ()) + "]"; + } + return text; + } + + @Override + public void visit(Renderer renderer) { + renderer.highlight(v); + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/resources/citydoctor_logo.ico b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/resources/citydoctor_logo.ico new file mode 100644 index 0000000000000000000000000000000000000000..3321b741356a9f40506da39dd8377c83e227d67a Binary files /dev/null and b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/resources/citydoctor_logo.ico differ diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/resources/de/hft/stuttgart/citydoctor2/gui/AboutDialog.fxml b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/resources/de/hft/stuttgart/citydoctor2/gui/AboutDialog.fxml new file mode 100644 index 0000000000000000000000000000000000000000..ef3c7e4c3fa42a74b28cf159e2c5d40e66769687 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/resources/de/hft/stuttgart/citydoctor2/gui/AboutDialog.fxml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/resources/de/hft/stuttgart/citydoctor2/gui/CheckDialog.fxml b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/resources/de/hft/stuttgart/citydoctor2/gui/CheckDialog.fxml new file mode 100644 index 0000000000000000000000000000000000000000..19930f97e6da6892145dd2053f4a9b5e48f883c3 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/resources/de/hft/stuttgart/citydoctor2/gui/CheckDialog.fxml @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/resources/de/hft/stuttgart/citydoctor2/gui/CreateRenderDataDialog.fxml b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/resources/de/hft/stuttgart/citydoctor2/gui/CreateRenderDataDialog.fxml new file mode 100644 index 0000000000000000000000000000000000000000..49cb7f12cec00a0af207ff81f563cc9933268967 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/resources/de/hft/stuttgart/citydoctor2/gui/CreateRenderDataDialog.fxml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/resources/de/hft/stuttgart/citydoctor2/gui/FilterPane.fxml b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/resources/de/hft/stuttgart/citydoctor2/gui/FilterPane.fxml new file mode 100644 index 0000000000000000000000000000000000000000..264bab351e4be0eddae2adfce5554f0cf6364fd6 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/resources/de/hft/stuttgart/citydoctor2/gui/FilterPane.fxml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/resources/de/hft/stuttgart/citydoctor2/gui/MainToolBar.fxml b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/resources/de/hft/stuttgart/citydoctor2/gui/MainToolBar.fxml new file mode 100644 index 0000000000000000000000000000000000000000..17503f5f787030442628f51e2a2cf45cd88b0702 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/resources/de/hft/stuttgart/citydoctor2/gui/MainToolBar.fxml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/resources/de/hft/stuttgart/citydoctor2/gui/MainWindow.fxml b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/resources/de/hft/stuttgart/citydoctor2/gui/MainWindow.fxml new file mode 100644 index 0000000000000000000000000000000000000000..e9f2c952de7e4ffe918f0338e1f30f9b6c860a1f --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/resources/de/hft/stuttgart/citydoctor2/gui/MainWindow.fxml @@ -0,0 +1,179 @@ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CityDoctorParent/Extensions/CityDoctorWebService/src/main/webapp/models_scripts.js b/CityDoctorParent/Extensions/CityDoctorWebService/src/main/webapp/models_scripts.js new file mode 100644 index 0000000000000000000000000000000000000000..0e1485dfd7820e9fba71012105133a3d1311f296 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorWebService/src/main/webapp/models_scripts.js @@ -0,0 +1,815 @@ +const nrOfPages = 7; +const itemsPerPage = 20; + +var token = window.localStorage.getItem('token'); +var loadedValidationPlan = false; + +var fileProgress = $('#file-progress'); +var invalidFile = $('#invalidFile'); +var invalidConfigFile = $('#invalidConfigFile'); +var onlyErrors = false; +var currentValidationId = null; +var currentModelId = null; + +Dropzone.options.addFileZone = { + init : function() { + this.on("sending", function(file, xhr, formData) { + invalidFile.slideUp(); + fileProgress.attr('aria-valuenow', '0'); + fileProgress.width('0%'); + }); + this.on('complete', function(file) { + this.removeFile(file); + }); + this.on('error', function(file, errorMessage, xhr) { + $('#invalidFileText').text(errorMessage); + invalidFile.slideDown(); + }); + this.on('success', function(file, response) { + refreshModels(token); + }); + }, + parallelUploads : 1, + createImageThumbnails : false, + maxFiles : 1, + headers : { + 'Authorization' : 'Bearer ' + token + }, + thumbnail : function(file, dataUrl) { + // Display the image in your file.previewElement + }, + uploadprogress : function(file, progress, bytesSent) { + // Display the progress + fileProgress.attr('aria-valuenow', progress); + fileProgress.width(progress + '%'); + }, + addedfile : function(file) { + }, + acceptedFiles : '.xml, .gml, .zip', +}; + +$(document).ready(function() { + createToggleListener(); + createFileNameListener(); + setupUploadButton(token); + setupBackButton(); + setupFilterEventListener(); + refreshModels(token); + addModalListener(); +}); + +function setupFilterEventListener() { + $('#only_errors').change(function() { + onlyErrors = $(this).prop('checked'); + loadBuildings(currentModelId, 0, currentValidationId); + }); +} + +function addModalListener() { + $('#validation_plan_modal').on('show.bs.modal', function (event) { + var button = $(event.relatedTarget); + var modelId = button.data('id'); + if (!loadedValidationPlan) { + loadedValidationPlan = true; + $.ajax({ + method : 'GET', + url : '/CityDoctorWebService/rest/checks', + success : function(response) { + var geometricChecksDiv = $('#geometric_checks'); + response.geometricChecks.forEach(function (check, i) { + var checkDiv = document.createElement('div'); + geometricChecksDiv.append(checkDiv); + + var input = document.createElement('input'); + checkDiv.append(input); + input.setAttribute('type', 'checkbox'); + input.setAttribute('checked', ''); + input.setAttribute('id', 'check' + i); + input.setAttribute('data-toggle', 'toggle'); + input.setAttribute('data-onstyle', 'success'); + input.setAttribute('data-offstyle', 'danger'); + input.setAttribute('data-size', 'sm'); + $(input).bootstrapToggle(); + + var label = document.createElement('label'); + checkDiv.append(label); + label.setAttribute('class', 'ml-1'); + label.setAttribute('for', 'check' + i); + label.append(check.name); + + if (check.parameters.length != 0) { + var groupDiv = document.createElement('div'); + checkDiv.append(groupDiv); + groupDiv.setAttribute('class', 'ml-3 list-group list-group-flush'); + var itemDiv = document.createElement('div'); + groupDiv.append(itemDiv); + itemDiv.setAttribute('class', 'list-group-item'); + + check.parameters.forEach(function (parameter, i) { + + var inputGroupDiv = document.createElement('div'); + itemDiv.append(inputGroupDiv); + inputGroupDiv.setAttribute('class', 'input-group'); + + var prependDiv = document.createElement('div'); + inputGroupDiv.append(prependDiv); + prependDiv.setAttribute('class', 'input-group-prepend'); + + var span = document.createElement('span'); + prependDiv.append(span); + span.setAttribute('class', 'input-group-text'); + span.append(parameter.name); + + var input = document.createElement('input'); + inputGroupDiv.append(input); + input.setAttribute('type', 'text'); + input.setAttribute('class', 'form-control'); + input.setAttribute('value', parameter.defaultValue); + }); + } + }); + }, + complete : function(xhr, status) { + if (xhr.status !== 200) { + loadedValidationPlan = false; + if (xhr.status === 500) { + document.location.href = 'internal_server_error.html'; + } + } + } + }); + } + }); +} + +function logoutClick() { + $.ajax({ + method : 'POST', + url : '/CityDoctorWebService/rest/logout', + beforeSend : function(xhr) { + xhr.setRequestHeader('Authorization', 'Bearer ' + token); + }, + success : function(response) { + document.location.href = 'index.html'; + }, + complete : function(xhr, status) { + if (xhr.status == 403) { + document.location.href = 'index.html'; + } else if (xhr.status == 500) { + document.location.href = 'internal_server_error.html'; + } + } + }); +} + +function setupBackButton() { + $('#backButton').click(function() { + $('#modelsPage').slideToggle(); + $('#viewPage').slideToggle(); + stopRender(); + }); +} + +function refreshModels(token) { + var container = $('#models'); + container.empty(); + $.ajax({ + method : 'GET', + url : '/CityDoctorWebService/rest/models', + beforeSend : function(xhr) { + xhr.setRequestHeader('Authorization', 'Bearer ' + token); + }, + success : function(response) { + createModelBars(response, container); + }, + complete : function(xhr, status) { + if (xhr.status == 403) { + document.location.href = 'index.html'; + } else if (xhr.status == 500) { + document.location.href = 'internal_server_error.html'; + } + } + }); +} + +function createModelBars(models, container) { + models.forEach(function(model, i) { + var div = document.createElement('div'); + div.setAttribute('class', 'row justify-content-center') + container.append(div); + + var colDiv = document.createElement('div'); + div.append(colDiv); + colDiv.setAttribute('class', 'col-md-8'); + + var cardDiv = document.createElement('div'); + colDiv.append(cardDiv); + cardDiv.setAttribute('class', 'card border border-secondary'); + + var modelName = 'model' + i; + var headingId = 'headingModel' + i; + + var heading = document.createElement('h5'); + cardDiv.append(heading); + heading.setAttribute('class', 'card-title card-header'); + heading.setAttribute('data-toggle', 'collapse'); + heading.setAttribute('data-target', '#' + modelName); + heading.setAttribute('aria-expanded', 'false'); + heading.setAttribute('aria-controls', modelName); + heading.setAttribute('id', headingId); + + var headingButton = document.createElement('button'); + heading.append(headingButton); + headingButton.setAttribute('class', 'btn btn-link text-dark'); + headingButton.setAttribute('data-toggle', 'collapse'); + headingButton.setAttribute('data-target', '#' + modelName); + headingButton.setAttribute('aria-expanded', 'false'); + headingButton.setAttribute('aria-controls', modelName); + headingButton.innerHTML = model.name; + + var collapseDiv = document.createElement('div'); + cardDiv.append(collapseDiv); + collapseDiv.setAttribute('id', modelName); + collapseDiv.setAttribute('class', 'collapse'); + collapseDiv.setAttribute('aria-labelledby', headingId); + + var cardBodyDiv = document.createElement('div'); + collapseDiv.append(cardBodyDiv); + cardBodyDiv.setAttribute('class', 'card-body'); + + var deleteButton = document.createElement('button'); + cardBodyDiv.append(deleteButton); + deleteButton.setAttribute('class', 'btn btn-danger float-right'); + deleteButton.append('Delete'); + deleteButton.addEventListener('click', function(e) { + $.ajax({ + method : 'DELETE', + url : '/CityDoctorWebService/rest/models/' + model.id, + beforeSend : function(xhr) { + xhr.setRequestHeader('Authorization', 'Bearer ' + token); + }, + success : function(response) { + div.parentNode.removeChild(div); + }, + complete : function(xhr, status) { + if (xhr.status == 403) { + document.location.href = 'index.html'; + } else if (xhr.status == 500) { + document.location.href = 'internal_server_error.html'; + } + } + }); + }); + + var badge = document.createElement('span'); + heading.append(badge); + if (model.status == 'OK') { + badge.setAttribute('class', 'badge badge-success float-right'); + badge.innerHTML = 'Parsing Successful'; + addOKParsingControls(cardBodyDiv, model); + } else if (model.status == 'ERROR') { + badge.setAttribute('class', 'badge badge-danger float-right'); + badge.innerHTML = 'Parsing Failed'; + } else if (model.status == 'PARSING') { + badge.setAttribute('class', 'badge badge-warning float-right'); + badge.innerHTML = 'Parsing in Progress'; + window.setTimeout(function() { + modelStatusListener(model, cardBodyDiv, badge); + }, 1000); + } + }); +} + +var modelStatusListener = function (model, root, badge) { + $.ajax({ + method : 'GET', + url : '/CityDoctorWebService/rest/models/' + model.id + '/status', + beforeSend : function(xhr) { + xhr.setRequestHeader('Authorization', 'Bearer ' + token); + }, + success : function(response) { + if (response.status == 'OK') { + badge.setAttribute('class', 'badge badge-success float-right'); + badge.innerHTML = 'Parsing Successful'; + addOKParsingControls(root, model); + } else if (response.status == 'PARSING') { + window.setTimeout(function() { + modelStatusListener(model, root, badge); + }, 1000); + } else if (response.status == 'ERROR') { + badge.setAttribute('class', 'badge badge-danger float-right'); + badge.innerHTML = 'Parsing Failed'; + } + }, + complete : function(xhr, status) { + if (xhr.status == 403) { + document.location.href = 'index.html'; + } else if (xhr.status == 500) { + document.location.href = 'internal_server_error.html'; + } + } + }); +} + +var validationStatusListener = function (validation, root, badge, model) { + $.ajax({ + method : 'GET', + url : '/CityDoctorWebService/rest/models/validations/' + validation.id + '/status', + beforeSend : function(xhr) { + xhr.setRequestHeader('Authorization', 'Bearer ' + token); + }, + success : function(response) { + if (response.status == 'PARSING') { + badge.setAttribute('class', 'badge badge-warning float-right'); + badge.innerHTML = 'Parsing'; + window.setTimeout(function() { + validationStatusListener(validation, root, badge, model); + }, 1000); + } else if (response.status == 'VALIDATING') { + badge.setAttribute('class', 'badge badge-warning float-right'); + badge.innerHTML = 'Validating'; + window.setTimeout(function() { + validationStatusListener(validation, root, badge, model); + }, 1000); + } else if (response.status == 'OK') { + badge.setAttribute('class', 'badge badge-success float-right'); + badge.innerHTML = 'Validation Successful'; + addOKValidationControls(root, model, validation); + } else if (response.status == 'ERROR') { + badge.setAttribute('class', 'badge badge-danger float-right'); + badge.innerHTML = 'Validation Failed'; + } + }, + complete : function(xhr, status) { + if (xhr.status == 403) { + document.location.href = 'index.html'; + } else if (xhr.status == 500) { + document.location.href = 'internal_server_error.html'; + } + } + }); +} + +function searchInputEvent(input) { + console.log(input.value); +} + +function downloadFile(url) { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, true); + xhr.responseType = 'arraybuffer'; + xhr.onload = function () { + if (this.status === 200) { + var filename = ""; + var disposition = xhr.getResponseHeader('Content-Disposition'); + if (disposition && disposition.indexOf('attachment') !== -1) { + var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/; + var matches = filenameRegex.exec(disposition); + if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, ''); + } + var type = xhr.getResponseHeader('Content-Type'); + + var blob; + if (typeof File === 'function') { + try { + blob = new File([this.response], filename, { type: type }); + } catch (e) { /* Edge */ } + } + if (typeof blob === 'undefined') { + blob = new Blob([this.response], { type: type }); + } + + if (typeof window.navigator.msSaveBlob !== 'undefined') { + // IE workaround for "HTML7007: One or more blob URLs were revoked by closing the blob for which they were created. These URLs will no longer resolve as the data backing the URL has been freed." + window.navigator.msSaveBlob(blob, filename); + } else { + var URL = window.URL || window.webkitURL; + var downloadUrl = URL.createObjectURL(blob); + + if (filename) { + // use HTML5 a[download] attribute to specify filename + var a = document.createElement("a"); + // safari doesn't support this yet + if (typeof a.download === 'undefined') { + window.location = downloadUrl; + } else { + a.href = downloadUrl; + a.download = filename; + document.body.appendChild(a); + a.click(); + } + } else { + window.location = downloadUrl; + } + + setTimeout(function () { URL.revokeObjectURL(downloadUrl); }, 100); // cleanup + } + } + }; + xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); + xhr.setRequestHeader('Authorization', 'Bearer ' + token); + xhr.send(); +} + +function addOKParsingControls(root, model) { + var viewButton = document.createElement('button'); + root.append(viewButton); + viewButton.setAttribute('class', 'btn btn-primary') + viewButton.innerHTML = 'View'; + viewButton.onclick = function(e) { + $('#modelsPage').slideToggle(); + $('#viewPage').slideToggle(); + loadBuildings(model.id, 0, null); + }; + + var validationHeading = document.createElement('h5'); + root.append(validationHeading); + validationHeading.setAttribute('class', 'mt-3'); + validationHeading.append('Validation'); + + + var borderDiv = document.createElement('div'); + root.append(borderDiv); + borderDiv.setAttribute('class', 'list-group'); + + var borderItemDiv = document.createElement('div'); + borderDiv.append(borderItemDiv); + borderItemDiv.setAttribute('class', 'list-group-item border-secondary'); + + borderItemDiv.append('Upload validation configuration files to start a validation process'); + + var configForm = document.createElement('form'); + borderItemDiv.append(configForm); + + var configFileInput = document.createElement('input'); + configForm.append(configFileInput); + configFileInput.setAttribute('name', 'file'); + configFileInput.setAttribute('type', 'file'); + + var configSubmit = document.createElement('button'); + configForm.append(configSubmit); + configSubmit.setAttribute('type', 'submit'); + configSubmit.setAttribute('class', 'btn btn-primary'); + configSubmit.append('Upload'); + + var configCreate = document.createElement('button'); + configForm.append(configCreate); + configCreate.setAttribute('type', 'button'); + configCreate.setAttribute('class', 'btn btn-secondary float-right'); + configCreate.setAttribute('data-toggle', 'modal'); + configCreate.setAttribute('data-target', '#validation_plan_modal'); + configCreate.setAttribute('data-id', model.id); + configCreate.append('Create'); + + var validationItemsDiv = document.createElement('div'); + borderItemDiv.append(validationItemsDiv); + validationItemsDiv.setAttribute('class', 'list-group mt-3'); + + $(configForm).submit(function (e) { + var url = '/CityDoctorWebService/rest/models/' + model.id + '/validations'; + e.preventDefault(); + + var data = new FormData(); + $.each($(configFileInput)[0].files, function(i, file) { + data.append('file', file); + }); + + $.ajax({ + method : 'POST', + url : url, + cache: false, + contentType: false, + processData: false, + data : data, + beforeSend : function(xhr) { + xhr.setRequestHeader('Authorization', 'Bearer ' + token); + }, + success : function (response) { + addValidationControls(validationItemsDiv, response, model); + }, + complete : function (xhr, status) { + if (xhr.status == 403) { + console.log('Authentication failed') + } else if (xhr.status == 500) { + document.location.href = 'internal_server_error.html'; + } + } + }); + }); + + model.validations.forEach(function (validation, i) { + addValidationControls(validationItemsDiv, validation, model); + }); +} + +function addValidationControls(root, validation, model) { + var validationItemDiv = document.createElement('div'); + root.append(validationItemDiv); + validationItemDiv.setAttribute('class', 'list-group-item border-secondary'); + + var itemHeading = document.createElement('h5'); + validationItemDiv.append(itemHeading); + itemHeading.append(validation.name); + + var badgeSpan = document.createElement('span'); + itemHeading.append(badgeSpan); + if (validation.status == 'PARSING') { + badgeSpan.setAttribute('class', 'badge badge-warning float-right'); + badgeSpan.append('Parsing'); + window.setTimeout(function() { + validationStatusListener(validation, validationItemDiv, badgeSpan, model); + }, 1000); + } else if (validation.status == 'VALIDATING') { + badgeSpan.setAttribute('class', 'badge badge-warning float-right'); + badgeSpan.append('Validating'); + window.setTimeout(function() { + validationStatusListener(validation, validationItemDiv, badgeSpan, model); + }, 1000); + } else if (validation.status == 'OK') { + badgeSpan.setAttribute('class', 'badge badge-success float-right'); + badgeSpan.append('Validation Successful'); + addOKValidationControls(validationItemDiv, model, validation); + } else if (validation.status == 'ERROR') { + badgeSpan.setAttribute('class', 'badge badge-danger float-right'); + badgeSpan.append('Validation Failed'); + addValidationDeleteButton(validationItemDiv, validation); + } +} + +function addOKValidationControls(root, model, validation) { + var viewItemButton = document.createElement('button'); + root.append(viewItemButton); + viewItemButton.setAttribute('class', 'btn btn-primary'); + viewItemButton.append('View'); + viewItemButton.addEventListener('click', function(e) { + $('#modelsPage').slideToggle(); + $('#viewPage').slideToggle(); + loadBuildings(model.id, 0, validation.id); + }); + + addValidationDeleteButton(root, validation); + + var downloadDiv = document.createElement('div'); + root.append(downloadDiv); + downloadDiv.append('Download Reports:'); + + var xmlDownload = document.createElement('button'); + downloadDiv.append(xmlDownload); + xmlDownload.setAttribute('class', 'ml-3 btn btn-secondary'); + xmlDownload.append('XML'); + $(xmlDownload).click(function(e) { + downloadFile('/CityDoctorWebService/rest/models/validations/' + validation.id + '/xml'); + }); + + var pdfDownload = document.createElement('button'); + downloadDiv.append(pdfDownload); + pdfDownload.setAttribute('class', 'ml-1 btn btn-secondary'); + pdfDownload.append('PDF'); + $(pdfDownload).click(function(e) { + downloadFile('/CityDoctorWebService/rest/models/validations/' + validation.id + '/pdf'); + }); + +} + +function addValidationDeleteButton(root, validation) { + var deleteItemButton = document.createElement('button'); + root.append(deleteItemButton); + deleteItemButton.setAttribute('class', 'btn btn-danger float-right'); + deleteItemButton.append('Delete'); + deleteItemButton.addEventListener('click', function(e) { + $.ajax({ + method : 'DELETE', + url : '/CityDoctorWebService/rest/models/validations/' + validation.id, + beforeSend : function(xhr) { + xhr.setRequestHeader('Authorization', 'Bearer ' + token); + }, + success : function(response) { + root.parentNode.removeChild(root); + }, + complete : function(xhr, status) { + if (xhr.status == 403) { + document.location.href = 'index.html'; + } else if (xhr.status == 500) { + document.location.href = 'internal_server_error.html'; + } + } + }); + }); +} + +function loadBuildings(modelId, from, validationId) { + currentValidationId = validationId; + currentModelId = modelId; + // view page is now visible, resize gl viewport + resizeCanvas(); + + // clear errors + var errorList = $('#error_list'); + errorList.empty(); + var e = document.getElementById('error_heading'); + if (validationId) { + e.style.visibility = 'visible'; + } else { + e.style.visibility = 'hidden'; + } + + var buildingsReq = new XMLHttpRequest(); + if (validationId) { + if (onlyErrors) { + buildingsReq.open('GET', '/CityDoctorWebService/rest/models/' + modelId + '/error_buildings?from=' + from + '&valid=' + validationId); + } else { + buildingsReq.open('GET', '/CityDoctorWebService/rest/models/' + modelId + '/buildings?from=' + from + '&valid=' + validationId); + } + } else { + buildingsReq.open('GET', '/CityDoctorWebService/rest/models/' + modelId + '/buildings?from=' + from); + } + buildingsReq.responseType = 'json'; + buildingsReq.setRequestHeader('Authorization', 'Bearer ' + token); + + buildingsReq.onload = function(e) { + if (this.status == 200) { + var buildings = buildingsReq.response; + + // setup pagination + var pagesDiv = $('#pages'); + pagesDiv.empty(); + var maxPages = Math.trunc(buildings.to / itemsPerPage) + 1; + if (maxPages > 1) { + var currentPage = Math.trunc(buildings.from / itemsPerPage) + 1; + var minPage = Math.max(1, currentPage - Math.max(2, currentPage - maxPages + (nrOfPages - 1))); + var maxPage = Math.min(maxPages, currentPage + (nrOfPages - 1) - (currentPage - minPage)); + + var nav = document.createElement('nav'); + pagesDiv.append(nav); + nav.setAttribute('aria-label', 'feature navigation'); + + var ul = document.createElement('ul'); + nav.append(ul); + ul.setAttribute('class', 'pagination'); + + createPageButton(ul, modelId, validationId, 0, 'First', false); + var pageIndex; + for (pageIndex = minPage; pageIndex < maxPage + 1; pageIndex++) { + createPageButton(ul, modelId, validationId, (pageIndex - 1) * itemsPerPage, pageIndex, pageIndex === currentPage); + } + createPageButton(ul, modelId, validationId, (maxPages - 1) * itemsPerPage, 'Last', false); + } + var buildingDiv = $('#bu'); + buildingDiv.empty(); + buildings.buildings.forEach(function (building, i) { + + var buildingLabel = document.createElement('label'); + buildingDiv.append(buildingLabel); + if (validationId) { + if (building.hasErrors) { + buildingLabel.setAttribute('class', 'text-left btn btn-sm btn-outline-danger'); + } else { + buildingLabel.setAttribute('class', 'text-left btn btn-sm btn-outline-success'); + } + } else { + buildingLabel.setAttribute('class', 'text-left btn btn-sm btn-outline-primary'); + } + + var buildingRadio = document.createElement('input'); + buildingLabel.append(buildingRadio); + buildingRadio.setAttribute('type', 'radio'); + buildingRadio.setAttribute('style', 'display: none;'); + + buildingLabel.append(building.gmlId); + + buildingLabel.addEventListener('click', function (e) { + // get geometry data + var oReq = new XMLHttpRequest(); + oReq.open('GET', '/CityDoctorWebService/rest/buildings/' + building.id, true); + oReq.responseType = 'arraybuffer'; + oReq.setRequestHeader('Authorization', 'Bearer ' + token); + + oReq.onload = function(oEvent) { + if (this.status == 200) { + var arrayBuffer = oReq.response; + + // accessing the received bytes + var nrOfVertices = arrayBuffer.byteLength / (9 * 4); + var dataView = new DataView(arrayBuffer); + var floatArray = new Float32Array(nrOfVertices * 9); + var i; + for (i = 0; i < nrOfVertices * 9; i++) { + floatArray[i] = dataView.getFloat32(i * 4); + } + drawModel(nrOfVertices, floatArray, building.width); + } else if (this.status == 403) { + window.location.href = 'index.html'; + } + }; + oReq.send(); + + if (validationId) { + // get errors + var errorReq = new XMLHttpRequest(); + errorReq.open('GET', '/CityDoctorWebService/rest/buildings/' + building.id + '/validation/' + validationId + '/errors', true); + errorReq.responseType = 'json'; + errorReq.setRequestHeader('Authorization', 'Bearer ' + token); + + errorReq.onload = function(oEvent) { + if (this.status == 200) { + errorList.empty(); + var errors = errorReq.response; + if (errors.length) { + errors.forEach(function (err) { + var errBtn = document.createElement('button'); + errorList.append(errBtn); + errBtn.setAttribute('class', 'list-group-item list-group-item-action'); + errBtn.append(err.name); + }); + } + } else if (this.status == 403) { + window.location.href = 'index.html'; + } + }; + errorReq.send(); + } + }); + }); + } else if (this.status == 403) { + window.location.href = 'index.html'; + } else if (this.status == 500) { + window.location.href = 'internal_server_error.html'; + } + } + + buildingsReq.send(); +} + +function setupUploadButton(token) { + $('#uploadForm').submit(function(e) { + + $('#addCollapse').toggleClass('collapse'); + var url = '/CityDoctorWebService/rest/models'; + e.preventDefault(); + + var data = new FormData(); + jQuery.each(jQuery('#file')[0].files, function(i, file) { + data.append('file', file); + }); + jQuery.each(jQuery('#configFile')[0].files, function(i, file) { + data.append('configFile', file); + }); + + $.ajax({ + method : 'POST', + url : url, + data : data, + contentType : false, + processData : false, + cache : false, + beforeSend : function(xhr) { + xhr.setRequestHeader('Authorization', 'Bearer ' + token); + }, + success : function(response) { + refreshModels(token); + }, + complete : function(xhr, status) { + if (xhr.status == 403) { + document.location.href = 'index.html'; + } else if (xhr.status == 500) { + document.location.href = 'internal_server_error.html'; + } + } + }); + }); +} + +function createPageButton(root, modelId, validationId, from, text, active) { + var first = document.createElement('li'); + root.append(first); + if (active) { + first.setAttribute('class', 'page-item active'); + } else { + first.setAttribute('class', 'page-item'); + } + first.onclick = function(e) { + loadBuildings(modelId, from, validationId); + } + + var firstA = document.createElement('a'); + first.append(firstA); + firstA.setAttribute('class', 'page-link'); + firstA.append(text); +} + +function createFileNameListener() { + $(".custom-file-input").on( + "change", + function() { + var fileName = $(this).val().split("\\").pop(); + $(this).siblings(".custom-file-label").addClass("selected") + .html(fileName); + }); +} + +function createToggleListener() { + var addBtn = $('#addBtn'); + addBtn.click(function() { + addBtn.toggleClass('active'); + }); +} diff --git a/CityDoctorParent/Extensions/CityDoctorWebService/src/test/java/de/hft/stuttgart/citydoctor2/webservice/endpoints/BuildingEndpointTest.java b/CityDoctorParent/Extensions/CityDoctorWebService/src/test/java/de/hft/stuttgart/citydoctor2/webservice/endpoints/BuildingEndpointTest.java new file mode 100644 index 0000000000000000000000000000000000000000..da5b2a75cb9e1e13aa6fe69bb78206358d282c24 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorWebService/src/test/java/de/hft/stuttgart/citydoctor2/webservice/endpoints/BuildingEndpointTest.java @@ -0,0 +1,29 @@ +package de.hft.stuttgart.citydoctor2.webservice.endpoints; + +import java.io.IOException; + +import javax.ws.rs.core.HttpHeaders; + +import org.apache.http.HttpResponse; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.HttpClients; +import org.junit.Test; + +public class BuildingEndpointTest { + + @Test + public void testGetErrors() throws ClientProtocolException, IOException { + HttpClient client = HttpClients.createMinimal(); + LoginValues login = TestUtils.login(client); + + HttpGet get = new HttpGet("http://localhost:8080/CityDoctorWebService/rest/buildings/10/errors"); + get.addHeader(HttpHeaders.AUTHORIZATION, "Bearer " + login.getToken()); + + HttpResponse response = client.execute(get); + + System.out.println(TestUtils.readCompleteReponse(response)); + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorWebService/src/test/java/de/hft/stuttgart/citydoctor2/webservice/endpoints/LoginEndpointTest.java b/CityDoctorParent/Extensions/CityDoctorWebService/src/test/java/de/hft/stuttgart/citydoctor2/webservice/endpoints/LoginEndpointTest.java new file mode 100644 index 0000000000000000000000000000000000000000..4fd7d6fe32f2d432720c217d6953a0706ca7ab76 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorWebService/src/test/java/de/hft/stuttgart/citydoctor2/webservice/endpoints/LoginEndpointTest.java @@ -0,0 +1,59 @@ +package de.hft.stuttgart.citydoctor2.webservice.endpoints; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; + +import org.apache.http.HttpResponse; +import org.apache.http.NameValuePair; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.HttpClient; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.message.BasicNameValuePair; +import org.json.JSONObject; +import org.json.JSONTokener; +import org.junit.Test; + +public class LoginEndpointTest { + + @Test + public void testLoginCorrectPassword() throws ClientProtocolException, IOException { + HttpClient client = HttpClients.createMinimal(); + HttpPost post = new HttpPost("http://localhost:8080/CityDoctorWebService/rest/login"); + + List params = new ArrayList(2); + params.add(new BasicNameValuePair("username", "Test")); + params.add(new BasicNameValuePair("password", "TestPassword")); + post.setEntity(new UrlEncodedFormEntity(params, "UTF-8")); + + HttpResponse response = client.execute(post); + assertEquals(200, response.getStatusLine().getStatusCode()); + try (BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent()))) { + JSONTokener tokener = new JSONTokener(br); + JSONObject o = new JSONObject(tokener); + assertNotNull(o.getString("token")); + } + } + + @Test + public void testLoginIncorrectPassword() throws ClientProtocolException, IOException { + HttpClient client = HttpClients.createMinimal(); + HttpPost post = new HttpPost("http://localhost:8080/CityDoctorWebService/rest/login"); + + List params = new ArrayList(2); + params.add(new BasicNameValuePair("username", "Test")); + params.add(new BasicNameValuePair("password", "TestIncorrectPassword")); + post.setEntity(new UrlEncodedFormEntity(params, "UTF-8")); + + HttpResponse response = client.execute(post); + assertEquals(403, response.getStatusLine().getStatusCode()); + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorWebService/src/test/java/de/hft/stuttgart/citydoctor2/webservice/endpoints/LoginValues.java b/CityDoctorParent/Extensions/CityDoctorWebService/src/test/java/de/hft/stuttgart/citydoctor2/webservice/endpoints/LoginValues.java new file mode 100644 index 0000000000000000000000000000000000000000..ac392e59312400d370bfd3295dc98e46d1723603 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorWebService/src/test/java/de/hft/stuttgart/citydoctor2/webservice/endpoints/LoginValues.java @@ -0,0 +1,30 @@ +package de.hft.stuttgart.citydoctor2.webservice.endpoints; + +public class LoginValues { + + private String token; + private int id; + + public LoginValues(String token, int id) { + super(); + this.token = token; + this.id = id; + } + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorWebService/src/test/java/de/hft/stuttgart/citydoctor2/webservice/endpoints/ModelsEndpointTest.java b/CityDoctorParent/Extensions/CityDoctorWebService/src/test/java/de/hft/stuttgart/citydoctor2/webservice/endpoints/ModelsEndpointTest.java new file mode 100644 index 0000000000000000000000000000000000000000..926db50c116f8af89b81eb14ae3d8d3d995ca913 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorWebService/src/test/java/de/hft/stuttgart/citydoctor2/webservice/endpoints/ModelsEndpointTest.java @@ -0,0 +1,136 @@ +package de.hft.stuttgart.citydoctor2.webservice.endpoints; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; + +import javax.ws.rs.core.HttpHeaders; + +import org.apache.http.HttpResponse; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.mime.HttpMultipartMode; +import org.apache.http.entity.mime.MultipartEntityBuilder; +import org.apache.http.impl.client.HttpClients; +import org.json.JSONArray; +import org.json.JSONObject; +import org.json.JSONTokener; +import org.junit.Ignore; +import org.junit.Test; + +public class ModelsEndpointTest { + + @Test + public void testRetrievingModels() throws ClientProtocolException, IOException { + HttpClient client = HttpClients.createMinimal(); + LoginValues login = TestUtils.login(client); + + HttpGet get = new HttpGet("http://localhost:8080/CityDoctorWebService/rest/models"); + get.addHeader(HttpHeaders.AUTHORIZATION, "Bearer " + login.getToken()); + + HttpResponse response = client.execute(get); + + assertEquals(200, response.getStatusLine().getStatusCode()); + JSONTokener tokener = TestUtils.tokenizeReponse(response); + JSONArray models = new JSONArray(tokener); + + for (Object o : models) { + assertTrue(o instanceof JSONObject); + } + assertNotNull(models); + + } + + @Test + public void testUploadModel() throws ClientProtocolException, IOException { + HttpClient client = HttpClients.createMinimal(); + LoginValues login = TestUtils.login(client); + + HttpPost post = new HttpPost("http://localhost:8080/CityDoctorWebService/rest/models"); + post.addHeader(HttpHeaders.AUTHORIZATION, "Bearer " + login.getToken()); + File file = new File("C:\\Job\\CityGML Files\\1-stoeckach_multisurface_only.xml"); +// File configFile = new File("src\\test\\resources\\testConfig.yml"); + MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create(); + entityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); + entityBuilder.addBinaryBody("file", file); +// entityBuilder.addBinaryBody("configFile", configFile); + post.setEntity(entityBuilder.build()); + + HttpResponse response = client.execute(post); + int httpStatus = response.getStatusLine().getStatusCode(); + assertEquals(200, httpStatus); + JSONTokener tokener = TestUtils.tokenizeReponse(response); + JSONObject model = new JSONObject(tokener); + assertNotNull(model); + assertEquals("1-stoeckach_multisurface_only.xml", model.getString("name")); + } + + @Ignore + @Test + public void downloadPdfFile() throws ClientProtocolException, IOException { + HttpClient client = HttpClients.createMinimal(); + LoginValues login = TestUtils.login(client); + + HttpGet get = new HttpGet( + "http://localhost:8080/CityDoctorWebService/rest/" + login.getId() + "/models/15/pdf"); + get.addHeader(HttpHeaders.AUTHORIZATION, "Bearer " + login.getToken()); + + HttpResponse response = client.execute(get); + + assertEquals(200, response.getStatusLine().getStatusCode()); + + Path path = Files.createTempFile(null, null); + Files.copy(response.getEntity().getContent(), path, StandardCopyOption.REPLACE_EXISTING); + assertTrue(path.toFile().exists()); + } + + @Ignore + @Test + public void downloadXmlFile() throws ClientProtocolException, IOException { + HttpClient client = HttpClients.createMinimal(); + LoginValues login = TestUtils.login(client); + + HttpGet get = new HttpGet( + "http://localhost:8080/CityDoctorWebService/rest/" + login.getId() + "/models/15/xml"); + get.addHeader(HttpHeaders.AUTHORIZATION, "Bearer " + login.getToken()); + + HttpResponse response = client.execute(get); + + assertEquals(200, response.getStatusLine().getStatusCode()); + + Path path = Files.createTempFile(null, null); + Files.copy(response.getEntity().getContent(), path, StandardCopyOption.REPLACE_EXISTING); + assertTrue(path.toFile().exists()); + } + + @Test + public void testGetBuildings() throws ClientProtocolException, IOException { + HttpClient client = HttpClients.createMinimal(); + LoginValues login = TestUtils.login(client); + + HttpGet get = new HttpGet("http://localhost:8080/CityDoctorWebService/rest/models/5/buildings?from=0"); + get.addHeader(HttpHeaders.AUTHORIZATION, "Bearer " + login.getToken()); + + HttpResponse response = client.execute(get); + + String readCompleteReponse = TestUtils.readCompleteReponse(response); + System.out.println(readCompleteReponse); + +// JSONTokener tokener = TestUtils.tokenizeReponse(response); +// JSONArray models = new JSONArray(tokener); + +// for (Object o : models) { +// System.out.println(o); +// } + + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorWebService/src/test/java/de/hft/stuttgart/citydoctor2/webservice/endpoints/RegisterEndpointTest.java b/CityDoctorParent/Extensions/CityDoctorWebService/src/test/java/de/hft/stuttgart/citydoctor2/webservice/endpoints/RegisterEndpointTest.java new file mode 100644 index 0000000000000000000000000000000000000000..e9fcb9c6803433219dc51258222bbaf331818698 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorWebService/src/test/java/de/hft/stuttgart/citydoctor2/webservice/endpoints/RegisterEndpointTest.java @@ -0,0 +1,58 @@ +package de.hft.stuttgart.citydoctor2.webservice.endpoints; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import javax.persistence.EntityManager; + +import org.apache.http.HttpResponse; +import org.apache.http.NameValuePair; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.HttpClient; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.message.BasicNameValuePair; +import org.junit.Test; + +import de.hft.stuttgart.citydoctor2.webservice.database.UserQueries; +import de.hft.stuttgart.citydoctor2.webservice.utils.HibernateUtils; + +public class RegisterEndpointTest { + + @Test + public void testRegisterExistingUser() throws ClientProtocolException, IOException { + HttpClient client = HttpClients.createMinimal(); + HttpPost post = new HttpPost("http://localhost:8080/CityDoctorWebService/rest/register"); + + List params = new ArrayList(2); + params.add(new BasicNameValuePair("username", "Test")); + params.add(new BasicNameValuePair("password", "TestPassword")); + post.setEntity(new UrlEncodedFormEntity(params, "UTF-8")); + + HttpResponse response = client.execute(post); + assertEquals(409, response.getStatusLine().getStatusCode()); + } + + @Test + public void testRegisterNewUser() throws ClientProtocolException, IOException { + HttpClient client = HttpClients.createMinimal(); + HttpPost post = new HttpPost("http://localhost:8080/CityDoctorWebService/rest/register"); + + List params = new ArrayList(2); + params.add(new BasicNameValuePair("username", "TestNotExisting")); + params.add(new BasicNameValuePair("password", "TestPassword")); + post.setEntity(new UrlEncodedFormEntity(params, "UTF-8")); + + HttpResponse response = client.execute(post); + assertEquals(200, response.getStatusLine().getStatusCode()); + + EntityManager manager = HibernateUtils.createManager(); + UserQueries.deleteUser(UserQueries.getUserForUsername("TestNotExisting", manager), manager); + manager.close(); + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorWebService/src/test/java/de/hft/stuttgart/citydoctor2/webservice/endpoints/TestUtils.java b/CityDoctorParent/Extensions/CityDoctorWebService/src/test/java/de/hft/stuttgart/citydoctor2/webservice/endpoints/TestUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..caa783887e27e9f677ecb1043071f67a06495d57 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorWebService/src/test/java/de/hft/stuttgart/citydoctor2/webservice/endpoints/TestUtils.java @@ -0,0 +1,62 @@ +package de.hft.stuttgart.citydoctor2.webservice.endpoints; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; + +import org.apache.http.HttpResponse; +import org.apache.http.NameValuePair; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.HttpClient; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.message.BasicNameValuePair; +import org.json.JSONException; +import org.json.JSONObject; +import org.json.JSONTokener; + +public class TestUtils { + + private TestUtils() { + // only static use + } + + public static LoginValues login(HttpClient client) throws ClientProtocolException, IOException { + HttpPost post = new HttpPost("http://localhost:8080/CityDoctorWebService/rest/login"); + + List params = new ArrayList<>(2); + params.add(new BasicNameValuePair("username", "Test")); + params.add(new BasicNameValuePair("password", "TestPassword")); + post.setEntity(new UrlEncodedFormEntity(params, "UTF-8")); + + HttpResponse response = client.execute(post); + String text = readCompleteReponse(response); + try { + JSONTokener tokener = new JSONTokener(text); + JSONObject o = new JSONObject(tokener); + String token = o.getString("token"); + int id = o.getInt("userId"); + return new LoginValues(token, id); + } catch (JSONException e) { + System.out.println(text); + throw e; + } + } + + public static String readCompleteReponse(HttpResponse response) throws IOException { + InputStreamReader reader = new InputStreamReader(response.getEntity().getContent()); + char[] buffer = new char[1000]; + int readChars = -1; + StringBuilder sb = new StringBuilder(); + while ((readChars = reader.read(buffer)) != -1) { + sb.append(buffer, 0, readChars); + } + return sb.toString(); + } + + public static JSONTokener tokenizeReponse(HttpResponse response) throws IOException { + return new JSONTokener(readCompleteReponse(response)); + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorWebService/src/test/java/de/hft/stuttgart/citydoctor2/webservice/endpoints/ValidationEndpointTest.java b/CityDoctorParent/Extensions/CityDoctorWebService/src/test/java/de/hft/stuttgart/citydoctor2/webservice/endpoints/ValidationEndpointTest.java new file mode 100644 index 0000000000000000000000000000000000000000..8bd5d74e447c2b113fd8e3d0534b7b3f069919a3 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorWebService/src/test/java/de/hft/stuttgart/citydoctor2/webservice/endpoints/ValidationEndpointTest.java @@ -0,0 +1,49 @@ +package de.hft.stuttgart.citydoctor2.webservice.endpoints; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; + +import javax.ws.rs.core.HttpHeaders; + +import org.apache.http.HttpResponse; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.HttpClients; +import org.junit.Test; + +public class ValidationEndpointTest { + + @Test + public void testRetrieveXmlReport() throws ClientProtocolException, IOException { + HttpClient client = HttpClients.createMinimal(); + LoginValues login = TestUtils.login(client); + + HttpGet get = new HttpGet("http://localhost:8080/CityDoctorWebService/rest/models/validations/5/xml"); + get.addHeader(HttpHeaders.AUTHORIZATION, "Bearer " + login.getToken()); + + HttpResponse response = client.execute(get); + File file = new File("C:/WebService/test.xml"); + Files.copy(response.getEntity().getContent(), file.toPath(), StandardCopyOption.REPLACE_EXISTING); + assertTrue(file.exists()); + } + + @Test + public void testRetrievePdfReport() throws ClientProtocolException, IOException { + HttpClient client = HttpClients.createMinimal(); + LoginValues login = TestUtils.login(client); + + HttpGet get = new HttpGet("http://localhost:8080/CityDoctorWebService/rest/models/validations/5/pdf"); + get.addHeader(HttpHeaders.AUTHORIZATION, "Bearer " + login.getToken()); + + HttpResponse response = client.execute(get); + File file = new File("C:/WebService/test.pdf"); + Files.copy(response.getEntity().getContent(), file.toPath(), StandardCopyOption.REPLACE_EXISTING); + assertTrue(file.exists()); + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorWebService/src/test/resources/testConfig.yml b/CityDoctorParent/Extensions/CityDoctorWebService/src/test/resources/testConfig.yml new file mode 100644 index 0000000000000000000000000000000000000000..04f23f4cdaec5bdb48f78d691ec3b719a20675e5 --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorWebService/src/test/resources/testConfig.yml @@ -0,0 +1,45 @@ +minVertexDistance: 1.0E-4 +useStreaming: false +xmlValidation: false +checks: + C_GE_R_TOO_FEW_POINTS: + enabled: true + C_GE_R_NOT_CLOSED: + enabled: true + C_GE_R_DUPLICATE_POINT: + enabled: true + C_GE_R_SELF_INTERSECTION: + enabled: true + C_GE_S_MULTIPLE_CONNECTED_COMPONENTS: + enabled: true + C_GE_P_INTERIOR_DISCONNECTED: + enabled: true + C_GE_P_INTERSECTING_RINGS: + enabled: true + C_GE_P_NON_PLANAR: + enabled: false + parameters: + # one of ("distance", "angle", "both") + type: distance + distanceTolerance: 0.01 + angleTolerance: 0.1 + C_GE_P_HOLE_OUTSIDE: + enabled: true + C_GE_P_ORIENTATION_RINGS_SAME: + enabled: true + C_GE_P_INNER_RINGS_NESTED: + enabled: true + C_GE_S_TOO_FEW_POLYGONS: + enabled: true + C_GE_S_NOT_CLOSED: + enabled: true + C_GE_S_NON_MANIFOLD_EDGE: + enabled: true + C_GE_S_POLYGON_WRONG_ORIENTATION: + enabled: true + C_GE_S_ALL_POLYGONS_WRONG_ORIENTATION: + enabled: true + C_GE_S_NON_MANIFOLD_VERTEX: + enabled: true + C_GE_S_SELF_INTERSECTION: + enabled: true \ No newline at end of file diff --git a/CityDoctorParent/Extensions/README.md b/CityDoctorParent/Extensions/README.md new file mode 100644 index 0000000000000000000000000000000000000000..b81834c5a81558fc9d2d42530edf30bf8716f974 --- /dev/null +++ b/CityDoctorParent/Extensions/README.md @@ -0,0 +1,139 @@ +# CityDoctor2 Extensions +Extension modules to the core functionality of CityDoctor2. + +# Loading + +Except for CityDoctorGUI, all extension modules are not loaded into the Maven project by default. +Loading an extension module can be done by either loading the Maven module directly, or by adjusting the CityDoctorParent +pom.xml and moving the respective modules out of the comment-block in the module list found at the end of the file. + +# Building + +If the modules are loaded by including them in the CityDoctorParent pom, Maven will +automatically build them while building CityDoctor2. +If the modules are loaded directly, they need to be built directly with Maven. + +After building, the jars can be found in the **/target** subdirectory of each respective extension module. + +# Module Information + +## CityDoctorAutoPro + +![Maintenance Level: Deprecated](../resources/Badges/MaintenanceLevel_Deprecated.svg) + +The AutoPro (short for automated processing) module is an interface for the conversion of the internal data model to a C++ +representation, to allow use of advanced functionalities of CGAL with CityDoctor2. + +### Usage + +> ⚠ The AutoPro module is deprecated and will be removed in a future release, once the CGAL functionalities have been ported to Java. + +AutoPro requires a collection of .dll-files to run, some of which are not available as FOSS and thus cannot be +distributed with this project. +Access to the collection, or information about the required .dll-files, can be granted upon request for a valid reason. +Contact a Maintainer of this project for further information in this regard. + +--- + +## CityDoctorGUI +![Maintenance Level: Actively Maintained](../resources/Badges/MaintenanceLevel_ActivelyMaintained.svg) + +The GUI module offers a graphical user interface for CityDoctor2, including a model viewer allowing for visual +inspection of validation results and found errors. + +### View-Plugins + +The GUI is expandable via plugins, enabling the creation of views for custom functionalities or extensions of the CityDoctor2 core. +Custom views can be created by extending the Abstract class `View` of the CityDoctorGUI and need to be registered by calling +`ViewRegistration.registerView(View view);` before starting the GUI. + +### Usage + +> ⚠ CityDoctorGUI requires a JDK/JRE containing the JavaFX library to run. + +Prebuilt binaries for the GUI are available in [CityDoctorReleases](https://transfer.hft-stuttgart.de/gitlab/citydoctor/citydoctorreleases). +After extracting the archive the GUI can be started with **start.bat**. + +Binaries can be built with Maven using the create-binaries profile from the CityDoctorParent directory: +``` +mvn install -P create-binaries +``` + +Lastly, the GUI can also be started by calling `MainWindow.main(args[])`. + +--- + +## CityDoctorHealer +![Maintenance Level: Inactively Maintained](../resources/Badges/MaintenanceLevel_InactivelyMaintained.svg) + +CityDoctorHealer implements functionalities for the automated repair of geometries containing errors. +The healer uses naive approaches to fix geometrical errors, and thus, it cannot be guaranteed that semantical +correctness is maintained after the healing process. + + +### Usage + +Usage of CityDoctorHealer is similar to [CityDoctor](https://transfer.hft-stuttgart.de/gitlab/citydoctor/citydoctor2/-/tree/dev_GUI#usage). +An example start command looks like this: +``` +java -classpath libs/*;plugins/*;CityDoctorHealer-.jar de.hft.stuttgart.citydoctor2.CityDoctorHealer -in .gml -config .yml -xmlReport .xml -pdfReport .pdf -out .gml +``` +Note: Unlike CityDoctor core, the _-out_ argument is required. +The -xml-output and -pdfReport arguments are still optional. + +To prevent infinite loops the `Healer` class has a limit for the number of healing iterations (default: 200). This limit +can be changed by calling `Healer.setNumberOfIterations(int limit)`. + +--- + +## CityDoctorHealerGenetic +![Maintenance Level: Abandoned](../resources/Badges/MaintenanceLevel_Abandoned.svg) + +CityDoctorHealerGenetic uses a genetical algorithm to establish an optimal CityDoctorHealer healing-plan for geometries containing errors. + +### Usage +> ⚠ This module has been abandoned. As of writing the module is still functional, but it may break at any time. +>Issues, bug reports and suggestions for this module will not be processed. Use at your own discretion. + +Usage is nearly identical to CityDoctorHealer, only requiring changing the classpath to the HealerGenetic jar. + +A View for usage with CityDoctorGUI is included. + +--- + +## CityDoctorHealerGUI + +![Maintenance Level: Inactively Maintained](../resources/Badges/MaintenanceLevel_InactivelyMaintained.svg) + +CityDoctorGUI-view for CityDoctorHealer. Allows fine control over the automated healing steps, including a preview of the +result of each healing step. + +### Usage + +See [CityDoctorGUI View-plugins](#view-plugins) + +--- + +## CityDoctorWebService +![Maintenance Level: Abandoned](../resources/Badges/MaintenanceLevel_Abandoned.svg) + +Contains a web service implementation for CityDoctor2. + +### Usage +> ⚠ This module has been abandoned. As of writing the module is still functional, but it may break at any time. +>Issues, bug reports and suggestions for this module will not be processed. Use at your own discretion. + +> ⚠ CityDoctorWebservice requires connection to a PostgreSQL Server. Connection parameters need to be set in the +pgpass.conf file found in the /DBScripts directory. +> +The PostgreSQL Server needs to contain a database called "CityDoctorDB" with a schema called "citydoctordb". +The required tables will be automatically created by the web service if they're missing. + +To run the web service, build the module and [deploy CityDoctorWebService.war](https://tomcat.apache.org/tomcat-9.0-doc/deployer-howto.html) +to a Tomcat server (version 8 or 9). + +--- + + +## License +[LGPL](http://www.gnu.org/licenses/lgpl-3.0.de.html) diff --git a/CityDoctorParent/pom.xml b/CityDoctorParent/pom.xml index 356a8cd9f4cfa4f7c87a2baaffe242896bb79269..1b8d4cacae0052a0812e2d1e466e93527ae300a3 100644 --- a/CityDoctorParent/pom.xml +++ b/CityDoctorParent/pom.xml @@ -1,220 +1,277 @@ - - 4.0.0 - de.hft.stuttgart - CityDoctorParent - 3.14.1 - pom - CityDoctorParent - - UTF-8 - 17 - 17 - 2.18.0 - ${project.version} - ${project.baseUri}../non-maven-libs - 17.0.10 - ${jre-version-short}+13 - - - - non-maven-libs - ${nonMavenLibsPath} - - - sonartype - https://oss.sonatype.org/content/repositories/snapshots/ - - - - - - - org.apache.maven.plugins - maven-surefire-plugin - 2.22.0 - - false - - **/SolidSelfIntCheckFalsePositiveBigMeshTest.java - - - - - - - - - - org.openjfx - javafx-controls - 17.0.2 - - - org.openjfx - javafx-fxml - 17.0.2 - - - org.openjfx - javafx-swing - 17.0.2 - - - de.hft.stuttgart - CityDoctorModel - ${revision} - - - de.hft.stuttgart - CityDoctorAutoPro - ${revision} - - - de.hft.stuttgart - CityDoctorValidation - ${revision} - - - de.hft.stuttgart - CityDoctorGUI - ${revision} - - - de.hft.stuttgart - CityDoctorEdge - ${revision} - - - de.hft.stuttgart - CityDoctorCheckResult - ${revision} - - - de.hft.stuttgart - CityDoctorHealer - ${revision} - - - net.sf.saxon - Saxon-HE - 12.2 - - - org.hibernate - hibernate-core - 5.6.9.Final - - - org.citygml4j - citygml4j-core - 3.2.0 - - - org.citygml4j - citygml4j-xml - 3.2.0 - - - de.hft.stuttgart - citygml4j-quality-ade - 3.2.0 - - - org.apache.xmlgraphics - fop - 2.7 - - - org.jdom - jdom2 - 2.0.6.1 - - - junit - junit - 4.13.2 - test - - - org.jogamp.gluegen - gluegen-rt-main - 2.3.2 - - - gov.nist.math - jama - 1.0.3 - - - org.jogamp.jogl - jogl-all-main - 2.3.2 - - - org.apache.logging.log4j - log4j-api - ${log4j.version} - - - org.apache.logging.log4j - log4j-core - ${log4j.version} - - - org.apache.logging.log4j - log4j-jul - ${log4j.version} - - - org.yaml - snakeyaml - 1.30 - - - org.apache.logging.log4j - log4j-slf4j18-impl - ${log4j.version} - - - org.locationtech.proj4j - proj4j - 1.1.5 - - - org.hibernate - hibernate-search-orm - 5.11.9.Final - - - org.locationtech.jts - jts-core - 1.19.0 - - - com.sun.xml.bind - jaxb-impl - 2.3.3 - - - jakarta.xml.bind - jakarta.xml.bind-api - 2.3.3 - - - - - - org.mockito - mockito-core - 4.6.1 - test - - - - CityDoctorModel - CityDoctorValidation - CityDoctorEdge - CityDoctorCheckResult - + + 4.0.0 + de.hft.stuttgart + CityDoctorParent + 3.14.1 + pom + CityDoctorParent + + UTF-8 + 17 + 17 + 2.18.0 + ${project.version} + ${project.baseUri}../non-maven-libs + 17.0.10 + ${jre-version-short}+13 + + + + non-maven-libs + ${nonMavenLibsPath} + + + sonartype + https://oss.sonatype.org/content/repositories/snapshots/ + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.0 + + false + + **/SolidSelfIntCheckFalsePositiveBigMeshTest.java + + + + + + + + maven-compiler-plugin + 3.13.0 + + true + true + + + + org.codehaus.plexus + plexus-compiler-api + 2.15.0 + + + org.codehaus.plexus + plexus-compiler-manager + 2.15.0 + + + org.codehaus.plexus + plexus-compiler-eclipse + 2.15.0 + + + org.openjfx + javafx-maven-plugin + 0.0.8 + + + + + + + org.openjfx + javafx-controls + 17.0.2 + + + org.openjfx + javafx-fxml + 17.0.2 + + + org.openjfx + javafx-swing + 17.0.2 + + + de.hft.stuttgart + CityDoctorModel + ${revision} + + + de.hft.stuttgart + CityDoctorAutoPro + ${revision} + + + de.hft.stuttgart + CityDoctorValidation + ${revision} + + + de.hft.stuttgart + CityDoctorGUI + ${revision} + + + de.hft.stuttgart + CityDoctorEdge + ${revision} + + + de.hft.stuttgart + CityDoctorCheckResult + ${revision} + + + de.hft.stuttgart + CityDoctorHealer + ${revision} + + + net.sf.saxon + Saxon-HE + 12.2 + + + org.hibernate + hibernate-core + 5.6.9.Final + + + org.citygml4j + citygml4j-core + 3.2.0 + + + org.citygml4j + citygml4j-xml + 3.2.0 + + + de.hft.stuttgart + citygml4j-quality-ade + 3.2.0 + + + org.apache.xmlgraphics + fop + 2.7 + + + org.jdom + jdom2 + 2.0.6.1 + + + junit + junit + 4.13.2 + test + + + org.jogamp.gluegen + gluegen-rt-main + 2.3.2 + + + gov.nist.math + jama + 1.0.3 + + + org.jogamp.jogl + jogl-all-main + 2.3.2 + + + org.apache.logging.log4j + log4j-api + ${log4j.version} + + + org.apache.logging.log4j + log4j-core + ${log4j.version} + + + org.apache.logging.log4j + log4j-jul + ${log4j.version} + + + org.yaml + snakeyaml + 2.0 + + + org.apache.logging.log4j + log4j-slf4j18-impl + ${log4j.version} + + + org.locationtech.proj4j + proj4j + 1.1.5 + + + org.hibernate + hibernate-search-orm + 5.11.9.Final + + + org.locationtech.jts + jts-core + 1.19.0 + + + com.sun.xml.bind + jaxb-impl + 2.3.3 + + + jakarta.xml.bind + jakarta.xml.bind-api + 2.3.3 + + + + + + org.mockito + mockito-core + 4.6.1 + test + + + org.openjfx + javafx-controls + 17.0.2 + + + org.openjfx + javafx-fxml + 17.0.2 + + + org.openjfx + javafx-swing + 17.0.2 + + + + + CityDoctorModel + CityDoctorValidation + CityDoctorEdge + CityDoctorCheckResult + + + Extensions/CityDoctorGUI + + \ No newline at end of file diff --git a/CityDoctorParent/resources/Badges/MaintenanceLevel_Abandoned.svg b/CityDoctorParent/resources/Badges/MaintenanceLevel_Abandoned.svg new file mode 100644 index 0000000000000000000000000000000000000000..c677a00663a7501b48860b9ac49e54b6f4901f87 --- /dev/null +++ b/CityDoctorParent/resources/Badges/MaintenanceLevel_Abandoned.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + Maintenance Level + Maintenance Level + + + Abandoned + Abandoned + + diff --git a/CityDoctorParent/resources/Badges/MaintenanceLevel_ActivelyDeveloped.svg b/CityDoctorParent/resources/Badges/MaintenanceLevel_ActivelyDeveloped.svg new file mode 100644 index 0000000000000000000000000000000000000000..63a7480313b7b3ab679cc81bf82a2d1a2911cea1 --- /dev/null +++ b/CityDoctorParent/resources/Badges/MaintenanceLevel_ActivelyDeveloped.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + Maintenance Level + Maintenance Level + + + Actively Developed + Actively Developed + + diff --git a/CityDoctorParent/resources/Badges/MaintenanceLevel_ActivelyMaintained.svg b/CityDoctorParent/resources/Badges/MaintenanceLevel_ActivelyMaintained.svg new file mode 100644 index 0000000000000000000000000000000000000000..7bc745449b0d2d9b24e98035b36da51c4a18d729 --- /dev/null +++ b/CityDoctorParent/resources/Badges/MaintenanceLevel_ActivelyMaintained.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + Maintenance Level + Maintenance Level + + + Actively Maintained + Actively Maintained + + diff --git a/CityDoctorParent/resources/Badges/MaintenanceLevel_Deprecated.svg b/CityDoctorParent/resources/Badges/MaintenanceLevel_Deprecated.svg new file mode 100644 index 0000000000000000000000000000000000000000..20410822ebadc973ba7036a0efecbd3a2a8759db --- /dev/null +++ b/CityDoctorParent/resources/Badges/MaintenanceLevel_Deprecated.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + Maintenance Level + Maintenance Level + + + Deprecated + Deprecated + + diff --git a/CityDoctorParent/resources/Badges/MaintenanceLevel_InactivelyMaintained.svg b/CityDoctorParent/resources/Badges/MaintenanceLevel_InactivelyMaintained.svg new file mode 100644 index 0000000000000000000000000000000000000000..320d7e4a05210c8fb4c0010b360a345a67c7afe9 --- /dev/null +++ b/CityDoctorParent/resources/Badges/MaintenanceLevel_InactivelyMaintained.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + Maintenance Level + Maintenance Level + + + Inactively Maintained + Inactively Maintained + + diff --git a/CityDoctorParent/resources/Badges/MaintenanceLevel_NotMaintained.svg b/CityDoctorParent/resources/Badges/MaintenanceLevel_NotMaintained.svg new file mode 100644 index 0000000000000000000000000000000000000000..b21cd9ea9045cf2cff566c3866421c2495c0fefa --- /dev/null +++ b/CityDoctorParent/resources/Badges/MaintenanceLevel_NotMaintained.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + Maintenance Level + Maintenance Level + + + Not Maintained + Not Maintained + + diff --git a/CityDoctorParent/resources/Badges/MaintenanceLevel_Obsolete.svg b/CityDoctorParent/resources/Badges/MaintenanceLevel_Obsolete.svg new file mode 100644 index 0000000000000000000000000000000000000000..f26fd5a62ba1c4cb5c6d494eb868866737b0f345 --- /dev/null +++ b/CityDoctorParent/resources/Badges/MaintenanceLevel_Obsolete.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + Maintenance Level + Maintenance Level + + + Obsolete + Obsolete + + diff --git a/CityDoctorParent/resources/Badges/Project_CD2.svg b/CityDoctorParent/resources/Badges/Project_CD2.svg new file mode 100644 index 0000000000000000000000000000000000000000..1d815f5deb72137434db4627663bf9842bb4e296 --- /dev/null +++ b/CityDoctorParent/resources/Badges/Project_CD2.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + Project + + + CityDoctor2 + + diff --git a/CityDoctorParent/resources/Badges/Project_UDigiT.svg b/CityDoctorParent/resources/Badges/Project_UDigiT.svg new file mode 100644 index 0000000000000000000000000000000000000000..611334399064639a773421db2e1a1711152810e1 --- /dev/null +++ b/CityDoctorParent/resources/Badges/Project_UDigiT.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + Project + + + UDigiT-Doctor + + diff --git a/README.md b/README.md index de178766a3cda9189d584dcfdbc9a1c80082a7a9..7b9a843a3250a4a51c6318487f2eb91e1cd4192c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # CityDoctor2 -[![pipeline status](https://transfer.hft-stuttgart.de/gitlab/betzms/citydoctor2/badges/master/pipeline.svg)](https://transfer.hft-stuttgart.de/gitlab/betzms/citydoctor2/-/commits/master) +[![pipeline status](https://transfer.hft-stuttgart.de/gitlab/betzms/citydoctor2/badges/master/pipeline.svg)](https://transfer.hft-stuttgart.de/gitlab/betzms/citydoctor2/-/commits/master) ![Maintenance Level: Actively Developed](/CityDoctorParent/resources/Badges/MaintenanceLevel_ActivelyDeveloped.svg) CityDoctor2 is a Java program for validating CityGML files. It checks whether certain criteria for e.g. geometries are met and outputs a report on the results. @@ -42,6 +42,10 @@ java -classpath libs/*;plugins/*;CityDoctorValidation-.jar de.hft.stutt Note: -xmlReport, -pdfReport and -out are optional +## Extension + +Example extensions for CityDoctor are included in this repository, and can be found in the [Extensions subdirectory](./CityDoctorParent/Extensions) +alongside a short description for each respective extension. ## License [LGPL](http://www.gnu.org/licenses/lgpl-3.0.de.html)