/*-
* 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 extends Checkable> 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();
}
}