Commit fdfd472b authored by Riegel's avatar Riegel
Browse files

Add data structure support for ImplicitGeometry

parent c949352d
package de.hft.stuttgart.citydoctor2.datastructure;
import de.hft.stuttgart.citydoctor2.check.Check;
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.Logger;
import org.citygml4j.core.model.core.ImplicitGeometry;
import java.io.Serial;
/**
* Datastructure for representation of implicit geometries
*/
public class ImplicitGeometryHolder extends Geometry{
private static final Logger logger = LogManager.getLogger(LibraryObject.class);
@Serial
private static final long serialVersionUID = -8938931081577196349L;
private ImplicitGeometry cgmlImplicitGeometry = null;
/*
LibraryObject and RelativeGeometry are mutually exclusive
*/
private final LibraryObject libObject;
private final RelativeGeometry relativeGeom;
public ImplicitGeometryHolder(ImplicitGeometry cgmlImplicitGeometry, LibraryObject libObject) {
super(libObject.getType(), libObject.getLod());
this.libObject = libObject;
this.relativeGeom = null;
this.cgmlImplicitGeometry = cgmlImplicitGeometry;
applyTransformation();
}
public ImplicitGeometryHolder(ImplicitGeometry cgmlImplicitGeometry, RelativeGeometry relativeGeometry) {
super(relativeGeometry.getType(),relativeGeometry.getLod());
this.libObject = null;
this.relativeGeom = relativeGeometry;
this.cgmlImplicitGeometry = cgmlImplicitGeometry;
applyTransformation();
}
@Override
public void accept(Check c) {
/**
* Checks are only run on the referenced prototypical geometry.
*/
if (relativeGeom != null) {
relativeGeom.accept(c);
}
if (libObject != null) {
libObject.accept(c);
}
}
/**
* Applies the transformation matrix of the implicit geometry to a copy of the reference geometry and copies the resulting
* transformed geometry into this object.
*/
private void applyTransformation(){
TransformationMatrix transformMatrix = new TransformationMatrix(cgmlImplicitGeometry);
Geometry refGeo = null;
if (libObject == null){
refGeo = relativeGeom;
} else if (relativeGeom == null){
refGeo = libObject;
}
if (refGeo == null){
throw new NullPointerException("Geometry reference object of ImplicitGeometryHolder is null!");
}
Geometry transformedGeom = transformMatrix.transformGeometry(refGeo);
transformedGeom.getPolygons().forEach(this::addPolygon);
this.updateEdgesAndVertices();
}
}
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.CityGmlParser;
import de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException;
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.Logger;
import java.io.Serial;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.List;
/**
* Reference object for handling of implicit geometries with a library object contained in an external file
*/
public class LibraryObject extends Geometry{
private static final Logger logger = LogManager.getLogger(LibraryObject.class);
@Serial
private static final long serialVersionUID = -50293435187454911L;
private final String filepath;
private final ParserConfiguration config;
private static HashMap<String,LibraryObject> libraryObjects = new HashMap<>();
public static LibraryObject of(Path path, ParserConfiguration config) {
if (libraryObjects.containsKey(path)) {
return libraryObjects.get(path);
}
Geometry protoGeom = parseFile(path, config);
if (protoGeom == null) {
return null;
}
LibraryObject libOb = new LibraryObject(protoGeom.getType(),protoGeom.getLod(),path, config);
protoGeom.getPolygons().forEach(libOb::addPolygon);
libOb.updateEdgesAndVertices();
libraryObjects.put(path.toString(), libOb);
return libOb;
}
private LibraryObject(GeometryType type, Lod lod, Path path, ParserConfiguration config) {
super(type,lod);
this.filepath = path.toString();
this.config = config;
}
private static Geometry parseFile(Path path, ParserConfiguration config) {
Geometry geo = null;
if (path.toFile().exists()){
try {
CityGmlParser.gagLogger(true);
CityDoctorModel model = CityGmlParser.parseCityGmlFile(path.toString(), config);
List<CityObject> objects = model.createFeatureStream().toList();
if (objects.isEmpty()){
throw new InvalidGmlFileException("Referenced library-object's gml file does not contain a CityGML object!");
} else if (objects.size() > 1){
throw new InvalidGmlFileException("Referenced library-object's gml file contains more than one CityGML object!");
}
geo = objects.get(0).getHighestLodGeometry();
} catch (CityGmlParseException e){
logger.error(String.format(
"Encountered an error while parsing library object %s", path));
logger.error(e.getStackTrace());
} catch (InvalidGmlFileException e){
logger.error(e.getStackTrace());
} finally {
// Failsafe to remove gag should parsing fail
CityGmlParser.gagLogger(false);
}
} else{
logger.error(String.format("Implicit geometry references non-existing library object file %s.", path));
}
return geo;
}
}
package de.hft.stuttgart.citydoctor2.datastructure;
import de.hft.stuttgart.citydoctor2.utils.CopyHandler;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.Serial;
import java.util.HashMap;
/**
* Reference object for handling of implicit geometries with a relative geometry
*/
public class RelativeGeometry extends Geometry {
private static final Logger logger = LogManager.getLogger(RelativeGeometry.class);
@Serial
private static final long serialVersionUID = -686112245455298977L;
private static HashMap<Geometry,RelativeGeometry> relativeGeometries = new HashMap<>();
public static RelativeGeometry of(Geometry geom){
if (relativeGeometries.containsKey(geom)){
return relativeGeometries.get(geom);
}
RelativeGeometry relGeo = new RelativeGeometry(geom.getType(),geom.getLod());
geom.getPolygons().forEach(relGeo::addPolygon);
relGeo.updateEdgesAndVertices();
relativeGeometries.put(geom,relGeo);
return relGeo;
}
private RelativeGeometry(GeometryType type, Lod lod) {
super(type, lod);
}
}
package de.hft.stuttgart.citydoctor2.math;
import Jama.Matrix;
import de.hft.stuttgart.citydoctor2.datastructure.*;
import de.hft.stuttgart.citydoctor2.utils.Copy;
import org.citygml4j.core.model.core.ImplicitGeometry;
import org.citygml4j.core.model.core.TransformationMatrix4x4;
import org.xmlobjects.gml.model.geometry.primitives.Point;
import org.xmlobjects.gml.model.geometry.primitives.PointProperty;
import org.xmlobjects.util.copy.CopyBuilder;
import java.util.*;
/**
* Adapter class for CityGML-TransformationMatrix4x4
*/
public class TransformationMatrix {
private final TransformationMatrix4x4 originalTM4x4;
private Matrix tMatrix;
/**
* The {@code TransformationMatrix} class is an adapter for applying the {@link TransformationMatrix4x4} of implicitGeometries to geometries
* of CityDoctor's internal model.
* @param transformationMatrix the transformation matrix.
* @param pointProperty the reference point for the translation of the geometry's position.
*/
public TransformationMatrix(TransformationMatrix4x4 transformationMatrix, PointProperty pointProperty) {
originalTM4x4 = transformationMatrix;
setupMatrix();
incorporateRefPoint(pointProperty);
}
/**
* The {@code TransformationMatrix} class is an adapter for applying the {@link TransformationMatrix4x4} of implicitGeometries to geometries
* of CityDoctor's internal model.
* @param implicitGeometry the implicitGeometry containing the TransformationMatrix and ReferencePoint.
*/
public TransformationMatrix(ImplicitGeometry implicitGeometry) {
originalTM4x4 = implicitGeometry.getTransformationMatrix();
setupMatrix();
incorporateRefPoint(implicitGeometry.getReferencePoint());
}
private void setupMatrix() {
double[][] matrix = new double[4][4];
CopyBuilder copyBuilder = new CopyBuilder();
TransformationMatrix4x4 tmMatrix = (TransformationMatrix4x4) originalTM4x4.deepCopy(copyBuilder);
List<Double> tmValues = tmMatrix.toRowMajorList();
for (int i = 0; i < 4 ; i++){
for (int j = 0; j < 4 ; j++){
matrix[i][j] = tmValues.get(i*4+j);
}
}
tMatrix = new Matrix(matrix);
}
private void incorporateRefPoint(PointProperty pointProperty) {
Point refPoint = pointProperty.getObject();
List<Double> refCoord = refPoint.getPos().toCoordinateList3D();
double [][] tArray = tMatrix.getArray();
tArray[0][3] = refCoord.get(0);
tArray[1][3] = refCoord.get(1);
tArray[2][3] = refCoord.get(2);
}
/**
* Transforms a vector with the transformation matrix.
* @param referenceGeom reference geometry to transform.
* @return A transformed copy of {@code referenceGeom}.
*/
public Geometry transformGeometry(Geometry referenceGeom) {
// Create deep copy of reference geom
Geometry geom = Copy.copy(referenceGeom);
Map<Vertex, Boolean> visitedVertices = new IdentityHashMap<>();
Set<Vertex> visitedVerticesSet = Collections.newSetFromMap(visitedVertices);
// Transform all vertices
for (Polygon polygon : geom.getPolygons()){
for (Vertex vertex : polygon.getExteriorRing().getVertices()){
if (!visitedVerticesSet.contains(vertex)){
transformVector3D(vertex);
visitedVerticesSet.add(vertex);
}
}
for (LinearRing ring : polygon.getInnerRings()){
for (Vertex vertex : ring.getVertices()){
if (!visitedVerticesSet.contains(vertex)){
transformVector3D(vertex);
visitedVerticesSet.add(vertex);
}
}
}
}
geom.updateEdgesAndVertices();
return geom;
}
public void transformVector3D(Vector3d vector) {
double[] tfVector = new double[]{vector.getX(), vector.getY(), vector.getZ(), 1d};
Matrix vectorMatrix = new Matrix(tfVector,4);
Matrix res = tMatrix.times(vectorMatrix);
double[] resultVector = res.getRowPackedCopy();
vector.setX(resultVector[0]);
vector.setY(resultVector[1]);
vector.setZ(resultVector[2]);
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment