Commit 81be0b1d authored by Riegel's avatar Riegel
Browse files

Merge branch 'dev_GUI' into 'dev'

Open source release of CityDoctorGUI and other extensions.

See merge request !6
parents 12d96d95 5a4d0a74
Pipeline #10056 passed with stage
in 1 minute and 6 seconds
package de.hft.stuttgart.citydoctor2.healing;
import java.io.IOException;
import org.junit.Assert;
import org.junit.Test;
import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.Checker;
import de.hft.stuttgart.citydoctor2.check.ValidationConfiguration;
import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.healer.Healer;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException;
import de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException;
public class HealHoleOutsideErrorTest {
@Test
public void testHealHoleOutside() throws CityGmlParseException, IOException, InvalidGmlFileException {
String path = "src/test/resources/SimpleSolid_SrefBS-GE-gml-PO-0004-T0001.gml";
ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
CityDoctorModel model = TestUtil.loadCityModel(path, config);
Checker c = new Checker(config, model);
c.runChecks();
Geometry geom = model.getBuildings().get(0).getGeometries().get(0);
Assert.assertTrue(geom.containsError(CheckId.C_GE_P_HOLE_OUTSIDE));
Healer healer = new Healer(c);
healer.healCityObject(model.getBuildings().get(0));
Assert.assertFalse(geom.containsError(CheckId.C_GE_P_HOLE_OUTSIDE));
}
}
/*-
* 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 <https://www.gnu.org/licenses/>.
*/
package de.hft.stuttgart.citydoctor2.healing;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.citygml4j.core.model.core.AbstractThematicSurface;
import org.citygml4j.core.model.core.CityModel;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.Checker;
import de.hft.stuttgart.citydoctor2.check.ModificationListener;
import de.hft.stuttgart.citydoctor2.check.Requirement;
import de.hft.stuttgart.citydoctor2.check.RequirementConfiguration;
import de.hft.stuttgart.citydoctor2.check.ValidationConfiguration;
import de.hft.stuttgart.citydoctor2.check.error.AttributeMissingError;
import de.hft.stuttgart.citydoctor2.datastructure.BoundarySurface;
import de.hft.stuttgart.citydoctor2.datastructure.Building;
import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel;
import de.hft.stuttgart.citydoctor2.datastructure.ConcretePolygon;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.datastructure.GeometryType;
import de.hft.stuttgart.citydoctor2.datastructure.Installation;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing.LinearRingType;
import de.hft.stuttgart.citydoctor2.datastructure.LinkedPolygon;
import de.hft.stuttgart.citydoctor2.datastructure.Lod;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
import de.hft.stuttgart.citydoctor2.exceptions.CityDoctorWriteException;
import de.hft.stuttgart.citydoctor2.healer.Healer;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParser;
import de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException;
public class HealMissingSolidTest {
@Rule
public TemporaryFolder folder = new TemporaryFolder();
@Test
public void testCreateSolid() throws CityDoctorWriteException, IOException, CityGmlParseException, InvalidGmlFileException {
ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
CityDoctorModel model = new CityDoctorModel(config.getParserConfiguration(), new File("test"));
model.setCityModel(new CityModel());
Building b = new Building();
model.addBuilding(b);
b.setGmlObject(new org.citygml4j.core.model.building.Building());
Geometry geom = new Geometry(GeometryType.MULTI_SURFACE, Lod.LOD2);
b.addGeometry(geom);
ConcretePolygon p1 = new ConcretePolygon();
LinearRing ext1 = createTestRing();
p1.setExteriorRing(ext1);
geom.addPolygon(p1);
BoundarySurface bs1 = new BoundarySurface(mock(AbstractThematicSurface.class));
b.addBoundarySurface(bs1);
Geometry geom2 = new Geometry(GeometryType.MULTI_SURFACE, Lod.LOD2);
bs1.addGeometry(geom2);
ConcretePolygon p2 = new ConcretePolygon();
LinearRing ext2 = createTestRing();
p2.setExteriorRing(ext2);
geom2.addPolygon(p2);
LinkedPolygon p5 = new LinkedPolygon(p2, geom);
geom.addPolygon(p5);
Installation bi = new Installation();
b.addBuildingInstallation(bi);
Geometry geom3 = new Geometry(GeometryType.MULTI_SURFACE, Lod.LOD2);
bi.addGeometry(geom3);
ConcretePolygon p3 = new ConcretePolygon();
LinearRing ext3 = createTestRing();
p3.setExteriorRing(ext3);
geom3.addPolygon(p3);
BoundarySurface bs2 = new BoundarySurface(mock(AbstractThematicSurface.class));
bi.addBoundarySurface(bs2);
Geometry geom4 = new Geometry(GeometryType.MULTI_SURFACE, Lod.LOD2);
bs2.addGeometry(geom4);
ConcretePolygon p4 = new ConcretePolygon();
LinearRing ext4 = createTestRing();
p4.setExteriorRing(ext4);
geom4.addPolygon(p4);
AttributeMissingError err = new AttributeMissingError(b, "", "lod2solid");
HealMissingSolid lodHealer = new HealMissingSolid();
lodHealer.visit(err, mock(ModificationListener.class));
assertEquals(1, b.getGeometries().size());
Geometry geometry = b.getGeometries().get(0);
assertEquals(4, geometry.getPolygons().size());
assertEquals(Lod.LOD2, geometry.getLod());
assertEquals(GeometryType.SOLID, geometry.getType());
int nrOfConcrete = 0;
int nrOfLinks = 0;
for (Polygon p : geometry.getPolygons()) {
if (p.isLink()) {
nrOfLinks++;
} else {
nrOfConcrete++;
}
}
assertEquals(1, nrOfConcrete);
assertEquals(3, nrOfLinks);
File createSolidFile = folder.newFile("createdSolid.gml");
model.saveAs(createSolidFile.toString(), false);
CityDoctorModel parsedModel = CityGmlParser.parseCityGmlFile(createSolidFile.toString(), config.getParserConfiguration());
Building building = parsedModel.getBuildings().get(0);
assertEquals(1, building.getGeometries().size());
Geometry geometry2 = building.getGeometries().get(0);
assertEquals(GeometryType.SOLID, geometry2.getType());
}
private LinearRing createTestRing() {
LinearRing ext = new LinearRing(LinearRingType.EXTERIOR);
ext.addVertex(new Vertex(1, 0, 0));
ext.addVertex(new Vertex(2, 2, 0));
ext.addVertex(new Vertex(3, 4, 0));
ext.addVertex(new Vertex(1, 0, 0));
return ext;
}
@Test
public void testFixingFile() throws CityGmlParseException, InvalidGmlFileException {
ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
config.setSchematronFilePathInGlobalParameters("src/test/resources/schematronTestForMissingSolid.xml");
config.getRequirements().put(Requirement.R_SE_BS_ROOF_UNFRAGMENTED.getId(),
new RequirementConfiguration(false));
CityDoctorModel model = CityGmlParser.parseCityGmlFile("src/test/resources/SimpleSolid_SrefBS_withoutSolid.gml",
config.getParserConfiguration());
Building b = model.getBuildings().get(0);
assertTrue(b.getGeometries().isEmpty());
Checker c = new Checker(config, model);
c.runChecks();
assertTrue(b.containsAnyError());
List<CheckError> errors = new ArrayList<>();
b.collectContainedErrors(errors);
assertEquals(1, errors.size());
CheckError err = errors.get(0);
assertTrue(err instanceof AttributeMissingError);
Healer healer = new Healer(c);
healer.healModel(model);
assertFalse(b.containsAnyError());
Geometry geom = b.getGeometry(GeometryType.SOLID, Lod.LOD2);
assertNotNull(geom);
assertEquals(7, geom.getPolygons().size());
}
}
package de.hft.stuttgart.citydoctor2.healing;
import java.io.IOException;
import org.junit.Assert;
import org.junit.Test;
import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.Checker;
import de.hft.stuttgart.citydoctor2.check.ValidationConfiguration;
import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.healer.Healer;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException;
import de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException;
public class HealNonManifoldEdgeErrorTest {
@Test
public void test() throws CityGmlParseException, IOException, InvalidGmlFileException {
String path = "src/test/resources/SimpleSolid_SrefBS-GE-gml-SO-0004-T0001.gml";
ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
CityDoctorModel model = TestUtil.loadCityModel(path, config);
Checker c = new Checker(config, model);
c.runChecks();
Geometry geom = model.getBuildings().get(0).getGeometries().get(0);
Assert.assertTrue(geom.containsError(CheckId.C_GE_S_NON_MANIFOLD_EDGE));
Healer healer = new Healer(c);
healer.healCityObject(model.getBuildings().get(0));
Assert.assertFalse(geom.containsError(CheckId.C_GE_S_NON_MANIFOLD_EDGE));
}
}
package de.hft.stuttgart.citydoctor2.healing;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.fail;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
import de.hft.stuttgart.citydoctor2.CppInitializer;
import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.CheckId;
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.checks.geometry.PlanarCheck;
import de.hft.stuttgart.citydoctor2.datastructure.Building;
import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel;
import de.hft.stuttgart.citydoctor2.datastructure.ConcretePolygon;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.datastructure.GeometryType;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing.LinearRingType;
import de.hft.stuttgart.citydoctor2.datastructure.Lod;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
import de.hft.stuttgart.citydoctor2.healer.Healer;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException;
import de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException;
public class HealPlanarPolygonErrorTest {
@Test
public void testPlanarPlaneDistance() throws CityGmlParseException, IOException, InvalidGmlFileException {
String path = "src/test/resources/SimpleSolid_SrefBS-GE-gml-PO-0002-T0001.gml";
ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
CityDoctorModel model = TestUtil.loadCityModel(path, config);
Checker c = new Checker(config, model);
c.runChecks();
Geometry geom = model.getBuildings().get(0).getGeometries().get(0);
Assert.assertTrue(geom.containsError(CheckId.C_GE_P_NON_PLANAR));
Healer healer = new Healer(c);
healer.setNumberOfIterations(2);
healer.healCityObject(model.getBuildings().get(0));
Assert.assertFalse(geom.containsError(CheckId.C_GE_P_NON_PLANAR));
}
@Test
public void testNonplanarPolygon() {
CppInitializer.initCpp();
Building b = new Building();
Geometry geom = new Geometry(GeometryType.SOLID, Lod.LOD2);
b.addGeometry(geom);
Vertex v0 = new Vertex(0, 0, 0);
Vertex v1 = new Vertex(4, 0, 0);
Vertex v4 = new Vertex(4, 4, 1);
Vertex v6 = new Vertex(0, 4, 0);
Vertex v8 = new Vertex(4, 0, 4);
Vertex v9 = new Vertex(4, 4, 4);
Vertex v10 = new Vertex(0, 4, 4);
Vertex v11 = new Vertex(0, 0, 5);
Polygon p3 = new ConcretePolygon();
geom.addPolygon(p3);
LinearRing r3 = new LinearRing(LinearRingType.EXTERIOR);
p3.setExteriorRing(r3); // z = 0
r3.addVertex(v0);
r3.addVertex(v1);
r3.addVertex(v4);
r3.addVertex(v6);
r3.addVertex(v0);
Polygon p4 = new ConcretePolygon();
geom.addPolygon(p4);
LinearRing r4 = new LinearRing(LinearRingType.EXTERIOR);
p4.setExteriorRing(r4); // x = 4
r4.addVertex(v1);
r4.addVertex(v8);
r4.addVertex(v9);
r4.addVertex(v4);
r4.addVertex(v1);
Polygon p5 = new ConcretePolygon();
geom.addPolygon(p5);
LinearRing r5 = new LinearRing(LinearRingType.EXTERIOR);
p5.setExteriorRing(r5); // z = 4
r5.addVertex(v8);
r5.addVertex(v11);
r5.addVertex(v10);
r5.addVertex(v9);
r5.addVertex(v8);
Polygon p6 = new ConcretePolygon();
geom.addPolygon(p6);
LinearRing r6 = new LinearRing(LinearRingType.EXTERIOR);
p6.setExteriorRing(r6); // x = 0
r6.addVertex(v0);
r6.addVertex(v6);
r6.addVertex(v10);
r6.addVertex(v11);
r6.addVertex(v0);
Polygon p7 = new ConcretePolygon();
geom.addPolygon(p7);
LinearRing r7 = new LinearRing(LinearRingType.EXTERIOR);
p7.setExteriorRing(r7); // y = 4
r7.addVertex(v4);
r7.addVertex(v9);
r7.addVertex(v10);
r7.addVertex(v6);
r7.addVertex(v4);
Polygon p8 = new ConcretePolygon();
geom.addPolygon(p8);
LinearRing r8 = new LinearRing(LinearRingType.EXTERIOR);
p8.setExteriorRing(r8); // y = 0
r8.addVertex(v0);
r8.addVertex(v11);
r8.addVertex(v8);
r8.addVertex(v1);
r8.addVertex(v0);
geom.updateEdgesAndVertices();
PlanarCheck check = new PlanarCheck();
geom.accept(check);
check.check(geom);
List<CheckError> errors = new ArrayList<>();
geom.collectContainedErrors(errors);
List<CheckError> planarErrors = new ArrayList<>();
for (CheckError e : errors) {
if (e.getErrorId() == ErrorId.GE_P_NON_PLANAR_POLYGON_DISTANCE_PLANE) {
planarErrors.add(e);
}
}
if (!planarErrors.isEmpty()) {
CheckError e = planarErrors.get(0);
HealPlanarPolygonCpp healer = new HealPlanarPolygonCpp();
e.accept(healer, TestUtil.createDummyModificationListener());
geom.updateEdgesAndVertices();
geom.clearAllContainedCheckResults();
geom.accept(check);
assertFalse(geom.containsError(CheckId.C_GE_P_NON_PLANAR));
} else {
fail();
}
}
@Test
public void testNonplanarPolygon_Split() {
CppInitializer.initCpp();
Building b = new Building();
Geometry geom = new Geometry(GeometryType.SOLID, Lod.LOD2);
b.addGeometry(geom);
Vertex v0 = new Vertex(0, 0, 0);
Vertex v1 = new Vertex(4, -1, 0);
Vertex v4 = new Vertex(4, 4, 0);
Vertex v6 = new Vertex(0, 4, 0);
Vertex v8 = new Vertex(4, 0, 4);
Vertex v9 = new Vertex(4, 4, 4);
Vertex v10 = new Vertex(0, 4, 4);
Vertex v11 = new Vertex(0, 0, 5);
Polygon p3 = new ConcretePolygon();
geom.addPolygon(p3);
LinearRing r3 = new LinearRing(LinearRingType.EXTERIOR);
p3.setExteriorRing(r3); // z = 0
r3.addVertex(v0);
r3.addVertex(v1);
r3.addVertex(v4);
r3.addVertex(v6);
r3.addVertex(v0);
Polygon p4 = new ConcretePolygon();
geom.addPolygon(p4);
LinearRing r4 = new LinearRing(LinearRingType.EXTERIOR);
p4.setExteriorRing(r4); // x = 4
r4.addVertex(v1);
r4.addVertex(v8);
r4.addVertex(v9);
r4.addVertex(v4);
r4.addVertex(v1);
Polygon p5 = new ConcretePolygon();
geom.addPolygon(p5);
LinearRing r5 = new LinearRing(LinearRingType.EXTERIOR);
p5.setExteriorRing(r5); // z = 4
r5.addVertex(v8);
r5.addVertex(v11);
r5.addVertex(v10);
r5.addVertex(v9);
r5.addVertex(v8);
Polygon p6 = new ConcretePolygon();
geom.addPolygon(p6);
LinearRing r6 = new LinearRing(LinearRingType.EXTERIOR);
p6.setExteriorRing(r6); // x = 0
r6.addVertex(v0);
r6.addVertex(v6);
r6.addVertex(v10);
r6.addVertex(v11);
r6.addVertex(v0);
Polygon p7 = new ConcretePolygon();
geom.addPolygon(p7);
LinearRing r7 = new LinearRing(LinearRingType.EXTERIOR);
p7.setExteriorRing(r7); // y = 4
r7.addVertex(v4);
r7.addVertex(v9);
r7.addVertex(v10);
r7.addVertex(v6);
r7.addVertex(v4);
Polygon p8 = new ConcretePolygon();
geom.addPolygon(p8);
LinearRing r8 = new LinearRing(LinearRingType.EXTERIOR);
p8.setExteriorRing(r8); // y = 0
r8.addVertex(v11);
r8.addVertex(v8);
r8.addVertex(v1);
r8.addVertex(v11);
Polygon p8_2 = new ConcretePolygon();
geom.addPolygon(p8_2);
LinearRing r8_2 = new LinearRing(LinearRingType.EXTERIOR);
p8_2.setExteriorRing(r8_2); // y = 0
r8_2.addVertex(v0);
r8_2.addVertex(v11);
r8_2.addVertex(v1);
r8_2.addVertex(v0);
geom.updateEdgesAndVertices();
PlanarCheck check = new PlanarCheck();
geom.accept(check);
check.check(geom);
List<CheckError> errors = new ArrayList<>();
geom.collectContainedErrors(errors);
List<CheckError> planarErrors = new ArrayList<>();
for (CheckError e : errors) {
if (e.getErrorId() == ErrorId.GE_P_NON_PLANAR_POLYGON_DISTANCE_PLANE) {
planarErrors.add(e);
}
}
if (!planarErrors.isEmpty()) {
CheckError e = planarErrors.get(0);
HealPlanarPolygonCpp healer = new HealPlanarPolygonCpp();
e.accept(healer, TestUtil.createDummyModificationListener());
geom.updateEdgesAndVertices();
geom.clearAllContainedCheckResults();
geom.accept(check);
assertFalse(geom.containsError(CheckId.C_GE_P_NON_PLANAR));
} else {
fail();
}
}
@Test
public void testNonplanarPolygon_Split2() {
CppInitializer.initCpp();
Building b = new Building();
Geometry geom = new Geometry(GeometryType.SOLID, Lod.LOD2);
b.addGeometry(geom);
Vertex v0 = new Vertex(0, 0, 0);
Vertex v1 = new Vertex(4, 0, 0);
Vertex v4 = new Vertex(4, 5, 0);
Vertex v6 = new Vertex(0, 4, 0);
Vertex v8 = new Vertex(4, 0, 4);
Vertex v9 = new Vertex(4, 4, 4);
Vertex v10 = new Vertex(0, 4, 4);
Vertex v11 = new Vertex(0, 0, 5);
Polygon p3 = new ConcretePolygon();
geom.addPolygon(p3);
LinearRing r3 = new LinearRing(LinearRingType.EXTERIOR);
p3.setExteriorRing(r3); // z = 0
r3.addVertex(v0);
r3.addVertex(v1);
r3.addVertex(v4);
r3.addVertex(v6);
r3.addVertex(v0);
Polygon p4 = new ConcretePolygon();
geom.addPolygon(p4);
LinearRing r4 = new LinearRing(LinearRingType.EXTERIOR);
p4.setExteriorRing(r4); // x = 4
r4.addVertex(v1);
r4.addVertex(v8);
r4.addVertex(v9);
r4.addVertex(v4);
r4.addVertex(v1);
Polygon p5 = new ConcretePolygon();
geom.addPolygon(p5);
LinearRing r5 = new LinearRing(LinearRingType.EXTERIOR);
p5.setExteriorRing(r5); // z = 4
r5.addVertex(v8);
r5.addVertex(v11);
r5.addVertex(v10);
r5.addVertex(v9);
r5.addVertex(v8);
Polygon p6 = new ConcretePolygon();
geom.addPolygon(p6);
LinearRing r6 = new LinearRing(LinearRingType.EXTERIOR);
p6.setExteriorRing(r6); // x = 0
r6.addVertex(v0);
r6.addVertex(v6);
r6.addVertex(v10);
r6.addVertex(v11);
r6.addVertex(v0);
Polygon p7 = new ConcretePolygon();
geom.addPolygon(p7);
LinearRing r7 = new LinearRing(LinearRingType.EXTERIOR);
p7.setExteriorRing(r7); // y = 4
r7.addVertex(v4);
r7.addVertex(v9);
r7.addVertex(v10);
r7.addVertex(v4);
Polygon p7_2 = new ConcretePolygon();
geom.addPolygon(p7_2);
LinearRing r7_2 = new LinearRing(LinearRingType.EXTERIOR);
p7_2.setExteriorRing(r7_2); // y = 4
r7_2.addVertex(v4);
r7_2.addVertex(v10);
r7_2.addVertex(v6);
r7_2.addVertex(v4);
Polygon p8 = new ConcretePolygon();
geom.addPolygon(p8);
LinearRing r8 = new LinearRing(LinearRingType.EXTERIOR);
p8.setExteriorRing(r8); // y = 0
r8.addVertex(v0);
r8.addVertex(v11);
r8.addVertex(v8);
r8.addVertex(v1);
r8.addVertex(v0);
geom.updateEdgesAndVertices();
PlanarCheck check = new PlanarCheck();
geom.accept(check);
check.check(geom);
List<CheckError> errors = new ArrayList<>();
geom.collectContainedErrors(errors);
List<CheckError> planarErrors = new ArrayList<>();
for (CheckError e : errors) {
if (e.getErrorId() == ErrorId.GE_P_NON_PLANAR_POLYGON_DISTANCE_PLANE) {
planarErrors.add(e);
}
}
if (!planarErrors.isEmpty()) {
CheckError e = planarErrors.get(0);
HealPlanarPolygonCpp healer = new HealPlanarPolygonCpp();
e.accept(healer, TestUtil.createDummyModificationListener());
geom.updateEdgesAndVertices();
geom.clearAllContainedCheckResults();
geom.accept(check);
assertFalse(geom.containsError(CheckId.C_GE_P_NON_PLANAR));
} else {
fail();
}
}
}
package de.hft.stuttgart.citydoctor2.healing;
import java.io.File;
import java.io.IOException;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.Checker;
import de.hft.stuttgart.citydoctor2.check.Requirement;
import de.hft.stuttgart.citydoctor2.check.RequirementConfiguration;
import de.hft.stuttgart.citydoctor2.check.ValidationConfiguration;
import de.hft.stuttgart.citydoctor2.datastructure.Building;
import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel;
import de.hft.stuttgart.citydoctor2.exceptions.CityDoctorWriteException;
import de.hft.stuttgart.citydoctor2.healer.Healer;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException;
import de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException;
public class HealPolygonWithoutSurfaceTest {
@Rule
public TemporaryFolder folder = new TemporaryFolder();
@Test
public void testHealPolygonWithoutSurface() throws CityGmlParseException, IOException, InvalidGmlFileException, CityDoctorWriteException {
ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
config.getRequirements().put(Requirement.R_SE_POLYGON_WITHOUT_SURFACE.getId(), new RequirementConfiguration(true));
String path = "src/test/resources/MissingGroundSurface.gml";
CityDoctorModel model = TestUtil.loadCityModel(path, config);
Checker c = new Checker(config, model);
c.runChecks();
Building building = model.getBuildings().get(0);
Assert.assertTrue(building.containsError(CheckId.C_SE_POLYGON_WITHOUT_SURFACE));
Healer healer = new Healer(c);
healer.healCityObject(model.getBuildings().get(0));
Assert.assertFalse(building.containsError(CheckId.C_SE_POLYGON_WITHOUT_SURFACE));
File outputFile = folder.newFile();
model.saveAs(outputFile.toString(), false);
CityDoctorModel loadedModel = TestUtil.loadCityModel(outputFile.toString(), config);
c = new Checker(config, loadedModel);
c.runChecks();
building = loadedModel.getBuildings().get(0);
Assert.assertFalse(building.containsError(CheckId.C_SE_POLYGON_WITHOUT_SURFACE));
}
}
package de.hft.stuttgart.citydoctor2.healing;
import java.io.IOException;
import org.junit.Assert;
import org.junit.Test;
import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.Checker;
import de.hft.stuttgart.citydoctor2.check.ValidationConfiguration;
import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.healer.Healer;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException;
import de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException;
public class HealPolygonWrongOrientationErrorTest {
@Test
public void testPolygonWrongOrientation1() throws CityGmlParseException, IOException, InvalidGmlFileException {
String path = "src/test/resources/SimpleSolid_SrefBS-GE-gml-SO-0007-T0001.gml";
checkAndRepairFile(path);
}
@Test
public void testPolygonWrongOrientation2() throws CityGmlParseException, IOException, InvalidGmlFileException {
String path = "src/test/resources/SimpleSolid_SrefBS-GE-gml-SO-0007-T0002.gml";
checkAndRepairFile(path);
}
@Test
public void testPolygonWrongOrientation3() throws CityGmlParseException, IOException, InvalidGmlFileException {
String path = "src/test/resources/SimpleSolid_SrefBS-GE-gml-SO-0007-T0003.gml";
checkAndRepairFile(path);
}
private void checkAndRepairFile(String path) throws CityGmlParseException, IOException, InvalidGmlFileException {
ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
CityDoctorModel model = TestUtil.loadCityModel(path, config);
Checker c = new Checker(config, model);
c.runChecks();
Geometry geom = model.getBuildings().get(0).getGeometries().get(0);
Assert.assertTrue(geom.containsError(CheckId.C_GE_S_POLYGON_WRONG_ORIENTATION));
Healer healer = new Healer(c);
healer.healCityObject(model.getBuildings().get(0));
Assert.assertFalse(geom.containsError(CheckId.C_GE_S_POLYGON_WRONG_ORIENTATION));
}
}
package de.hft.stuttgart.citydoctor2.healing;
import java.io.IOException;
import org.junit.Assert;
import org.junit.Test;
import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.Checker;
import de.hft.stuttgart.citydoctor2.check.ValidationConfiguration;
import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.healer.Healer;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException;
import de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException;
public class HealRingNotClosedErrorTest {
@Test
public void testRingNotClosed() throws CityGmlParseException, IOException, InvalidGmlFileException {
String path = "src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0003-T0001.gml";
ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
CityDoctorModel model = TestUtil.loadCityModel(path, config);
Checker c = new Checker(config, model);
c.runChecks();
Geometry geom = model.getBuildings().get(0).getGeometries().get(0);
Assert.assertTrue(geom.containsError(CheckId.C_GE_R_NOT_CLOSED));
Healer healer = new Healer(c);
healer.healCityObject(model.getBuildings().get(0));
Assert.assertFalse(geom.containsError(CheckId.C_GE_R_NOT_CLOSED));
}
}
package de.hft.stuttgart.citydoctor2.healing;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import org.junit.Assert;
import org.junit.Test;
import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.CheckResult;
import de.hft.stuttgart.citydoctor2.check.Checker;
import de.hft.stuttgart.citydoctor2.check.ErrorId;
import de.hft.stuttgart.citydoctor2.check.ResultStatus;
import de.hft.stuttgart.citydoctor2.check.ValidationConfiguration;
import de.hft.stuttgart.citydoctor2.check.error.RingEdgeIntersectionError;
import de.hft.stuttgart.citydoctor2.checks.geometry.DuplicatePointsCheck;
import de.hft.stuttgart.citydoctor2.checks.geometry.RingSelfIntCheck;
import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel;
import de.hft.stuttgart.citydoctor2.datastructure.ConcretePolygon;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.datastructure.GeometryType;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing.LinearRingType;
import de.hft.stuttgart.citydoctor2.datastructure.Lod;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
import de.hft.stuttgart.citydoctor2.healer.Healer;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException;
import de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException;
public class HealRingSelfIntErrorTest {
@Test
public void testIntersectingEdges1() {
Geometry geom = new Geometry(GeometryType.SOLID, Lod.LOD1);
Polygon p = new ConcretePolygon();
geom.addPolygon(p);
Vertex v0 = new Vertex(0, 4, 0);
Vertex v1 = new Vertex(0, 0, 0);
Vertex v2 = new Vertex(4, 4, 0);
Vertex v3 = new Vertex(6, 2, 0);
Vertex v4 = new Vertex(4, 0, 0);
LinearRing r = new LinearRing(LinearRingType.EXTERIOR);
p.setExteriorRing(r);
r.addVertex(v0);
r.addVertex(v1);
r.addVertex(v2);
r.addVertex(v3);
r.addVertex(v4);
r.addVertex(v0);
geom.updateEdgesAndVertices();
RingSelfIntCheck check = new RingSelfIntCheck();
check.check(r);
CheckResult cr = r.getCheckResult(check);
assertNotNull(cr);
assertEquals(ResultStatus.ERROR, cr.getResultStatus());
assertEquals(ErrorId.GE_R_SELF_INTERSECTION, cr.getError().getErrorId());
assertTrue(cr.getError() instanceof RingEdgeIntersectionError);
HealRingSelfIntError healer = new HealRingSelfIntError();
cr.getError().accept(healer, TestUtil.createDummyModificationListener());
geom.updateEdgesAndVertices();
assertEquals(2, geom.getPolygons().size());
Polygon p1 = geom.getPolygons().get(0);
Polygon p2 = geom.getPolygons().get(1);
if (p1.getExteriorRing().getVertices().size() == 4) {
assertEquals(5, p2.getExteriorRing().getVertices().size());
} else {
assertEquals(5, p1.getExteriorRing().getVertices().size());
assertEquals(4, p2.getExteriorRing().getVertices().size());
}
check.check(p1.getExteriorRing());
check.check(p2.getExteriorRing());
cr = p1.getExteriorRing().getCheckResult(check);
assertNotNull(cr);
assertEquals(ResultStatus.OK, cr.getResultStatus());
cr = p2.getExteriorRing().getCheckResult(check);
assertNotNull(cr);
assertEquals(ResultStatus.OK, cr.getResultStatus());
}
@Test
public void testDuplicatePoint1() {
Geometry geom = new Geometry(GeometryType.SOLID, Lod.LOD1);
Polygon p = new ConcretePolygon();
geom.addPolygon(p);
Vertex v0 = new Vertex(0, 0, 0);
Vertex v1 = new Vertex(4, 0, 0);
Vertex v2 = new Vertex(4, 4, 0);
Vertex v3 = new Vertex(2, 4, 0);
Vertex v4 = new Vertex(0, 4, 0);
LinearRing r = new LinearRing(LinearRingType.EXTERIOR);
p.setExteriorRing(r);
r.addVertex(v0);
r.addVertex(v1);
r.addVertex(v2);
r.addVertex(v0);
r.addVertex(v3);
r.addVertex(v4);
r.addVertex(v0);
DuplicatePointsCheck check = new DuplicatePointsCheck();
check.check(r);
CheckResult cr = r.getCheckResult(check);
assertNotNull(cr);
assertEquals(ResultStatus.ERROR, cr.getResultStatus());
assertEquals(ErrorId.GE_R_SELF_INTERSECTION, cr.getError().getErrorId());
HealRingSelfIntError healer = new HealRingSelfIntError();
cr.getError().accept(healer, TestUtil.createDummyModificationListener());
geom.updateEdgesAndVertices();
assertEquals(2, geom.getPolygons().size());
Polygon p1 = geom.getPolygons().get(0);
Polygon p2 = geom.getPolygons().get(1);
assertEquals(4, p1.getExteriorRing().getVertices().size());
assertEquals(4, p2.getExteriorRing().getVertices().size());
assertEquals(2, v0.getAdjacentRings(geom).size());
}
@Test
public void testDuplicatePoint2() {
Geometry geom = new Geometry(GeometryType.SOLID, Lod.LOD1);
Polygon p = new ConcretePolygon();
geom.addPolygon(p);
Vertex v0 = new Vertex(0, 0, 0);
Vertex v1 = new Vertex(4, 0, 0);
Vertex v2 = new Vertex(4, 4, 0);
Vertex v3 = new Vertex(2, 4, 0);
Vertex v4 = new Vertex(0, 4, 0);
LinearRing r = new LinearRing(LinearRingType.EXTERIOR);
p.setExteriorRing(r);
r.addVertex(v4);
r.addVertex(v0);
r.addVertex(v1);
r.addVertex(v2);
r.addVertex(v0);
r.addVertex(v3);
r.addVertex(v4);
DuplicatePointsCheck check = new DuplicatePointsCheck();
check.check(r);
CheckResult cr = r.getCheckResult(check);
assertNotNull(cr);
assertEquals(ResultStatus.ERROR, cr.getResultStatus());
assertEquals(ErrorId.GE_R_SELF_INTERSECTION, cr.getError().getErrorId());
HealRingSelfIntError healer = new HealRingSelfIntError();
cr.getError().accept(healer, TestUtil.createDummyModificationListener());
geom.updateEdgesAndVertices();
assertEquals(2, geom.getPolygons().size());
Polygon p1 = geom.getPolygons().get(0);
Polygon p2 = geom.getPolygons().get(1);
assertEquals(4, p1.getExteriorRing().getVertices().size());
assertEquals(4, p2.getExteriorRing().getVertices().size());
assertEquals(2, v0.getAdjacentRings(geom).size());
}
@Test
public void testDuplicatePoint3() throws CityGmlParseException, IOException, InvalidGmlFileException {
String path = "src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0002-T0002.gml";
ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
CityDoctorModel model = TestUtil.loadCityModel(path, config);
Checker c = new Checker(config, model);
c.runChecks();
Geometry geom = model.getBuildings().get(0).getGeometries().get(0);
Assert.assertTrue(geom.containsError(CheckId.C_GE_R_SELF_INTERSECTION));
Healer healer = new Healer(c);
healer.healCityObject(model.getBuildings().get(0));
Assert.assertFalse(geom.containsError(CheckId.C_GE_R_SELF_INTERSECTION));
}
@Test
public void testIntersectingEdges2() throws CityGmlParseException, IOException, InvalidGmlFileException {
String path = "src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0004-T0004.gml";
ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
CityDoctorModel model = TestUtil.loadCityModel(path, config);
Checker c = new Checker(config, model);
c.runChecks();
Geometry geom = model.getBuildings().get(0).getGeometries().get(0);
Assert.assertTrue(geom.containsError(CheckId.C_GE_R_SELF_INTERSECTION));
Healer healer = new Healer(c);
healer.healCityObject(model.getBuildings().get(0));
Assert.assertFalse(geom.containsError(CheckId.C_GE_R_SELF_INTERSECTION));
}
@Test
public void testTouchingVertex() throws CityGmlParseException, IOException, InvalidGmlFileException {
String path = "src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0004-T0005.gml";
ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
config.setMinVertexDistanceInGlobalParameters(0.1);
config.setNumberOfRoundingPlacesInGlobalParameters(8);
CityDoctorModel model = TestUtil.loadCityModel(path, config);
Checker c = new Checker(config, model);
c.runChecks();
Geometry geom = model.getBuildings().get(0).getGeometries().get(0);
Assert.assertTrue(geom.containsError(CheckId.C_GE_R_SELF_INTERSECTION));
Healer healer = new Healer(c);
healer.healCityObject(model.getBuildings().get(0));
Assert.assertFalse(geom.containsError(CheckId.C_GE_R_SELF_INTERSECTION));
}
}
package de.hft.stuttgart.citydoctor2.healing;
import java.io.IOException;
import org.junit.Assert;
import org.junit.Test;
import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.Checker;
import de.hft.stuttgart.citydoctor2.check.ValidationConfiguration;
import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.healer.Healer;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException;
import de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException;
public class HealSameOrientationErrorTest {
@Test
public void testHealSameOrientationError1()
throws CityGmlParseException, IOException, InvalidGmlFileException {
String path = "src/test/resources/SimpleSolid_SrefBS-GE-gml-PO-0006-T0001.gml";
ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
CityDoctorModel model = TestUtil.loadCityModel(path, config);
Checker c = new Checker(config, model);
c.runChecks();
Geometry geom = model.getBuildings().get(0).getGeometries().get(0);
Assert.assertTrue(geom.containsError(CheckId.C_GE_P_ORIENTATION_RINGS_SAME));
Healer healer = new Healer(c);
healer.healCityObject(model.getBuildings().get(0));
Assert.assertFalse(geom.containsError(CheckId.C_GE_P_ORIENTATION_RINGS_SAME));
}
}
package de.hft.stuttgart.citydoctor2.healing;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import org.citygml4j.xml.writer.CityGMLWriteException;
import org.junit.Assert;
import org.junit.Test;
import de.hft.stuttgart.citydoctor2.CppInitializer;
import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.CheckResult;
import de.hft.stuttgart.citydoctor2.check.Checker;
import de.hft.stuttgart.citydoctor2.check.ErrorId;
import de.hft.stuttgart.citydoctor2.check.ResultStatus;
import de.hft.stuttgart.citydoctor2.check.ValidationConfiguration;
import de.hft.stuttgart.citydoctor2.check.error.SolidNotClosedError;
import de.hft.stuttgart.citydoctor2.checks.geometry.SolidNotClosedCheck;
import de.hft.stuttgart.citydoctor2.datastructure.Building;
import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel;
import de.hft.stuttgart.citydoctor2.datastructure.ConcretePolygon;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.datastructure.GeometryType;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing.LinearRingType;
import de.hft.stuttgart.citydoctor2.datastructure.Lod;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
import de.hft.stuttgart.citydoctor2.healer.Healer;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException;
import de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException;
public class HealSolidNotClosedErrorTest {
/**
* One polygon is split up in 3 but has not matching edges
*/
@Test
public void testVertexCloseToEdge() {
CppInitializer.initCpp();
Building b = new Building(); //Angelika: als Test eingefügt
Geometry geom = new Geometry(GeometryType.SOLID, Lod.LOD0); //Original
// Geometry geom = new Geometry(GeometryType.SOLID, Lod.LOD2); //Angelika: Test
b.addGeometry(geom); //Angelika: als Test eingefügt
Vertex v0 = new Vertex(0, 0, 0);
Vertex v1 = new Vertex(4, 0, 0);
Vertex v2 = new Vertex(4, 2, 0);
Vertex v3 = new Vertex(2, 2, 0);
Vertex v4 = new Vertex(4, 4, 0);
Vertex v5 = new Vertex(2, 4, 0);
Vertex v6 = new Vertex(0, 4, 0);
Vertex v7 = new Vertex(0, 2, 0);
Vertex v8 = new Vertex(4, 0, 4);
Vertex v9 = new Vertex(4, 4, 4);
Vertex v10 = new Vertex(0, 4, 4);
Vertex v11 = new Vertex(0, 0, 4);
// error polygons
Polygon p1 = new ConcretePolygon();
geom.addPolygon(p1);
LinearRing r1 = new LinearRing(LinearRingType.EXTERIOR);
p1.setExteriorRing(r1);
r1.addVertex(v0);
r1.addVertex(v1);
r1.addVertex(v2);
r1.addVertex(v7);
r1.addVertex(v0);
Polygon p2 = new ConcretePolygon();
geom.addPolygon(p2);
LinearRing r2 = new LinearRing(LinearRingType.EXTERIOR);
p2.setExteriorRing(r2);
r2.addVertex(v2);
r2.addVertex(v4);
r2.addVertex(v5);
r2.addVertex(v3);
r2.addVertex(v2);
Polygon p3 = new ConcretePolygon();
geom.addPolygon(p3);
LinearRing r3 = new LinearRing(LinearRingType.EXTERIOR);
p3.setExteriorRing(r3);
r3.addVertex(v7);
r3.addVertex(v3);
r3.addVertex(v5);
r3.addVertex(v6);
r3.addVertex(v7);
// close the shell
Polygon p4 = new ConcretePolygon();
geom.addPolygon(p4);
LinearRing r4 = new LinearRing(LinearRingType.EXTERIOR);
p4.setExteriorRing(r4);
r4.addVertex(v1);
r4.addVertex(v8);
r4.addVertex(v9);
r4.addVertex(v4);
r4.addVertex(v1);
Polygon p5 = new ConcretePolygon();
geom.addPolygon(p5);
LinearRing r5 = new LinearRing(LinearRingType.EXTERIOR);
p5.setExteriorRing(r5);
r5.addVertex(v8);
r5.addVertex(v11);
r5.addVertex(v10);
r5.addVertex(v9);
r5.addVertex(v8);
Polygon p6 = new ConcretePolygon();
geom.addPolygon(p6);
LinearRing r6 = new LinearRing(LinearRingType.EXTERIOR);
p6.setExteriorRing(r6);
r6.addVertex(v0);
r6.addVertex(v6);
r6.addVertex(v10);
r6.addVertex(v11);
r6.addVertex(v0);
Polygon p7 = new ConcretePolygon();
geom.addPolygon(p7);
LinearRing r7 = new LinearRing(LinearRingType.EXTERIOR);
p7.setExteriorRing(r7);
r7.addVertex(v4);
r7.addVertex(v9);
r7.addVertex(v10);
r7.addVertex(v6);
r7.addVertex(v4);
Polygon p8 = new ConcretePolygon();
geom.addPolygon(p8);
LinearRing r8 = new LinearRing(LinearRingType.EXTERIOR);
p8.setExteriorRing(r8);
r8.addVertex(v0);
r8.addVertex(v11);
r8.addVertex(v8);
r8.addVertex(v1);
r8.addVertex(v0);
geom.updateEdgesAndVertices();
SolidNotClosedCheck check = new SolidNotClosedCheck();
check.check(geom);
CheckResult cr = geom.getCheckResult(check);
assertNotNull(cr);
assertEquals(ResultStatus.ERROR, cr.getResultStatus());
assertEquals(ErrorId.GE_S_NOT_CLOSED, cr.getError().getErrorId());
assertTrue(cr.getError() instanceof SolidNotClosedError);
// HealSolidNotClosedError healer = new HealSolidNotClosedError(); //Original
HealSolidNotClosedCpp healer = new HealSolidNotClosedCpp(); // Angelika
cr.getError().accept(healer, TestUtil.createDummyModificationListener());
geom.updateEdgesAndVertices();
check.check(geom);
cr = geom.getCheckResult(check);
assertNotNull(cr);
assertEquals(ResultStatus.OK, cr.getResultStatus());
}
@Test
public void testMissingPolygon() {
CppInitializer.initCpp();
Building b = new Building();
Geometry geom = new Geometry(GeometryType.SOLID, Lod.LOD2);
b.addGeometry(geom);
Vertex v0 = new Vertex(0, 0, 0);
Vertex v1 = new Vertex(4, 0, 0);
Vertex v4 = new Vertex(4, 4, 0);
Vertex v6 = new Vertex(0, 4, 0);
Vertex v8 = new Vertex(4, 0, 4);
Vertex v9 = new Vertex(4, 4, 4);
Vertex v10 = new Vertex(0, 4, 4);
Vertex v11 = new Vertex(0, 0, 4);
Polygon p4 = new ConcretePolygon();
geom.addPolygon(p4);
LinearRing r4 = new LinearRing(LinearRingType.EXTERIOR);
p4.setExteriorRing(r4);
r4.addVertex(v1);
r4.addVertex(v8);
r4.addVertex(v9);
r4.addVertex(v4);
r4.addVertex(v1);
Polygon p5 = new ConcretePolygon();
geom.addPolygon(p5);
LinearRing r5 = new LinearRing(LinearRingType.EXTERIOR);
p5.setExteriorRing(r5);
r5.addVertex(v8);
r5.addVertex(v11);
r5.addVertex(v10);
r5.addVertex(v9);
r5.addVertex(v8);
Polygon p6 = new ConcretePolygon();
geom.addPolygon(p6);
LinearRing r6 = new LinearRing(LinearRingType.EXTERIOR);
p6.setExteriorRing(r6);
r6.addVertex(v0);
r6.addVertex(v6);
r6.addVertex(v10);
r6.addVertex(v11);
r6.addVertex(v0);
Polygon p7 = new ConcretePolygon();
geom.addPolygon(p7);
LinearRing r7 = new LinearRing(LinearRingType.EXTERIOR);
p7.setExteriorRing(r7);
r7.addVertex(v4);
r7.addVertex(v9);
r7.addVertex(v10);
r7.addVertex(v6);
r7.addVertex(v4);
Polygon p8 = new ConcretePolygon();
geom.addPolygon(p8);
LinearRing r8 = new LinearRing(LinearRingType.EXTERIOR);
p8.setExteriorRing(r8);
r8.addVertex(v0);
r8.addVertex(v11);
r8.addVertex(v8);
r8.addVertex(v1);
r8.addVertex(v0);
geom.updateEdgesAndVertices();
SolidNotClosedCheck check = new SolidNotClosedCheck();
check.check(geom);
CheckResult cr = geom.getCheckResult(check);
assertNotNull(cr);
assertEquals(ResultStatus.ERROR, cr.getResultStatus());
assertEquals(ErrorId.GE_S_NOT_CLOSED, cr.getError().getErrorId());
assertTrue(cr.getError() instanceof SolidNotClosedError);
HealSolidNotClosedCpp healer = new HealSolidNotClosedCpp();
// HealSolidNotClosedError healer = new HealSolidNotClosedError(); //Angelika: Test
cr.getError().accept(healer, TestUtil.createDummyModificationListener());
geom.updateEdgesAndVertices();
geom.clearAllContainedCheckResults();
check.check(geom);
cr = geom.getCheckResult(check);
assertNotNull(cr);
assertEquals(ResultStatus.OK, cr.getResultStatus());
}
@Test
public void test2MissingPolygons() {
Building b = new Building();
Geometry geom = new Geometry(GeometryType.SOLID, Lod.LOD0);
b.addGeometry(geom);
Vertex v0 = new Vertex(0, 0, 0);
Vertex v1 = new Vertex(4, 0, 0);
Vertex v4 = new Vertex(4, 4, 0);
Vertex v6 = new Vertex(0, 4, 0);
Vertex v8 = new Vertex(4, 0, 4);
Vertex v9 = new Vertex(4, 4, 4);
Vertex v10 = new Vertex(0, 4, 4);
Vertex v11 = new Vertex(0, 0, 4);
Polygon p4 = new ConcretePolygon();
geom.addPolygon(p4);
LinearRing r4 = new LinearRing(LinearRingType.EXTERIOR);
p4.setExteriorRing(r4);
r4.addVertex(v1);
r4.addVertex(v8);
r4.addVertex(v9);
r4.addVertex(v4);
r4.addVertex(v1);
Polygon p5 = new ConcretePolygon();
geom.addPolygon(p5);
LinearRing r5 = new LinearRing(LinearRingType.EXTERIOR);
p5.setExteriorRing(r5);
r5.addVertex(v8);
r5.addVertex(v11);
r5.addVertex(v10);
r5.addVertex(v9);
r5.addVertex(v8);
Polygon p6 = new ConcretePolygon();
geom.addPolygon(p6);
LinearRing r6 = new LinearRing(LinearRingType.EXTERIOR);
p6.setExteriorRing(r6);
r6.addVertex(v0);
r6.addVertex(v6);
r6.addVertex(v10);
r6.addVertex(v11);
r6.addVertex(v0);
Polygon p8 = new ConcretePolygon();
geom.addPolygon(p8);
LinearRing r8 = new LinearRing(LinearRingType.EXTERIOR);
p8.setExteriorRing(r8);
r8.addVertex(v0);
r8.addVertex(v11);
r8.addVertex(v8);
r8.addVertex(v1);
r8.addVertex(v0);
geom.updateEdgesAndVertices();
SolidNotClosedCheck check = new SolidNotClosedCheck();
check.check(geom);
CheckResult cr = geom.getCheckResult(check);
assertNotNull(cr);
assertEquals(ResultStatus.ERROR, cr.getResultStatus());
assertEquals(ErrorId.GE_S_NOT_CLOSED, cr.getError().getErrorId());
assertTrue(cr.getError() instanceof SolidNotClosedError);
HealSolidNotClosedError healer = new HealSolidNotClosedError();
cr.getError().accept(healer, TestUtil.createDummyModificationListener());
geom.updateEdgesAndVertices();
geom.clearAllContainedCheckResults();
check.check(geom);
cr = geom.getCheckResult(check);
assertNotNull(cr);
assertEquals(ResultStatus.ERROR, cr.getResultStatus());
assertEquals(ErrorId.GE_S_NOT_CLOSED, cr.getError().getErrorId());
assertTrue(cr.getError() instanceof SolidNotClosedError);
cr.getError().accept(healer, TestUtil.createDummyModificationListener());
geom.updateEdgesAndVertices();
geom.clearAllContainedCheckResults();
check.check(geom);
cr = geom.getCheckResult(check);
assertNotNull(cr);
assertEquals(ResultStatus.OK, cr.getResultStatus());
}
@Test
public void test2MissingPolygonsCpp() {
CppInitializer.initCpp();
Building b = new Building();
Geometry geom = new Geometry(GeometryType.SOLID, Lod.LOD2);
b.addGeometry(geom);
Vertex v0 = new Vertex(0, 0, 0);
Vertex v1 = new Vertex(4, 0, 0);
Vertex v4 = new Vertex(4, 4, 0);
Vertex v6 = new Vertex(0, 4, 0);
Vertex v8 = new Vertex(4, 0, 4);
Vertex v9 = new Vertex(4, 4, 4);
Vertex v10 = new Vertex(0, 4, 4);
Vertex v11 = new Vertex(0, 0, 4);
Polygon p4 = new ConcretePolygon();
geom.addPolygon(p4);
LinearRing r4 = new LinearRing(LinearRingType.EXTERIOR);
p4.setExteriorRing(r4);
r4.addVertex(v1);
r4.addVertex(v8);
r4.addVertex(v9);
r4.addVertex(v4);
r4.addVertex(v1);
Polygon p5 = new ConcretePolygon();
geom.addPolygon(p5);
LinearRing r5 = new LinearRing(LinearRingType.EXTERIOR);
p5.setExteriorRing(r5);
r5.addVertex(v8);
r5.addVertex(v11);
r5.addVertex(v10);
r5.addVertex(v9);
r5.addVertex(v8);
Polygon p6 = new ConcretePolygon();
geom.addPolygon(p6);
LinearRing r6 = new LinearRing(LinearRingType.EXTERIOR);
p6.setExteriorRing(r6);
r6.addVertex(v0);
r6.addVertex(v6);
r6.addVertex(v10);
r6.addVertex(v11);
r6.addVertex(v0);
Polygon p8 = new ConcretePolygon();
geom.addPolygon(p8);
LinearRing r8 = new LinearRing(LinearRingType.EXTERIOR);
p8.setExteriorRing(r8);
r8.addVertex(v0);
r8.addVertex(v11);
r8.addVertex(v8);
r8.addVertex(v1);
r8.addVertex(v0);
geom.updateEdgesAndVertices();
SolidNotClosedCheck check = new SolidNotClosedCheck();
check.check(geom);
CheckResult cr = geom.getCheckResult(check);
assertNotNull(cr);
assertEquals(ResultStatus.ERROR, cr.getResultStatus());
assertEquals(ErrorId.GE_S_NOT_CLOSED, cr.getError().getErrorId());
assertTrue(cr.getError() instanceof SolidNotClosedError);
// HealSolidNotClosedError healer = new HealSolidNotClosedError(); //Original
HealSolidNotClosedCpp healer = new HealSolidNotClosedCpp(); // Angelika
cr.getError().accept(healer, TestUtil.createDummyModificationListener());
geom.updateEdgesAndVertices();
geom.clearAllContainedCheckResults();
check.check(geom);
cr = geom.getCheckResult(check);
assertNotNull(cr);
assertEquals(ResultStatus.OK, cr.getResultStatus());
}
/**
* Missing Polygon has a self intersection
* @throws IOException
* @throws CityGmlParseException
* @throws CityGMLWriteException
* @throws CityGMLBuilderException
* @throws InvalidGmlFileException
*/
@Test
public void testMissingPolygon2() throws CityGmlParseException, IOException, InvalidGmlFileException {
String path = "src/test/resources/SimpleSolid_SrefBS-GE-gml-SO-0002-T0002.gml"; //bei diesem Modell stürzt die VM ab
// String path = "src/test/resources/SimpleSolid_SrefBS-GE-gml-SO-0002-T0001.gml"; //hier nur Fehlermeldung
ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
CityDoctorModel model = TestUtil.loadCityModel(path, config);
Checker c = new Checker(config, model);
c.runChecks();
Geometry geom = model.getBuildings().get(0).getGeometries().get(0);
geom.updateVertices();
for (Vertex v : geom.getVertices()) {
v.setX(v.getX() - 10);
v.setY(v.getY() - 10);
}
Assert.assertTrue(geom.containsError(CheckId.C_GE_S_NOT_CLOSED));
Healer healer = new Healer(c);
//healer.setNumberOfIterations(2);
healer.healCityObject(model.getBuildings().get(0));
Assert.assertFalse(geom.containsError(CheckId.C_GE_S_NOT_CLOSED));
}
}
package de.hft.stuttgart.citydoctor2.healing;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import org.junit.Test;
import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.Checker;
import de.hft.stuttgart.citydoctor2.check.ValidationConfiguration;
import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.healer.Healer;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException;
import de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException;
public class HealTooFewPointsTest {
@Test
public void testHealTooFewPoints1() throws IOException, CityGmlParseException, InvalidGmlFileException {
String path = "src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0001-T0001.gml";
ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
CityDoctorModel model = TestUtil.loadCityModel(path, config);
Checker c = new Checker(config, model);
c.runChecks();
Geometry geom = model.getBuildings().get(0).getGeometries().get(0);
assertTrue(geom.containsError(CheckId.C_GE_R_TOO_FEW_POINTS));
Healer healer = new Healer(c);
healer.healCityObject(model.getBuildings().get(0));
assertFalse(geom.containsError(CheckId.C_GE_R_TOO_FEW_POINTS));
}
}
package de.hft.stuttgart.citydoctor2.healing;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.citygml4j.xml.writer.CityGMLWriteException;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.Checker;
import de.hft.stuttgart.citydoctor2.check.Requirement;
import de.hft.stuttgart.citydoctor2.check.RequirementConfiguration;
import de.hft.stuttgart.citydoctor2.check.ValidationConfiguration;
import de.hft.stuttgart.citydoctor2.datastructure.BoundarySurface;
import de.hft.stuttgart.citydoctor2.datastructure.Building;
import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.exceptions.CityDoctorWriteException;
import de.hft.stuttgart.citydoctor2.healer.Healer;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParser;
import de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException;
public class TestHealer {
@Rule
public TemporaryFolder folder = new TemporaryFolder();
@Test
public void testMissingMainHealing() throws CityGmlParseException, IOException, InvalidGmlFileException, CityDoctorWriteException {
String path = "src/test/resources/LoD2_33_396_5807_AmWaldrand_fix_with_addresses.gml";
ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
config.setSchematronFilePathInGlobalParameters("src/test/resources/missingMainBuilding.xml");
CityDoctorModel model = TestUtil.loadCityModel(path, config);
Checker c = new Checker(config, model);
c.runChecks();
Building b = null;
for (Building building : model.getBuildings()) {
if (building.getGmlId().getGmlString().equals("DEBE08YYF0004KZs")) {
b = building;
break;
}
}
assertNotNull(b);
List<CheckError> errors = new ArrayList<>();
b.collectContainedErrors(errors);
assertFalse(errors.isEmpty());
Healer healer = new Healer(c);
healer.healCityObject(b);
assertFalse(b.containsAnyError());
}
@Test
public void testHealingAPI()
throws CityGmlParseException, IOException, InvalidGmlFileException, CityDoctorWriteException {
File in = new File("src/test/resources/TestBuilding1.gml");
File config = new File("src/test/resources/testConfigWithStreaming.yml");
File out = folder.newFile("out.gml");
out.delete();
Healer.heal(in, config, out);
assertTrue(out.exists());
}
@Test
public void testHealingMainWithStreaming() throws IOException, CityGmlParseException, InterruptedException,
InvalidGmlFileException, CityDoctorWriteException {
File in = new File("src/test/resources/TestBuilding1.gml");
File configFile = new File("src/test/resources/streamingStandardConfig.yml");
File out = folder.newFile("out.gml");
out.delete();
String[] args = new String[6];
args[0] = "-in";
args[1] = in.getAbsolutePath();
args[2] = "-out";
args[3] = out.getAbsolutePath();
args[4] = "-config";
args[5] = configFile.getAbsolutePath();
Healer.main(args);
assertTrue(out.exists());
ValidationConfiguration valConfig = ValidationConfiguration.loadStandardValidationConfig();
valConfig.setSchematronFilePathInGlobalParameters(null);
CityDoctorModel model = CityGmlParser.parseCityGmlFile(out.getAbsolutePath(), valConfig.getParserConfiguration());
Checker c = new Checker(valConfig, model);
c.runChecks();
model.createFeatureStream().forEach(co -> {
List<CheckError> errors = new ArrayList<>();
co.collectContainedErrors(errors);
assertFalse(co.containsAnyError());
});
}
/**
* Building has a lot of consecutive points same errors
*
* @throws CityGmlParseException
* @throws IOException
* @throws CityGMLBuilderException
* @throws CityGMLWriteException
* @throws InvalidGmlFileException
*/
@Test
public void testHealing1()
throws CityGmlParseException, IOException, CityGMLWriteException, InvalidGmlFileException {
String path = "src/test/resources/TestBuilding1.gml";
ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
CityDoctorModel model = TestUtil.loadCityModel(path, config);
Checker c = new Checker(config, model);
c.runChecks();
Healer healer = new Healer(c);
Geometry geom = model.getBuildings().get(0).getGeometries().get(0);
healer.healCityObject(model.getBuildings().get(0));
c.runChecks();
assertFalse(geom.containsAnyError());
}
/**
* Many consecutive points same and manifold edge errors
*
* @throws CityGmlParseException
* @throws IOException
* @throws CityGMLBuilderException
* @throws CityGMLWriteException
* @throws InvalidGmlFileException
*/
@Test
public void testHealing2()
throws CityGmlParseException, IOException, CityGMLWriteException, InvalidGmlFileException {
String path = "src/test/resources/TestBuilding2.gml";
ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
CityDoctorModel model = TestUtil.loadCityModel(path, config);
Checker c = new Checker(config, model);
c.runChecks();
Geometry geom = model.getBuildings().get(0).getGeometries().get(0);
Healer healer = new Healer(c);
healer.setNumberOfIterations(33);
healer.healCityObject(model.getBuildings().get(0));
c.runChecks();
assertFalse(geom.containsAnyError());
}
@Test
public void testHealing3()
throws CityGmlParseException, IOException, CityGMLWriteException, InvalidGmlFileException {
String path = "src/test/resources/TestBuilding3.gml";
ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
CityDoctorModel model = TestUtil.loadCityModel(path, config);
Checker c = new Checker(config, model);
c.runChecks();
Geometry geom = model.getBuildings().get(0).getGeometries().get(0);
Healer healer = new Healer(c);
healer.healCityObject(model.getBuildings().get(0));
c.runChecks();
assertFalse(geom.containsAnyError());
}
@Test
public void testHealing4()
throws CityGmlParseException, IOException, CityGMLWriteException, InvalidGmlFileException {
String path = "src/test/resources/TestBuilding4.gml";
ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
CityDoctorModel model = TestUtil.loadCityModel(path, config);
Checker c = new Checker(config, model);
c.runChecks();
Geometry geom = model.getBuildings().get(0).getGeometries().get(0);
Healer healer = new Healer(c);
healer.setNumberOfIterations(83);
healer.healCityObject(model.getBuildings().get(0));
c.runChecks();
assertFalse(geom.containsAnyError());
}
@Test
public void testHealing5()
throws CityGmlParseException, IOException, CityGMLWriteException, InvalidGmlFileException {
String path = "src/test/resources/TestBuilding5.gml";
ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
CityDoctorModel model = TestUtil.loadCityModel(path, config);
Checker c = new Checker(config, model);
c.runChecks();
Geometry geom = model.getBuildings().get(0).getGeometries().get(0);
Healer healer = new Healer(c);
healer.setNumberOfIterations(165);
healer.healCityObject(model.getBuildings().get(0));
c.runChecks();
assertFalse(geom.containsAnyError());
}
@Test
public void testHealing6()
throws CityGmlParseException, IOException, CityGMLWriteException, InvalidGmlFileException {
String path = "src/test/resources/TestBuilding6.gml";
ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
RequirementConfiguration checkConfiguration = config.getRequirements()
.get(Requirement.R_SE_BS_IS_CEILING.toString());
checkConfiguration.setEnabled(false);
checkConfiguration = config.getRequirements().get(Requirement.R_SE_BS_IS_FLOOR.toString());
checkConfiguration.setEnabled(false);
checkConfiguration = config.getRequirements().get(Requirement.R_SE_BS_IS_GROUND.toString());
checkConfiguration.setEnabled(false);
checkConfiguration = config.getRequirements().get(Requirement.R_SE_BS_IS_WALL.toString());
checkConfiguration.setEnabled(false);
checkConfiguration = config.getRequirements().get(Requirement.R_SE_BS_ROOF_UNFRAGMENTED.toString());
checkConfiguration.setEnabled(false);
CityDoctorModel model = TestUtil.loadCityModel(path, config);
Checker c = new Checker(config, model);
c.runChecks();
Building b = model.getBuildings().get(0);
Healer healer = new Healer(c);
healer.healCityObject(b);
c.runChecks();
for (BoundarySurface bs : b.getBoundarySurfaces()) {
assertFalse(bs.containsAnyError());
}
}
@Test
public void testHealing8()
throws CityGmlParseException, IOException, CityGMLWriteException, InvalidGmlFileException {
String path = "src/test/resources/TestBuilding8.gml";
ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
CityDoctorModel model = TestUtil.loadCityModel(path, config);
Checker c = new Checker(config, model);
c.runChecks();
Geometry geom = model.getBuildings().get(0).getGeometries().get(0);
Healer healer = new Healer(c);
healer.setNumberOfIterations(45);
healer.healCityObject(model.getBuildings().get(0));
c.runChecks();
assertFalse(geom.containsAnyError());
}
@Test
public void testHealingFailWrite() throws CityGmlParseException, IOException, InvalidGmlFileException, CityDoctorWriteException {
String path = "src/test/resources/TestBuilding8.gml";
ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
CityDoctorModel model = TestUtil.loadCityModel(path, config);
Checker c = new Checker(config, model);
c.runChecks();
Healer healer = new Healer(c);
healer.setNumberOfIterations(45);
healer.healModel(model);
}
@Test
public void testHealingBigBuildingWithoutErrors()
throws CityGmlParseException, IOException, CityGMLWriteException, InvalidGmlFileException {
String path = "src/test/resources/bigBuilding1.gml";
ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
config.setSchematronFilePathInGlobalParameters(null);
CityDoctorModel model = TestUtil.loadCityModel(path, config);
Checker c = new Checker(config, model);
c.runChecks();
Geometry geom = model.getBuildings().get(0).getGeometries().get(0);
Healer healer = new Healer(c);
healer.setNumberOfIterations(100);
healer.healCityObject(model.getBuildings().get(0));
c.runChecks();
assertFalse(geom.containsAnyError());
}
}
package de.hft.stuttgart.citydoctor2.healing;
import java.io.IOException;
import java.util.List;
import de.hft.stuttgart.citydoctor2.check.ModificationListener;
import de.hft.stuttgart.citydoctor2.check.ValidationConfiguration;
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.Polygon;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParser;
import de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException;
public class TestUtil {
public static ModificationListener createDummyModificationListener() {
return new ModificationListener() {
@Override
public void polygonRemoved(Polygon p) {
// nothing
}
@Override
public void polygonAdded(Polygon p) {
// nothing
}
};
}
public static CityDoctorModel loadCityModel(String path, ValidationConfiguration config) throws CityGmlParseException, IOException, InvalidGmlFileException {
return CityGmlParser.parseCityGmlFile(path, config.getParserConfiguration());
}
public static Polygon getPolygonById(String gmlId, CityDoctorModel model) {
if (gmlId == null) {
return null;
}
Polygon result = getPolygonById(gmlId, model.getBuildings());
if (result != null) {
return result;
}
result = getPolygonById(gmlId, model.getVegetation());
if (result != null) {
return result;
}
return getPolygonById(gmlId, model.getTransportation());
}
private static Polygon getPolygonById(String gmlId, List<? extends CityObject> features) {
if (gmlId == null) {
return null;
}
for (CityObject co : features) {
Polygon result = getPolygonById(gmlId, co);
if (result != null) {
return result;
}
}
return null;
}
public static Polygon getPolygonById(String gmlId, String featureId, CityDoctorModel model) {
if (gmlId == null || featureId == null) {
return null;
}
CityObject co = getCityObjectById(featureId, model);
return getPolygonById(gmlId, co);
}
private static Polygon getPolygonById(String gmlId, CityObject co) {
for (Geometry geom : co.getGeometries()) {
for (Polygon p : geom.getPolygons()) {
if (gmlId.equals(p.getGmlId().getGmlString())) {
return p;
}
}
}
return null;
}
private static CityObject getCityObjectById(String featureId, CityDoctorModel model) {
if (featureId == null) {
return null;
}
for (CityObject co : model.getBuildings()) {
if (featureId.equals(co.getGmlId().getGmlString())) {
return co;
}
}
for (CityObject co : model.getTransportation()) {
if (featureId.equals(co.getGmlId().getGmlString())) {
return co;
}
}
for (CityObject co : model.getVegetation()) {
if (featureId.equals(co.getGmlId().getGmlString())) {
return co;
}
}
return null;
}
}
package de.hft.stuttgart.citydoctor2.healing.math;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import de.hft.stuttgart.citydoctor2.datastructure.Edge;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
public class EdgeGraphTest {
@Test
public void testGetCycles1() {
Vertex v0 = new Vertex(4, 4, 0);
Vertex v1 = new Vertex(4, 4, 4);
Vertex v2 = new Vertex(0, 4, 4);
Vertex v3 = new Vertex(0, 4, 0);
Edge e1 = new Edge(v1, v0);
Edge e2 = new Edge(v1, v2);
Edge e3 = new Edge(v2, v3);
List<Edge> edges = new ArrayList<>();
edges.add(e1);
edges.add(e2);
edges.add(e3);
EdgeGraph graph = new EdgeGraph();
graph.addEdge(e1, edges);
graph.addEdge(e2, edges);
graph.addEdge(e3, edges);
assertTrue(graph.getCycles().isEmpty());
}
@Test
public void testGetCycles2() {
Vertex v0 = new Vertex(4, 4, 0);
Vertex v1 = new Vertex(4, 4, 4);
Vertex v2 = new Vertex(0, 4, 4);
Vertex v3 = new Vertex(0, 4, 0);
Edge e1 = new Edge(v1, v0);
Edge e2 = new Edge(v1, v2);
Edge e3 = new Edge(v2, v3);
Edge e4 = new Edge(v0, v3);
List<Edge> edges = new ArrayList<>();
edges.add(e1);
edges.add(e2);
edges.add(e3);
edges.add(e4);
EdgeGraph graph = new EdgeGraph();
graph.addEdge(e1, edges);
graph.addEdge(e2, edges);
graph.addEdge(e3, edges);
graph.addEdge(e4, edges);
assertFalse(graph.getCycles().isEmpty());
}
}
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<core:CityModel xmlns:xAL="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0" xmlns:gml="http://www.opengis.net/gml" xmlns:wtr="http://www.opengis.net/citygml/waterbody/2.0" xmlns:app="http://www.opengis.net/citygml/appearance/2.0" xmlns:core="http://www.opengis.net/citygml/2.0" xmlns:veg="http://www.opengis.net/citygml/vegetation/2.0" xmlns:dem="http://www.opengis.net/citygml/relief/2.0" xmlns:tran="http://www.opengis.net/citygml/transportation/2.0" xmlns:bldg="http://www.opengis.net/citygml/building/2.0" xmlns:grp="http://www.opengis.net/citygml/cityobjectgroup/2.0" xmlns:tun="http://www.opengis.net/citygml/tunnel/2.0" xmlns:qual="https://transfer.hft-stuttgart.de/pages/citydoctor/qualityade/1.0.0" xmlns:frn="http://www.opengis.net/citygml/cityfurniture/2.0" xmlns:brid="http://www.opengis.net/citygml/bridge/2.0" xmlns:gen="http://www.opengis.net/citygml/generics/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:luse="http://www.opengis.net/citygml/landuse/2.0" xsi:schemaLocation="http://www.opengis.net/citygml/building/2.0 http://schemas.opengis.net/citygml/building/2.0/building.xsd http://www.opengis.net/citygml/cityobjectgroup/2.0 http://schemas.opengis.net/citygml/cityobjectgroup/2.0/cityObjectGroup.xsd http://www.opengis.net/citygml/tunnel/2.0 http://schemas.opengis.net/citygml/tunnel/2.0/tunnel.xsd http://www.opengis.net/citygml/waterbody/2.0 http://schemas.opengis.net/citygml/waterbody/2.0/waterBody.xsd http://www.opengis.net/citygml/appearance/2.0 http://schemas.opengis.net/citygml/appearance/2.0/appearance.xsd http://www.opengis.net/citygml/cityfurniture/2.0 http://schemas.opengis.net/citygml/cityfurniture/2.0/cityFurniture.xsd http://www.opengis.net/citygml/bridge/2.0 http://schemas.opengis.net/citygml/bridge/2.0/bridge.xsd http://www.opengis.net/citygml/generics/2.0 http://schemas.opengis.net/citygml/generics/2.0/generics.xsd http://www.opengis.net/citygml/vegetation/2.0 http://schemas.opengis.net/citygml/vegetation/2.0/vegetation.xsd http://www.opengis.net/citygml/relief/2.0 http://schemas.opengis.net/citygml/relief/2.0/relief.xsd http://www.opengis.net/citygml/transportation/2.0 http://schemas.opengis.net/citygml/transportation/2.0/transportation.xsd http://www.opengis.net/citygml/landuse/2.0 http://schemas.opengis.net/citygml/landuse/2.0/landUse.xsd">
<core:cityObjectMember>
<bldg:Building gml:id="DEBW522AA00021b87">
<gml:name>08111000_0_048_29380_000</gml:name>
<bldg:consistsOfBuildingPart>
<bldg:BuildingPart gml:id="DEBW522AA00021b88">
<gml:name>08111000_0_048_29380_000,08111000_0_048_29380_000_000</gml:name>
<core:externalReference>
<core:informationSystem>Aufruf GrundIS</core:informationSystem>
<core:externalObject>
<core:name>https://grundis.lhs.stuttgart.de/amt62/GrundIS?ak=9&amp;amp;&amp;quot;amp;&amp;quot;lg=29380&amp;amp;&amp;quot;amp;&amp;quot;hn=48</core:name>
</core:externalObject>
</core:externalReference>
<gen:stringAttribute name="umbauterRaum">
<gen:value>1535.0</gen:value>
</gen:stringAttribute>
<gen:stringAttribute name="grundflaeche">
<gen:value>226.0</gen:value>
</gen:stringAttribute>
<gen:stringAttribute name="baublockNummer">
<gen:value>761505</gen:value>
</gen:stringAttribute>
<gen:stringAttribute name="verwaltendesAmt">
<gen:value/>
</gen:stringAttribute>
<gen:stringAttribute name="alkisFFDatum">
<gen:value>13.03.2023</gen:value>
</gen:stringAttribute>
<gen:stringAttribute name="LoD1_datenquelleBodenhoehe">
<gen:value>1000</gen:value>
</gen:stringAttribute>
<gen:stringAttribute name="gmlIdALKISLageBezeichnung_2">
<gen:value>DEBWL522100042Dd</gen:value>
</gen:stringAttribute>
<gen:stringAttribute name="gmlIdALKISLageBezeichnung_1">
<gen:value>DEBWL52210004T74</gen:value>
</gen:stringAttribute>
<gen:stringAttribute name="LoD1_datenquelleLage">
<gen:value>1000</gen:value>
</gen:stringAttribute>
<gen:stringAttribute name="alkisId">
<gen:value>DEBWL522100053ew</gen:value>
</gen:stringAttribute>
<gen:stringAttribute name="fortfuehrungsFall">
<gen:value>REPLACE</gen:value>
</gen:stringAttribute>
<gen:stringAttribute name="statusDesGebaeudes">
<gen:value>1</gen:value>
</gen:stringAttribute>
<gen:stringAttribute name="baublockseitenNummer">
<gen:value>2</gen:value>
</gen:stringAttribute>
<gen:stringAttribute name="geschossflaeche">
<gen:value>452.0</gen:value>
</gen:stringAttribute>
<bldg:function codeSpace="http://www.adv-online.de/codespaces/buildingfunctiontypeADV.xml">2112</bldg:function>
<bldg:yearOfConstruction>1970</bldg:yearOfConstruction>
<bldg:roofType codeSpace="http://www.adv-online.de/codespaces/rooftypetypeADV.xml">2100</bldg:roofType>
<bldg:measuredHeight uom="#m">6.0</bldg:measuredHeight>
<bldg:storeysAboveGround>1</bldg:storeysAboveGround>
<bldg:storeysBelowGround>1</bldg:storeysBelowGround>
<bldg:lod2Solid>
<gml:Solid gml:id="CityDoctor_1708557190212_661">
<gml:exterior>
<gml:CompositeSurface>
<gml:surfaceMember xlink:href="#PolyIDGeo4027008"/>
<gml:surfaceMember xlink:href="#PolyIDGeo4027009"/>
<gml:surfaceMember xlink:href="#PolyIDGeo3628596"/>
<gml:surfaceMember xlink:href="#PolyIDGeo3628597"/>
<gml:surfaceMember xlink:href="#PolyIDGeo3628569"/>
<gml:surfaceMember xlink:href="#PolyIDGeo3628570"/>
<gml:surfaceMember xlink:href="#PolyIDGeo3628571"/>
<gml:surfaceMember xlink:href="#PolyIDGeo3628572"/>
<gml:surfaceMember xlink:href="#PolyIDGeo3628573"/>
<gml:surfaceMember xlink:href="#PolyIDGeo3628574"/>
<gml:surfaceMember>
<gml:Polygon gml:id="CityDoctor_1708591028834_67626">
<gml:exterior>
<gml:LinearRing gml:id="CityDoctor_1708591028834_67625">
<gml:posList srsDimension="3">518583.670057 5401170.997012 221.48 518574.663883 5401166.638461 221.48 518568.255395 5401179.993381 221.48 518566.005866 5401184.691595 221.48 518579.390493 5401191.139453 221.48 518581.669942 5401186.401255 221.48 518577.231719 5401184.281958 221.48 518583.670057 5401170.997012 221.48</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:CompositeSurface>
</gml:exterior>
</gml:Solid>
</bldg:lod2Solid>
<bldg:boundedBy>
<bldg:RoofSurface gml:id="CityDoctor_1708557190119_619">
<bldg:lod2MultiSurface>
<gml:MultiSurface gml:id="CityDoctor_1708557190119_620">
<gml:surfaceMember>
<gml:Polygon gml:id="PolyIDGeo4027008">
<gml:exterior>
<gml:LinearRing gml:id="ringID4027008">
<gml:posList srsDimension="3">518581.669942 5401186.401255 230.16 518579.390493 5401191.139453 230.16 518566.005866 5401184.691595 230.16 518568.255395 5401179.993381 230.16 518577.231719 5401184.281958 230.16 518581.669942 5401186.401255 230.16</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:RoofSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:RoofSurface gml:id="CityDoctor_1708557190119_621">
<bldg:lod2MultiSurface>
<gml:MultiSurface gml:id="CityDoctor_1708557190119_622">
<gml:surfaceMember>
<gml:Polygon gml:id="PolyIDGeo4027009">
<gml:exterior>
<gml:LinearRing gml:id="ringID4027009">
<gml:posList srsDimension="3">518568.255395 5401179.993381 231.78 518574.663883 5401166.638461 231.78 518583.670057 5401170.997012 231.78 518577.231719 5401184.281958 231.78 518568.255395 5401179.993381 231.78</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:RoofSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="CityDoctor_1708557190119_623">
<bldg:lod2MultiSurface>
<gml:MultiSurface gml:id="CityDoctor_1708557190119_624">
<gml:surfaceMember>
<gml:Polygon gml:id="PolyIDGeo3628596">
<gml:exterior>
<gml:LinearRing gml:id="ringID3628596">
<gml:posList srsDimension="3">518583.670057 5401170.997012 231.78 518574.663883 5401166.638461 231.78 518574.663883 5401166.638461 221.48 518583.670057 5401170.997012 221.48 518583.670057 5401170.997012 231.78</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="CityDoctor_1708557190119_625">
<bldg:lod2MultiSurface>
<gml:MultiSurface gml:id="CityDoctor_1708557190119_626">
<gml:surfaceMember>
<gml:Polygon gml:id="PolyIDGeo3628597">
<gml:exterior>
<gml:LinearRing gml:id="ringID3628597">
<gml:posList srsDimension="3">518577.231719 5401184.281958 230.16 518577.231719 5401184.281958 231.78 518583.670057 5401170.997012 231.78 518583.670057 5401170.997012 221.48 518577.231719 5401184.281958 221.48 518577.231719 5401184.281958 230.16</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="CityDoctor_1708557190119_627">
<bldg:lod2MultiSurface>
<gml:MultiSurface gml:id="CityDoctor_1708557190119_628">
<gml:surfaceMember>
<gml:Polygon gml:id="PolyIDGeo3628569">
<gml:exterior>
<gml:LinearRing gml:id="ringID3628569">
<gml:posList srsDimension="3">518568.255395 5401179.993381 231.78 518577.231719 5401184.281958 231.78 518577.231719 5401184.281958 230.16 518568.255395 5401179.993381 230.16 518568.255395 5401179.993381 231.78</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="CityDoctor_1708557190119_629">
<bldg:lod2MultiSurface>
<gml:MultiSurface gml:id="CityDoctor_1708557190119_630">
<gml:surfaceMember>
<gml:Polygon gml:id="PolyIDGeo3628570">
<gml:exterior>
<gml:LinearRing gml:id="ringID3628570">
<gml:posList srsDimension="3">518581.669942 5401186.401255 230.16 518577.231719 5401184.281958 230.16 518577.231719 5401184.281958 221.48 518581.669942 5401186.401255 221.48 518581.669942 5401186.401255 230.16</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="CityDoctor_1708557190119_631">
<bldg:lod2MultiSurface>
<gml:MultiSurface gml:id="CityDoctor_1708557190119_632">
<gml:surfaceMember>
<gml:Polygon gml:id="PolyIDGeo3628571">
<gml:exterior>
<gml:LinearRing gml:id="ringID3628571">
<gml:posList srsDimension="3">518566.005866 5401184.691595 230.16 518579.390493 5401191.139453 230.16 518579.390493 5401191.139453 221.48 518566.005866 5401184.691595 221.48 518566.005866 5401184.691595 230.16</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="CityDoctor_1708557190119_633">
<bldg:lod2MultiSurface>
<gml:MultiSurface gml:id="CityDoctor_1708557190119_634">
<gml:surfaceMember>
<gml:Polygon gml:id="PolyIDGeo3628572">
<gml:exterior>
<gml:LinearRing gml:id="ringID3628572">
<gml:posList srsDimension="3">518579.390493 5401191.139453 230.16 518581.669942 5401186.401255 230.16 518581.669942 5401186.401255 221.48 518579.390493 5401191.139453 221.48 518579.390493 5401191.139453 230.16</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="CityDoctor_1708557190119_635">
<bldg:lod2MultiSurface>
<gml:MultiSurface gml:id="CityDoctor_1708557190119_636">
<gml:surfaceMember>
<gml:Polygon gml:id="PolyIDGeo3628573">
<gml:exterior>
<gml:LinearRing gml:id="ringID3628573">
<gml:posList srsDimension="3">518574.663883 5401166.638461 231.78 518568.255395 5401179.993381 231.78 518568.255395 5401179.993381 230.16 518568.255395 5401179.993381 221.48 518574.663883 5401166.638461 221.48 518574.663883 5401166.638461 231.78</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="CityDoctor_1708557190119_637">
<bldg:lod2MultiSurface>
<gml:MultiSurface gml:id="CityDoctor_1708557190119_638">
<gml:surfaceMember>
<gml:Polygon gml:id="PolyIDGeo3628574">
<gml:exterior>
<gml:LinearRing gml:id="ringID3628574">
<gml:posList srsDimension="3">518568.255395 5401179.993381 230.16 518566.005866 5401184.691595 230.16 518566.005866 5401184.691595 221.48 518568.255395 5401179.993381 221.48 518568.255395 5401179.993381 230.16</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:address>
<core:Address gml:id="_ac1b4a9c-9542-4749-9501-167d0f8b635c">
<gml:description>DEBWL52210004T74</gml:description>
<core:xalAddress>
<xAL:AddressDetails>
<xAL:Locality Type="Town">
<xAL:LocalityName>Stuttgart</xAL:LocalityName>
<xAL:Thoroughfare Type="Street">
<xAL:ThoroughfareNumber>48</xAL:ThoroughfareNumber>
<xAL:ThoroughfareName Code="0811100029380">Kesselstraße</xAL:ThoroughfareName>
</xAL:Thoroughfare>
</xAL:Locality>
</xAL:AddressDetails>
</core:xalAddress>
</core:Address>
</bldg:address>
<bldg:address>
<core:Address gml:id="_479b87cd-927e-41c3-ae66-0d3397ddb656">
<gml:description>DEBWL522100042Dd</gml:description>
<core:xalAddress>
<xAL:AddressDetails>
<xAL:Locality Type="Town">
<xAL:LocalityName>Stuttgart</xAL:LocalityName>
<xAL:Thoroughfare Type="Street">
<xAL:ThoroughfareName Code="0811100029380">Kesselstraße</xAL:ThoroughfareName>
</xAL:Thoroughfare>
</xAL:Locality>
</xAL:AddressDetails>
</core:xalAddress>
</core:Address>
</bldg:address>
</bldg:BuildingPart>
</bldg:consistsOfBuildingPart>
<bldg:consistsOfBuildingPart>
<bldg:BuildingPart gml:id="DEBW522AA00021b89">
<gml:name>08111000_0_048_29380_000_001</gml:name>
<core:externalReference>
<core:informationSystem>Aufruf GrundIS</core:informationSystem>
<core:externalObject>
<core:name>https://grundis.lhs.stuttgart.de/amt62/GrundIS?ak=9&amp;amp;&amp;quot;amp;&amp;quot;lg=29380&amp;amp;&amp;quot;amp;&amp;quot;hn=48</core:name>
</core:externalObject>
</core:externalReference>
<gen:stringAttribute name="umbauterRaum">
<gen:value>1050.0</gen:value>
</gen:stringAttribute>
<gen:stringAttribute name="grundflaeche">
<gen:value>194.0</gen:value>
</gen:stringAttribute>
<gen:stringAttribute name="baublockNummer">
<gen:value>761505</gen:value>
</gen:stringAttribute>
<gen:stringAttribute name="verwaltendesAmt">
<gen:value/>
</gen:stringAttribute>
<gen:stringAttribute name="alkisFFDatum">
<gen:value>13.03.2023</gen:value>
</gen:stringAttribute>
<gen:stringAttribute name="LoD1_datenquelleBodenhoehe">
<gen:value>1000</gen:value>
</gen:stringAttribute>
<gen:stringAttribute name="gmlIdALKISLageBezeichnung_1">
<gen:value>DEBWL52210004OgK</gen:value>
</gen:stringAttribute>
<gen:stringAttribute name="LoD1_datenquelleLage">
<gen:value>1000</gen:value>
</gen:stringAttribute>
<gen:stringAttribute name="alkisId">
<gen:value>DEBWL52210003xgi</gen:value>
</gen:stringAttribute>
<gen:stringAttribute name="fortfuehrungsFall">
<gen:value>REPLACE</gen:value>
</gen:stringAttribute>
<gen:stringAttribute name="statusDesGebaeudes">
<gen:value>1</gen:value>
</gen:stringAttribute>
<gen:stringAttribute name="baublockseitenNummer">
<gen:value>2</gen:value>
</gen:stringAttribute>
<gen:stringAttribute name="geschossflaeche">
<gen:value>582.0</gen:value>
</gen:stringAttribute>
<bldg:function codeSpace="http://www.adv-online.de/codespaces/buildingfunctiontypeADV.xml">2120</bldg:function>
<bldg:yearOfConstruction>1979</bldg:yearOfConstruction>
<bldg:roofType codeSpace="http://www.adv-online.de/codespaces/rooftypetypeADV.xml">2100</bldg:roofType>
<bldg:measuredHeight uom="#m">9.6</bldg:measuredHeight>
<bldg:storeysAboveGround>2</bldg:storeysAboveGround>
<bldg:storeysBelowGround>1</bldg:storeysBelowGround>
<bldg:lod2Solid>
<gml:Solid gml:id="CityDoctor_1708557190212_662">
<gml:exterior>
<gml:CompositeSurface>
<gml:surfaceMember xlink:href="#PolyIDGeo4027002"/>
<gml:surfaceMember xlink:href="#PolyIDGeo4027003"/>
<gml:surfaceMember xlink:href="#PolyIDGeo3628575"/>
<gml:surfaceMember xlink:href="#PolyIDGeo3628576"/>
<gml:surfaceMember xlink:href="#PolyIDGeo3628577"/>
<gml:surfaceMember xlink:href="#PolyIDGeo3628578"/>
<gml:surfaceMember xlink:href="#PolyIDGeo3628579"/>
<gml:surfaceMember xlink:href="#PolyIDGeo3628580"/>
<gml:surfaceMember xlink:href="#PolyIDGeo3628581"/>
<gml:surfaceMember xlink:href="#PolyIDGeo3628582"/>
<gml:surfaceMember xlink:href="#PolyIDGeo3628583"/>
<gml:surfaceMember>
<gml:Polygon gml:id="CityDoctor_1708591028834_67628">
<gml:exterior>
<gml:LinearRing gml:id="CityDoctor_1708591028834_67627">
<gml:posList srsDimension="3">518589.138898 5401153.943323 221.46 518582.312001 5401150.64431 221.46 518574.663883 5401166.638461 221.46 518583.670057 5401170.997012 221.46 518589.198436 5401159.571358 221.46 518592.217139 5401161.050866 221.46 518594.446503 5401156.522537 221.46 518591.387881 5401155.032993 221.46 518589.138898 5401153.943323 221.46</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:CompositeSurface>
</gml:exterior>
</gml:Solid>
</bldg:lod2Solid>
<bldg:lod2MultiSurface>
<gml:MultiSurface gml:id="CityDoctor_1708557170737_14">
<gml:surfaceMember xlink:href="#PolyIDGeo4027002"/>
<gml:surfaceMember xlink:href="#PolyIDGeo4027003"/>
<gml:surfaceMember xlink:href="#PolyIDGeo3628575"/>
<gml:surfaceMember xlink:href="#PolyIDGeo3628576"/>
<gml:surfaceMember xlink:href="#PolyIDGeo3628577"/>
<gml:surfaceMember xlink:href="#PolyIDGeo3628578"/>
<gml:surfaceMember xlink:href="#PolyIDGeo3628579"/>
<gml:surfaceMember xlink:href="#PolyIDGeo3628580"/>
<gml:surfaceMember xlink:href="#PolyIDGeo3628581"/>
<gml:surfaceMember xlink:href="#PolyIDGeo3628582"/>
<gml:surfaceMember xlink:href="#PolyIDGeo3628583"/>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
<bldg:boundedBy>
<bldg:RoofSurface gml:id="CityDoctor_1708557190119_639">
<bldg:lod2MultiSurface>
<gml:MultiSurface gml:id="CityDoctor_1708557190119_640">
<gml:surfaceMember>
<gml:Polygon gml:id="PolyIDGeo4027002">
<gml:exterior>
<gml:LinearRing gml:id="ringID4027002">
<gml:posList srsDimension="3">518592.217139 5401161.050866 232.74 518589.198436 5401159.571358 232.74 518591.387881 5401155.032993 232.74 518594.446503 5401156.522537 232.74 518592.217139 5401161.050866 232.74</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:RoofSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:RoofSurface gml:id="CityDoctor_1708557190119_641">
<bldg:lod2MultiSurface>
<gml:MultiSurface gml:id="CityDoctor_1708557190119_642">
<gml:surfaceMember>
<gml:Polygon gml:id="PolyIDGeo4027003">
<gml:exterior>
<gml:LinearRing gml:id="ringID4027003">
<gml:posList srsDimension="3">518583.670057 5401170.997012 235.06 518574.663883 5401166.638461 235.06 518582.312001 5401150.64431 235.06 518589.138898 5401153.943323 235.06 518591.387881 5401155.032993 235.06 518589.198436 5401159.571358 235.06 518583.670057 5401170.997012 235.06</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:RoofSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="CityDoctor_1708557190119_643">
<bldg:lod2MultiSurface>
<gml:MultiSurface gml:id="CityDoctor_1708557190119_644">
<gml:surfaceMember>
<gml:Polygon gml:id="PolyIDGeo3628575">
<gml:exterior>
<gml:LinearRing gml:id="ringID3628575">
<gml:posList srsDimension="3">518589.198436 5401159.571358 232.74 518592.217139 5401161.050866 232.74 518592.217139 5401161.050866 221.46 518589.198436 5401159.571358 221.46 518589.198436 5401159.571358 232.74</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="CityDoctor_1708557190119_645">
<bldg:lod2MultiSurface>
<gml:MultiSurface gml:id="CityDoctor_1708557190119_646">
<gml:surfaceMember>
<gml:Polygon gml:id="PolyIDGeo3628576">
<gml:exterior>
<gml:LinearRing gml:id="ringID3628576">
<gml:posList srsDimension="3">518592.217139 5401161.050866 232.74 518594.446503 5401156.522537 232.74 518594.446503 5401156.522537 221.46 518592.217139 5401161.050866 221.46 518592.217139 5401161.050866 232.74</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="CityDoctor_1708557190119_647">
<bldg:lod2MultiSurface>
<gml:MultiSurface gml:id="CityDoctor_1708557190119_648">
<gml:surfaceMember>
<gml:Polygon gml:id="PolyIDGeo3628577">
<gml:exterior>
<gml:LinearRing gml:id="ringID3628577">
<gml:posList srsDimension="3">518574.663883 5401166.638461 235.06 518583.670057 5401170.997012 235.06 518583.670057 5401170.997012 221.46 518574.663883 5401166.638461 221.46 518574.663883 5401166.638461 235.06</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="CityDoctor_1708557190119_649">
<bldg:lod2MultiSurface>
<gml:MultiSurface gml:id="CityDoctor_1708557190119_650">
<gml:surfaceMember>
<gml:Polygon gml:id="PolyIDGeo3628578">
<gml:exterior>
<gml:LinearRing gml:id="ringID3628578">
<gml:posList srsDimension="3">518583.670057 5401170.997012 235.06 518589.198436 5401159.571358 235.06 518589.198436 5401159.571358 232.74 518589.198436 5401159.571358 221.46 518583.670057 5401170.997012 221.46 518583.670057 5401170.997012 235.06</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="CityDoctor_1708557190119_651">
<bldg:lod2MultiSurface>
<gml:MultiSurface gml:id="CityDoctor_1708557190119_652">
<gml:surfaceMember>
<gml:Polygon gml:id="PolyIDGeo3628579">
<gml:exterior>
<gml:LinearRing gml:id="ringID3628579">
<gml:posList srsDimension="3">518589.138898 5401153.943323 235.06 518582.312001 5401150.64431 235.06 518582.312001 5401150.64431 221.46 518589.138898 5401153.943323 221.46 518589.138898 5401153.943323 235.06</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="CityDoctor_1708557190119_653">
<bldg:lod2MultiSurface>
<gml:MultiSurface gml:id="CityDoctor_1708557190119_654">
<gml:surfaceMember>
<gml:Polygon gml:id="PolyIDGeo3628580">
<gml:exterior>
<gml:LinearRing gml:id="ringID3628580">
<gml:posList srsDimension="3">518582.312001 5401150.64431 235.06 518574.663883 5401166.638461 235.06 518574.663883 5401166.638461 221.46 518582.312001 5401150.64431 221.46 518582.312001 5401150.64431 235.06</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="CityDoctor_1708557190119_655">
<bldg:lod2MultiSurface>
<gml:MultiSurface gml:id="CityDoctor_1708557190119_656">
<gml:surfaceMember>
<gml:Polygon gml:id="PolyIDGeo3628581">
<gml:exterior>
<gml:LinearRing gml:id="ringID3628581">
<gml:posList srsDimension="3">518594.446503 5401156.522537 232.74 518591.387881 5401155.032993 232.74 518591.387881 5401155.032993 221.46 518594.446503 5401156.522537 221.46 518594.446503 5401156.522537 232.74</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="CityDoctor_1708557190119_657">
<bldg:lod2MultiSurface>
<gml:MultiSurface gml:id="CityDoctor_1708557190119_658">
<gml:surfaceMember>
<gml:Polygon gml:id="PolyIDGeo3628582">
<gml:exterior>
<gml:LinearRing gml:id="ringID3628582">
<gml:posList srsDimension="3">518591.387881 5401155.032993 232.74 518591.387881 5401155.032993 235.06 518589.138898 5401153.943323 235.06 518589.138898 5401153.943323 221.46 518591.387881 5401155.032993 221.46 518591.387881 5401155.032993 232.74</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="CityDoctor_1708557190119_659">
<bldg:lod2MultiSurface>
<gml:MultiSurface gml:id="CityDoctor_1708557190119_660">
<gml:surfaceMember>
<gml:Polygon gml:id="PolyIDGeo3628583">
<gml:exterior>
<gml:LinearRing gml:id="ringID3628583">
<gml:posList srsDimension="3">518591.387881 5401155.032993 232.74 518589.198436 5401159.571358 232.74 518589.198436 5401159.571358 235.06 518591.387881 5401155.032993 235.06 518591.387881 5401155.032993 232.74</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:address>
<core:Address gml:id="_ef529fad-91cb-4830-991c-9de65a5d9061">
<gml:description>DEBWL52210004OgK</gml:description>
<core:xalAddress>
<xAL:AddressDetails>
<xAL:Locality Type="Town">
<xAL:LocalityName>Stuttgart</xAL:LocalityName>
<xAL:Thoroughfare Type="Street">
<xAL:ThoroughfareName Code="0811100029380">Kesselstraße</xAL:ThoroughfareName>
</xAL:Thoroughfare>
</xAL:Locality>
</xAL:AddressDetails>
</core:xalAddress>
</core:Address>
</bldg:address>
</bldg:BuildingPart>
</bldg:consistsOfBuildingPart>
</bldg:Building>
</core:cityObjectMember>
</core:CityModel>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<core:CityModel xmlns:core="http://www.opengis.net/citygml/2.0" xmlns:gen="http://www.opengis.net/citygml/generics/2.0" xmlns:bldg="http://www.opengis.net/citygml/building/2.0" xmlns:app="http://www.opengis.net/citygml/appearance/2.0" xmlns:dem="http://www.opengis.net/citygml/relief/2.0" xmlns:gml="http://www.opengis.net/gml" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/citygml/building/2.0 http://schemas.opengis.net/citygml/building/2.0/building.xsd http://www.opengis.net/citygml/appearance/2.0 http://schemas.opengis.net/citygml/appearance/2.0/appearance.xsd http://www.opengis.net/citygml/relief/2.0 http://schemas.opengis.net/citygml/relief/2.0/relief.xsd http://www.opengis.net/citygml/2.0 http://schemas.opengis.net/citygml/2.0/cityGMLBase.xsd http://www.opengis.net/citygml/generics/2.0 http://schemas.opengis.net/citygml/generics/2.0/generics.xsd">
<!--
Einfaches Gebäude mit Grundriss 3m x 5m und Satteldach, Traufhöhe 3m, Firsthöhe 4,5m
Modelliert mit Begrenzungsflächen (eine Dachfläche, 4 Wandflächen, 1 Grundfläche), die Gebäudegeometrie als Solid, der auf die Polygone der Begrenzungsflächen referenziert
CityGML 2.0
linear ring _Simple_BD.1_PG.6_LR.1 (RoofSurface) hat nur 2 verschiedene Punkte
Author: V. Coors, 10.5.2017
Lizenz:
-->
<core:cityObjectMember>
<bldg:Building gml:id="Test-010-CP-NUMPOINTS">
<bldg:lod2Solid>
<gml:Solid>
<gml:exterior>
<gml:CompositeSurface>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.1"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.2"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.3"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.4"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.5"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.6"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.7"/>
</gml:CompositeSurface>
</gml:exterior>
</gml:Solid>
</bldg:lod2Solid>
<bldg:boundedBy>
<bldg:WallSurface gml:id="_Simple_BD.1_WallSurface_1">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.2">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.2_LR.1">
<gml:posList srsDimension="3">
13.0 15.0 0.0
13.0 15.0 3.0
13.0 10.0 3.0
13.0 10.0 0.0
13.0 15.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="_Simple_BD.1_WallSurface_2">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.3">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.3_LR.1">
<gml:posList srsDimension="3">
10.0 15.0 0.0
10.0 15.0 3.0
11.5 15.0 4.5
13.0 15.0 3.0
13.0 15.0 0.0
10.0 15.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="_Simple_BD.1_WallSurface_3">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.4">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.4_LR.1">
<gml:posList srsDimension="3">
10.0 10.0 3.0
10.0 15.0 3.0
10.0 15.0 0.0
10.0 10.0 0.0
10.0 10.0 3.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="_Simple_BD.1_WallSurface_4">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.5">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.5_LR.1">
<gml:posList srsDimension="3">
13.0 10.0 0.0
13.0 10.0 3.0
11.5 10.0 4.5
10.0 10.0 3.0
10.0 10.0 0.0
13.0 10.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:RoofSurface gml:id="_Simple_BD.1_RoofSurface_1">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.6">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.6_LR.1">
<gml:posList srsDimension="3">
10.0 10.0 3.0
11.5 10.0 4.5
10.0 10.0 3.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.7">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.7_LR.1">
<gml:posList srsDimension="3">
11.5 10.0 4.5
13.0 10.0 3.0
13.0 15.0 3.0
11.5 15.0 4.5
11.5 10.0 4.5
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:RoofSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:GroundSurface gml:id="_Simple_BD.1_GroundSurface_1">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.1">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.1_LR.1">
<gml:posList srsDimension="3">
10.0 10.0 0.0
10.0 15.0 0.0
13.0 15.0 0.0
13.0 10.0 0.0
10.0 10.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:GroundSurface>
</bldg:boundedBy>
</bldg:Building>
</core:cityObjectMember>
</core:CityModel>
<?xml version="1.0" encoding="utf-8"?>
<core:CityModel xmlns:core="http://www.opengis.net/citygml/2.0" xmlns:gen="http://www.opengis.net/citygml/generics/2.0" xmlns:bldg="http://www.opengis.net/citygml/building/2.0" xmlns:app="http://www.opengis.net/citygml/appearance/2.0" xmlns:dem="http://www.opengis.net/citygml/relief/2.0" xmlns:gml="http://www.opengis.net/gml" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/citygml/building/2.0 http://schemas.opengis.net/citygml/building/2.0/building.xsd http://www.opengis.net/citygml/appearance/2.0 http://schemas.opengis.net/citygml/appearance/2.0/appearance.xsd http://www.opengis.net/citygml/relief/2.0 http://schemas.opengis.net/citygml/relief/2.0/relief.xsd http://www.opengis.net/citygml/2.0 http://schemas.opengis.net/citygml/2.0/cityGMLBase.xsd http://www.opengis.net/citygml/generics/2.0 http://schemas.opengis.net/citygml/generics/2.0/generics.xsd">
<!--
Einfaches Gebäude mit Grundriss 3m x 5m und Satteldach, Traufhöhe 3m, Firsthöhe 4,5m
Modelliert mit Begrenzungsflächen (eine Dachfläche, 4 Wandflächen, 1 Grundfläche),
die Gebäudegeometrie als Solid, der auf die Polygone der Begrenzungsflächen referenziert
CityGML 2.0
linear ring _Simple_BD.1_PG.6_LR.1 beinhaltet zwei aufeinander folgende Punkte, die identisch sind.
10.5.2017
Author: V. Coors, HFT Stuttgart
Lizenz:
-->
<core:cityObjectMember>
<bldg:Building gml:id="_Simple_BD.1">
<bldg:lod2Solid>
<gml:Solid>
<gml:exterior>
<gml:CompositeSurface>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.1"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.2"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.3"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.4"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.5"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.6"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.7"/>
</gml:CompositeSurface>
</gml:exterior>
</gml:Solid>
</bldg:lod2Solid>
<bldg:boundedBy>
<bldg:WallSurface gml:id="_Simple_BD.1_WallSurface_1">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.2">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.2_LR.1">
<gml:posList srsDimension="3">
13.0 15.0 0.0
13.0 15.0 3.0
13.0 10.0 3.0
13.0 10.0 0.0
13.0 15.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="_Simple_BD.1_WallSurface_2">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.3">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.3_LR.1">
<gml:posList srsDimension="3">
10.0 15.0 0.0
10.0 15.0 3.0
11.5 15.0 4.5
13.0 15.0 3.0
13.0 15.0 0.0
10.0 15.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="_Simple_BD.1_WallSurface_3">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.4">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.4_LR.1">
<gml:posList srsDimension="3">
10.0 10.0 3.0
10.0 15.0 3.0
10.0 15.0 0.0
10.0 10.0 0.0
10.0 10.0 3.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="_Simple_BD.1_WallSurface_4">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.5">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.5_LR.1">
<gml:posList srsDimension="3">
13.0 10.0 0.0
13.0 10.0 3.0
11.5 10.0 4.5
10.0 10.0 3.0
10.0 10.0 0.0
13.0 10.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:RoofSurface gml:id="_Simple_BD.1_RoofSurface_1">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.6">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.6_LR.1">
<gml:posList srsDimension="3">
10.0 10.0 3.0
11.5 10.0 4.5
11.5 10.0 4.5
11.5 15.0 4.5
10.0 15.0 3.0
10.0 10.0 3.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.7">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.7_LR.1">
<gml:posList srsDimension="3">
11.5 10.0 4.5
13.0 10.0 3.0
13.0 15.0 3.0
11.5 15.0 4.5
11.5 10.0 4.5
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:RoofSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:GroundSurface gml:id="_Simple_BD.1_GroundSurface_1">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.1">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.1_LR.1">
<gml:posList srsDimension="3">
10.0 10.0 0.0
10.0 15.0 0.0
13.0 15.0 0.0
13.0 10.0 0.0
10.0 10.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:GroundSurface>
</bldg:boundedBy>
</bldg:Building>
</core:cityObjectMember>
</core:CityModel>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<core:CityModel xmlns:core="http://www.opengis.net/citygml/2.0" xmlns:gen="http://www.opengis.net/citygml/generics/2.0" xmlns:bldg="http://www.opengis.net/citygml/building/2.0" xmlns:app="http://www.opengis.net/citygml/appearance/2.0" xmlns:dem="http://www.opengis.net/citygml/relief/2.0" xmlns:gml="http://www.opengis.net/gml" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/citygml/building/2.0 http://schemas.opengis.net/citygml/building/2.0/building.xsd http://www.opengis.net/citygml/appearance/2.0 http://schemas.opengis.net/citygml/appearance/2.0/appearance.xsd http://www.opengis.net/citygml/relief/2.0 http://schemas.opengis.net/citygml/relief/2.0/relief.xsd http://www.opengis.net/citygml/2.0 http://schemas.opengis.net/citygml/2.0/cityGMLBase.xsd http://www.opengis.net/citygml/generics/2.0 http://schemas.opengis.net/citygml/generics/2.0/generics.xsd">
<!--
Einfaches Gebäude mit Grundriss 3m x 5m und Satteldach, Traufhöhe 3m, Firsthöhe 4,5m
Modelliert mit Begrenzungsflächen (eine Dachfläche, 4 Wandflächen, 1 Grundfläche), die Gebäudegeometrie als Solid, der auf die Polygone der Begrenzungsflächen referenziert
CityGML 2.0
linear ring _Simple_BD.1_PG.6_LR.1 beinhaltet einen doppelten Punkt, der aber nicht direkt folgt.
Kann auch als Selbst-Verschneidung interpretiert werden.
10.5.2017
Author: V. Coors, HFT Stuttgart
Lizenz:
-->
<core:cityObjectMember>
<bldg:Building gml:id="_Simple_BD.1">
<bldg:lod2Solid>
<gml:Solid>
<gml:exterior>
<gml:CompositeSurface>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.1"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.2"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.3"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.4"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.5"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.6"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.7"/>
</gml:CompositeSurface>
</gml:exterior>
</gml:Solid>
</bldg:lod2Solid>
<bldg:boundedBy>
<bldg:WallSurface gml:id="_Simple_BD.1_WallSurface_1">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.2">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.2_LR.1">
<gml:posList srsDimension="3">
13.0 15.0 0.0
13.0 15.0 3.0
13.0 10.0 3.0
13.0 10.0 0.0
13.0 15.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="_Simple_BD.1_WallSurface_2">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.3">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.3_LR.1">
<gml:posList srsDimension="3">
10.0 15.0 0.0
10.0 15.0 3.0
11.5 15.0 4.5
13.0 15.0 3.0
13.0 15.0 0.0
10.0 15.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="_Simple_BD.1_WallSurface_3">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.4">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.4_LR.1">
<gml:posList srsDimension="3">
10.0 10.0 3.0
10.0 15.0 3.0
10.0 15.0 0.0
10.0 10.0 0.0
10.0 10.0 3.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="_Simple_BD.1_WallSurface_4">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.5">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.5_LR.1">
<gml:posList srsDimension="3">
13.0 10.0 0.0
13.0 10.0 3.0
11.5 10.0 4.5
10.0 10.0 3.0
10.0 10.0 0.0
13.0 10.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:RoofSurface gml:id="_Simple_BD.1_RoofSurface_1">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.6">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.6_LR.1">
<gml:posList srsDimension="3">
10.0 10.0 3.0
11.5 10.0 4.5
11.5 15.0 4.5
11.5 10.0 4.5
10.0 15.0 3.0
10.0 10.0 3.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.7">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.7_LR.1">
<gml:posList srsDimension="3">
11.5 10.0 4.5
13.0 10.0 3.0
13.0 15.0 3.0
11.5 15.0 4.5
11.5 10.0 4.5
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:RoofSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:GroundSurface gml:id="_Simple_BD.1_GroundSurface_1">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.1">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.1_LR.1">
<gml:posList srsDimension="3">
10.0 10.0 0.0
10.0 15.0 0.0
13.0 15.0 0.0
13.0 10.0 0.0
10.0 10.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:GroundSurface>
</bldg:boundedBy>
</bldg:Building>
</core:cityObjectMember>
</core:CityModel>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<core:CityModel xmlns:core="http://www.opengis.net/citygml/2.0" xmlns:gen="http://www.opengis.net/citygml/generics/2.0" xmlns:bldg="http://www.opengis.net/citygml/building/2.0" xmlns:app="http://www.opengis.net/citygml/appearance/2.0" xmlns:dem="http://www.opengis.net/citygml/relief/2.0" xmlns:gml="http://www.opengis.net/gml" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/citygml/building/2.0 http://schemas.opengis.net/citygml/building/2.0/building.xsd http://www.opengis.net/citygml/appearance/2.0 http://schemas.opengis.net/citygml/appearance/2.0/appearance.xsd http://www.opengis.net/citygml/relief/2.0 http://schemas.opengis.net/citygml/relief/2.0/relief.xsd http://www.opengis.net/citygml/2.0 http://schemas.opengis.net/citygml/2.0/cityGMLBase.xsd http://www.opengis.net/citygml/generics/2.0 http://schemas.opengis.net/citygml/generics/2.0/generics.xsd">
<!--
Einfaches Gebäude mit Grundriss 3m x 5m und Satteldach, Traufhöhe 3m, Firsthöhe 4,5m
Modelliert mit Begrenzungsflächen (eine Dachfläche, 4 Wandflächen, 1 Grundfläche),
die Gebäudegeometrie als Solid, der auf die Polygone der Begrenzungsflächen referenziert
CityGML 2.0
linear ring _Simple_BD.1_PG.6_LR.1 ist nicht geschlossen,
d.h. erster und letzter Punkt sind nicht identisch
10.5.2017
Author: V. Coors, HFT Stuttgart
Lizenz:
-->
<core:cityObjectMember>
<bldg:Building gml:id="_Simple_BD.1">
<bldg:lod2Solid>
<gml:Solid>
<gml:exterior>
<gml:CompositeSurface>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.1"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.2"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.3"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.4"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.5"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.6"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.7"/>
</gml:CompositeSurface>
</gml:exterior>
</gml:Solid>
</bldg:lod2Solid>
<bldg:boundedBy>
<bldg:WallSurface gml:id="_Simple_BD.1_WallSurface_1">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.2">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.2_LR.1">
<gml:posList srsDimension="3">
13.0 15.0 0.0
13.0 15.0 3.0
13.0 10.0 3.0
13.0 10.0 0.0
13.0 15.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="_Simple_BD.1_WallSurface_2">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.3">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.3_LR.1">
<gml:posList srsDimension="3">
10.0 15.0 0.0
10.0 15.0 3.0
11.5 15.0 4.5
13.0 15.0 3.0
13.0 15.0 0.0
10.0 15.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="_Simple_BD.1_WallSurface_3">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.4">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.4_LR.1">
<gml:posList srsDimension="3">
10.0 10.0 3.0
10.0 15.0 3.0
10.0 15.0 0.0
10.0 10.0 0.0
10.0 10.0 3.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="_Simple_BD.1_WallSurface_4">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.5">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.5_LR.1">
<gml:posList srsDimension="3">
13.0 10.0 0.0
13.0 10.0 3.0
11.5 10.0 4.5
10.0 10.0 3.0
10.0 10.0 0.0
13.0 10.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:RoofSurface gml:id="_Simple_BD.1_RoofSurface_1">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.6">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.6_LR.1">
<gml:posList srsDimension="3">
10.0 10.0 3.0
11.5 10.0 4.5
11.5 15.0 4.5
10.0 15.0 3.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.7">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.7_LR.1">
<gml:posList srsDimension="3">
11.5 10.0 4.5
13.0 10.0 3.0
13.0 15.0 3.0
11.5 15.0 4.5
11.5 10.0 4.5
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:RoofSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:GroundSurface gml:id="_Simple_BD.1_GroundSurface_1">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.1">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.1_LR.1">
<gml:posList srsDimension="3">
10.0 10.0 0.0
10.0 15.0 0.0
13.0 15.0 0.0
13.0 10.0 0.0
10.0 10.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:GroundSurface>
</bldg:boundedBy>
</bldg:Building>
</core:cityObjectMember>
</core:CityModel>
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment