Commit 02de0a22 authored by Riegel's avatar Riegel
Browse files

Reformat code

parent ad3589e8
Pipeline #10297 passed with stage
in 1 minute and 5 seconds
...@@ -11,12 +11,18 @@ import de.hft.stuttgart.citydoctor2.utils.CopyHandler; ...@@ -11,12 +11,18 @@ import de.hft.stuttgart.citydoctor2.utils.CopyHandler;
import de.hft.stuttgart.citydoctor2.utils.Copyable; import de.hft.stuttgart.citydoctor2.utils.Copyable;
import java.io.Serial; import java.io.Serial;
import java.util.*; import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/** /**
* Dataholding class for parsing and resolving of CompositeSurfaces. * Pseudo-abstract polygon class for parsing and resolving of CompositeSurfaces and references to them.
* <p>CompositePolygons have no exterior or interior LinearRings themselves and need to be filtered out from
* the polygons of a CityObject geometry before further processing steps.
*
* @author Riegel
*/ */
public final class CompositePolygon extends ConcretePolygon{ public final class CompositePolygon extends ConcretePolygon {
@Serial @Serial
private static final long serialVersionUID = -1867197873443341287L; private static final long serialVersionUID = -1867197873443341287L;
...@@ -32,7 +38,8 @@ public final class CompositePolygon extends ConcretePolygon{ ...@@ -32,7 +38,8 @@ public final class CompositePolygon extends ConcretePolygon{
} }
@Override @Override
public void accept(Check c){} public void accept(Check c) {
}
@Override @Override
public Class<? extends Checkable> getCheckClass() { public Class<? extends Checkable> getCheckClass() {
...@@ -40,24 +47,25 @@ public final class CompositePolygon extends ConcretePolygon{ ...@@ -40,24 +47,25 @@ public final class CompositePolygon extends ConcretePolygon{
} }
@Override @Override
public boolean containsAnyError(){ public boolean containsAnyError() {
return false; return false;
} }
@Override @Override
public void collectContainedErrors(List<CheckError> errors) {} public void collectContainedErrors(List<CheckError> errors) {
}
@Override @Override
public void clearAllContainedCheckResults() { public void clearAllContainedCheckResults() {
} }
public void addCompositeMember(ConcretePolygon p){ public void addCompositeMember(ConcretePolygon p) {
compositeMembers.add(p); compositeMembers.add(p);
p.setPartOfComposite(this); p.setPartOfComposite(this);
} }
public List<ConcretePolygon> getCompositeMembers(){ public List<ConcretePolygon> getCompositeMembers() {
return compositeMembers; return compositeMembers;
} }
...@@ -67,7 +75,6 @@ public final class CompositePolygon extends ConcretePolygon{ ...@@ -67,7 +75,6 @@ public final class CompositePolygon extends ConcretePolygon{
} }
@Override @Override
public Vector3d calculateNormal() { public Vector3d calculateNormal() {
return compositeMembers.get(0).calculateNormal(); return compositeMembers.get(0).calculateNormal();
...@@ -76,7 +83,7 @@ public final class CompositePolygon extends ConcretePolygon{ ...@@ -76,7 +83,7 @@ public final class CompositePolygon extends ConcretePolygon{
@Override @Override
public TesselatedPolygon tesselate() { public TesselatedPolygon tesselate() {
List<Triangle3d> tessPolys = new ArrayList<>(); List<Triangle3d> tessPolys = new ArrayList<>();
return new TesselatedPolygon(tessPolys,this ); return new TesselatedPolygon(tessPolys, this);
} }
@Override @Override
...@@ -190,7 +197,6 @@ public final class CompositePolygon extends ConcretePolygon{ ...@@ -190,7 +197,6 @@ public final class CompositePolygon extends ConcretePolygon{
} }
@Override @Override
public void collectInstances(CopyHandler handler) { public void collectInstances(CopyHandler handler) {
......
...@@ -53,9 +53,7 @@ public class ConcretePolygon extends Polygon { ...@@ -53,9 +53,7 @@ public class ConcretePolygon extends Polygon {
private Geometry parent; private Geometry parent;
private LinkedPolygon linkedFromPolygon; private LinkedPolygon linkedFromPolygon;
public ConcretePolygon() { public ConcretePolygon() {}
// TODO Auto-generated constructor stub
}
/* /*
* (non-Javadoc) * (non-Javadoc)
......
/*- /*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
* *
* This file is part of CityDoctor2. * This file is part of CityDoctor2.
* *
* CityDoctor2 is free software: you can redistribute it and/or modify * CityDoctor2 is free software: you can redistribute it and/or modify
...@@ -18,202 +18,201 @@ ...@@ -18,202 +18,201 @@
*/ */
package de.hft.stuttgart.citydoctor2.datastructure; package de.hft.stuttgart.citydoctor2.datastructure;
import de.hft.stuttgart.citydoctor2.utils.CopyHandler;
import de.hft.stuttgart.citydoctor2.utils.Copyable;
import java.io.Serial; import java.io.Serial;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import de.hft.stuttgart.citydoctor2.utils.CopyHandler;
import de.hft.stuttgart.citydoctor2.utils.Copyable;
/** /**
* Representing an edge between two consecutive points of a linear ring * Representing an edge between two consecutive points of a linear ring
*
* @author Matthias Betz
* *
* @author Matthias Betz
*/ */
public class Edge implements Serializable, Copyable { public class Edge implements Serializable, Copyable {
@Serial @Serial
private static final long serialVersionUID = -504694863498128296L; private static final long serialVersionUID = -504694863498128296L;
private final List<Polygon> adjacentPolygons = new ArrayList<>(2); private final List<Polygon> adjacentPolygons = new ArrayList<>(2);
private final List<LinearRing> adjacentRings = new ArrayList<>(2); private final List<LinearRing> adjacentRings = new ArrayList<>(2);
private Vertex from; private Vertex from;
private Vertex to; private Vertex to;
// start with 1 for a new edge // start with 1 for a new edge
private int numberOfHalfEdges = 1; private int numberOfHalfEdges = 1;
private int numberOfOppositeHalfEdges; private int numberOfOppositeHalfEdges;
public Edge(Vertex from, Vertex to) { public Edge(Vertex from, Vertex to) {
this.from = from; this.from = from;
this.to = to; this.to = to;
} }
private Edge() { private Edge() {
} }
public Vertex getFrom() { public Vertex getFrom() {
return from; return from;
} }
public Vertex getTo() { public Vertex getTo() {
return to; return to;
} }
public void addHalfEdge(Vertex v0, Vertex v1) { public void addHalfEdge(Vertex v0, Vertex v1) {
if (v0 == null || v1 == null) { if (v0 == null || v1 == null) {
return; return;
} }
if (isPointOfEdge(v0, from) && isPointOfEdge(v1, to)) { if (isPointOfEdge(v0, from) && isPointOfEdge(v1, to)) {
numberOfHalfEdges++; numberOfHalfEdges++;
return; return;
} }
if (isPointOfEdge(v1, from) && isPointOfEdge(v0, to)) { if (isPointOfEdge(v1, from) && isPointOfEdge(v0, to)) {
numberOfOppositeHalfEdges++; numberOfOppositeHalfEdges++;
return; return;
} }
throw new IllegalStateException( throw new IllegalStateException(
"The given vertices do not form this edge\n v0=" + v0 + ", v1=" + v1 + ", edge" + this); "The given vertices do not form this edge\n v0=" + v0 + ", v1=" + v1 + ", edge" + this);
} }
private boolean isPointOfEdge(Vertex v0, Vertex edgePoint) { private boolean isPointOfEdge(Vertex v0, Vertex edgePoint) {
return v0.equals(edgePoint); return v0.equals(edgePoint);
} }
public boolean formedByIgnoreDirection(Vertex v1, Vertex v2) { public boolean formedByIgnoreDirection(Vertex v1, Vertex v2) {
return (v1 == from && v2 == to) || (v1 == to && v2 == from); return (v1 == from && v2 == to) || (v1 == to && v2 == from);
} }
public boolean equalsIgnoreDirection(Edge other) { public boolean equalsIgnoreDirection(Edge other) {
return (other.from.equals(from) && other.to.equals(to)) || (other.from.equals(to) && other.to.equals(from)); return (other.from.equals(from) && other.to.equals(to)) || (other.from.equals(to) && other.to.equals(from));
} }
public int getNumberOfHalfEdges() { public int getNumberOfHalfEdges() {
return numberOfHalfEdges; return numberOfHalfEdges;
} }
public int getNumberOppositeHalfEdges() { public int getNumberOppositeHalfEdges() {
return numberOfOppositeHalfEdges; return numberOfOppositeHalfEdges;
} }
public int getNumberOfAllHalfEdges() { public int getNumberOfAllHalfEdges() {
return numberOfHalfEdges + numberOfOppositeHalfEdges; return numberOfHalfEdges + numberOfOppositeHalfEdges;
} }
public List<Polygon> getAdjacentPolygons() { public List<Polygon> getAdjacentPolygons() {
return adjacentPolygons; return adjacentPolygons;
} }
public List<LinearRing> getAdjacentRings() { public List<LinearRing> getAdjacentRings() {
return adjacentRings; return adjacentRings;
} }
@Override @Override
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;
int result = 1; int result = 1;
result = prime * result + ((from == null) ? 0 : from.hashCode()); result = prime * result + ((from == null) ? 0 : from.hashCode());
result = prime * result + ((to == null) ? 0 : to.hashCode()); result = prime * result + ((to == null) ? 0 : to.hashCode());
return result; return result;
} }
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (this == obj) { if (this == obj) {
return true; return true;
} }
if (obj == null) { if (obj == null) {
return false; return false;
} }
if (getClass() != obj.getClass()) { if (getClass() != obj.getClass()) {
return false; return false;
} }
Edge other = (Edge) obj; Edge other = (Edge) obj;
if (from == null) { if (from == null) {
if (other.from != null) { if (other.from != null) {
return false; return false;
} }
} else if (!from.equals(other.from)) { } else if (!from.equals(other.from)) {
return false; return false;
} }
if (to == null) { if (to == null) {
return other.to == null; return other.to == null;
} else return to.equals(other.to); } else return to.equals(other.to);
} }
public void addAdjacentPolygon(Polygon p) { public void addAdjacentPolygon(Polygon p) {
adjacentPolygons.add(p); adjacentPolygons.add(p);
} }
public void addAdjacentRing(LinearRing lr) { public void addAdjacentRing(LinearRing lr) {
adjacentRings.add(lr); adjacentRings.add(lr);
} }
@Override @Override
public String toString() { public String toString() {
return "Edge [from=" + from + ", to=" + to + "]"; return "Edge [from=" + from + ", to=" + to + "]";
} }
public boolean contains(Vertex v) { public boolean contains(Vertex v) {
return v == from || v == to; return v == from || v == to;
} }
public Vertex getConnectionPoint(Edge e) { public Vertex getConnectionPoint(Edge e) {
if (from == e.getTo() || from == e.getFrom()) { if (from == e.getTo() || from == e.getFrom()) {
return from; return from;
} }
if (to == e.getTo() || to == e.getFrom()) { if (to == e.getTo() || to == e.getFrom()) {
return to; return to;
} }
return null; return null;
} }
/** /**
* finds the point on the other end of the edge if the given vertex is one of * finds the point on the other end of the edge if the given vertex is one of
* the end points. * the end points.
* *
* @param c the given vertex * @param c the given vertex
* @return the opposite vertex or null if the given vertex is not an end point. * @return the opposite vertex or null if the given vertex is not an end point.
*/ */
public Vertex getOppositeVertex(Vertex c) { public Vertex getOppositeVertex(Vertex c) {
if (c == from) { if (c == from) {
return to; return to;
} }
if (c == to) { if (c == to) {
return from; return from;
} }
return null; return null;
} }
@Override @Override
public void collectInstances(CopyHandler handler) { public void collectInstances(CopyHandler handler) {
handler.addInstance(from); handler.addInstance(from);
handler.addInstance(to); handler.addInstance(to);
handler.addInstance(adjacentPolygons); handler.addInstance(adjacentPolygons);
handler.addInstance(adjacentRings); handler.addInstance(adjacentRings);
} }
@Override @Override
public Copyable createCopyInstance() { public Copyable createCopyInstance() {
return new Edge(); return new Edge();
} }
@Override @Override
public void fillValues(Copyable original, CopyHandler handler) { public void fillValues(Copyable original, CopyHandler handler) {
Edge originalEdge = (Edge) original; Edge originalEdge = (Edge) original;
from = handler.getCopyInstance(originalEdge.from); from = handler.getCopyInstance(originalEdge.from);
to = handler.getCopyInstance(originalEdge.to); to = handler.getCopyInstance(originalEdge.to);
numberOfHalfEdges = originalEdge.numberOfHalfEdges; numberOfHalfEdges = originalEdge.numberOfHalfEdges;
numberOfOppositeHalfEdges = originalEdge.numberOfOppositeHalfEdges; numberOfOppositeHalfEdges = originalEdge.numberOfOppositeHalfEdges;
for (Polygon originalPoly : originalEdge.adjacentPolygons) { for (Polygon originalPoly : originalEdge.adjacentPolygons) {
adjacentPolygons.add(handler.getCopyInstance(originalPoly)); adjacentPolygons.add(handler.getCopyInstance(originalPoly));
} }
for (LinearRing originalRing : originalEdge.adjacentRings) { for (LinearRing originalRing : originalEdge.adjacentRings) {
adjacentRings.add(handler.getCopyInstance(originalRing)); adjacentRings.add(handler.getCopyInstance(originalRing));
} }
} }
} }
/*- /*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
* *
* This file is part of CityDoctor2. * This file is part of CityDoctor2.
* *
* CityDoctor2 is free software: you can redistribute it and/or modify * CityDoctor2 is free software: you can redistribute it and/or modify
...@@ -20,13 +20,12 @@ package de.hft.stuttgart.citydoctor2.datastructure; ...@@ -20,13 +20,12 @@ package de.hft.stuttgart.citydoctor2.datastructure;
/** /**
* Possible feature types in CityGML * Possible feature types in CityGML
*
* @author Matthias Betz
* *
* @author Matthias Betz
*/ */
public enum FeatureType { public enum FeatureType {
BUILDING, TRANSPORTATION, VEGETATION, BRIDGE, LAND, WATER, BOUNDARY_SURFACE, INSTALLATION, OPENING, BUILDING, TRANSPORTATION, VEGETATION, BRIDGE, LAND, WATER, BOUNDARY_SURFACE, INSTALLATION, OPENING,
BUILDING_PART, BUILDING_SUBDIVISION, BRIDGE_CONSTRUCTION_ELEMENT, BRIDGE_INSTALLATION, ROOM, FURNITURE, CITY_FURNITURE, BUILDING_PART, BUILDING_SUBDIVISION, BRIDGE_CONSTRUCTION_ELEMENT, BRIDGE_INSTALLATION, ROOM, FURNITURE, CITY_FURNITURE,
GENERIC_CITY_OBJECT, TUNNEL, TUNNEL_PART GENERIC_CITY_OBJECT, TUNNEL, TUNNEL_PART
} }
...@@ -24,7 +24,7 @@ import java.util.List; ...@@ -24,7 +24,7 @@ import java.util.List;
/** /**
* *
*/ */
public class GenericCityObject extends CityObject{ public class GenericCityObject extends CityObject {
@Serial @Serial
private static final long serialVersionUID = 5886527664552294353L; private static final long serialVersionUID = 5886527664552294353L;
...@@ -49,7 +49,7 @@ public class GenericCityObject extends CityObject{ ...@@ -49,7 +49,7 @@ public class GenericCityObject extends CityObject{
@Override @Override
public void reCreateGeometries(GeometryFactory factory, ParserConfiguration config) { public void reCreateGeometries(GeometryFactory factory, ParserConfiguration config) {
for (Geometry geom : getGeometries()) { for (Geometry geom : getGeometries()) {
if (geom instanceof ImplicitGeometryHolder){ if (geom instanceof ImplicitGeometryHolder) {
continue; continue;
} }
if (geom.getType() == GeometryType.MULTI_SURFACE) { if (geom.getType() == GeometryType.MULTI_SURFACE) {
...@@ -213,7 +213,7 @@ public class GenericCityObject extends CityObject{ ...@@ -213,7 +213,7 @@ public class GenericCityObject extends CityObject{
} }
} }
public void setGmlObject(org.citygml4j.core.model.generics.GenericOccupiedSpace gos){ public void setGmlObject(org.citygml4j.core.model.generics.GenericOccupiedSpace gos) {
this.cgmlGos = gos; this.cgmlGos = gos;
} }
......
/*- /*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
* *
* This file is part of CityDoctor2. * This file is part of CityDoctor2.
* *
* CityDoctor2 is free software: you can redistribute it and/or modify * CityDoctor2 is free software: you can redistribute it and/or modify
...@@ -18,16 +18,6 @@ ...@@ -18,16 +18,6 @@
*/ */
package de.hft.stuttgart.citydoctor2.datastructure; package de.hft.stuttgart.citydoctor2.datastructure;
import java.io.Serial;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.Set;
import de.hft.stuttgart.citydoctor2.check.Check; import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.CheckError; import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.CheckId; import de.hft.stuttgart.citydoctor2.check.CheckId;
...@@ -39,420 +29,423 @@ import de.hft.stuttgart.citydoctor2.utils.CopyHandler; ...@@ -39,420 +29,423 @@ import de.hft.stuttgart.citydoctor2.utils.CopyHandler;
import de.hft.stuttgart.citydoctor2.utils.Copyable; import de.hft.stuttgart.citydoctor2.utils.Copyable;
import de.hft.stuttgart.citydoctor2.utils.SerializablePair; import de.hft.stuttgart.citydoctor2.utils.SerializablePair;
import java.io.Serial;
import java.util.*;
import java.util.Map.Entry;
/** /**
* Representation of a geometry containing the polygons and edges * Representation of a geometry containing the polygons and edges
*
* @author Matthias Betz
* *
* @author Matthias Betz
*/ */
public class Geometry extends GmlElement { public class Geometry extends GmlElement {
private static final String FAILED_REMOVING_POLYGON = "Removing polygon %s but polygon is not in geometry"; private static final String FAILED_REMOVING_POLYGON = "Removing polygon %s but polygon is not in geometry";
@Serial @Serial
private static final long serialVersionUID = 2539031030917731575L; private static final long serialVersionUID = 2539031030917731575L;
private static final Random r = new Random(); private static final Random r = new Random();
private GeometryType type; private GeometryType type;
private final Lod lod; private final Lod lod;
private CityObject parent; private CityObject parent;
private final List<Polygon> polygons = new ArrayList<>(2); private final List<Polygon> polygons = new ArrayList<>(2);
private List<Edge> edges; private List<Edge> edges;
private Map<SerializablePair<Vertex, Vertex>, Edge> edgeMap; private Map<SerializablePair<Vertex, Vertex>, Edge> edgeMap;
private List<Vertex> vertices; private List<Vertex> vertices;
public Geometry(GeometryType type, Lod lod) { public Geometry(GeometryType type, Lod lod) {
this.lod = lod; this.lod = lod;
this.type = type; this.type = type;
} }
void setParent(CityObject parent) { void setParent(CityObject parent) {
this.parent = parent; this.parent = parent;
} }
public CityObject getParent() { public CityObject getParent() {
return parent; return parent;
} }
public void setType(GeometryType type) { public void setType(GeometryType type) {
this.type = type; this.type = type;
} }
public GeometryType getType() { public GeometryType getType() {
return type; return type;
} }
public Lod getLod() { public Lod getLod() {
return lod; return lod;
} }
public List<Polygon> getPolygons() { public List<Polygon> getPolygons() {
return polygons; return polygons;
} }
public void addPolygon(Polygon cdPoly) { public void addPolygon(Polygon cdPoly) {
polygons.add(cdPoly); polygons.add(cdPoly);
cdPoly.setParent(this); cdPoly.setParent(this);
// set part of boundary surface or building installation or both // set part of boundary surface or building installation or both
if (parent instanceof BoundarySurface bs) { if (parent instanceof BoundarySurface bs) {
cdPoly.setPartOfSurface(bs); cdPoly.setPartOfSurface(bs);
if (bs.getParent() instanceof Installation bi) { if (bs.getParent() instanceof Installation bi) {
cdPoly.setPartOfInstallation(bi); cdPoly.setPartOfInstallation(bi);
} }
} else if (parent instanceof Installation bi) { } else if (parent instanceof Installation bi) {
cdPoly.setPartOfInstallation(bi); cdPoly.setPartOfInstallation(bi);
} }
} }
public void updateEdges() { public void updateEdges() {
edges = new ArrayList<>(); edges = new ArrayList<>();
edgeMap = new HashMap<>(); edgeMap = new HashMap<>();
Map<Edge, Edge> duplicacyMap = new HashMap<>(); Map<Edge, Edge> duplicacyMap = new HashMap<>();
for (Polygon p : polygons) { for (Polygon p : polygons) {
LinearRing extRing = p.getExteriorRing(); LinearRing extRing = p.getExteriorRing();
createEdgesFromRing(duplicacyMap, p, extRing); createEdgesFromRing(duplicacyMap, p, extRing);
for (LinearRing inner : p.getInnerRings()) { for (LinearRing inner : p.getInnerRings()) {
createEdgesFromRing(duplicacyMap, p, inner); createEdgesFromRing(duplicacyMap, p, inner);
} }
} }
} }
void anonymize() { void anonymize() {
setGmlId(GmlId.generateId()); setGmlId(GmlId.generateId());
for (Polygon p : polygons) { for (Polygon p : polygons) {
p.anonymize(); p.anonymize();
} }
double minX = Double.MAX_VALUE; double minX = Double.MAX_VALUE;
double minY = Double.MAX_VALUE; double minY = Double.MAX_VALUE;
double minZ = Double.MAX_VALUE; double minZ = Double.MAX_VALUE;
for (Vertex v : vertices) { for (Vertex v : vertices) {
if (v.getX() < minX) { if (v.getX() < minX) {
minX = v.getX(); minX = v.getX();
} }
if (v.getY() < minY) { if (v.getY() < minY) {
minY = v.getY(); minY = v.getY();
} }
if (v.getZ() < minZ) { if (v.getZ() < minZ) {
minZ = v.getZ(); minZ = v.getZ();
} }
} }
double varX = r.nextDouble() * 10; double varX = r.nextDouble() * 10;
double varY = r.nextDouble() * 10; double varY = r.nextDouble() * 10;
double varZ = r.nextDouble() * 10; double varZ = r.nextDouble() * 10;
for (Vertex v : vertices) { for (Vertex v : vertices) {
v.setX(v.getX() - minX + varX); v.setX(v.getX() - minX + varX);
v.setY(v.getY() - minY + varY); v.setY(v.getY() - minY + varY);
v.setZ(v.getZ() - minZ + varZ); v.setZ(v.getZ() - minZ + varZ);
} }
} }
private void createEdgesFromRing(Map<Edge, Edge> duplicacyMap, Polygon p, LinearRing ring) { private void createEdgesFromRing(Map<Edge, Edge> duplicacyMap, Polygon p, LinearRing ring) {
if (ring == null) { if (ring == null) {
return; return;
} }
// only go to size -1 as ring should be closed // only go to size -1 as ring should be closed
for (int i = 0; i < ring.getVertices().size() - 1; i++) { for (int i = 0; i < ring.getVertices().size() - 1; i++) {
Vertex v0 = ring.getVertices().get(i); Vertex v0 = ring.getVertices().get(i);
Vertex v1 = ring.getVertices().get(i + 1); Vertex v1 = ring.getVertices().get(i + 1);
Edge tempEdge = new Edge(v0, v1); Edge tempEdge = new Edge(v0, v1);
Edge e = duplicacyMap.get(tempEdge); Edge e = duplicacyMap.get(tempEdge);
if (e == null) { if (e == null) {
// no duplicate found, enter edges // no duplicate found, enter edges
Edge oppositeEdge = new Edge(v1, v0); Edge oppositeEdge = new Edge(v1, v0);
duplicacyMap.put(tempEdge, tempEdge); duplicacyMap.put(tempEdge, tempEdge);
duplicacyMap.put(oppositeEdge, tempEdge); duplicacyMap.put(oppositeEdge, tempEdge);
e = tempEdge; e = tempEdge;
edges.add(e); edges.add(e);
edgeMap.put(new SerializablePair<>(v0, v1), e); edgeMap.put(new SerializablePair<>(v0, v1), e);
edgeMap.put(new SerializablePair<>(v1, v0), e); edgeMap.put(new SerializablePair<>(v1, v0), e);
} else { } else {
e.addHalfEdge(v0, v1); e.addHalfEdge(v0, v1);
} }
e.addAdjacentPolygon(p); e.addAdjacentPolygon(p);
e.addAdjacentRing(ring); e.addAdjacentRing(ring);
} }
} }
public Vector3d getCenter() { public Vector3d getCenter() {
return calculateBoundingBox().getCenter(); return calculateBoundingBox().getCenter();
} }
/** /**
* This will calculate two points where every other point in the geometry is * This will calculate two points where every other point in the geometry is
* between those two. If the geometry does not contain points or is null, an * between those two. If the geometry does not contain points or is null, an
* empty array is returned. This is considered an axis aligned bounding box. * empty array is returned. This is considered an axis aligned bounding box.
* Only the exterior rings of the polygons is used as inner rings should be * Only the exterior rings of the polygons is used as inner rings should be
* within the exterior or they are faulty. * within the exterior or they are faulty.
* *
* @return an array of two points. The first contains the lowest coordinates, * @return an array of two points. The first contains the lowest coordinates,
* the second contains the highest coordinates * the second contains the highest coordinates
*/ */
public BoundingBox calculateBoundingBox() { public BoundingBox calculateBoundingBox() {
return BoundingBoxCalculator.calculateBoundingBox(polygons); return BoundingBoxCalculator.calculateBoundingBox(polygons);
} }
public double calculateVolume() { public double calculateVolume() {
double sum = 0; double sum = 0;
Vector3d center = calculateBoundingBox().getCenter(); Vector3d center = calculateBoundingBox().getCenter();
for (Polygon p : polygons) { for (Polygon p : polygons) {
TesselatedPolygon tesselatedPolygon = p.tesselate(); TesselatedPolygon tesselatedPolygon = p.tesselate();
for (Triangle3d t : tesselatedPolygon.getTriangles()) { for (Triangle3d t : tesselatedPolygon.getTriangles()) {
Vector3d p1 = t.getP1().minus(center); Vector3d p1 = t.getP1().minus(center);
Vector3d p2 = t.getP2().minus(center); Vector3d p2 = t.getP2().minus(center);
Vector3d p3 = t.getP3().minus(center); Vector3d p3 = t.getP3().minus(center);
sum += det(p1.getCoordinates(), p2.getCoordinates(), p3.getCoordinates()); sum += det(p1.getCoordinates(), p2.getCoordinates(), p3.getCoordinates());
} }
} }
return sum / 6d; return sum / 6d;
} }
private double det(double[] a, double[] b, double[] c) { private double det(double[] a, double[] b, double[] c) {
return -c[0] * b[1] * a[2] + b[0] * c[1] * a[2] + c[0] * a[1] * b[2] - a[0] * c[1] * b[2] - b[0] * a[1] * c[2] return -c[0] * b[1] * a[2] + b[0] * c[1] * a[2] + c[0] * a[1] * b[2] - a[0] * c[1] * b[2] - b[0] * a[1] * c[2]
+ a[0] * b[1] * c[2]; + a[0] * b[1] * c[2];
} }
@Override @Override
public boolean containsError(CheckId checkIdentifier) { public boolean containsError(CheckId checkIdentifier) {
boolean hasError = super.containsError(checkIdentifier); boolean hasError = super.containsError(checkIdentifier);
if (hasError) { if (hasError) {
return true; return true;
} }
for (Polygon p : polygons) { for (Polygon p : polygons) {
if (p.containsError(checkIdentifier)) { if (p.containsError(checkIdentifier)) {
return true; return true;
} }
} }
return false; return false;
} }
@Override @Override
public void clearAllContainedCheckResults() { public void clearAllContainedCheckResults() {
super.clearCheckResults(); super.clearCheckResults();
for (Polygon p : polygons) { for (Polygon p : polygons) {
p.clearAllContainedCheckResults(); p.clearAllContainedCheckResults();
} }
} }
@Override @Override
public void collectContainedErrors(List<CheckError> errors) { public void collectContainedErrors(List<CheckError> errors) {
super.collectContainedErrors(errors); super.collectContainedErrors(errors);
for (Polygon p : polygons) { for (Polygon p : polygons) {
p.collectContainedErrors(errors); p.collectContainedErrors(errors);
} }
} }
@Override @Override
public boolean containsAnyError() { public boolean containsAnyError() {
boolean hasError = super.containsAnyError(); boolean hasError = super.containsAnyError();
if (hasError) { if (hasError) {
return true; return true;
} }
for (Polygon p : polygons) { for (Polygon p : polygons) {
if (p.containsAnyError()) { if (p.containsAnyError()) {
return true; return true;
} }
} }
return false; return false;
} }
@Override @Override
public void accept(Check c) { public void accept(Check c) {
super.accept(c); super.accept(c);
if (c.canExecute(this)) { if (c.canExecute(this)) {
c.check(this); c.check(this);
} }
for (Polygon p : polygons) { for (Polygon p : polygons) {
p.accept(c); p.accept(c);
} }
} }
@Override @Override
public String toString() { public String toString() {
return "Geometry [type=" + type + ", lod=" + lod + ", id=" + getGmlId() + "]"; return "Geometry [type=" + type + ", lod=" + lod + ", id=" + getGmlId() + "]";
} }
public List<Vertex> getVertices() { public List<Vertex> getVertices() {
return vertices; return vertices;
} }
public List<Edge> getEdges() { public List<Edge> getEdges() {
return edges; return edges;
} }
public List<Edge> getEdgesAdjacentTo(Vertex v) { public List<Edge> getEdgesAdjacentTo(Vertex v) {
List<Edge> adjacentEdges = new ArrayList<>(); List<Edge> adjacentEdges = new ArrayList<>();
for (Edge e : edges) { for (Edge e : edges) {
if (e.getFrom() == v || e.getTo() == v) { if (e.getFrom() == v || e.getTo() == v) {
adjacentEdges.add(e); adjacentEdges.add(e);
} }
} }
return adjacentEdges; return adjacentEdges;
} }
public Edge getEdge(Vertex v1, Vertex v2) { public Edge getEdge(Vertex v1, Vertex v2) {
return edgeMap.get(new SerializablePair<>(v1, v2)); return edgeMap.get(new SerializablePair<>(v1, v2));
} }
public void updateEdgesAndVertices() { public void updateEdgesAndVertices() {
updateVertices(); updateVertices();
updateEdges(); updateEdges();
} }
public void updateVertices() { public void updateVertices() {
Set<Vertex> vertexSet = new HashSet<>(); Set<Vertex> vertexSet = new HashSet<>();
for (Polygon p : getPolygons()) { for (Polygon p : getPolygons()) {
updateRing(vertexSet, p.getExteriorRing()); updateRing(vertexSet, p.getExteriorRing());
for (LinearRing inner : p.getInnerRings()) { for (LinearRing inner : p.getInnerRings()) {
updateRing(vertexSet, inner); updateRing(vertexSet, inner);
} }
} }
vertices = new ArrayList<>(vertexSet); vertices = new ArrayList<>(vertexSet);
} }
private void updateRing(Set<Vertex> vertexSet, LinearRing ring) { private void updateRing(Set<Vertex> vertexSet, LinearRing ring) {
if (ring == null) { if (ring == null) {
return; return;
} }
for (Vertex v : ring.getVertices()) { for (Vertex v : ring.getVertices()) {
if (vertexSet.add(v)) { if (vertexSet.add(v)) {
// new vertex, clear adjacent rings in case new rings have been added // new vertex, clear adjacent rings in case new rings have been added
v.clearAdjacentRings(this); v.clearAdjacentRings(this);
} }
// add ring to adjacent rings of vertex // add ring to adjacent rings of vertex
v.addAdjacentRing(ring, this); v.addAdjacentRing(ring, this);
} }
} }
void removePolygon(Polygon p) { void removePolygon(Polygon p) {
p.removeRings(); p.removeRings();
if (!polygons.remove(p)) { if (!polygons.remove(p)) {
throw new IllegalStateException(String.format(FAILED_REMOVING_POLYGON, p)); throw new IllegalStateException(String.format(FAILED_REMOVING_POLYGON, p));
} }
if (p.isLink()) { if (p.isLink()) {
Polygon original = p.getOriginal(); Polygon original = p.getOriginal();
if (!original.getParent().polygons.remove(original)) { if (!original.getParent().polygons.remove(original)) {
throw new IllegalStateException(String.format(FAILED_REMOVING_POLYGON, p)); throw new IllegalStateException(String.format(FAILED_REMOVING_POLYGON, p));
} }
} else if (p.isLinkedTo()) { } else if (p.isLinkedTo()) {
Polygon link = p.getLinkedFromPolygon(); Polygon link = p.getLinkedFromPolygon();
if (!link.getParent().polygons.remove(link)) { if (!link.getParent().polygons.remove(link)) {
throw new IllegalStateException(String.format(FAILED_REMOVING_POLYGON, p)); throw new IllegalStateException(String.format(FAILED_REMOVING_POLYGON, p));
} }
} }
} }
public void replacePolygon(Polygon p, ConcretePolygon... polygons) { public void replacePolygon(Polygon p, ConcretePolygon... polygons) {
removePolygon(p); removePolygon(p);
if (p.isLink()) { if (p.isLink()) {
Geometry geom2 = p.getOriginal().getParent(); Geometry geom2 = p.getOriginal().getParent();
for (ConcretePolygon newPoly : polygons) { for (ConcretePolygon newPoly : polygons) {
geom2.addPolygon(newPoly); geom2.addPolygon(newPoly);
addPolygon(new LinkedPolygon(newPoly, this)); addPolygon(new LinkedPolygon(newPoly, this));
} }
} else if (p.isLinkedTo()) { } else if (p.isLinkedTo()) {
Geometry geom2 = p.getLinkedFromPolygon().getParent(); Geometry geom2 = p.getLinkedFromPolygon().getParent();
for (ConcretePolygon newPoly : polygons) { for (ConcretePolygon newPoly : polygons) {
addPolygon(newPoly); addPolygon(newPoly);
geom2.addPolygon(new LinkedPolygon(newPoly, geom2)); geom2.addPolygon(new LinkedPolygon(newPoly, geom2));
} }
} else { } else {
for (Polygon newPoly : polygons) { for (Polygon newPoly : polygons) {
addPolygon(newPoly); addPolygon(newPoly);
} }
} }
} }
public List<Edge> getEdgesAdjacentTo(Polygon p) { public List<Edge> getEdgesAdjacentTo(Polygon p) {
List<Edge> list = new ArrayList<>(); List<Edge> list = new ArrayList<>();
for (Edge e : edges) { for (Edge e : edges) {
if (e.getAdjacentPolygons().contains(p)) { if (e.getAdjacentPolygons().contains(p)) {
list.add(e); list.add(e);
} }
} }
return list; return list;
} }
public boolean containsPolygon(Polygon other) { public boolean containsPolygon(Polygon other) {
for (Polygon p : polygons) { for (Polygon p : polygons) {
if (p.getGmlId().equals(other.getGmlId())) { if (p.getGmlId().equals(other.getGmlId())) {
return true; return true;
} }
} }
return false; return false;
} }
@Override @Override
public void prepareForChecking() { public void prepareForChecking() {
updateEdgesAndVertices(); updateEdgesAndVertices();
} }
@Override @Override
public void clearMetaInformation() { public void clearMetaInformation() {
if (vertices != null) { if (vertices != null) {
for (Vertex v : vertices) { for (Vertex v : vertices) {
v.clearAdjacentRings(); v.clearAdjacentRings();
} }
vertices = null; vertices = null;
} }
edges = null; edges = null;
edgeMap = null; edgeMap = null;
} }
@Override @Override
public void collectInstances(CopyHandler handler) { public void collectInstances(CopyHandler handler) {
handler.addInstance(parent); handler.addInstance(parent);
handler.addInstance(polygons); handler.addInstance(polygons);
handler.addInstance(edges); handler.addInstance(edges);
handler.addInstance(vertices); handler.addInstance(vertices);
if (edgeMap != null) { if (edgeMap != null) {
for (Entry<SerializablePair<Vertex, Vertex>, Edge> e : edgeMap.entrySet()) { for (Entry<SerializablePair<Vertex, Vertex>, Edge> e : edgeMap.entrySet()) {
handler.addInstance(e.getKey().getValue0()); handler.addInstance(e.getKey().getValue0());
handler.addInstance(e.getKey().getValue1()); handler.addInstance(e.getKey().getValue1());
handler.addInstance(e.getValue()); handler.addInstance(e.getValue());
} }
} }
} }
@Override @Override
public Copyable createCopyInstance() { public Copyable createCopyInstance() {
return new Geometry(type, lod); return new Geometry(type, lod);
} }
@Override @Override
public void fillValues(Copyable original, CopyHandler handler) { public void fillValues(Copyable original, CopyHandler handler) {
super.fillValues(original, handler); super.fillValues(original, handler);
Geometry originalGeometry = (Geometry) original; Geometry originalGeometry = (Geometry) original;
for (Polygon originalPoly : originalGeometry.polygons) { for (Polygon originalPoly : originalGeometry.polygons) {
polygons.add(handler.getCopyInstance(originalPoly)); polygons.add(handler.getCopyInstance(originalPoly));
} }
if (originalGeometry.edges != null) { if (originalGeometry.edges != null) {
edges = new ArrayList<>(originalGeometry.edges.size()); edges = new ArrayList<>(originalGeometry.edges.size());
for (Edge originalEdge : originalGeometry.edges) { for (Edge originalEdge : originalGeometry.edges) {
edges.add(handler.getCopyInstance(originalEdge)); edges.add(handler.getCopyInstance(originalEdge));
} }
} }
if (originalGeometry.edgeMap != null) { if (originalGeometry.edgeMap != null) {
edgeMap = new HashMap<>(originalGeometry.edgeMap.size()); edgeMap = new HashMap<>(originalGeometry.edgeMap.size());
for (Entry<SerializablePair<Vertex, Vertex>, Edge> originalEntry : originalGeometry.edgeMap.entrySet()) { for (Entry<SerializablePair<Vertex, Vertex>, Edge> originalEntry : originalGeometry.edgeMap.entrySet()) {
Vertex copyV0 = handler.getCopyInstance(originalEntry.getKey().getValue0()); Vertex copyV0 = handler.getCopyInstance(originalEntry.getKey().getValue0());
Vertex copyV1 = handler.getCopyInstance(originalEntry.getKey().getValue1()); Vertex copyV1 = handler.getCopyInstance(originalEntry.getKey().getValue1());
SerializablePair<Vertex, Vertex> pair = new SerializablePair<>(copyV0, copyV1); SerializablePair<Vertex, Vertex> pair = new SerializablePair<>(copyV0, copyV1);
Edge copyEdge = handler.getCopyInstance(originalEntry.getValue()); Edge copyEdge = handler.getCopyInstance(originalEntry.getValue());
edgeMap.put(pair, copyEdge); edgeMap.put(pair, copyEdge);
} }
} }
if (originalGeometry.vertices != null) { if (originalGeometry.vertices != null) {
vertices = new ArrayList<>(originalGeometry.vertices.size()); vertices = new ArrayList<>(originalGeometry.vertices.size());
for (Vertex originalVertex : originalGeometry.vertices) { for (Vertex originalVertex : originalGeometry.vertices) {
vertices.add(handler.getCopyInstance(originalVertex)); vertices.add(handler.getCopyInstance(originalVertex));
} }
} }
parent = handler.getCopyInstance(originalGeometry.parent); parent = handler.getCopyInstance(originalGeometry.parent);
} }
} }
/*- /*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
* *
* This file is part of CityDoctor2. * This file is part of CityDoctor2.
* *
* CityDoctor2 is free software: you can redistribute it and/or modify * CityDoctor2 is free software: you can redistribute it and/or modify
...@@ -20,12 +20,11 @@ package de.hft.stuttgart.citydoctor2.datastructure; ...@@ -20,12 +20,11 @@ package de.hft.stuttgart.citydoctor2.datastructure;
/** /**
* Available geometry types * Available geometry types
*
* @author Matthias Betz
* *
* @author Matthias Betz
*/ */
public enum GeometryType { public enum GeometryType {
MULTI_SURFACE, SOLID, COMPOSITE_SURFACE MULTI_SURFACE, SOLID, COMPOSITE_SURFACE
} }
/*- /*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
* *
* This file is part of CityDoctor2. * This file is part of CityDoctor2.
* *
* CityDoctor2 is free software: you can redistribute it and/or modify * CityDoctor2 is free software: you can redistribute it and/or modify
...@@ -26,38 +26,37 @@ import java.io.Serial; ...@@ -26,38 +26,37 @@ import java.io.Serial;
/** /**
* A general GML element that has a gml id * A general GML element that has a gml id
*
* @author Matthias Betz
* *
* @author Matthias Betz
*/ */
public abstract class GmlElement extends Checkable implements Copyable { public abstract class GmlElement extends Checkable implements Copyable {
@Serial @Serial
private static final long serialVersionUID = -3242505393303017359L; private static final long serialVersionUID = -3242505393303017359L;
private GmlId gmlId; private GmlId gmlId;
public void setGmlId(GmlId id) { public void setGmlId(GmlId id) {
gmlId = id; gmlId = id;
} }
@Override @Override
public GmlId getGmlId() { public GmlId getGmlId() {
if (gmlId == null) { if (gmlId == null) {
gmlId = GmlId.generateId(); gmlId = GmlId.generateId();
} }
return gmlId; return gmlId;
} }
public boolean hasExistingGmlId() { public boolean hasExistingGmlId() {
return gmlId != null && !gmlId.isGenerated(); return gmlId != null && !gmlId.isGenerated();
} }
@Override @Override
public void fillValues(Copyable original, CopyHandler handler) { public void fillValues(Copyable original, CopyHandler handler) {
GmlElement originalElement = (GmlElement) original; GmlElement originalElement = (GmlElement) original;
// generate gml id before copying // generate gml id before copying
gmlId = originalElement.getGmlId(); gmlId = originalElement.getGmlId();
} }
} }
/*- /*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
* *
* This file is part of CityDoctor2. * This file is part of CityDoctor2.
* *
* CityDoctor2 is free software: you can redistribute it and/or modify * CityDoctor2 is free software: you can redistribute it and/or modify
...@@ -25,83 +25,82 @@ import java.util.concurrent.atomic.AtomicInteger; ...@@ -25,83 +25,82 @@ import java.util.concurrent.atomic.AtomicInteger;
/** /**
* Represents a GML id. Additionally contains information whether this id was * Represents a GML id. Additionally contains information whether this id was
* generated by city doctor * generated by city doctor
*
* @author Matthias Betz
* *
* @author Matthias Betz
*/ */
public class GmlId implements Serializable { public class GmlId implements Serializable {
@Serial @Serial
private static final long serialVersionUID = 4273817255150972966L; private static final long serialVersionUID = 4273817255150972966L;
/* prefixes for generation */ /* prefixes for generation */
private static final String GENERAL_GEN = "CityDoctor_%d_%d"; private static final String GENERAL_GEN = "CityDoctor_%d_%d";
private static final AtomicInteger ID_COUNTER = new AtomicInteger(); private static final AtomicInteger ID_COUNTER = new AtomicInteger();
private final String gmlString; private final String gmlString;
private final boolean generated; private final boolean generated;
public GmlId(String gmlId) { public GmlId(String gmlId) {
this(gmlId, false); this(gmlId, false);
} }
private GmlId(String gmlId, boolean generated) { private GmlId(String gmlId, boolean generated) {
if (gmlId == null || gmlId.isEmpty()) { if (gmlId == null || gmlId.isEmpty()) {
throw new IllegalArgumentException("GmlId may not be null or empty. If no GmlId is given generate one"); throw new IllegalArgumentException("GmlId may not be null or empty. If no GmlId is given generate one");
} }
this.gmlString = gmlId; this.gmlString = gmlId;
this.generated = generated; this.generated = generated;
} }
@Override @Override
public String toString() { public String toString() {
return gmlString; return gmlString;
} }
public String getGmlString() { public String getGmlString() {
return gmlString; return gmlString;
} }
@Override @Override
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;
int result = 1; int result = 1;
result = prime * result + (generated ? 1231 : 1237); result = prime * result + (generated ? 1231 : 1237);
result = prime * result + ((gmlString == null) ? 0 : gmlString.hashCode()); result = prime * result + ((gmlString == null) ? 0 : gmlString.hashCode());
return result; return result;
} }
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (this == obj) { if (this == obj) {
return true; return true;
} }
if (obj == null) { if (obj == null) {
return false; return false;
} }
if (getClass() != obj.getClass()) { if (getClass() != obj.getClass()) {
return false; return false;
} }
GmlId other = (GmlId) obj; GmlId other = (GmlId) obj;
if (generated != other.generated) { if (generated != other.generated) {
return false; return false;
} }
if (gmlString == null) { if (gmlString == null) {
return other.gmlString == null; return other.gmlString == null;
} else return gmlString.equals(other.gmlString); } else return gmlString.equals(other.gmlString);
} }
/** /**
* Determines if the GML-ID was generated by CityDoctor or not. * Determines if the GML-ID was generated by CityDoctor or not.
* *
* @return True if it was generated, otherwise false. * @return True if it was generated, otherwise false.
*/ */
public boolean isGenerated() { public boolean isGenerated() {
return generated; return generated;
} }
public static GmlId generateId() { public static GmlId generateId() {
return new GmlId(String.format(GENERAL_GEN, System.currentTimeMillis(), ID_COUNTER.getAndIncrement()), true); return new GmlId(String.format(GENERAL_GEN, System.currentTimeMillis(), ID_COUNTER.getAndIncrement()), true);
} }
} }
...@@ -2,7 +2,6 @@ package de.hft.stuttgart.citydoctor2.datastructure; ...@@ -2,7 +2,6 @@ package de.hft.stuttgart.citydoctor2.datastructure;
import de.hft.stuttgart.citydoctor2.check.Check; import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.math.TransformationMatrix; import de.hft.stuttgart.citydoctor2.math.TransformationMatrix;
import de.hft.stuttgart.citydoctor2.utils.CopyHandler;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.citygml4j.core.model.core.ImplicitGeometry; import org.citygml4j.core.model.core.ImplicitGeometry;
...@@ -10,9 +9,11 @@ import org.citygml4j.core.model.core.ImplicitGeometry; ...@@ -10,9 +9,11 @@ import org.citygml4j.core.model.core.ImplicitGeometry;
import java.io.Serial; import java.io.Serial;
/** /**
* Datastructure for representation of implicit geometries * Datastructure for representation and resolving of implicit geometries
*
* @author Riegel
*/ */
public class ImplicitGeometryHolder extends Geometry{ public class ImplicitGeometryHolder extends Geometry {
private static final Logger logger = LogManager.getLogger(LibraryObject.class); private static final Logger logger = LogManager.getLogger(LibraryObject.class);
@Serial @Serial
...@@ -34,7 +35,7 @@ public class ImplicitGeometryHolder extends Geometry{ ...@@ -34,7 +35,7 @@ public class ImplicitGeometryHolder extends Geometry{
} }
public ImplicitGeometryHolder(ImplicitGeometry cgmlImplicitGeometry, RelativeGeometry relativeGeometry) { public ImplicitGeometryHolder(ImplicitGeometry cgmlImplicitGeometry, RelativeGeometry relativeGeometry) {
super(relativeGeometry.getType(),relativeGeometry.getLod()); super(relativeGeometry.getType(), relativeGeometry.getLod());
this.libObject = null; this.libObject = null;
this.relativeGeom = relativeGeometry; this.relativeGeom = relativeGeometry;
this.cgmlImplicitGeometry = cgmlImplicitGeometry; this.cgmlImplicitGeometry = cgmlImplicitGeometry;
...@@ -59,15 +60,15 @@ public class ImplicitGeometryHolder extends Geometry{ ...@@ -59,15 +60,15 @@ public class ImplicitGeometryHolder extends Geometry{
* Applies the transformation matrix of the implicit geometry to a copy of the reference geometry and copies the resulting * Applies the transformation matrix of the implicit geometry to a copy of the reference geometry and copies the resulting
* transformed geometry into this object. * transformed geometry into this object.
*/ */
private void applyTransformation(){ private void applyTransformation() {
TransformationMatrix transformMatrix = new TransformationMatrix(cgmlImplicitGeometry); TransformationMatrix transformMatrix = new TransformationMatrix(cgmlImplicitGeometry);
Geometry refGeo = null; Geometry refGeo = null;
if (libObject == null){ if (libObject == null) {
refGeo = relativeGeom; refGeo = relativeGeom;
} else if (relativeGeom == null){ } else if (relativeGeom == null) {
refGeo = libObject; refGeo = libObject;
} }
if (refGeo == null){ if (refGeo == null) {
throw new NullPointerException("Geometry reference object of ImplicitGeometryHolder is null!"); throw new NullPointerException("Geometry reference object of ImplicitGeometryHolder is null!");
} }
Geometry transformedGeom = transformMatrix.transformGeometry(refGeo); Geometry transformedGeom = transformMatrix.transformGeometry(refGeo);
......
/*- /*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
* *
* This file is part of CityDoctor2. * This file is part of CityDoctor2.
* *
* CityDoctor2 is free software: you can redistribute it and/or modify * CityDoctor2 is free software: you can redistribute it and/or modify
...@@ -18,10 +18,13 @@ ...@@ -18,10 +18,13 @@
*/ */
package de.hft.stuttgart.citydoctor2.datastructure; package de.hft.stuttgart.citydoctor2.datastructure;
import java.io.Serial; import de.hft.stuttgart.citydoctor2.check.Check;
import java.util.ArrayList; import de.hft.stuttgart.citydoctor2.check.CheckError;
import java.util.List; 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.bridge.BridgeInstallation; import org.citygml4j.core.model.bridge.BridgeInstallation;
import org.citygml4j.core.model.construction.AbstractInstallation; import org.citygml4j.core.model.construction.AbstractInstallation;
import org.citygml4j.core.model.core.AbstractSpaceBoundaryProperty; import org.citygml4j.core.model.core.AbstractSpaceBoundaryProperty;
...@@ -32,252 +35,248 @@ import org.xmlobjects.gml.model.geometry.aggregates.MultiSurfaceProperty; ...@@ -32,252 +35,248 @@ import org.xmlobjects.gml.model.geometry.aggregates.MultiSurfaceProperty;
import org.xmlobjects.gml.model.geometry.complexes.CompositeSurface; import org.xmlobjects.gml.model.geometry.complexes.CompositeSurface;
import org.xmlobjects.gml.model.geometry.primitives.SurfaceProperty; import org.xmlobjects.gml.model.geometry.primitives.SurfaceProperty;
import de.hft.stuttgart.citydoctor2.check.Check; import java.io.Serial;
import de.hft.stuttgart.citydoctor2.check.CheckError; import java.util.ArrayList;
import de.hft.stuttgart.citydoctor2.check.CheckId; import java.util.List;
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;
public class Installation extends CityObject { public class Installation extends CityObject {
@Serial @Serial
private static final long serialVersionUID = 1576237433322680191L; private static final long serialVersionUID = 1576237433322680191L;
private List<BoundarySurface> boundarySurfaces = new ArrayList<>(4); private List<BoundarySurface> boundarySurfaces = new ArrayList<>(4);
private AbstractInstallation gmlBi; private AbstractInstallation gmlBi;
private CityObject parent; private CityObject parent;
public void reCreateGeometries(GeometryFactory factory, ParserConfiguration config) { public void reCreateGeometries(GeometryFactory factory, ParserConfiguration config) {
for (Geometry geom : getGeometries()) { for (Geometry geom : getGeometries()) {
if (geom.getType() == GeometryType.MULTI_SURFACE) { if (geom.getType() == GeometryType.MULTI_SURFACE) {
MultiSurface ms = CityGmlUtils.createMultiSurface(geom, factory, config); MultiSurface ms = CityGmlUtils.createMultiSurface(geom, factory, config);
if (ms != null) { if (ms != null) {
setGeometryAccordingToLod(geom.getLod(), new MultiSurfaceProperty(ms)); setGeometryAccordingToLod(geom.getLod(), new MultiSurfaceProperty(ms));
} }
} else if (geom.getType() == GeometryType.COMPOSITE_SURFACE) { } else if (geom.getType() == GeometryType.COMPOSITE_SURFACE) {
CompositeSurface cs = CityGmlUtils.createCompositeSurface(geom, factory, config); CompositeSurface cs = CityGmlUtils.createCompositeSurface(geom, factory, config);
if (cs != null) { if (cs != null) {
setGeometryAccordingToLod(geom.getLod(), new SurfaceProperty(cs)); setGeometryAccordingToLod(geom.getLod(), new SurfaceProperty(cs));
} }
} else { } else {
throw new IllegalStateException("BuildingInstallation not have Solid geometries"); throw new IllegalStateException("BuildingInstallation not have Solid geometries");
} }
} }
for (BoundarySurface bs : boundarySurfaces) { for (BoundarySurface bs : boundarySurfaces) {
bs.reCreateGeometries(factory, config); bs.reCreateGeometries(factory, config);
} }
} }
private void setGeometryAccordingToLod(Lod lod, GeometryProperty<?> ms) { private void setGeometryAccordingToLod(Lod lod, GeometryProperty<?> ms) {
if (gmlBi instanceof org.citygml4j.core.model.building.BuildingInstallation localBi) { if (gmlBi instanceof org.citygml4j.core.model.building.BuildingInstallation localBi) {
addGeometryToBuildingInstallation(lod, ms, localBi); addGeometryToBuildingInstallation(lod, ms, localBi);
} else if (gmlBi instanceof BridgeInstallation localBi) { } else if (gmlBi instanceof BridgeInstallation localBi) {
addGeometryToBridgeInstallation(lod, ms, localBi); addGeometryToBridgeInstallation(lod, ms, localBi);
} }
} }
private void addGeometryToBuildingInstallation(Lod lod, GeometryProperty<?> ms, private void addGeometryToBuildingInstallation(Lod lod, GeometryProperty<?> ms,
org.citygml4j.core.model.building.BuildingInstallation localBi) { org.citygml4j.core.model.building.BuildingInstallation localBi) {
switch (lod) { switch (lod) {
case LOD2: case LOD2:
localBi.getDeprecatedProperties().setLod2Geometry(ms); localBi.getDeprecatedProperties().setLod2Geometry(ms);
break; break;
case LOD3: case LOD3:
localBi.getDeprecatedProperties().setLod3Geometry(ms); localBi.getDeprecatedProperties().setLod3Geometry(ms);
break; break;
case LOD4: case LOD4:
localBi.getDeprecatedProperties().setLod4Geometry(ms); localBi.getDeprecatedProperties().setLod4Geometry(ms);
break; break;
default: default:
throw new IllegalStateException("Found geometry with LOD other than LOD2," throw new IllegalStateException("Found geometry with LOD other than LOD2,"
+ " LOD3, LOD4, which is illegal for BuildingInstallations: " + lod); + " LOD3, LOD4, which is illegal for BuildingInstallations: " + lod);
} }
} }
private void addGeometryToBridgeInstallation(Lod lod, GeometryProperty<?> ms, BridgeInstallation localBi) { private void addGeometryToBridgeInstallation(Lod lod, GeometryProperty<?> ms, BridgeInstallation localBi) {
switch (lod) { switch (lod) {
case LOD2: case LOD2:
localBi.getDeprecatedProperties().setLod2Geometry(ms); localBi.getDeprecatedProperties().setLod2Geometry(ms);
break; break;
case LOD3: case LOD3:
localBi.getDeprecatedProperties().setLod3Geometry(ms); localBi.getDeprecatedProperties().setLod3Geometry(ms);
break; break;
case LOD4: case LOD4:
localBi.getDeprecatedProperties().setLod4Geometry(ms); localBi.getDeprecatedProperties().setLod4Geometry(ms);
break; break;
default: default:
throw new IllegalStateException("Found geometry with LOD other than LOD2," throw new IllegalStateException("Found geometry with LOD other than LOD2,"
+ " LOD3, LOD4, which is illegal for BuildingInstallations: " + lod); + " LOD3, LOD4, which is illegal for BuildingInstallations: " + lod);
} }
} }
@Override @Override
public void accept(Check c) { public void accept(Check c) {
super.accept(c); super.accept(c);
if (c.canExecute(this)) { if (c.canExecute(this)) {
c.check(this); c.check(this);
} }
for (BoundarySurface bs : boundarySurfaces) { for (BoundarySurface bs : boundarySurfaces) {
bs.accept(c); bs.accept(c);
} }
} }
@Override @Override
public void clearAllContainedCheckResults() { public void clearAllContainedCheckResults() {
super.clearAllContainedCheckResults(); super.clearAllContainedCheckResults();
for (BoundarySurface bs : boundarySurfaces) { for (BoundarySurface bs : boundarySurfaces) {
bs.clearAllContainedCheckResults(); bs.clearAllContainedCheckResults();
} }
} }
@Override @Override
public void collectContainedErrors(List<CheckError> errors) { public void collectContainedErrors(List<CheckError> errors) {
super.collectContainedErrors(errors); super.collectContainedErrors(errors);
for (BoundarySurface bs : boundarySurfaces) { for (BoundarySurface bs : boundarySurfaces) {
bs.collectContainedErrors(errors); bs.collectContainedErrors(errors);
} }
} }
@Override @Override
public boolean containsAnyError() { public boolean containsAnyError() {
boolean hasError = super.containsAnyError(); boolean hasError = super.containsAnyError();
if (hasError) { if (hasError) {
return true; return true;
} }
for (BoundarySurface bs : boundarySurfaces) { for (BoundarySurface bs : boundarySurfaces) {
if (bs.containsAnyError()) { if (bs.containsAnyError()) {
return true; return true;
} }
} }
return false; return false;
} }
@Override @Override
public boolean containsError(CheckId checkIdentifier) { public boolean containsError(CheckId checkIdentifier) {
boolean hasError = super.containsError(checkIdentifier); boolean hasError = super.containsError(checkIdentifier);
if (hasError) { if (hasError) {
return true; return true;
} }
for (BoundarySurface bs : boundarySurfaces) { for (BoundarySurface bs : boundarySurfaces) {
if (bs.containsError(checkIdentifier)) { if (bs.containsError(checkIdentifier)) {
return true; return true;
} }
} }
return false; return false;
} }
public void setParent(CityObject parent) { public void setParent(CityObject parent) {
this.parent = parent; this.parent = parent;
} }
public CityObject getParent() { public CityObject getParent() {
return parent; return parent;
} }
public void addBoundarySurface(BoundarySurface bs) { public void addBoundarySurface(BoundarySurface bs) {
boundarySurfaces.add(bs); boundarySurfaces.add(bs);
bs.setParent(this); bs.setParent(this);
} }
public void unsetGmlGeometries() { public void unsetGmlGeometries() {
if (gmlBi instanceof org.citygml4j.core.model.building.BuildingInstallation localBi) { if (gmlBi instanceof org.citygml4j.core.model.building.BuildingInstallation localBi) {
localBi.getDeprecatedProperties().setLod2Geometry(null); localBi.getDeprecatedProperties().setLod2Geometry(null);
localBi.getDeprecatedProperties().setLod3Geometry(null); localBi.getDeprecatedProperties().setLod3Geometry(null);
localBi.getDeprecatedProperties().setLod4Geometry(null); localBi.getDeprecatedProperties().setLod4Geometry(null);
} else if (gmlBi instanceof BridgeInstallation localBi) { } else if (gmlBi instanceof BridgeInstallation localBi) {
removeGeometriesFromBridgeInstallation(localBi); removeGeometriesFromBridgeInstallation(localBi);
} }
for (BoundarySurface bs : boundarySurfaces) { for (BoundarySurface bs : boundarySurfaces) {
bs.unsetGmlGeometries(); bs.unsetGmlGeometries();
} }
} }
private void removeGeometriesFromBridgeInstallation(BridgeInstallation localBi) { private void removeGeometriesFromBridgeInstallation(BridgeInstallation localBi) {
localBi.getDeprecatedProperties().setLod2Geometry(null); localBi.getDeprecatedProperties().setLod2Geometry(null);
localBi.getDeprecatedProperties().setLod3Geometry(null); localBi.getDeprecatedProperties().setLod3Geometry(null);
localBi.getDeprecatedProperties().setLod4Geometry(null); localBi.getDeprecatedProperties().setLod4Geometry(null);
} }
public void setGmlObject(AbstractInstallation gmlBi) { public void setGmlObject(AbstractInstallation gmlBi) {
this.gmlBi = gmlBi; this.gmlBi = gmlBi;
} }
@Override @Override
public String toString() { public String toString() {
return "BuildingInstallation [id=" + getGmlId() + "]"; return "BuildingInstallation [id=" + getGmlId() + "]";
} }
void anonymize() { void anonymize() {
setGmlId(GmlId.generateId()); setGmlId(GmlId.generateId());
gmlBi = new org.citygml4j.core.model.building.BuildingInstallation(); gmlBi = new org.citygml4j.core.model.building.BuildingInstallation();
gmlBi.setId(getGmlId().getGmlString()); gmlBi.setId(getGmlId().getGmlString());
for (BoundarySurface bs : boundarySurfaces) { for (BoundarySurface bs : boundarySurfaces) {
bs.anonymize(); bs.anonymize();
gmlBi.getBoundaries().add(new AbstractSpaceBoundaryProperty(bs.getGmlObject())); gmlBi.getBoundaries().add(new AbstractSpaceBoundaryProperty(bs.getGmlObject()));
} }
} }
@Override @Override
public AbstractInstallation getGmlObject() { public AbstractInstallation getGmlObject() {
return gmlBi; return gmlBi;
} }
@Override @Override
public FeatureType getFeatureType() { public FeatureType getFeatureType() {
return FeatureType.INSTALLATION; return FeatureType.INSTALLATION;
} }
public List<BoundarySurface> getBoundarySurfaces() { public List<BoundarySurface> getBoundarySurfaces() {
if (boundarySurfaces == null) { if (boundarySurfaces == null) {
boundarySurfaces = new ArrayList<>(4); boundarySurfaces = new ArrayList<>(4);
} }
return boundarySurfaces; return boundarySurfaces;
} }
@Override @Override
public void clearMetaInformation() { public void clearMetaInformation() {
super.clearMetaInformation(); super.clearMetaInformation();
for (BoundarySurface bs : boundarySurfaces) { for (BoundarySurface bs : boundarySurfaces) {
bs.clearMetaInformation(); bs.clearMetaInformation();
} }
} }
@Override @Override
public void prepareForChecking() { public void prepareForChecking() {
super.prepareForChecking(); super.prepareForChecking();
for (BoundarySurface bs : boundarySurfaces) { for (BoundarySurface bs : boundarySurfaces) {
bs.prepareForChecking(); bs.prepareForChecking();
} }
} }
@Override @Override
public void fillValues(Copyable original, CopyHandler handler) { public void fillValues(Copyable original, CopyHandler handler) {
super.fillValues(original, handler); super.fillValues(original, handler);
Installation originalBi = (Installation) original; Installation originalBi = (Installation) original;
for (BoundarySurface originalBs : originalBi.boundarySurfaces) { for (BoundarySurface originalBs : originalBi.boundarySurfaces) {
boundarySurfaces.add(handler.getCopyInstance(originalBs)); boundarySurfaces.add(handler.getCopyInstance(originalBs));
} }
gmlBi = originalBi.gmlBi; gmlBi = originalBi.gmlBi;
parent = handler.getCopyInstance(parent); parent = handler.getCopyInstance(parent);
} }
@Override @Override
public void collectInstances(CopyHandler handler) { public void collectInstances(CopyHandler handler) {
super.collectInstances(handler); super.collectInstances(handler);
for (BoundarySurface bs : boundarySurfaces) { for (BoundarySurface bs : boundarySurfaces) {
handler.addInstance(bs); handler.addInstance(bs);
} }
handler.addInstance(parent); handler.addInstance(parent);
} }
@Override @Override
public Copyable createCopyInstance() { public Copyable createCopyInstance() {
return new Installation(); return new Installation();
} }
} }
/*- /*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
* *
* This file is part of CityDoctor2. * This file is part of CityDoctor2.
* *
* CityDoctor2 is free software: you can redistribute it and/or modify * CityDoctor2 is free software: you can redistribute it and/or modify
...@@ -18,107 +18,105 @@ ...@@ -18,107 +18,105 @@
*/ */
package de.hft.stuttgart.citydoctor2.datastructure; package de.hft.stuttgart.citydoctor2.datastructure;
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.core.AbstractCityObject;
import org.citygml4j.core.model.landuse.LandUse; import org.citygml4j.core.model.landuse.LandUse;
import org.citygml4j.core.util.geometry.GeometryFactory; import org.citygml4j.core.util.geometry.GeometryFactory;
import org.xmlobjects.gml.model.geometry.aggregates.MultiSurface; import org.xmlobjects.gml.model.geometry.aggregates.MultiSurface;
import org.xmlobjects.gml.model.geometry.aggregates.MultiSurfaceProperty; 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.Copyable;
import java.io.Serial; import java.io.Serial;
/** /**
* Represents a land use CityGML object. * Represents a land use CityGML object.
*
* @author Matthias Betz
* *
* @author Matthias Betz
*/ */
public class LandObject extends CityObject { public class LandObject extends CityObject {
@Serial @Serial
private static final long serialVersionUID = 1887455662411087326L; private static final long serialVersionUID = 1887455662411087326L;
private LandUse lu; private LandUse lu;
public LandObject(LandUse lu) { public LandObject(LandUse lu) {
this.lu = lu; this.lu = lu;
} }
@Override @Override
public void reCreateGeometries(GeometryFactory factory, ParserConfiguration config) { public void reCreateGeometries(GeometryFactory factory, ParserConfiguration config) {
for (Geometry geom : getGeometries()) { for (Geometry geom : getGeometries()) {
if (geom.getType() == GeometryType.MULTI_SURFACE) { if (geom.getType() == GeometryType.MULTI_SURFACE) {
MultiSurface ms = CityGmlUtils.createMultiSurface(geom, factory, config); MultiSurface ms = CityGmlUtils.createMultiSurface(geom, factory, config);
setMultiSurfaceAccordingToLod(geom, ms); setMultiSurfaceAccordingToLod(geom, ms);
} else { } else {
throw new IllegalStateException("Landuse cannot have solids: " + geom); throw new IllegalStateException("Landuse cannot have solids: " + geom);
} }
} }
} }
@Override @Override
public FeatureType getFeatureType() { public FeatureType getFeatureType() {
return FeatureType.LAND; return FeatureType.LAND;
} }
private void setMultiSurfaceAccordingToLod(Geometry geom, MultiSurface ms) { private void setMultiSurfaceAccordingToLod(Geometry geom, MultiSurface ms) {
switch (geom.getLod()) { switch (geom.getLod()) {
case LOD0: case LOD0:
lu.setLod0MultiSurface(new MultiSurfaceProperty(ms)); lu.setLod0MultiSurface(new MultiSurfaceProperty(ms));
break; break;
case LOD1: case LOD1:
lu.setLod1MultiSurface(new MultiSurfaceProperty(ms)); lu.setLod1MultiSurface(new MultiSurfaceProperty(ms));
break; break;
case LOD2: case LOD2:
lu.setLod2MultiSurface(new MultiSurfaceProperty(ms)); lu.setLod2MultiSurface(new MultiSurfaceProperty(ms));
break; break;
case LOD3: case LOD3:
lu.setLod3MultiSurface(new MultiSurfaceProperty(ms)); lu.setLod3MultiSurface(new MultiSurfaceProperty(ms));
break; break;
case LOD4: case LOD4:
lu.getDeprecatedProperties().setLod4MultiSurface(new MultiSurfaceProperty(ms)); lu.getDeprecatedProperties().setLod4MultiSurface(new MultiSurfaceProperty(ms));
break; break;
} }
} }
@Override @Override
public void accept(Check c) { public void accept(Check c) {
super.accept(c); super.accept(c);
if (c.canExecute(this)) { if (c.canExecute(this)) {
c.check(this); c.check(this);
} }
} }
@Override @Override
public AbstractCityObject getGmlObject() { public AbstractCityObject getGmlObject() {
return lu; return lu;
} }
@Override @Override
public void unsetGmlGeometries() { public void unsetGmlGeometries() {
lu.setLod0MultiSurface(null); lu.setLod0MultiSurface(null);
lu.setLod1MultiSurface(null); lu.setLod1MultiSurface(null);
lu.setLod2MultiSurface(null); lu.setLod2MultiSurface(null);
lu.setLod3MultiSurface(null); lu.setLod3MultiSurface(null);
lu.getDeprecatedProperties().setLod4MultiSurface(null); lu.getDeprecatedProperties().setLod4MultiSurface(null);
} }
public void setGmlObject(LandUse landUse) { public void setGmlObject(LandUse landUse) {
lu = landUse; lu = landUse;
} }
@Override @Override
public String toString() { public String toString() {
return "LandObject [id=" + getGmlId() + "]"; return "LandObject [id=" + getGmlId() + "]";
} }
@Override @Override
public Copyable createCopyInstance() { public Copyable createCopyInstance() {
return new LandObject(lu); return new LandObject(lu);
} }
} }
package de.hft.stuttgart.citydoctor2.datastructure; package de.hft.stuttgart.citydoctor2.datastructure;
import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.mapper.citygml3.Citygml3FeatureMapper;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException; import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParser; import de.hft.stuttgart.citydoctor2.parser.CityGmlParser;
import de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException; import de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException;
import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration; import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;
import de.hft.stuttgart.citydoctor2.utils.CopyHandler;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
...@@ -14,17 +11,20 @@ import java.io.Serial; ...@@ -14,17 +11,20 @@ import java.io.Serial;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
/** /**
* Reference object for handling of implicit geometries with a library object contained in an external file * Reference object for handling of implicit geometries with a library object contained in an external file
*
* @author Riegel
*/ */
public class LibraryObject extends Geometry{ public class LibraryObject extends Geometry {
private static final Logger logger = LogManager.getLogger(LibraryObject.class); private static final Logger logger = LogManager.getLogger(LibraryObject.class);
@Serial @Serial
private static final long serialVersionUID = -50293435187454911L; private static final long serialVersionUID = -50293435187454911L;
private final String filepath; private final String filepath;
private final ParserConfiguration config; private final ParserConfiguration config;
private static HashMap<String,LibraryObject> libraryObjects = new HashMap<>(); private static HashMap<String, LibraryObject> libraryObjects = new HashMap<>();
public static LibraryObject of(Path path, ParserConfiguration config) { public static LibraryObject of(Path path, ParserConfiguration config) {
if (libraryObjects.containsKey(path.toString())) { if (libraryObjects.containsKey(path.toString())) {
...@@ -34,7 +34,7 @@ public class LibraryObject extends Geometry{ ...@@ -34,7 +34,7 @@ public class LibraryObject extends Geometry{
if (protoGeom == null) { if (protoGeom == null) {
return null; return null;
} }
LibraryObject libOb = new LibraryObject(protoGeom.getType(),protoGeom.getLod(),path, config); LibraryObject libOb = new LibraryObject(protoGeom.getType(), protoGeom.getLod(), path, config);
protoGeom.getPolygons().forEach(libOb::addPolygon); protoGeom.getPolygons().forEach(libOb::addPolygon);
libOb.updateEdgesAndVertices(); libOb.updateEdgesAndVertices();
libraryObjects.put(path.toString(), libOb); libraryObjects.put(path.toString(), libOb);
...@@ -42,7 +42,7 @@ public class LibraryObject extends Geometry{ ...@@ -42,7 +42,7 @@ public class LibraryObject extends Geometry{
} }
private LibraryObject(GeometryType type, Lod lod, Path path, ParserConfiguration config) { private LibraryObject(GeometryType type, Lod lod, Path path, ParserConfiguration config) {
super(type,lod); super(type, lod);
this.filepath = path.toString(); this.filepath = path.toString();
this.config = config; this.config = config;
} }
...@@ -50,28 +50,28 @@ public class LibraryObject extends Geometry{ ...@@ -50,28 +50,28 @@ public class LibraryObject extends Geometry{
private static Geometry parseFile(Path path, ParserConfiguration config) { private static Geometry parseFile(Path path, ParserConfiguration config) {
Geometry geo = null; Geometry geo = null;
if (path.toFile().exists()){ if (path.toFile().exists()) {
try { try {
CityGmlParser.gagLogger(true); CityGmlParser.gagLogger(true);
CityDoctorModel model = CityGmlParser.parseCityGmlFile(path.toString(), config); CityDoctorModel model = CityGmlParser.parseCityGmlFile(path.toString(), config);
List<CityObject> objects = model.createFeatureStream().toList(); List<CityObject> objects = model.createFeatureStream().toList();
if (objects.isEmpty()){ if (objects.isEmpty()) {
throw new InvalidGmlFileException("Referenced library-object's gml file does not contain a CityGML object!"); throw new InvalidGmlFileException("Referenced library-object's gml file does not contain a CityGML object!");
} else if (objects.size() > 1){ } else if (objects.size() > 1) {
throw new InvalidGmlFileException("Referenced library-object's gml file contains more than one CityGML object!"); throw new InvalidGmlFileException("Referenced library-object's gml file contains more than one CityGML object!");
} }
geo = objects.get(0).getHighestLodGeometry(); geo = objects.get(0).getHighestLodGeometry();
} catch (CityGmlParseException e){ } catch (CityGmlParseException e) {
logger.error(String.format( logger.error(String.format(
"Encountered an error while parsing library object %s", path)); "Encountered an error while parsing library object %s", path));
logger.error(e.getStackTrace()); logger.error(e.getStackTrace());
} catch (InvalidGmlFileException e){ } catch (InvalidGmlFileException e) {
logger.error(e.getStackTrace()); logger.error(e.getStackTrace());
} finally { } finally {
// Failsafe to remove gag should parsing fail // Failsafe to remove gag should parsing fail
CityGmlParser.gagLogger(false); CityGmlParser.gagLogger(false);
} }
} else{ } else {
logger.error(String.format("Implicit geometry references non-existing library object file %s.", path)); logger.error(String.format("Implicit geometry references non-existing library object file %s.", path));
} }
return geo; return geo;
......
/*- /*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
* *
* This file is part of CityDoctor2. * This file is part of CityDoctor2.
* *
* CityDoctor2 is free software: you can redistribute it and/or modify * CityDoctor2 is free software: you can redistribute it and/or modify
...@@ -18,337 +18,332 @@ ...@@ -18,337 +18,332 @@
*/ */
package de.hft.stuttgart.citydoctor2.datastructure; 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.Check;
import de.hft.stuttgart.citydoctor2.math.ProjectionAxis; import de.hft.stuttgart.citydoctor2.math.*;
import de.hft.stuttgart.citydoctor2.math.Ring2d;
import de.hft.stuttgart.citydoctor2.math.UnitVector3d;
import de.hft.stuttgart.citydoctor2.math.Vector2d;
import de.hft.stuttgart.citydoctor2.math.Vector3d;
import de.hft.stuttgart.citydoctor2.utils.CopyHandler; import de.hft.stuttgart.citydoctor2.utils.CopyHandler;
import de.hft.stuttgart.citydoctor2.utils.Copyable; import de.hft.stuttgart.citydoctor2.utils.Copyable;
import java.io.Serial;
import java.util.ArrayList;
import java.util.List;
/** /**
* Represents a linear ring used in polygons. The ring contains the vertices. * Represents a linear ring used in polygons. The ring contains the vertices.
*
* @author Matthias Betz
* *
* @author Matthias Betz
*/ */
public class LinearRing extends GmlElement { public class LinearRing extends GmlElement {
@Serial @Serial
private static final long serialVersionUID = -2488180830514940722L; private static final long serialVersionUID = -2488180830514940722L;
private LinearRingType type; private LinearRingType type;
private Polygon parent; private Polygon parent;
private final List<Vertex> vertices = new ArrayList<>(); private final List<Vertex> vertices = new ArrayList<>();
public enum LinearRingType { public enum LinearRingType {
EXTERIOR, INTERIOR EXTERIOR, INTERIOR
} }
public LinearRing(LinearRingType type) { public LinearRing(LinearRingType type) {
this.type = type; this.type = type;
} }
/** /**
* Checks whether a point is inside this ring. A point on the edge does count as * Checks whether a point is inside this ring. A point on the edge does count as
* inside. * inside.
* *
* @param v the point. * @param v the point.
* @return true if the point is inside or on an edge, false if it is outside. * @return true if the point is inside or on an edge, false if it is outside.
*/ */
public boolean isPointInside(Vector3d v) { public boolean isPointInside(Vector3d v) {
// project to 2d ring // project to 2d ring
ProjectionAxis axis = ProjectionAxis.of(this); ProjectionAxis axis = ProjectionAxis.of(this);
Vector2d point = axis.project(v); Vector2d point = axis.project(v);
Ring2d ring = Ring2d.of(this, axis); Ring2d ring = Ring2d.of(this, axis);
int t = -1; int t = -1;
for (int i = 0; i < ring.getVertices().size() - 1; i++) { for (int i = 0; i < ring.getVertices().size() - 1; i++) {
t = t * crossProdTest(point, ring.getVertices().get(i), ring.getVertices().get(i + 1)); t = t * crossProdTest(point, ring.getVertices().get(i), ring.getVertices().get(i + 1));
if (t == 0) { if (t == 0) {
return true; return true;
} }
} }
return t >= 0; return t >= 0;
} }
private int crossProdTest(Vector2d a, Vector2d b, Vector2d c) { private int crossProdTest(Vector2d a, Vector2d b, Vector2d c) {
if (a.getY() == b.getY() && a.getY() == c.getY()) { if (a.getY() == b.getY() && a.getY() == c.getY()) {
if ((b.getX() <= a.getX() && a.getX() <= c.getX()) || (c.getX() <= a.getX() && a.getX() <= b.getX())) { if ((b.getX() <= a.getX() && a.getX() <= c.getX()) || (c.getX() <= a.getX() && a.getX() <= b.getX())) {
return 0; return 0;
} else { } else {
return 1; return 1;
} }
} }
if (a.getY() == b.getY() && a.getX() == b.getX()) { if (a.getY() == b.getY() && a.getX() == b.getX()) {
return 0; return 0;
} }
if (b.getY() > c.getY()) { if (b.getY() > c.getY()) {
Vector2d temp = b; Vector2d temp = b;
b = c; b = c;
c = temp; c = temp;
} }
if (a.getY() <= b.getY() || a.getY() > c.getY()) { if (a.getY() <= b.getY() || a.getY() > c.getY()) {
return 1; return 1;
} }
return calculateDelta(a, b, c); return calculateDelta(a, b, c);
} }
private int calculateDelta(Vector2d a, Vector2d b, Vector2d c) { private int calculateDelta(Vector2d a, Vector2d b, Vector2d c) {
double delta = (b.getX() - a.getX()) * (c.getY() - a.getY()) - (b.getY() - a.getY()) * (c.getX() - a.getX()); double delta = (b.getX() - a.getX()) * (c.getY() - a.getY()) - (b.getY() - a.getY()) * (c.getX() - a.getX());
if (delta > 0) { if (delta > 0) {
return -1; return -1;
} else if (delta < 0) { } else if (delta < 0) {
return 1; return 1;
} else { } else {
return 0; return 0;
} }
} }
/** /**
* Calculates the normal vector of the ring. Method by Newell. If the Newell * Calculates the normal vector of the ring. Method by Newell. If the Newell
* method would return a (0, 0, 0) vector a cross product is formed from the * method would return a (0, 0, 0) vector a cross product is formed from the
* first 3 vertices. If there are no 3 vertices available (1, 0, 0) is returned. * first 3 vertices. If there are no 3 vertices available (1, 0, 0) is returned.
* *
* @return the normal as a normalized vector * @return the normal as a normalized vector
*/ */
public UnitVector3d calculateNormalNormalized() { public UnitVector3d calculateNormalNormalized() {
return calculateNormal().normalize(); return calculateNormal().normalize();
} }
/** /**
* Calculates the normal vector of the ring. Method by Newell. If the Newell * Calculates the normal vector of the ring. Method by Newell. If the Newell
* method would return a (0, 0, 0) vector a cross product is formed from the * method would return a (0, 0, 0) vector a cross product is formed from the
* first 3 vertices. If there are no 3 vertices available (1, 0, 0) is returned. * first 3 vertices. If there are no 3 vertices available (1, 0, 0) is returned.
* *
* @return the normal vector * @return the normal vector
*/ */
public Vector3d calculateNormal() { public Vector3d calculateNormal() {
double[] coords = new double[3]; double[] coords = new double[3];
for (int i = 0; i < vertices.size() - 1; i++) { for (int i = 0; i < vertices.size() - 1; i++) {
Vertex current = vertices.get(i); Vertex current = vertices.get(i);
Vertex next = vertices.get(i + 1); Vertex next = vertices.get(i + 1);
coords[0] += (current.getZ() + next.getZ()) * (current.getY() - next.getY()); coords[0] += (current.getZ() + next.getZ()) * (current.getY() - next.getY());
coords[1] += (current.getX() + next.getX()) * (current.getZ() - next.getZ()); coords[1] += (current.getX() + next.getX()) * (current.getZ() - next.getZ());
coords[2] += (current.getY() + next.getY()) * (current.getX() - next.getX()); coords[2] += (current.getY() + next.getY()) * (current.getX() - next.getX());
} }
if (coords[0] == 0 && coords[1] == 0 && coords[2] == 0) { if (coords[0] == 0 && coords[1] == 0 && coords[2] == 0) {
// no valid normal vector found // no valid normal vector found
if (vertices.size() < 3) { if (vertices.size() < 3) {
// no three points, return x-axis // no three points, return x-axis
return UnitVector3d.X_AXIS; return UnitVector3d.X_AXIS;
} }
Vertex v1 = vertices.get(0); Vertex v1 = vertices.get(0);
Vertex v2 = vertices.get(1); Vertex v2 = vertices.get(1);
Vertex v3 = vertices.get(2); Vertex v3 = vertices.get(2);
return calculateNormalWithCross(v1, v2, v3); return calculateNormalWithCross(v1, v2, v3);
} }
return new Vector3d(coords); return new Vector3d(coords);
} }
public double getArea() { public double getArea() {
int n = vertices.size(); int n = vertices.size();
if (n < 3) if (n < 3)
return 0.0; // a degenerated polygon return 0.0; // a degenerated polygon
// prepare an vertex array with n+2 vertices: // prepare an vertex array with n+2 vertices:
// V[0] ... V[n-1] - the n different vertices // V[0] ... V[n-1] - the n different vertices
// V[n]=V[0] // V[n]=V[0]
// V[n+1]=V[1] // V[n+1]=V[1]
Vertex[] vertexArray = new Vertex[n + 2]; Vertex[] vertexArray = new Vertex[n + 2];
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
vertexArray[i] = vertices.get(i); vertexArray[i] = vertices.get(i);
} }
vertexArray[n] = vertices.get(0); vertexArray[n] = vertices.get(0);
vertexArray[n + 1] = vertices.get(1); vertexArray[n + 1] = vertices.get(1);
double area = 0; double area = 0;
// make sure the normal has been calculated // make sure the normal has been calculated
Vector3d normal = calculateNormal(); Vector3d normal = calculateNormal();
// select largest abs coordinate to ignore for projection // select largest abs coordinate to ignore for projection
double ax = Math.abs(normal.getX()); // abs x-coord double ax = Math.abs(normal.getX()); // abs x-coord
double ay = Math.abs(normal.getY()); // abs y-coord double ay = Math.abs(normal.getY()); // abs y-coord
double az = Math.abs(normal.getZ()); // abs z-coord double az = Math.abs(normal.getZ()); // abs z-coord
// coord to ignore: 1=x, 2=y, 3=z // coord to ignore: 1=x, 2=y, 3=z
int coord = 3; // ignore z-coord int coord = 3; // ignore z-coord
if (ax > ay) { if (ax > ay) {
if (ax > az) { if (ax > az) {
coord = 1; // ignore x-coord coord = 1; // ignore x-coord
} }
} else if (ay > az) { } else if (ay > az) {
coord = 2; // ignore y-coord coord = 2; // ignore y-coord
} }
// compute area of the 2D projection // compute area of the 2D projection
for (int i = 1, j = 2, k = 0; i <= vertexArray.length - 2; i++, j++, k++) { for (int i = 1, j = 2, k = 0; i <= vertexArray.length - 2; i++, j++, k++) {
switch (coord) { switch (coord) {
case 1: case 1:
area += (vertexArray[i].getY() * (vertexArray[j].getZ() - vertexArray[k].getZ())); area += (vertexArray[i].getY() * (vertexArray[j].getZ() - vertexArray[k].getZ()));
break; break;
case 2: case 2:
area += (vertexArray[i].getX() * (vertexArray[j].getZ() - vertexArray[k].getZ())); area += (vertexArray[i].getX() * (vertexArray[j].getZ() - vertexArray[k].getZ()));
break; break;
case 3: case 3:
area += (vertexArray[i].getX() * (vertexArray[j].getY() - vertexArray[k].getY())); area += (vertexArray[i].getX() * (vertexArray[j].getY() - vertexArray[k].getY()));
break; break;
default: default:
throw new IllegalStateException(); throw new IllegalStateException();
} }
} }
// scale to get area before projection // scale to get area before projection
double an = Math.sqrt(ax * ax + ay * ay + az * az); // length of normal vector double an = Math.sqrt(ax * ax + ay * ay + az * az); // length of normal vector
switch (coord) { switch (coord) {
case 1: case 1:
area *= (an / (2 * ax)); area *= (an / (2 * ax));
break; break;
case 2: case 2:
area *= (an / (2 * ay)); area *= (an / (2 * ay));
break; break;
case 3: case 3:
area *= (an / (2 * az)); area *= (an / (2 * az));
break; break;
default: default:
throw new IllegalStateException(); throw new IllegalStateException();
} }
return Math.abs(area); return Math.abs(area);
} }
private UnitVector3d calculateNormalWithCross(Vertex v1, Vertex v2, Vertex v3) { private UnitVector3d calculateNormalWithCross(Vertex v1, Vertex v2, Vertex v3) {
Vector3d dir1 = v2.minus(v1); Vector3d dir1 = v2.minus(v1);
Vector3d dir2 = v3.minus(v1); Vector3d dir2 = v3.minus(v1);
Vector3d cross = dir1.cross(dir2); Vector3d cross = dir1.cross(dir2);
return cross.normalize(); return cross.normalize();
} }
@Override @Override
public void accept(Check c) { public void accept(Check c) {
super.accept(c); super.accept(c);
if (c.canExecute(this)) { if (c.canExecute(this)) {
c.check(this); c.check(this);
} }
} }
@Override @Override
public void clearAllContainedCheckResults() { public void clearAllContainedCheckResults() {
super.clearCheckResults(); super.clearCheckResults();
} }
public void setParent(Polygon polygon) { public void setParent(Polygon polygon) {
parent = polygon; parent = polygon;
} }
public Polygon getParent() { public Polygon getParent() {
return parent; return parent;
} }
public LinearRingType getType() { public LinearRingType getType() {
return type; return type;
} }
public List<Vertex> getVertices() { public List<Vertex> getVertices() {
return vertices; return vertices;
} }
public void addVertex(Vertex v) { public void addVertex(Vertex v) {
vertices.add(v); vertices.add(v);
if (parent == null) { if (parent == null) {
return; return;
} }
if (parent.isLinkedTo()) { if (parent.isLinkedTo()) {
v.addAdjacentRing(this, parent.getLinkedFromPolygon().getParent()); v.addAdjacentRing(this, parent.getLinkedFromPolygon().getParent());
} }
v.addAdjacentRing(this, parent.getParent()); v.addAdjacentRing(this, parent.getParent());
} }
public void addVertex(int i, Vertex v) { public void addVertex(int i, Vertex v) {
vertices.add(i, v); vertices.add(i, v);
if (parent.isLinkedTo()) { if (parent.isLinkedTo()) {
v.addAdjacentRing(this, parent.getLinkedFromPolygon().getParent()); v.addAdjacentRing(this, parent.getLinkedFromPolygon().getParent());
} }
v.addAdjacentRing(this, parent.getParent()); v.addAdjacentRing(this, parent.getParent());
} }
public void setVertex(int i, Vertex v) { public void setVertex(int i, Vertex v) {
vertices.set(i, v); vertices.set(i, v);
if (parent.isLinkedTo()) { if (parent.isLinkedTo()) {
v.addAdjacentRing(this, parent.getLinkedFromPolygon().getParent()); v.addAdjacentRing(this, parent.getLinkedFromPolygon().getParent());
} }
v.addAdjacentRing(this, parent.getParent()); v.addAdjacentRing(this, parent.getParent());
} }
@Override @Override
public String toString() { public String toString() {
return "LinearRing [type=" + type + ", gmlId=" + getGmlId() + "]"; return "LinearRing [type=" + type + ", gmlId=" + getGmlId() + "]";
} }
void anonymize() { void anonymize() {
setGmlId(GmlId.generateId()); setGmlId(GmlId.generateId());
} }
public boolean isRingConnectedViaPoint(LinearRing other) { public boolean isRingConnectedViaPoint(LinearRing other) {
for (Vertex v : vertices) { for (Vertex v : vertices) {
if (other.getVertices().contains(v)) { if (other.getVertices().contains(v)) {
return true; return true;
} }
} }
return false; return false;
} }
public boolean hasPointAsCorner(Vertex v) { public boolean hasPointAsCorner(Vertex v) {
return vertices.contains(v); return vertices.contains(v);
} }
public void setType(LinearRingType type) { public void setType(LinearRingType type) {
this.type = type; this.type = type;
} }
public void addAllVertices(List<Vertex> extRing) { public void addAllVertices(List<Vertex> extRing) {
vertices.addAll(extRing); vertices.addAll(extRing);
} }
@Override @Override
public void prepareForChecking() { public void prepareForChecking() {
parent.getParent().prepareForChecking(); parent.getParent().prepareForChecking();
} }
@Override @Override
public void clearMetaInformation() { public void clearMetaInformation() {
parent.getParent().clearMetaInformation(); parent.getParent().clearMetaInformation();
} }
@Override @Override
public void fillValues(Copyable original, CopyHandler handler) { public void fillValues(Copyable original, CopyHandler handler) {
super.fillValues(original, handler); super.fillValues(original, handler);
LinearRing originalRing = (LinearRing) original; LinearRing originalRing = (LinearRing) original;
type = originalRing.type; type = originalRing.type;
parent = handler.getCopyInstance(originalRing.parent); parent = handler.getCopyInstance(originalRing.parent);
for (Vertex v : originalRing.vertices) { for (Vertex v : originalRing.vertices) {
vertices.add(handler.getCopyInstance(v)); vertices.add(handler.getCopyInstance(v));
} }
} }
@Override @Override
public void collectInstances(CopyHandler handler) { public void collectInstances(CopyHandler handler) {
for (Vertex v : vertices) { for (Vertex v : vertices) {
handler.addInstance(v); handler.addInstance(v);
} }
handler.addInstance(parent); handler.addInstance(parent);
} }
@Override @Override
public Copyable createCopyInstance() { public Copyable createCopyInstance() {
return new LinearRing(type); return new LinearRing(type);
} }
} }
/*- /*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
* *
* This file is part of CityDoctor2. * This file is part of CityDoctor2.
* *
* CityDoctor2 is free software: you can redistribute it and/or modify * CityDoctor2 is free software: you can redistribute it and/or modify
...@@ -18,10 +18,6 @@ ...@@ -18,10 +18,6 @@
*/ */
package de.hft.stuttgart.citydoctor2.datastructure; package de.hft.stuttgart.citydoctor2.datastructure;
import java.io.Serial;
import java.util.List;
import java.util.Map;
import de.hft.stuttgart.citydoctor2.check.Check; import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.CheckError; import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.CheckId; import de.hft.stuttgart.citydoctor2.check.CheckId;
...@@ -31,275 +27,277 @@ import de.hft.stuttgart.citydoctor2.tesselation.TesselatedPolygon; ...@@ -31,275 +27,277 @@ import de.hft.stuttgart.citydoctor2.tesselation.TesselatedPolygon;
import de.hft.stuttgart.citydoctor2.utils.CopyHandler; import de.hft.stuttgart.citydoctor2.utils.CopyHandler;
import de.hft.stuttgart.citydoctor2.utils.Copyable; import de.hft.stuttgart.citydoctor2.utils.Copyable;
import java.io.Serial;
import java.util.List;
import java.util.Map;
/** /**
* A polygon that does not contain the geometry but is only a link to an actual * A polygon that does not contain the geometry but is only a link to an actual
* polygon. Created when href in CityGML are used. * polygon. Created when href in CityGML are used.
*
* @author Matthias Betz
* *
* @author Matthias Betz
*/ */
public class LinkedPolygon extends Polygon { public class LinkedPolygon extends Polygon {
@Serial @Serial
private static final long serialVersionUID = -4897578390280277931L; private static final long serialVersionUID = -4897578390280277931L;
private Geometry parent; private Geometry parent;
private ConcretePolygon poly; private ConcretePolygon poly;
private LinkedPolygon() { private LinkedPolygon() {
} }
/** /**
* * @param poly polygon this is linked to
* @param poly polygon this is linked to * @param parent the parent of the linked polygon
* @param parent the parent of the linked polygon */
*/ public LinkedPolygon(ConcretePolygon poly, Geometry parent) {
public LinkedPolygon(ConcretePolygon poly, Geometry parent) { this.parent = parent;
this.parent = parent; this.poly = poly;
this.poly = poly; poly.setLinkedTo(this);
poly.setLinkedTo(this); for (Vertex v : poly.getExteriorRing().getVertices()) {
for (Vertex v : poly.getExteriorRing().getVertices()) { v.addAdjacentRing(poly.getExteriorRing(), parent);
v.addAdjacentRing(poly.getExteriorRing(), parent); }
} for (LinearRing lr : poly.getInnerRings()) {
for (LinearRing lr : poly.getInnerRings()) { for (Vertex v : lr.getVertices()) {
for (Vertex v : lr.getVertices()) { v.addAdjacentRing(lr, parent);
v.addAdjacentRing(lr, parent); }
} }
} }
}
@Override
@Override public CheckResult getCheckResult(Check c) {
public CheckResult getCheckResult(Check c) { return poly.getCheckResult(c);
return poly.getCheckResult(c); }
}
@Override
@Override public Map<CheckId, CheckResult> getAllCheckResults() {
public Map<CheckId, CheckResult> getAllCheckResults() { return poly.getAllCheckResults();
return poly.getAllCheckResults(); }
}
@Override
@Override public boolean hasAnyError() {
public boolean hasAnyError() { return poly.hasAnyError();
return poly.hasAnyError(); }
}
@Override
@Override public boolean hasDependencyNotMetError(CheckId id) {
public boolean hasDependencyNotMetError(CheckId id) { return poly.hasDependencyNotMetError(id);
return poly.hasDependencyNotMetError(id); }
}
@Override
@Override public CheckResult getCheckResult(CheckId id) {
public CheckResult getCheckResult(CheckId id) { return poly.getCheckResult(id);
return poly.getCheckResult(id); }
}
@Override
@Override public boolean hasCheckResults() {
public boolean hasCheckResults() { return poly.hasCheckResults();
return poly.hasCheckResults(); }
}
@Override
@Override public void setGmlId(GmlId id) {
public void setGmlId(GmlId id) { poly.setGmlId(id);
poly.setGmlId(id); }
}
@Override
@Override public GmlId getGmlId() {
public GmlId getGmlId() { return poly.getGmlId();
return poly.getGmlId(); }
}
@Override
@Override public void accept(Check c) {
public void accept(Check c) { // linked polygons are not checked
// linked polygons are not checked setValidated(true);
setValidated(true); }
}
@Override
@Override public void addCheckResult(CheckResult cr) {
public void addCheckResult(CheckResult cr) { poly.addCheckResult(cr);
poly.addCheckResult(cr); }
}
@Override
@Override public void collectContainedErrors(List<CheckError> errors) {
public void collectContainedErrors(List<CheckError> errors) { poly.collectContainedErrors(errors);
poly.collectContainedErrors(errors); }
}
@Override
@Override public boolean containsAnyError() {
public boolean containsAnyError() { return poly.containsAnyError();
return poly.containsAnyError(); }
}
@Override
@Override public boolean containsError(CheckId checkIdentifier) {
public boolean containsError(CheckId checkIdentifier) { return poly.containsError(checkIdentifier);
return poly.containsError(checkIdentifier); }
}
@Override
@Override public void clearCheckResults() {
public void clearCheckResults() { poly.clearCheckResults();
poly.clearCheckResults(); }
}
@Override
@Override public Vector3d calculateNormalNormalized() {
public Vector3d calculateNormalNormalized() { return poly.calculateNormalNormalized();
return poly.calculateNormalNormalized(); }
}
@Override
@Override public Vector3d calculateNormal() {
public Vector3d calculateNormal() { return poly.calculateNormal();
return poly.calculateNormal(); }
}
@Override
@Override public TesselatedPolygon tesselate() {
public TesselatedPolygon tesselate() { return poly.tesselate();
return poly.tesselate(); }
}
@Override
@Override public LinearRing getExteriorRing() {
public LinearRing getExteriorRing() { return poly.getExteriorRing();
return poly.getExteriorRing(); }
}
@Override
@Override public List<LinearRing> getInnerRings() {
public List<LinearRing> getInnerRings() { return poly.getInnerRings();
return poly.getInnerRings(); }
}
@Override
@Override public boolean isPointInsideExteriorRing(Vector3d v) {
public boolean isPointInsideExteriorRing(Vector3d v) { return poly.isPointInsideExteriorRing(v);
return poly.isPointInsideExteriorRing(v); }
}
@Override
@Override public Geometry getParent() {
public Geometry getParent() { return parent;
return parent; }
}
@Override
@Override public void setParent(Geometry geometry) {
public void setParent(Geometry geometry) { this.parent = geometry;
this.parent = geometry; }
}
@Override
@Override public void setExteriorRing(LinearRing extRing) {
public void setExteriorRing(LinearRing extRing) { poly.setExteriorRing(extRing);
poly.setExteriorRing(extRing); }
}
@Override
@Override public boolean isPolygonConnectedViaPoint(Polygon other) {
public boolean isPolygonConnectedViaPoint(Polygon other) { return poly.isPolygonConnectedViaPoint(other);
return poly.isPolygonConnectedViaPoint(other); }
}
@Override
@Override public String toString() {
public String toString() { return "LinkedPolygon [" + poly.getGmlId() + "]";
return "LinkedPolygon [" + poly.getGmlId() + "]"; }
}
@Override
@Override public void addInteriorRing(LinearRing inter) {
public void addInteriorRing(LinearRing inter) { poly.addInteriorRing(inter);
poly.addInteriorRing(inter); }
}
@Override
@Override public BoundarySurface getPartOfSurface() {
public BoundarySurface getPartOfSurface() { return poly.getPartOfSurface();
return poly.getPartOfSurface(); }
}
@Override
@Override public void setPartOfSurface(BoundarySurface bs) {
public void setPartOfSurface(BoundarySurface bs) { poly.setPartOfSurface(bs);
poly.setPartOfSurface(bs); }
}
@Override
@Override public void removeInnerRing(LinearRing ring) {
public void removeInnerRing(LinearRing ring) { poly.removeInnerRing(ring);
poly.removeInnerRing(ring); }
}
@Override
@Override public void setPartOfInstallation(Installation bi) {
public void setPartOfInstallation(Installation bi) { poly.setPartOfInstallation(bi);
poly.setPartOfInstallation(bi); }
}
@Override
@Override public Installation getPartOfInstallation() {
public Installation getPartOfInstallation() { return poly.getPartOfInstallation();
return poly.getPartOfInstallation(); }
}
@Override
@Override public boolean hasPointAsCorner(Vertex v) {
public boolean hasPointAsCorner(Vertex v) { return poly.hasPointAsCorner(v);
return poly.hasPointAsCorner(v); }
}
@Override
@Override public void removeRings() {
public void removeRings() { poly.removeRings();
poly.removeRings(); }
}
@Override
@Override public boolean isLink() {
public boolean isLink() { return true;
return true; }
}
@Override
@Override public LinkedPolygon getLinkedFromPolygon() {
public LinkedPolygon getLinkedFromPolygon() { return this;
return this; }
}
@Override
@Override void anonymize() {
void anonymize() { poly.anonymize();
poly.anonymize(); }
}
@Override
@Override public void clearAllContainedCheckResults() {
public void clearAllContainedCheckResults() { poly.clearAllContainedCheckResults();
poly.clearAllContainedCheckResults(); }
}
@Override
@Override public ConcretePolygon getOriginal() {
public ConcretePolygon getOriginal() { return poly;
return poly; }
}
@Override
@Override public void prepareForChecking() {
public void prepareForChecking() { poly.prepareForChecking();
poly.prepareForChecking(); }
}
@Override
@Override public void clearMetaInformation() {
public void clearMetaInformation() { poly.clearMetaInformation();
poly.clearMetaInformation(); }
}
@Override
@Override public boolean isLinkedTo() {
public boolean isLinkedTo() { return false;
return false; }
}
@Override
@Override public void collectInstances(CopyHandler handler) {
public void collectInstances(CopyHandler handler) { handler.addInstance(parent);
handler.addInstance(parent); handler.addInstance(poly);
handler.addInstance(poly); }
}
@Override
@Override public Copyable createCopyInstance() {
public Copyable createCopyInstance() { return new LinkedPolygon();
return new LinkedPolygon(); }
}
@Override
@Override public void fillValues(Copyable original, CopyHandler handler) {
public void fillValues(Copyable original, CopyHandler handler) { LinkedPolygon linkedOriginal = (LinkedPolygon) original;
LinkedPolygon linkedOriginal = (LinkedPolygon) original; parent = handler.getCopyInstance(linkedOriginal.parent);
parent = handler.getCopyInstance(linkedOriginal.parent); poly = handler.getCopyInstance(linkedOriginal.poly);
poly = handler.getCopyInstance(linkedOriginal.poly); }
}
@Override
@Override public void remove() {
public void remove() { poly.remove();
poly.remove(); }
}
@Override
@Override public double getArea() {
public double getArea() { return poly.getArea();
return poly.getArea(); }
}
} }
/*- /*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
* *
* This file is part of CityDoctor2. * This file is part of CityDoctor2.
* *
* CityDoctor2 is free software: you can redistribute it and/or modify * CityDoctor2 is free software: you can redistribute it and/or modify
...@@ -20,24 +20,23 @@ package de.hft.stuttgart.citydoctor2.datastructure; ...@@ -20,24 +20,23 @@ package de.hft.stuttgart.citydoctor2.datastructure;
/** /**
* The different LODs available in CityGML * The different LODs available in CityGML
*
* @author Matthias Betz
* *
* @author Matthias Betz
*/ */
public enum Lod { public enum Lod {
LOD0(0), LOD1(1), LOD2(2), LOD3(3), LOD4(4); LOD0(0), LOD1(1), LOD2(2), LOD3(3), LOD4(4);
private final int rank; private final int rank;
private Lod(int rank) { private Lod(int rank) {
this.rank = rank; this.rank = rank;
} }
public boolean isHigher(Lod other) { public boolean isHigher(Lod other) {
if (other == null) { if (other == null) {
return true; return true;
} }
return rank > other.rank; return rank > other.rank;
} }
} }
/*- /*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
* *
* This file is part of CityDoctor2. * This file is part of CityDoctor2.
* *
* CityDoctor2 is free software: you can redistribute it and/or modify * CityDoctor2 is free software: you can redistribute it and/or modify
...@@ -18,17 +18,16 @@ ...@@ -18,17 +18,16 @@
*/ */
package de.hft.stuttgart.citydoctor2.datastructure; package de.hft.stuttgart.citydoctor2.datastructure;
import org.citygml4j.core.model.construction.AbstractFillingSurface;
import org.citygml4j.core.model.core.AbstractCityObject;
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.Check;
import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration; import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;
import de.hft.stuttgart.citydoctor2.utils.CityGmlUtils; import de.hft.stuttgart.citydoctor2.utils.CityGmlUtils;
import de.hft.stuttgart.citydoctor2.utils.CopyHandler; import de.hft.stuttgart.citydoctor2.utils.CopyHandler;
import de.hft.stuttgart.citydoctor2.utils.Copyable; import de.hft.stuttgart.citydoctor2.utils.Copyable;
import org.citygml4j.core.model.construction.AbstractFillingSurface;
import org.citygml4j.core.model.core.AbstractCityObject;
import org.citygml4j.core.util.geometry.GeometryFactory;
import org.xmlobjects.gml.model.geometry.aggregates.MultiSurface;
import org.xmlobjects.gml.model.geometry.aggregates.MultiSurfaceProperty;
import java.io.Serial; import java.io.Serial;
...@@ -36,145 +35,144 @@ import java.io.Serial; ...@@ -36,145 +35,144 @@ import java.io.Serial;
* Represents an Opening suchs a window or Door in a surface of a feature. * Represents an Opening suchs a window or Door in a surface of a feature.
* Contains a reference to the boundary surface where this opening is embedded * Contains a reference to the boundary surface where this opening is embedded
* in. * in.
*
* @author Matthias Betz
* *
* @author Matthias Betz
*/ */
public class Opening extends CityObject { public class Opening extends CityObject {
@Serial @Serial
private static final long serialVersionUID = 6409303152284607944L; private static final long serialVersionUID = 6409303152284607944L;
private BoundarySurface partOf; private BoundarySurface partOf;
private OpeningType type; private OpeningType type;
private SurfaceFeatureType featureType; private SurfaceFeatureType featureType;
private AbstractFillingSurface ao; private AbstractFillingSurface ao;
private Opening(OpeningType type) { private Opening(OpeningType type) {
this.type = type; this.type = type;
} }
public Opening(OpeningType type, SurfaceFeatureType featureType, BoundarySurface partOf, public Opening(OpeningType type, SurfaceFeatureType featureType, BoundarySurface partOf,
AbstractFillingSurface ao) { AbstractFillingSurface ao) {
this.featureType = featureType; this.featureType = featureType;
this.partOf = partOf; this.partOf = partOf;
this.type = type; this.type = type;
this.ao = ao; this.ao = ao;
} }
public void reCreateGeometries(GeometryFactory factory, ParserConfiguration config) { public void reCreateGeometries(GeometryFactory factory, ParserConfiguration config) {
if (ao.getId() != null) { if (ao.getId() != null) {
ao.setId(getGmlId().getGmlString()); ao.setId(getGmlId().getGmlString());
} }
for (Geometry geom : getGeometries()) { for (Geometry geom : getGeometries()) {
if (geom.getType() == GeometryType.MULTI_SURFACE) { if (geom.getType() == GeometryType.MULTI_SURFACE) {
MultiSurface ms = CityGmlUtils.createMultiSurface(geom, factory, config); MultiSurface ms = CityGmlUtils.createMultiSurface(geom, factory, config);
setGeometryAccordingToLod(geom.getLod(), new MultiSurfaceProperty(ms)); setGeometryAccordingToLod(geom.getLod(), new MultiSurfaceProperty(ms));
} else { } else {
throw new IllegalStateException("Openings can only have MultiSurface geometries"); throw new IllegalStateException("Openings can only have MultiSurface geometries");
} }
} }
} }
private void setGeometryAccordingToLod(Lod lod, MultiSurfaceProperty ms) { private void setGeometryAccordingToLod(Lod lod, MultiSurfaceProperty ms) {
switch (lod) { switch (lod) {
case LOD0: case LOD0:
ao.setLod0MultiSurface(ms); ao.setLod0MultiSurface(ms);
break; break;
case LOD1: case LOD1:
ao.setLod1MultiSurface(ms); ao.setLod1MultiSurface(ms);
break; break;
case LOD2: case LOD2:
ao.setLod2MultiSurface(ms); ao.setLod2MultiSurface(ms);
break; break;
case LOD3: case LOD3:
ao.setLod3MultiSurface(ms); ao.setLod3MultiSurface(ms);
break; break;
case LOD4: case LOD4:
ao.getDeprecatedProperties().setLod4MultiSurface(ms); ao.getDeprecatedProperties().setLod4MultiSurface(ms);
break; break;
default: default:
throw new IllegalStateException("Cannot add geometry to opening because lod is not allowed: " + lod); throw new IllegalStateException("Cannot add geometry to opening because lod is not allowed: " + lod);
} }
} }
public SurfaceFeatureType getSurfaceFeatureType() { public SurfaceFeatureType getSurfaceFeatureType() {
return featureType; return featureType;
} }
public BoundarySurface getPartOf() { public BoundarySurface getPartOf() {
return partOf; return partOf;
} }
public void setType(OpeningType type) { public void setType(OpeningType type) {
this.type = type; this.type = type;
} }
public OpeningType getType() { public OpeningType getType() {
return type; return type;
} }
@Override @Override
public void accept(Check c) { public void accept(Check c) {
super.accept(c); super.accept(c);
if (c.canExecute(this)) { if (c.canExecute(this)) {
c.check(this); c.check(this);
} }
} }
@Override @Override
public void clearAllContainedCheckResults() { public void clearAllContainedCheckResults() {
super.clearCheckResults(); super.clearCheckResults();
} }
public void unsetGmlGeometries() { public void unsetGmlGeometries() {
ao.setLod0MultiSurface(null); ao.setLod0MultiSurface(null);
ao.setLod1MultiSurface(null); ao.setLod1MultiSurface(null);
ao.setLod2MultiSurface(null); ao.setLod2MultiSurface(null);
ao.setLod3MultiSurface(null); ao.setLod3MultiSurface(null);
ao.getDeprecatedProperties().setLod4MultiSurface(null); ao.getDeprecatedProperties().setLod4MultiSurface(null);
} }
@Override @Override
public String toString() { public String toString() {
return "Opening [type=" + type + ", id=" + getGmlId() + "]"; return "Opening [type=" + type + ", id=" + getGmlId() + "]";
} }
public void setPartOfSurface(BoundarySurface boundarySurface) { public void setPartOfSurface(BoundarySurface boundarySurface) {
partOf = boundarySurface; partOf = boundarySurface;
} }
@Override @Override
public AbstractCityObject getGmlObject() { public AbstractCityObject getGmlObject() {
return ao; return ao;
} }
@Override @Override
public FeatureType getFeatureType() { public FeatureType getFeatureType() {
return FeatureType.OPENING; return FeatureType.OPENING;
} }
@Override @Override
public Copyable createCopyInstance() { public Copyable createCopyInstance() {
return new Opening(type); return new Opening(type);
} }
@Override @Override
public void collectInstances(CopyHandler handler) { public void collectInstances(CopyHandler handler) {
super.collectInstances(handler); super.collectInstances(handler);
handler.addInstance(partOf); handler.addInstance(partOf);
} }
@Override @Override
public void fillValues(Copyable original, CopyHandler handler) { public void fillValues(Copyable original, CopyHandler handler) {
super.fillValues(original, handler); super.fillValues(original, handler);
Opening originalOpening = (Opening) original; Opening originalOpening = (Opening) original;
partOf = handler.getCopyInstance(originalOpening.partOf); partOf = handler.getCopyInstance(originalOpening.partOf);
type = originalOpening.type; type = originalOpening.type;
featureType = originalOpening.featureType; featureType = originalOpening.featureType;
ao = originalOpening.ao; ao = originalOpening.ao;
} }
} }
/*- /*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
* *
* This file is part of CityDoctor2. * This file is part of CityDoctor2.
* *
* CityDoctor2 is free software: you can redistribute it and/or modify * CityDoctor2 is free software: you can redistribute it and/or modify
...@@ -20,12 +20,11 @@ package de.hft.stuttgart.citydoctor2.datastructure; ...@@ -20,12 +20,11 @@ package de.hft.stuttgart.citydoctor2.datastructure;
/** /**
* The available opening types in CityGML * The available opening types in CityGML
*
* @author Matthias Betz
* *
* @author Matthias Betz
*/ */
public enum OpeningType { public enum OpeningType {
DOOR, WINDOW, UNKNOWN DOOR, WINDOW, UNKNOWN
} }
/*- /*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
* *
* This file is part of CityDoctor2. * This file is part of CityDoctor2.
* *
* CityDoctor2 is free software: you can redistribute it and/or modify * CityDoctor2 is free software: you can redistribute it and/or modify
...@@ -18,70 +18,70 @@ ...@@ -18,70 +18,70 @@
*/ */
package de.hft.stuttgart.citydoctor2.datastructure; 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.math.Vector3d;
import de.hft.stuttgart.citydoctor2.tesselation.TesselatedPolygon; import de.hft.stuttgart.citydoctor2.tesselation.TesselatedPolygon;
import java.io.Serial;
import java.util.List;
/** /**
* Interface for concrete and linked polygons. * Interface for concrete and linked polygons.
*
* @author Matthias Betz
* *
* @author Matthias Betz
*/ */
public abstract class Polygon extends GmlElement { public abstract class Polygon extends GmlElement {
@Serial @Serial
private static final long serialVersionUID = -613942946364706513L; private static final long serialVersionUID = -613942946364706513L;
public abstract Vector3d calculateNormalNormalized();
public abstract Vector3d calculateNormal();
public abstract TesselatedPolygon tesselate();
public abstract Vector3d calculateNormalNormalized(); public abstract LinearRing getExteriorRing();
public abstract Vector3d calculateNormal();
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 double getArea();
public abstract void remove();
public abstract double getArea();
} }
\ No newline at end of file
package de.hft.stuttgart.citydoctor2.datastructure; package de.hft.stuttgart.citydoctor2.datastructure;
import de.hft.stuttgart.citydoctor2.utils.CopyHandler;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
...@@ -10,6 +9,8 @@ import java.util.HashMap; ...@@ -10,6 +9,8 @@ import java.util.HashMap;
/** /**
* Reference object for handling of implicit geometries with a relative geometry * Reference object for handling of implicit geometries with a relative geometry
*
* @author Riegel
*/ */
public class RelativeGeometry extends Geometry { public class RelativeGeometry extends Geometry {
...@@ -17,16 +18,16 @@ public class RelativeGeometry extends Geometry { ...@@ -17,16 +18,16 @@ public class RelativeGeometry extends Geometry {
@Serial @Serial
private static final long serialVersionUID = -686112245455298977L; private static final long serialVersionUID = -686112245455298977L;
private static HashMap<Geometry,RelativeGeometry> relativeGeometries = new HashMap<>(); private static HashMap<Geometry, RelativeGeometry> relativeGeometries = new HashMap<>();
public static RelativeGeometry of(Geometry geom){ public static RelativeGeometry of(Geometry geom) {
if (relativeGeometries.containsKey(geom)){ if (relativeGeometries.containsKey(geom)) {
return relativeGeometries.get(geom); return relativeGeometries.get(geom);
} }
RelativeGeometry relGeo = new RelativeGeometry(geom.getType(),geom.getLod()); RelativeGeometry relGeo = new RelativeGeometry(geom.getType(), geom.getLod());
geom.getPolygons().forEach(relGeo::addPolygon); geom.getPolygons().forEach(relGeo::addPolygon);
relGeo.updateEdgesAndVertices(); relGeo.updateEdgesAndVertices();
relativeGeometries.put(geom,relGeo); relativeGeometries.put(geom, relGeo);
return relGeo; return relGeo;
} }
......
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