Commit 03bb154f authored by Matthias Betz's avatar Matthias Betz
Browse files

fixing an endless loop in edge because of composite surfaces

parent ea3e78be
Pipeline #5705 passed with stage
in 3 minutes and 25 seconds
......@@ -19,12 +19,18 @@
package de.hft.stuttgart.citydoctor2.edge;
import java.text.NumberFormat;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
public class DebugUtils {
private static AtomicInteger polygon3dCounter = new AtomicInteger(1);
......@@ -204,5 +210,40 @@ public class DebugUtils {
System.out.println("CDPolygonNs* p" + counter + " = new CDPolygonNs(coords" + firstListCounter + ");");
return counterArr[0];
}
public static int printCityDoctorPolygons(Polygon... polygons) {
Locale.setDefault(Locale.US);
NumberFormat nf = NumberFormat.getNumberInstance();
nf.setMaximumFractionDigits(30);
nf.setGroupingUsed(false);
Map<Vertex, String> pointMap = new HashMap<>();
AtomicInteger counter = new AtomicInteger(0);
int listCounter = 0;
for (Polygon p : polygons) {
LinearRing ext = p.getExteriorRing();
System.out.println("Coordinate3dList coords" + listCounter + ";");
for (int i = 0; i < ext.getVertices().size() - 1; i++) {
Vertex v = ext.getVertices().get(i);
String coordName = pointMap.computeIfAbsent(v, key -> {
int index = counter.getAndIncrement();
System.out.println(String.format("Coordinate3d* c%d = new Coordinate3d(%s, %s, %s);", index, nf.format(v.getX()), nf.format(v.getY()), nf.format(v.getZ())));
return "c" + index;
});
System.out.println(String.format("coords%d.push_back(%s);", listCounter, coordName));
}
System.out.println("CDPolygonNs* p" + listCounter + " = new CDPolygonNs(coords" + listCounter + ");");
listCounter++;
}
return listCounter;
}
public static void printCityDoctorGeometry(Geometry geom) {
int listCounter = printCityDoctorPolygons(geom.getPolygons().toArray(new Polygon[0]));
System.out.println("CDPolygonNsList polygons;");
for (int i = 0; i < listCounter; i++) {
System.out.println("polygons.push_back(p" + i + ");");
}
System.out.println("CDMeshSurfaceNs* surface = new CDMeshSurfaceNs(polygons);");
}
}
......@@ -20,8 +20,15 @@ package de.hft.stuttgart.citydoctor2.edge;
import java.util.List;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class HalfEdge extends BaseEntity {
private static final Logger logger = LogManager.getLogger(HalfEdge.class);
private static final boolean ALLOW_CIRCULAR_CHAINS = false;
private Coordinate3d start;
private Coordinate3d end;
......@@ -89,8 +96,64 @@ public class HalfEdge extends BaseEntity {
}
public void setPartner(HalfEdge partner) {
this.partner = partner;
partner.partner = this;
if (partner == this) {
logger.debug("HalfEdge.setPartner() : cannot reference myself");
return;
}
if (null != this.partner) {
if (null != partner) {
if (ALLOW_CIRCULAR_CHAINS) {
// check if the the partner already exists in the list of partners
HalfEdge pNextPartner = this.partner;
while (pNextPartner != this) {
if (pNextPartner == partner) {
logger.debug("(HalfEdge " + partner + " already exits in chain");
return;
}
pNextPartner = pNextPartner.partner;
}
// insert new partner in list
partner.partner = this.partner;
this.partner = partner;
} else {
logger.debug("Cannot overwrite existing partner-connection, set the connection to null first!");
}
} else {
// remove the existing connection
this.partner.partner = null;
this.partner = null;
}
} else {
if (partner != null) {
if (partner.partner != null) {
if (ALLOW_CIRCULAR_CHAINS) {
// this partner pointer is NULL and pPartner->mpPartner is not
// NULL ==> insert this half edge in the chain of pPartner
// first get the predecessor half edge of pPartner
HalfEdge pNextPartner = partner.partner;
HalfEdge pPreviousPartner = partner;
while (pNextPartner != partner) {
pPreviousPartner = pNextPartner;
pNextPartner = pNextPartner.partner;
}
// insert new partner in list
pPreviousPartner.partner = this;
this.partner = partner;
} else {
/**
* TODO : das riecht nach einer Ringverzeigerung : 3 Polygonraender treffen auf
* einander
*/
logger.debug("Cannot overwrite existing partner-connection, set the connection to null first!");
}
} else {
this.partner = partner;
partner.partner = this;
}
}
}
}
public HalfEdge getPartner() {
......
......@@ -29,11 +29,17 @@ import java.util.List;
import org.junit.Test;
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.parser.CityGmlParseException;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParser;
import de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException;
import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;
import de.hft.stuttgart.citydoctor2.datastructure.Lod;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
......@@ -1247,5 +1253,17 @@ public class MeshSurfaceUtilsTest {
assertNotNull(intersectPolygons);
assertTrue(intersectPolygons.isEmpty());
}
@Test(timeout = 10000)
public void testKaiserwallComplexBuilding() throws CityGmlParseException, InvalidGmlFileException {
ParserConfiguration config = new ParserConfiguration(8, false);
CityDoctorModel model = CityGmlParser.parseCityGmlFile("src/test/resources/KaiserwallComplexBuilding.gml", config);
Building building = model.getBuildings().get(0);
Geometry geom = building.getBuildingInstallations().get(0).getGeometries().get(0);
assertNotNull(geom);
MeshSurface surface = MeshSurface.of(geom);
List<PolygonPolygonIntersection> selfIntersects = MeshSurfaceUtils.selfIntersects(surface, 0.000001, 0.001);
assertTrue(selfIntersects.isEmpty());
}
}
......@@ -147,6 +147,9 @@ public class Geometry extends GmlElement {
}
private void createEdgesFromRing(Map<Edge, Edge> duplicacyMap, Polygon p, LinearRing ring) {
if (ring == null) {
return;
}
// only go to size -1 as ring should be closed
for (int i = 0; i < ring.getVertices().size() - 1; i++) {
Vertex v0 = ring.getVertices().get(i + 0);
......@@ -307,6 +310,9 @@ public class Geometry extends GmlElement {
}
private void updateRing(Set<Vertex> vertexSet, LinearRing ring) {
if (ring == null) {
return;
}
for (Vertex v : ring.getVertices()) {
if (vertexSet.add(v)) {
// new vertex, clear adjacent rings in case new rings have been added
......
......@@ -5,10 +5,10 @@
<pattern>
<rule context="//*:Building">
<assert test="count(descendant::*:lod1Solid) &gt; 0 or count(descendant::*:lod2Solid) &gt; 0 or count(descendant::*:lod3Solid) &gt; 0 or count(descendant::*:lod4Solid) &gt; 0"><value-of select="@gml:id | @id"/>||||SE_ATTRIBUTE_MISSING||any solid||false</assert>
<assert test="count(descendant::*:lod1Solid) &gt; 0 or count(descendant::*:lod2Solid) &gt; 0 or count(descendant::*:lod3Solid) &gt; 0 or count(descendant::*:lod4Solid) &gt; 0"><value-of select="@gml:id | @id"/>||||SE_ATTRIBUTE_MISSING||lodXsolid||false</assert>
</rule>
<rule context="//*:BuildingPart">
<assert test="count(*:lod1Solid) = 1 or count(*:lod2Solid) = 1 or count(*:lod3Solid) = 1 or count(*:lod4Solid) = 1"><value-of select="ancestor::*:Building/@*:id"/>||<value-of select="@gml:id | @id"/>||SE_ATTRIBUTE_MISSING||any solid||false</assert>
<assert test="count(*:lod1Solid) = 1 or count(*:lod2Solid) = 1 or count(*:lod3Solid) = 1 or count(*:lod4Solid) = 1"><value-of select="ancestor::*:Building/@*:id"/>||<value-of select="@gml:id | @id"/>||SE_ATTRIBUTE_MISSING||lodXsolid||false</assert>
</rule>
</pattern>
</schema>
......@@ -75,7 +75,7 @@ public class SelfIntersectionUtil {
private static final Logger logger = LogManager.getLogger(SelfIntersectionUtil.class);
private static boolean useEdge = false;
private static boolean useEdge = true;
private static GeometryFactory factory = new GeometryFactory(new PrecisionModel(PrecisionModel.FLOATING));
......@@ -95,26 +95,8 @@ public class SelfIntersectionUtil {
List<PolygonPolygonIntersection> selfIntersects = MeshSurfaceUtils.selfIntersects(meshSurface, 0.000001, 0.001);
if (!selfIntersects.isEmpty()) {
PolygonPolygonIntersection polygonPolygonIntersection = selfIntersects.get(0);
// DebugUtils.printGeoknechtPolygon(polygonPolygonIntersection.getPolygon1(), polygonPolygonIntersection.getPolygon2());
Polygon p1 = polygonPolygonIntersection.getPolygon1().getOriginal();
Polygon p2 = polygonPolygonIntersection.getPolygon2().getOriginal();
// DebugUtils.printPolygon3d(polygonPolygonIntersection.getPolygon1(), polygonPolygonIntersection.getPolygon2());
// int counter = 0;
// for (Vertex v : p1.getExteriorRing().getVertices()) {
// System.out.println("Vertex v" + counter + " = new Vertex(" + v.getX() + ", " + v.getY() + ", " + v.getZ());
// counter++;
// }
// System.out.println();
// counter = 0;
// for (Vertex v : p2.getExteriorRing().getVertices()) {
// System.out.println("Vertex v" + counter + " = new Vertex(" + v.getX() + ", " + v.getY() + ", " + v.getZ());
// counter++;
// }
// DebugUtils.printPolygon3d(polygonPolygonIntersection.getPolygon1(), polygonPolygonIntersection.getPolygon2());
// System.out.println();
// DebugUtils.printPolygon3d(polygonPolygonIntersection.getPolygon2());
intersections.add(PolygonIntersection.lines(Collections.emptyList(), p1, p2));
}
}
......
Markdown is supported
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