Commit 3032c1f9 authored by Numanoglu's avatar Numanoglu
Browse files

Add synthetic sweep planarity test models

parent cec0e9d5
Pipeline #12402 passed with stage
in 2 minutes and 17 seconds
...@@ -36,6 +36,30 @@ import org.junit.experimental.categories.Category; ...@@ -36,6 +36,30 @@ import org.junit.experimental.categories.Category;
public class HealPlanarPolygonErrorTest { public class HealPlanarPolygonErrorTest {
@Test
public void testRaisedTopCornerCubeHasNonPlanarPolygon() {
Building building = SyntheticSweepPlanarityModelFactory.createRaisedTopCornerCube();
Geometry geom = building.getGeometries().get(0);
PlanarCheck check = new PlanarCheck();
geom.accept(check);
check.check(geom);
Assert.assertTrue(geom.containsError(CheckId.C_GE_P_NON_PLANAR));
}
@Test
public void testExistingHealerModelHasNonPlanarPolygon() {
Building building = SyntheticSweepPlanarityModelFactory.createExistingHealerTestModel();
Geometry geom = building.getGeometries().get(0);
PlanarCheck check = new PlanarCheck();
geom.accept(check);
check.check(geom);
Assert.assertTrue(geom.containsError(CheckId.C_GE_P_NON_PLANAR));
}
@Test @Test
public void testPlanarPlaneDistance() throws CityGmlParseException, IOException, InvalidGmlFileException { public void testPlanarPlaneDistance() throws CityGmlParseException, IOException, InvalidGmlFileException {
// Model with a non planar wall on the east side // Model with a non planar wall on the east side
......
...@@ -4,11 +4,7 @@ import java.io.File; ...@@ -4,11 +4,7 @@ import java.io.File;
import org.citygml4j.core.model.CityGMLVersion; import org.citygml4j.core.model.CityGMLVersion;
import org.citygml4j.core.model.core.CityModel; import org.citygml4j.core.model.core.CityModel;
import org.junit.Assert;
import org.junit.Test;
import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.checks.geometry.PlanarCheck;
import de.hft.stuttgart.citydoctor2.database.UnconnectedCache; import de.hft.stuttgart.citydoctor2.database.UnconnectedCache;
import de.hft.stuttgart.citydoctor2.datastructure.Building; import de.hft.stuttgart.citydoctor2.datastructure.Building;
import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel; import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel;
...@@ -24,36 +20,61 @@ import de.hft.stuttgart.citydoctor2.datastructure.Vertex; ...@@ -24,36 +20,61 @@ import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
import de.hft.stuttgart.citydoctor2.exceptions.CityDoctorWriteException; import de.hft.stuttgart.citydoctor2.exceptions.CityDoctorWriteException;
import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration; import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;
public class SyntheticSweepPlanarityModelTest { public class SyntheticSweepPlanarityModelFactory {
public static void main(String[] args) throws CityDoctorWriteException { public static void main(String[] args) throws CityDoctorWriteException {
exportBuildingForGui(createSweepPlanarityCubeWithRaisedTopCorner(), new File("sweep-planarity-raised-top-corner.gml")); exportForGui(
exportBuildingForGui(createNonPlanarSweepBox(), new File("sweep-planarity-existing-healer-test-model.gml")); createRaisedTopCornerCube(),
new File("sweep-planarity-raised-top-corner.gml"),
"SweepPlanarityRaisedTopCorner");
exportForGui(
createExistingHealerTestModel(),
new File("sweep-planarity-existing-healer-test-model.gml"),
"SweepPlanarityExistingHealerTestModel");
exportForGui(
createWallWithProtrudingWindowInnerRingPoint(),
new File("sweep-case1-wall-window-inner-ring-point.gml"),
"SweepCase1WallWindowInnerRingPoint");
exportForGui(
createWallWithProtrudingFacadePolygonPoint(),
new File("sweep-case1-wall-facade-polygon-point.gml"),
"SweepCase1WallFacadePolygonPoint");
exportForGui(
createSlopedRoofWithProtrudingOpeningRingPoint(),
new File("sweep-case1-sloped-roof-opening-ring-point.gml"),
"SweepCase1SlopedRoofOpeningRingPoint");
} }
static Building createNonPlanarCube(double boxsize, double bottomerr, double topLift) {
Building building = new Building();
Geometry geom = new Geometry(GeometryType.SOLID, Lod.LOD2, Orientation.OUTWARD);
building.addGeometry(geom);
@Test Vertex v0 = new Vertex(0, 0, 0);
public void testSyntheticSweepPlanarityCubeHasNonPlanarTopFace() { Vertex v1 = new Vertex(boxsize, 0, 0);
Building building = createSweepPlanarityCubeWithRaisedTopCorner(); Vertex v4 = new Vertex(boxsize, boxsize, bottomerr);
Geometry geom = building.getGeometries().get(0); Vertex v6 = new Vertex(0, boxsize, 0);
Vertex v8 = new Vertex(boxsize, 0, boxsize);
PlanarCheck check = new PlanarCheck(); Vertex v9 = new Vertex(boxsize, boxsize, boxsize);
geom.accept(check); Vertex v10 = new Vertex(0, boxsize, boxsize);
check.check(geom); Vertex v11 = new Vertex(0, 0, boxsize + topLift);
Assert.assertTrue(geom.containsError(CheckId.C_GE_P_NON_PLANAR)); addPolygon(geom, v0, v1, v4, v6);
} addPolygon(geom, v1, v8, v9, v4);
addPolygon(geom, v8, v11, v10, v9);
addPolygon(geom, v0, v6, v10, v11);
addPolygon(geom, v4, v9, v10, v6);
addPolygon(geom, v0, v11, v8, v1);
@Test geom.updateEdgesAndVertices();
public void exportSyntheticSweepPlanarityCubeForGui() throws CityDoctorWriteException { return building;
exportBuildingForGui(createSweepPlanarityCubeWithRaisedTopCorner(), new File("sweep-planarity-raised-top-corner.gml"));
}
@Test
public void exportNonPlanarSweepBoxForGui() throws CityDoctorWriteException {
exportBuildingForGui(createNonPlanarSweepBox(), new File("sweep-planarity-existing-healer-test-model.gml"));
} }
static Building createSweepPlanarityCubeWithRaisedTopCorner() { static Building createRaisedTopCornerCube() {
Building building = new Building(); Building building = new Building();
Geometry geom = new Geometry(GeometryType.SOLID, Lod.LOD2, Orientation.OUTWARD); Geometry geom = new Geometry(GeometryType.SOLID, Lod.LOD2, Orientation.OUTWARD);
building.addGeometry(geom); building.addGeometry(geom);
...@@ -78,7 +99,83 @@ public class SyntheticSweepPlanarityModelTest { ...@@ -78,7 +99,83 @@ public class SyntheticSweepPlanarityModelTest {
return building; return building;
} }
static Building createNonPlanarSweepBox() { /**
* Fall 1 model: one point of a window-like inner ring protrudes from an otherwise
* planar wall. The intended target plane is x = 0 and the protruding ring point
* has no outgoing solid edge, so it should be orthogonally projected back.
*/
static Building createWallWithProtrudingWindowInnerRingPoint() {
Building building = new Building();
Geometry geom = new Geometry(GeometryType.MULTI_SURFACE, Lod.LOD2, Orientation.OUTWARD);
building.addGeometry(geom);
Polygon wall = addPolygon(geom,
new Vertex(0, 0, 0),
new Vertex(0, 6, 0),
new Vertex(0, 6, 4),
new Vertex(0, 0, 4));
addInteriorRing(wall,
new Vertex(0, 2, 1),
new Vertex(0, 4, 1),
new Vertex(0.3, 4, 3),
new Vertex(0, 2, 3));
geom.updateEdgesAndVertices();
return building;
}
/**
* Fall 1 model: a separate facade/window polygon should lie on the wall plane
* x = 0, but one polygon corner sticks out. Because the facade polygon is not
* topologically connected to a solid edge, the faulty point is a pure projection
* case.
*/
static Building createWallWithProtrudingFacadePolygonPoint() {
Building building = new Building();
Geometry geom = new Geometry(GeometryType.MULTI_SURFACE, Lod.LOD2, Orientation.OUTWARD);
building.addGeometry(geom);
addPolygon(geom,
new Vertex(0, 0, 0),
new Vertex(0, 6, 0),
new Vertex(0, 6, 4),
new Vertex(0, 0, 4));
addPolygon(geom,
new Vertex(0, 2, 1),
new Vertex(0, 4, 1),
new Vertex(0.3, 4, 3),
new Vertex(0, 2, 3));
geom.updateEdgesAndVertices();
return building;
}
/**
* Fall 1 model: an opening ring in a sloped roof has one point outside the roof
* plane. This checks projection to a general oblique target plane instead of an
* axis-aligned wall plane.
*/
static Building createSlopedRoofWithProtrudingOpeningRingPoint() {
Building building = new Building();
Geometry geom = new Geometry(GeometryType.MULTI_SURFACE, Lod.LOD2, Orientation.OUTWARD);
building.addGeometry(geom);
Polygon roof = addPolygon(geom,
new Vertex(0, 0, 2),
new Vertex(4, 0, 4),
new Vertex(4, 4, 4),
new Vertex(0, 4, 2));
addInteriorRing(roof,
new Vertex(1, 1, 2.5),
new Vertex(3, 1, 3.5),
new Vertex(3, 3, 4.0),
new Vertex(1, 3, 2.5));
geom.updateEdgesAndVertices();
return building;
}
static Building createExistingHealerTestModel() {
Building building = new Building(); Building building = new Building();
Geometry geom = new Geometry(GeometryType.SOLID, Lod.LOD2, Orientation.OUTWARD); Geometry geom = new Geometry(GeometryType.SOLID, Lod.LOD2, Orientation.OUTWARD);
building.addGeometry(geom); building.addGeometry(geom);
...@@ -103,27 +200,27 @@ public class SyntheticSweepPlanarityModelTest { ...@@ -103,27 +200,27 @@ public class SyntheticSweepPlanarityModelTest {
return building; return building;
} }
private static CityDoctorModel createCityDoctorModel(Building building, File sourceFile) { private static void exportForGui(Building building, File output, String gmlId) throws CityDoctorWriteException {
CityDoctorModel model = createCityDoctorModel(building, output, gmlId);
model.saveAs(output.getAbsolutePath(), false);
System.out.println("Open in CityDoctor GUI:");
System.out.println(output.getAbsolutePath());
}
private static CityDoctorModel createCityDoctorModel(Building building, File sourceFile, String gmlId) {
ParserConfiguration config = new ParserConfiguration(8, false); ParserConfiguration config = new ParserConfiguration(8, false);
CityDoctorModel model = new CityDoctorModel(config, sourceFile, new UnconnectedCache()); CityDoctorModel model = new CityDoctorModel(config, sourceFile, new UnconnectedCache());
model.setParsedCityGMLVersion(CityGMLVersion.v2_0); model.setParsedCityGMLVersion(CityGMLVersion.v2_0);
model.setCityModel(new CityModel()); model.setCityModel(new CityModel());
org.citygml4j.core.model.building.Building gmlBuilding = new org.citygml4j.core.model.building.Building(); org.citygml4j.core.model.building.Building gmlBuilding = new org.citygml4j.core.model.building.Building();
gmlBuilding.setId("SyntheticSweepPlanarityRaisedCorner"); gmlBuilding.setId(gmlId);
building.setGmlObject(gmlBuilding); building.setGmlObject(gmlBuilding);
model.addBuilding(building); model.addBuilding(building);
return model; return model;
} }
private static void exportBuildingForGui(Building building, File output) throws CityDoctorWriteException {
CityDoctorModel model = createCityDoctorModel(building, output);
model.saveAs(output.getAbsolutePath(), false);
System.out.println("Open in CityDoctor GUI:");
System.out.println(output.getAbsolutePath());
}
private static Polygon addPolygon(Geometry geom, Vertex... vertices) { private static Polygon addPolygon(Geometry geom, Vertex... vertices) {
Polygon polygon = new ConcretePolygon(); Polygon polygon = new ConcretePolygon();
geom.addPolygon(polygon); geom.addPolygon(polygon);
...@@ -136,4 +233,14 @@ public class SyntheticSweepPlanarityModelTest { ...@@ -136,4 +233,14 @@ public class SyntheticSweepPlanarityModelTest {
return polygon; return polygon;
} }
private static LinearRing addInteriorRing(Polygon polygon, Vertex... vertices) {
LinearRing ring = new LinearRing(LinearRingType.INTERIOR);
polygon.addInteriorRing(ring);
for (Vertex vertex : vertices) {
ring.addVertex(vertex);
}
ring.addVertex(vertices[0]);
return ring;
}
} }
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