/*- * 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 * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CityDoctor2 is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with CityDoctor2. If not, see . */ package de.hft.stuttgart.citydoctor2.datastructure; import java.util.ArrayList; import java.util.List; import org.citygml4j.factory.GMLGeometryFactory; import org.citygml4j.model.citygml.core.AbstractCityObject; import org.citygml4j.model.gml.geometry.aggregates.MultiSurface; import org.citygml4j.model.gml.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; /** * Representing a boundary surface in CityGML * * @author Matthias Betz * */ public class BoundarySurface extends CityObject { private static final long serialVersionUID = 8793865135393496408L; private SurfaceFeatureType featureType; private BoundarySurfaceType type; private List openings; private CityObject parent; private AbstractCityObject gmlObject; public BoundarySurface(AbstractCityObject aco) { this(SurfaceFeatureType.BUILDING, BoundarySurfaceType.UNDEFINED, aco); } @Override public CityObject copy() { throw new UnsupportedOperationException("Cannot copy BoundarySurface"); } public BoundarySurface(SurfaceFeatureType featureType, BoundarySurfaceType type, AbstractCityObject aco) { this.featureType = featureType; this.type = type; gmlObject = aco; openings = new ArrayList<>(2); } public void setFeatureType(SurfaceFeatureType featureType) { this.featureType = featureType; } public void setType(BoundarySurfaceType type) { this.type = type; } public void setGmlObject(AbstractCityObject gmlObject) { this.gmlObject = gmlObject; } public SurfaceFeatureType getSurfaceFeatureType() { return featureType; } public BoundarySurfaceType getType() { return type; } public List getOpenings() { return openings; } @Override public void reCreateGeometries(GMLGeometryFactory factory, ParserConfiguration config) { if (!gmlObject.isSetId()) { gmlObject.setId(getGmlId().getGmlString()); } for (Geometry geom : getGeometries()) { if (geom.getType() == GeometryType.MULTI_SURFACE) { MultiSurface ms = CityGmlUtils.createMultiSurface(geom, factory, config); setGeometryAccordingToLod(geom.getLod(), new MultiSurfaceProperty(ms)); } else { throw new IllegalStateException("BoundarySurfaces can only have MultiSurface geometries"); } } for (Opening o : openings) { o.reCreateGeometries(factory, config); } } private void setGeometryAccordingToLod(Lod lod, MultiSurfaceProperty ms) { switch (lod) { case LOD2: setLod2Ms(ms); break; case LOD3: setLod3Ms(ms); break; case LOD4: setLod4Ms(ms); break; default: throw new IllegalStateException("Found geometry with LOD other than LOD2," + " LOD3, LOD4, which is illegal for BoundarySurfaces: " + lod); } } private void setLod2Ms(MultiSurfaceProperty ms) { switch (featureType) { case BRIDGE: org.citygml4j.model.citygml.bridge.AbstractBoundarySurface bridgeAbs = (org.citygml4j.model.citygml.bridge.AbstractBoundarySurface) gmlObject; bridgeAbs.setLod2MultiSurface(ms); break; case BUILDING: org.citygml4j.model.citygml.building.AbstractBoundarySurface buildAbs = (org.citygml4j.model.citygml.building.AbstractBoundarySurface) gmlObject; buildAbs.setLod2MultiSurface(ms); break; case TUNNEL: org.citygml4j.model.citygml.tunnel.AbstractBoundarySurface tunAbs = (org.citygml4j.model.citygml.tunnel.AbstractBoundarySurface) gmlObject; tunAbs.setLod2MultiSurface(ms); } } private void setLod3Ms(MultiSurfaceProperty ms) { switch (featureType) { case BRIDGE: org.citygml4j.model.citygml.bridge.AbstractBoundarySurface bridgeAbs = (org.citygml4j.model.citygml.bridge.AbstractBoundarySurface) gmlObject; bridgeAbs.setLod3MultiSurface(ms); break; case BUILDING: org.citygml4j.model.citygml.building.AbstractBoundarySurface buildAbs = (org.citygml4j.model.citygml.building.AbstractBoundarySurface) gmlObject; buildAbs.setLod3MultiSurface(ms); break; case TUNNEL: org.citygml4j.model.citygml.tunnel.AbstractBoundarySurface tunAbs = (org.citygml4j.model.citygml.tunnel.AbstractBoundarySurface) gmlObject; tunAbs.setLod3MultiSurface(ms); } } private void setLod4Ms(MultiSurfaceProperty ms) { switch (featureType) { case BRIDGE: org.citygml4j.model.citygml.bridge.AbstractBoundarySurface bridgeAbs = (org.citygml4j.model.citygml.bridge.AbstractBoundarySurface) gmlObject; bridgeAbs.setLod4MultiSurface(ms); break; case BUILDING: org.citygml4j.model.citygml.building.AbstractBoundarySurface buildAbs = (org.citygml4j.model.citygml.building.AbstractBoundarySurface) gmlObject; buildAbs.setLod4MultiSurface(ms); break; case TUNNEL: org.citygml4j.model.citygml.tunnel.AbstractBoundarySurface tunAbs = (org.citygml4j.model.citygml.tunnel.AbstractBoundarySurface) gmlObject; tunAbs.setLod4MultiSurface(ms); } } @Override public void clearAllContainedCheckResults() { super.clearAllContainedCheckResults(); for (Opening o : openings) { o.clearAllContainedCheckResults(); } } @Override public void collectContainedErrors(List errors) { super.collectContainedErrors(errors); for (Opening o : openings) { o.collectContainedErrors(errors); } } @Override public boolean containsAnyError() { boolean hasError = super.containsAnyError(); if (hasError) { return true; } for (Opening o : openings) { if (o.containsAnyError()) { return true; } } return false; } @Override public boolean containsError(CheckId checkIdentifier) { boolean hasError = super.containsError(checkIdentifier); if (hasError) { return true; } for (Opening o : openings) { if (o.containsError(checkIdentifier)) { return true; } } return false; } @Override public void accept(Check c) { super.accept(c); if (c.canExecute(this)) { c.check(this); } for (Opening o : openings) { o.accept(c); } } public void setParent(CityObject parent) { this.parent = parent; } public CityObject getParent() { return parent; } public void unsetGmlGeometries() { switch (featureType) { case BRIDGE: org.citygml4j.model.citygml.bridge.AbstractBoundarySurface bridgeAbs = (org.citygml4j.model.citygml.bridge.AbstractBoundarySurface) gmlObject; bridgeAbs.unsetLod2MultiSurface(); bridgeAbs.unsetLod3MultiSurface(); bridgeAbs.unsetLod4MultiSurface(); break; case BUILDING: org.citygml4j.model.citygml.building.AbstractBoundarySurface buildAbs = (org.citygml4j.model.citygml.building.AbstractBoundarySurface) gmlObject; buildAbs.unsetLod2MultiSurface(); buildAbs.unsetLod3MultiSurface(); buildAbs.unsetLod4MultiSurface(); break; case TUNNEL: org.citygml4j.model.citygml.tunnel.AbstractBoundarySurface tunAbs = (org.citygml4j.model.citygml.tunnel.AbstractBoundarySurface) gmlObject; tunAbs.unsetLod2MultiSurface(); tunAbs.unsetLod3MultiSurface(); tunAbs.unsetLod4MultiSurface(); } for (Opening o : openings) { o.unsetGmlGeometries(); } } @Override public String toString() { return "BoundarySurface [type=" + type + ", id=" + getGmlId() + "]"; } void anonymize() { gmlObject.unsetAppearance(); gmlObject.unsetBoundedBy(); gmlObject.unsetCreationDate(); gmlObject.unsetDescription(); gmlObject.unsetExternalReference(); gmlObject.unsetGeneralizesTo(); gmlObject.unsetGenericADEElement(); gmlObject.unsetGenericApplicationPropertyOfCityObject(); gmlObject.unsetGenericAttribute(); setGmlId(GmlId.generateId()); gmlObject.setId(getGmlId().getGmlString()); } @Override public AbstractCityObject getGmlObject() { return gmlObject; } @Override public FeatureType getFeatureType() { return FeatureType.BOUNDARY_SURFACE; } public void addOpening(Opening opening) { openings.add(opening); opening.setPartOfSurface(this); } @Override public void prepareForChecking() { super.prepareForChecking(); for (Opening o : openings) { o.prepareForChecking(); } } @Override public void clearMetaInformation() { super.clearMetaInformation(); for (Opening o : openings) { o.clearMetaInformation(); } } }