Commit ad2e1a75 authored by Riegel's avatar Riegel
Browse files

Merge branch 'refs/heads/dev' into dev_embedded_geodb

# Conflicts:
#	CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/GenericAttribute.java
parents aa17c02e 9c97175d
......@@ -20,6 +20,7 @@ package de.hft.stuttgart.citydoctor2.datastructure;
import de.hft.stuttgart.citydoctor2.check.CheckableUtilsVisitor;
import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.CheckableVisitor;
import de.hft.stuttgart.citydoctor2.exceptions.CityDoctorWriteException;
import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;
import de.hft.stuttgart.citydoctor2.writer.CityGMLWriterUtils;
......@@ -121,6 +122,18 @@ public class CityDoctorModel {
tunnels.stream(), water.stream(), cityfurniture.stream(), genericObjects.stream()).flatMap(co -> co);
}
public void accept(CheckableVisitor visitor) {
buildings.forEach(co -> co.accept(visitor));
vegetation.forEach(co -> co.accept(visitor));
bridges.forEach(co -> co.accept(visitor));
land.forEach(co -> co.accept(visitor));
roads.forEach(co -> co.accept(visitor));
tunnels.forEach(co -> co.accept(visitor));
water.forEach(co -> co.accept(visitor));
cityfurniture.forEach(co -> co.accept(visitor));
genericObjects.forEach(co -> co.accept(visitor));
}
public void saveAs(String file, boolean saveQualityAde) throws CityDoctorWriteException {
if (file.endsWith(".off")) {
exportAsOff(file);
......
......@@ -48,9 +48,6 @@ public class Edge implements Serializable {
this.to = to;
}
private Edge() {
}
public Vertex getFrom() {
return from;
}
......
......@@ -8,6 +8,8 @@ import org.citygml4j.core.model.generics.*;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
public class GenericAttribute implements Serializable {
......@@ -51,6 +53,22 @@ public class GenericAttribute implements Serializable {
} else if (attributeProperty.getObject() instanceof CodeAttribute ca) {
type = String.format("CodeAttribute (%s)", ca.getValue().getLanguage());
value = String.format("'''%s''' %n CodeSpace: %s", ca.getValue().getValue(), ca.getValue().getCodeSpace());
} else if (attributeProperty.getObject() instanceof GenericAttributeSet gas) {
type = "GenericAttributeSet";
List<AbstractGenericAttributeProperty> attributes = gas.getValue();
StringBuilder sb = new StringBuilder();
sb.append("{");
for (AbstractGenericAttributeProperty attribute : attributes) {
if (attribute.getObject() != null) {
sb.append(attribute.getObject().getName());
sb.append(" = ");
sb.append(attribute.getObject().getValue());
sb.append("; ");
}
}
sb.replace(sb.length() - 1, sb.length(), "}");
value = String.format("'%s'", sb);
} else {
logger.warn("GenericAttribute {} is of unknown type {}", attributeProperty, attributeProperty.getObject());
value = attributeProperty.getObject().getValue().toString();
......
......@@ -40,6 +40,10 @@ public class Geometry extends GmlElement {
@Serial
private static final long serialVersionUID = 2539031030917731575L;
public enum Orientation {
INWARD, OUTWARD
}
private static final Random r = new Random();
......@@ -52,11 +56,20 @@ public class Geometry extends GmlElement {
private List<Edge> edges;
private Map<SerializablePair<Vertex, Vertex>, Edge> edgeMap;
private List<Vertex> vertices;
private Orientation orientation;
public Geometry(GeometryType type, Lod lod) {
public Geometry(GeometryType type, Lod lod, Orientation orientation) {
this.lod = lod;
this.type = type;
if (type == GeometryType.SOLID) {
Objects.requireNonNull(orientation);
}
this.orientation = orientation;
}
public Orientation getOrientation() {
return orientation;
}
void setParent(CityObject parent) {
this.parent = parent;
......
package de.hft.stuttgart.citydoctor2.datastructure;
import java.io.Serial;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import de.hft.stuttgart.citydoctor2.check.CheckableVisitor;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.citygml4j.core.model.core.ImplicitGeometry;
import de.hft.stuttgart.citydoctor2.math.TransformationMatrix;
......@@ -16,14 +21,16 @@ public class ImplicitGeometryHolder extends Geometry {
@Serial
private static final long serialVersionUID = -8938931081577196349L;
private static final Logger logger = LogManager.getLogger(ImplicitGeometryHolder.class);
private ImplicitGeometry cgmlImplicitGeometry = null;
private ImplicitGeometry cgmlImplicitGeometry = null;
private static ConcurrentHashMap<ImplicitGeometryHolder, ImplicitGeometry> deferredRelGeomObjects = new ConcurrentHashMap<>();
private final PrototypeGeometryType type;
private final Geometry prototypeGeometry;
public ImplicitGeometryHolder(ImplicitGeometry cgmlImplicitGeometry, LibraryObject libObject) {
super(libObject.getType(), libObject.getLod());
super(libObject.getType(), libObject.getLod(), libObject.getOrientation());
prototypeGeometry = libObject;
type = PrototypeGeometryType.LIBRARY_OBJECT;
this.cgmlImplicitGeometry = cgmlImplicitGeometry;
......@@ -31,14 +38,47 @@ public class ImplicitGeometryHolder extends Geometry {
}
public ImplicitGeometryHolder(ImplicitGeometry cgmlImplicitGeometry, RelativeGeometry relativeGeometry) {
super(relativeGeometry.getType(), relativeGeometry.getLod());
super(relativeGeometry.getType(), relativeGeometry.getLod(), relativeGeometry.getOrientation());
prototypeGeometry = relativeGeometry;
type = PrototypeGeometryType.RELATIVE_GEOMETRY;
this.cgmlImplicitGeometry = cgmlImplicitGeometry;
applyTransformation();
}
public static ImplicitGeometryHolder deferRelativeGeomParsing(ImplicitGeometry ig, Lod lod) {
ImplicitGeometryHolder igh = new ImplicitGeometryHolder(lod);
deferredRelGeomObjects.put(igh, ig);
return igh;
}
public static void resolveDeferredObjects() {
Set<GmlId> missingGeoms = new HashSet<>();
for (ImplicitGeometryHolder key : deferredRelGeomObjects.keySet()) {
ImplicitGeometry ig = deferredRelGeomObjects.get(key);
String hrefId = ig.getRelativeGeometry().getHref();
hrefId = hrefId.startsWith("#") ? hrefId.substring(1) : hrefId;
GmlId gmlId = new GmlId(hrefId);
RelativeGeometry relGeom = RelativeGeometry.of(gmlId);
if (relGeom != null) {
ImplicitGeometryHolder igh = new ImplicitGeometryHolder(ig, relGeom);
CityObject parent = key.getParent();
parent.removeGeometry(igh.getLod(), igh.getType());
parent.addGeometry(igh);
} else {
missingGeoms.add(gmlId);
}
}
if (!missingGeoms.isEmpty()) {
logger.warn("RelativeGeometries of the following gmlIDs could not be resolved: {}", missingGeoms);
}
deferredRelGeomObjects.clear();
}
private ImplicitGeometryHolder(Lod lod) {
super(null, lod, null);
type = null;
prototypeGeometry = new Geometry(null, lod, null);
}
/**
* Applies the transformation matrix of the implicit geometry to a copy of the reference geometry and copies the resulting
* transformed geometry into this object.
......
......@@ -37,7 +37,7 @@ public class LibraryObject extends Geometry {
if (protoGeom == null) {
return null;
}
LibraryObject libOb = new LibraryObject(protoGeom.getType(), protoGeom.getLod());
LibraryObject libOb = new LibraryObject(protoGeom.getType(), protoGeom.getLod(), protoGeom.getOrientation());
protoGeom.getPolygons().forEach(libOb::addPolygon);
libOb.updateEdgesAndVertices();
libraryObjects.put(path.toString(), libOb);
......@@ -53,15 +53,15 @@ public class LibraryObject extends Geometry {
if (protoGeom == null) {
return null;
}
LibraryObject libOb = new LibraryObject(protoGeom.getType(), protoGeom.getLod());
LibraryObject libOb = new LibraryObject(protoGeom.getType(), protoGeom.getLod(), protoGeom.getOrientation());
protoGeom.getPolygons().forEach(libOb::addPolygon);
libOb.updateEdgesAndVertices();
libraryObjects.put(fileName, libOb);
return libOb;
}
private LibraryObject(GeometryType type, Lod lod) {
super(type, lod);
private LibraryObject(GeometryType type, Lod lod, Orientation orientation) {
super(type, lod, orientation);
}
......
......@@ -44,9 +44,6 @@ public class LinkedPolygon extends Polygon {
private Geometry parent;
private ConcretePolygon poly;
private LinkedPolygon() {
}
/**
* @param poly polygon this is linked to
* @param parent the parent of the linked polygon
......
......@@ -14,20 +14,24 @@ public class RelativeGeometry extends Geometry {
@Serial
private static final long serialVersionUID = -686112245455298977L;
private static Map<Geometry, RelativeGeometry> relativeGeometries = new ConcurrentHashMap<>();
private static final Map<GmlId, RelativeGeometry> relativeGeometries = new ConcurrentHashMap<>();
public static RelativeGeometry of(Geometry geom) {
if (relativeGeometries.containsKey(geom)) {
return relativeGeometries.get(geom);
public static RelativeGeometry of(GmlId gmlId, Geometry geom) {
if (relativeGeometries.containsKey(gmlId)) {
return relativeGeometries.get(gmlId);
}
RelativeGeometry relGeo = new RelativeGeometry(geom.getType(), geom.getLod());
RelativeGeometry relGeo = new RelativeGeometry(geom.getType(), geom.getLod(), geom.getOrientation());
geom.getPolygons().forEach(relGeo::addPolygon);
relGeo.updateEdgesAndVertices();
relativeGeometries.put(geom, relGeo);
relativeGeometries.put(gmlId, relGeo);
return relGeo;
}
private RelativeGeometry(GeometryType type, Lod lod) {
super(type, lod);
public static RelativeGeometry of(GmlId gmlId) {
return relativeGeometries.getOrDefault(gmlId, null);
}
private RelativeGeometry(GeometryType type, Lod lod, Orientation orientation) {
super(type, lod, orientation);
}
}
......@@ -18,32 +18,45 @@
*/
package de.hft.stuttgart.citydoctor2.mapper.citygml3;
import de.hft.stuttgart.citydoctor2.datastructure.AbstractBuilding;
import de.hft.stuttgart.citydoctor2.datastructure.AbstractTunnel;
import de.hft.stuttgart.citydoctor2.datastructure.BridgeConstructiveElement;
import de.hft.stuttgart.citydoctor2.datastructure.*;
import de.hft.stuttgart.citydoctor2.datastructure.Building;
import de.hft.stuttgart.citydoctor2.datastructure.BuildingPart;
import de.hft.stuttgart.citydoctor2.datastructure.BuildingRoom;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import de.hft.stuttgart.citydoctor2.datastructure.TunnelConstructiveElement;
import de.hft.stuttgart.citydoctor2.datastructure.TunnelFurniture;
import de.hft.stuttgart.citydoctor2.datastructure.TunnelPart;
import de.hft.stuttgart.citydoctor2.datastructure.Vegetation.VegetationType;
import de.hft.stuttgart.citydoctor2.math.graph.KDTree;
import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;
import de.hft.stuttgart.citydoctor2.utils.Localization;
import de.hft.stuttgart.citydoctor2.zip.CityGmlZipEntry;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.citygml4j.core.model.CityGMLVersion;
import org.citygml4j.core.model.bridge.*;
import org.citygml4j.core.model.bridge.AbstractBridge;
import org.citygml4j.core.model.bridge.Bridge;
import org.citygml4j.core.model.bridge.BridgeConstructiveElementProperty;
import org.citygml4j.core.model.bridge.BridgeInstallation;
import org.citygml4j.core.model.bridge.BridgeInstallationProperty;
import org.citygml4j.core.model.bridge.BridgePart;
import org.citygml4j.core.model.bridge.BridgePartProperty;
import org.citygml4j.core.model.building.AbstractBuildingSubdivisionProperty;
import org.citygml4j.core.model.building.BuildingConstructiveElement;
import org.citygml4j.core.model.building.BuildingConstructiveElementProperty;
import org.citygml4j.core.model.building.BuildingFurniture;
import org.citygml4j.core.model.building.BuildingFurnitureProperty;
import org.citygml4j.core.model.building.BuildingInstallationProperty;
import org.citygml4j.core.model.building.BuildingPartProperty;
import org.citygml4j.core.model.building.BuildingRoomProperty;
import org.citygml4j.core.model.building.BuildingUnit;
import org.citygml4j.core.model.building.Storey;
import org.citygml4j.core.model.building.*;
import org.citygml4j.core.model.construction.AbstractConstruction;
import org.citygml4j.core.model.core.*;
import org.citygml4j.core.model.core.AbstractCityObject;
import org.citygml4j.core.model.core.AbstractFeatureWithLifespan;
import org.citygml4j.core.model.core.AbstractGenericAttributeProperty;
import org.citygml4j.core.model.core.AbstractOccupiedSpace;
import org.citygml4j.core.model.core.AbstractPhysicalSpace;
import org.citygml4j.core.model.core.AbstractSpace;
import org.citygml4j.core.model.core.AbstractSpaceBoundary;
import org.citygml4j.core.model.core.AbstractSpaceBoundaryProperty;
import org.citygml4j.core.model.core.AbstractThematicSurface;
import org.citygml4j.core.model.core.AbstractUnoccupiedSpace;
import org.citygml4j.core.model.core.CityModel;
import org.citygml4j.core.model.core.ImplicitGeometry;
import org.citygml4j.core.model.deprecated.transportation.TransportationComplex;
import org.citygml4j.core.model.landuse.LandUse;
import org.citygml4j.core.model.relief.AbstractReliefComponentProperty;
......@@ -52,9 +65,28 @@ import org.citygml4j.core.model.relief.MassPointRelief;
import org.citygml4j.core.model.relief.RasterRelief;
import org.citygml4j.core.model.relief.ReliefFeature;
import org.citygml4j.core.model.relief.TINRelief;
import org.citygml4j.core.model.transportation.*;
import org.citygml4j.core.model.transportation.AbstractTransportationSpace;
import org.citygml4j.core.model.transportation.AuxiliaryTrafficArea;
import org.citygml4j.core.model.transportation.AuxiliaryTrafficSpace;
import org.citygml4j.core.model.transportation.AuxiliaryTrafficSpaceProperty;
import org.citygml4j.core.model.transportation.IntersectionProperty;
import org.citygml4j.core.model.transportation.Railway;
import org.citygml4j.core.model.transportation.Road;
import org.citygml4j.core.model.transportation.SectionProperty;
import org.citygml4j.core.model.transportation.Square;
import org.citygml4j.core.model.transportation.Track;
import org.citygml4j.core.model.transportation.TrafficArea;
import org.citygml4j.core.model.transportation.TrafficSpace;
import org.citygml4j.core.model.transportation.TrafficSpaceProperty;
import org.citygml4j.core.model.transportation.Waterway;
import org.citygml4j.core.model.tunnel.HollowSpace;
import org.citygml4j.core.model.tunnel.HollowSpaceProperty;
import org.citygml4j.core.model.tunnel.Tunnel;
import org.citygml4j.core.model.tunnel.*;
import org.citygml4j.core.model.tunnel.TunnelConstructiveElementProperty;
import org.citygml4j.core.model.tunnel.TunnelFurnitureProperty;
import org.citygml4j.core.model.tunnel.TunnelInstallation;
import org.citygml4j.core.model.tunnel.TunnelInstallationProperty;
import org.citygml4j.core.model.tunnel.TunnelPartProperty;
import org.citygml4j.core.model.vegetation.AbstractVegetationObject;
import org.citygml4j.core.model.vegetation.PlantCover;
import org.citygml4j.core.model.vegetation.SolitaryVegetationObject;
......@@ -67,13 +99,65 @@ import org.xmlobjects.gml.model.geometry.GeometryProperty;
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.*;
import org.xmlobjects.gml.model.geometry.primitives.AbstractSolid;
import org.xmlobjects.gml.model.geometry.primitives.AbstractSurface;
import org.xmlobjects.gml.model.geometry.primitives.Shell;
import org.xmlobjects.gml.model.geometry.primitives.ShellProperty;
import org.xmlobjects.gml.model.geometry.primitives.Solid;
import org.xmlobjects.gml.model.geometry.primitives.SolidProperty;
import org.xmlobjects.gml.model.geometry.primitives.SurfaceProperty;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import de.hft.stuttgart.citydoctor2.datastructure.AbstractBuilding;
import de.hft.stuttgart.citydoctor2.datastructure.AbstractTunnel;
import de.hft.stuttgart.citydoctor2.datastructure.BoundarySurface;
import de.hft.stuttgart.citydoctor2.datastructure.BridgeConstructiveElement;
import de.hft.stuttgart.citydoctor2.datastructure.BridgeObject;
import de.hft.stuttgart.citydoctor2.datastructure.Building;
import de.hft.stuttgart.citydoctor2.datastructure.BuildingPart;
import de.hft.stuttgart.citydoctor2.datastructure.BuildingRoom;
import de.hft.stuttgart.citydoctor2.datastructure.BuildingRoomFurniture;
import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel;
import de.hft.stuttgart.citydoctor2.datastructure.CityFurniture;
import de.hft.stuttgart.citydoctor2.datastructure.CityObject;
import de.hft.stuttgart.citydoctor2.datastructure.CompositeCollection;
import de.hft.stuttgart.citydoctor2.datastructure.ConcretePolygon;
import de.hft.stuttgart.citydoctor2.datastructure.GenericAttribute;
import de.hft.stuttgart.citydoctor2.datastructure.GenericCityObject;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry.Orientation;
import de.hft.stuttgart.citydoctor2.datastructure.GeometryType;
import de.hft.stuttgart.citydoctor2.datastructure.GmlElement;
import de.hft.stuttgart.citydoctor2.datastructure.GmlId;
import de.hft.stuttgart.citydoctor2.datastructure.ImplicitGeometryHolder;
import de.hft.stuttgart.citydoctor2.datastructure.Installation;
import de.hft.stuttgart.citydoctor2.datastructure.LandObject;
import de.hft.stuttgart.citydoctor2.datastructure.LibraryObject;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.LinkedPolygon;
import de.hft.stuttgart.citydoctor2.datastructure.Lod;
import de.hft.stuttgart.citydoctor2.datastructure.Opening;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import de.hft.stuttgart.citydoctor2.datastructure.RelativeGeometry;
import de.hft.stuttgart.citydoctor2.datastructure.ReliefObject;
import de.hft.stuttgart.citydoctor2.datastructure.TinObject;
import de.hft.stuttgart.citydoctor2.datastructure.TopLevelTransportFeature;
import de.hft.stuttgart.citydoctor2.datastructure.TrafficAreaObject;
import de.hft.stuttgart.citydoctor2.datastructure.TrafficSpaceObject;
import de.hft.stuttgart.citydoctor2.datastructure.TransportSection;
import de.hft.stuttgart.citydoctor2.datastructure.TransportationObject;
import de.hft.stuttgart.citydoctor2.datastructure.TransportationSpace;
import de.hft.stuttgart.citydoctor2.datastructure.TunnelConstructiveElement;
import de.hft.stuttgart.citydoctor2.datastructure.TunnelFurniture;
import de.hft.stuttgart.citydoctor2.datastructure.TunnelHollow;
import de.hft.stuttgart.citydoctor2.datastructure.TunnelPart;
import de.hft.stuttgart.citydoctor2.datastructure.Vegetation;
import de.hft.stuttgart.citydoctor2.datastructure.Vegetation.VegetationType;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
import de.hft.stuttgart.citydoctor2.datastructure.WaterObject;
import de.hft.stuttgart.citydoctor2.math.graph.KDTree;
import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;
import de.hft.stuttgart.citydoctor2.utils.Localization;
import de.hft.stuttgart.citydoctor2.zip.CityGmlZipEntry;
public class Citygml3FeatureMapper extends ObjectWalker {
......@@ -123,7 +207,7 @@ public class Citygml3FeatureMapper extends ObjectWalker {
public void visit(org.citygml4j.core.model.cityfurniture.CityFurniture gmlCityFurniture) {
CityFurniture cf = new CityFurniture();
cf.setGmlObject(gmlCityFurniture);
mapAbstractOccupiedSpace(gmlCityFurniture, cf);
mapAbstractOccupiedSpace(gmlCityFurniture, cf, Orientation.OUTWARD);
finishCityObjectConstruction(cf);
model.addCityFurniture(cf);
}
......@@ -141,10 +225,10 @@ public class Citygml3FeatureMapper extends ObjectWalker {
if (agLod4.getObject() instanceof MultiSurface ms) {
gco.addGeometry(parseMultiSurface(ms, Lod.LOD4));
} else if (agLod4.getObject() instanceof AbstractSolid solid) {
gco.addGeometry(parseSolid(solid, Lod.LOD4));
gco.addGeometry(parseSolid(solid, Lod.LOD4, Orientation.OUTWARD));
}
}
mapAbstractOccupiedSpace(gos, gco);
mapAbstractOccupiedSpace(gos, gco, Orientation.OUTWARD);
finishCityObjectConstruction(gco);
model.addGenericCityObject(gco);
}
......@@ -168,9 +252,9 @@ public class Citygml3FeatureMapper extends ObjectWalker {
public void visit(WaterBody waterBody) {
WaterObject wo = new WaterObject();
wo.setGmlObject(waterBody);
mapAbstractOccupiedSpace(waterBody, wo);
mapAbstractOccupiedSpace(waterBody, wo, Orientation.OUTWARD);
parseAndAddMultiSurface(waterBody.getDeprecatedProperties().getLod1MultiSurface(), Lod.LOD1, wo);
parseAndAddSolid(waterBody.getDeprecatedProperties().getLod4Solid(), Lod.LOD4, wo);
parseAndAddSolid(waterBody.getDeprecatedProperties().getLod4Solid(), Lod.LOD4, wo, Orientation.OUTWARD);
SurfaceMapper surfaceMapper = new SurfaceMapper(polygonMap, references, compositeMap, vertexMap, config);
for (AbstractSpaceBoundaryProperty surfaceProp : waterBody.getBoundaries()) {
......@@ -257,7 +341,7 @@ public class Citygml3FeatureMapper extends ObjectWalker {
reliefObject.addComponent(to);
Citygml3GeometryMapper tinMapper = new Citygml3GeometryMapper(config, vertexMap);
relief.getTin().getObject().accept(tinMapper);
Geometry geom = new Geometry(GeometryType.MULTI_SURFACE, reliefLod);
Geometry geom = new Geometry(GeometryType.MULTI_SURFACE, reliefLod, Orientation.OUTWARD);
tinMapper.getPolygons().forEach(geom::addPolygon);
to.addGeometry(geom);
}
......@@ -282,39 +366,39 @@ public class Citygml3FeatureMapper extends ObjectWalker {
mapAbstractVegetationObject(solitaryVegetationObject, veg);
parseAndAddAbstractGeometry(solitaryVegetationObject.getDeprecatedProperties().getLod1Geometry(), Lod.LOD1,
veg);
veg, Orientation.OUTWARD);
parseAndAddAbstractGeometry(solitaryVegetationObject.getDeprecatedProperties().getLod2Geometry(), Lod.LOD2,
veg);
veg, Orientation.OUTWARD);
parseAndAddAbstractGeometry(solitaryVegetationObject.getDeprecatedProperties().getLod3Geometry(), Lod.LOD3,
veg);
veg, Orientation.OUTWARD);
parseAndAddAbstractGeometry(solitaryVegetationObject.getDeprecatedProperties().getLod4Geometry(), Lod.LOD4,
veg);
veg, Orientation.OUTWARD);
finishCityObjectConstruction(veg);
model.addVegetation(veg);
}
private void mapAbstractVegetationObject(AbstractVegetationObject avo, Vegetation veg) {
mapAbstractOccupiedSpace(avo, veg);
mapAbstractOccupiedSpace(avo, veg, Orientation.OUTWARD);
}
private void mapAbstractOccupiedSpace(AbstractOccupiedSpace aos, CityObject co) {
mapAbstractPhysicalSpace(aos, co);
parseImplicitGeometry(aos, co);
private void mapAbstractOccupiedSpace(AbstractOccupiedSpace aos, CityObject co, Orientation orientation) {
mapAbstractPhysicalSpace(aos, co, orientation);
parseImplicitGeometry(aos, co, orientation);
}
private void mapAbstractPhysicalSpace(AbstractPhysicalSpace aps, CityObject co) {
mapAbstractSpace(aps, co);
private void mapAbstractPhysicalSpace(AbstractPhysicalSpace aps, CityObject co, Orientation orientation) {
mapAbstractSpace(aps, co, orientation);
}
private void mapAbstractSpace(AbstractSpace as, CityObject co) {
private void mapAbstractSpace(AbstractSpace as, CityObject co, Orientation orientation) {
mapAbstractFeature(as, co);
parseAndAddMultiSurface(as.getLod0MultiSurface(), Lod.LOD0, co);
parseAndAddMultiSurface(as.getLod2MultiSurface(), Lod.LOD2, co);
parseAndAddMultiSurface(as.getLod3MultiSurface(), Lod.LOD3, co);
parseAndAddSolid(as.getLod1Solid(), Lod.LOD1, co);
parseAndAddSolid(as.getLod2Solid(), Lod.LOD2, co);
parseAndAddSolid(as.getLod3Solid(), Lod.LOD3, co);
parseAndAddSolid(as.getLod1Solid(), Lod.LOD1, co, orientation);
parseAndAddSolid(as.getLod2Solid(), Lod.LOD2, co, orientation);
parseAndAddSolid(as.getLod3Solid(), Lod.LOD3, co, orientation);
parseAndAddGenericAttributes(as, co);
}
......@@ -331,7 +415,7 @@ public class Citygml3FeatureMapper extends ObjectWalker {
// parse deprecated geometries
parseAndAddMultiSurface(bridge.getDeprecatedProperties().getLod1MultiSurface(), Lod.LOD1, bo);
parseAndAddMultiSurface(bridge.getDeprecatedProperties().getLod4MultiSurface(), Lod.LOD4, bo);
parseAndAddSolid(bridge.getDeprecatedProperties().getLod4Solid(), Lod.LOD4, bo);
parseAndAddSolid(bridge.getDeprecatedProperties().getLod4Solid(), Lod.LOD4, bo, Orientation.OUTWARD);
mapAbstractBridge(bridge, bo);
for (BridgePartProperty bPartProperty : bridge.getBridgeParts()) {
......@@ -403,13 +487,13 @@ public class Citygml3FeatureMapper extends ObjectWalker {
private Installation mapBridgeInstallation(BridgeInstallation gmlBi) {
Installation bi = new Installation();
bi.setGmlObject(gmlBi);
mapAbstractOccupiedSpace(gmlBi, bi);
mapAbstractOccupiedSpace(gmlBi, bi, Orientation.OUTWARD);
GeometryProperty<?> lod2Prop = gmlBi.getDeprecatedProperties().getLod2Geometry();
parseAndAddAbstractGeometry(lod2Prop, Lod.LOD2, bi);
parseAndAddAbstractGeometry(lod2Prop, Lod.LOD2, bi, Orientation.OUTWARD);
GeometryProperty<?> lod3Prop = gmlBi.getDeprecatedProperties().getLod3Geometry();
parseAndAddAbstractGeometry(lod3Prop, Lod.LOD3, bi);
parseAndAddAbstractGeometry(lod3Prop, Lod.LOD3, bi, Orientation.OUTWARD);
GeometryProperty<?> lod4Prop = gmlBi.getDeprecatedProperties().getLod4Geometry();
parseAndAddAbstractGeometry(lod4Prop, Lod.LOD4, bi);
parseAndAddAbstractGeometry(lod4Prop, Lod.LOD4, bi, Orientation.OUTWARD);
SurfaceMapper surfaceMapper = new SurfaceMapper(polygonMap, references, compositeMap, vertexMap, config);
for (AbstractSpaceBoundaryProperty surfaceProp : gmlBi.getBoundaries()) {
......@@ -459,13 +543,13 @@ public class Citygml3FeatureMapper extends ObjectWalker {
}
private void readAbstractTunnel(org.citygml4j.core.model.tunnel.AbstractTunnel gmlTunnel, AbstractTunnel cdTunnel) {
mapAbstractOccupiedSpace(gmlTunnel, cdTunnel);
mapAbstractOccupiedSpace(gmlTunnel, cdTunnel, Orientation.OUTWARD);
cdTunnel.setGmlObject(gmlTunnel);
// parse deprecated geometries
parseAndAddMultiSurface(gmlTunnel.getDeprecatedProperties().getLod1MultiSurface(), Lod.LOD1, cdTunnel);
parseAndAddMultiSurface(gmlTunnel.getDeprecatedProperties().getLod4MultiSurface(), Lod.LOD4, cdTunnel);
parseAndAddSolid(gmlTunnel.getDeprecatedProperties().getLod4Solid(), Lod.LOD4, cdTunnel);
parseAndAddSolid(gmlTunnel.getDeprecatedProperties().getLod4Solid(), Lod.LOD4, cdTunnel, Orientation.OUTWARD);
parseTunnelInstallations(gmlTunnel, cdTunnel);
parseHollowSpaces(gmlTunnel, cdTunnel);
......@@ -540,21 +624,21 @@ public class Citygml3FeatureMapper extends ObjectWalker {
// ignore empty properties
continue;
}
Installation ti = mapTunnelInstallation(gmlTi);
Installation ti = mapTunnelInstallation(gmlTi, Orientation.OUTWARD);
cdTunnel.addTunnelInstallation(ti);
}
}
private Installation mapTunnelInstallation(TunnelInstallation gmlTi) {
private Installation mapTunnelInstallation(TunnelInstallation gmlTi, Orientation orientation) {
Installation ti = new Installation();
ti.setGmlObject(gmlTi);
mapAbstractOccupiedSpace(gmlTi, ti);
mapAbstractOccupiedSpace(gmlTi, ti, Orientation.OUTWARD);
GeometryProperty<?> lod2Prop = gmlTi.getDeprecatedProperties().getLod2Geometry();
parseAndAddAbstractGeometry(lod2Prop, Lod.LOD2, ti);
parseAndAddAbstractGeometry(lod2Prop, Lod.LOD2, ti, orientation);
GeometryProperty<?> lod3Prop = gmlTi.getDeprecatedProperties().getLod3Geometry();
parseAndAddAbstractGeometry(lod3Prop, Lod.LOD3, ti);
parseAndAddAbstractGeometry(lod3Prop, Lod.LOD3, ti, orientation);
GeometryProperty<?> lod4Prop = gmlTi.getDeprecatedProperties().getLod4Geometry();
parseAndAddAbstractGeometry(lod4Prop, Lod.LOD4, ti);
parseAndAddAbstractGeometry(lod4Prop, Lod.LOD4, ti, orientation);
SurfaceMapper surfaceMapper = new SurfaceMapper(polygonMap, references, compositeMap, vertexMap, config);
......@@ -586,7 +670,7 @@ public class Citygml3FeatureMapper extends ObjectWalker {
private TunnelHollow mapTunnelHollow(HollowSpace gmlHo) {
TunnelHollow tHollow = new TunnelHollow();
tHollow.setGmlObject(gmlHo);
mapAbstractUnoccupiedSpace(gmlHo, tHollow);
mapAbstractUnoccupiedSpace(gmlHo, tHollow, Orientation.INWARD);
SurfaceMapper surfaceMapper = new SurfaceMapper(polygonMap, references, compositeMap, vertexMap, config);
for (AbstractSpaceBoundaryProperty surfaceProp : gmlHo.getBoundaries()) {
......@@ -610,7 +694,7 @@ public class Citygml3FeatureMapper extends ObjectWalker {
// ignore empty properties
continue;
}
Installation bi = mapTunnelInstallation(gmlTi);
Installation bi = mapTunnelInstallation(gmlTi, Orientation.INWARD);
tHollow.addRoomInstallation(bi);
}
for (TunnelFurnitureProperty tfProp : gmlHo.getTunnelFurniture()) {
......@@ -626,7 +710,7 @@ public class Citygml3FeatureMapper extends ObjectWalker {
private TunnelFurniture mapTunnelFurniture(org.citygml4j.core.model.tunnel.TunnelFurniture gmlTf) {
TunnelFurniture tf = new TunnelFurniture();
tf.setGmlObject(gmlTf);
mapAbstractOccupiedSpace(gmlTf, tf);
mapAbstractOccupiedSpace(gmlTf, tf, Orientation.OUTWARD);
SurfaceMapper surfaceMapper = new SurfaceMapper(polygonMap, references, compositeMap, vertexMap, config);
for (AbstractSpaceBoundaryProperty surfaceProp : gmlTf.getBoundaries()) {
......@@ -650,7 +734,7 @@ public class Citygml3FeatureMapper extends ObjectWalker {
private TunnelConstructiveElement mapTunnelConstructiveElement(
org.citygml4j.core.model.tunnel.TunnelConstructiveElement gmlTe) {
TunnelConstructiveElement te = new TunnelConstructiveElement(gmlTe);
mapAbstractOccupiedSpace(gmlTe, te);
mapAbstractOccupiedSpace(gmlTe, te, Orientation.OUTWARD);
SurfaceMapper surfaceMapper = new SurfaceMapper(polygonMap, references, compositeMap, vertexMap, config);
for (AbstractSpaceBoundaryProperty surfaceProp : gmlTe.getBoundaries()) {
if (!surfaceProp.isSetObject()) {
......@@ -700,11 +784,11 @@ public class Citygml3FeatureMapper extends ObjectWalker {
private void mapAbstractConstructiveElement(org.citygml4j.core.model.bridge.BridgeConstructiveElement ele,
BridgeConstructiveElement bce) {
mapAbstractOccupiedSpace(ele, bce);
mapAbstractOccupiedSpace(ele, bce, Orientation.OUTWARD);
}
private void mapAbstractConstruction(AbstractConstruction ac, BridgeObject bo) {
mapAbstractOccupiedSpace(ac, bo);
mapAbstractOccupiedSpace(ac, bo, Orientation.OUTWARD);
}
@Override
......@@ -839,7 +923,7 @@ public class Citygml3FeatureMapper extends ObjectWalker {
private void mapTrafficSpace(TrafficSpace ts, TrafficSpaceObject tso) {
tso.setGmlObject(ts);
mapAbstractUnoccupiedSpace(ts, tso);
mapAbstractUnoccupiedSpace(ts, tso, Orientation.OUTWARD);
for (AbstractSpaceBoundaryProperty boundary : ts.getBoundaries()) {
if (boundary.isSetObject()) {
TrafficArea area = (TrafficArea) boundary.getObject();
......@@ -853,7 +937,7 @@ public class Citygml3FeatureMapper extends ObjectWalker {
private void mapAuxiliaryTrafficSpace(AuxiliaryTrafficSpace ats, TrafficSpaceObject tso) {
tso.setGmlObject(ats);
mapAbstractUnoccupiedSpace(ats, tso);
mapAbstractUnoccupiedSpace(ats, tso, Orientation.OUTWARD);
for (AbstractSpaceBoundaryProperty boundary : ats.getBoundaries()) {
if (boundary.isSetObject()) {
AuxiliaryTrafficArea area = (AuxiliaryTrafficArea) boundary.getObject();
......@@ -885,8 +969,8 @@ public class Citygml3FeatureMapper extends ObjectWalker {
finishCityObjectConstruction(tao);
}
private void mapAbstractUnoccupiedSpace(AbstractUnoccupiedSpace aus, CityObject co) {
mapAbstractPhysicalSpace(aus, co);
private void mapAbstractUnoccupiedSpace(AbstractUnoccupiedSpace aus, CityObject co, Orientation orientation) {
mapAbstractPhysicalSpace(aus, co, orientation);
}
private void parseAbstractTransportationSpaceGeometries(AbstractTransportationSpace space, CityObject co) {
......@@ -894,16 +978,6 @@ public class Citygml3FeatureMapper extends ObjectWalker {
parseAndAddMultiSurface(space.getDeprecatedProperties().getLod4MultiSurface(), Lod.LOD4, co);
}
private void parseAbstractSpaceGeometries(AbstractSpace as, CityObject co) {
parseAndAddMultiSurface(as.getLod0MultiSurface(), Lod.LOD0, co);
parseAndAddMultiSurface(as.getLod2MultiSurface(), Lod.LOD2, co);
parseAndAddMultiSurface(as.getLod3MultiSurface(), Lod.LOD3, co);
parseAndAddSolid(as.getLod1Solid(), Lod.LOD1, co);
parseAndAddSolid(as.getLod2Solid(), Lod.LOD2, co);
parseAndAddSolid(as.getLod3Solid(), Lod.LOD3, co);
}
private void parseAndAddMultiSurface(MultiSurfaceProperty msp, Lod lod, CityObject co) {
if (msp == null || msp.getObject() == null) {
return;
......@@ -912,24 +986,24 @@ public class Citygml3FeatureMapper extends ObjectWalker {
co.addGeometry(geom);
}
private void parseAndAddSolid(SolidProperty sp, Lod lod, CityObject co) {
private void parseAndAddSolid(SolidProperty sp, Lod lod, CityObject co, Orientation orientation) {
if (sp == null || sp.getObject() == null) {
return;
}
Geometry geom = parseSolid(sp.getObject(), lod);
Geometry geom = parseSolid(sp.getObject(), lod, orientation);
if (geom != null) {
co.addGeometry(geom);
}
}
private void parseImplicitGeometry(AbstractOccupiedSpace aos, CityObject co) {
private void parseImplicitGeometry(AbstractOccupiedSpace aos, CityObject co, Orientation orientation) {
for (int i = 1; i <= 3; i++) {
if (aos.getImplicitRepresentation(i) == null) {
continue;
}
if (aos.getImplicitRepresentation(i).getObject() != null) {
ImplicitGeometry impGeom = aos.getImplicitRepresentation(i).getObject();
ImplicitGeometryHolder igh = resolveImplicitGeometry(impGeom, i);
ImplicitGeometryHolder igh = resolveImplicitGeometry(impGeom, i, orientation);
if (igh != null) {
co.addGeometry(igh);
}
......@@ -943,7 +1017,7 @@ public class Citygml3FeatureMapper extends ObjectWalker {
}
private ImplicitGeometryHolder resolveImplicitGeometry(ImplicitGeometry ig, int lodInt) {
private ImplicitGeometryHolder resolveImplicitGeometry(ImplicitGeometry ig, int lodInt, Orientation orientation) {
ImplicitGeometryHolder igh = null;
if (ig.getLibraryObject() != null) {
LibraryObject libObj = null;
......@@ -961,19 +1035,33 @@ public class Citygml3FeatureMapper extends ObjectWalker {
}
} else if (ig.getRelativeGeometry() != null) {
AbstractGeometry aGeom = ig.getRelativeGeometry().getObject();
Geometry geom = null;
Lod lod = Lod.values()[lodInt];
RelativeGeometry relGeo = null;
if (aGeom instanceof MultiSurface ms) {
geom = parseMultiSurface(ms, lod);
} else if (aGeom instanceof Solid s) {
geom = parseSolid(s, lod);
} else if (aGeom instanceof CompositeSurface cs) {
geom = parseCompositeSurface(cs, lod);
}
if (geom != null) {
relGeo = RelativeGeometry.of(geom);
igh = new ImplicitGeometryHolder(ig, relGeo);
if (aGeom != null) {
Geometry geom = null;
if (aGeom instanceof MultiSurface ms) {
geom = parseMultiSurface(ms, lod);
} else if (aGeom instanceof Solid s) {
geom = parseSolid(s, lod, orientation);
} else if (aGeom instanceof CompositeSurface cs) {
geom = parseCompositeSurface(cs, lod);
}
if (geom != null) {
geom.setGmlId(new GmlId(aGeom.getId()));
RelativeGeometry relGeo = RelativeGeometry.of(geom.getGmlId(), geom);
igh = new ImplicitGeometryHolder(ig, relGeo);
}
} else if (ig.getRelativeGeometry().getHref() != null) {
String hrefId = ig.getRelativeGeometry().getHref();
hrefId = hrefId.startsWith("#") ? hrefId.substring(1) : hrefId;
GmlId gmlId = new GmlId(hrefId);
RelativeGeometry relGeo = RelativeGeometry.of(gmlId);
if (relGeo == null) {
igh = ImplicitGeometryHolder.deferRelativeGeomParsing(ig, lod);
} else {
igh = new ImplicitGeometryHolder(ig, relGeo);
}
} else {
logger.warn("Relative geometry of GML-ID {} has neither geometry nor an href", ig.getId());
}
} else {
......@@ -1024,13 +1112,14 @@ public class Citygml3FeatureMapper extends ObjectWalker {
private void readAbstractBuilding(org.citygml4j.core.model.building.AbstractBuilding gmlAb,
AbstractBuilding cdBuilding) {
mapAbstractOccupiedSpace(gmlAb, cdBuilding);
mapAbstractOccupiedSpace(gmlAb, cdBuilding, Orientation.OUTWARD);
cdBuilding.setGmlObject(gmlAb);
// parse deprecated geometries
parseAndAddMultiSurface(gmlAb.getDeprecatedProperties().getLod1MultiSurface(), Lod.LOD1, cdBuilding);
parseAndAddMultiSurface(gmlAb.getDeprecatedProperties().getLod4MultiSurface(), Lod.LOD4, cdBuilding);
parseAndAddSolid(gmlAb.getDeprecatedProperties().getLod4Solid(), Lod.LOD4, cdBuilding);
parseAndAddSolid(gmlAb.getDeprecatedProperties().getLod4Solid(), Lod.LOD4, cdBuilding, Orientation.OUTWARD);
parseBuildingConstructiveElements(gmlAb, cdBuilding);
parseBuildingInstallations(gmlAb, cdBuilding);
parseBuildingRooms(gmlAb, cdBuilding);
parseBuildingSubdivisions(gmlAb, cdBuilding);
......@@ -1084,6 +1173,19 @@ public class Citygml3FeatureMapper extends ObjectWalker {
}
}
private void parseBuildingConstructiveElements(org.citygml4j.core.model.building.AbstractBuilding gmlAb, AbstractBuilding cdBuilding) {
for (BuildingConstructiveElementProperty bceProp : gmlAb.getBuildingConstructiveElements()) {
var gmlBCE = bceProp.getObject();
if (gmlBCE == null) {
continue;
}
de.hft.stuttgart.citydoctor2.datastructure.BuildingConstructiveElement bce =
new de.hft.stuttgart.citydoctor2.datastructure.BuildingConstructiveElement(gmlBCE);
mapBuildingConstructiveElement(bce, gmlBCE);
cdBuilding.addConstructiveElement(bce);
}
}
private void parseBuildingRooms(org.citygml4j.core.model.building.AbstractBuilding gmlAb, AbstractBuilding cdBuilding) {
for (BuildingRoomProperty brProp : gmlAb.getBuildingRooms()) {
var gmlBr = brProp.getObject();
......@@ -1120,7 +1222,7 @@ public class Citygml3FeatureMapper extends ObjectWalker {
BuildingRoom br = new BuildingRoom();
br.setGmlObject(gmlBr);
mapAbstractUnoccupiedSpace(gmlBr, br);
mapAbstractUnoccupiedSpace(gmlBr, br, Orientation.INWARD);
SurfaceMapper surfaceMapper = new SurfaceMapper(polygonMap, references, compositeMap, vertexMap, config);
for (AbstractSpaceBoundaryProperty surfaceProp : gmlBr.getBoundaries()) {
......@@ -1161,7 +1263,7 @@ public class Citygml3FeatureMapper extends ObjectWalker {
private BuildingRoomFurniture mapBuildingFurniture(BuildingFurniture gmlAF) {
BuildingRoomFurniture bf = new BuildingRoomFurniture();
bf.setGmlObject(gmlAF);
mapAbstractOccupiedSpace(gmlAF, bf);
mapAbstractOccupiedSpace(gmlAF, bf, Orientation.OUTWARD);
SurfaceMapper surfaceMapper = new SurfaceMapper(polygonMap, references, compositeMap, vertexMap, config);
for (AbstractSpaceBoundaryProperty surfaceProp : gmlAF.getBoundaries()) {
if (!surfaceProp.isSetObject()) {
......@@ -1182,10 +1284,25 @@ public class Citygml3FeatureMapper extends ObjectWalker {
}
private void mapBuildingConstructiveElement(de.hft.stuttgart.citydoctor2.datastructure.BuildingConstructiveElement bce, BuildingConstructiveElement ele) {
mapAbstractOccupiedSpace(ele, bce, Orientation.OUTWARD);
SurfaceMapper surfaceMapper = new SurfaceMapper(polygonMap, references, compositeMap, vertexMap, config);
for (AbstractSpaceBoundaryProperty surfaceProp : ele.getBoundaries()) {
if (!surfaceProp.isSetObject()) {
continue;
}
AbstractSpaceBoundary surface = surfaceProp.getObject();
surface.accept(surfaceMapper);
}
for (BoundarySurface bs : surfaceMapper.getSurfaces()) {
bce.addBoundarySurface(bs);
}
}
private de.hft.stuttgart.citydoctor2.datastructure.Storey mapBuildingStorey(Storey gmlStorey) {
de.hft.stuttgart.citydoctor2.datastructure.Storey storey = new de.hft.stuttgart.citydoctor2.datastructure.Storey();
storey.setGmlObject(gmlStorey);
mapAbstractSpace(gmlStorey, storey);
mapAbstractSpace(gmlStorey, storey, Orientation.INWARD);
SurfaceMapper surfaceMapper = new SurfaceMapper(polygonMap, references, compositeMap, vertexMap, config);
for (AbstractSpaceBoundaryProperty surfaceProp : gmlStorey.getBoundaries()) {
if (!surfaceProp.isSetObject()) {
......@@ -1208,7 +1325,7 @@ public class Citygml3FeatureMapper extends ObjectWalker {
private de.hft.stuttgart.citydoctor2.datastructure.BuildingUnit mapBuildingUnit(BuildingUnit gmlBU) {
de.hft.stuttgart.citydoctor2.datastructure.BuildingUnit bu = new de.hft.stuttgart.citydoctor2.datastructure.BuildingUnit();
bu.setGmlObject(gmlBU);
mapAbstractSpace(gmlBU, bu);
mapAbstractSpace(gmlBU, bu, Orientation.OUTWARD);
SurfaceMapper surfaceMapper = new SurfaceMapper(polygonMap, references, compositeMap, vertexMap, config);
for (AbstractSpaceBoundaryProperty surfaceProp : gmlBU.getBoundaries()) {
if (!surfaceProp.isSetObject()) {
......@@ -1242,13 +1359,13 @@ public class Citygml3FeatureMapper extends ObjectWalker {
private Installation mapBuildingInstallation(org.citygml4j.core.model.building.BuildingInstallation gmlBi) {
Installation bi = new Installation();
bi.setGmlObject(gmlBi);
mapAbstractOccupiedSpace(gmlBi, bi);
mapAbstractOccupiedSpace(gmlBi, bi, Orientation.OUTWARD);
GeometryProperty<?> lod2Prop = gmlBi.getDeprecatedProperties().getLod2Geometry();
parseAndAddAbstractGeometry(lod2Prop, Lod.LOD2, bi);
parseAndAddAbstractGeometry(lod2Prop, Lod.LOD2, bi, Orientation.OUTWARD);
GeometryProperty<?> lod3Prop = gmlBi.getDeprecatedProperties().getLod3Geometry();
parseAndAddAbstractGeometry(lod3Prop, Lod.LOD3, bi);
parseAndAddAbstractGeometry(lod3Prop, Lod.LOD3, bi, Orientation.OUTWARD);
GeometryProperty<?> lod4Prop = gmlBi.getDeprecatedProperties().getLod4Geometry();
parseAndAddAbstractGeometry(lod4Prop, Lod.LOD4, bi);
parseAndAddAbstractGeometry(lod4Prop, Lod.LOD4, bi, Orientation.OUTWARD);
SurfaceMapper surfaceMapper = new SurfaceMapper(polygonMap, references, compositeMap, vertexMap, config);
for (AbstractSpaceBoundaryProperty surfaceProp : gmlBi.getBoundaries()) {
......@@ -1276,7 +1393,7 @@ public class Citygml3FeatureMapper extends ObjectWalker {
return bi;
}
private void parseAndAddAbstractGeometry(GeometryProperty<?> geomProp, Lod lod, CityObject co) {
private void parseAndAddAbstractGeometry(GeometryProperty<?> geomProp, Lod lod, CityObject co, Orientation orientation) {
if (geomProp == null || geomProp.getObject() == null) {
return;
}
......@@ -1285,7 +1402,7 @@ public class Citygml3FeatureMapper extends ObjectWalker {
Geometry geom = parseMultiSurface(ms, lod);
co.addGeometry(geom);
} else if (abstractGeometry instanceof Solid solid) {
Geometry geom = parseSolid(solid, lod);
Geometry geom = parseSolid(solid, lod, orientation);
if (geom != null) {
co.addGeometry(geom);
}
......@@ -1294,9 +1411,9 @@ public class Citygml3FeatureMapper extends ObjectWalker {
}
}
private Geometry parseSolid(AbstractSolid abstractSolid, Lod lod) {
private Geometry parseSolid(AbstractSolid abstractSolid, Lod lod, Orientation orientation) {
if (abstractSolid instanceof Solid s) {
return handleSolidGeometry(s, lod);
return handleSolidGeometry(s, lod, orientation);
} else {
logger.warn("Cannot handle solid class {}, can only process pure solids",
abstractSolid.getClass().getSimpleName());
......@@ -1304,13 +1421,13 @@ public class Citygml3FeatureMapper extends ObjectWalker {
}
}
private Geometry handleSolidGeometry(Solid solid, Lod lod) {
private Geometry handleSolidGeometry(Solid solid, Lod lod, Orientation orientation) {
ShellProperty exteriorProperty = solid.getExterior();
if (exteriorProperty == null || exteriorProperty.getObject() == null) {
logger.warn("Found solid {} without exterior hull, ignoring", solid.getId());
return null;
}
Geometry geom = new Geometry(GeometryType.SOLID, lod);
Geometry geom = new Geometry(GeometryType.SOLID, lod, orientation);
Shell exterior = solid.getExterior().getObject();
Citygml3GeometryMapper geometryMapper = new Citygml3GeometryMapper(config, vertexMap);
readSurfaceMember(geom, geometryMapper, exterior.getSurfaceMembers());
......@@ -1318,7 +1435,7 @@ public class Citygml3FeatureMapper extends ObjectWalker {
}
private Geometry parseMultiSurface(MultiSurface ms, Lod lod) {
Geometry geom = new Geometry(GeometryType.MULTI_SURFACE, lod);
Geometry geom = new Geometry(GeometryType.MULTI_SURFACE, lod, null);
Citygml3GeometryMapper geometryMapper = new Citygml3GeometryMapper(config, vertexMap);
readSurfaceMember(geom, geometryMapper, ms.getSurfaceMember());
return geom;
......@@ -1348,7 +1465,7 @@ public class Citygml3FeatureMapper extends ObjectWalker {
}
private Geometry parseCompositeSurface(CompositeSurface cs, Lod lod) {
Geometry geom = new Geometry(GeometryType.COMPOSITE_SURFACE, lod);
Geometry geom = new Geometry(GeometryType.COMPOSITE_SURFACE, lod, null);
Citygml3GeometryMapper geometryMapper = new Citygml3GeometryMapper(config, vertexMap);
readSurfaceMember(geom, geometryMapper, cs.getSurfaceMembers());
return geom;
......
......@@ -111,7 +111,6 @@ public class Citygml3GeometryMapper extends GeometryWalker {
conc.addInteriorRing(currentRing);
}
collection.addPatchMember(conc);
polygons.add(conc);
}
private void parsePolygon(String id, AbstractRingProperty exterior, List<AbstractRingProperty> interior) {
......
......@@ -107,7 +107,7 @@ public class SurfaceMapper extends ObjectWalker {
}
private Geometry parseMultiSurface(MultiSurface ms, Lod lod) {
Geometry geom = new Geometry(GeometryType.MULTI_SURFACE, lod);
Geometry geom = new Geometry(GeometryType.MULTI_SURFACE, lod, null);
Citygml3GeometryMapper geometryMapper = new Citygml3GeometryMapper(config, vertexMap);
readSurfaceMember(geom, geometryMapper, ms.getSurfaceMember());
return geom;
......
......@@ -32,4 +32,6 @@ public interface CityGmlConsumer {
}
// public void endOfFile();
}
......@@ -18,26 +18,43 @@
*/
package de.hft.stuttgart.citydoctor2.parser;
import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel;
import de.hft.stuttgart.citydoctor2.datastructure.CityObject;
import de.hft.stuttgart.citydoctor2.mapper.citygml3.Citygml3FeatureMapper;
import de.hft.stuttgart.citydoctor2.mapper.citygml3.GMLValidationHandler;
import de.hft.stuttgart.citydoctor2.math.Vector3d;
import de.hft.stuttgart.citydoctor2.utils.Localization;
import de.hft.stuttgart.citydoctor2.zip.CityGmlZipEntry;
import de.hft.stuttgart.citydoctor2.zip.CityGmlZipEntryFile;
import de.hft.stuttgart.quality.QualityADEContext;
import de.hft.stuttgart.quality.QualityADEModule;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.xml.XMLConstants;
import javax.xml.namespace.QName;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import de.hft.stuttgart.citydoctor2.datastructure.ImplicitGeometryHolder;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.citygml4j.core.ade.ADEException;
import org.citygml4j.core.ade.ADERegistry;
import org.citygml4j.core.model.CityGMLVersion;
import org.citygml4j.core.model.ade.ADEProperty;
import org.citygml4j.core.model.core.AbstractCityObject;
import org.citygml4j.core.model.core.AbstractCityObjectProperty;
import org.citygml4j.core.model.core.AbstractFeature;
import org.citygml4j.core.model.core.AbstractFeatureProperty;
import org.citygml4j.core.model.core.CityModel;
import org.citygml4j.core.util.CityGMLConstants;
import org.citygml4j.xml.CityGMLContext;
......@@ -68,30 +85,16 @@ import org.xmlobjects.schema.SchemaHandlerException;
import org.xmlobjects.stream.XMLReader;
import org.xmlobjects.stream.XMLReaderFactory;
import javax.xml.XMLConstants;
import javax.xml.namespace.QName;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel;
import de.hft.stuttgart.citydoctor2.datastructure.CityObject;
import de.hft.stuttgart.citydoctor2.mapper.citygml3.Citygml3FeatureMapper;
import de.hft.stuttgart.citydoctor2.mapper.citygml3.GMLValidationHandler;
import de.hft.stuttgart.citydoctor2.math.Vector3d;
import de.hft.stuttgart.citydoctor2.utils.Localization;
import de.hft.stuttgart.citydoctor2.zip.CityGmlZipEntry;
import de.hft.stuttgart.citydoctor2.zip.CityGmlZipEntryFile;
import de.hft.stuttgart.quality.QualityADEContext;
import de.hft.stuttgart.quality.QualityADEModule;
/**
* Utility class to parse CityGML files.
......@@ -430,6 +433,7 @@ public class CityGmlParser {
writer.writeMember(chunk);
}
}
// end of stream
logger.debug("End of gml file stream");
} catch (CityGMLReadException e) {
......@@ -447,11 +451,11 @@ public class CityGmlParser {
}
}
private static void writeCityModel(CityGMLChunkWriter writer, CityModel cModel) {
private static void writeCityModel(CityGMLChunkWriter writer, CityModel cModel) throws CityGMLWriteException {
if (writer != null) {
for (ADEProperty genEle : cModel.getADEProperties()) {
writer.getCityModelInfo().addADEProperty(genEle);
}
for (AbstractFeatureProperty featureProp : cModel.getFeatureMembers()) {
writer.writeMember(featureProp.getObject());
}
}
}
......@@ -525,6 +529,8 @@ public class CityGmlParser {
logger.info(Localization.getText("CityGmlParser.parsedObjects"),
mapper.getModel().getNumberOfFeatures());
}
// After parsing is complete, try to resolve deferred RelativeGeometries
ImplicitGeometryHolder.resolveDeferredObjects();
mapper.setCityGMLVersion(version);
return mapper.getModel();
}
......
......@@ -26,12 +26,10 @@ 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.datastructure.TopLevelTransportFeature;
import de.hft.stuttgart.citydoctor2.datastructure.TrafficSpaceObject;
import de.hft.stuttgart.citydoctor2.datastructure.TransportationObject;
import de.hft.stuttgart.citydoctor2.datastructure.TransportationSpace;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
import de.hft.stuttgart.citydoctor2.math.Vector3d;
import de.hft.stuttgart.citydoctor2.utils.visitors.CityObjectCollector;
import de.hft.stuttgart.citydoctor2.utils.visitors.MinMaxExtentVisitor;
/**
* Utility class for calculating axis aligned bounding boxes for different
......@@ -99,24 +97,11 @@ public class BoundingBoxCalculator {
* @return the bounding box of the model
*/
public static BoundingBox calculateBoundingBox(CityDoctorModel model) {
Vector3d low = new Vector3d(Double.MAX_VALUE, Double.MAX_VALUE, Double.MAX_VALUE);
Vector3d high = new Vector3d(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY);
// TODO: Rework to Visitor
MinMaxExtentVisitor mima = new MinMaxExtentVisitor();
model.accept(mima);
//TODO: Rework this using visitors
findMinMax(low, high, model.getBuildings());
findMinMax(low, high, model.getBridges());
findMinMax(low, high, model.getLand());
findMinMaxTransport(low, high, model.getTransportation());
findMinMax(low, high, model.getWater());
findMinMax(low, high, model.getVegetation());
findMinMax(low, high, model.getTunnels());
findMinMax(low, high, model.getCityFurniture());
findMinMax(low, high, model.getGenericCityObjects());
Vector3d[] result = new Vector3d[2];
result[0] = low;
result[1] = high;
return BoundingBox.of(result);
return BoundingBox.of(mima.getMinMaxExtent());
}
public static BoundingBox calculateBoundingBoxFromPoints(List<? extends Vector3d> points) {
......@@ -159,47 +144,39 @@ public class BoundingBoxCalculator {
}
}
//TODO: Implement this properly with visitor. Quick and dirty fix for the renderer
private static void findMinMaxTransport(Vector3d low, Vector3d high, List<? extends TransportationObject> features) {
for (TransportationObject to : features) {
findMinMax(low, high, to);
if (to instanceof TransportationSpace ts) {
findMinMaxTransport(low, high, ts.getTrafficSpaces());
findMinMaxTransport(low, high, ts.getAuxTrafficSpaces());
if (to instanceof TopLevelTransportFeature top) {
findMinMaxTransport(low, high, top.getSections());
findMinMaxTransport(low, high, top.getIntersections());
private static void findMinMax(Vector3d low, Vector3d high, CityObject co) {
CityObjectCollector collector = new CityObjectCollector();
co.accept(collector);
for (CityObject object : collector.getCityObjects()) {
for (Geometry geom : object.getGeometries()) {
if (geom.getVertices() == null) {
geom.updateVertices();
}
} else if (to instanceof TrafficSpaceObject tso) {
findMinMaxTransport(low, high, tso.getTrafficAreas());
findMinMax(low, high, geom);
}
}
}
private static void findMinMax(Vector3d low, Vector3d high, CityObject co) {
for (Geometry geom : co.getGeometries()) {
if (geom.getVertices() == null) {
geom.updateVertices();
private static void findMinMax(Vector3d low, Vector3d high, Geometry geom) {
for (Vertex v : geom.getVertices()) {
if (v.getX() < low.getX()) {
low.setX(v.getX());
}
for (Vertex v : geom.getVertices()) {
if (v.getX() < low.getX()) {
low.setX(v.getX());
}
if (v.getX() > high.getX()) {
high.setX(v.getX());
}
if (v.getY() < low.getY()) {
low.setY(v.getY());
}
if (v.getY() > high.getY()) {
high.setY(v.getY());
}
if (v.getZ() < low.getZ()) {
low.setZ(v.getZ());
}
if (v.getZ() > high.getZ()) {
high.setZ(v.getZ());
}
if (v.getX() > high.getX()) {
high.setX(v.getX());
}
if (v.getY() < low.getY()) {
low.setY(v.getY());
}
if (v.getY() > high.getY()) {
high.setY(v.getY());
}
if (v.getZ() < low.getZ()) {
low.setZ(v.getZ());
}
if (v.getZ() > high.getZ()) {
high.setZ(v.getZ());
}
}
}
......
package de.hft.stuttgart.citydoctor2.utils;
import java.io.Serial;
/**
* This Throwable signals that a requested CheckError was found.
*/
public class CheckErrorFound extends Throwable {
@Serial
private static final long serialVersionUID = -2066876428396230230L;
public CheckErrorFound() {
public CheckErrorFound() {
super("CheckError was found", null, true, false);
}
}
package de.hft.stuttgart.citydoctor2.utils.visitors;
import de.hft.stuttgart.citydoctor2.check.Checkable;
import de.hft.stuttgart.citydoctor2.check.CheckableUtilsVisitor;
import de.hft.stuttgart.citydoctor2.datastructure.CityObject;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.datastructure.ImplicitGeometryHolder;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
import de.hft.stuttgart.citydoctor2.math.Vector3d;
public class MinMaxExtentVisitor extends CheckableUtilsVisitor {
Vector3d low;
Vector3d high;
public MinMaxExtentVisitor() {
low = new Vector3d(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
high = new Vector3d(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY);
}
public Vector3d[] getMinMaxExtent() {
Vector3d[] result = new Vector3d[2];
result[0] = low;
result[1] = high;
return result;
}
@Override
public void check(CityObject co) {
for (Geometry geom : co.getGeometries()) {
if (geom.getVertices() == null) {
geom.updateVertices();
}
for (Vertex v : geom.getVertices()) {
if (v.getX() < low.getX()) {
low.setX(v.getX());
}
if (v.getX() > high.getX()) {
high.setX(v.getX());
}
if (v.getY() < low.getY()) {
low.setY(v.getY());
}
if (v.getY() > high.getY()) {
high.setY(v.getY());
}
if (v.getZ() < low.getZ()) {
low.setZ(v.getZ());
}
if (v.getZ() > high.getZ()) {
high.setZ(v.getZ());
}
}
}
}
}
......@@ -11,5 +11,8 @@
<Root level="debug" additivity="false">
<AppenderRef ref="console" />
</Root>
<Logger name="org.apache.fop" level="INFO">
<AppenderRef ref="console" />
</Logger>
</Loggers>
</Configuration>
\ No newline at end of file
......@@ -31,6 +31,7 @@ import org.junit.Test;
import de.hft.stuttgart.citydoctor2.check.error.SchematronError;
import de.hft.stuttgart.citydoctor2.datastructure.Building;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry.Orientation;
import de.hft.stuttgart.citydoctor2.datastructure.GeometryType;
import de.hft.stuttgart.citydoctor2.datastructure.GmlId;
import de.hft.stuttgart.citydoctor2.datastructure.Lod;
......@@ -90,7 +91,7 @@ public class CheckableTest {
@Test
public void testContainsError() {
Building b = new Building();
Geometry geom = new Geometry(GeometryType.SOLID, Lod.LOD0);
Geometry geom = new Geometry(GeometryType.SOLID, Lod.LOD0, Orientation.OUTWARD);
b.addGeometry(geom);
assertFalse(b.containsError(CheckId.C_GE_P_HOLE_OUTSIDE));
assertFalse(b.containsAnyError());
......@@ -148,7 +149,7 @@ public class CheckableTest {
@Test
public void testCollectAllContainedErrors() {
Building b = new Building();
Geometry geom = new Geometry(GeometryType.SOLID, Lod.LOD0);
Geometry geom = new Geometry(GeometryType.SOLID, Lod.LOD0, Orientation.OUTWARD);
b.addGeometry(geom);
b.addCheckResult(new CheckResult(CheckId.C_GE_P_HOLE_OUTSIDE, ResultStatus.ERROR,
new SchematronError(null, null, null, null)));
......
......@@ -30,6 +30,7 @@ import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.datastructure.GeometryType;
import de.hft.stuttgart.citydoctor2.datastructure.GmlId;
import de.hft.stuttgart.citydoctor2.datastructure.Lod;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry.Orientation;
import de.hft.stuttgart.quality.model.properties.AbstractErrorProperty;
import de.hft.stuttgart.quality.model.types.AbstractError;
import de.hft.stuttgart.quality.model.types.AllPolygonsOrientedWrongError;
......@@ -39,7 +40,7 @@ public class AllPolygonsWrongOrientationErrorTest {
@Test
public void testAddToValidationResult() {
Geometry geom = new Geometry(GeometryType.SOLID, Lod.LOD2);
Geometry geom = new Geometry(GeometryType.SOLID, Lod.LOD2, Orientation.OUTWARD);
GmlId gmlId = new GmlId("testId");
geom.setGmlId(gmlId);
AllPolygonsWrongOrientationError err = new AllPolygonsWrongOrientationError(geom);
......
......@@ -33,6 +33,7 @@ import de.hft.stuttgart.citydoctor2.datastructure.GeometryType;
import de.hft.stuttgart.citydoctor2.datastructure.GmlId;
import de.hft.stuttgart.citydoctor2.datastructure.Lod;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry.Orientation;
import de.hft.stuttgart.quality.model.properties.AbstractErrorProperty;
import de.hft.stuttgart.quality.model.properties.PolygonIdListProperty;
import de.hft.stuttgart.quality.model.types.AbstractError;
......@@ -44,7 +45,7 @@ public class MultipleConnectedComponentsErrorTest {
@Test
public void testConvertToQualityAdeDatastructure() {
Geometry geom = new Geometry(GeometryType.SOLID, Lod.LOD2);
Geometry geom = new Geometry(GeometryType.SOLID, Lod.LOD2, Orientation.OUTWARD);
GmlId geomId = new GmlId("geomId");
geom.setGmlId(geomId);
Polygon p1 = new ConcretePolygon();
......
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