CityGmlUtils.java 6.7 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/*-
 *  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 <https://www.gnu.org/licenses/>.
 */
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.osgeo.proj4j.BasicCoordinateTransform;
import org.osgeo.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;
		}
	}

	private 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<Double> 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<SurfaceProperty> 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<AbstractSurface> 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<Polygon> polygons, GMLGeometryFactory factory,
			ParserConfiguration config) {
		List<AbstractSurface> 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);
	}

Matthias Betz's avatar
Matthias Betz committed
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
	public static CompositeSurface createCompositeSurface(Geometry geom, GMLGeometryFactory factory,
			ParserConfiguration config) {
		List<AbstractSurface> 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);
	}

194
}