/*- * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart * * This file is part of CityDoctor2. * * CityDoctor2 is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CityDoctor2 is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with CityDoctor2. If not, see . */ package de.hft.stuttgart.citydoctor2.utils; import java.util.ArrayList; import java.util.List; import org.citygml4j.factory.DimensionMismatchException; import org.citygml4j.factory.GMLGeometryFactory; import org.citygml4j.model.gml.geometry.aggregates.MultiSurface; import org.citygml4j.model.gml.geometry.complexes.CompositeSurface; import org.citygml4j.model.gml.geometry.primitives.AbstractSurface; import org.citygml4j.model.gml.geometry.primitives.Exterior; import org.citygml4j.model.gml.geometry.primitives.Interior; import org.citygml4j.model.gml.geometry.primitives.Solid; import org.citygml4j.model.gml.geometry.primitives.SurfaceProperty; import org.locationtech.proj4j.BasicCoordinateTransform; import org.locationtech.proj4j.ProjCoordinate; import de.hft.stuttgart.citydoctor2.datastructure.Geometry; import de.hft.stuttgart.citydoctor2.datastructure.GeometryType; import de.hft.stuttgart.citydoctor2.datastructure.LinearRing; import de.hft.stuttgart.citydoctor2.datastructure.Polygon; import de.hft.stuttgart.citydoctor2.datastructure.Vertex; import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration; /** * Utility class dedicated to create CityGML4j datastructures. * * @author Matthias Betz * */ public final class CityGmlUtils { private CityGmlUtils() { // util class } public static org.citygml4j.model.gml.geometry.primitives.Polygon createGmlPolygon(GMLGeometryFactory factory, Polygon cdPoly, ParserConfiguration config) { if (cdPoly.getExteriorRing() == null) { return null; } org.citygml4j.model.gml.geometry.primitives.Polygon gmlPoly = new org.citygml4j.model.gml.geometry.primitives.Polygon(); try { // exterior ring LinearRing extLr = cdPoly.getExteriorRing(); org.citygml4j.model.gml.geometry.primitives.LinearRing gmlLr = createGmlRing(factory, config, extLr); gmlPoly.setExterior(new Exterior(gmlLr)); // interior rings for (LinearRing lr : cdPoly.getInnerRings()) { gmlLr = createGmlRing(factory, config, lr); gmlPoly.addInterior(new Interior(gmlLr)); } gmlPoly.setId(cdPoly.getGmlId().getGmlString()); return gmlPoly; } catch (DimensionMismatchException e) { // cannot happen as every vertex has 3 coordinates return null; } } public static org.citygml4j.model.gml.geometry.primitives.LinearRing createGmlRing(GMLGeometryFactory factory, ParserConfiguration config, LinearRing lr) throws DimensionMismatchException { ProjCoordinate p1 = new ProjCoordinate(); ProjCoordinate p2 = new ProjCoordinate(); List ringValues = new ArrayList<>(); BasicCoordinateTransform trans = config.getOriginalTransform(); for (Vertex v : lr.getVertices()) { double x = v.getX(); double y = v.getY(); double z = v.getZ(); if (trans != null) { p1.x = x; p1.y = y; trans.transform(p1, p2); x = p2.x; y = p2.y; z = z * config.getFromMetres(); } ringValues.add(x); ringValues.add(y); ringValues.add(z); } org.citygml4j.model.gml.geometry.primitives.LinearRing gmlLr = factory.createLinearRing(ringValues, 3); gmlLr.setId(lr.getGmlId().getGmlString()); return gmlLr; } public static Solid createSolid(Geometry geom, GMLGeometryFactory factory, ParserConfiguration config) { if (geom.getType() != GeometryType.SOLID) { throw new IllegalArgumentException("Only solids are allowed"); } List surfaceMember = new ArrayList<>(); for (Polygon cdPoly : geom.getPolygons()) { if (!cdPoly.isLink()) { org.citygml4j.model.gml.geometry.primitives.Polygon gmlPoly = createGmlPolygon(factory, cdPoly, config); if (gmlPoly != null) { surfaceMember.add(new SurfaceProperty(gmlPoly)); } } else { // add reference to polygon surfaceMember.add(new SurfaceProperty("#" + cdPoly.getGmlId().getGmlString())); } } if (surfaceMember.isEmpty()) { return null; } CompositeSurface comp = new CompositeSurface(); comp.setSurfaceMember(surfaceMember); Solid solid = new Solid(); solid.setExterior(new SurfaceProperty(comp)); solid.setId(geom.getGmlId().getGmlString()); return solid; } public static MultiSurface createMultiSurface(Geometry geom, GMLGeometryFactory factory, ParserConfiguration config) { if (geom.getType() != GeometryType.MULTI_SURFACE) { throw new IllegalArgumentException("This can only handle MultiSurfaces"); } List surfaces = new ArrayList<>(); for (Polygon cdPoly : geom.getPolygons()) { if (!cdPoly.isLink()) { // is not part of a boundary surface org.citygml4j.model.gml.geometry.primitives.Polygon gmlPoly = createGmlPolygon(factory, cdPoly, config); if (gmlPoly != null) { surfaces.add(gmlPoly); } } else { // add reference to polygon CompositeSurface cs = new CompositeSurface(); cs.addSurfaceMember(new SurfaceProperty("#" + cdPoly.getGmlId().getGmlString())); surfaces.add(cs); } } if (surfaces.isEmpty()) { return null; } MultiSurface ms = new MultiSurface(surfaces); ms.setId(geom.getGmlId().getGmlString()); return ms; } public static MultiSurface createMultiSurface(List polygons, GMLGeometryFactory factory, ParserConfiguration config) { List surfaces = new ArrayList<>(); for (Polygon cdPoly : polygons) { org.citygml4j.model.gml.geometry.primitives.Polygon gmlPoly = createGmlPolygon(factory, cdPoly, config); if (gmlPoly != null) { surfaces.add(gmlPoly); } } if (surfaces.isEmpty()) { return null; } return new MultiSurface(surfaces); } public static CompositeSurface createCompositeSurface(Geometry geom, GMLGeometryFactory factory, ParserConfiguration config) { List surfaces = new ArrayList<>(); for (Polygon cdPoly : geom.getPolygons()) { org.citygml4j.model.gml.geometry.primitives.Polygon gmlPoly = createGmlPolygon(factory, cdPoly, config); if (gmlPoly != null) { surfaces.add(gmlPoly); } } if (surfaces.isEmpty()) { return null; } return new CompositeSurface(surfaces); } }