CityGmlUtils.java 6.87 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
/*-
 *  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;

Matthias Betz's avatar
Matthias Betz committed
24
import org.citygml4j.core.util.geometry.GeometryFactory;
25
26
import org.locationtech.proj4j.BasicCoordinateTransform;
import org.locationtech.proj4j.ProjCoordinate;
Matthias Betz's avatar
Matthias Betz committed
27
28
29
30
31
32
33
import org.xmlobjects.gml.model.geometry.aggregates.MultiSurface;
import org.xmlobjects.gml.model.geometry.complexes.CompositeSurface;
import org.xmlobjects.gml.model.geometry.primitives.AbstractRingProperty;
import org.xmlobjects.gml.model.geometry.primitives.Shell;
import org.xmlobjects.gml.model.geometry.primitives.ShellProperty;
import org.xmlobjects.gml.model.geometry.primitives.Solid;
import org.xmlobjects.gml.model.geometry.primitives.SurfaceProperty;
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

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
	}

Matthias Betz's avatar
Matthias Betz committed
54
	public static org.xmlobjects.gml.model.geometry.primitives.Polygon createGmlPolygon(GeometryFactory factory,
55
56
57
58
			Polygon cdPoly, ParserConfiguration config) {
		if (cdPoly.getExteriorRing() == null) {
			return null;
		}
Matthias Betz's avatar
Matthias Betz committed
59
60
61
		org.xmlobjects.gml.model.geometry.primitives.Polygon gmlPoly = new org.xmlobjects.gml.model.geometry.primitives.Polygon();
		// exterior ring
		LinearRing extLr = cdPoly.getExteriorRing();
62
63
64
65
66
		if (extLr.getVertices().size() < 3) {
			// this ring does not have enough points in it
			// this leads to errors when exporting therefore ignore it
			return null;
		}
Matthias Betz's avatar
Matthias Betz committed
67
68
		org.xmlobjects.gml.model.geometry.primitives.LinearRing gmlLr = createGmlRing(factory, config, extLr);
		gmlPoly.setExterior(new AbstractRingProperty(gmlLr));
69

Matthias Betz's avatar
Matthias Betz committed
70
71
72
		// interior rings
		for (LinearRing lr : cdPoly.getInnerRings()) {
			gmlLr = createGmlRing(factory, config, lr);
73
74
75
76
77
			if (lr.getVertices().size() < 3) {
				// this ring does not have enough points in it
				// this leads to errors when exporting therefore ignore it
				return null;
			}
Matthias Betz's avatar
Matthias Betz committed
78
			gmlPoly.getInterior().add(new AbstractRingProperty(gmlLr));
79
		}
Matthias Betz's avatar
Matthias Betz committed
80
81
		gmlPoly.setId(cdPoly.getGmlId().getGmlString());
		return gmlPoly;
82
83
	}

84
	public static org.xmlobjects.gml.model.geometry.primitives.LinearRing createGmlRing(GeometryFactory factory,
Matthias Betz's avatar
Matthias Betz committed
85
			ParserConfiguration config, LinearRing lr) {
86

87
88
89
90
91
92
93
94
95
96
97
98
99
100
		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;
101
				z = z * config.getFromMeters();
102
103
104
105
106
			}
			ringValues.add(x);
			ringValues.add(y);
			ringValues.add(z);
		}
107

Matthias Betz's avatar
Matthias Betz committed
108
		org.xmlobjects.gml.model.geometry.primitives.LinearRing gmlLr = factory.createLinearRing(ringValues, 3);
109
110
111
112
		gmlLr.setId(lr.getGmlId().getGmlString());
		return gmlLr;
	}

Matthias Betz's avatar
Matthias Betz committed
113
	public static Solid createSolid(Geometry geom, GeometryFactory factory, ParserConfiguration config) {
114
115
116
117
		if (geom.getType() != GeometryType.SOLID) {
			throw new IllegalArgumentException("Only solids are allowed");
		}

Matthias Betz's avatar
Matthias Betz committed
118
119
		CompositeSurface comp = new CompositeSurface();
		List<SurfaceProperty> surfaceMember = comp.getSurfaceMembers();
120
121
		for (Polygon cdPoly : geom.getPolygons()) {
			if (!cdPoly.isLink()) {
Matthias Betz's avatar
Matthias Betz committed
122
				org.xmlobjects.gml.model.geometry.primitives.Polygon gmlPoly = createGmlPolygon(factory, cdPoly, config);
123
124
125
126
127
128
129
130
131
132
133
134
135
				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;
		}
		Solid solid = new Solid();
Matthias Betz's avatar
Matthias Betz committed
136
137
		Shell shell = new Shell(surfaceMember);
		solid.setExterior(new ShellProperty(shell));
138
139
140
141
		solid.setId(geom.getGmlId().getGmlString());
		return solid;
	}

Matthias Betz's avatar
Matthias Betz committed
142
	public static MultiSurface createMultiSurface(Geometry geom, GeometryFactory factory,
143
144
145
146
			ParserConfiguration config) {
		if (geom.getType() != GeometryType.MULTI_SURFACE) {
			throw new IllegalArgumentException("This can only handle MultiSurfaces");
		}
Matthias Betz's avatar
Matthias Betz committed
147
		List<SurfaceProperty> surfaces = new ArrayList<>();
148
149
150
		for (Polygon cdPoly : geom.getPolygons()) {
			if (!cdPoly.isLink()) {
				// is not part of a boundary surface
Matthias Betz's avatar
Matthias Betz committed
151
				org.xmlobjects.gml.model.geometry.primitives.Polygon gmlPoly = createGmlPolygon(factory, cdPoly, config);
152
				if (gmlPoly != null) {
Matthias Betz's avatar
Matthias Betz committed
153
					surfaces.add(new SurfaceProperty(gmlPoly));
154
155
156
				}
			} else {
				// add reference to polygon
Matthias Betz's avatar
Matthias Betz committed
157
				surfaces.add(new SurfaceProperty("#" + cdPoly.getGmlId().getGmlString()));
158
159
160
161
162
163
164
165
166
167
			}
		}
		if (surfaces.isEmpty()) {
			return null;
		}
		MultiSurface ms = new MultiSurface(surfaces);
		ms.setId(geom.getGmlId().getGmlString());
		return ms;
	}

Matthias Betz's avatar
Matthias Betz committed
168
	public static MultiSurface createMultiSurface(List<Polygon> polygons, GeometryFactory factory,
169
			ParserConfiguration config) {
Matthias Betz's avatar
Matthias Betz committed
170
		List<SurfaceProperty> surfaces = new ArrayList<>();
171
		for (Polygon cdPoly : polygons) {
Matthias Betz's avatar
Matthias Betz committed
172
			org.xmlobjects.gml.model.geometry.primitives.Polygon gmlPoly = createGmlPolygon(factory, cdPoly, config);
173
			if (gmlPoly != null) {
Matthias Betz's avatar
Matthias Betz committed
174
				surfaces.add(new SurfaceProperty(gmlPoly));
175
176
177
178
179
180
181
182
			}
		}
		if (surfaces.isEmpty()) {
			return null;
		}
		return new MultiSurface(surfaces);
	}

Matthias Betz's avatar
Matthias Betz committed
183
	public static CompositeSurface createCompositeSurface(Geometry geom, GeometryFactory factory,
Matthias Betz's avatar
Matthias Betz committed
184
			ParserConfiguration config) {
Matthias Betz's avatar
Matthias Betz committed
185
		List<SurfaceProperty> surfaces = new ArrayList<>();
Matthias Betz's avatar
Matthias Betz committed
186
		for (Polygon cdPoly : geom.getPolygons()) {
Matthias Betz's avatar
Matthias Betz committed
187
			org.xmlobjects.gml.model.geometry.primitives.Polygon gmlPoly = createGmlPolygon(factory, cdPoly, config);
Matthias Betz's avatar
Matthias Betz committed
188
			if (gmlPoly != null) {
Matthias Betz's avatar
Matthias Betz committed
189
				surfaces.add(new SurfaceProperty(gmlPoly));
Matthias Betz's avatar
Matthias Betz committed
190
191
192
193
194
195
196
197
			}
		}
		if (surfaces.isEmpty()) {
			return null;
		}
		return new CompositeSurface(surfaces);
	}

198
}