diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/CompositePolygon.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/CompositePolygon.java new file mode 100644 index 0000000000000000000000000000000000000000..2a867b25a8b2aba097ee6a54fd6828fecbe2aa19 --- /dev/null +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/CompositePolygon.java @@ -0,0 +1,278 @@ +package de.hft.stuttgart.citydoctor2.datastructure; + +import de.hft.stuttgart.citydoctor2.check.Check; +import de.hft.stuttgart.citydoctor2.check.CheckError; +import de.hft.stuttgart.citydoctor2.check.CheckId; +import de.hft.stuttgart.citydoctor2.check.Checkable; +import de.hft.stuttgart.citydoctor2.math.Triangle3d; +import de.hft.stuttgart.citydoctor2.math.Vector3d; +import de.hft.stuttgart.citydoctor2.tesselation.TesselatedPolygon; +import de.hft.stuttgart.citydoctor2.utils.CopyHandler; +import de.hft.stuttgart.citydoctor2.utils.Copyable; + +import java.io.Serial; +import java.util.*; + +/** + * + */ +public class CompositePolygon extends ConcretePolygon{ + + @Serial + private static final long serialVersionUID = -1867197873443341287L; + + private Geometry parent; + private BoundarySurface partOfSurface; + private Installation partOfInstallation; + private List compositeMembers = new ArrayList<>(); + private LinearRing exterior = null; + + @Override + public Vector3d calculateNormalNormalized() { + return this.calculateNormal().normalize(); + } + + @Override + public void accept(Check c){ + for (Polygon p : compositeMembers){ + p.accept(c); + } + setValidated(true); + } + + @Override + public Class getCheckClass() { + return Polygon.class; + } + + @Override + public boolean containsAnyError(){ + if (super.containsAnyError()){ + return true; + } + for (Polygon p : compositeMembers){ + if (p.containsAnyError()){ + return true; + } + } + return false; + } + + @Override + public void collectContainedErrors(List errors) { + super.collectContainedErrors(errors); + for (Polygon p : compositeMembers){ + p.collectContainedErrors(errors); + } + } + + @Override + public void clearAllContainedCheckResults() { + super.clearCheckResults(); + for (Polygon p : compositeMembers){ + p.clearAllContainedCheckResults(); + } + } + + public void addCompositeMember(Polygon p){ + compositeMembers.add(p); + } + + public List getCompositeMembers(){ + return compositeMembers; + } + + @Override + public boolean containsError(CheckId checkIdentifier) { + boolean hasError = super.containsError(checkIdentifier); + if (hasError) { + return true; + } + for (Polygon p : compositeMembers){ + if (p.containsError(checkIdentifier)) { + return true; + } + } + return false; + } + + + + @Override + public Vector3d calculateNormal() { + return this.getExteriorRing().calculateNormal(); + } + + @Override + public TesselatedPolygon tesselate() { + List tessPolys = new ArrayList<>(); + for (Polygon p : compositeMembers){ + TesselatedPolygon t = p.tesselate(); + tessPolys.addAll(t.getTriangles()); + } + return new TesselatedPolygon(tessPolys,this ); + } + + @Override + public LinearRing getExteriorRing() { + if( exterior != null ){ + return exterior; + } + Map outerVertices = new HashMap<>(); + for (Polygon p : compositeMembers){ + for (Vertex v: p.getExteriorRing().getVertices()){ + outerVertices.merge(v, 1, Integer::sum); + } + } + List vertices = new ArrayList<>(); + for (Vertex v : outerVertices.keySet()){ + if (outerVertices.get(v) <= 3){ + vertices.add(v); + } + } + LinearRing ext = new LinearRing(LinearRing.LinearRingType.EXTERIOR); + ext.setParent(this); + ext.addAllVertices(vertices); + exterior = ext; + return ext; + } + + @Override + public List getInnerRings() { + List innerRings = new ArrayList<>(); + for (Polygon p : compositeMembers){ + innerRings.addAll(p.getInnerRings()); + } + return innerRings; + } + + @Override + public boolean isPointInsideExteriorRing(Vector3d v) { + for (Polygon p : compositeMembers) { + if (p.isPointInsideExteriorRing(v)) { + return true; + } + } + return false; + } + + @Override + public Geometry getParent() { + return parent; + } + + @Override + public void setParent(Geometry geometry) { + this.parent = geometry; + } + + @Override + public void setExteriorRing(LinearRing extRing) { + // ConcretePolygons' exterior ring is not settable + } + + @Override + public boolean isPolygonConnectedViaPoint(Polygon other) { + for (Polygon p : compositeMembers) { + if (p.isPolygonConnectedViaPoint(other)) { + return true; + } + } + return false; + } + + @Override + public void addInteriorRing(LinearRing inter) { + // ConcretePolygons have no interior ring themselves + } + + @Override + public BoundarySurface getPartOfSurface() { + return partOfSurface; + } + + @Override + public void setPartOfSurface(BoundarySurface bs) { + this.partOfSurface = bs; + } + + @Override + public void removeInnerRing(LinearRing ring) { + for (Polygon p : compositeMembers) { + p.removeInnerRing(ring); + } + } + + @Override + public void setPartOfInstallation(Installation bi) { + this.partOfInstallation = bi; + } + + @Override + public Installation getPartOfInstallation() { + return partOfInstallation; + } + + @Override + public boolean hasPointAsCorner(Vertex v) { + for (Polygon p : compositeMembers){ + if (p.hasPointAsCorner(v)) { + return true; + } + } + return false; + } + + @Override + public void removeRings() { + + } + + @Override + public boolean isLinkedTo() { + return false; + } + + @Override + public boolean isLink() { + return false; + } + + @Override + public LinkedPolygon getLinkedFromPolygon() { + return null; + } + + @Override + void anonymize() { + + } + + + @Override + public double getArea() { + return 0; + } + + @Override + public void prepareForChecking() { + + } + + @Override + public void clearMetaInformation() { + + } + + + + @Override + public void collectInstances(CopyHandler handler) { + + } + + @Override + public Copyable createCopyInstance() { + return null; + } +} diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/mapper/citygml3/Citygml3FeatureMapper.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/mapper/citygml3/Citygml3FeatureMapper.java index c07a73b4281b895c81fbdb4db8904fd4fa8d93b5..eec47f1dbf378c406ec44f10c3e387efec4579ae 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/mapper/citygml3/Citygml3FeatureMapper.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/mapper/citygml3/Citygml3FeatureMapper.java @@ -553,7 +553,7 @@ public class Citygml3FeatureMapper extends ObjectWalker { } private void parseAndAddCompositeSurface(MultiSurfaceProperty ms, Lod lod, CityObject co){ - if (ms == null || ms.getObject() == null || ms.getObject().getSurfaceMember().isEmpty()) { + if (ms == null || ms.getObject() == null) { return; } List surfaces = ms.getObject().getSurfaceMember(); @@ -633,6 +633,10 @@ public class Citygml3FeatureMapper extends ObjectWalker { } continue; } + // TODO: Insert handling of compPoly dummy objects + if (concPoly instanceof CompositePolygon comp) {} + // + LinkedPolygon lPoly = new LinkedPolygon(concPoly, geom); if (geom.getParent() instanceof BoundarySurface bs) { lPoly.setPartOfSurface(bs); @@ -976,7 +980,7 @@ public class Citygml3FeatureMapper extends ObjectWalker { } } - public Geometry parseCompositeSurface(CompositeSurface cs, Lod lod) { + private Geometry parseCompositeSurface(CompositeSurface cs, Lod lod) { Geometry geom = new Geometry(GeometryType.COMPOSITE_SURFACE, lod); Citygml3GeometryMapper geometryMapper = new Citygml3GeometryMapper(config, vertexMap); readSurfaceMember(geom, geometryMapper, cs.getSurfaceMembers()); diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/mapper/citygml3/SurfaceMapper.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/mapper/citygml3/SurfaceMapper.java index d75534ac755fbc6b9a6d2fd308663cf2823ee271..43015bb7a97a761b776e604048963a2250803508 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/mapper/citygml3/SurfaceMapper.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/mapper/citygml3/SurfaceMapper.java @@ -22,6 +22,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import de.hft.stuttgart.citydoctor2.datastructure.*; import org.citygml4j.core.model.construction.AbstractConstructionSurface; import org.citygml4j.core.model.construction.AbstractFillingSurface; import org.citygml4j.core.model.construction.AbstractFillingSurfaceProperty; @@ -40,20 +41,10 @@ import org.citygml4j.core.model.core.ClosureSurface; import org.citygml4j.core.visitor.ObjectWalker; import org.xmlobjects.gml.model.geometry.aggregates.MultiSurface; import org.xmlobjects.gml.model.geometry.aggregates.MultiSurfaceProperty; +import org.xmlobjects.gml.model.geometry.complexes.CompositeSurface; import org.xmlobjects.gml.model.geometry.primitives.AbstractSurface; import org.xmlobjects.gml.model.geometry.primitives.SurfaceProperty; -import de.hft.stuttgart.citydoctor2.datastructure.BoundarySurface; -import de.hft.stuttgart.citydoctor2.datastructure.BoundarySurfaceType; -import de.hft.stuttgart.citydoctor2.datastructure.CityObject; -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.Lod; -import de.hft.stuttgart.citydoctor2.datastructure.Opening; -import de.hft.stuttgart.citydoctor2.datastructure.OpeningType; -import de.hft.stuttgart.citydoctor2.datastructure.SurfaceFeatureType; -import de.hft.stuttgart.citydoctor2.datastructure.Vertex; import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration; public class SurfaceMapper extends ObjectWalker { @@ -106,6 +97,11 @@ public class SurfaceMapper extends ObjectWalker { parseAndAddMultiSurface(afs.getLod2MultiSurface(), Lod.LOD2, o); parseAndAddMultiSurface(afs.getLod3MultiSurface(), Lod.LOD3, o); parseAndAddMultiSurface(afs.getDeprecatedProperties().getLod4MultiSurface(), Lod.LOD4, o); + parseAndAddCompositeSurface(afs.getLod0MultiSurface(), Lod.LOD0, o); + parseAndAddCompositeSurface(afs.getLod1MultiSurface(), Lod.LOD1, o); + parseAndAddCompositeSurface(afs.getLod2MultiSurface(), Lod.LOD2, o); + parseAndAddCompositeSurface(afs.getLod3MultiSurface(), Lod.LOD3, o); + parseAndAddCompositeSurface(afs.getDeprecatedProperties().getLod4MultiSurface(), Lod.LOD4, o); o.unsetGmlGeometries(); } @@ -116,6 +112,11 @@ public class SurfaceMapper extends ObjectWalker { parseAndAddMultiSurface(gmlSurface.getLod2MultiSurface(), Lod.LOD2, cdSurface); parseAndAddMultiSurface(gmlSurface.getLod3MultiSurface(), Lod.LOD3, cdSurface); parseAndAddMultiSurface(gmlSurface.getDeprecatedProperties().getLod4MultiSurface(), Lod.LOD4, cdSurface); + parseAndAddCompositeSurface(gmlSurface.getLod0MultiSurface(), Lod.LOD0, cdSurface); + parseAndAddCompositeSurface(gmlSurface.getLod1MultiSurface(), Lod.LOD1, cdSurface); + parseAndAddCompositeSurface(gmlSurface.getLod2MultiSurface(), Lod.LOD2, cdSurface); + parseAndAddCompositeSurface(gmlSurface.getLod3MultiSurface(), Lod.LOD3, cdSurface); + parseAndAddCompositeSurface(gmlSurface.getDeprecatedProperties().getLod4MultiSurface(), Lod.LOD4, cdSurface); } private void parseAndAddMultiSurface(MultiSurfaceProperty msp, Lod lod, CityObject cdSurface) { @@ -132,7 +133,36 @@ public class SurfaceMapper extends ObjectWalker { readSurfaceMember(geom, geometryMapper, ms.getSurfaceMember()); return geom; } - + + private void parseAndAddCompositeSurface(MultiSurfaceProperty ms, Lod lod, CityObject cdSurface){ + if (ms == null || ms.getObject() == null) { + return; + } + List surfaceMember = ms.getObject().getSurfaceMember(); + for (SurfaceProperty surface : surfaceMember) { + if (surface.getObject() instanceof CompositeSurface cs) { + Geometry geom = parseCompositeSurface(cs, lod); + cdSurface.addGeometry(geom); + + } + } + + } + + private Geometry parseCompositeSurface(CompositeSurface cs, Lod lod) { + Geometry geom = new Geometry(GeometryType.COMPOSITE_SURFACE, lod); + Citygml3GeometryMapper geometryMapper = new Citygml3GeometryMapper(config, vertexMap); + readSurfaceMember(geom, geometryMapper, cs.getSurfaceMembers()); + if (cs.getId() != null){ + CompositePolygon compPoly = new CompositePolygon(); + polygonMap.put(cs.getId(), compPoly); + geom.getPolygons().forEach(compPoly::addCompositeMember); + compPoly.setParent(geom); + + } + return geom; + } + private void readSurfaceMember(Geometry geom, Citygml3GeometryMapper geometryMapper, List surfaceMember) { for (SurfaceProperty prop : surfaceMember) {