1 |
|
2 | var RADIUS = 6300000;
|
3 | var GEO2METER = RADIUS * (Math.PI / 180)
|
4 |
|
5 |
|
6 | function newScene(x3dJsonBlock) {
|
7 | return {"X3D": {
|
8 | "@profile": "Immersive",
|
9 | "@version": 3.3,
|
10 | "@xsd:noNamespaceSchemaLocation": "http://www.web3d.org/specifications/x3d-3.3.xsd",
|
11 | "Scene": {
|
12 | "-children": x3dJsonBlock
|
13 | }
|
14 | }
|
15 | };
|
16 | }
|
17 |
|
18 | function newX3dJsonBldPart(minHeight, color, transparency, points, height) {
|
19 | return {"Transform": {
|
20 | "@translation": [0, minHeight, 0],
|
21 | "-children": [
|
22 | {"Group": {
|
23 | "@class": "buildingPart",
|
24 | "-children": [
|
25 | {"Shape": {
|
26 | "-appearance": [
|
27 | {"Appearance": {
|
28 | "-material": [
|
29 | {"Material": {
|
30 | "@diffuseColor": color,
|
31 | "@transparency": transparency
|
32 | }
|
33 | }
|
34 | ]
|
35 | }
|
36 | }
|
37 | ],
|
38 | "-geometry": [
|
39 | {"Extrusion": {
|
40 | "@convex": false,
|
41 | "@creaseAngle": 0.785,
|
42 | "@crossSection": points,
|
43 | "@solid": false,
|
44 | "@endCap": false,
|
45 | "@spine": [0, 0, 0, 0, height, 0]
|
46 | }
|
47 | }
|
48 | ]
|
49 | }
|
50 | }
|
51 | ]
|
52 | }
|
53 | }
|
54 | ]
|
55 | }
|
56 | };
|
57 | }
|
58 | function newX3dJsonBlFloordPart(minHeight, points) {
|
59 | return {"Transform": {
|
60 | "@translation": [0, minHeight, 0],
|
61 | "-children": [
|
62 | {"Group": {
|
63 | "@class": "buildingPart",
|
64 | "-children": [
|
65 | {"Shape": {
|
66 | "-appearance": [
|
67 | {"Appearance": {
|
68 | "-material": [
|
69 | {"Material": {
|
70 | "@diffuseColor": [1, 1, 1],
|
71 | "@transparency": 0
|
72 | }
|
73 | }
|
74 | ]
|
75 | }
|
76 | }
|
77 | ],
|
78 | "-geometry": [
|
79 | {"Polyline2D": {
|
80 | "@lineSegments": points}
|
81 | }
|
82 | ]
|
83 | }
|
84 | }
|
85 | ]
|
86 | }
|
87 | }
|
88 | ]
|
89 | }
|
90 | };
|
91 | }
|
92 | function getGeoJsonRoof(geoJsonBlock, id) {
|
93 | var result;
|
94 | for (var idx = 0; idx < geoJsonBlock.features.length; idx++) {
|
95 | if (geoJsonBlock.features[idx].properties.type === "geoRoof" && geoJsonBlock.features[idx].properties.id === id) {
|
96 | result = geoJsonBlock.features[idx];
|
97 | break;
|
98 | }
|
99 | }
|
100 | return result;
|
101 | }
|
102 |
|
103 | function geoToX3dColor(geoColor) {
|
104 | var regex = /^rgb: \(([0-9]+), ([0-9]+), ([0-9]+)\)$/
|
105 | var result = string.match(regex);
|
106 | return [result[1], result[2], result[3]];
|
107 | }
|
108 |
|
109 | function isInside(geopoint, geobound) {
|
110 | return !(geopoint[0] < geobound.minbound[0]
|
111 | || geopoint[0] > geobound.maxbound[0]
|
112 | || geopoint[1] < geobound.minbound[1]
|
113 | || geopoint[1] > geobound.maxbound[1]);
|
114 | }
|
115 |
|
116 | function centroid(geonodes) {
|
117 | var sumlon = 0;
|
118 | var sumlat = 0;
|
119 | for (var i = 0; i < geonodes.length; i++) {
|
120 | sumlon += geonodes[i][0];
|
121 | sumlat += geonodes[i][1];
|
122 | }
|
123 | return [
|
124 | sumlon / geonodes.length,
|
125 | sumlat / geonodes.length
|
126 | ];
|
127 | }
|
128 |
|
129 | var myOsmGround;
|
130 |
|
131 |
|
132 |
|
133 |
|
134 |
|
135 |
|
136 |
|
137 | function convert(geoJsonBlock, my3dOutputStream, onBlock) {
|
138 |
|
139 | x3dJsonBlock = [];
|
140 |
|
141 | switch (geoJsonBlock["properties"]["type"]) {
|
142 | case "ground":
|
143 | break;
|
144 | case "building":
|
145 | for (var i = 0; i < geoJsonBlock.features.length; i++) {
|
146 | var geoJsonBldPart = geoJsonBlock.features[i];
|
147 | var my3dBldPart = {};
|
148 | points = [];
|
149 | perimeter = 0;
|
150 | if (geoJsonBldPart.geometry.coordinates[0].length > 0) {
|
151 | var pointRef = geoJsonBldPart.geometry.coordinates[0][geoJsonBldPart.geometry.coordinates[0].length - 1];
|
152 | for (var j = 0; j < geoJsonBldPart.geometry.coordinates[0].length; j++) {
|
153 | var node = geoJsonBldPart.geometry.coordinates[0][j];
|
154 | points[points.length] = [node[0], node[1]];
|
155 | var z = (pointRef[1] - node[1]) * GEO2METER;
|
156 | var x = (node[0] - pointRef[0]) * GEO2METER;
|
157 | pointRef = node;
|
158 | perimeter += Math.sqrt(z * z + x * x);
|
159 | }
|
160 | }
|
161 | if (geoJsonBldPart.properties.levels) {
|
162 | my3dBldPart.levels = +geoJsonBldPart.properties.levels;
|
163 | }
|
164 |
|
165 |
|
166 | var roof = getGeoJsonRoof(geoJsonBlock, geoJsonBldPart.properties.id);
|
167 |
|
168 |
|
169 |
|
170 |
|
171 |
|
172 |
|
173 |
|
174 | my3dBldPart.roof = {};
|
175 | my3dBldPart.roof.shape = "flat";
|
176 | my3dBldPart.roof.shape = (roof && roof.shape) ? roof.shape : "flat";
|
177 | my3dBldPart.roof.elevation = ((geoJsonBldPart.properties.height) ? geoJsonBldPart.properties.height : 0)
|
178 | - ((my3dBldPart.roof && my3dBldPart.roof.elevation) ? my3dBldPart.roof.elevation : 0);
|
179 | my3dBldPart.roof.points = my3dBldPart.points;
|
180 | my3dBldPart.roof.height = (roof && roof.height) ? roof.height : 0;
|
181 |
|
182 | var diffuseColor = (geoJsonBldPart.properties.colour !== undefined) ?
|
183 | geoToX3dColor(geoJsonBldPart.properties.colour) :
|
184 | [
|
185 | (((13 * (1 + height)) % 100) / 100),
|
186 | (((17 * (1 + height)) % 100) / 100),
|
187 | (((23 * (1 + height)) % 100) / 100)];
|
188 | var height = ((geoJsonBldPart.properties.height) ? geoJsonBldPart.properties.height : 0)
|
189 | - ((roof && roof.height) ? (roof.height) : 0)
|
190 | - geoJsonBldPart.properties.minHeight;
|
191 | if (height === undefined) {
|
192 | height = 9.99
|
193 | }
|
194 | x3dJsonBlock[x3dJsonBlock.length] = newX3dJsonBldPart(
|
195 | +geoJsonBldPart.properties.minHeight,
|
196 | diffuseColor,
|
197 | geoJsonBldPart.properties.levels ? 0.6 : 0,
|
198 | points,
|
199 | height);
|
200 |
|
201 |
|
202 | if (geoJsonBldPart.properties.levels && my3dBldPart.height) {
|
203 | var floorHeight = my3dBldPart.height / (geoJsonBldPart.properties.levels - geoJsonBldPart.properties.minLevel);
|
204 | var level;
|
205 | for (level = +geoJsonBldPart.properties.minLevel; level < geoJsonBldPart.properties.levels; level++) {
|
206 | x3dJsonBlock[x3dJsonBlock.length] = newX3dJsonBlFloordPart(
|
207 | +my3dBldPart.elevation + (level - geoJsonBldPart.properties.minLevel) * floorHeight,
|
208 | points);
|
209 | }
|
210 | }
|
211 | }
|
212 | break;
|
213 | }
|
214 | onBlock(x3dJsonBlock);
|
215 |
|
216 | if (my3dOutputStream !== undefined) {
|
217 | var scene = newScene(x3dJsonBlock);
|
218 | my3dOutputStream.write(JSON.stringify(scene));
|
219 | my3dOutputStream.end();
|
220 | }
|
221 | }
|
222 |
|
223 | exports.convert = convert;
|