/*- * 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.Collections; 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.check.Checkable; import de.hft.stuttgart.citydoctor2.math.Vector3d; import de.hft.stuttgart.citydoctor2.tesselation.TesselatedPolygon; import de.hft.stuttgart.citydoctor2.tesselation.JoglTesselator; /** * A polygon that actually contains the rings and points representing the * geometry * * @author Matthias Betz * */ public class ConcretePolygon extends Polygon { private static final long serialVersionUID = -2208347892270418372L; private LinearRing exterior; private List innerRings; private BoundarySurface partOfSurface; private BuildingInstallation partfOfInstallation; private Geometry parent; private LinkedPolygon linkedFromPolygon; /* * (non-Javadoc) * * @see de.hft.stuttgart.citydoctor2.datastructure.Polygon#calculateNormal() */ @Override public Vector3d calculateNormalNormalized() { return exterior.calculateNormalNormalized(); } @Override public Vector3d calculateNormal() { return exterior.calculateNormal(); } /* * (non-Javadoc) * * @see de.hft.stuttgart.citydoctor2.datastructure.Polygon#tesselate() */ @Override public TesselatedPolygon tesselate() { return JoglTesselator.tesselatePolygon(this); } /* * (non-Javadoc) * * @see de.hft.stuttgart.citydoctor2.datastructure.Polygon#getExteriorRing() */ @Override public LinearRing getExteriorRing() { return exterior; } /* * (non-Javadoc) * * @see de.hft.stuttgart.citydoctor2.datastructure.Polygon#getInnerRings() */ @Override public List getInnerRings() { if (innerRings == null) { return Collections.emptyList(); } return innerRings; } /* * (non-Javadoc) * * @see * de.hft.stuttgart.citydoctor2.datastructure.Polygon#isPointInsideExteriorRing( * de.hft.stuttgart.citydoctor2.math.Vector3d) */ @Override public boolean isPointInsideExteriorRing(Vector3d v) { return exterior.isPointInside(v); } /* * (non-Javadoc) * * @see de.hft.stuttgart.citydoctor2.datastructure.Polygon#getParent() */ @Override public Geometry getParent() { return parent; } /* * (non-Javadoc) * * @see * de.hft.stuttgart.citydoctor2.datastructure.Polygon#setParent(de.hft.stuttgart * .citydoctor2.datastructure.Geometry) */ @Override public void setParent(Geometry geometry) { parent = geometry; } /* * (non-Javadoc) * * @see * de.hft.stuttgart.citydoctor2.datastructure.Polygon#setExteriorRing(de.hft. * stuttgart.citydoctor2.datastructure.LinearRing) */ @Override public void setExteriorRing(LinearRing extRing) { exterior = extRing; extRing.setParent(this); } /* * (non-Javadoc) * * @see * de.hft.stuttgart.citydoctor2.datastructure.Polygon#accept(de.hft.stuttgart. * citydoctor2.check.Check) */ @Override public void accept(Check c) { if (c.canExecute(this)) { c.check(this); } if (exterior != null) { exterior.accept(c); } if (innerRings != null) { for (LinearRing lr : innerRings) { lr.accept(c); } } setValidated(true); } @Override public Class getCheckClass() { return Polygon.class; } /* * (non-Javadoc) * * @see * de.hft.stuttgart.citydoctor2.datastructure.Polygon#isPolygonConnectedViaPoint * (de.hft.stuttgart.citydoctor2.datastructure.ConcretePolygon) */ @Override public boolean isPolygonConnectedViaPoint(Polygon other) { return exterior.isRingConnectedViaPoint(other.getExteriorRing()); } /* * (non-Javadoc) * * @see de.hft.stuttgart.citydoctor2.datastructure.Polygon#containsAnyError() */ @Override public boolean containsAnyError() { if (super.containsAnyError()) { return true; } if (exterior != null && exterior.containsAnyError()) { return true; } if (innerRings != null) { for (LinearRing lr : innerRings) { if (lr.containsAnyError()) { return true; } } } return false; } /* * (non-Javadoc) * * @see * de.hft.stuttgart.citydoctor2.datastructure.Polygon#collectContainedErrors( * java.util.List) */ @Override public void collectContainedErrors(List errors) { super.collectContainedErrors(errors); if (exterior != null) { exterior.collectContainedErrors(errors); } if (innerRings != null) { for (LinearRing lr : innerRings) { lr.collectContainedErrors(errors); } } } /* * (non-Javadoc) * * @see de.hft.stuttgart.citydoctor2.datastructure.Polygon# * clearAllContainedCheckResults() */ @Override public void clearAllContainedCheckResults() { super.clearCheckResults(); if (exterior != null) { exterior.clearAllContainedCheckResults(); } if (innerRings != null) { for (LinearRing lr : innerRings) { lr.clearAllContainedCheckResults(); } } } /* * (non-Javadoc) * * @see de.hft.stuttgart.citydoctor2.datastructure.Polygon#containsError(de.hft. * stuttgart.citydoctor2.check.CheckId) */ @Override public boolean containsError(CheckId checkIdentifier) { boolean hasError = super.containsError(checkIdentifier); if (hasError) { return true; } if (exterior.containsError(checkIdentifier)) { return true; } if (innerRings != null) { for (LinearRing lr : innerRings) { if (lr.containsError(checkIdentifier)) { return true; } } } return false; } /* * (non-Javadoc) * * @see * de.hft.stuttgart.citydoctor2.datastructure.Polygon#addInteriorRing(de.hft. * stuttgart.citydoctor2.datastructure.LinearRing) */ @Override public void addInteriorRing(LinearRing inter) { if (inter == null) { return; } if (innerRings == null) { innerRings = new ArrayList<>(2); } innerRings.add(inter); inter.setParent(this); } /* * (non-Javadoc) * * @see de.hft.stuttgart.citydoctor2.datastructure.Polygon#getPartOfSurface() */ @Override public BoundarySurface getPartOfSurface() { return partOfSurface; } /* * (non-Javadoc) * * @see * de.hft.stuttgart.citydoctor2.datastructure.Polygon#setPartOfSurface(de.hft. * stuttgart.citydoctor2.datastructure.BoundarySurface) */ @Override public void setPartOfSurface(BoundarySurface bs) { partOfSurface = bs; } @Override public void removeInnerRing(LinearRing ring) { if (innerRings == null) { return; } innerRings.remove(ring); // remove vertex association emptyRing(ring); } /* * (non-Javadoc) * * @see * de.hft.stuttgart.citydoctor2.datastructure.Polygon#setPartOfInstallation(de. * hft.stuttgart.citydoctor2.datastructure.BuildingInstallation) */ @Override public void setPartOfInstallation(BuildingInstallation bi) { partfOfInstallation = bi; } /* * (non-Javadoc) * * @see * de.hft.stuttgart.citydoctor2.datastructure.Polygon#getPartOfInstallation() */ @Override public BuildingInstallation getPartOfInstallation() { return partfOfInstallation; } /* * (non-Javadoc) * * @see de.hft.stuttgart.citydoctor2.datastructure.Polygon#toString() */ @Override public String toString() { return "Polygon [id=" + getGmlId() + "]"; } @Override void anonymize() { setGmlId(GmlId.generateId()); exterior.anonymize(); if (innerRings != null) { for (LinearRing lr : innerRings) { lr.anonymize(); } } } /* * (non-Javadoc) * * @see * de.hft.stuttgart.citydoctor2.datastructure.Polygon#hasPointAsCorner(de.hft. * stuttgart.citydoctor2.datastructure.Vertex) */ @Override public boolean hasPointAsCorner(Vertex v) { boolean hasPoint = exterior.hasPointAsCorner(v); if (hasPoint) { return true; } if (innerRings != null) { for (LinearRing lr : innerRings) { if (lr.hasPointAsCorner(v)) { return true; } } } return false; } /* * (non-Javadoc) * * @see de.hft.stuttgart.citydoctor2.datastructure.Polygon#removeRings() */ @Override public void removeRings() { emptyRing(exterior); exterior = null; clearInteriorRings(); } private void clearInteriorRings() { if (innerRings == null) { return; } for (LinearRing lr : innerRings) { emptyRing(lr); } innerRings.clear(); } private void emptyRing(LinearRing lr) { if (isLinkedTo()) { Geometry geom2 = linkedFromPolygon.getParent(); for (Vertex v : lr.getVertices()) { v.removeAdjacency(lr, geom2); } } for (Vertex v : lr.getVertices()) { v.removeAdjacency(lr, parent); } } @Override public boolean isLinkedTo() { return linkedFromPolygon != null; } @Override public LinkedPolygon getLinkedFromPolygon() { return linkedFromPolygon; } @Override public boolean isLink() { return false; } @Override public ConcretePolygon getOriginal() { return this; } void setLinkedTo(LinkedPolygon linkedPolygon) { linkedFromPolygon = linkedPolygon; } @Override public void prepareForChecking() { parent.prepareForChecking(); } @Override public void clearMetaInformation() { parent.clearMetaInformation(); } }