diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 695773f95d7cee421ca24b375869f620774595b9..33fe14f5e7dd8c7b95ed9dd470b5e47e25267142 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,4 @@ -image: maven:3.8.4-openjdk-17 +image: maven:3.8.6-eclipse-temurin-17 build: diff --git a/CityDoctorParent/CityDoctorCheckResult/pom.xml b/CityDoctorParent/CityDoctorCheckResult/pom.xml index 2de985b10767bfedeb28e0e6cb5d1efcf32ecf7a..641786f133df196ceb941ccf29a2fc6dfe5b6340 100644 --- a/CityDoctorParent/CityDoctorCheckResult/pom.xml +++ b/CityDoctorParent/CityDoctorCheckResult/pom.xml @@ -1,6 +1,6 @@ <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> + xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>de.hft.stuttgart</groupId> diff --git a/CityDoctorParent/CityDoctorEdge/pom.xml b/CityDoctorParent/CityDoctorEdge/pom.xml index 1413e31df97362897368372a94fb193fec2b2876..25adedb0491a5dabdd198f78bfabc0f5fde85c4b 100644 --- a/CityDoctorParent/CityDoctorEdge/pom.xml +++ b/CityDoctorParent/CityDoctorEdge/pom.xml @@ -1,6 +1,6 @@ <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> + xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>de.hft.stuttgart</groupId> diff --git a/CityDoctorParent/CityDoctorModel/pom.xml b/CityDoctorParent/CityDoctorModel/pom.xml index a6f0cb21457a4247ece3c8506536f3be7a950a16..90bf87b2bcba0d57a45a62ca8bbc2092e78ad01d 100644 --- a/CityDoctorParent/CityDoctorModel/pom.xml +++ b/CityDoctorParent/CityDoctorModel/pom.xml @@ -1,4 +1,4 @@ -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>de.hft.stuttgart</groupId> 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 85cd9cfa25c43110652c3e054568f8400fc37eeb..64fae306767dea1f8b5fc492aaf9cdd9e96ec38c 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 @@ -38,6 +38,8 @@ import de.hft.stuttgart.citydoctor2.datastructure.LandObject; import de.hft.stuttgart.citydoctor2.datastructure.LinearRing; 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.WaterObject; @@ -301,6 +303,14 @@ public abstract class Check { */ public void check(LinearRing ring) { + } + + public void check(TinObject tin) { + + } + + public void check(ReliefObject relief) { + } /** 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 5865bc82f60b14aa25382d2ed07c5c4d7cf40ed5..c95196131bb62afc720a588b4672ce7395fafbf8 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 @@ -56,7 +56,7 @@ public class CityDoctorModel { private List<Building> buildings; private List<Vegetation> vegetation; private List<BridgeObject> bridges; - private List<LandObject> land; + private List<CityObject> land; private List<TransportationObject> roads; private List<WaterObject> water; private CityModel cModel; @@ -260,7 +260,7 @@ public class CityDoctorModel { return water; } - public List<LandObject> getLand() { + public List<CityObject> getLand() { return land; } @@ -369,6 +369,10 @@ public class CityDoctorModel { land.add(lo); } else if (co instanceof WaterObject wo) { water.add(wo); + } else if (co instanceof ReliefObject) { + land.add(co); + } else if (co instanceof TinObject) { + land.add(co); } } @@ -379,4 +383,12 @@ public class CityDoctorModel { public CityGMLVersion getCityGMLVersion() { return cityGMLVersion; } + + public void addRelief(ReliefObject relief) { + addCityObject(relief); + } + + public void addTin(TinObject tin) { + addCityObject(tin); + } } 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 new file mode 100644 index 0000000000000000000000000000000000000000..8fab1029fec8c81423569b1001f86da0259a8fc8 --- /dev/null +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/ReliefObject.java @@ -0,0 +1,157 @@ +/*- + * 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 <https://www.gnu.org/licenses/>. + */ +package de.hft.stuttgart.citydoctor2.datastructure; + +import java.util.ArrayList; +import java.util.List; + +import org.citygml4j.core.model.relief.ReliefFeature; +import org.citygml4j.core.util.geometry.GeometryFactory; + +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.CopyHandler; +import de.hft.stuttgart.citydoctor2.utils.Copyable; + +public class ReliefObject extends CityObject { + + private static final long serialVersionUID = -9162169874426519903L; + + private ReliefFeature feature; + + private List<TinObject> components = new ArrayList<>(); + + public ReliefObject(ReliefFeature feature) { + this.feature = feature; + } + + @Override + public void accept(Check c) { + super.accept(c); + if (c.canExecute(this)) { + c.check(this); + } + for (TinObject tin : components) { + tin.accept(c); + } + } + + @Override + public void collectInstances(CopyHandler handler) { + handler.addInstance(components); + } + + @Override + public void fillValues(Copyable original, CopyHandler handler) { + super.fillValues(original, handler); + ReliefObject originalRelief = (ReliefObject) original; + for (TinObject tin : originalRelief.components) { + components.add(handler.getCopyInstance(tin)); + } + } + + @Override + public Copyable createCopyInstance() { + return new ReliefObject(feature); + } + + @Override + public void prepareForChecking() { + for (TinObject component : components) { + component.prepareForChecking(); + } + } + + @Override + public void clearMetaInformation() { + for (TinObject component : components) { + component.clearMetaInformation(); + } + } + + @Override + public void clearAllContainedCheckResults() { + for (TinObject component : components) { + component.clearAllContainedCheckResults(); + } + } + + @Override + public void collectContainedErrors(List<CheckError> errors) { + super.collectContainedErrors(errors); + for (TinObject tin : components) { + tin.collectContainedErrors(errors); + } + } + + @Override + public boolean containsAnyError() { + boolean containsError = super.containsAnyError(); + if (containsError) { + return true; + } + for (TinObject tin : components) { + if (tin.containsAnyError()) { + return true; + } + } + return false; + } + + @Override + public boolean containsError(CheckId checkIdentifier) { + boolean hasError = super.containsError(checkIdentifier); + if (hasError) { + return true; + } + for (TinObject tin : components) { + if (tin.containsError(checkIdentifier)) { + return true; + } + } + return false; + } + + @Override + public void reCreateGeometries(GeometryFactory factory, ParserConfiguration config) { + // no geometries + } + + @Override + public ReliefFeature getGmlObject() { + return feature; + } + + @Override + public void unsetGmlGeometries() { + // no geometries + } + + @Override + public FeatureType getFeatureType() { + return FeatureType.LAND; + } + + public List<TinObject> getComponents() { + return components; + } + +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..b06c1be88f6348a57b170f9d43b34dfced0ebf2d --- /dev/null +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/TinObject.java @@ -0,0 +1,98 @@ +/*- + * 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 <https://www.gnu.org/licenses/>. + */ +package de.hft.stuttgart.citydoctor2.datastructure; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.citygml4j.core.model.relief.TINRelief; +import org.citygml4j.core.util.geometry.GeometryFactory; +import org.xmlobjects.gml.model.geometry.primitives.AbstractRingProperty; +import org.xmlobjects.gml.model.geometry.primitives.Triangle; +import org.xmlobjects.gml.model.geometry.primitives.TriangleArrayProperty; +import org.xmlobjects.gml.model.geometry.primitives.TriangulatedSurface; + +import de.hft.stuttgart.citydoctor2.check.Check; +import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration; +import de.hft.stuttgart.citydoctor2.utils.CityGmlUtils; + +public class TinObject extends CityObject { + + private static final Logger logger = LogManager.getLogger(TinObject.class); + + private static final long serialVersionUID = 1910744427384724422L; + + private TINRelief gmlRelief; + + public TinObject(TINRelief gmlRelief) { + this.gmlRelief = gmlRelief; + } + + @Override + public void accept(Check c) { + super.accept(c); + if (c.canExecute(this)) { + c.check(this); + } + } + + @Override + public TinObject createCopyInstance() { + return new TinObject(gmlRelief); + } + + @Override + public void reCreateGeometries(GeometryFactory factory, ParserConfiguration config) { + if (getGeometries().isEmpty()) { + return; + } + if (getGeometries().size() > 1) { + logger.warn("A TINRelief can only have one geometry but found {}. Using the first geometry found", + getGeometries().size()); + } + Geometry geom = getGeometries().get(0); + List<Triangle> triangles = new ArrayList<>(); + TriangulatedSurface surface = new TriangulatedSurface(); + surface.setPatches(new TriangleArrayProperty(triangles)); + for (Polygon poly : geom.getPolygons()) { + LinearRing ring = poly.getExteriorRing(); + Triangle t = new Triangle(); + t.setExterior(new AbstractRingProperty(CityGmlUtils.createGmlRing(factory, config, ring))); + triangles.add(t); + } + } + + @Override + public TINRelief getGmlObject() { + return gmlRelief; + } + + @Override + public void unsetGmlGeometries() { + gmlRelief.setTin(null); + } + + @Override + public FeatureType getFeatureType() { + return FeatureType.LAND; + } + +} diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/CityGmlUtils.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/CityGmlUtils.java index dbd9463ca1a2e6c284ef7a6c92bb1222046552fa..4337ac3366d35b7766b0d14ea78258852700be61 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/CityGmlUtils.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/CityGmlUtils.java @@ -71,7 +71,7 @@ public final class CityGmlUtils { return gmlPoly; } - private static org.xmlobjects.gml.model.geometry.primitives.LinearRing createGmlRing(GeometryFactory factory, + public static org.xmlobjects.gml.model.geometry.primitives.LinearRing createGmlRing(GeometryFactory factory, ParserConfiguration config, LinearRing lr) { ProjCoordinate p1 = new ProjCoordinate(); ProjCoordinate p2 = new ProjCoordinate(); diff --git a/CityDoctorParent/CityDoctorValidation/pom.xml b/CityDoctorParent/CityDoctorValidation/pom.xml index ab74fb106c45ef5453ae51558f71acd454311272..52504dc2895ea8ea516f1c8491ccb29b9fbb055d 100644 --- a/CityDoctorParent/CityDoctorValidation/pom.xml +++ b/CityDoctorParent/CityDoctorValidation/pom.xml @@ -1,6 +1,6 @@ <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> + xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>de.hft.stuttgart</groupId> 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 921aa3ab38c617731c1f5903c12737a585751873..d88b721002670b3567028913d732d0344c05a900 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 @@ -84,6 +84,7 @@ import de.hft.stuttgart.quality.model.properties.RequirementProperty; import de.hft.stuttgart.quality.model.types.Checking; import de.hft.stuttgart.quality.model.types.Parameter; import de.hft.stuttgart.quality.model.types.ValidationPlan; +import net.sf.saxon.lib.ResourceResolverWrappingURIResolver; import net.sf.saxon.s9api.DOMDestination; import net.sf.saxon.s9api.Destination; import net.sf.saxon.s9api.Processor; @@ -444,14 +445,14 @@ public class Checker { } Processor processor = new Processor(false); XsltCompiler xsltCompiler = processor.newXsltCompiler(); - xsltCompiler.setURIResolver(new URIResolver() { + xsltCompiler.setResourceResolver(new ResourceResolverWrappingURIResolver(new URIResolver() { @Override public Source resolve(String href, String base) throws TransformerException { return new StreamSource(Checker.class.getResourceAsStream(href)); } - }); + })); try { XsltExecutable includeExecutable = xsltCompiler .compile(new StreamSource(Checker.class.getResourceAsStream("iso_dsdl_include.xsl"))); diff --git a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/reporting/XmlValidationReporter.java b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/reporting/XmlValidationReporter.java index 4f848d73a36fd29e8d2aa8d709443d5057f15c42..5fc97f580e375e41bc5324bfa5085f7780e7ad4c 100644 --- a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/reporting/XmlValidationReporter.java +++ b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/reporting/XmlValidationReporter.java @@ -27,7 +27,7 @@ import de.hft.stuttgart.citydoctor2.checks.Checks; import de.hft.stuttgart.citydoctor2.datastructure.BridgeObject; import de.hft.stuttgart.citydoctor2.datastructure.Building; import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel; -import de.hft.stuttgart.citydoctor2.datastructure.LandObject; +import de.hft.stuttgart.citydoctor2.datastructure.CityObject; import de.hft.stuttgart.citydoctor2.datastructure.TransportationObject; import de.hft.stuttgart.citydoctor2.datastructure.Vegetation; import de.hft.stuttgart.citydoctor2.datastructure.WaterObject; @@ -51,7 +51,7 @@ public class XmlValidationReporter implements Reporter { for (TransportationObject to : model.getTransportation()) { streamReporter.report(to); } - for (LandObject lo : model.getLand()) { + for (CityObject lo : model.getLand()) { streamReporter.report(lo); } for (Vegetation v : model.getVegetation()) { diff --git a/CityDoctorParent/pom.xml b/CityDoctorParent/pom.xml index 2928f37033d0307f1be588a1628ece72e5cf65ba..b36076467d3c637037985d2c767f40af7a6b72b5 100644 --- a/CityDoctorParent/pom.xml +++ b/CityDoctorParent/pom.xml @@ -1,4 +1,4 @@ -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>de.hft.stuttgart</groupId> <artifactId>CityDoctorParent</artifactId> @@ -81,13 +81,13 @@ <dependency> <groupId>net.sf.saxon</groupId> <artifactId>Saxon-HE</artifactId> - <version>10.6</version> + <version>11.3</version> </dependency> <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> - <version>5.4.3.Final</version> + <version>5.6.9.Final</version> </dependency> <dependency> <groupId>org.citygml4j</groupId> @@ -108,19 +108,19 @@ <dependency> <groupId>org.apache.xmlgraphics</groupId> <artifactId>fop</artifactId> - <version>2.6</version> + <version>2.7</version> </dependency> <!-- https://mvnrepository.com/artifact/org.jdom/jdom2 --> <dependency> <groupId>org.jdom</groupId> <artifactId>jdom2</artifactId> - <version>2.0.6</version> + <version>2.0.6.1</version> </dependency> <!-- https://mvnrepository.com/artifact/junit/junit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> - <version>4.12</version> + <version>4.13.2</version> <scope>test</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.jogamp.gluegen/gluegen-rt-main --> @@ -144,39 +144,39 @@ <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> - <version>2.17.1</version> + <version>2.17.2</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> - <version>2.17.1</version> + <version>2.17.2</version> </dependency> <dependency> <groupId>org.yaml</groupId> <artifactId>snakeyaml</artifactId> - <version>1.24</version> + <version>1.30</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-slf4j18-impl --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j18-impl</artifactId> - <version>2.17.1</version> + <version>2.17.2</version> </dependency> <dependency> <groupId>org.locationtech.proj4j</groupId> <artifactId>proj4j</artifactId> - <version>1.1.2</version> + <version>1.1.5</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-search-orm</artifactId> - <version>5.11.3.Final</version> + <version>5.11.9.Final</version> </dependency> <dependency> <groupId>org.locationtech.jts</groupId> <artifactId>jts-core</artifactId> - <version>1.18.1</version> + <version>1.19.0</version> </dependency> <dependency> <groupId>com.sun.xml.bind</groupId> @@ -194,7 +194,7 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> - <version>3.8.0</version> + <version>4.6.1</version> <scope>test</scope> </dependency> </dependencies> diff --git a/README.md b/README.md index e0964744e2739e107596d454797e9c8d9bea2f0e..054d8c462847b43a6bf75e6195d578b21a32157d 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,8 @@ CityDoctor2 is a Java program for validating CityGML files. It checks whether ce ## Installation +You can download releases from the BHT page [here](https://projekt.bht-berlin.de/citydoctor2/downloads/) or from a git repository [here](https://gitlab.com/volkercoors/CiD4Sim/-/tree/master/CityDoctorExtension). + Use [Maven](https://maven.apache.org/) to build CityDoctor2. ```bash @@ -28,4 +30,4 @@ Note: ## License -[LGPL](http://www.gnu.org/licenses/lgpl-3.0.de.html) \ No newline at end of file +[LGPL](http://www.gnu.org/licenses/lgpl-3.0.de.html)