Commit 0f3d9a85 authored by Riegel's avatar Riegel
Browse files

Merge branch 'dev' into 'master'

CityDoctor Release Version 3.16.0

See merge request !11
parents b7b8f5fe b2d40f78
Pipeline #10323 passed with stage
in 1 minute and 25 seconds
/*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
......@@ -20,12 +20,11 @@ package de.hft.stuttgart.citydoctor2.datastructure;
/**
* The available opening types in CityGML
*
* @author Matthias Betz
*
* @author Matthias Betz
*/
public enum OpeningType {
DOOR, WINDOW, UNKNOWN
DOOR, WINDOW, UNKNOWN
}
/*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
......@@ -18,70 +18,70 @@
*/
package de.hft.stuttgart.citydoctor2.datastructure;
import java.io.Serial;
import java.util.List;
import de.hft.stuttgart.citydoctor2.math.Vector3d;
import de.hft.stuttgart.citydoctor2.tesselation.TesselatedPolygon;
import java.io.Serial;
import java.util.List;
/**
* Interface for concrete and linked polygons.
*
* @author Matthias Betz
*
* @author Matthias Betz
*/
public abstract class Polygon extends GmlElement {
@Serial
private static final long serialVersionUID = -613942946364706513L;
@Serial
private static final long serialVersionUID = -613942946364706513L;
public abstract Vector3d calculateNormalNormalized();
public abstract Vector3d calculateNormal();
public abstract TesselatedPolygon tesselate();
public abstract Vector3d calculateNormalNormalized();
public abstract Vector3d calculateNormal();
public abstract LinearRing getExteriorRing();
public abstract TesselatedPolygon tesselate();
public abstract List<LinearRing> getInnerRings();
public abstract LinearRing getExteriorRing();
public abstract boolean isPointInsideExteriorRing(Vector3d v);
public abstract List<LinearRing> getInnerRings();
public abstract Geometry getParent();
public abstract boolean isPointInsideExteriorRing(Vector3d v);
public abstract void setParent(Geometry geometry);
public abstract Geometry getParent();
public abstract void setExteriorRing(LinearRing extRing);
public abstract void setParent(Geometry geometry);
public abstract boolean isPolygonConnectedViaPoint(Polygon other);
public abstract void setExteriorRing(LinearRing extRing);
public abstract void addInteriorRing(LinearRing inter);
public abstract boolean isPolygonConnectedViaPoint(Polygon other);
public abstract BoundarySurface getPartOfSurface();
public abstract void addInteriorRing(LinearRing inter);
public abstract void setPartOfSurface(BoundarySurface bs);
public abstract BoundarySurface getPartOfSurface();
public abstract void removeInnerRing(LinearRing ring);
public abstract void setPartOfSurface(BoundarySurface bs);
public abstract void setPartOfInstallation(Installation bi);
public abstract void removeInnerRing(LinearRing ring);
public abstract Installation getPartOfInstallation();
public abstract void setPartOfInstallation(Installation bi);
public abstract boolean hasPointAsCorner(Vertex v);
public abstract Installation getPartOfInstallation();
public abstract void removeRings();
public abstract boolean hasPointAsCorner(Vertex v);
public abstract boolean isLinkedTo();
public abstract void removeRings();
public abstract boolean isLink();
public abstract boolean isLinkedTo();
public abstract LinkedPolygon getLinkedFromPolygon();
public abstract boolean isLink();
abstract void anonymize();
public abstract LinkedPolygon getLinkedFromPolygon();
public abstract ConcretePolygon getOriginal();
abstract void anonymize();
public abstract void remove();
public abstract ConcretePolygon getOriginal();
public abstract void remove();
public abstract double getArea();
public abstract double getArea();
}
\ No newline at end of file
package de.hft.stuttgart.citydoctor2.datastructure;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.Serial;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Reference object for handling of implicit geometries with a relative geometry
*
* @author Riegel
*/
public class RelativeGeometry extends Geometry {
private static final Logger logger = LogManager.getLogger(RelativeGeometry.class);
@Serial
private static final long serialVersionUID = -686112245455298977L;
private static Map<Geometry, RelativeGeometry> relativeGeometries = new ConcurrentHashMap<>();
public static RelativeGeometry of(Geometry geom) {
if (relativeGeometries.containsKey(geom)) {
return relativeGeometries.get(geom);
}
RelativeGeometry relGeo = new RelativeGeometry(geom.getType(), geom.getLod());
geom.getPolygons().forEach(relGeo::addPolygon);
relGeo.updateEdgesAndVertices();
relativeGeometries.put(geom, relGeo);
return relGeo;
}
private RelativeGeometry(GeometryType type, Lod lod) {
super(type, lod);
}
}
/*-
* Copyright 2022 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
......@@ -18,142 +18,141 @@
*/
package de.hft.stuttgart.citydoctor2.datastructure;
import java.io.Serial;
import java.util.ArrayList;
import java.util.List;
import org.citygml4j.core.model.relief.ReliefFeature;
import org.citygml4j.core.util.geometry.GeometryFactory;
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.parser.ParserConfiguration;
import de.hft.stuttgart.citydoctor2.utils.CopyHandler;
import de.hft.stuttgart.citydoctor2.utils.Copyable;
import org.citygml4j.core.model.relief.ReliefFeature;
import org.citygml4j.core.util.geometry.GeometryFactory;
import java.io.Serial;
import java.util.ArrayList;
import java.util.List;
public class ReliefObject extends CityObject {
@Serial
private static final long serialVersionUID = -9162169874426519903L;
private final ReliefFeature feature;
private final List<TinObject> components = new ArrayList<>();
public ReliefObject(ReliefFeature feature) {
this.feature = feature;
}
@Override
public void accept(Check c) {
super.accept(c);
if (c.canExecute(this)) {
c.check(this);
}
for (TinObject tin : components) {
tin.accept(c);
}
}
@Override
public void collectInstances(CopyHandler handler) {
handler.addInstance(components);
}
@Override
public void fillValues(Copyable original, CopyHandler handler) {
super.fillValues(original, handler);
ReliefObject originalRelief = (ReliefObject) original;
for (TinObject tin : originalRelief.components) {
components.add(handler.getCopyInstance(tin));
}
}
@Override
public Copyable createCopyInstance() {
return new ReliefObject(feature);
}
@Override
public void prepareForChecking() {
for (TinObject component : components) {
component.prepareForChecking();
}
}
@Override
public void clearMetaInformation() {
for (TinObject component : components) {
component.clearMetaInformation();
}
}
@Override
public void clearAllContainedCheckResults() {
for (TinObject component : components) {
component.clearAllContainedCheckResults();
}
}
@Override
public void collectContainedErrors(List<CheckError> errors) {
super.collectContainedErrors(errors);
for (TinObject tin : components) {
tin.collectContainedErrors(errors);
}
}
@Override
public boolean containsAnyError() {
boolean containsError = super.containsAnyError();
if (containsError) {
return true;
}
for (TinObject tin : components) {
if (tin.containsAnyError()) {
return true;
}
}
return false;
}
@Override
public boolean containsError(CheckId checkIdentifier) {
boolean hasError = super.containsError(checkIdentifier);
if (hasError) {
return true;
}
for (TinObject tin : components) {
if (tin.containsError(checkIdentifier)) {
return true;
}
}
return false;
}
@Override
public void reCreateGeometries(GeometryFactory factory, ParserConfiguration config) {
// no geometries
}
@Override
public ReliefFeature getGmlObject() {
return feature;
}
@Override
public void unsetGmlGeometries() {
// no geometries
}
@Override
public FeatureType getFeatureType() {
return FeatureType.LAND;
}
public List<TinObject> getComponents() {
return components;
}
@Serial
private static final long serialVersionUID = -9162169874426519903L;
private final ReliefFeature feature;
private final List<TinObject> components = new ArrayList<>();
public ReliefObject(ReliefFeature feature) {
this.feature = feature;
}
@Override
public void accept(Check c) {
super.accept(c);
if (c.canExecute(this)) {
c.check(this);
}
for (TinObject tin : components) {
tin.accept(c);
}
}
@Override
public void collectInstances(CopyHandler handler) {
handler.addInstance(components);
}
@Override
public void fillValues(Copyable original, CopyHandler handler) {
super.fillValues(original, handler);
ReliefObject originalRelief = (ReliefObject) original;
for (TinObject tin : originalRelief.components) {
components.add(handler.getCopyInstance(tin));
}
}
@Override
public Copyable createCopyInstance() {
return new ReliefObject(feature);
}
@Override
public void prepareForChecking() {
for (TinObject component : components) {
component.prepareForChecking();
}
}
@Override
public void clearMetaInformation() {
for (TinObject component : components) {
component.clearMetaInformation();
}
}
@Override
public void clearAllContainedCheckResults() {
for (TinObject component : components) {
component.clearAllContainedCheckResults();
}
}
@Override
public void collectContainedErrors(List<CheckError> errors) {
super.collectContainedErrors(errors);
for (TinObject tin : components) {
tin.collectContainedErrors(errors);
}
}
@Override
public boolean containsAnyError() {
boolean containsError = super.containsAnyError();
if (containsError) {
return true;
}
for (TinObject tin : components) {
if (tin.containsAnyError()) {
return true;
}
}
return false;
}
@Override
public boolean containsError(CheckId checkIdentifier) {
boolean hasError = super.containsError(checkIdentifier);
if (hasError) {
return true;
}
for (TinObject tin : components) {
if (tin.containsError(checkIdentifier)) {
return true;
}
}
return false;
}
@Override
public void reCreateGeometries(GeometryFactory factory, ParserConfiguration config) {
// no geometries
}
@Override
public ReliefFeature getGmlObject() {
return feature;
}
@Override
public void unsetGmlGeometries() {
// no geometries
}
@Override
public FeatureType getFeatureType() {
return FeatureType.LAND;
}
public List<TinObject> getComponents() {
return components;
}
}
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.parser.ParserConfiguration;
import de.hft.stuttgart.citydoctor2.utils.CopyHandler;
import de.hft.stuttgart.citydoctor2.utils.Copyable;
import org.citygml4j.core.util.geometry.GeometryFactory;
import java.io.Serial;
import java.util.ArrayList;
import java.util.List;
public class Storey extends AbstractBuildingSubdivision {
@Serial
private static final long serialVersionUID = 5162814691642668089L;
private final List<BuildingUnit> buildingUnits = new ArrayList<>();
@Override
public Copyable createCopyInstance() {
return new Storey();
}
@Override
public void unsetGmlGeometries() {
super.unsetGmlGeometries();
for (BuildingUnit buildingUnit : buildingUnits) {
buildingUnit.unsetGmlGeometries();
}
}
@Override
public void reCreateGeometries(GeometryFactory factory, ParserConfiguration config) {
super.reCreateGeometries(factory, config);
for (BuildingUnit buildingUnit : buildingUnits) {
buildingUnit.reCreateGeometries(factory, config);
}
}
@Override
public void accept(Check c) {
super.accept(c);
for (BuildingUnit buildingUnit : buildingUnits) {
buildingUnit.accept(c);
}
}
@Override
public void collectContainedErrors(List<CheckError> errors) {
super.collectContainedErrors(errors);
for (BuildingUnit buildingUnit : buildingUnits) {
buildingUnit.collectContainedErrors(errors);
}
}
@Override
public void clearAllContainedCheckResults() {
super.clearAllContainedCheckResults();
for (BuildingUnit buildingUnit : buildingUnits) {
buildingUnit.clearAllContainedCheckResults();
}
}
@Override
public boolean containsError(CheckId checkIdentifier) {
boolean hasError = super.containsError(checkIdentifier);
if (hasError) {
return true;
}
for (BuildingUnit buildingUnit : buildingUnits) {
if (buildingUnit.containsError(checkIdentifier)) {
return true;
}
}
return false;
}
@Override
public boolean containsAnyError() {
boolean hasError = super.containsAnyError();
if (hasError) {
return true;
}
for (BuildingUnit buildingUnit : buildingUnits) {
if (buildingUnit.containsAnyError()) {
return true;
}
}
return false;
}
@Override
public void prepareForChecking() {
super.prepareForChecking();
for (BuildingUnit buildingUnit : buildingUnits) {
buildingUnit.prepareForChecking();
}
}
@Override
public void clearMetaInformation() {
super.clearMetaInformation();
for (BuildingUnit buildingUnit : buildingUnits) {
buildingUnit.clearMetaInformation();
}
}
@Override
public void collectInstances(CopyHandler handler) {
super.collectInstances(handler);
for (BuildingUnit buildingUnit : buildingUnits) {
buildingUnit.collectInstances(handler);
}
}
@Override
public void fillValues(Copyable original, CopyHandler handler) {
super.fillValues(original, handler);
Storey originalSt = (Storey) original;
for (BuildingUnit buildingUnit : originalSt.buildingUnits) {
buildingUnits.add(handler.getCopyInstance(buildingUnit));
}
this.abs = originalSt.abs;
}
}
/*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
......@@ -20,12 +20,11 @@ package de.hft.stuttgart.citydoctor2.datastructure;
/**
* Availabel bridge types in CityGML
*
* @author Matthias Betz
*
* @author Matthias Betz
*/
public enum SurfaceFeatureType {
BUILDING, BRIDGE, TUNNEL
BUILDING, BRIDGE, TUNNEL
}
/*-
* Copyright 2022 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
......@@ -18,10 +18,9 @@
*/
package de.hft.stuttgart.citydoctor2.datastructure;
import java.io.Serial;
import java.util.ArrayList;
import java.util.List;
import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;
import de.hft.stuttgart.citydoctor2.utils.CityGmlUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.citygml4j.core.model.relief.TINRelief;
......@@ -31,70 +30,70 @@ import org.xmlobjects.gml.model.geometry.primitives.Triangle;
import org.xmlobjects.gml.model.geometry.primitives.TriangleArrayProperty;
import org.xmlobjects.gml.model.geometry.primitives.TriangulatedSurface;
import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;
import de.hft.stuttgart.citydoctor2.utils.CityGmlUtils;
import java.io.Serial;
import java.util.ArrayList;
import java.util.List;
public class TinObject extends CityObject {
private static final Logger logger = LogManager.getLogger(TinObject.class);
private static final Logger logger = LogManager.getLogger(TinObject.class);
@Serial
private static final long serialVersionUID = 1910744427384724422L;
@Serial
private static final long serialVersionUID = 1910744427384724422L;
private final TINRelief gmlRelief;
private final TINRelief gmlRelief;
public TinObject(TINRelief gmlRelief) {
this.gmlRelief = gmlRelief;
}
public TinObject(TINRelief gmlRelief) {
this.gmlRelief = gmlRelief;
}
@Override
public void accept(Check c) {
super.accept(c);
if (c.canExecute(this)) {
c.check(this);
}
}
@Override
public void accept(Check c) {
super.accept(c);
if (c.canExecute(this)) {
c.check(this);
}
}
@Override
public TinObject createCopyInstance() {
return new TinObject(gmlRelief);
}
@Override
public TinObject createCopyInstance() {
return new TinObject(gmlRelief);
}
@Override
public void reCreateGeometries(GeometryFactory factory, ParserConfiguration config) {
if (getGeometries().isEmpty()) {
return;
}
if (getGeometries().size() > 1) {
logger.warn("A TINRelief can only have one geometry but found {}. Using the first geometry found",
getGeometries().size());
}
Geometry geom = getGeometries().get(0);
List<Triangle> triangles = new ArrayList<>();
TriangulatedSurface surface = new TriangulatedSurface();
surface.setPatches(new TriangleArrayProperty(triangles));
for (Polygon poly : geom.getPolygons()) {
LinearRing ring = poly.getExteriorRing();
Triangle t = new Triangle();
t.setExterior(new AbstractRingProperty(CityGmlUtils.createGmlRing(factory, config, ring)));
triangles.add(t);
}
}
@Override
public void reCreateGeometries(GeometryFactory factory, ParserConfiguration config) {
if (getGeometries().isEmpty()) {
return;
}
if (getGeometries().size() > 1) {
logger.warn("A TINRelief can only have one geometry but found {}. Using the first geometry found",
getGeometries().size());
}
Geometry geom = getGeometries().get(0);
List<Triangle> triangles = new ArrayList<>();
TriangulatedSurface surface = new TriangulatedSurface();
surface.setPatches(new TriangleArrayProperty(triangles));
for (Polygon poly : geom.getPolygons()) {
LinearRing ring = poly.getExteriorRing();
Triangle t = new Triangle();
t.setExterior(new AbstractRingProperty(CityGmlUtils.createGmlRing(factory, config, ring)));
triangles.add(t);
}
}
@Override
public TINRelief getGmlObject() {
return gmlRelief;
}
@Override
public TINRelief getGmlObject() {
return gmlRelief;
}
@Override
public void unsetGmlGeometries() {
gmlRelief.setTin(null);
}
@Override
public void unsetGmlGeometries() {
gmlRelief.setTin(null);
}
@Override
public FeatureType getFeatureType() {
return FeatureType.LAND;
}
@Override
public FeatureType getFeatureType() {
return FeatureType.LAND;
}
}
/*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
......@@ -18,10 +18,13 @@
*/
package de.hft.stuttgart.citydoctor2.datastructure;
import java.io.Serial;
import java.util.ArrayList;
import java.util.List;
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.parser.ParserConfiguration;
import de.hft.stuttgart.citydoctor2.utils.CityGmlUtils;
import de.hft.stuttgart.citydoctor2.utils.CopyHandler;
import de.hft.stuttgart.citydoctor2.utils.Copyable;
import org.citygml4j.core.model.core.AbstractCityObject;
import org.citygml4j.core.model.core.AbstractSpace;
import org.citygml4j.core.model.transportation.AbstractTransportationSpace;
......@@ -31,299 +34,297 @@ import org.citygml4j.core.util.geometry.GeometryFactory;
import org.xmlobjects.gml.model.geometry.aggregates.MultiSurface;
import org.xmlobjects.gml.model.geometry.aggregates.MultiSurfaceProperty;
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.parser.ParserConfiguration;
import de.hft.stuttgart.citydoctor2.utils.CityGmlUtils;
import de.hft.stuttgart.citydoctor2.utils.CopyHandler;
import de.hft.stuttgart.citydoctor2.utils.Copyable;
import java.io.Serial;
import java.util.ArrayList;
import java.util.List;
/**
* Representation of a transportation object.
*
* @author Matthias Betz
*
* @author Matthias Betz
*/
public class TransportationObject extends CityObject {
@Serial
private static final long serialVersionUID = -2698907271726700390L;
@Serial
private static final long serialVersionUID = -2698907271726700390L;
public enum TransportationType {
ROAD, TRACK, RAILWAY, TRAFFIC_AREA, AUXILLIARY_TRAFFIC_AREA, TRANSPORTATION_COMPLEX, SQUARE, AUXILLIARY_TRAFFIC_SPACE, TRAFFIC_SPACE
}
private AbstractCityObject ato;
private final List<TransportationObject> composesOf = new ArrayList<>(1);
private final TransportationType type;
public enum TransportationType {
ROAD, TRACK, RAILWAY, TRAFFIC_AREA, AUXILLIARY_TRAFFIC_AREA, TRANSPORTATION_COMPLEX, SQUARE, AUXILLIARY_TRAFFIC_SPACE, TRAFFIC_SPACE
}
public TransportationObject(TransportationType type) {
this.type = type;
}
private AbstractCityObject ato;
private final List<TransportationObject> composesOf = new ArrayList<>(1);
private final TransportationType type;
@Override
public FeatureType getFeatureType() {
return FeatureType.TRANSPORTATION;
}
public TransportationObject(TransportationType type) {
this.type = type;
}
@Override
public void reCreateGeometries(GeometryFactory factory, ParserConfiguration config) {
for (Geometry geom : getGeometries()) {
if (geom instanceof ImplicitGeometryHolder) {
continue;
}
if (geom.getType() == GeometryType.MULTI_SURFACE) {
MultiSurface ms = CityGmlUtils.createMultiSurface(geom, factory, config);
switch (type) {
case ROAD, TRACK, RAILWAY, SQUARE, TRANSPORTATION_COMPLEX:
AbstractTransportationSpace tc = (AbstractTransportationSpace) ato;
setMultiSurfaceAccordingToLod(tc, ms, geom.getLod());
break;
case TRAFFIC_AREA:
TrafficArea ta = (TrafficArea) ato;
setMultiSurfaceAccordingToLod(ta, ms, geom.getLod());
break;
case AUXILLIARY_TRAFFIC_AREA:
AuxiliaryTrafficArea ata = (AuxiliaryTrafficArea) ato;
setMultiSurfaceAccordingToLod(ata, ms, geom.getLod());
break;
case AUXILLIARY_TRAFFIC_SPACE, TRAFFIC_SPACE:
AbstractSpace ats = (AbstractSpace) ato;
setMultiSurfaceAccordingToLod(ats, ms, geom.getLod());
break;
}
} else {
throw new IllegalStateException("Geometry in TransportationObject cannot be of type " + geom.getType()
+ ". Only MultiSurface allowed");
}
}
for (TransportationObject children : composesOf) {
children.reCreateGeometries(factory, config);
}
}
@Override
public FeatureType getFeatureType() {
return FeatureType.TRANSPORTATION;
}
private void setMultiSurfaceAccordingToLod(AbstractSpace ats, MultiSurface ms, Lod lod) {
switch (lod) {
case LOD0:
ats.setLod0MultiSurface(new MultiSurfaceProperty(ms));
break;
case LOD2:
ats.setLod2MultiSurface(new MultiSurfaceProperty(ms));
break;
case LOD3:
ats.setLod3MultiSurface(new MultiSurfaceProperty(ms));
break;
default:
throw new IllegalStateException("cannot set geometry with LOD for AuxiliaryTrafficSpace: " + lod);
}
}
@Override
public void reCreateGeometries(GeometryFactory factory, ParserConfiguration config) {
for (Geometry geom : getGeometries()) {
if (geom.getType() == GeometryType.MULTI_SURFACE) {
MultiSurface ms = CityGmlUtils.createMultiSurface(geom, factory, config);
switch (type) {
case ROAD, TRACK, RAILWAY, SQUARE, TRANSPORTATION_COMPLEX:
AbstractTransportationSpace tc = (AbstractTransportationSpace) ato;
setMultiSurfaceAccordingToLod(tc, ms, geom.getLod());
break;
case TRAFFIC_AREA:
TrafficArea ta = (TrafficArea) ato;
setMultiSurfaceAccordingToLod(ta, ms, geom.getLod());
break;
case AUXILLIARY_TRAFFIC_AREA:
AuxiliaryTrafficArea ata = (AuxiliaryTrafficArea) ato;
setMultiSurfaceAccordingToLod(ata, ms, geom.getLod());
break;
case AUXILLIARY_TRAFFIC_SPACE, TRAFFIC_SPACE:
AbstractSpace ats = (AbstractSpace) ato;
setMultiSurfaceAccordingToLod(ats, ms, geom.getLod());
break;
}
} else {
throw new IllegalStateException("Geometry in TransportationObject cannot be of type " + geom.getType()
+ ". Only MultiSurface allowed");
}
}
for (TransportationObject children : composesOf) {
children.reCreateGeometries(factory, config);
}
}
private void setMultiSurfaceAccordingToLod(AbstractTransportationSpace tc, MultiSurface ms, Lod lod) {
switch (lod) {
case LOD1:
tc.getDeprecatedProperties().setLod1MultiSurface(new MultiSurfaceProperty(ms));
break;
case LOD2:
tc.setLod2MultiSurface(new MultiSurfaceProperty(ms));
break;
case LOD3:
tc.setLod3MultiSurface(new MultiSurfaceProperty(ms));
break;
case LOD4:
tc.getDeprecatedProperties().setLod4MultiSurface(new MultiSurfaceProperty(ms));
break;
default:
throw new IllegalStateException("cannot set geometry with LOD for TransportationComplex: " + lod);
}
}
private void setMultiSurfaceAccordingToLod(AbstractSpace ats, MultiSurface ms, Lod lod) {
switch (lod) {
case LOD0:
ats.setLod0MultiSurface(new MultiSurfaceProperty(ms));
break;
case LOD2:
ats.setLod2MultiSurface(new MultiSurfaceProperty(ms));
break;
case LOD3:
ats.setLod3MultiSurface(new MultiSurfaceProperty(ms));
break;
default:
throw new IllegalStateException("cannot set geometry with LOD for AuxiliaryTrafficSpace: " + lod);
}
}
private void setMultiSurfaceAccordingToLod(AuxiliaryTrafficArea ata, MultiSurface ms, Lod lod) {
switch (lod) {
case LOD0:
ata.setLod0MultiSurface(new MultiSurfaceProperty(ms));
break;
case LOD1:
ata.setLod1MultiSurface(new MultiSurfaceProperty(ms));
break;
case LOD2:
ata.setLod2MultiSurface(new MultiSurfaceProperty(ms));
break;
case LOD3:
ata.setLod3MultiSurface(new MultiSurfaceProperty(ms));
break;
case LOD4:
ata.getDeprecatedProperties().setLod4MultiSurface(new MultiSurfaceProperty(ms));
break;
default:
throw new IllegalStateException("cannot set geometry with LOD for AuxiliaryTrafficArea: " + lod);
}
}
private void setMultiSurfaceAccordingToLod(AbstractTransportationSpace tc, MultiSurface ms, Lod lod) {
switch (lod) {
case LOD1:
tc.getDeprecatedProperties().setLod1MultiSurface(new MultiSurfaceProperty(ms));
break;
case LOD2:
tc.setLod2MultiSurface(new MultiSurfaceProperty(ms));
break;
case LOD3:
tc.setLod3MultiSurface(new MultiSurfaceProperty(ms));
break;
case LOD4:
tc.getDeprecatedProperties().setLod4MultiSurface(new MultiSurfaceProperty(ms));
break;
default:
throw new IllegalStateException("cannot set geometry with LOD for TransportationComplex: " + lod);
}
}
private void setMultiSurfaceAccordingToLod(TrafficArea ta, MultiSurface ms, Lod lod) {
switch (lod) {
case LOD2:
ta.setLod2MultiSurface(new MultiSurfaceProperty(ms));
break;
case LOD3:
ta.setLod3MultiSurface(new MultiSurfaceProperty(ms));
break;
case LOD4:
ta.getDeprecatedProperties().setLod4MultiSurface(new MultiSurfaceProperty(ms));
break;
default:
throw new IllegalStateException("cannot set geometry with LOD for TrafficArea: " + lod);
}
}
private void setMultiSurfaceAccordingToLod(AuxiliaryTrafficArea ata, MultiSurface ms, Lod lod) {
switch (lod) {
case LOD0:
ata.setLod0MultiSurface(new MultiSurfaceProperty(ms));
break;
case LOD1:
ata.setLod1MultiSurface(new MultiSurfaceProperty(ms));
break;
case LOD2:
ata.setLod2MultiSurface(new MultiSurfaceProperty(ms));
break;
case LOD3:
ata.setLod3MultiSurface(new MultiSurfaceProperty(ms));
break;
case LOD4:
ata.getDeprecatedProperties().setLod4MultiSurface(new MultiSurfaceProperty(ms));
break;
default:
throw new IllegalStateException("cannot set geometry with LOD for AuxiliaryTrafficArea: " + lod);
}
}
@Override
public boolean containsError(CheckId checkIdentifier) {
boolean hasError = super.containsError(checkIdentifier);
if (hasError) {
return true;
}
for (TransportationObject to : composesOf) {
if (to.containsError(checkIdentifier)) {
return true;
}
}
return false;
}
private void setMultiSurfaceAccordingToLod(TrafficArea ta, MultiSurface ms, Lod lod) {
switch (lod) {
case LOD2:
ta.setLod2MultiSurface(new MultiSurfaceProperty(ms));
break;
case LOD3:
ta.setLod3MultiSurface(new MultiSurfaceProperty(ms));
break;
case LOD4:
ta.getDeprecatedProperties().setLod4MultiSurface(new MultiSurfaceProperty(ms));
break;
default:
throw new IllegalStateException("cannot set geometry with LOD for TrafficArea: " + lod);
}
}
@Override
public void clearAllContainedCheckResults() {
super.clearAllContainedCheckResults();
for (TransportationObject to : composesOf) {
to.clearAllContainedCheckResults();
}
}
@Override
public boolean containsError(CheckId checkIdentifier) {
boolean hasError = super.containsError(checkIdentifier);
if (hasError) {
return true;
}
for (TransportationObject to : composesOf) {
if (to.containsError(checkIdentifier)) {
return true;
}
}
return false;
}
@Override
public void collectContainedErrors(List<CheckError> errors) {
super.collectContainedErrors(errors);
for (TransportationObject to : composesOf) {
to.collectContainedErrors(errors);
}
}
@Override
public void clearAllContainedCheckResults() {
super.clearAllContainedCheckResults();
for (TransportationObject to : composesOf) {
to.clearAllContainedCheckResults();
}
}
@Override
public boolean containsAnyError() {
boolean hasError = super.containsAnyError();
if (hasError) {
return true;
}
for (TransportationObject to : composesOf) {
if (to.containsAnyError()) {
return true;
}
}
return false;
}
@Override
public void collectContainedErrors(List<CheckError> errors) {
super.collectContainedErrors(errors);
for (TransportationObject to : composesOf) {
to.collectContainedErrors(errors);
}
}
@Override
public void accept(Check c) {
super.accept(c);
if (c.canExecute(this)) {
c.check(this);
}
for (TransportationObject to : composesOf) {
to.accept(c);
}
}
@Override
public boolean containsAnyError() {
boolean hasError = super.containsAnyError();
if (hasError) {
return true;
}
for (TransportationObject to : composesOf) {
if (to.containsAnyError()) {
return true;
}
}
return false;
}
@Override
public AbstractCityObject getGmlObject() {
return ato;
}
@Override
public void accept(Check c) {
super.accept(c);
if (c.canExecute(this)) {
c.check(this);
}
for (TransportationObject to : composesOf) {
to.accept(c);
}
}
@Override
public void unsetGmlGeometries() {
switch (type) {
case ROAD, TRACK, RAILWAY, SQUARE, TRANSPORTATION_COMPLEX:
AbstractTransportationSpace tc = (AbstractTransportationSpace) ato;
tc.getDeprecatedProperties().setLod1MultiSurface(null);
tc.setLod2MultiSurface(null);
tc.setLod3MultiSurface(null);
tc.getDeprecatedProperties().setLod4MultiSurface(null);
break;
case TRAFFIC_AREA:
TrafficArea ta = (TrafficArea) ato;
ta.setLod2MultiSurface(null);
ta.setLod3MultiSurface(null);
ta.getDeprecatedProperties().setLod4MultiSurface(null);
break;
case AUXILLIARY_TRAFFIC_AREA:
AuxiliaryTrafficArea ata = (AuxiliaryTrafficArea) ato;
ata.setLod0MultiSurface(null);
ata.setLod1MultiSurface(null);
ata.setLod2MultiSurface(null);
ata.setLod3MultiSurface(null);
ata.getDeprecatedProperties().setLod4MultiSurface(null);
break;
case AUXILLIARY_TRAFFIC_SPACE, TRAFFIC_SPACE:
AbstractSpace ats = (AbstractSpace) ato;
ats.setLod0MultiSurface(null);
ats.setLod2MultiSurface(null);
ats.setLod3MultiSurface(null);
break;
}
}
@Override
public AbstractCityObject getGmlObject() {
return ato;
}
public void setGmlObject(AbstractCityObject tc) {
ato = tc;
}
@Override
public void unsetGmlGeometries() {
switch (type) {
case ROAD, TRACK, RAILWAY, SQUARE,TRANSPORTATION_COMPLEX:
AbstractTransportationSpace tc = (AbstractTransportationSpace) ato;
tc.getDeprecatedProperties().setLod1MultiSurface(null);
tc.setLod2MultiSurface(null);
tc.setLod3MultiSurface(null);
tc.getDeprecatedProperties().setLod4MultiSurface(null);
break;
case TRAFFIC_AREA:
TrafficArea ta = (TrafficArea) ato;
ta.setLod2MultiSurface(null);
ta.setLod3MultiSurface(null);
ta.getDeprecatedProperties().setLod4MultiSurface(null);
break;
case AUXILLIARY_TRAFFIC_AREA:
AuxiliaryTrafficArea ata = (AuxiliaryTrafficArea) ato;
ata.setLod0MultiSurface(null);
ata.setLod1MultiSurface(null);
ata.setLod2MultiSurface(null);
ata.setLod3MultiSurface(null);
ata.getDeprecatedProperties().setLod4MultiSurface(null);
break;
case AUXILLIARY_TRAFFIC_SPACE, TRAFFIC_SPACE:
AbstractSpace ats = (AbstractSpace) ato;
ats.setLod0MultiSurface(null);
ats.setLod2MultiSurface(null);
ats.setLod3MultiSurface(null);
break;
}
}
public void addChild(TransportationObject subTrans) {
composesOf.add(subTrans);
}
public void setGmlObject(AbstractCityObject tc) {
ato = tc;
}
public List<TransportationObject> getChildren() {
return composesOf;
}
public void addChild(TransportationObject subTrans) {
composesOf.add(subTrans);
}
public TransportationType getTransportationType() {
return type;
}
public List<TransportationObject> getChildren() {
return composesOf;
}
@Override
public String toString() {
return "TransportationObject [id=" + getGmlId() + "]";
}
public TransportationType getTransportationType() {
return type;
}
@Override
public void prepareForChecking() {
super.prepareForChecking();
for (TransportationObject child : composesOf) {
child.prepareForChecking();
}
}
@Override
public String toString() {
return "TransportationObject [id=" + getGmlId() + "]";
}
@Override
public void clearMetaInformation() {
super.clearMetaInformation();
for (TransportationObject child : composesOf) {
child.clearMetaInformation();
}
}
@Override
public void prepareForChecking() {
super.prepareForChecking();
for (TransportationObject child : composesOf) {
child.prepareForChecking();
}
}
@Override
public void collectInstances(CopyHandler handler) {
super.collectInstances(handler);
for (TransportationObject to : composesOf) {
handler.addInstance(to);
}
}
@Override
public void clearMetaInformation() {
super.clearMetaInformation();
for (TransportationObject child : composesOf) {
child.clearMetaInformation();
}
}
@Override
public void collectInstances(CopyHandler handler) {
super.collectInstances(handler);
for (TransportationObject to : composesOf) {
handler.addInstance(to);
}
}
@Override
public void fillValues(Copyable original, CopyHandler handler) {
super.fillValues(original, handler);
TransportationObject originalTo = (TransportationObject) original;
for (TransportationObject to : originalTo.composesOf) {
composesOf.add(handler.getCopyInstance(to));
}
ato = originalTo.ato;
}
@Override
public void fillValues(Copyable original, CopyHandler handler) {
super.fillValues(original, handler);
TransportationObject originalTo = (TransportationObject) original;
for (TransportationObject to : originalTo.composesOf) {
composesOf.add(handler.getCopyInstance(to));
}
ato = originalTo.ato;
}
@Override
public Copyable createCopyInstance() {
return new TransportationObject(type);
}
@Override
public Copyable createCopyInstance() {
return new TransportationObject(type);
}
}
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.parser.ParserConfiguration;
import de.hft.stuttgart.citydoctor2.utils.CopyHandler;
import de.hft.stuttgart.citydoctor2.utils.Copyable;
import org.citygml4j.core.model.core.AbstractSpaceBoundaryProperty;
import org.citygml4j.core.model.tunnel.TunnelInstallation;
import org.citygml4j.core.model.tunnel.TunnelInstallationProperty;
import org.citygml4j.core.util.geometry.GeometryFactory;
import java.io.Serial;
import java.util.ArrayList;
import java.util.List;
public class Tunnel extends AbstractTunnel {
@Serial
private static final long serialVersionUID = 5316281216192555555L;
private List<TunnelPart> tunnelParts = new ArrayList<>();
public List<TunnelPart> getTunnelParts() {
return tunnelParts;
}
@Override
public void reCreateGeometries(GeometryFactory factory, ParserConfiguration config) {
super.reCreateGeometries(factory, config);
for (TunnelPart tp : tunnelParts) {
tp.reCreateGeometries(factory, config);
}
}
@Override
public void accept(Check c) {
super.accept(c);
if (c.canExecute(this)) {
c.check(this);
}
for (TunnelPart tp : tunnelParts) {
tp.accept(c);
}
}
@Override
public void clearAllContainedCheckResults() {
super.clearAllContainedCheckResults();
for (TunnelPart tp : tunnelParts) {
tp.clearAllContainedCheckResults();
}
}
@Override
public void collectContainedErrors(List<CheckError> errors) {
super.collectContainedErrors(errors);
for (TunnelPart tp : tunnelParts) {
tp.collectContainedErrors(errors);
}
}
@Override
public boolean containsAnyError() {
boolean hasError = super.containsAnyError();
if (hasError) {
return true;
}
for (TunnelPart tp : tunnelParts) {
if (tp.containsAnyError()) {
return true;
}
}
return false;
}
@Override
public boolean containsError(CheckId checkIdentifier) {
boolean hasError = super.containsError(checkIdentifier);
if (hasError) {
return true;
}
for (TunnelPart tp : tunnelParts) {
if (tp.containsError(checkIdentifier)) {
return true;
}
}
return false;
}
public void addTunnelPart(TunnelPart tunnelPart) {
tunnelParts.add(tunnelPart);
}
@Override
public String toString() {
return "Tunnel [id=" + getGmlId() + "]";
}
public void anonymize() {
for (Geometry geom : getGeometries()) {
geom.anonymize();
}
org.citygml4j.core.model.tunnel.Tunnel gmlT = new org.citygml4j.core.model.tunnel.Tunnel();
gmlT.setId(GmlId.generateId().getGmlString());
for (Installation ti : getTunnelInstallations()) {
ti.anonymize();
gmlT.getTunnelInstallations().add(new TunnelInstallationProperty((TunnelInstallation) ti.getGmlObject()));
}
for (BoundarySurface bs : getBoundarySurfaces()) {
bs.anonymize();
gmlT.addBoundary(new AbstractSpaceBoundaryProperty(bs.getGmlObject()));
}
setCityGmlBuilding(gmlT);
}
@Override
public void clearMetaInformation() {
super.clearMetaInformation();
for (TunnelPart tp : tunnelParts) {
tp.clearMetaInformation();
}
}
@Override
public void prepareForChecking() {
super.prepareForChecking();
for (TunnelPart tp : tunnelParts) {
tp.prepareForChecking();
}
}
@Override
public void fillValues(Copyable original, CopyHandler handler) {
super.fillValues(original, handler);
Tunnel originalTunnel = (Tunnel) original;
for (TunnelPart originalTp : originalTunnel.tunnelParts) {
tunnelParts.add(handler.getCopyInstance(originalTp));
}
}
@Override
public void collectInstances(CopyHandler handler) {
super.collectInstances(handler);
for (TunnelPart tp : tunnelParts) {
handler.addInstance(tp);
}
}
@Override
public Copyable createCopyInstance() {
return new Tunnel();
}
}
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.parser.ParserConfiguration;
import de.hft.stuttgart.citydoctor2.utils.CityGmlUtils;
import de.hft.stuttgart.citydoctor2.utils.CopyHandler;
import de.hft.stuttgart.citydoctor2.utils.Copyable;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.citygml4j.core.model.core.AbstractSpaceBoundaryProperty;
import org.citygml4j.core.util.geometry.GeometryFactory;
import org.xmlobjects.gml.model.geometry.aggregates.MultiSurface;
import org.xmlobjects.gml.model.geometry.aggregates.MultiSurfaceProperty;
import org.xmlobjects.gml.model.geometry.primitives.Solid;
import org.xmlobjects.gml.model.geometry.primitives.SolidProperty;
import java.io.Serial;
import java.util.ArrayList;
import java.util.List;
public class TunnelConstructiveElement extends CityObject {
private static final Logger logger = LogManager.getLogger(TunnelConstructiveElement.class);
private static final String CANNOT_ADD = "Cannot add ";
@Serial
private static final long serialVersionUID = 7353233899458901155L;
private final org.citygml4j.core.model.tunnel.TunnelConstructiveElement gmlTunnelElement;
private final List<BoundarySurface> boundarySurfaceList = new ArrayList<>();
public TunnelConstructiveElement(org.citygml4j.core.model.tunnel.TunnelConstructiveElement gmlObject) {
this.gmlTunnelElement = gmlObject;
}
@Override
public Copyable createCopyInstance() {
return new TunnelConstructiveElement(gmlTunnelElement);
}
@Override
public void reCreateGeometries(GeometryFactory factory, ParserConfiguration config) {
// only handles CityGML2 for now
// unknown which CityGML is handled here
// need context information to decide
for (Geometry geom : getGeometries()) {
if (geom instanceof ImplicitGeometryHolder) {
continue;
}
switch (geom.getType()) {
case SOLID:
Solid solid = CityGmlUtils.createSolid(geom, factory, config);
setSolidAccordingToLod(geom, solid);
break;
case MULTI_SURFACE:
MultiSurface ms = CityGmlUtils.createMultiSurface(geom, factory, config);
setMultiSurfaceAccordingToLod(geom, ms);
break;
}
}
for (BoundarySurface bs : boundarySurfaceList) {
reCreateBoundarySurface(factory, config, bs);
}
}
@Override
public void accept(Check c) {
super.accept(c);
if (c.canExecute(this)) {
c.check(this);
}
for (BoundarySurface bs : boundarySurfaceList) {
bs.accept(c);
}
}
@Override
public void collectContainedErrors(List<CheckError> errors) {
super.collectContainedErrors(errors);
for (BoundarySurface bs : boundarySurfaceList) {
bs.collectContainedErrors(errors);
}
}
@Override
public void clearAllContainedCheckResults() {
super.clearAllContainedCheckResults();
for (BoundarySurface bs : boundarySurfaceList) {
bs.clearAllContainedCheckResults();
}
}
@Override
public boolean containsError(CheckId checkIdentifier) {
boolean hasError = super.containsError(checkIdentifier);
if (hasError) {
return true;
}
for (BoundarySurface bs : boundarySurfaceList) {
if (bs.containsError(checkIdentifier)) {
return true;
}
}
return false;
}
@Override
public boolean containsAnyError() {
boolean hasError = super.containsAnyError();
if (hasError) {
return true;
}
for (BoundarySurface bs : boundarySurfaceList) {
if (bs.containsAnyError()) {
return true;
}
}
return false;
}
private void reCreateBoundarySurface(GeometryFactory factory, ParserConfiguration config, BoundarySurface bs) {
if (bs.getGeometries().isEmpty()) {
for (AbstractSpaceBoundaryProperty bsp : gmlTunnelElement.getBoundaries()) {
if (bsp.getObject() != null && bsp.getObject() == bs.getGmlObject()) {
logger.warn("Found empty boundary surface: {}, removing from TunnelConstructiveElement", bs.getGmlId());
gmlTunnelElement.getBoundaries().remove(bsp);
break;
}
}
return;
}
bs.reCreateGeometries(factory, config);
}
private void setSolidAccordingToLod(Geometry geom, Solid solid) {
switch (geom.getLod()) {
case LOD1:
gmlTunnelElement.setLod1Solid(new SolidProperty(solid));
break;
case LOD2:
gmlTunnelElement.setLod2Solid(new SolidProperty(solid));
break;
case LOD3:
gmlTunnelElement.setLod3Solid(new SolidProperty(solid));
break;
default:
throw new IllegalStateException(CANNOT_ADD + geom.getLod() + " solid to buildings");
}
}
private void setMultiSurfaceAccordingToLod(Geometry geom, MultiSurface ms) {
switch (geom.getLod()) {
case LOD0:
gmlTunnelElement.setLod0MultiSurface(new MultiSurfaceProperty(ms));
break;
case LOD2:
gmlTunnelElement.setLod2MultiSurface(new MultiSurfaceProperty(ms));
break;
case LOD3:
gmlTunnelElement.setLod3MultiSurface(new MultiSurfaceProperty(ms));
break;
default:
throw new IllegalStateException(CANNOT_ADD + geom.getLod() + " multi surface to buildings");
}
}
@Override
public org.citygml4j.core.model.tunnel.TunnelConstructiveElement getGmlObject() {
return gmlTunnelElement;
}
@Override
public void unsetGmlGeometries() {
gmlTunnelElement.setLod0MultiSurface(null);
gmlTunnelElement.setLod2MultiSurface(null);
gmlTunnelElement.setLod3MultiSurface(null);
gmlTunnelElement.setLod1Solid(null);
gmlTunnelElement.setLod2Solid(null);
gmlTunnelElement.setLod3Solid(null);
for (BoundarySurface bs : boundarySurfaceList) {
bs.unsetGmlGeometries();
}
}
@Override
public FeatureType getFeatureType() {
return FeatureType.TUNNEL_CONSTRUCTION_ELEMENT;
}
public void addBoundarySurface(BoundarySurface bs) {
boundarySurfaceList.add(bs);
bs.setParent(this);
}
public List<BoundarySurface> getBoundarySurfaces() {
return boundarySurfaceList;
}
@Override
public void prepareForChecking() {
super.prepareForChecking();
for (BoundarySurface bs : boundarySurfaceList) {
bs.prepareForChecking();
}
}
@Override
public void clearMetaInformation() {
super.clearMetaInformation();
for (BoundarySurface bs : boundarySurfaceList) {
bs.clearMetaInformation();
}
}
@Override
public void collectInstances(CopyHandler handler) {
super.collectInstances(handler);
handler.addInstance(boundarySurfaceList);
}
@Override
public void fillValues(Copyable original, CopyHandler handler) {
super.fillValues(original, handler);
TunnelConstructiveElement originalTce = (TunnelConstructiveElement) original;
for (BoundarySurface originalTs : originalTce.boundarySurfaceList) {
boundarySurfaceList.add(handler.getCopyInstance(originalTs));
}
}
}
package de.hft.stuttgart.citydoctor2.datastructure;
import de.hft.stuttgart.citydoctor2.utils.Copyable;
import java.io.Serial;
public class TunnelFurniture extends AbstractFurniture {
@Serial
private static final long serialVersionUID = -4667219019432204174L;
public void setGmlObject(org.citygml4j.core.model.tunnel.TunnelFurniture gmlObject) {
super.setGmlObject(gmlObject);
}
@Override
public Copyable createCopyInstance() {
return new BuildingRoomFurniture();
}
}
package de.hft.stuttgart.citydoctor2.datastructure;
import de.hft.stuttgart.citydoctor2.utils.CopyHandler;
import de.hft.stuttgart.citydoctor2.utils.Copyable;
import org.citygml4j.core.model.tunnel.TunnelFurnitureProperty;
import java.io.Serial;
import java.util.ArrayList;
import java.util.List;
public class TunnelHollow extends AbstractRoom {
@Serial
private static final long serialVersionUID = -276088332165299253L;
private final List<TunnelFurnitureProperty> furnitureRefs = new ArrayList<>(2);
private CityObject parent;
public void setGmlObject(org.citygml4j.core.model.tunnel.HollowSpace gmlHollowSpace) {
super.cgmlRoom = gmlHollowSpace;
}
public void setParent(CityObject parent) {
this.parent = parent;
}
public void addFurnitureRef(TunnelFurnitureProperty furnitureRef) {
furnitureRefs.add(furnitureRef);
}
public List<TunnelFurnitureProperty> getFurnitureRefs() {
return furnitureRefs;
}
public CityObject getParent() {
return parent;
}
@Override
public void fillValues(Copyable original, CopyHandler handler) {
super.fillValues(original, handler);
TunnelHollow oHollow = (TunnelHollow) original;
parent = handler.getCopyInstance(oHollow.getParent());
}
@Override
public void collectInstances(CopyHandler handler) {
super.collectInstances(handler);
handler.addInstance(parent);
}
@Override
public Copyable createCopyInstance() {
return new TunnelHollow();
}
}
package de.hft.stuttgart.citydoctor2.datastructure;
import de.hft.stuttgart.citydoctor2.utils.CopyHandler;
import de.hft.stuttgart.citydoctor2.utils.Copyable;
import java.io.Serial;
public class TunnelPart extends AbstractTunnel {
@Serial
private static final long serialVersionUID = 8200322261958679163L;
private Tunnel parent;
public TunnelPart(Tunnel parent) {
this.parent = parent;
parent.addTunnelPart(this);
}
public Tunnel getParent() {
return parent;
}
@Override
public FeatureType getFeatureType() {
return FeatureType.TUNNEL_PART;
}
@Override
public String toString() {
return "TunnelPart [id=" + getGmlId() + "]";
}
@Override
public void fillValues(Copyable original, CopyHandler handler) {
super.fillValues(original, handler);
TunnelPart originalPart = (TunnelPart) original;
parent = handler.getCopyInstance(originalPart.parent);
}
@Override
public void collectInstances(CopyHandler handler) {
super.collectInstances(handler);
handler.addInstance(parent);
}
@Override
public Copyable createCopyInstance() {
return new TunnelPart();
}
private TunnelPart() {
}
}
/*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
......@@ -18,9 +18,10 @@
*/
package de.hft.stuttgart.citydoctor2.datastructure;
import java.io.Serial;
import java.util.Collections;
import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;
import de.hft.stuttgart.citydoctor2.utils.CityGmlUtils;
import de.hft.stuttgart.citydoctor2.utils.Copyable;
import org.citygml4j.core.model.core.AbstractCityObject;
import org.citygml4j.core.model.vegetation.AbstractVegetationObject;
import org.citygml4j.core.model.vegetation.PlantCover;
......@@ -33,185 +34,185 @@ import org.xmlobjects.gml.model.geometry.aggregates.MultiSurfaceProperty;
import org.xmlobjects.gml.model.geometry.primitives.Solid;
import org.xmlobjects.gml.model.geometry.primitives.SolidProperty;
import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;
import de.hft.stuttgart.citydoctor2.utils.CityGmlUtils;
import de.hft.stuttgart.citydoctor2.utils.Copyable;
import java.io.Serial;
import java.util.Collections;
/**
* Representation of CityGML vegetation objects
*
* @author Matthias Betz
*
* @author Matthias Betz
*/
public class Vegetation extends CityObject {
@Serial
private static final long serialVersionUID = -5136358065541704146L;
public enum VegetationType {
SOLITARY_VEGETATION_OBJECT, PLANT_COVER
}
private AbstractVegetationObject citygmlVegetation;
private final VegetationType type;
public Vegetation(VegetationType type) {
this.type = type;
}
@Override
public FeatureType getFeatureType() {
return FeatureType.VEGETATION;
}
@Override
public void reCreateGeometries(GeometryFactory factory, ParserConfiguration config) {
for (Geometry geom : getGeometries()) {
if (geom.getType() == GeometryType.MULTI_SURFACE) {
MultiSurface ms = CityGmlUtils.createMultiSurface(geom, factory, config);
if (type == VegetationType.SOLITARY_VEGETATION_OBJECT) {
SolitaryVegetationObject svo = (SolitaryVegetationObject) citygmlVegetation;
setMultiSurfaceAccordingToLod(svo, ms, geom.getLod());
} else {
PlantCover pc = (PlantCover) citygmlVegetation;
setMultiSurfaceAccordingToLod(pc, ms, geom.getLod());
}
} else {
Solid solid = CityGmlUtils.createSolid(geom, factory, config);
if (type == VegetationType.SOLITARY_VEGETATION_OBJECT) {
SolitaryVegetationObject svo = (SolitaryVegetationObject) citygmlVegetation;
setSolidAccordingToLod(svo, solid, geom.getLod());
} else {
PlantCover pc = (PlantCover) citygmlVegetation;
setSolidAccordingToLod(pc, solid, geom.getLod());
}
}
}
}
private void setSolidAccordingToLod(PlantCover pc, Solid solid, Lod lod) {
switch (lod) {
case LOD1:
pc.getDeprecatedProperties().setLod1MultiSolid(new MultiSolidProperty(new MultiSolid(Collections.singletonList(new SolidProperty(solid)))));
break;
case LOD2:
pc.getDeprecatedProperties().setLod2MultiSolid(new MultiSolidProperty(new MultiSolid(Collections.singletonList(new SolidProperty(solid)))));
break;
case LOD3:
pc.getDeprecatedProperties().setLod3MultiSolid(new MultiSolidProperty(new MultiSolid(Collections.singletonList(new SolidProperty(solid)))));
break;
case LOD4:
pc.getDeprecatedProperties().setLod4MultiSolid(new MultiSolidProperty(new MultiSolid(Collections.singletonList(new SolidProperty(solid)))));
break;
default:
throw new IllegalStateException("Cannot set Solid with lod to PlantCover:" + lod);
}
}
private void setSolidAccordingToLod(SolitaryVegetationObject svo, Solid solid, Lod lod) {
switch (lod) {
case LOD1:
svo.getDeprecatedProperties().setLod1Geometry(new SolidProperty(solid));
break;
case LOD2:
svo.getDeprecatedProperties().setLod2Geometry(new SolidProperty(solid));
break;
case LOD3:
svo.getDeprecatedProperties().setLod3Geometry(new SolidProperty(solid));
break;
case LOD4:
svo.getDeprecatedProperties().setLod4Geometry(new SolidProperty(solid));
break;
default:
throw new IllegalStateException("Cannot set Solid with lod to SolitaryVegetationObject:" + lod);
}
}
private void setMultiSurfaceAccordingToLod(PlantCover pc, MultiSurface ms, Lod lod) {
switch (lod) {
case LOD1:
pc.getDeprecatedProperties().setLod1MultiSurface(new MultiSurfaceProperty(ms));
break;
case LOD2:
pc.setLod2MultiSurface(new MultiSurfaceProperty(ms));
break;
case LOD3:
pc.setLod3MultiSurface(new MultiSurfaceProperty(ms));
break;
case LOD4:
pc.getDeprecatedProperties().setLod4MultiSurface(new MultiSurfaceProperty(ms));
break;
default:
throw new IllegalStateException("Cannot set MultiSurface with lod to PlantCover:" + lod);
}
}
private void setMultiSurfaceAccordingToLod(SolitaryVegetationObject svo, MultiSurface ms, Lod lod) {
switch (lod) {
case LOD1:
svo.getDeprecatedProperties().setLod1Geometry(new MultiSurfaceProperty(ms));
break;
case LOD2:
svo.getDeprecatedProperties().setLod2Geometry(new MultiSurfaceProperty(ms));
break;
case LOD3:
svo.getDeprecatedProperties().setLod3Geometry(new MultiSurfaceProperty(ms));
break;
case LOD4:
svo.getDeprecatedProperties().setLod4Geometry(new MultiSurfaceProperty(ms));
break;
default:
throw new IllegalStateException("Cannot set MultiSurface with lod to SolitaryVegetationObject:" + lod);
}
}
@Override
public void accept(Check c) {
super.accept(c);
if (c.canExecute(this)) {
c.check(this);
}
}
@Override
public AbstractCityObject getGmlObject() {
return citygmlVegetation;
}
@Override
public void unsetGmlGeometries() {
if (type == VegetationType.SOLITARY_VEGETATION_OBJECT) {
SolitaryVegetationObject svo = (SolitaryVegetationObject) citygmlVegetation;
svo.getDeprecatedProperties().setLod1Geometry(null);
svo.getDeprecatedProperties().setLod2Geometry(null);
svo.getDeprecatedProperties().setLod3Geometry(null);
svo.getDeprecatedProperties().setLod4Geometry(null);
} else {
PlantCover pc = (PlantCover) citygmlVegetation;
pc.getDeprecatedProperties().setLod1MultiSurface(null);
pc.setLod2MultiSurface(null);
pc.setLod3MultiSurface(null);
pc.getDeprecatedProperties().setLod4MultiSurface(null);
}
}
public void setGmlObject(AbstractVegetationObject avo) {
citygmlVegetation = avo;
}
public VegetationType getVegetationType() {
return type;
}
@Override
public String toString() {
return "Vegetation [id=" + getGmlId() + "]";
}
@Override
public Copyable createCopyInstance() {
return new Vegetation(type);
}
@Serial
private static final long serialVersionUID = -5136358065541704146L;
public enum VegetationType {
SOLITARY_VEGETATION_OBJECT, PLANT_COVER
}
private AbstractVegetationObject citygmlVegetation;
private final VegetationType type;
public Vegetation(VegetationType type) {
this.type = type;
}
@Override
public FeatureType getFeatureType() {
return FeatureType.VEGETATION;
}
@Override
public void reCreateGeometries(GeometryFactory factory, ParserConfiguration config) {
for (Geometry geom : getGeometries()) {
if (geom instanceof ImplicitGeometryHolder) {
continue;
}
if (geom.getType() == GeometryType.MULTI_SURFACE) {
MultiSurface ms = CityGmlUtils.createMultiSurface(geom, factory, config);
if (type == VegetationType.SOLITARY_VEGETATION_OBJECT) {
SolitaryVegetationObject svo = (SolitaryVegetationObject) citygmlVegetation;
setMultiSurfaceAccordingToLod(svo, ms, geom.getLod());
} else {
PlantCover pc = (PlantCover) citygmlVegetation;
setMultiSurfaceAccordingToLod(pc, ms, geom.getLod());
}
} else {
Solid solid = CityGmlUtils.createSolid(geom, factory, config);
if (type == VegetationType.SOLITARY_VEGETATION_OBJECT) {
SolitaryVegetationObject svo = (SolitaryVegetationObject) citygmlVegetation;
setSolidAccordingToLod(svo, solid, geom.getLod());
} else {
PlantCover pc = (PlantCover) citygmlVegetation;
setSolidAccordingToLod(pc, solid, geom.getLod());
}
}
}
}
private void setSolidAccordingToLod(PlantCover pc, Solid solid, Lod lod) {
switch (lod) {
case LOD1:
pc.getDeprecatedProperties().setLod1MultiSolid(new MultiSolidProperty(new MultiSolid(Collections.singletonList(new SolidProperty(solid)))));
break;
case LOD2:
pc.getDeprecatedProperties().setLod2MultiSolid(new MultiSolidProperty(new MultiSolid(Collections.singletonList(new SolidProperty(solid)))));
break;
case LOD3:
pc.getDeprecatedProperties().setLod3MultiSolid(new MultiSolidProperty(new MultiSolid(Collections.singletonList(new SolidProperty(solid)))));
break;
case LOD4:
pc.getDeprecatedProperties().setLod4MultiSolid(new MultiSolidProperty(new MultiSolid(Collections.singletonList(new SolidProperty(solid)))));
break;
default:
throw new IllegalStateException("Cannot set Solid with lod to PlantCover:" + lod);
}
}
private void setSolidAccordingToLod(SolitaryVegetationObject svo, Solid solid, Lod lod) {
switch (lod) {
case LOD1:
svo.getDeprecatedProperties().setLod1Geometry(new SolidProperty(solid));
break;
case LOD2:
svo.getDeprecatedProperties().setLod2Geometry(new SolidProperty(solid));
break;
case LOD3:
svo.getDeprecatedProperties().setLod3Geometry(new SolidProperty(solid));
break;
case LOD4:
svo.getDeprecatedProperties().setLod4Geometry(new SolidProperty(solid));
break;
default:
throw new IllegalStateException("Cannot set Solid with lod to SolitaryVegetationObject:" + lod);
}
}
private void setMultiSurfaceAccordingToLod(PlantCover pc, MultiSurface ms, Lod lod) {
switch (lod) {
case LOD1:
pc.getDeprecatedProperties().setLod1MultiSurface(new MultiSurfaceProperty(ms));
break;
case LOD2:
pc.setLod2MultiSurface(new MultiSurfaceProperty(ms));
break;
case LOD3:
pc.setLod3MultiSurface(new MultiSurfaceProperty(ms));
break;
case LOD4:
pc.getDeprecatedProperties().setLod4MultiSurface(new MultiSurfaceProperty(ms));
break;
default:
throw new IllegalStateException("Cannot set MultiSurface with lod to PlantCover:" + lod);
}
}
private void setMultiSurfaceAccordingToLod(SolitaryVegetationObject svo, MultiSurface ms, Lod lod) {
switch (lod) {
case LOD1:
svo.getDeprecatedProperties().setLod1Geometry(new MultiSurfaceProperty(ms));
break;
case LOD2:
svo.getDeprecatedProperties().setLod2Geometry(new MultiSurfaceProperty(ms));
break;
case LOD3:
svo.getDeprecatedProperties().setLod3Geometry(new MultiSurfaceProperty(ms));
break;
case LOD4:
svo.getDeprecatedProperties().setLod4Geometry(new MultiSurfaceProperty(ms));
break;
default:
throw new IllegalStateException("Cannot set MultiSurface with lod to SolitaryVegetationObject:" + lod);
}
}
@Override
public void accept(Check c) {
super.accept(c);
if (c.canExecute(this)) {
c.check(this);
}
}
@Override
public AbstractCityObject getGmlObject() {
return citygmlVegetation;
}
@Override
public void unsetGmlGeometries() {
if (type == VegetationType.SOLITARY_VEGETATION_OBJECT) {
SolitaryVegetationObject svo = (SolitaryVegetationObject) citygmlVegetation;
svo.getDeprecatedProperties().setLod1Geometry(null);
svo.getDeprecatedProperties().setLod2Geometry(null);
svo.getDeprecatedProperties().setLod3Geometry(null);
svo.getDeprecatedProperties().setLod4Geometry(null);
} else {
PlantCover pc = (PlantCover) citygmlVegetation;
pc.getDeprecatedProperties().setLod1MultiSurface(null);
pc.setLod2MultiSurface(null);
pc.setLod3MultiSurface(null);
pc.getDeprecatedProperties().setLod4MultiSurface(null);
}
}
public void setGmlObject(AbstractVegetationObject avo) {
citygmlVegetation = avo;
}
public VegetationType getVegetationType() {
return type;
}
@Override
public String toString() {
return "Vegetation [id=" + getGmlId() + "]";
}
@Override
public Copyable createCopyInstance() {
return new Vegetation(type);
}
}
/*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
......@@ -18,155 +18,154 @@
*/
package de.hft.stuttgart.citydoctor2.datastructure;
import de.hft.stuttgart.citydoctor2.math.Vector3d;
import de.hft.stuttgart.citydoctor2.utils.CopyHandler;
import de.hft.stuttgart.citydoctor2.utils.Copyable;
import de.hft.stuttgart.citydoctor2.utils.SerializablePair;
import java.io.Serial;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import de.hft.stuttgart.citydoctor2.math.Vector3d;
import de.hft.stuttgart.citydoctor2.utils.CopyHandler;
import de.hft.stuttgart.citydoctor2.utils.Copyable;
import de.hft.stuttgart.citydoctor2.utils.SerializablePair;
/**
* Contains the vertex information of a point in a linear ring
*
* @author Matthias Betz
*
* @author Matthias Betz
*/
public class Vertex extends Vector3d implements Copyable {
@Serial
private static final long serialVersionUID = -5525361920397934892L;
private List<SerializablePair<Geometry, HashSet<LinearRing>>> adjacentRings = new ArrayList<>(2);
public Vertex(double x, double y, double z) {
super(x, y, z);
}
public Vertex(Vector3d vec) {
super(vec);
}
private Set<LinearRing> getAdjacentRingsWithoutNeighbor(Geometry geom) {
for (SerializablePair<Geometry, HashSet<LinearRing>> adjacency : adjacentRings) {
if (adjacency.getValue0() == geom) {
return adjacency.getValue1();
}
}
throw new IllegalStateException("Requested adjacent rings with Geometry not containing this vertex");
}
public Set<LinearRing> getAdjacentRings(Geometry geom) {
return getAdjacentRingsWithoutNeighbor(geom);
}
void addAdjacentRing(LinearRing ring, Geometry geom) {
findAdjacentRingsForGeometry(geom).add(ring);
}
private Set<LinearRing> findAdjacentRingsForGeometry(Geometry geom) {
HashSet<LinearRing> adjacendRingsSet = null;
for (SerializablePair<Geometry, HashSet<LinearRing>> adjacency : adjacentRings) {
if (adjacency.getValue0() == geom) {
adjacendRingsSet = adjacency.getValue1();
}
}
if (adjacendRingsSet == null) {
adjacendRingsSet = new HashSet<>(4);
adjacentRings.add(new SerializablePair<>(geom, adjacendRingsSet));
}
return adjacendRingsSet;
}
private Set<Polygon> getAdjacentPolygonsWithoutNeighbor(Geometry geom) {
for (SerializablePair<Geometry, HashSet<LinearRing>> adjacency : adjacentRings) {
if (adjacency.getValue0() == geom) {
Set<Polygon> polygons = new HashSet<>();
for (LinearRing lr : adjacency.getValue1()) {
polygons.add(lr.getParent());
}
return polygons;
}
}
throw new IllegalStateException("Requested adjacent polygons with Geometry not containing this vertex");
}
public Set<Polygon> getAdjacentPolygons(Geometry geom) {
return getAdjacentPolygonsWithoutNeighbor(geom);
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
return prime * result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!super.equals(obj)) {
return false;
}
return getClass() == obj.getClass();
}
@Override
public String toString() {
return "Vertex [x=" + getX() + ", y=" + getY() + ", z=" + getZ() + "]";
}
public void clearAdjacentRings(Geometry geometry) {
if (adjacentRings == null) {
return;
}
findAdjacentRingsForGeometry(geometry).clear();
}
void removeAdjacency(LinearRing lr, Geometry geom) {
findAdjacentRingsForGeometry(geom).remove(lr);
}
/**
* Remove all adjacent rings from this vertex, ignoring geometry association
*/
void clearAdjacentRings() {
adjacentRings = new ArrayList<>(2);
}
@Override
public void collectInstances(CopyHandler handler) {
for (SerializablePair<Geometry, HashSet<LinearRing>> pair : adjacentRings) {
handler.addInstance(pair.getValue0());
for (LinearRing lr : pair.getValue1()) {
handler.addInstance(lr);
}
}
}
@Override
public Copyable createCopyInstance() {
return new Vertex(this);
}
@Override
public void fillValues(Copyable original, CopyHandler handler) {
Vertex originalVertex = (Vertex) original;
// vertex point data already filled
for (SerializablePair<Geometry, HashSet<LinearRing>> pair : originalVertex.adjacentRings) {
Geometry geomCopy = handler.getCopyInstance(pair.getValue0());
HashSet<LinearRing> set = new HashSet<>();
for (LinearRing originalRing : pair.getValue1()) {
set.add(handler.getCopyInstance(originalRing));
}
SerializablePair<Geometry, HashSet<LinearRing>> copyPair = new SerializablePair<>(geomCopy, set);
adjacentRings.add(copyPair);
}
}
@Serial
private static final long serialVersionUID = -5525361920397934892L;
private List<SerializablePair<Geometry, HashSet<LinearRing>>> adjacentRings = new ArrayList<>(2);
public Vertex(double x, double y, double z) {
super(x, y, z);
}
public Vertex(Vector3d vec) {
super(vec);
}
private Set<LinearRing> getAdjacentRingsWithoutNeighbor(Geometry geom) {
for (SerializablePair<Geometry, HashSet<LinearRing>> adjacency : adjacentRings) {
if (adjacency.getValue0() == geom) {
return adjacency.getValue1();
}
}
throw new IllegalStateException("Requested adjacent rings with Geometry not containing this vertex");
}
public Set<LinearRing> getAdjacentRings(Geometry geom) {
return getAdjacentRingsWithoutNeighbor(geom);
}
void addAdjacentRing(LinearRing ring, Geometry geom) {
findAdjacentRingsForGeometry(geom).add(ring);
}
private Set<LinearRing> findAdjacentRingsForGeometry(Geometry geom) {
HashSet<LinearRing> adjacendRingsSet = null;
for (SerializablePair<Geometry, HashSet<LinearRing>> adjacency : adjacentRings) {
if (adjacency.getValue0() == geom) {
adjacendRingsSet = adjacency.getValue1();
}
}
if (adjacendRingsSet == null) {
adjacendRingsSet = new HashSet<>(4);
adjacentRings.add(new SerializablePair<>(geom, adjacendRingsSet));
}
return adjacendRingsSet;
}
private Set<Polygon> getAdjacentPolygonsWithoutNeighbor(Geometry geom) {
for (SerializablePair<Geometry, HashSet<LinearRing>> adjacency : adjacentRings) {
if (adjacency.getValue0() == geom) {
Set<Polygon> polygons = new HashSet<>();
for (LinearRing lr : adjacency.getValue1()) {
polygons.add(lr.getParent());
}
return polygons;
}
}
throw new IllegalStateException("Requested adjacent polygons with Geometry not containing this vertex");
}
public Set<Polygon> getAdjacentPolygons(Geometry geom) {
return getAdjacentPolygonsWithoutNeighbor(geom);
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
return prime * result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!super.equals(obj)) {
return false;
}
return getClass() == obj.getClass();
}
@Override
public String toString() {
return "Vertex [x=" + getX() + ", y=" + getY() + ", z=" + getZ() + "]";
}
public void clearAdjacentRings(Geometry geometry) {
if (adjacentRings == null) {
return;
}
findAdjacentRingsForGeometry(geometry).clear();
}
void removeAdjacency(LinearRing lr, Geometry geom) {
findAdjacentRingsForGeometry(geom).remove(lr);
}
/**
* Remove all adjacent rings from this vertex, ignoring geometry association
*/
void clearAdjacentRings() {
adjacentRings = new ArrayList<>(2);
}
@Override
public void collectInstances(CopyHandler handler) {
for (SerializablePair<Geometry, HashSet<LinearRing>> pair : adjacentRings) {
handler.addInstance(pair.getValue0());
for (LinearRing lr : pair.getValue1()) {
handler.addInstance(lr);
}
}
}
@Override
public Copyable createCopyInstance() {
return new Vertex(this);
}
@Override
public void fillValues(Copyable original, CopyHandler handler) {
Vertex originalVertex = (Vertex) original;
// vertex point data already filled
for (SerializablePair<Geometry, HashSet<LinearRing>> pair : originalVertex.adjacentRings) {
Geometry geomCopy = handler.getCopyInstance(pair.getValue0());
HashSet<LinearRing> set = new HashSet<>();
for (LinearRing originalRing : pair.getValue1()) {
set.add(handler.getCopyInstance(originalRing));
}
SerializablePair<Geometry, HashSet<LinearRing>> copyPair = new SerializablePair<>(geomCopy, set);
adjacentRings.add(copyPair);
}
}
}
/*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
......@@ -18,155 +18,153 @@
*/
package de.hft.stuttgart.citydoctor2.datastructure;
import java.io.Serial;
import java.util.ArrayList;
import java.util.List;
import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;
import de.hft.stuttgart.citydoctor2.utils.CityGmlUtils;
import de.hft.stuttgart.citydoctor2.utils.CopyHandler;
import de.hft.stuttgart.citydoctor2.utils.Copyable;
import org.citygml4j.core.model.core.AbstractCityObject;
import org.citygml4j.core.model.waterbody.WaterBody;
import org.citygml4j.core.util.geometry.GeometryFactory;
import org.xmlobjects.gml.model.geometry.aggregates.MultiSurface;
import org.xmlobjects.gml.model.geometry.aggregates.MultiSurfaceProperty;
import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;
import de.hft.stuttgart.citydoctor2.utils.CityGmlUtils;
import de.hft.stuttgart.citydoctor2.utils.CopyHandler;
import de.hft.stuttgart.citydoctor2.utils.Copyable;
import java.io.Serial;
import java.util.ArrayList;
import java.util.List;
/**
* Represents cityGML water body objects.
*
* @author Matthias Betz
*
* @author Matthias Betz
*/
public class WaterObject extends CityObject {
@Serial
private static final long serialVersionUID = -3821060595086337424L;
private WaterBody gmlWater;
private final List<BoundarySurface> boundarySurfaceList = new ArrayList<>();
@Override
public void reCreateGeometries(GeometryFactory factory, ParserConfiguration config) {
for (Geometry geom : getGeometries()) {
if (geom.getType() == GeometryType.MULTI_SURFACE) {
MultiSurface ms = CityGmlUtils.createMultiSurface(geom, factory, config);
if (geom.getLod() == Lod.LOD0) {
gmlWater.setLod0MultiSurface(new MultiSurfaceProperty(ms));
} else if (geom.getLod() == Lod.LOD1) {
gmlWater.getDeprecatedProperties().setLod1MultiSurface(new MultiSurfaceProperty(ms));
} else {
throw new IllegalStateException(
"Cannot add MultiSurface geometry with lod to WaterBody:" + geom.getLod());
}
} else {
throw new IllegalStateException("Cannot add Solid geometry to WaterBody");
}
}
}
/**
* Getter for all boundary surfaces contained in this building.
*
* @return the boundary surfaces
*/
public List<BoundarySurface> getBoundarySurfaces() {
return boundarySurfaceList;
}
public void addBoundarySurface(BoundarySurface bs) {
boundarySurfaceList.add(bs);
bs.setParent(this);
}
@Override
public FeatureType getFeatureType() {
return FeatureType.WATER;
}
@Override
public void accept(Check c) {
super.accept(c);
if (c.canExecute(this)) {
c.check(this);
}
for (BoundarySurface bs : boundarySurfaceList) {
bs.accept(c);
}
}
@Override
public AbstractCityObject getGmlObject() {
return gmlWater;
}
@Override
public void unsetGmlGeometries() {
gmlWater.setLod0MultiSurface(null);
gmlWater.getDeprecatedProperties().setLod1MultiSurface(null);
}
public void setGmlObject(WaterBody waterBody) {
gmlWater = waterBody;
}
@Override
public String toString() {
return "WaterObject [id=" + getGmlId() + "]";
}
@Override
public WaterObject createCopyInstance() {
return new WaterObject();
}
@Override
public void fillValues(Copyable original, CopyHandler handler) {
WaterObject wo = (WaterObject) original;
WaterObject originalWaterObject = (WaterObject) original;
for (BoundarySurface originalBs : originalWaterObject.boundarySurfaceList) {
boundarySurfaceList.add(handler.getCopyInstance(originalBs));
}
gmlWater = wo.gmlWater;
}
@Override
public boolean containsAnyError() {
boolean hasError = super.containsAnyError();
if (hasError) {
return true;
}
for (BoundarySurface bs : boundarySurfaceList) {
if (bs.containsAnyError()) {
return true;
}
}
return false;
}
@Override
public void collectInstances(CopyHandler handler) {
super.collectInstances(handler);
handler.addInstance(boundarySurfaceList);
}
@Override
public void clearMetaInformation() {
super.clearMetaInformation();
for (BoundarySurface bs : boundarySurfaceList) {
bs.clearMetaInformation();
}
}
@Override
public void prepareForChecking() {
super.prepareForChecking();
for (BoundarySurface bs : boundarySurfaceList) {
bs.prepareForChecking();
}
}
@Serial
private static final long serialVersionUID = -3821060595086337424L;
private WaterBody gmlWater;
private final List<BoundarySurface> boundarySurfaceList = new ArrayList<>();
@Override
public void reCreateGeometries(GeometryFactory factory, ParserConfiguration config) {
for (Geometry geom : getGeometries()) {
if (geom.getType() == GeometryType.MULTI_SURFACE) {
MultiSurface ms = CityGmlUtils.createMultiSurface(geom, factory, config);
if (geom.getLod() == Lod.LOD0) {
gmlWater.setLod0MultiSurface(new MultiSurfaceProperty(ms));
} else if (geom.getLod() == Lod.LOD1) {
gmlWater.getDeprecatedProperties().setLod1MultiSurface(new MultiSurfaceProperty(ms));
} else {
throw new IllegalStateException(
"Cannot add MultiSurface geometry with lod to WaterBody:" + geom.getLod());
}
} else {
throw new IllegalStateException("Cannot add Solid geometry to WaterBody");
}
}
}
/**
* Getter for all boundary surfaces contained in this building.
*
* @return the boundary surfaces
*/
public List<BoundarySurface> getBoundarySurfaces() {
return boundarySurfaceList;
}
public void addBoundarySurface(BoundarySurface bs) {
boundarySurfaceList.add(bs);
bs.setParent(this);
}
@Override
public FeatureType getFeatureType() {
return FeatureType.WATER;
}
@Override
public void accept(Check c) {
super.accept(c);
if (c.canExecute(this)) {
c.check(this);
}
for (BoundarySurface bs : boundarySurfaceList) {
bs.accept(c);
}
}
@Override
public AbstractCityObject getGmlObject() {
return gmlWater;
}
@Override
public void unsetGmlGeometries() {
gmlWater.setLod0MultiSurface(null);
gmlWater.getDeprecatedProperties().setLod1MultiSurface(null);
}
public void setGmlObject(WaterBody waterBody) {
gmlWater = waterBody;
}
@Override
public String toString() {
return "WaterObject [id=" + getGmlId() + "]";
}
@Override
public WaterObject createCopyInstance() {
return new WaterObject();
}
@Override
public void fillValues(Copyable original, CopyHandler handler) {
WaterObject wo = (WaterObject) original;
WaterObject originalWaterObject = (WaterObject) original;
for (BoundarySurface originalBs : originalWaterObject.boundarySurfaceList) {
boundarySurfaceList.add(handler.getCopyInstance(originalBs));
}
gmlWater = wo.gmlWater;
}
@Override
public boolean containsAnyError() {
boolean hasError = super.containsAnyError();
if (hasError) {
return true;
}
for (BoundarySurface bs : boundarySurfaceList) {
if (bs.containsAnyError()) {
return true;
}
}
return false;
}
@Override
public void collectInstances(CopyHandler handler) {
super.collectInstances(handler);
handler.addInstance(boundarySurfaceList);
}
@Override
public void clearMetaInformation() {
super.clearMetaInformation();
for (BoundarySurface bs : boundarySurfaceList) {
bs.clearMetaInformation();
}
}
@Override
public void prepareForChecking() {
super.prepareForChecking();
for (BoundarySurface bs : boundarySurfaceList) {
bs.prepareForChecking();
}
}
}
/*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
......@@ -18,48 +18,38 @@
*/
package de.hft.stuttgart.citydoctor2.mapper.citygml3;
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.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.BridgeObject.BridgeType;
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.TransportationObject.TransportationType;
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 org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.citygml4j.core.model.CityGMLVersion;
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.BuildingInstallationProperty;
import org.citygml4j.core.model.building.BuildingPartProperty;
import org.citygml4j.core.model.bridge.*;
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.AbstractCityObject;
import org.citygml4j.core.model.core.AbstractFeatureWithLifespan;
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.*;
import org.citygml4j.core.model.deprecated.transportation.TransportationComplex;
import org.citygml4j.core.model.landuse.LandUse;
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.Railway;
import org.citygml4j.core.model.transportation.Road;
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.*;
import org.citygml4j.core.model.tunnel.Tunnel;
import org.citygml4j.core.model.tunnel.*;
import org.citygml4j.core.model.vegetation.AbstractVegetationObject;
import org.citygml4j.core.model.vegetation.PlantCover;
import org.citygml4j.core.model.vegetation.SolitaryVegetationObject;
......@@ -71,727 +61,1198 @@ import org.xmlobjects.gml.model.geometry.AbstractGeometry;
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.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 org.xmlobjects.gml.model.geometry.complexes.CompositeSurface;
import org.xmlobjects.gml.model.geometry.primitives.*;
import de.hft.stuttgart.citydoctor2.datastructure.AbstractBuilding;
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.BridgeObject.BridgeType;
import de.hft.stuttgart.citydoctor2.datastructure.Building;
import de.hft.stuttgart.citydoctor2.datastructure.BuildingPart;
import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel;
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.GmlElement;
import de.hft.stuttgart.citydoctor2.datastructure.GmlId;
import de.hft.stuttgart.citydoctor2.datastructure.Installation;
import de.hft.stuttgart.citydoctor2.datastructure.LandObject;
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.TransportationObject;
import de.hft.stuttgart.citydoctor2.datastructure.TransportationObject.TransportationType;
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 java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Citygml3FeatureMapper extends ObjectWalker {
private static final Logger logger = LogManager.getLogger(Citygml3FeatureMapper.class);
private final CityDoctorModel model;
private Map<String, ConcretePolygon> polygonMap = new HashMap<>();
private List<ResolvableReference> references = new ArrayList<>();
private Map<Vertex, Vertex> vertexMap = new HashMap<>();
private final ParserConfiguration config;
private final double neighborDistance;
public Citygml3FeatureMapper(ParserConfiguration config, Path path) {
this.config = config;
model = new CityDoctorModel(config, path.toFile());
neighborDistance = 1.8d / Math.pow(10, config.getNumberOfRoundingPlaces());
}
@Override
public void visit(AbstractSpace space) {
// if we are here, an AbstractSpace thing was read that is not handled in the
// other methods
}
@Override
public void visit(org.citygml4j.core.model.building.Building gmlBuilding) {
Building cdBuilding = new Building();
readAbstractBuilding(gmlBuilding, cdBuilding);
for (BuildingPartProperty bpProp : gmlBuilding.getBuildingParts()) {
if (!bpProp.isSetObject()) {
continue;
}
BuildingPart part = new BuildingPart(cdBuilding);
readAbstractBuilding(bpProp.getObject(), part);
}
model.addBuilding(cdBuilding);
}
@Override
public void visit(WaterBody waterBody) {
WaterObject wo = new WaterObject();
wo.setGmlObject(waterBody);
mapAbstractOccupiedSpace(waterBody, wo);
parseAndAddMultiSurface(waterBody.getDeprecatedProperties().getLod1MultiSurface(), Lod.LOD1, wo);
parseAndAddSolid(waterBody.getDeprecatedProperties().getLod4Solid(), Lod.LOD4, wo);
SurfaceMapper surfaceMapper = new SurfaceMapper(polygonMap, references, vertexMap, config);
for (AbstractSpaceBoundaryProperty surfaceProp : waterBody.getBoundaries()) {
if (!surfaceProp.isSetObject()) {
continue;
}
AbstractSpaceBoundary surface = surfaceProp.getObject();
surface.accept(surfaceMapper);
}
for (BoundarySurface bs : surfaceMapper.getSurfaces()) {
wo.addBoundarySurface(bs);
}
resolveAndClearReferences();
wo.unsetGmlGeometries();
updateEdgesAndVertices(wo);
for (BoundarySurface bs : surfaceMapper.getSurfaces()) {
updateEdgesAndVertices(bs);
}
model.addWater(wo);
}
@Override
public void visit(LandUse landUse) {
LandObject lo = new LandObject(landUse);
mapAbstractThematicSurface(landUse, lo);
finishCityObjectConstruction(lo);
model.addLand(lo);
}
@Override
public void visit(PlantCover plantCover) {
Vegetation veg = new Vegetation(VegetationType.PLANT_COVER);
veg.setGmlObject(plantCover);
mapAbstractVegetationObject(plantCover, veg);
parseAndAddMultiSurface(plantCover.getDeprecatedProperties().getLod1MultiSurface(), Lod.LOD1, veg);
parseAndAddMultiSurface(plantCover.getDeprecatedProperties().getLod4MultiSurface(), Lod.LOD4, veg);
finishCityObjectConstruction(veg);
model.addVegetation(veg);
}
@Override
public void visit(SolitaryVegetationObject solitaryVegetationObject) {
Vegetation veg = new Vegetation(VegetationType.SOLITARY_VEGETATION_OBJECT);
veg.setGmlObject(solitaryVegetationObject);
mapAbstractVegetationObject(solitaryVegetationObject, veg);
parseAndAddAbstractGeometry(solitaryVegetationObject.getDeprecatedProperties().getLod1Geometry(), Lod.LOD1, veg);
parseAndAddAbstractGeometry(solitaryVegetationObject.getDeprecatedProperties().getLod2Geometry(), Lod.LOD2, veg);
parseAndAddAbstractGeometry(solitaryVegetationObject.getDeprecatedProperties().getLod3Geometry(), Lod.LOD3, veg);
parseAndAddAbstractGeometry(solitaryVegetationObject.getDeprecatedProperties().getLod4Geometry(), Lod.LOD4, veg);
finishCityObjectConstruction(veg);
model.addVegetation(veg);
}
private void mapAbstractVegetationObject(AbstractVegetationObject avo, Vegetation veg) {
mapAbstractOccupiedSpace(avo, veg);
}
private void mapAbstractOccupiedSpace(AbstractOccupiedSpace aos, CityObject co) {
mapAbstractPhysicalSpace(aos, co);
}
private void mapAbstractPhysicalSpace(AbstractPhysicalSpace aps, CityObject co) {
mapAbstractSpace(aps, co);
}
private void mapAbstractSpace(AbstractSpace as, CityObject co) {
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);
}
@Override
public void visit(Bridge bridge) {
BridgeObject bo = new BridgeObject(BridgeType.BRIDGE, bridge);
for (BridgePartProperty bPartProperty : bridge.getBridgeParts()) {
if (!bPartProperty.isSetObject()) {
continue;
}
BridgePart gmlBridgePart = bPartProperty.getObject();
BridgeObject bPart = new BridgeObject(BridgeType.BRIDGE_PART, gmlBridgePart);
mapAbstractBridge(gmlBridgePart, bPart);
bo.addBridgePart(bPart);
}
mapAbstractBridge(bridge, bo);
resolveAndClearReferences();
updateEdgesAndVertices(bo);
for (BridgeObject part : bo.getParts()) {
updateEdgesAndVertices(part);
}
for (BridgeConstructiveElement ele : bo.getConstructiveElements()) {
updateEdgesAndVertices(ele);
for (BoundarySurface bs : ele.getBoundarySurfaces()) {
updateEdgesAndVertices(bs);
}
}
for (Installation bi : bo.getBridgeInstallations()) {
updateEdgesAndVertices(bi);
for (BoundarySurface bs : bi.getBoundarySurfaces()) {
updateEdgesAndVertices(bs);
}
}
model.addBridge(bo);
}
private void mapAbstractBridge(AbstractBridge ab, BridgeObject bo) {
mapAbstractConstruction(ab, bo);
for (BridgeConstructiveElementProperty eleProp : ab.getBridgeConstructiveElements()) {
if (!eleProp.isSetObject()) {
continue;
}
org.citygml4j.core.model.bridge.BridgeConstructiveElement constructiveElement = eleProp.getObject();
BridgeConstructiveElement cdEle = new BridgeConstructiveElement(constructiveElement);
mapConstructiveElement(constructiveElement, cdEle);
bo.addConstructiveElement(cdEle);
}
List<BridgeInstallationProperty> bridgeInstallations = ab.getBridgeInstallations();
for (BridgeInstallationProperty installationProp : bridgeInstallations) {
var gmlBi = installationProp.getObject();
if (gmlBi == null) {
// ignore empty properties
continue;
}
Installation bi = mapBridgeInstallation(gmlBi);
bo.addBridgeInstallation(bi);
}
SurfaceMapper surfaceMapper = new SurfaceMapper(polygonMap, references, vertexMap, config);
for (AbstractSpaceBoundaryProperty surfaceProp : ab.getBoundaries()) {
if (!surfaceProp.isSetObject()) {
continue;
}
AbstractSpaceBoundary surface = surfaceProp.getObject();
surface.accept(surfaceMapper);
}
updatePartOfSurface(bo, surfaceMapper);
for (BoundarySurface bs : bo.getBoundarySurfaces()) {
updateEdgesAndVertices(bs);
}
bo.unsetGmlGeometries();
}
private Installation mapBridgeInstallation(BridgeInstallation gmlBi) {
Installation bi = new Installation();
bi.setGmlObject(gmlBi);
mapAbstractOccupiedSpace(gmlBi, bi);
GeometryProperty<?> lod2Prop = gmlBi.getDeprecatedProperties().getLod2Geometry();
parseAndAddAbstractGeometry(lod2Prop, Lod.LOD2, bi);
GeometryProperty<?> lod3Prop = gmlBi.getDeprecatedProperties().getLod3Geometry();
parseAndAddAbstractGeometry(lod3Prop, Lod.LOD3, bi);
GeometryProperty<?> lod4Prop = gmlBi.getDeprecatedProperties().getLod4Geometry();
parseAndAddAbstractGeometry(lod4Prop, Lod.LOD4, bi);
bi.unsetGmlGeometries();
SurfaceMapper surfaceMapper = new SurfaceMapper(polygonMap, references, vertexMap, config);
for (AbstractSpaceBoundaryProperty surfaceProp : gmlBi.getBoundaries()) {
if (!surfaceProp.isSetObject()) {
continue;
}
AbstractSpaceBoundary surface = surfaceProp.getObject();
surface.accept(surfaceMapper);
}
for (BoundarySurface bs : surfaceMapper.getSurfaces()) {
bi.addBoundarySurface(bs);
for (Geometry geom : bs.getGeometries()) {
for (Polygon p : geom.getPolygons()) {
p.setPartOfSurface(bs);
p.setPartOfInstallation(bi);
}
}
}
for (Geometry geom : bi.getGeometries()) {
for (Polygon p : geom.getPolygons()) {
p.setPartOfInstallation(bi);
}
}
return bi;
}
private void updatePartOfSurface(BridgeObject bo, SurfaceMapper surfaceMapper) {
for (BoundarySurface bs : surfaceMapper.getSurfaces()) {
bo.addBoundarySurface(bs);
for (Geometry geom : bs.getGeometries()) {
for (Polygon p : geom.getPolygons()) {
p.setPartOfSurface(bs);
}
}
}
}
private void mapConstructiveElement(org.citygml4j.core.model.bridge.BridgeConstructiveElement ele, BridgeConstructiveElement bce) {
mapAbstractConstructiveElement(ele, bce);
SurfaceMapper surfaceMapper = new SurfaceMapper(polygonMap, references, 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 void mapAbstractConstructiveElement(org.citygml4j.core.model.bridge.BridgeConstructiveElement ele, BridgeConstructiveElement bce) {
mapAbstractOccupiedSpace(ele, bce);
}
private void mapAbstractConstruction(AbstractConstruction ac, BridgeObject bo) {
mapAbstractOccupiedSpace(ac, bo);
}
@Override
public void visit(AuxiliaryTrafficArea ata) {
TransportationObject to = new TransportationObject(TransportationType.AUXILLIARY_TRAFFIC_AREA);
mapAbstractThematicSurface(ata, to);
finishTransportationMapping(to);
}
@Override
public void visit(TrafficArea ta) {
TransportationObject to = new TransportationObject(TransportationType.TRAFFIC_AREA);
mapAbstractThematicSurface(ta, to);
finishTransportationMapping(to);
}
@Override
public void visit(Road road) {
TransportationObject to = new TransportationObject(TransportationType.ROAD);
mapAbstractTransportationSpace(road, to);
finishTransportationMapping(to);
}
private void mapAbstractThematicSurface(AbstractThematicSurface ats, CityObject co) {
mapAbstractSpaceBoundary(ats, co);
parseAndAddMultiSurface(ats.getLod0MultiSurface(), Lod.LOD0, co);
parseAndAddMultiSurface(ats.getLod1MultiSurface(), Lod.LOD1, co);
parseAndAddMultiSurface(ats.getLod2MultiSurface(), Lod.LOD2, co);
parseAndAddMultiSurface(ats.getLod3MultiSurface(), Lod.LOD3, co);
parseAndAddMultiSurface(ats.getDeprecatedProperties().getLod4MultiSurface(), Lod.LOD4, co);
}
private void mapAbstractSpaceBoundary(AbstractSpaceBoundary asb, CityObject co) {
mapAbstractCityObject(asb, co);
}
private void mapAbstractCityObject(AbstractCityObject aco, CityObject to) {
mapAbstractFeatureWithLifespan(aco, to);
}
private void mapAbstractFeatureWithLifespan(AbstractFeatureWithLifespan afwl, CityObject to) {
mapAbstractFeature(afwl, to);
}
private void mapAbstractFeature(AbstractFeature af, CityObject to) {
mapAbstractGML(af, to);
}
private void mapAbstractGML(AbstractGML ag, CityObject to) {
parseId(ag, to);
}
@Override
public void visit(Railway railway) {
TransportationObject to = new TransportationObject(TransportationType.RAILWAY);
mapAbstractTransportationSpace(railway, to);
finishTransportationMapping(to);
}
@Override
public void visit(Square square) {
TransportationObject to = new TransportationObject(TransportationType.SQUARE);
mapAbstractTransportationSpace(square, to);
finishTransportationMapping(to);
}
@Override
public void visit(Track track) {
TransportationObject to = new TransportationObject(TransportationType.TRACK);
mapAbstractTransportationSpace(track, to);
finishTransportationMapping(to);
}
@Override
public void visit(TransportationComplex transportationComplex) {
TransportationObject to = new TransportationObject(TransportationType.TRANSPORTATION_COMPLEX);
mapAbstractTransportationSpace(transportationComplex, to);
finishTransportationMapping(to);
}
private void finishTransportationMapping(TransportationObject to) {
finishCityObjectConstruction(to);
model.addTransportation(to);
}
private void finishCityObjectConstruction(CityObject co) {
co.unsetGmlGeometries();
resolveAndClearReferences();
updateEdgesAndVertices(co);
}
private void mapAbstractTransportationSpace(AbstractTransportationSpace ats, TransportationObject to) {
to.setGmlObject(ats);
parseAbstractTransportationSpaceGeometries(ats, to);
for (TrafficSpaceProperty tsp : ats.getTrafficSpaces()) {
if (tsp.isSetObject()) {
TransportationObject trafficSpace = new TransportationObject(TransportationType.TRAFFIC_SPACE);
mapTrafficSpace(tsp.getObject(), trafficSpace);
finishTransportationMapping(trafficSpace);
to.getChildren().add(trafficSpace);
}
}
for (AuxiliaryTrafficSpaceProperty auxTrafficProp : ats.getAuxiliaryTrafficSpaces()) {
if (auxTrafficProp.isSetObject()) {
TransportationObject trafficSpace = parseAuxiliaryTrafficSpace(auxTrafficProp.getObject());
finishTransportationMapping(trafficSpace);
to.addChild(trafficSpace);
}
}
}
private void mapTrafficSpace(TrafficSpace ts, TransportationObject to) {
mapAbstractUnoccupiedSpace(ts, to);
}
private void mapAbstractUnoccupiedSpace(AbstractUnoccupiedSpace aus, TransportationObject to) {
mapAbstractPhysicalSpace(aus, to);
}
private TransportationObject parseAuxiliaryTrafficSpace(AuxiliaryTrafficSpace ats) {
TransportationObject to = new TransportationObject(TransportationType.AUXILLIARY_TRAFFIC_SPACE);
parseAbstractSpaceGeometries(ats, to);
finishCityObjectConstruction(to);
return to;
}
private void parseAbstractTransportationSpaceGeometries(AbstractTransportationSpace space, CityObject co) {
parseAndAddMultiSurface(space.getDeprecatedProperties().getLod1MultiSurface(), Lod.LOD1, co);
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;
}
Geometry geom = parseMultiSurface(msp.getObject(), lod);
co.addGeometry(geom);
}
private void parseAndAddSolid(SolidProperty sp, Lod lod, CityObject co) {
if (sp == null || sp.getObject() == null) {
return;
}
Geometry geom = parseSolid(sp.getObject(), lod);
if (geom != null) {
co.addGeometry(geom);
}
}
private void resolveAndClearReferences() {
for (ResolvableReference ref : references) {
String href = ref.href();
if (href.startsWith("#")) {
href = href.substring(1);
}
Geometry geom = ref.geometry();
ConcretePolygon concPoly = polygonMap.get(href);
if (concPoly == null) {
if (logger.isWarnEnabled()) {
logger.warn(Localization.getText("FeatureMapper.polygonUnreferenced"), href);
}
continue;
}
LinkedPolygon lPoly = new LinkedPolygon(concPoly, geom);
if (geom.getParent() instanceof BoundarySurface bs) {
lPoly.setPartOfSurface(bs);
if (bs.getParent() instanceof Installation bi) {
lPoly.setPartOfInstallation(bi);
}
}
geom.addPolygon(lPoly);
}
// clear storage for polygons and vertices
// probably faster than .clear() ?
references = new ArrayList<>();
vertexMap = new HashMap<>();
polygonMap = new HashMap<>();
}
private void readAbstractBuilding(org.citygml4j.core.model.building.AbstractBuilding gmlAb,
AbstractBuilding cdBuilding) {
mapAbstractOccupiedSpace(gmlAb, cdBuilding);
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);
for (BuildingInstallationProperty biProp : gmlAb.getBuildingInstallations()) {
var gmlBi = biProp.getObject();
if (gmlBi == null) {
// ignore empty properties
continue;
}
Installation bi = mapBuildingInstallation(gmlBi);
cdBuilding.addBuildingInstallation(bi);
}
SurfaceMapper surfaceMapper = new SurfaceMapper(polygonMap, references, vertexMap, config);
for (AbstractSpaceBoundaryProperty surfaceProp : gmlAb.getBoundaries()) {
if (!surfaceProp.isSetObject()) {
continue;
}
AbstractSpaceBoundary surface = surfaceProp.getObject();
surface.accept(surfaceMapper);
}
updatePartOfSurface(cdBuilding, surfaceMapper);
cdBuilding.unsetGmlGeometries();
resolveAndClearReferences();
updateEdgesAndVertices(cdBuilding);
for (BoundarySurface bs : surfaceMapper.getSurfaces()) {
updateEdgesAndVertices(bs);
for (Opening o : bs.getOpenings()) {
updateEdgesAndVertices(o);
}
}
for (Installation bi : cdBuilding.getBuildingInstallations()) {
updateEdgesAndVertices(bi);
for (BoundarySurface bs : bi.getBoundarySurfaces()) {
updateEdgesAndVertices(bs);
for (Opening o : bs.getOpenings()) {
updateEdgesAndVertices(o);
}
}
}
}
private void updatePartOfSurface(AbstractBuilding cdBuilding, SurfaceMapper surfaceMapper) {
for (BoundarySurface bs : surfaceMapper.getSurfaces()) {
cdBuilding.addBoundarySurface(bs);
for (Geometry geom : bs.getGeometries()) {
for (Polygon p : geom.getPolygons()) {
p.setPartOfSurface(bs);
}
}
}
}
public static void parseId(AbstractGML gml, GmlElement gmlElement) {
String id = gml.getId();
if (id != null) {
gmlElement.setGmlId(new GmlId(id));
}
}
private Installation mapBuildingInstallation(org.citygml4j.core.model.building.BuildingInstallation gmlBi) {
Installation bi = new Installation();
bi.setGmlObject(gmlBi);
mapAbstractOccupiedSpace(gmlBi, bi);
GeometryProperty<?> lod2Prop = gmlBi.getDeprecatedProperties().getLod2Geometry();
parseAndAddAbstractGeometry(lod2Prop, Lod.LOD2, bi);
GeometryProperty<?> lod3Prop = gmlBi.getDeprecatedProperties().getLod3Geometry();
parseAndAddAbstractGeometry(lod3Prop, Lod.LOD3, bi);
GeometryProperty<?> lod4Prop = gmlBi.getDeprecatedProperties().getLod4Geometry();
parseAndAddAbstractGeometry(lod4Prop, Lod.LOD4, bi);
bi.unsetGmlGeometries();
SurfaceMapper surfaceMapper = new SurfaceMapper(polygonMap, references, vertexMap, config);
for (AbstractSpaceBoundaryProperty surfaceProp : gmlBi.getBoundaries()) {
if (!surfaceProp.isSetObject()) {
continue;
}
AbstractSpaceBoundary surface = surfaceProp.getObject();
surface.accept(surfaceMapper);
}
for (BoundarySurface bs : surfaceMapper.getSurfaces()) {
bi.addBoundarySurface(bs);
for (Geometry geom : bs.getGeometries()) {
for (Polygon p : geom.getPolygons()) {
p.setPartOfSurface(bs);
p.setPartOfInstallation(bi);
}
}
}
for (Geometry geom : bi.getGeometries()) {
for (Polygon p : geom.getPolygons()) {
p.setPartOfInstallation(bi);
}
}
return bi;
}
private void parseAndAddAbstractGeometry(GeometryProperty<?> geomProp, Lod lod, CityObject co) {
if (geomProp == null || geomProp.getObject() == null) {
return;
}
AbstractGeometry abstractGeometry = geomProp.getObject();
if (abstractGeometry instanceof MultiSurface ms) {
Geometry geom = parseMultiSurface(ms, lod);
co.addGeometry(geom);
} else if (abstractGeometry instanceof Solid solid) {
Geometry geom = parseSolid(solid, lod);
if (geom != null) {
co.addGeometry(geom);
}
} else {
logger.warn("Cannot handle geometry type {}, ignoring", abstractGeometry.getClass().getSimpleName());
}
}
private Geometry parseSolid(AbstractSolid abstractSolid, Lod lod) {
if (abstractSolid instanceof Solid s) {
return handleSolidGeometry(s, lod);
} else {
logger.warn("Cannot handle solid class {}, can only process pure solids",
abstractSolid.getClass().getSimpleName());
return null;
}
}
private Geometry handleSolidGeometry(Solid solid, Lod lod) {
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);
Shell exterior = solid.getExterior().getObject();
Citygml3GeometryMapper geometryMapper = new Citygml3GeometryMapper(config, vertexMap);
readSurfaceMember(geom, geometryMapper, exterior.getSurfaceMembers());
return geom;
}
private Geometry parseMultiSurface(MultiSurface ms, Lod lod) {
Geometry geom = new Geometry(GeometryType.MULTI_SURFACE, lod);
Citygml3GeometryMapper geometryMapper = new Citygml3GeometryMapper(config, vertexMap);
readSurfaceMember(geom, geometryMapper, ms.getSurfaceMember());
return geom;
}
private void readSurfaceMember(Geometry geom, Citygml3GeometryMapper geometryMapper,
List<SurfaceProperty> surfaceMember) {
for (SurfaceProperty prop : surfaceMember) {
if (prop.getHref() != null) {
references.add(new ResolvableReference(prop.getHref(), geom));
continue;
}
if (prop.getObject() != null) {
AbstractSurface as = prop.getObject();
as.accept(geometryMapper);
}
}
List<ConcretePolygon> polygons = geometryMapper.getPolygons();
for (ConcretePolygon concretePoly : polygons) {
geom.addPolygon(concretePoly);
if (concretePoly.hasExistingGmlId()) {
polygonMap.put(concretePoly.getGmlId().getGmlString(), concretePoly);
}
}
}
private void updateEdgesAndVertices(CityObject co) {
// searching for neighboring vertices, replacing them with one single vertex to
// avoid later problems with edges and manifold problems
for (Geometry geom : co.getGeometries()) {
KDTree tree = new KDTree();
for (Polygon poly : geom.getPolygons()) {
LinearRing lr = poly.getExteriorRing();
updateRing(tree, lr);
for (LinearRing innerRing : poly.getInnerRings()) {
updateRing(tree, innerRing);
}
}
if (!config.useLowMemoryConsumption()) {
// no low memory consumption mode meaning create all meta information in
// geometry
geom.updateEdgesAndVertices();
}
}
}
private void updateRing(KDTree tree, LinearRing lr) {
for (int i = 0; i < lr.getVertices().size(); i++) {
Vertex v = lr.getVertices().get(i);
List<Vertex> nodesInRange = tree.getNodesInRange(v, neighborDistance);
if (nodesInRange.isEmpty()) {
tree.add(v);
} else {
// replace other vertex with any neighboring one
Vertex original = nodesInRange.get(0);
lr.setVertex(i, original);
}
}
}
public void setCityModel(CityModel cModel) {
model.setCityModel(cModel);
}
public CityDoctorModel getModel() {
return model;
}
public void setCityGMLVersion(CityGMLVersion cityGMLVersion) {
model.setParsedCityGMLVersion(cityGMLVersion);
}
private static final Logger logger = LogManager.getLogger(Citygml3FeatureMapper.class);
private final CityDoctorModel model;
private final ParserConfiguration config;
private final Path directory;
private final double neighborDistance;
private Map<String, ConcretePolygon> polygonMap = new HashMap<>();
private Map<String, CompositeCollection> compositeMap = new HashMap<>();
private List<ResolvableReference> references = new ArrayList<>();
private Map<Vertex, Vertex> vertexMap = new HashMap<>();
public Citygml3FeatureMapper(ParserConfiguration config, Path path) {
this.config = config;
this.directory = path.getParent();
model = new CityDoctorModel(config, path.toFile());
neighborDistance = 1.8d / Math.pow(10, config.getNumberOfRoundingPlaces());
}
public static void parseId(AbstractGML gml, GmlElement gmlElement) {
String id = gml.getId();
if (id != null) {
gmlElement.setGmlId(new GmlId(id));
}
}
@Override
public void visit(AbstractSpace space) {
// if we are here, an AbstractSpace thing was read that is not handled in the
// other methods
}
@Override
public void visit(org.citygml4j.core.model.cityfurniture.CityFurniture gmlCityFurniture) {
CityFurniture cf = new CityFurniture();
cf.setGmlObject(gmlCityFurniture);
mapAbstractOccupiedSpace(gmlCityFurniture, cf);
resolveAndClearReferences();
cf.unsetGmlGeometries();
updateEdgesAndVertices(cf);
model.addCityFurniture(cf);
}
@Override
public void visit(org.citygml4j.core.model.generics.GenericOccupiedSpace gos) {
GenericCityObject gco = new GenericCityObject();
gco.setGmlObject(gos);
GeometryProperty<?> agLod1 = gos.getDeprecatedProperties().getLod1Geometry();
GeometryProperty<?> agLod4 = gos.getDeprecatedProperties().getLod4Geometry();
if (agLod1 != null && agLod1.getObject() != null &&
agLod1.getObject() instanceof MultiSurface ms) {
gco.addGeometry(parseMultiSurface(ms, Lod.LOD1));
}
if (agLod4 != null && agLod4.getObject() != null) {
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));
}
}
mapAbstractOccupiedSpace(gos, gco);
resolveAndClearReferences();
gco.unsetGmlGeometries();
updateEdgesAndVertices(gco);
model.addGenericCityObject(gco);
}
@Override
public void visit(org.citygml4j.core.model.building.Building gmlBuilding) {
Building cdBuilding = new Building();
readAbstractBuilding(gmlBuilding, cdBuilding);
for (BuildingPartProperty bpProp : gmlBuilding.getBuildingParts()) {
if (!bpProp.isSetObject()) {
continue;
}
BuildingPart part = new BuildingPart(cdBuilding);
readAbstractBuilding(bpProp.getObject(), part);
}
model.addBuilding(cdBuilding);
}
@Override
public void visit(WaterBody waterBody) {
WaterObject wo = new WaterObject();
wo.setGmlObject(waterBody);
mapAbstractOccupiedSpace(waterBody, wo);
parseAndAddMultiSurface(waterBody.getDeprecatedProperties().getLod1MultiSurface(), Lod.LOD1, wo);
parseAndAddSolid(waterBody.getDeprecatedProperties().getLod4Solid(), Lod.LOD4, wo);
SurfaceMapper surfaceMapper = new SurfaceMapper(polygonMap, references, compositeMap, vertexMap, config);
for (AbstractSpaceBoundaryProperty surfaceProp : waterBody.getBoundaries()) {
if (!surfaceProp.isSetObject()) {
continue;
}
AbstractSpaceBoundary surface = surfaceProp.getObject();
surface.accept(surfaceMapper);
}
for (BoundarySurface bs : surfaceMapper.getSurfaces()) {
wo.addBoundarySurface(bs);
}
resolveAndClearReferences();
wo.unsetGmlGeometries();
updateEdgesAndVertices(wo);
for (BoundarySurface bs : surfaceMapper.getSurfaces()) {
updateEdgesAndVertices(bs);
}
model.addWater(wo);
}
@Override
public void visit(LandUse landUse) {
LandObject lo = new LandObject(landUse);
mapAbstractThematicSurface(landUse, lo);
finishCityObjectConstruction(lo);
model.addLand(lo);
}
@Override
public void visit(PlantCover plantCover) {
Vegetation veg = new Vegetation(VegetationType.PLANT_COVER);
veg.setGmlObject(plantCover);
mapAbstractVegetationObject(plantCover, veg);
parseAndAddMultiSurface(plantCover.getDeprecatedProperties().getLod1MultiSurface(), Lod.LOD1, veg);
parseAndAddMultiSurface(plantCover.getDeprecatedProperties().getLod4MultiSurface(), Lod.LOD4, veg);
finishCityObjectConstruction(veg);
model.addVegetation(veg);
}
@Override
public void visit(SolitaryVegetationObject solitaryVegetationObject) {
Vegetation veg = new Vegetation(VegetationType.SOLITARY_VEGETATION_OBJECT);
veg.setGmlObject(solitaryVegetationObject);
mapAbstractVegetationObject(solitaryVegetationObject, veg);
parseAndAddAbstractGeometry(solitaryVegetationObject.getDeprecatedProperties().getLod1Geometry(), Lod.LOD1, veg);
parseAndAddAbstractGeometry(solitaryVegetationObject.getDeprecatedProperties().getLod2Geometry(), Lod.LOD2, veg);
parseAndAddAbstractGeometry(solitaryVegetationObject.getDeprecatedProperties().getLod3Geometry(), Lod.LOD3, veg);
parseAndAddAbstractGeometry(solitaryVegetationObject.getDeprecatedProperties().getLod4Geometry(), Lod.LOD4, veg);
finishCityObjectConstruction(veg);
model.addVegetation(veg);
}
private void mapAbstractVegetationObject(AbstractVegetationObject avo, Vegetation veg) {
mapAbstractOccupiedSpace(avo, veg);
}
private void mapAbstractOccupiedSpace(AbstractOccupiedSpace aos, CityObject co) {
mapAbstractPhysicalSpace(aos, co);
parseImplicitGeometry(aos, co);
}
private void mapAbstractPhysicalSpace(AbstractPhysicalSpace aps, CityObject co) {
mapAbstractSpace(aps, co);
}
private void mapAbstractSpace(AbstractSpace as, CityObject co) {
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);
parseAndAddGenericAttributes(as, co);
}
private void parseAndAddGenericAttributes(AbstractSpace as, CityObject co) {
for (AbstractGenericAttributeProperty aga : as.getGenericAttributes()) {
co.addGenericAttribute(new GenericAttribute(aga));
}
}
@Override
public void visit(Bridge bridge) {
BridgeObject bo = new BridgeObject(BridgeType.BRIDGE, bridge);
// parse deprecated geometries
parseAndAddMultiSurface(bridge.getDeprecatedProperties().getLod1MultiSurface(), Lod.LOD1, bo);
parseAndAddMultiSurface(bridge.getDeprecatedProperties().getLod4MultiSurface(), Lod.LOD4, bo);
parseAndAddSolid(bridge.getDeprecatedProperties().getLod4Solid(), Lod.LOD4, bo);
mapAbstractBridge(bridge, bo);
for (BridgePartProperty bPartProperty : bridge.getBridgeParts()) {
if (!bPartProperty.isSetObject()) {
continue;
}
BridgePart gmlBridgePart = bPartProperty.getObject();
BridgeObject bPart = new BridgeObject(BridgeType.BRIDGE_PART, gmlBridgePart);
mapAbstractBridge(gmlBridgePart, bPart);
bo.addBridgePart(bPart);
}
resolveAndClearReferences();
updateEdgesAndVertices(bo);
for (BridgeObject part : bo.getParts()) {
updateEdgesAndVertices(part);
}
for (BridgeConstructiveElement ele : bo.getConstructiveElements()) {
updateEdgesAndVertices(ele);
for (BoundarySurface bs : ele.getBoundarySurfaces()) {
updateEdgesAndVertices(bs);
}
}
for (Installation bi : bo.getBridgeInstallations()) {
updateEdgesAndVertices(bi);
for (BoundarySurface bs : bi.getBoundarySurfaces()) {
updateEdgesAndVertices(bs);
}
}
model.addBridge(bo);
}
private void mapAbstractBridge(AbstractBridge ab, BridgeObject bo) {
mapAbstractConstruction(ab, bo);
for (BridgeConstructiveElementProperty eleProp : ab.getBridgeConstructiveElements()) {
if (!eleProp.isSetObject()) {
continue;
}
org.citygml4j.core.model.bridge.BridgeConstructiveElement constructiveElement = eleProp.getObject();
BridgeConstructiveElement cdEle = new BridgeConstructiveElement(constructiveElement);
mapConstructiveElement(constructiveElement, cdEle);
bo.addConstructiveElement(cdEle);
}
List<BridgeInstallationProperty> bridgeInstallations = ab.getBridgeInstallations();
for (BridgeInstallationProperty installationProp : bridgeInstallations) {
var gmlBi = installationProp.getObject();
if (gmlBi == null) {
// ignore empty properties
continue;
}
Installation bi = mapBridgeInstallation(gmlBi);
bo.addBridgeInstallation(bi);
}
SurfaceMapper surfaceMapper = new SurfaceMapper(polygonMap, references, compositeMap, vertexMap, config);
for (AbstractSpaceBoundaryProperty surfaceProp : ab.getBoundaries()) {
if (!surfaceProp.isSetObject()) {
continue;
}
AbstractSpaceBoundary surface = surfaceProp.getObject();
surface.accept(surfaceMapper);
}
updatePartOfSurface(bo, surfaceMapper);
for (BoundarySurface bs : bo.getBoundarySurfaces()) {
updateEdgesAndVertices(bs);
}
bo.unsetGmlGeometries();
}
private Installation mapBridgeInstallation(BridgeInstallation gmlBi) {
Installation bi = new Installation();
bi.setGmlObject(gmlBi);
mapAbstractOccupiedSpace(gmlBi, bi);
GeometryProperty<?> lod2Prop = gmlBi.getDeprecatedProperties().getLod2Geometry();
parseAndAddAbstractGeometry(lod2Prop, Lod.LOD2, bi);
GeometryProperty<?> lod3Prop = gmlBi.getDeprecatedProperties().getLod3Geometry();
parseAndAddAbstractGeometry(lod3Prop, Lod.LOD3, bi);
GeometryProperty<?> lod4Prop = gmlBi.getDeprecatedProperties().getLod4Geometry();
parseAndAddAbstractGeometry(lod4Prop, Lod.LOD4, bi);
bi.unsetGmlGeometries();
SurfaceMapper surfaceMapper = new SurfaceMapper(polygonMap, references, compositeMap, vertexMap, config);
for (AbstractSpaceBoundaryProperty surfaceProp : gmlBi.getBoundaries()) {
if (!surfaceProp.isSetObject()) {
continue;
}
AbstractSpaceBoundary surface = surfaceProp.getObject();
surface.accept(surfaceMapper);
}
for (BoundarySurface bs : surfaceMapper.getSurfaces()) {
bi.addBoundarySurface(bs);
for (Geometry geom : bs.getGeometries()) {
for (Polygon p : geom.getPolygons()) {
p.setPartOfSurface(bs);
p.setPartOfInstallation(bi);
}
}
}
for (Geometry geom : bi.getGeometries()) {
for (Polygon p : geom.getPolygons()) {
p.setPartOfInstallation(bi);
}
}
return bi;
}
@Override
public void visit(Tunnel tunnel) {
de.hft.stuttgart.citydoctor2.datastructure.Tunnel tu = new de.hft.stuttgart.citydoctor2.datastructure.Tunnel();
for (TunnelPartProperty tPartProperty : tunnel.getTunnelParts()) {
if (!tPartProperty.isSetObject()) {
continue;
}
org.citygml4j.core.model.tunnel.TunnelPart gmlTunnelPart = tPartProperty.getObject();
TunnelPart tPart = new TunnelPart(tu);
readAbstractTunnel(gmlTunnelPart, tPart);
tu.addTunnelPart(tPart);
}
readAbstractTunnel(tunnel, tu);
resolveAndClearReferences();
updateEdgesAndVertices(tu);
for (TunnelPart part : tu.getTunnelParts()) {
updateEdgesAndVertices(part);
}
model.addTunnel(tu);
}
private void readAbstractTunnel(org.citygml4j.core.model.tunnel.AbstractTunnel gmlTunnel, AbstractTunnel cdTunnel) {
mapAbstractOccupiedSpace(gmlTunnel, cdTunnel);
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);
for (TunnelInstallationProperty tiProp : gmlTunnel.getTunnelInstallations()) {
var gmlTi = tiProp.getObject();
if (gmlTi == null) {
// ignore empty properties
continue;
}
Installation ti = mapTunnelInstallation(gmlTi);
cdTunnel.addTunnelInstallation(ti);
}
for (HollowSpaceProperty thProp : gmlTunnel.getHollowSpaces()) {
var gmlTh = thProp.getObject();
if (gmlTh == null) {
continue;
}
TunnelHollow br = mapTunnelHollow(gmlTh);
cdTunnel.addTunnelHollow(br);
}
for (Installation ti : cdTunnel.getTunnelInstallations()) {
updateEdgesAndVertices(ti);
for (BoundarySurface bs : ti.getBoundarySurfaces()) {
updateEdgesAndVertices(bs);
for (Opening o : bs.getOpenings()) {
updateEdgesAndVertices(o);
}
}
}
for (TunnelFurnitureProperty tfProp : gmlTunnel.getTunnelFurniture()) {
var gmlTf = tfProp.getObject();
if (gmlTf == null) {
continue;
}
TunnelFurniture tf = mapTunnelFurniture(gmlTf);
cdTunnel.addTunnelFurniture(tf);
}
for (TunnelConstructiveElementProperty teProp : gmlTunnel.getTunnelConstructiveElements()) {
var gmlTc = teProp.getObject();
if (gmlTc == null) {
continue;
}
TunnelConstructiveElement tc = mapTunnelConstructiveElement(gmlTc);
cdTunnel.addTunnelConstructiveElement(tc);
}
SurfaceMapper surfaceMapper = new SurfaceMapper(polygonMap, references, compositeMap, vertexMap, config);
for (AbstractSpaceBoundaryProperty surfaceProp : gmlTunnel.getBoundaries()) {
if (!surfaceProp.isSetObject()) {
continue;
}
AbstractSpaceBoundary surface = surfaceProp.getObject();
surface.accept(surfaceMapper);
}
for (BoundarySurface bs : surfaceMapper.getSurfaces()) {
updateEdgesAndVertices(bs);
for (Opening o : bs.getOpenings()) {
updateEdgesAndVertices(o);
}
}
cdTunnel.unsetGmlGeometries();
resolveAndClearReferences();
updateEdgesAndVertices(cdTunnel);
}
private Installation mapTunnelInstallation(TunnelInstallation gmlTi) {
Installation ti = new Installation();
ti.setGmlObject(gmlTi);
mapAbstractOccupiedSpace(gmlTi, ti);
GeometryProperty<?> lod2Prop = gmlTi.getDeprecatedProperties().getLod2Geometry();
parseAndAddAbstractGeometry(lod2Prop, Lod.LOD2, ti);
GeometryProperty<?> lod3Prop = gmlTi.getDeprecatedProperties().getLod3Geometry();
parseAndAddAbstractGeometry(lod3Prop, Lod.LOD3, ti);
GeometryProperty<?> lod4Prop = gmlTi.getDeprecatedProperties().getLod4Geometry();
parseAndAddAbstractGeometry(lod4Prop, Lod.LOD4, ti);
ti.unsetGmlGeometries();
SurfaceMapper surfaceMapper = new SurfaceMapper(polygonMap, references, compositeMap, vertexMap, config);
for (AbstractSpaceBoundaryProperty surfaceProp : gmlTi.getBoundaries()) {
if (!surfaceProp.isSetObject()) {
continue;
}
AbstractSpaceBoundary surface = surfaceProp.getObject();
surface.accept(surfaceMapper);
}
for (BoundarySurface bs : surfaceMapper.getSurfaces()) {
ti.addBoundarySurface(bs);
for (Geometry geom : bs.getGeometries()) {
for (Polygon p : geom.getPolygons()) {
p.setPartOfSurface(bs);
p.setPartOfInstallation(ti);
}
}
}
for (Geometry geom : ti.getGeometries()) {
for (Polygon p : geom.getPolygons()) {
p.setPartOfInstallation(ti);
}
}
return ti;
}
private TunnelHollow mapTunnelHollow(HollowSpace gmlHo) {
TunnelHollow tHollow = new TunnelHollow();
tHollow.setGmlObject(gmlHo);
mapAbstractUnoccupiedSpace(gmlHo, tHollow);
SurfaceMapper surfaceMapper = new SurfaceMapper(polygonMap, references, compositeMap, vertexMap, config);
for (AbstractSpaceBoundaryProperty surfaceProp : gmlHo.getBoundaries()) {
if (!surfaceProp.isSetObject()) {
continue;
}
AbstractSpaceBoundary surface = surfaceProp.getObject();
surface.accept(surfaceMapper);
}
for (BoundarySurface bs : surfaceMapper.getSurfaces()) {
tHollow.addBoundarySurface(bs);
for (Geometry geom : bs.getGeometries()) {
for (Polygon p : geom.getPolygons()) {
p.setPartOfSurface(bs);
}
}
}
for (TunnelInstallationProperty tiProp : gmlHo.getTunnelInstallations()) {
var gmlTi = tiProp.getObject();
if (gmlTi == null) {
// ignore empty properties
continue;
}
Installation bi = mapTunnelInstallation(gmlTi);
tHollow.addRoomInstallation(bi);
}
for (TunnelFurnitureProperty tfProp : gmlHo.getTunnelFurniture()) {
var gmlHref = tfProp.getHref();
if (gmlHref == null) {
continue;
}
tHollow.addFurnitureRef(tfProp);
}
return tHollow;
}
private TunnelFurniture mapTunnelFurniture(org.citygml4j.core.model.tunnel.TunnelFurniture gmlTf) {
TunnelFurniture tf = new TunnelFurniture();
tf.setGmlObject(gmlTf);
mapAbstractOccupiedSpace(gmlTf, tf);
tf.unsetGmlGeometries();
SurfaceMapper surfaceMapper = new SurfaceMapper(polygonMap, references, compositeMap, vertexMap, config);
for (AbstractSpaceBoundaryProperty surfaceProp : gmlTf.getBoundaries()) {
if (!surfaceProp.isSetObject()) {
continue;
}
AbstractSpaceBoundary surface = surfaceProp.getObject();
surface.accept(surfaceMapper);
}
for (BoundarySurface bs : surfaceMapper.getSurfaces()) {
tf.addBoundarySurface(bs);
for (Geometry geom : bs.getGeometries()) {
for (Polygon p : geom.getPolygons()) {
p.setPartOfSurface(bs);
}
}
}
return tf;
}
private TunnelConstructiveElement mapTunnelConstructiveElement(org.citygml4j.core.model.tunnel.TunnelConstructiveElement gmlTe) {
TunnelConstructiveElement te = new TunnelConstructiveElement(gmlTe);
mapAbstractOccupiedSpace(gmlTe, te);
te.unsetGmlGeometries();
SurfaceMapper surfaceMapper = new SurfaceMapper(polygonMap, references, compositeMap, vertexMap, config);
for (AbstractSpaceBoundaryProperty surfaceProp : gmlTe.getBoundaries()) {
if (!surfaceProp.isSetObject()) {
continue;
}
AbstractSpaceBoundary surface = surfaceProp.getObject();
surface.accept(surfaceMapper);
}
for (BoundarySurface bs : surfaceMapper.getSurfaces()) {
te.addBoundarySurface(bs);
for (Geometry geom : bs.getGeometries()) {
for (Polygon p : geom.getPolygons()) {
p.setPartOfSurface(bs);
}
}
}
return te;
}
private void updatePartOfSurface(BridgeObject bo, SurfaceMapper surfaceMapper) {
for (BoundarySurface bs : surfaceMapper.getSurfaces()) {
bo.addBoundarySurface(bs);
for (Geometry geom : bs.getGeometries()) {
for (Polygon p : geom.getPolygons()) {
p.setPartOfSurface(bs);
}
}
}
}
private void mapConstructiveElement(org.citygml4j.core.model.bridge.BridgeConstructiveElement ele, BridgeConstructiveElement bce) {
mapAbstractConstructiveElement(ele, bce);
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 void mapAbstractConstructiveElement(org.citygml4j.core.model.bridge.BridgeConstructiveElement ele, BridgeConstructiveElement bce) {
mapAbstractOccupiedSpace(ele, bce);
}
private void mapAbstractConstruction(AbstractConstruction ac, BridgeObject bo) {
mapAbstractOccupiedSpace(ac, bo);
}
@Override
public void visit(AuxiliaryTrafficArea ata) {
TransportationObject to = new TransportationObject(TransportationType.AUXILLIARY_TRAFFIC_AREA);
mapAbstractThematicSurface(ata, to);
finishTransportationMapping(to);
}
@Override
public void visit(TrafficArea ta) {
TransportationObject to = new TransportationObject(TransportationType.TRAFFIC_AREA);
mapAbstractThematicSurface(ta, to);
finishTransportationMapping(to);
}
@Override
public void visit(Road road) {
TransportationObject to = new TransportationObject(TransportationType.ROAD);
mapAbstractTransportationSpace(road, to);
finishTransportationMapping(to);
}
private void mapAbstractThematicSurface(AbstractThematicSurface ats, CityObject co) {
mapAbstractSpaceBoundary(ats, co);
parseAndAddMultiSurface(ats.getLod0MultiSurface(), Lod.LOD0, co);
parseAndAddMultiSurface(ats.getLod1MultiSurface(), Lod.LOD1, co);
parseAndAddMultiSurface(ats.getLod2MultiSurface(), Lod.LOD2, co);
parseAndAddMultiSurface(ats.getLod3MultiSurface(), Lod.LOD3, co);
parseAndAddMultiSurface(ats.getDeprecatedProperties().getLod4MultiSurface(), Lod.LOD4, co);
}
private void mapAbstractSpaceBoundary(AbstractSpaceBoundary asb, CityObject co) {
mapAbstractCityObject(asb, co);
}
private void mapAbstractCityObject(AbstractCityObject aco, CityObject to) {
mapAbstractFeatureWithLifespan(aco, to);
}
private void mapAbstractFeatureWithLifespan(AbstractFeatureWithLifespan afwl, CityObject to) {
mapAbstractFeature(afwl, to);
}
private void mapAbstractFeature(AbstractFeature af, CityObject to) {
mapAbstractGML(af, to);
}
private void mapAbstractGML(AbstractGML ag, CityObject to) {
parseId(ag, to);
}
@Override
public void visit(Railway railway) {
TransportationObject to = new TransportationObject(TransportationType.RAILWAY);
mapAbstractTransportationSpace(railway, to);
finishTransportationMapping(to);
}
@Override
public void visit(Square square) {
TransportationObject to = new TransportationObject(TransportationType.SQUARE);
mapAbstractTransportationSpace(square, to);
finishTransportationMapping(to);
}
@Override
public void visit(Track track) {
TransportationObject to = new TransportationObject(TransportationType.TRACK);
mapAbstractTransportationSpace(track, to);
finishTransportationMapping(to);
}
@Override
public void visit(TransportationComplex transportationComplex) {
TransportationObject to = new TransportationObject(TransportationType.TRANSPORTATION_COMPLEX);
mapAbstractTransportationSpace(transportationComplex, to);
finishTransportationMapping(to);
}
private void finishTransportationMapping(TransportationObject to) {
finishCityObjectConstruction(to);
model.addTransportation(to);
}
private void finishCityObjectConstruction(CityObject co) {
co.unsetGmlGeometries();
resolveAndClearReferences();
updateEdgesAndVertices(co);
}
private void mapAbstractTransportationSpace(AbstractTransportationSpace ats, TransportationObject to) {
to.setGmlObject(ats);
parseAbstractTransportationSpaceGeometries(ats, to);
for (TrafficSpaceProperty tsp : ats.getTrafficSpaces()) {
if (tsp.isSetObject()) {
TransportationObject trafficSpace = new TransportationObject(TransportationType.TRAFFIC_SPACE);
mapTrafficSpace(tsp.getObject(), trafficSpace);
finishTransportationMapping(trafficSpace);
to.getChildren().add(trafficSpace);
}
}
for (AuxiliaryTrafficSpaceProperty auxTrafficProp : ats.getAuxiliaryTrafficSpaces()) {
if (auxTrafficProp.isSetObject()) {
TransportationObject trafficSpace = parseAuxiliaryTrafficSpace(auxTrafficProp.getObject());
finishTransportationMapping(trafficSpace);
to.addChild(trafficSpace);
}
}
}
private void mapTrafficSpace(TrafficSpace ts, TransportationObject to) {
mapAbstractUnoccupiedSpace(ts, to);
}
private void mapAbstractUnoccupiedSpace(AbstractUnoccupiedSpace aus, CityObject co) {
mapAbstractPhysicalSpace(aus, co);
}
private TransportationObject parseAuxiliaryTrafficSpace(AuxiliaryTrafficSpace ats) {
TransportationObject to = new TransportationObject(TransportationType.AUXILLIARY_TRAFFIC_SPACE);
parseAbstractSpaceGeometries(ats, to);
finishCityObjectConstruction(to);
return to;
}
private void parseAbstractTransportationSpaceGeometries(AbstractTransportationSpace space, CityObject co) {
parseAndAddMultiSurface(space.getDeprecatedProperties().getLod1MultiSurface(), Lod.LOD1, co);
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;
}
Geometry geom = parseMultiSurface(msp.getObject(), lod);
co.addGeometry(geom);
}
private void parseAndAddSolid(SolidProperty sp, Lod lod, CityObject co) {
if (sp == null || sp.getObject() == null) {
return;
}
Geometry geom = parseSolid(sp.getObject(), lod);
if (geom != null) {
co.addGeometry(geom);
}
}
private void parseAndAddCompositeSurface(MultiSurfaceProperty ms, Lod lod, CityObject co) {
if (ms == null || ms.getObject() == null) {
return;
}
List<SurfaceProperty> surfaces = ms.getObject().getSurfaceMember();
for (SurfaceProperty surface : surfaces) {
if (surface.getObject() instanceof CompositeSurface cs) {
Geometry geom = parseCompositeSurface(cs, lod);
if (geom != null) {
co.addGeometry(geom);
}
}
}
}
private void parseImplicitGeometry(AbstractOccupiedSpace aos, CityObject co) {
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);
if (igh != null) {
co.addGeometry(igh);
}
} else if (aos.getImplicitRepresentation(i).getHref() != null) {
// Hrefs of ImplicitGeometries point to its RelativeGeometry.
// Can be ignored for CD since the Href is only used for repeating the RelativeGeometry at different LODs
}
}
}
private ImplicitGeometryHolder resolveImplicitGeometry(ImplicitGeometry ig, int lodInt) {
ImplicitGeometryHolder igh = null;
if (ig.getLibraryObject() != null) {
Path libraryObjectPath = directory.resolve(ig.getLibraryObject());
LibraryObject libObj = LibraryObject.of(libraryObjectPath, config);
if (libObj != null) {
igh = new ImplicitGeometryHolder(ig, libObj);
}
} 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);
}
} else {
logger.error(String.format("Implicit geometry of GML-ID %s has no referenced geometry.", ig.getId()));
}
return igh;
}
private void resolveAndClearReferences() {
for (ResolvableReference ref : references) {
String href = ref.href();
if (href.startsWith("#")) {
href = href.substring(1);
}
Geometry geom = ref.geometry();
CompositeCollection comp = compositeMap.get(href);
if (comp != null) {
comp.getCompositeMembers().forEach(geom::addPolygon);
} else {
ConcretePolygon concPoly = polygonMap.get(href);
if (concPoly == null) {
if (logger.isWarnEnabled()) {
logger.warn(Localization.getText("FeatureMapper.polygonUnreferenced"), href);
}
} else {
LinkedPolygon lPoly = new LinkedPolygon(concPoly, geom);
if (geom.getParent() instanceof BoundarySurface bs) {
lPoly.setPartOfSurface(bs);
if (bs.getParent() instanceof Installation bi) {
lPoly.setPartOfInstallation(bi);
}
}
geom.addPolygon(lPoly);
}
}
}
// clear storage for polygons and vertices
// probably faster than .clear() ?
references = new ArrayList<>();
vertexMap = new HashMap<>();
polygonMap = new HashMap<>();
}
private void readAbstractBuilding(org.citygml4j.core.model.building.AbstractBuilding gmlAb,
AbstractBuilding cdBuilding) {
mapAbstractOccupiedSpace(gmlAb, cdBuilding);
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);
for (BuildingInstallationProperty biProp : gmlAb.getBuildingInstallations()) {
var gmlBi = biProp.getObject();
if (gmlBi == null) {
// ignore empty properties
continue;
}
Installation bi = mapBuildingInstallation(gmlBi);
cdBuilding.addBuildingInstallation(bi);
}
for (BuildingRoomProperty brProp : gmlAb.getBuildingRooms()) {
var gmlBr = brProp.getObject();
if (gmlBr == null) {
continue;
}
BuildingRoom br = mapBuildingRoom(gmlBr);
cdBuilding.addBuildingRoom(br);
}
for (AbstractBuildingSubdivisionProperty abs : gmlAb.getBuildingSubdivisions()) {
var gmlABS = abs.getObject();
if (gmlABS == null) {
continue;
}
if (gmlABS instanceof Storey gmlStorey) {
de.hft.stuttgart.citydoctor2.datastructure.Storey storey = mapBuildingStorey(gmlStorey);
cdBuilding.addStorey(storey);
} else if (gmlABS instanceof BuildingUnit gmlBU) {
de.hft.stuttgart.citydoctor2.datastructure.BuildingUnit bu = mapBuildingUnit(gmlBU);
cdBuilding.addBuildingUnit(bu);
}
}
SurfaceMapper surfaceMapper = new SurfaceMapper(polygonMap, references, compositeMap, vertexMap, config);
for (AbstractSpaceBoundaryProperty surfaceProp : gmlAb.getBoundaries()) {
if (!surfaceProp.isSetObject()) {
continue;
}
AbstractSpaceBoundary surface = surfaceProp.getObject();
surface.accept(surfaceMapper);
}
updatePartOfSurface(cdBuilding, surfaceMapper);
cdBuilding.unsetGmlGeometries();
resolveAndClearReferences();
updateEdgesAndVertices(cdBuilding);
for (BoundarySurface bs : surfaceMapper.getSurfaces()) {
updateEdgesAndVertices(bs);
for (Opening o : bs.getOpenings()) {
updateEdgesAndVertices(o);
}
}
for (Installation bi : cdBuilding.getBuildingInstallations()) {
updateEdgesAndVertices(bi);
for (BoundarySurface bs : bi.getBoundarySurfaces()) {
updateEdgesAndVertices(bs);
for (Opening o : bs.getOpenings()) {
updateEdgesAndVertices(o);
}
}
}
for (BuildingFurnitureProperty bfProp : gmlAb.getBuildingFurniture()) {
var gmlBf = bfProp.getObject();
if (gmlBf == null) {
continue;
}
BuildingRoomFurniture bf = mapBuildingFurniture(gmlBf);
cdBuilding.addBuildingRoomFurniture(bf);
}
}
private BuildingRoom mapBuildingRoom(org.citygml4j.core.model.building.BuildingRoom gmlBr) {
BuildingRoom br = new BuildingRoom();
br.setGmlObject(gmlBr);
mapAbstractUnoccupiedSpace(gmlBr, br);
SurfaceMapper surfaceMapper = new SurfaceMapper(polygonMap, references, compositeMap, vertexMap, config);
for (AbstractSpaceBoundaryProperty surfaceProp : gmlBr.getBoundaries()) {
if (!surfaceProp.isSetObject()) {
continue;
}
AbstractSpaceBoundary surface = surfaceProp.getObject();
surface.accept(surfaceMapper);
}
for (BoundarySurface bs : surfaceMapper.getSurfaces()) {
br.addBoundarySurface(bs);
for (Geometry geom : bs.getGeometries()) {
for (Polygon p : geom.getPolygons()) {
p.setPartOfSurface(bs);
}
}
}
for (BuildingInstallationProperty biProp : gmlBr.getBuildingInstallations()) {
var gmlBi = biProp.getObject();
if (gmlBi == null) {
// ignore empty properties
continue;
}
Installation bi = mapBuildingInstallation(gmlBi);
br.addRoomInstallation(bi);
}
for (BuildingFurnitureProperty bfProp : gmlBr.getBuildingFurniture()) {
var gmlHref = bfProp.getHref();
if (gmlHref == null) {
continue;
}
br.addFurnitureRef(bfProp);
}
return br;
}
private BuildingRoomFurniture mapBuildingFurniture(BuildingFurniture gmlAF) {
BuildingRoomFurniture bf = new BuildingRoomFurniture();
bf.setGmlObject(gmlAF);
mapAbstractOccupiedSpace(gmlAF, bf);
bf.unsetGmlGeometries();
SurfaceMapper surfaceMapper = new SurfaceMapper(polygonMap, references, compositeMap, vertexMap, config);
for (AbstractSpaceBoundaryProperty surfaceProp : gmlAF.getBoundaries()) {
if (!surfaceProp.isSetObject()) {
continue;
}
AbstractSpaceBoundary surface = surfaceProp.getObject();
surface.accept(surfaceMapper);
}
for (BoundarySurface bs : surfaceMapper.getSurfaces()) {
bf.addBoundarySurface(bs);
for (Geometry geom : bs.getGeometries()) {
for (Polygon p : geom.getPolygons()) {
p.setPartOfSurface(bs);
}
}
}
return bf;
}
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);
storey.unsetGmlGeometries();
SurfaceMapper surfaceMapper = new SurfaceMapper(polygonMap, references, compositeMap, vertexMap, config);
for (AbstractSpaceBoundaryProperty surfaceProp : gmlStorey.getBoundaries()) {
if (!surfaceProp.isSetObject()) {
continue;
}
AbstractSpaceBoundary surface = surfaceProp.getObject();
surface.accept(surfaceMapper);
}
for (BoundarySurface bs : surfaceMapper.getSurfaces()) {
storey.addBoundarySurface(bs);
for (Geometry geom : bs.getGeometries()) {
for (Polygon p : geom.getPolygons()) {
p.setPartOfSurface(bs);
}
}
}
return storey;
}
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);
bu.unsetGmlGeometries();
SurfaceMapper surfaceMapper = new SurfaceMapper(polygonMap, references, compositeMap, vertexMap, config);
for (AbstractSpaceBoundaryProperty surfaceProp : gmlBU.getBoundaries()) {
if (!surfaceProp.isSetObject()) {
continue;
}
AbstractSpaceBoundary surface = surfaceProp.getObject();
surface.accept(surfaceMapper);
}
for (BoundarySurface bs : surfaceMapper.getSurfaces()) {
bu.addBoundarySurface(bs);
for (Geometry geom : bs.getGeometries()) {
for (Polygon p : geom.getPolygons()) {
p.setPartOfSurface(bs);
}
}
}
return bu;
}
private void updatePartOfSurface(AbstractBuilding cdBuilding, SurfaceMapper surfaceMapper) {
for (BoundarySurface bs : surfaceMapper.getSurfaces()) {
cdBuilding.addBoundarySurface(bs);
for (Geometry geom : bs.getGeometries()) {
for (Polygon p : geom.getPolygons()) {
p.setPartOfSurface(bs);
}
}
}
}
private Installation mapBuildingInstallation(org.citygml4j.core.model.building.BuildingInstallation gmlBi) {
Installation bi = new Installation();
bi.setGmlObject(gmlBi);
mapAbstractOccupiedSpace(gmlBi, bi);
GeometryProperty<?> lod2Prop = gmlBi.getDeprecatedProperties().getLod2Geometry();
parseAndAddAbstractGeometry(lod2Prop, Lod.LOD2, bi);
GeometryProperty<?> lod3Prop = gmlBi.getDeprecatedProperties().getLod3Geometry();
parseAndAddAbstractGeometry(lod3Prop, Lod.LOD3, bi);
GeometryProperty<?> lod4Prop = gmlBi.getDeprecatedProperties().getLod4Geometry();
parseAndAddAbstractGeometry(lod4Prop, Lod.LOD4, bi);
bi.unsetGmlGeometries();
SurfaceMapper surfaceMapper = new SurfaceMapper(polygonMap, references, compositeMap, vertexMap, config);
for (AbstractSpaceBoundaryProperty surfaceProp : gmlBi.getBoundaries()) {
if (!surfaceProp.isSetObject()) {
continue;
}
AbstractSpaceBoundary surface = surfaceProp.getObject();
surface.accept(surfaceMapper);
}
for (BoundarySurface bs : surfaceMapper.getSurfaces()) {
bi.addBoundarySurface(bs);
for (Geometry geom : bs.getGeometries()) {
for (Polygon p : geom.getPolygons()) {
p.setPartOfSurface(bs);
p.setPartOfInstallation(bi);
}
}
}
for (Geometry geom : bi.getGeometries()) {
for (Polygon p : geom.getPolygons()) {
p.setPartOfInstallation(bi);
}
}
return bi;
}
private void parseAndAddAbstractGeometry(GeometryProperty<?> geomProp, Lod lod, CityObject co) {
if (geomProp == null || geomProp.getObject() == null) {
return;
}
AbstractGeometry abstractGeometry = geomProp.getObject();
if (abstractGeometry instanceof MultiSurface ms) {
Geometry geom = parseMultiSurface(ms, lod);
co.addGeometry(geom);
} else if (abstractGeometry instanceof Solid solid) {
Geometry geom = parseSolid(solid, lod);
if (geom != null) {
co.addGeometry(geom);
}
} else {
logger.warn("Cannot handle geometry type {}, ignoring", abstractGeometry.getClass().getSimpleName());
}
}
private Geometry parseSolid(AbstractSolid abstractSolid, Lod lod) {
if (abstractSolid instanceof Solid s) {
return handleSolidGeometry(s, lod);
} else {
logger.warn("Cannot handle solid class {}, can only process pure solids",
abstractSolid.getClass().getSimpleName());
return null;
}
}
private Geometry handleSolidGeometry(Solid solid, Lod lod) {
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);
Shell exterior = solid.getExterior().getObject();
Citygml3GeometryMapper geometryMapper = new Citygml3GeometryMapper(config, vertexMap);
readSurfaceMember(geom, geometryMapper, exterior.getSurfaceMembers());
return geom;
}
private Geometry parseMultiSurface(MultiSurface ms, Lod lod) {
Geometry geom = new Geometry(GeometryType.MULTI_SURFACE, lod);
Citygml3GeometryMapper geometryMapper = new Citygml3GeometryMapper(config, vertexMap);
readSurfaceMember(geom, geometryMapper, ms.getSurfaceMember());
return geom;
}
private void readSurfaceMember(Geometry geom, Citygml3GeometryMapper geometryMapper,
List<SurfaceProperty> surfaceMember) {
for (SurfaceProperty prop : surfaceMember) {
if (prop.getHref() != null) {
references.add(new ResolvableReference(prop.getHref(), geom));
continue;
}
if (prop.getObject() != null) {
AbstractSurface as = prop.getObject();
as.accept(geometryMapper);
}
}
List<ConcretePolygon> polygons = geometryMapper.getPolygons();
for (ConcretePolygon concretePoly : polygons) {
geom.addPolygon(concretePoly);
if (concretePoly.hasExistingGmlId()) {
polygonMap.put(concretePoly.getGmlId().getGmlString(), concretePoly);
}
}
}
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());
return geom;
}
private void updateEdgesAndVertices(CityObject co) {
// searching for neighboring vertices, replacing them with one single vertex to
// avoid later problems with edges and manifold problems
for (Geometry geom : co.getGeometries()) {
KDTree tree = new KDTree();
for (Polygon poly : geom.getPolygons()) {
LinearRing lr = poly.getExteriorRing();
updateRing(tree, lr);
for (LinearRing innerRing : poly.getInnerRings()) {
updateRing(tree, innerRing);
}
}
if (!config.useLowMemoryConsumption()) {
// no low memory consumption mode meaning create all meta information in
// geometry
geom.updateEdgesAndVertices();
}
}
}
private void updateRing(KDTree tree, LinearRing lr) {
for (int i = 0; i < lr.getVertices().size(); i++) {
Vertex v = lr.getVertices().get(i);
List<Vertex> nodesInRange = tree.getNodesInRange(v, neighborDistance);
if (nodesInRange.isEmpty()) {
tree.add(v);
} else {
// replace other vertex with any neighboring one
Vertex original = nodesInRange.get(0);
lr.setVertex(i, original);
}
}
}
public void setCityModel(CityModel cModel) {
model.setCityModel(cModel);
}
public CityDoctorModel getModel() {
return model;
}
public void setCityGMLVersion(CityGMLVersion cityGMLVersion) {
model.setParsedCityGMLVersion(cityGMLVersion);
}
}
/*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
......@@ -18,163 +18,193 @@
*/
package de.hft.stuttgart.citydoctor2.mapper.citygml3;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.*;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing.LinearRingType;
import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;
import de.hft.stuttgart.citydoctor2.utils.Localization;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.locationtech.proj4j.BasicCoordinateTransform;
import org.locationtech.proj4j.ProjCoordinate;
import org.xmlobjects.gml.model.geometry.primitives.AbstractRing;
import org.xmlobjects.gml.model.geometry.primitives.AbstractRingProperty;
import org.xmlobjects.gml.model.geometry.complexes.CompositeSurface;
import org.xmlobjects.gml.model.geometry.primitives.Polygon;
import org.xmlobjects.gml.model.geometry.primitives.Ring;
import org.xmlobjects.gml.model.geometry.primitives.*;
import org.xmlobjects.gml.visitor.GeometryWalker;
import de.hft.stuttgart.citydoctor2.datastructure.ConcretePolygon;
import de.hft.stuttgart.citydoctor2.datastructure.GmlId;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing.LinearRingType;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;
import de.hft.stuttgart.citydoctor2.utils.Localization;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class Citygml3GeometryMapper extends GeometryWalker {
private static final Logger logger = LogManager.getLogger(Citygml3GeometryMapper.class);
private final List<ConcretePolygon> polygons = new ArrayList<>();
private LinearRing currentRing = null;
private final ParserConfiguration config;
private final ProjCoordinate p1 = new ProjCoordinate();
private final ProjCoordinate p2 = new ProjCoordinate();
private final Map<Vertex, Vertex> vertexMap;
public Citygml3GeometryMapper(ParserConfiguration config, Map<Vertex, Vertex> vertices) {
this.config = config;
this.vertexMap = vertices;
}
@Override
public void visit(Polygon polygon) {
parsePolygon(polygon.getId(), polygon.getExterior(), polygon.getInterior());
if (polygon.getExterior() == null) {
logger.warn(String.format("No exterior: %s" ,polygon.getId()));
}
}
private void parsePolygon(String id, AbstractRingProperty exterior, List<AbstractRingProperty> interior) {
if (exterior == null || exterior.getObject() == null) {
if (logger.isWarnEnabled()) {
logger.warn(Localization.getText("GeometryMapper.emptyPolygon"));
}
return;
}
ConcretePolygon cdPoly = new ConcretePolygon();
polygons.add(cdPoly);
if (id != null) {
cdPoly.setGmlId(new GmlId(id));
}
currentRing = new LinearRing(LinearRingType.EXTERIOR);
exterior.getObject().accept(this);
cdPoly.setExteriorRing(currentRing);
for (AbstractRingProperty interiorGmlRing : interior) {
AbstractRing gmlRing = interiorGmlRing.getObject();
if (gmlRing == null) {
continue;
}
currentRing = new LinearRing(LinearRingType.INTERIOR);
gmlRing.accept(this);
cdPoly.addInteriorRing(currentRing);
}
}
@Override
public void visit(org.xmlobjects.gml.model.geometry.primitives.LinearRing gmlRing) {
if (gmlRing.getSrsDimension() != null && gmlRing.getSrsDimension() != 3) {
logger.warn("Cannot handle geometry with srsDimension not 3");
return;
}
if (gmlRing.getId() != null) {
currentRing.setGmlId(new GmlId(gmlRing.getId()));
}
List<Double> coordinates = gmlRing.toCoordinateList3D();
handleCoordinateList(coordinates);
}
@Override
public void visit(Ring ring) {
if (ring.getSrsDimension() != null && ring.getSrsDimension() != 3) {
logger.warn("Cannot handle geometry with srsDimension not 3");
return;
}
if (ring.getId() != null) {
currentRing.setGmlId(new GmlId(ring.getId()));
}
List<Double> coordinates = ring.toCoordinateList3D();
handleCoordinateList(coordinates);
}
private void handleCoordinateList(List<Double> coordinates) {
if (coordinates.size() % 3 != 0) {
String id;
if (currentRing.hasExistingGmlId()) {
id = currentRing.getGmlId().getGmlString();
} else {
id = "";
}
logger.warn("The number of coordinates for linear ring {} do not result in fully 3D points", id);
}
for (int i = 0; i < coordinates.size(); i = i + 3) {
double x = coordinates.get(i);
double y = coordinates.get(i + 1);
double z = coordinates.get(i + 2);
createVertex(x, y, z);
}
}
private void createVertex(double x, double y, double z) {
// transform into utm, if available
BasicCoordinateTransform trans = config.getTargetTransform();
if (trans != null) {
p1.setValue(x, y);
trans.transform(p1, p2);
x = p2.x;
y = p2.y;
z = z / config.getFromMeters();
}
x = round(x, config.getNumberOfRoundingPlaces());
y = round(y, config.getNumberOfRoundingPlaces());
z = round(z, config.getNumberOfRoundingPlaces());
Vertex v = new Vertex(x, y, z);
Vertex duplicate = vertexMap.get(v);
if (duplicate == null) {
vertexMap.put(v, v);
} else {
v = duplicate;
}
currentRing.addVertex(v);
}
private double round(double value, int places) {
if (places < 0) {
throw new IllegalArgumentException();
}
BigDecimal bd = BigDecimal.valueOf(value);
bd = bd.setScale(places, RoundingMode.HALF_UP);
return bd.doubleValue();
}
public List<ConcretePolygon> getPolygons() {
return polygons;
}
private static final Logger logger = LogManager.getLogger(Citygml3GeometryMapper.class);
private final List<ConcretePolygon> polygons = new ArrayList<>();
private final List<CompositeCollection> composites = new ArrayList<>();
private LinearRing currentRing = null;
private final ParserConfiguration config;
private final ProjCoordinate p1 = new ProjCoordinate();
private final ProjCoordinate p2 = new ProjCoordinate();
private final Map<Vertex, Vertex> vertexMap;
public Citygml3GeometryMapper(ParserConfiguration config, Map<Vertex, Vertex> vertices) {
this.config = config;
this.vertexMap = vertices;
}
@Override
public void visit(Polygon polygon) {
parsePolygon(polygon.getId(), polygon.getExterior(), polygon.getInterior());
if (polygon.getExterior() == null) {
logger.warn(String.format("No exterior: %s", polygon.getId()));
}
}
private void parsePolygon(String id, AbstractRingProperty exterior, List<AbstractRingProperty> interior) {
if (exterior == null || exterior.getObject() == null) {
if (logger.isWarnEnabled()) {
logger.warn(Localization.getText("GeometryMapper.emptyPolygon"));
}
return;
}
ConcretePolygon cdPoly = new ConcretePolygon();
polygons.add(cdPoly);
if (id != null) {
cdPoly.setGmlId(new GmlId(id));
}
currentRing = new LinearRing(LinearRingType.EXTERIOR);
exterior.getObject().accept(this);
cdPoly.setExteriorRing(currentRing);
for (AbstractRingProperty interiorGmlRing : interior) {
AbstractRing gmlRing = interiorGmlRing.getObject();
if (gmlRing == null) {
continue;
}
currentRing = new LinearRing(LinearRingType.INTERIOR);
gmlRing.accept(this);
cdPoly.addInteriorRing(currentRing);
}
}
@Override
public void visit(CompositeSurface cs) {
if (cs.getSurfaceMembers() != null && cs.getSurfaceMembers().isEmpty()) {
logger.warn("CompositeSurface %s is empty", cs.getId());
return;
}
List<SurfaceProperty> surfaceMember = cs.getSurfaceMembers();
Citygml3GeometryMapper recursiveMapper = new Citygml3GeometryMapper(config, vertexMap);
CompositeCollection comp = new CompositeCollection();
if (cs.getId() == null) {
comp.setGmlId(GmlId.generateId());
} else {
comp.setGmlId(new GmlId(cs.getId()));
}
for (SurfaceProperty prop : surfaceMember) {
if (prop.getObject() != null) {
AbstractSurface as = prop.getObject();
as.accept(recursiveMapper);
}
}
List<ConcretePolygon> compPolys = recursiveMapper.getPolygons();
compPolys.forEach(comp::addCompositeMember);
comp.addAllChildComposites(recursiveMapper.getComposites());
composites.add(comp);
polygons.addAll(compPolys);
}
@Override
public void visit(org.xmlobjects.gml.model.geometry.primitives.LinearRing gmlRing) {
if (gmlRing.getSrsDimension() != null && gmlRing.getSrsDimension() != 3) {
logger.warn("Cannot handle geometry with srsDimension not 3");
return;
}
if (gmlRing.getId() != null) {
currentRing.setGmlId(new GmlId(gmlRing.getId()));
}
List<Double> coordinates = gmlRing.toCoordinateList3D();
handleCoordinateList(coordinates);
}
@Override
public void visit(Ring ring) {
if (ring.getSrsDimension() != null && ring.getSrsDimension() != 3) {
logger.warn("Cannot handle geometry with srsDimension not 3");
return;
}
if (ring.getId() != null) {
currentRing.setGmlId(new GmlId(ring.getId()));
}
List<Double> coordinates = ring.toCoordinateList3D();
handleCoordinateList(coordinates);
}
private void handleCoordinateList(List<Double> coordinates) {
if (coordinates.size() % 3 != 0) {
String id;
if (currentRing.hasExistingGmlId()) {
id = currentRing.getGmlId().getGmlString();
} else {
id = "";
}
logger.warn("The number of coordinates for linear ring {} do not result in fully 3D points", id);
}
for (int i = 0; i < coordinates.size(); i = i + 3) {
double x = coordinates.get(i);
double y = coordinates.get(i + 1);
double z = coordinates.get(i + 2);
createVertex(x, y, z);
}
}
private void createVertex(double x, double y, double z) {
// transform into utm, if available
BasicCoordinateTransform trans = config.getTargetTransform();
if (trans != null) {
p1.setValue(x, y);
trans.transform(p1, p2);
x = p2.x;
y = p2.y;
z = z / config.getFromMeters();
}
x = round(x, config.getNumberOfRoundingPlaces());
y = round(y, config.getNumberOfRoundingPlaces());
z = round(z, config.getNumberOfRoundingPlaces());
Vertex v = new Vertex(x, y, z);
Vertex duplicate = vertexMap.get(v);
if (duplicate == null) {
vertexMap.put(v, v);
} else {
v = duplicate;
}
currentRing.addVertex(v);
}
private double round(double value, int places) {
if (places < 0) {
throw new IllegalArgumentException();
}
BigDecimal bd = BigDecimal.valueOf(value);
bd = bd.setScale(places, RoundingMode.HALF_UP);
return bd.doubleValue();
}
public List<ConcretePolygon> getPolygons() {
return polygons;
}
public List<CompositeCollection> getComposites() {
return composites;
}
}
/*-
* Copyright 2022 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
......@@ -18,23 +18,9 @@
*/
package de.hft.stuttgart.citydoctor2.mapper.citygml3;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.citygml4j.core.model.construction.AbstractConstructionSurface;
import org.citygml4j.core.model.construction.AbstractFillingSurface;
import org.citygml4j.core.model.construction.AbstractFillingSurfaceProperty;
import org.citygml4j.core.model.construction.CeilingSurface;
import org.citygml4j.core.model.construction.DoorSurface;
import org.citygml4j.core.model.construction.FloorSurface;
import org.citygml4j.core.model.construction.GroundSurface;
import org.citygml4j.core.model.construction.InteriorWallSurface;
import org.citygml4j.core.model.construction.OuterCeilingSurface;
import org.citygml4j.core.model.construction.OuterFloorSurface;
import org.citygml4j.core.model.construction.RoofSurface;
import org.citygml4j.core.model.construction.WallSurface;
import org.citygml4j.core.model.construction.WindowSurface;
import de.hft.stuttgart.citydoctor2.datastructure.*;
import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;
import org.citygml4j.core.model.construction.*;
import org.citygml4j.core.model.core.AbstractThematicSurface;
import org.citygml4j.core.model.core.ClosureSurface;
import org.citygml4j.core.visitor.ObjectWalker;
......@@ -43,184 +29,185 @@ import org.xmlobjects.gml.model.geometry.aggregates.MultiSurfaceProperty;
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;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class SurfaceMapper extends ObjectWalker {
private final List<BoundarySurface> surfaces = new ArrayList<>();
private final Map<String, ConcretePolygon> polygonMap;
private final List<ResolvableReference> references;
private final Map<Vertex, Vertex> vertexMap;
private final ParserConfiguration config;
public SurfaceMapper(Map<String, ConcretePolygon> polygonMap, List<ResolvableReference> references,
Map<Vertex, Vertex> vertexMap, ParserConfiguration config) {
this.polygonMap = polygonMap;
this.references = references;
this.vertexMap = vertexMap;
this.config = config;
}
@Override
public void visit(WallSurface wallSurface) {
BoundarySurface surface = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.WALL,
wallSurface);
handleConstructionSurface(wallSurface, surface);
surfaces.add(surface);
}
private void handleConstructionSurface(AbstractConstructionSurface gmlSurface, BoundarySurface cdSurface) {
for (AbstractFillingSurfaceProperty fillingProp : gmlSurface.getFillingSurfaces()) {
if (fillingProp.isSetObject()) {
readAbstractFillingSurface(fillingProp.getObject(), cdSurface);
}
}
handleThematicSurface(gmlSurface, cdSurface);
cdSurface.unsetGmlGeometries();
}
private void readAbstractFillingSurface(AbstractFillingSurface afs, BoundarySurface cdSurface) {
Opening o;
if (afs instanceof DoorSurface ds) {
o = new Opening(OpeningType.DOOR, SurfaceFeatureType.BUILDING, cdSurface, ds);
} else if (afs instanceof WindowSurface ws){
o = new Opening(OpeningType.WINDOW, SurfaceFeatureType.BUILDING, cdSurface, ws);
} else {
o = new Opening(OpeningType.UNKNOWN, SurfaceFeatureType.BUILDING, cdSurface, afs);
}
cdSurface.addOpening(o);
parseAndAddMultiSurface(afs.getLod0MultiSurface(), Lod.LOD0, o);
parseAndAddMultiSurface(afs.getLod1MultiSurface(), Lod.LOD1, o);
parseAndAddMultiSurface(afs.getLod2MultiSurface(), Lod.LOD2, o);
parseAndAddMultiSurface(afs.getLod3MultiSurface(), Lod.LOD3, o);
parseAndAddMultiSurface(afs.getDeprecatedProperties().getLod4MultiSurface(), Lod.LOD4, o);
o.unsetGmlGeometries();
}
private void handleThematicSurface(AbstractThematicSurface gmlSurface, CityObject cdSurface) {
Citygml3FeatureMapper.parseId(gmlSurface, cdSurface);
parseAndAddMultiSurface(gmlSurface.getLod0MultiSurface(), Lod.LOD0, cdSurface);
parseAndAddMultiSurface(gmlSurface.getLod1MultiSurface(), Lod.LOD1, cdSurface);
parseAndAddMultiSurface(gmlSurface.getLod2MultiSurface(), Lod.LOD2, cdSurface);
parseAndAddMultiSurface(gmlSurface.getLod3MultiSurface(), Lod.LOD3, cdSurface);
parseAndAddMultiSurface(gmlSurface.getDeprecatedProperties().getLod4MultiSurface(), Lod.LOD4, cdSurface);
}
private void parseAndAddMultiSurface(MultiSurfaceProperty msp, Lod lod, CityObject cdSurface) {
if (msp == null || msp.getObject() == null) {
return;
}
Geometry geom = parseMultiSurface(msp.getObject(), lod);
cdSurface.addGeometry(geom);
}
private Geometry parseMultiSurface(MultiSurface ms, Lod lod) {
Geometry geom = new Geometry(GeometryType.MULTI_SURFACE, lod);
Citygml3GeometryMapper geometryMapper = new Citygml3GeometryMapper(config, vertexMap);
readSurfaceMember(geom, geometryMapper, ms.getSurfaceMember());
return geom;
}
private void readSurfaceMember(Geometry geom, Citygml3GeometryMapper geometryMapper,
List<SurfaceProperty> surfaceMember) {
for (SurfaceProperty prop : surfaceMember) {
if (prop.getHref() != null) {
references.add(new ResolvableReference(prop.getHref(), geom));
continue;
}
if (prop.getObject() != null) {
AbstractSurface as = prop.getObject();
as.accept(geometryMapper);
}
}
List<ConcretePolygon> polygons = geometryMapper.getPolygons();
for (ConcretePolygon concretePoly : polygons) {
geom.addPolygon(concretePoly);
if (concretePoly.hasExistingGmlId()) {
polygonMap.put(concretePoly.getGmlId().getGmlString(), concretePoly);
}
}
}
@Override
public void visit(FloorSurface floorSurface) {
BoundarySurface surface = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.FLOOR,
floorSurface);
handleConstructionSurface(floorSurface, surface);
surfaces.add(surface);
}
@Override
public void visit(CeilingSurface ceilingSurface) {
BoundarySurface surface = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.CEILING,
ceilingSurface);
handleConstructionSurface(ceilingSurface, surface);
surfaces.add(surface);
}
@Override
public void visit(GroundSurface groundSurface) {
BoundarySurface surface = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.GROUND,
groundSurface);
handleConstructionSurface(groundSurface, surface);
surfaces.add(surface);
}
@Override
public void visit(InteriorWallSurface interiorWallSurface) {
BoundarySurface surface = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.INTERIOR_WALL,
interiorWallSurface);
handleConstructionSurface(interiorWallSurface, surface);
surfaces.add(surface);
}
@Override
public void visit(OuterCeilingSurface outerCeilingSurface) {
BoundarySurface surface = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.OUTER_CEILING,
outerCeilingSurface);
handleConstructionSurface(outerCeilingSurface, surface);
surfaces.add(surface);
}
@Override
public void visit(OuterFloorSurface outerFloorSurface) {
BoundarySurface surface = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.OUTER_FLOOR,
outerFloorSurface);
handleConstructionSurface(outerFloorSurface, surface);
surfaces.add(surface);
}
@Override
public void visit(RoofSurface roofSurface) {
BoundarySurface surface = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.ROOF,
roofSurface);
handleConstructionSurface(roofSurface, surface);
surfaces.add(surface);
}
@Override
public void visit(ClosureSurface closureSurface) {
BoundarySurface surface = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.CLOSURE,
closureSurface);
handleThematicSurface(closureSurface, surface);
surfaces.add(surface);
}
public List<BoundarySurface> getSurfaces() {
return surfaces;
}
private final List<BoundarySurface> surfaces = new ArrayList<>();
private final Map<String, ConcretePolygon> polygonMap;
private final Map<String, CompositeCollection> compositeMap;
private final List<ResolvableReference> references;
private final Map<Vertex, Vertex> vertexMap;
private final ParserConfiguration config;
public SurfaceMapper(Map<String, ConcretePolygon> polygonMap, List<ResolvableReference> references,
Map<String, CompositeCollection> compositeMap, Map<Vertex, Vertex> vertexMap,
ParserConfiguration config) {
this.polygonMap = polygonMap;
this.references = references;
this.vertexMap = vertexMap;
this.compositeMap = compositeMap;
this.config = config;
}
@Override
public void visit(WallSurface wallSurface) {
BoundarySurface surface = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.WALL,
wallSurface);
handleConstructionSurface(wallSurface, surface);
surfaces.add(surface);
}
private void handleConstructionSurface(AbstractConstructionSurface gmlSurface, BoundarySurface cdSurface) {
for (AbstractFillingSurfaceProperty fillingProp : gmlSurface.getFillingSurfaces()) {
if (fillingProp.isSetObject()) {
readAbstractFillingSurface(fillingProp.getObject(), cdSurface);
}
}
handleThematicSurface(gmlSurface, cdSurface);
cdSurface.unsetGmlGeometries();
}
private void readAbstractFillingSurface(AbstractFillingSurface afs, BoundarySurface cdSurface) {
Opening o;
if (afs instanceof DoorSurface ds) {
o = new Opening(OpeningType.DOOR, SurfaceFeatureType.BUILDING, cdSurface, ds);
} else if (afs instanceof WindowSurface ws) {
o = new Opening(OpeningType.WINDOW, SurfaceFeatureType.BUILDING, cdSurface, ws);
} else {
o = new Opening(OpeningType.UNKNOWN, SurfaceFeatureType.BUILDING, cdSurface, afs);
}
cdSurface.addOpening(o);
parseAndAddMultiSurface(afs.getLod0MultiSurface(), Lod.LOD0, o);
parseAndAddMultiSurface(afs.getLod1MultiSurface(), Lod.LOD1, o);
parseAndAddMultiSurface(afs.getLod2MultiSurface(), Lod.LOD2, o);
parseAndAddMultiSurface(afs.getLod3MultiSurface(), Lod.LOD3, o);
parseAndAddMultiSurface(afs.getDeprecatedProperties().getLod4MultiSurface(), Lod.LOD4, o);
o.unsetGmlGeometries();
}
private void handleThematicSurface(AbstractThematicSurface gmlSurface, CityObject cdSurface) {
Citygml3FeatureMapper.parseId(gmlSurface, cdSurface);
parseAndAddMultiSurface(gmlSurface.getLod0MultiSurface(), Lod.LOD0, cdSurface);
parseAndAddMultiSurface(gmlSurface.getLod1MultiSurface(), Lod.LOD1, cdSurface);
parseAndAddMultiSurface(gmlSurface.getLod2MultiSurface(), Lod.LOD2, cdSurface);
parseAndAddMultiSurface(gmlSurface.getLod3MultiSurface(), Lod.LOD3, cdSurface);
parseAndAddMultiSurface(gmlSurface.getDeprecatedProperties().getLod4MultiSurface(), Lod.LOD4, cdSurface);
}
private void parseAndAddMultiSurface(MultiSurfaceProperty msp, Lod lod, CityObject cdSurface) {
if (msp == null || msp.getObject() == null) {
return;
}
Geometry geom = parseMultiSurface(msp.getObject(), lod);
cdSurface.addGeometry(geom);
}
private Geometry parseMultiSurface(MultiSurface ms, Lod lod) {
Geometry geom = new Geometry(GeometryType.MULTI_SURFACE, lod);
Citygml3GeometryMapper geometryMapper = new Citygml3GeometryMapper(config, vertexMap);
readSurfaceMember(geom, geometryMapper, ms.getSurfaceMember());
return geom;
}
private void readSurfaceMember(Geometry geom, Citygml3GeometryMapper geometryMapper,
List<SurfaceProperty> surfaceMember) {
for (SurfaceProperty prop : surfaceMember) {
if (prop.getHref() != null) {
references.add(new ResolvableReference(prop.getHref(), geom));
continue;
}
if (prop.getObject() != null) {
AbstractSurface as = prop.getObject();
as.accept(geometryMapper);
}
}
List<ConcretePolygon> polygons = geometryMapper.getPolygons();
List<CompositeCollection> composites = geometryMapper.getComposites();
for (CompositeCollection cc : composites) {
references.add(new ResolvableReference(cc.getGmlId().toString(), geom));
compositeMap.put(cc.getGmlId().getGmlString(), cc);
}
for (ConcretePolygon concretePoly : polygons) {
geom.addPolygon(concretePoly);
if (concretePoly.hasExistingGmlId()) {
polygonMap.put(concretePoly.getGmlId().getGmlString(), concretePoly);
}
}
}
@Override
public void visit(FloorSurface floorSurface) {
BoundarySurface surface = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.FLOOR,
floorSurface);
handleConstructionSurface(floorSurface, surface);
surfaces.add(surface);
}
@Override
public void visit(CeilingSurface ceilingSurface) {
BoundarySurface surface = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.CEILING,
ceilingSurface);
handleConstructionSurface(ceilingSurface, surface);
surfaces.add(surface);
}
@Override
public void visit(GroundSurface groundSurface) {
BoundarySurface surface = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.GROUND,
groundSurface);
handleConstructionSurface(groundSurface, surface);
surfaces.add(surface);
}
@Override
public void visit(InteriorWallSurface interiorWallSurface) {
BoundarySurface surface = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.INTERIOR_WALL,
interiorWallSurface);
handleConstructionSurface(interiorWallSurface, surface);
surfaces.add(surface);
}
@Override
public void visit(OuterCeilingSurface outerCeilingSurface) {
BoundarySurface surface = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.OUTER_CEILING,
outerCeilingSurface);
handleConstructionSurface(outerCeilingSurface, surface);
surfaces.add(surface);
}
@Override
public void visit(OuterFloorSurface outerFloorSurface) {
BoundarySurface surface = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.OUTER_FLOOR,
outerFloorSurface);
handleConstructionSurface(outerFloorSurface, surface);
surfaces.add(surface);
}
@Override
public void visit(RoofSurface roofSurface) {
BoundarySurface surface = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.ROOF,
roofSurface);
handleConstructionSurface(roofSurface, surface);
surfaces.add(surface);
}
@Override
public void visit(ClosureSurface closureSurface) {
BoundarySurface surface = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.CLOSURE,
closureSurface);
handleThematicSurface(closureSurface, surface);
surfaces.add(surface);
}
public List<BoundarySurface> getSurfaces() {
return surfaces;
}
}
package de.hft.stuttgart.citydoctor2.math;
import Jama.Matrix;
import de.hft.stuttgart.citydoctor2.datastructure.*;
import de.hft.stuttgart.citydoctor2.utils.Copy;
import org.citygml4j.core.model.core.ImplicitGeometry;
import org.citygml4j.core.model.core.TransformationMatrix4x4;
import org.xmlobjects.gml.model.geometry.primitives.Point;
import org.xmlobjects.gml.model.geometry.primitives.PointProperty;
import org.xmlobjects.util.copy.CopyBuilder;
import java.util.*;
/**
* Adapter class for CityGML-TransformationMatrix4x4
*/
public class TransformationMatrix {
private final TransformationMatrix4x4 originalTM4x4;
private Matrix tMatrix;
/**
* The {@code TransformationMatrix} class is an adapter for applying the {@link TransformationMatrix4x4} of implicitGeometries to geometries
* of CityDoctor's internal model.
* @param transformationMatrix the transformation matrix.
* @param pointProperty the reference point for the translation of the geometry's position.
*/
public TransformationMatrix(TransformationMatrix4x4 transformationMatrix, PointProperty pointProperty) {
originalTM4x4 = transformationMatrix;
setupMatrix();
incorporateRefPoint(pointProperty);
}
/**
* The {@code TransformationMatrix} class is an adapter for applying the {@link TransformationMatrix4x4} of implicitGeometries to geometries
* of CityDoctor's internal model.
* @param implicitGeometry the implicitGeometry containing the TransformationMatrix and ReferencePoint.
*/
public TransformationMatrix(ImplicitGeometry implicitGeometry) {
originalTM4x4 = implicitGeometry.getTransformationMatrix();
setupMatrix();
incorporateRefPoint(implicitGeometry.getReferencePoint());
}
private void setupMatrix() {
double[][] matrix = new double[4][4];
CopyBuilder copyBuilder = new CopyBuilder();
TransformationMatrix4x4 tmMatrix = (TransformationMatrix4x4) originalTM4x4.deepCopy(copyBuilder);
List<Double> tmValues = tmMatrix.toRowMajorList();
for (int i = 0; i < 4 ; i++){
for (int j = 0; j < 4 ; j++){
matrix[i][j] = tmValues.get(i*4+j);
}
}
tMatrix = new Matrix(matrix);
}
private void incorporateRefPoint(PointProperty pointProperty) {
Point refPoint = pointProperty.getObject();
List<Double> refCoord = refPoint.getPos().toCoordinateList3D();
double [][] tArray = tMatrix.getArray();
tArray[0][3] = refCoord.get(0);
tArray[1][3] = refCoord.get(1);
tArray[2][3] = refCoord.get(2);
}
/**
* Transforms a vector with the transformation matrix.
* @param referenceGeom reference geometry to transform.
* @return A transformed copy of {@code referenceGeom}.
*/
public Geometry transformGeometry(Geometry referenceGeom) {
// Create deep copy of reference geom
Geometry geom = Copy.copy(referenceGeom);
Map<Vertex, Boolean> visitedVertices = new IdentityHashMap<>();
Set<Vertex> visitedVerticesSet = Collections.newSetFromMap(visitedVertices);
// Transform all vertices
for (Polygon polygon : geom.getPolygons()){
for (Vertex vertex : polygon.getExteriorRing().getVertices()){
if (!visitedVerticesSet.contains(vertex)){
transformVector3D(vertex);
visitedVerticesSet.add(vertex);
}
}
for (LinearRing ring : polygon.getInnerRings()){
for (Vertex vertex : ring.getVertices()){
if (!visitedVerticesSet.contains(vertex)){
transformVector3D(vertex);
visitedVerticesSet.add(vertex);
}
}
}
}
geom.updateEdgesAndVertices();
return geom;
}
public void transformVector3D(Vector3d vector) {
double[] tfVector = new double[]{vector.getX(), vector.getY(), vector.getZ(), 1d};
Matrix vectorMatrix = new Matrix(tfVector,4);
Matrix res = tMatrix.times(vectorMatrix);
double[] resultVector = res.getRowPackedCopy();
vector.setX(resultVector[0]);
vector.setY(resultVector[1]);
vector.setZ(resultVector[2]);
}
}
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