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/.gitlab/.gitmessage b/.gitlab/.gitmessage new file mode 100644 index 0000000000000000000000000000000000000000..b9db7232635742a00a55a87d627ca9a9c08ccb7f --- /dev/null +++ b/.gitlab/.gitmessage @@ -0,0 +1,23 @@ +# Title: Summary, imperative, start upper case, don't end with a period +# No more than 50 chars. #### 50 chars is here: # + +# Remember blank line between title and body. + +# Body: Explain *what* and *why* (not *how*). Include task ID (Jira issue). +# Wrap at 72 chars. ################################## which is here: # + + +# At the end: Include Co-authored-by for all contributors. +# Include at least one empty line before it. Format: +# Co-authored-by: name +# +# How to Write a Git Commit Message: +# https://chris.beams.io/posts/git-commit/ +# +# 1. Separate subject from body with a blank line +# 2. Limit the subject line to 50 characters +# 3. Capitalize the subject line +# 4. Do not end the subject line with a period +# 5. Use the imperative mood in the subject line +# 6. Wrap the body at 72 characters +# 7. Use the body to explain what and why vs. how \ No newline at end of file diff --git a/.gitlab/VULNERABILTIY CLASSIFICATION GUIDE.md b/.gitlab/VULNERABILTIY CLASSIFICATION GUIDE.md new file mode 100644 index 0000000000000000000000000000000000000000..e32bb92a3b115ef88c31eea7a5848c0806358391 --- /dev/null +++ b/.gitlab/VULNERABILTIY CLASSIFICATION GUIDE.md @@ -0,0 +1,14 @@ +## Classification Score + +Disclosed vulnerabilities are evaluated by using the [Common Vulnerability Scoring System](https://www.first.org/cvss/v4.0/user-guide). + +The calculator can be found [here](https://www.first.org/cvss/calculator/4.0). + + +## Vulnerability Severities + +**Critical:** ~"Vulnerability::Critical" Vulnerabilities with a Score >= 9, or vulnerabilities which enable remote code execution. + +**High:** ~"Vulnerability::High" Vulnerabilities with a Score >= 5. + +**Minor:** ~"Vulnerability::Minor" Vulnerabilities with a Score < 5, or which require physical access to the system. \ No newline at end of file diff --git a/.gitlab/changelog_config.yml b/.gitlab/changelog_config.yml new file mode 100644 index 0000000000000000000000000000000000000000..f589acdbea3c22d71fa6458d725c5d1718782928 --- /dev/null +++ b/.gitlab/changelog_config.yml @@ -0,0 +1,38 @@ +--- +# Settings for generating changelogs using the GitLab API. See +# https://docs.gitlab.com/ee/api/repositories.html#generate-changelog-data for +# more information. +categories: + added: Added + fixed: Fixed + changed: Changed + deprecated: Deprecated + removed: Removed + security: Security + performance: Performance + other: Other +template: | + {% if categories %} + {% each categories %} + ### {{ title }} ({% if single_change %}1 change{% else %}{{ count }} changes{% end %}) + + {% each entries %} + - [{{ title }}]({{ commit.web_url }})\ + {% if author.credit %} by {{ author.reference }}{% end %}\ + {% if commit.trailers.MR %}\ + ([merge request]({{ commit.trailers.MR }}))\ + {% else %}\ + {% if merge_request %}\ + ([merge request]({{ merge_request.web_url }}))\ + {% end %}\ + {% end %}\ + {% if commit.trailers.EE %}\ + **GitLab Enterprise Edition**\ + {% end %} + + {% end %} + + {% end %} + {% else %} + No changes. + {% end %} diff --git a/.gitlab/issue_templates/bug_report.md b/.gitlab/issue_templates/bug_report.md new file mode 100644 index 0000000000000000000000000000000000000000..621c58ebee00038d465b76581814fb2d1dab3422 --- /dev/null +++ b/.gitlab/issue_templates/bug_report.md @@ -0,0 +1,27 @@ +## Summary + + + +## Steps to reproduce + + + + +## What is the current bug behavior? + + + +## What is the expected correct behavior? + + + +## Relevant logs and/or screenshots + + + +## Possible cause + + + +/label Bug \ No newline at end of file diff --git a/.gitlab/issue_templates/documentation.md b/.gitlab/issue_templates/documentation.md new file mode 100644 index 0000000000000000000000000000000000000000..b30eef6943e227298a771b1cbef0f600d795cf02 --- /dev/null +++ b/.gitlab/issue_templates/documentation.md @@ -0,0 +1,14 @@ +## Short description + + + +## Content + + + +## Location + + + + +/label Type::Documentation \ No newline at end of file diff --git a/.gitlab/issue_templates/feature_request.md b/.gitlab/issue_templates/feature_request.md new file mode 100644 index 0000000000000000000000000000000000000000..877fac13545947228ea48141ede07fb0c792647b --- /dev/null +++ b/.gitlab/issue_templates/feature_request.md @@ -0,0 +1,14 @@ +## Summary + + + +## What is the function? + + + +## Why is it requested? + + + + +/label Type::Feature Request \ No newline at end of file diff --git a/.gitlab/issue_templates/user_story.md b/.gitlab/issue_templates/user_story.md new file mode 100644 index 0000000000000000000000000000000000000000..4bb52398846a795c5d43b8f21a6434a1eb859333 --- /dev/null +++ b/.gitlab/issue_templates/user_story.md @@ -0,0 +1,26 @@ +## Description + + + +**As a:** + +**I want:** + +**So that:** + +## Acceptance Criteria + + + +**Scenario X: Title of scenario** + +--- +**Given** + +**When** + + +**Then** + + +/label Type::Feature Request \ No newline at end of file diff --git a/.gitlab/issue_templates/vulnerability_disclosure.md b/.gitlab/issue_templates/vulnerability_disclosure.md new file mode 100644 index 0000000000000000000000000000000000000000..4dfbd18b2bd8120027a2ff01a245b002fcbe3cce --- /dev/null +++ b/.gitlab/issue_templates/vulnerability_disclosure.md @@ -0,0 +1,28 @@ +## Summary + + + +## Steps to reproduce + + + + +## What is the current bug behavior? + + + +## What is the expected correct behavior? + + + +## Relevant logs and/or screenshots + + + +## Possible cause + + + +/label Type::Bug Vulnerability::Unclassified +/confidential \ No newline at end of file diff --git a/.gitlab/merge_request_templates/Default.md b/.gitlab/merge_request_templates/Default.md new file mode 100644 index 0000000000000000000000000000000000000000..72041d1481f6f9d454eb57280105a2879c5a1172 --- /dev/null +++ b/.gitlab/merge_request_templates/Default.md @@ -0,0 +1,21 @@ + + + +## What does this MR do? + + + + +## Related issues + + + +## Checklist + +- [ ] Commits squashed, following the message-template and containing changelog-trailers +- [ ] MR title and description are up to date, accurate, and descriptive. +- [ ] MR targeting the appropriate branch. +- [ ] Latest Merge Result pipeline is green. + + + diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000000000000000000000000000000000000..fd1b8fe4a3822d0bde27b8da32f40bc11002bf88 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,36 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + + + +## [3.15.0] (2024-09-03) + +### Added (7 changes) + +- Add CityDoctorAutoPro extension. +- Add CityDoctorGUI extension. +- Add CityDoctorHealer extension. +- Add CityDoctorHealerGUI extension. +- Add CityDoctorHealerGenetic extension. +- Add CityDoctorWebService extension. +- Add Documentation for extension modules. + +### Fixed (1 change) + +- Fix false positives for Solid self-intersections. + +### Changed (1 change) + +- Update Maven dependencies: Include JavaFX + +### Security (1 change) + +- Upgrade SnakeYAML to version 2.0 + +## [3.14.0] (2024-03-20) + +Official Release of CityDoctor2 diff --git a/CityDoctorParent/.gitignore b/CityDoctorParent/.gitignore index 42b96a856f86cf4ca1ed9849a11569907105b488..4b263fe597b18a8aebedb41fb1bce0a9ae81729c 100644 --- a/CityDoctorParent/.gitignore +++ b/CityDoctorParent/.gitignore @@ -304,3 +304,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..2f47478c371044b560d62da28cde5412ada2614a 100644 --- a/CityDoctorParent/CityDoctorCheckResult/pom.xml +++ b/CityDoctorParent/CityDoctorCheckResult/pom.xml @@ -1,10 +1,9 @@ - - 4.0.0 + 4.0.0 de.hft.stuttgart CityDoctorParent - 3.14.1 + 3.15.0 CityDoctorCheckResult 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..5161e3ff66325f7d7d362db3072ae5a9a4cf66ec 100644 --- a/CityDoctorParent/CityDoctorEdge/pom.xml +++ b/CityDoctorParent/CityDoctorEdge/pom.xml @@ -1,10 +1,9 @@ - - 4.0.0 + 4.0.0 de.hft.stuttgart CityDoctorParent - 3.14.1 + 3.15.0 CityDoctorEdge 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/DebugUtils.java b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/DebugUtils.java index e165ea445539fa38535b76e77af6dbe7d39829a9..6c46fbe25004449b562b704b61e67abe80db8a00 100644 --- a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/DebugUtils.java +++ b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/DebugUtils.java @@ -210,7 +210,84 @@ public class DebugUtils { System.out.println("CDPolygonNs* p" + counter + " = new CDPolygonNs(coords" + firstListCounter + ");"); return counterArr[0]; } - + + public static void printFPSelfIntersectionTestCaseCode(PolygonPolygonIntersection... intersectionResults){ + for (PolygonPolygonIntersection intersection : intersectionResults) { + printFPSelfIntersectionTestCaseCode(intersection.getPolygon1(), intersection.getPolygon2()); + } + } + + public static void printFPSelfIntersectionTestCaseCode(EdgePolygon polygon1, EdgePolygon polygon2) { + Locale.setDefault(Locale.US); + System.out.println("-----------------------------------------------------"); + System.out.println(""); + + System.out.println("@Test"); + System.out.println("public void testFalsePositiveCASENAME() {"); + printTabbedLine("Geometry geom = new Geometry(GeometryType.SOLID, Lod.LOD1);"); + System.out.println(""); + + printTestCasePolygonCode(polygon1, polygon2); + + + printTabbedLine("CDPolygonNs edgePoly1 = CDPolygonNs.of(p1, new HashMap<>());"); + printTabbedLine("CDPolygonNs edgePoly2 = CDPolygonNs.of(p2, new HashMap<>());"); + printTabbedLine("List intersectPolygons;"); + printTabbedLine("intersectPolygons = IntersectPlanarPolygons.intersectPolygons(edgePoly1, edgePoly2, 0.000001, 0.001);"); + printTabbedLine("assertNotNull(intersectPolygons);"); + printTabbedLine("assertTrue(intersectPolygons.isEmpty());"); + System.out.println(""); + + + printTabbedLine("intersectPolygons = IntersectPlanarPolygons.intersectPolygons(edgePoly2, edgePoly1, 0.000001, 0.001);"); + printTabbedLine("assertNotNull(intersectPolygons);"); + printTabbedLine("assertTrue(intersectPolygons.isEmpty());"); + System.out.println("}"); + } + + private static void printTabbedLine(String line){ + Locale.setDefault(Locale.US); + String format = "\t%s\n"; + System.out.format(format, line); + } + + private static void printTestCasePolygonCode(EdgePolygon polygon1, EdgePolygon polygon2) { + printTabbedLine("Polygon p1 = new ConcretePolygon();"); + printTabbedLine("geom.addPolygon(p1);"); + printTabbedLine("LinearRing ext = new LinearRing(LinearRingType.EXTERIOR);"); + printTabbedLine("p1.setExteriorRing(ext);"); + printTabbedLine("List vertices= new ArrayList<>();"); + printTestCasePolygonVertices(polygon1); + System.out.println(""); + + printTabbedLine("Polygon p2 = new ConcretePolygon();"); + printTabbedLine("geom.addPolygon(p2);"); + printTabbedLine("ext = new LinearRing(LinearRingType.EXTERIOR);"); + printTabbedLine("p2.setExteriorRing(ext);"); + printTabbedLine("vertices= new ArrayList<>();"); + printTestCasePolygonVertices(polygon2); + System.out.println(""); + + } + + private static void printTestCasePolygonVertices(EdgePolygon polygon) { + List coordList = polygon.getCoordinates(); + NumberFormat nf = NumberFormat.getNumberInstance(); + nf.setMaximumFractionDigits(30); + + String vertexFormat = "vertices.add(new Vertex(%s,%s,%s));"; + for (Coordinate3d coordinate3d : coordList) { + Point3d point = coordinate3d.getPoint(); + printTabbedLine(String.format(vertexFormat, + nf.format(point.getX()), nf.format(point.getY()), nf.format(point.getZ()))); + } + // close ring + Point3d point = coordList.get(0).getPoint(); + printTabbedLine(String.format(vertexFormat,point.getX(),point.getY(),point.getZ())); + printTabbedLine("ext.addAllVertices(vertices);"); + } + + public static int printCityDoctorPolygons(Polygon... polygons) { Locale.setDefault(Locale.US); NumberFormat nf = NumberFormat.getNumberInstance(); 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..65d915c58e601b08da03062d7d0e2ce2803a4ef3 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,17 +142,20 @@ 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, List intersections, double epsilon) { // check if both polygons have this point in common if (!sharingBothPolygonsThisPoint(p1, p2, point, epsilon)) { - PolyLine pPL = new PolyLine(new Coordinate3d(point), new Coordinate3d(point)); + Coordinate3d realPointCoordinate = new Coordinate3d(point); + PolyLine pPL = new PolyLine(realPointCoordinate, realPointCoordinate); PolygonPolygonIntersection pPPI = new PolygonPolygonIntersection(p1, p2, pPL); intersections.add(pPPI); } @@ -200,7 +209,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 +247,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 +264,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 +279,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 +288,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 +362,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 +390,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 +460,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 +470,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 +507,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 +577,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 +607,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/PolyLine.java b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/PolyLine.java index 5cea520a3e2673e08e3b537611f8977d7dc7e05f..0a7494eb048f9669316341d8fedf1b2c7664216c 100644 --- a/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/PolyLine.java +++ b/CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/PolyLine.java @@ -79,7 +79,7 @@ public class PolyLine extends BaseEntity { } public boolean isNullLine() { - return isNullLine(0.00); + return isNullLine(0.0000001); } @@ -88,6 +88,13 @@ public class PolyLine extends BaseEntity { if (mpFirst == null || mpLast == null) { return true; } + // Check if same point object is start and end + if (mpFirst == mpLast){ + Point3d start = mpFirst.getStart().getPoint(); + Point3d end = mpLast.getEnd().getPoint(); + // If start- and endpoint same object: -> not null line, intersection on a vertex + if(start == end) return false; + } PolyLineSegment currentSegment = mpFirst; double length = 0.00; // Add length of all segments, starting from mpFirst @@ -108,7 +115,7 @@ public class PolyLine extends BaseEntity { length += segmentLength; } // Check if total length is less than the set tolerance - return length <= tolerance; + return length < tolerance; } 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..3057db767717457c35b29d27c05b51e8111548d9 100644 --- a/CityDoctorParent/CityDoctorModel/pom.xml +++ b/CityDoctorParent/CityDoctorModel/pom.xml @@ -1,10 +1,9 @@ - - 4.0.0 + 4.0.0 de.hft.stuttgart CityDoctorParent - 3.14.1 + 3.15.0 ${project.version}-${git.commit.id.abbrev} 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..c7ce6393bf0481e285124ddb1279d2e9fb315e39 100644 --- a/CityDoctorParent/CityDoctorValidation/pom.xml +++ b/CityDoctorParent/CityDoctorValidation/pom.xml @@ -1,10 +1,9 @@ - - 4.0.0 + 4.0.0 de.hft.stuttgart CityDoctorParent - 3.14.1 + 3.15.0 CityDoctorValidation CityDoctorValidation @@ -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/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..0378a53e3cc9fac98ea1e6b4816ba1040783f30f --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorAutoPro/pom.xml @@ -0,0 +1,55 @@ + + 4.0.0 + + de.hft.stuttgart + CityDoctorParent + 3.15.0 + ../../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..379af8f3b8a53615cd2f18fc1e3e32ea3b97c74e --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/pom.xml @@ -0,0 +1,189 @@ + + 4.0.0 + + de.hft.stuttgart + CityDoctorParent + 3.15.0 + ../../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 @@ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +