UNPKG

16.9 kBJavaScriptView Raw
1
2var RADIUS = 6371000.0;
3var GEO2METER = RADIUS * (Math.PI / 180)
4
5function newScene(sceneContent) {
6 return {"X3D": {
7 "@version": "3.0",
8 "@profile": "Immersive",
9 "@xmlns:xsd": "http://www.w3.org/2001/XMLSchema-instance",
10 "@xsd:noNamespaceSchemaLocation": "http://www.web3d.org/specifications/x3d-3.0.xsd",
11 "Scene": {
12 "-children": sceneContent
13 }
14 }
15 };
16}
17
18function newX3dJsonBld(id) {
19 var result = {"Group": {
20 "@class": "building",
21 "@DEF": id,
22 "@id": id,
23 "-children": []
24 }
25 };
26// console.log('id: ' + JSON.stringify(id));
27// console.log('uuu: ' + JSON.stringify(result));
28 return result;
29}
30function addBldPart(x3dJsonBld, x3dJsonBldPart) {
31 var children = x3dJsonBld['Group']['-children'];
32// var children = [];
33// console.log('xxx: ' + JSON.stringify(children));
34// console.log('zzz: ' + JSON.stringify(JSON.parse(JSON.stringify(x3dJsonBldPart))));
35 children[children.length] = JSON.parse(JSON.stringify(x3dJsonBldPart));
36}
37
38//function addBlock(x3dJsonBlockGroup, x3dJsonBlock) {
39// var x3dJsonBlocks = x3dJsonBlockGroup['Group']['-children'];
40//}
41
42function newX3dJsonBldPart(minHeight, color, transparency, points, height) {
43 var result = {"Transform": {
44 "@translation": [0, minHeight, 0],
45 "-children": [{"Group": {"@class": "buildingPart",
46 "-children": [{"Shape": {
47 "-appearance": [{"Appearance": {
48 "-material": [{"Material": {
49 "@diffuseColor": color,
50 "@transparency": transparency
51 }}]
52 }}],
53 "-geometry": [{"Extrusion": {
54 "@convex": false,
55 "@creaseAngle": 0.785,
56 "@crossSection": points,
57 "@solid": false,
58 "@endCap": false,
59 "@spine": [0, 0, 0, 0, height, 0]
60 }}]
61 }}]
62 }}]
63 }
64 };
65// console.log('result: ' + JSON.stringify(result));
66 return result;
67}
68function newX3dJsonBldFloorPart(height, points) {
69// console.log("height: " + height);
70 var result = {"Transform": {
71 "@translation": [0, height, 0],
72 "-children": [{"Transform": {"@rotation": '1 0 0 1.5708',
73 "-children": [{"Group": {"@class": "buildingPart",
74 "-children": [{"Shape": {
75 "-appearance": [{"Appearance": {
76 "-material": [{"Material": {
77 "@diffuseColor": [1, 1, 1],
78 "@transparency": 0
79 }}]
80 }}],
81 "-geometry": [{"Polyline2D": {
82 "@lineSegments": points}}]
83 }}]
84 }}]
85 }}]
86 }
87 };
88// console.log('yyy: ' + result)
89 return result;
90}
91
92
93// <Transform rotation='1 0 0 1.5708'>
94
95
96
97
98function getGeoJsonRoof(geoJson, id) {
99 var result;
100 for (var idx = 0; idx < geoJson.features.length; idx++) {
101 if (geoJson.features[idx].properties.type === "geoRoof" && geoJson.features[idx].properties.id === id) {
102 result = geoJson.features[idx];
103 break;
104 }
105 }
106 return result;
107}
108
109function geoToX3dColor(geoColor) {
110// console.log("geoColor: " + geoColor);
111// rgb(245, 245, 220)
112 var regex = /^rgb\(([0-9]+), *([0-9]+), *([0-9]+)\)$/
113 var result = geoColor.match(regex);
114 return [
115 Math.round(parseFloat(result[1], 10) / 2.56) / 100,
116 Math.round(parseFloat(result[2], 10) / 2.56) / 100,
117 Math.round(parseFloat(result[3], 10) / 2.56) / 100];
118}
119//Math.round(number * 100) / 100
120function isInside(geopoint, geobound) {
121 return !(geopoint[0] < geobound.minbound[0]
122 || geopoint[0] > geobound.maxbound[0]
123 || geopoint[1] < geobound.minbound[1]
124 || geopoint[1] > geobound.maxbound[1]);
125}
126
127/**
128 * Process centroid of set of points.
129 * e.g.: geonodes = [[x1,y1],[x2,y2]]
130 */
131//function centroid(geonodes) {
132// var sumlon = 0;
133// var sumlat = 0;
134// for (var i = 0; i < geonodes.length; i++) {
135// sumlon += geonodes[i][0];
136// sumlat += geonodes[i][1];
137// }
138// return [
139// sumlon / geonodes.length,
140// sumlat / geonodes.length
141// ];
142//}
143
144var myOsmGround;
145
146/**
147 *                                    
148 *              +--------->          
149 *              |       X            
150 *              |                    
151 *              |                    
152 * lat  ^       | Y                  
153 *      |       v                    
154 *      |                            
155 *      |    A       B               
156 *      |     +-----+    lat=lat_A   
157 *      |     |     |                
158 *      |     |     |    lon=lon_A   
159 *      |     +-----+                
160 *      |    D       C               
161 *      |                            
162 *      +----------------->          
163 *                      long         
164 *                                   
165 */
166
167/**
168 * Create ground tile.
169 * @param shift shift from origin
170 * @param size ground size
171 * @param tile tile url
172 */
173function createTile(shift, size, tile) {
174 var shape = {
175 '-geometry': [{"Rectangle2D": {
176 "@size": size
177 }}]
178 };
179 if (tile) {
180 shape['-appearance'] = [{"Appearance": {
181 "-texture": [{"ImageTexture": {
182 "@url": tile,
183 }}]
184 }}];
185 }
186 var result = {
187 "Transform": {
188 "@translation": [shift[0], -0.1, shift[1]],
189 "@rotation": '1 0 0 -1.5708',
190 "-children": [{"Group": {"@class": "tile",
191 "-children": [{"Shape": shape}]
192 }}]
193 }
194 };
195// if (tile) {
196// result["-children"][0]
197// }
198 return result;
199}
200// <Transform translation='57.264285044396 -0.1 -43.3774179598869' rotation='1 0 0 -1.5708'>
201// <Group>
202// <Shape>
203// <Appearance>
204// <ImageTexture url='"http://a.tile.openstreetmap.org/20/308790/394107.png"'/>
205// </Appearance>
206// <Rectangle2D size='38.1757484360134 28.9212942252524'></Rectangle2D>
207// </Shape>
208// </Group>
209
210// <Transform translation='0 0 0'>
211// <Group class='tile'>
212// <Shape>
213// <Appearance>
214// <ImageTexture>
215// </ImageTexture>
216// </Appearance>
217// <Rectangle2D>
218// </Rectangle2D>
219// </Shape>
220// </Group>
221// </Transform>
222// <Group class='building'>
223// </Group>
224//
225// <Transform translation='-57.2629602636441 -0.1 -43.3774179598869' rotation='1 0 0 -1.5708'>
226// <Group>
227// <Shape>
228// <Appearance>
229// <ImageTexture url='"http://a.tile.openstreetmap.org/20/308787/394107.png"'/>
230// </Appearance>
231// <Rectangle2D size='38.1757484360133 28.9212942252524'></Rectangle2D>
232// </Shape>
233// </Group>
234// </Transform>
235
236/**
237 * Convert GeoJSON data to x3dJson data
238 * @param geoJson GeoJson buildings.
239 * @param options Options.
240 * @param onConvert callback at end of conversion
241 */
242function convert(geoJson, options, onConvert) {
243 var origin = (options && options.origin) ? options.origin : null;
244 var loD = (options && options.loD) ? options.loD : 0;
245 var tile = (options && options.tile) ? options.tile : null;
246 var x3dJs = [];
247 for (var idxGJ = 0; idxGJ < geoJson.length; idxGJ++) {
248 switch (geoJson[idxGJ].type) {
249 case "Feature":
250 if (geoJson[idxGJ].properties.type === 'bounds') {
251 var boundCoord = geoJson[idxGJ].geometry.coordinates[0];
252// console.log('boundCoord: ' + JSON.stringify(boundCoord));
253// boundCoord: [["-73.9862797","40.7481926"],["-73.9852939","40.7481926"],["-73.9852939","40.7486022"],["-73.9862797","40.7486022"]]
254
255 if (!origin) {
256 origin = boundCoord[0];
257 }
258// 0:0,0--1:X,0
259// | |
260// | |
261// 3:0,Y--2:X,Y
262 var size = [
263 ((+boundCoord[2][0] - +boundCoord[0][0])) * GEO2METER,
264 ((+boundCoord[2][1] - +boundCoord[0][1])) * GEO2METER];
265// console.log("size: " + JSON.stringify(size));
266// console.log("origin: " + JSON.stringify(origin));
267// console.log("boundCoord: " + JSON.stringify(boundCoord));
268 x3dJs[x3dJs.length] = createTile(
269 [((boundCoord[2][0] - origin[0]) * GEO2METER) / 2.0, ((+origin[1] - boundCoord[0][1]) * GEO2METER) / 2.0],
270 size,
271 tile);
272 }
273 break;
274 case "FeatureCollection":
275 var id = geoJson[idxGJ].properties.id;
276 x3dJsonBlock = newX3dJsonBld(id);
277 for (var i = 0; i < geoJson[idxGJ].features.length; i++) {
278 var geoJsonBldPart = geoJson[idxGJ].features[i];
279// var my3dBldPart = {};
280 points = [];
281 perimeter = 0;
282 if (geoJsonBldPart.geometry.coordinates[0].length > 0) {
283 var pointRef = geoJsonBldPart.geometry.coordinates[0][geoJsonBldPart.geometry.coordinates[0].length - 1];
284 for (var j = 0; j < geoJsonBldPart.geometry.coordinates[0].length; j++) {
285 var node = geoJsonBldPart.geometry.coordinates[0][j];
286 points[points.length] = [(node[0] - origin[0]) * GEO2METER, (origin[1] - node[1]) * GEO2METER];
287 var z = (pointRef[1] - node[1]) * GEO2METER;
288 var x = (node[0] - pointRef[0]) * GEO2METER;
289 pointRef = node;
290 perimeter += Math.sqrt(z * z + x * x);
291 }
292 }
293
294// if (geoJsonBldPart.properties.levels) {
295// my3dBldPart.levels = +geoJsonBldPart.properties.levels;
296// }
297
298 // BldPart roof
299 var roof = getGeoJsonRoof(geoJson[idxGJ], geoJsonBldPart.properties.id);
300
301// my3dBldPart.roof = {};
302// my3dBldPart.roof.shape = "flat";
303// my3dBldPart.roof.shape = (roof && roof.shape) ? roof.shape : "flat";
304// my3dBldPart.roof.elevation = ((geoJsonBldPart.properties.height) ? geoJsonBldPart.properties.height : 0)
305// - ((my3dBldPart.roof && my3dBldPart.roof.elevation) ? my3dBldPart.roof.elevation : 0);
306// my3dBldPart.roof.points = my3dBldPart.points;
307// my3dBldPart.roof.height = (roof && roof.height) ? roof.height : 0;
308
309 var diffuseColor = (geoJsonBldPart.properties.color) ?
310 geoToX3dColor(geoJsonBldPart.properties.color) :
311 [
312 (((13 * (1 + height)) % 100) / 100),
313 (((17 * (1 + height)) % 100) / 100),
314 (((23 * (1 + height)) % 100) / 100)];
315 var minHeight = (geoJsonBldPart.properties.minHeight) ? +geoJsonBldPart.properties.minHeight : 0;
316 var height = ((geoJsonBldPart.properties.height) ? geoJsonBldPart.properties.height : 0)
317 - ((roof && roof.height) ? (roof.height) : 0)
318 - minHeight;
319 if (!height) {
320 height = 9.99
321 }
322 var x3dPoints = [];
323 for (var iP = 0; iP < points.length; iP++) {
324 x3dPoints[x3dPoints.length] = points[iP][0];
325 x3dPoints[x3dPoints.length] = points[iP][1];
326 }
327 addBldPart(x3dJsonBlock,
328 newX3dJsonBldPart(
329 minHeight,
330 diffuseColor,
331 geoJsonBldPart.properties.levels ? 0.6 : 0,
332 x3dPoints,
333 height));
334
335 // Floors
336 if (loD >= 4 && geoJsonBldPart.properties.levels && geoJsonBldPart.properties.height) {
337// console.log("geoJsonBldPart.properties.levels: " + geoJsonBldPart.properties.levels);
338// console.log("geoJsonBldPart.properties.height: " + geoJsonBldPart.properties.height);
339// console.log("geoJsonBldPart.properties.minLevel: " + geoJsonBldPart.properties.minLevel);
340// console.log("loD: " + loD);
341 var floorHeight = (geoJsonBldPart.properties.height - minHeight) / (geoJsonBldPart.properties.levels - geoJsonBldPart.properties.minLevel);
342 var level;
343 console.log("geoJsonBldPart.properties.height: " + geoJsonBldPart.properties.height);
344 console.log("geoJsonBldPart.properties.levels: " + geoJsonBldPart.properties.levels);
345 console.log("geoJsonBldPart.properties.minLevel: " + geoJsonBldPart.properties.minLevel);
346 console.log("floorHeight: " + floorHeight);
347 console.log("minHeight: " + minHeight);
348 for (level = +geoJsonBldPart.properties.minLevel; level < geoJsonBldPart.properties.levels; level++) {
349 console.log("level: " + level);
350 console.log("elevation processed: " + (+minHeight + (level - geoJsonBldPart.properties.minLevel) * floorHeight));
351 addBldPart(x3dJsonBlock,
352 newX3dJsonBldFloorPart(
353 +minHeight + (level - geoJsonBldPart.properties.minLevel) * floorHeight,
354 x3dPoints));
355 }
356 }
357 }
358 x3dJs[x3dJs.length] = JSON.parse(JSON.stringify(x3dJsonBlock));
359 break;
360 }
361 }
362 var scene = newScene(x3dJs);
363 onConvert(scene);
364}
365
366exports.convert = convert;