TreeGenerator.java 7.21 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
package de.hft.stuttgart.citygml.green.osm;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Polygon;
import org.xmlobjects.gml.model.geometry.aggregates.MultiSurface;
import org.xmlobjects.gml.model.geometry.primitives.SurfaceProperty;

public class TreeGenerator {
	
	private static final double TRUNK_INCREASE_FACTOR = 1.2;
	public static MultiSurface generateTree(Coordinate point, double trunkRadius, double trunkHeight,
			double crownXRadius, double crownYRadius, double crownHeight) {

		List<Coordinate> trunkWestCoordinateList = new ArrayList<>();
		trunkWestCoordinateList.add(new Coordinate(point.x - trunkRadius, point.y - trunkRadius, 0));
		double drawTrunkHeight = trunkHeight * TRUNK_INCREASE_FACTOR;
		trunkWestCoordinateList.add(new Coordinate(point.x - trunkRadius, point.y - trunkRadius, drawTrunkHeight));
		trunkWestCoordinateList.add(new Coordinate(point.x - trunkRadius, point.y + trunkRadius, drawTrunkHeight));
		trunkWestCoordinateList.add(new Coordinate(point.x - trunkRadius, point.y + trunkRadius, 0));
		trunkWestCoordinateList.add(new Coordinate(point.x - trunkRadius, point.y - trunkRadius, 0));
		Polygon trunkWestPolygon = convertPolygon(trunkWestCoordinateList);
		var trunkWestConvertedPolygon = GreenEnricher.convertToCityGmlPoly(trunkWestPolygon);
		MultiSurface ms = new MultiSurface();
		ms.getSurfaceMember().add(new SurfaceProperty(trunkWestConvertedPolygon));

		List<Coordinate> trunkEastCoordinateList = new ArrayList<>();
		trunkEastCoordinateList.add(new Coordinate(point.x + trunkRadius, point.y - trunkRadius, 0));
		trunkEastCoordinateList.add(new Coordinate(point.x + trunkRadius, point.y + trunkRadius, 0));
		trunkEastCoordinateList.add(new Coordinate(point.x + trunkRadius, point.y + trunkRadius, drawTrunkHeight));
		trunkEastCoordinateList.add(new Coordinate(point.x + trunkRadius, point.y - trunkRadius, drawTrunkHeight));
		trunkEastCoordinateList.add(new Coordinate(point.x + trunkRadius, point.y - trunkRadius, 0));
		Polygon trunkEastPolygon = convertPolygon(trunkEastCoordinateList);
		var trunkEastConvertedPolygon = GreenEnricher.convertToCityGmlPoly(trunkEastPolygon);
		ms.getSurfaceMember().add(new SurfaceProperty(trunkEastConvertedPolygon));

		List<Coordinate> trunkSouthCoordinateList = new ArrayList<>();
		trunkSouthCoordinateList.add(new Coordinate(point.x - trunkRadius, point.y - trunkRadius, 0));
		trunkSouthCoordinateList.add(new Coordinate(point.x + trunkRadius, point.y - trunkRadius, 0));
		trunkSouthCoordinateList.add(new Coordinate(point.x + trunkRadius, point.y - trunkRadius, drawTrunkHeight));
		trunkSouthCoordinateList.add(new Coordinate(point.x - trunkRadius, point.y - trunkRadius, drawTrunkHeight));
		trunkSouthCoordinateList.add(new Coordinate(point.x - trunkRadius, point.y - trunkRadius, 0));
		Polygon trunkSouthPolygon = convertPolygon(trunkSouthCoordinateList);
		var trunkSouthConvertedPolygon = GreenEnricher.convertToCityGmlPoly(trunkSouthPolygon);
		ms.getSurfaceMember().add(new SurfaceProperty(trunkSouthConvertedPolygon));

		List<Coordinate> trunkNorthCoordinateList = new ArrayList<>();
		trunkNorthCoordinateList.add(new Coordinate(point.x - trunkRadius, point.y + trunkRadius, 0));
		trunkNorthCoordinateList.add(new Coordinate(point.x - trunkRadius, point.y + trunkRadius, drawTrunkHeight));
		trunkNorthCoordinateList.add(new Coordinate(point.x + trunkRadius, point.y + trunkRadius, drawTrunkHeight));
		trunkNorthCoordinateList.add(new Coordinate(point.x + trunkRadius, point.y + trunkRadius, 0));
		trunkNorthCoordinateList.add(new Coordinate(point.x - trunkRadius, point.y + trunkRadius, 0));
		Polygon trunkNorthPolygon = convertPolygon(trunkNorthCoordinateList);
		var trunkNorthConvertedPolygon = GreenEnricher.convertToCityGmlPoly(trunkNorthPolygon);
		ms.getSurfaceMember().add(new SurfaceProperty(trunkNorthConvertedPolygon));

		/*-
		 * Spheroid formula:
		 * x = a * sin(thetha) * cos(phi)
		 * y = b * sin(thetha) * sin(phi)
		 * z = c * cos(thetha)
		 * 
		 * 0 <= theta <= pi
		 * 0 <= phi	 < 2 pi
		 */

		// create crown
		// divide by 2 to get radius, height is diameter
		double c = crownHeight / 2D;

		double a = crownXRadius;
		double b = crownYRadius;

		int numberOfThetaRings = 5;
		int numberOfPhiRings = 10;

		double thetaDelta = Math.PI / (numberOfThetaRings - 1);
		double phiDelta = Math.PI * 2 / numberOfPhiRings;

		List<List<Coordinate>> ringCoordinates = new ArrayList<>();

		// top point triangles
		Coordinate topPoint = new Coordinate(point.x, point.y, point.z + c + trunkHeight + c);
		ringCoordinates.add(Collections.singletonList(topPoint));
		for (int i = 1; i < numberOfThetaRings - 1; i++) {
			double theta = i * thetaDelta;
			List<Coordinate> coords = new ArrayList<>();
			ringCoordinates.add(coords);
			for (int j = 0; j < numberOfPhiRings; j++) {
				double phi = j * phiDelta;
				double x = a * Math.sin(theta) * Math.cos(phi) + point.x;
				double y = b * Math.sin(theta) * Math.sin(phi) + point.y;
				double z = c * Math.cos(theta) + point.z + trunkHeight + c;
				Coordinate p1 = new Coordinate(x, y, z);
				coords.add(p1);
			}
		}
		Coordinate bottomPoint = new Coordinate(point.x, point.y, point.z + trunkHeight);
		ringCoordinates.add(Collections.singletonList(bottomPoint));
		
		List<Coordinate> secondRing = ringCoordinates.get(1);
		for (int i = 0; i < secondRing.size(); i++) {
			Coordinate[] coordArray = new Coordinate[] { topPoint, secondRing.get(i), secondRing.get((i + 1) % secondRing.size()), topPoint };
Matthias Betz's avatar
Matthias Betz committed
107
			Polygon polygon = GreenEnricher.GEOM_FACTORY.createPolygon(coordArray);
108
109
110
111
112
113
114
115
116
117
118
119
120
			var convertedPoly = GreenEnricher.convertToCityGmlPoly(polygon);
			ms.getSurfaceMember().add(new SurfaceProperty(convertedPoly));
		}
		for (int i = 1; i < ringCoordinates.size() - 2; i++) {
			List<Coordinate> topRing = ringCoordinates.get(i);
			List<Coordinate> bottomRing = ringCoordinates.get(i + 1);
			for (int j = 0; j < topRing.size(); j++) {
				int nextRingIndex = (j + 1) % topRing.size();
				Coordinate p1 = topRing.get(j);
				Coordinate p2 = topRing.get(nextRingIndex);
				Coordinate p3 = bottomRing.get(j);
				Coordinate p4 = bottomRing.get(nextRingIndex);
				Coordinate[] coordArray = new Coordinate[] { p1, p3, p4, p2, p1 };
Matthias Betz's avatar
Matthias Betz committed
121
				Polygon polygon = GreenEnricher.GEOM_FACTORY.createPolygon(coordArray);
122
123
124
125
126
127
128
129
130
131
132
133
				var convertedPoly = GreenEnricher.convertToCityGmlPoly(polygon);
				ms.getSurfaceMember().add(new SurfaceProperty(convertedPoly));
			}
		}
		
		// bottom point triangles
		List<Coordinate> bottomRing = ringCoordinates.get(ringCoordinates.size() - 2);
		for (int i = 0; i < bottomRing.size(); i++) {
			int nextRingIndex = (i + 1) % bottomRing.size();
			Coordinate p1 = bottomRing.get(i);
			Coordinate p2 = bottomRing.get(nextRingIndex);
			Coordinate[] coordArray = new Coordinate[] { p2, p1, bottomPoint, p2 };
Matthias Betz's avatar
Matthias Betz committed
134
			Polygon polygon = GreenEnricher.GEOM_FACTORY.createPolygon(coordArray);
135
136
137
138
139
140
141
142
			var convertedPoly = GreenEnricher.convertToCityGmlPoly(polygon);
			ms.getSurfaceMember().add(new SurfaceProperty(convertedPoly));
		}

		return ms;
	}

	private static Polygon convertPolygon(List<Coordinate> trunkWestCoordinateList) {
Matthias Betz's avatar
Matthias Betz committed
143
		return GreenEnricher.GEOM_FACTORY
144
145
146
147
				.createPolygon(trunkWestCoordinateList.toArray(new Coordinate[trunkWestCoordinateList.size()]));
	}

}