@ohuoy/easymap 1.0.19 → 1.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/bundle.js +318 -290
  2. package/dist/example - /345/211/257/346/234/254/bundle.js" +318 -290
  3. package/dist/example - /345/211/257/346/234/254/index.html" +11 -11
  4. package/index.js +4 -0
  5. package/lib/threebox-plugin/CHANGELOG.md +665 -0
  6. package/lib/threebox-plugin/LICENSE.txt +97 -0
  7. package/lib/threebox-plugin/README.md +199 -0
  8. package/lib/threebox-plugin/exports.js +2 -0
  9. package/lib/threebox-plugin/main.js +8 -0
  10. package/lib/threebox-plugin/package.json +44 -0
  11. package/lib/threebox-plugin/server.stop.js +13 -0
  12. package/lib/threebox-plugin/src/Threebox.js +1216 -0
  13. package/lib/threebox-plugin/src/animation/AnimationManager.js +483 -0
  14. package/lib/threebox-plugin/src/camera/CameraSync.js +302 -0
  15. package/lib/threebox-plugin/src/objects/CSS2DRenderer.js +245 -0
  16. package/lib/threebox-plugin/src/objects/LabelRenderer.js +71 -0
  17. package/lib/threebox-plugin/src/objects/Object3D.js +34 -0
  18. package/lib/threebox-plugin/src/objects/effects/BuildingShadows.js +115 -0
  19. package/lib/threebox-plugin/src/objects/extrusion.js +61 -0
  20. package/lib/threebox-plugin/src/objects/fflate.min.js +15 -0
  21. package/lib/threebox-plugin/src/objects/label.js +29 -0
  22. package/lib/threebox-plugin/src/objects/line.js +1386 -0
  23. package/lib/threebox-plugin/src/objects/loadObj.js +142 -0
  24. package/lib/threebox-plugin/src/objects/loaders/ColladaLoader.js +3751 -0
  25. package/lib/threebox-plugin/src/objects/loaders/FBXLoader.js +3864 -0
  26. package/lib/threebox-plugin/src/objects/loaders/GLTFLoader.js +3857 -0
  27. package/lib/threebox-plugin/src/objects/loaders/MTLLoader.js +498 -0
  28. package/lib/threebox-plugin/src/objects/loaders/OBJLoader.js +818 -0
  29. package/lib/threebox-plugin/src/objects/objects.js +1113 -0
  30. package/lib/threebox-plugin/src/objects/sphere.js +28 -0
  31. package/lib/threebox-plugin/src/objects/tooltip.js +27 -0
  32. package/lib/threebox-plugin/src/objects/tube.js +35 -0
  33. package/lib/threebox-plugin/src/three.js +6 -0
  34. package/lib/threebox-plugin/src/three.module.js +54571 -0
  35. package/lib/threebox-plugin/src/utils/ValueGenerator.js +11 -0
  36. package/lib/threebox-plugin/src/utils/constants.js +21 -0
  37. package/lib/threebox-plugin/src/utils/material.js +52 -0
  38. package/lib/threebox-plugin/src/utils/suncalc.js +322 -0
  39. package/lib/threebox-plugin/src/utils/utils.js +424 -0
  40. package/lib/threebox-plugin/src/utils/validate.js +115 -0
  41. package/package.json +18 -18
  42. package/src/components/EasyMapMarker.js +8 -0
  43. package/src/components/control/DrawBar.js +5 -0
  44. package/src/components/control/TilesBar.js +116 -27
  45. package/src/components/control/Toobars.js +20 -1
  46. package/src/components/layer/AlarmLayer.js +4 -1
  47. package/src/components/layer/AnimationBarbsLayer.js +1 -1
  48. package/src/components/layer/AnimationLayer copy.js +1 -1
  49. package/src/components/layer/AnimationLayer.js +11 -3
  50. package/src/components/layer/CustomIconLayer.js +1 -1
  51. package/src/components/layer/ExtrusionLayer.js +1 -1
  52. package/src/components/layer/ExtrusionLayerold.js +2 -1
  53. package/src/components/layer/MarkerAreaLayer.js +1 -1
  54. package/src/components/layer/PathLineLayer.js +1 -1
  55. package/src/components/layer/ThreeScanLayer.js +51 -14
  56. package/src/components/layer/ThreeWallLayer.js +1 -1
  57. package/webpack.config.js +2 -1
@@ -0,0 +1,1113 @@
1
+ /**
2
+ * @author peterqliu / https://github.com/peterqliu
3
+ * @author jscastro / https://github.com/jscastro76
4
+ */
5
+ //const utils = require("../utils/utils.js");
6
+ import utils from '../utils/utils.js';
7
+ import material from '../utils/material.js'
8
+ //const material = require("../utils/material.js");
9
+ import * as THREE from '../three.module.js'
10
+ import AnimationManager from '../animation/AnimationManager.js'
11
+ //const AnimationManager = require("../animation/AnimationManager.js");
12
+ import CSS2D from './CSS2DRenderer.js'
13
+ //const CSS2D = require("./CSS2DRenderer.js");
14
+
15
+ function Objects(){
16
+
17
+ }
18
+
19
+ Objects.prototype = {
20
+
21
+ // standard 1px line with gl
22
+ line: function (obj) {
23
+
24
+ obj = utils._validate(obj, this._defaults.line);
25
+
26
+ //project to world and normalize
27
+ var straightProject = utils.lnglatsToWorld(obj.geometry);
28
+ var normalized = utils.normalizeVertices(straightProject);
29
+
30
+ //flatten array for buffergeometry
31
+ var flattenedArray = utils.flattenVectors(normalized.vertices);
32
+
33
+ var positions = new Float32Array(flattenedArray); // 3 vertices per point
34
+ var geometry = new THREE.BufferGeometry();
35
+ geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
36
+
37
+ // material
38
+ var material = new THREE.LineBasicMaterial({ color: 0xff0000, linewidth: 21 });
39
+ var line = new THREE.Line(geometry, material);
40
+
41
+ line.options = options || {};
42
+ line.position.copy(normalized.position)
43
+
44
+ return line
45
+ },
46
+
47
+ extrusion: function (options) {
48
+
49
+ },
50
+
51
+ unenroll: function (obj, isStatic) {
52
+ var root = this;
53
+
54
+ if (isStatic) {
55
+
56
+ }
57
+
58
+ else {
59
+ // Bestow this mesh with animation superpowers and keeps track of its movements in the global animation queue
60
+ root.animationManager.unenroll(obj);
61
+
62
+ }
63
+
64
+ },
65
+
66
+ _addMethods: function (obj, isStatic,map) {
67
+
68
+ var root = this;
69
+ const labelName = "label";
70
+ const tooltipName = "tooltip";
71
+ const helpName = "help";
72
+ const shadowPlane = "shadowPlane";
73
+
74
+ if (isStatic) {
75
+
76
+ }
77
+
78
+ else {
79
+
80
+ if (!obj.coordinates) obj.coordinates = [0, 0, 0];
81
+
82
+ //[jscastro] added property for the internal 3D model
83
+ Object.defineProperty(obj, 'model', {
84
+ get() {
85
+ return obj.getObjectByName("model");
86
+ }
87
+ });
88
+
89
+ let _animations;
90
+ //[jscastro] added property for the internal 3D model
91
+ Object.defineProperty(obj, 'animations', {
92
+ get() {
93
+ const model = obj.model;
94
+ if (model) {
95
+ return model.animations
96
+ } else return null;
97
+ },
98
+ //set(value) { _animations = value}
99
+ });
100
+
101
+ // Bestow this mesh with animation superpowers and keeps track of its movements in the global animation queue
102
+ root.animationManager.enroll(obj);
103
+
104
+ // Place an object on the map at the given lnglat
105
+ obj.setCoords = function (lnglat) {
106
+
107
+ // CSS2DObjects could bring an specific vertical positioning to correct in units
108
+ if (obj.userData.topMargin && obj.userData.feature) {
109
+ lnglat[2] += ((obj.userData.feature.properties.height || 0) - (obj.userData.feature.properties.base_height || obj.userData.feature.properties.min_height || 0)) * (obj.userData.topMargin || 0);
110
+ }
111
+
112
+ obj.coordinates = lnglat;
113
+ obj.set({ position: lnglat });
114
+ return obj;
115
+
116
+ }
117
+
118
+ obj.setTranslate = function (lnglat) {
119
+
120
+ obj.set({ translate: lnglat });
121
+ return obj;
122
+
123
+ }
124
+
125
+ obj.setRotation = function (xyz) {
126
+
127
+ if (typeof xyz === 'number') xyz = { z: xyz }
128
+
129
+ var r = {
130
+ x: utils.radify(xyz.x) || obj.rotation.x,
131
+ y: utils.radify(xyz.y) || obj.rotation.y,
132
+ z: utils.radify(xyz.z) || obj.rotation.z
133
+ }
134
+
135
+ obj._setObject({ rotation: [r.x, r.y, r.z] })
136
+ }
137
+
138
+ //[jscastro] added method to adjust 3D models to their issues with center position for rotation
139
+ obj.calculateAdjustedPosition = function (lnglat, xyz, inverse) {
140
+
141
+ let location = lnglat.slice();
142
+
143
+ //we convert the units to Long/Lat/Height
144
+ let newCoords = utils.unprojectFromWorld(obj.modelSize);
145
+
146
+ if (inverse) {
147
+ //each model will have different adjustment attributes, we add them for x, y, z
148
+ location[0] -= (xyz.x != 0 ? (newCoords[0] / xyz.x) : 0);
149
+ location[1] -= (xyz.y != 0 ? (newCoords[1] / xyz.y) : 0);
150
+ location[2] -= (xyz.z != 0 ? (newCoords[2] / xyz.z) : 0);
151
+ } else {
152
+ //each model will have different adjustment attributes, we add them for x, y, z
153
+ location[0] += (xyz.x != 0 ? (newCoords[0] / xyz.x) : 0);
154
+ location[1] += (xyz.y != 0 ? (newCoords[1] / xyz.y) : 0);
155
+ location[2] += (xyz.z != 0 ? (newCoords[2] / xyz.z) : 0);
156
+
157
+ }
158
+ return location;
159
+ }
160
+
161
+ //[jscastro] added method to rotate on objects on an axis instead of centers
162
+ obj.setRotationAxis = function (xyz) {
163
+ if (typeof xyz === 'number') xyz = { z: xyz }
164
+
165
+ let bb = obj.modelBox();
166
+
167
+ let point = new THREE.Vector3(bb.max.x, bb.max.y, bb.min.z);
168
+ //apply Axis rotation on angle
169
+ if (xyz.x != 0) _applyAxisAngle(obj, point, new THREE.Vector3(0, 0, 1), xyz.x);
170
+ if (xyz.y != 0) _applyAxisAngle(obj, point, new THREE.Vector3(0, 0, 1), xyz.y);
171
+ if (xyz.z != 0) _applyAxisAngle(obj, point, new THREE.Vector3(0, 0, 1), xyz.z);
172
+ }
173
+
174
+ //[jscastro] Auxiliar method to rotate an object on an axis
175
+ function _applyAxisAngle(model, point, axis, degrees) {
176
+ let theta = utils.radify(degrees);
177
+ model.position.sub(point); // remove the offset
178
+ model.position.applyAxisAngle(axis, theta); // rotate the POSITION
179
+ model.position.add(point); // re-add the offset
180
+ model.rotateOnAxis(axis, theta)
181
+
182
+ map.repaint = true;
183
+ }
184
+
185
+
186
+ //[jscastro] added property for scaled group inside threeboxObject
187
+ Object.defineProperty(obj, 'scaleGroup', {
188
+ get() {
189
+ return obj.getObjectByName("scaleGroup");
190
+ }
191
+ })
192
+
193
+ //[jscastro] added property for boundingBox group helper
194
+ Object.defineProperty(obj, 'boxGroup', {
195
+ get() {
196
+ return obj.getObjectByName("boxGroup");
197
+ }
198
+ })
199
+
200
+ //[jscastro] added property for boundingBox helper
201
+ Object.defineProperty(obj, 'boundingBox', {
202
+ get() {
203
+ return obj.getObjectByName("boxModel");
204
+ }
205
+ })
206
+
207
+ let _boundingBoxShadow;
208
+ //[jscastro] added property for boundingBox shadow helper
209
+ Object.defineProperty(obj, 'boundingBoxShadow', {
210
+ get() {
211
+ return obj.getObjectByName("boxShadow");
212
+ }
213
+ })
214
+
215
+ //[jscastro] added method to create a bounding box and a shadow box
216
+ obj.drawBoundingBox = function () {
217
+ //let's create 2 wireframes, one for the object and one to project on the floor position
218
+ let bb = obj.box3();
219
+ //create the group to return
220
+ let boxGroup = new THREE.Group();
221
+ boxGroup.name = "boxGroup";
222
+ boxGroup.updateMatrixWorld(true);
223
+ let boxModel = new THREE.Box3Helper(bb, Objects.prototype._defaults.colors.yellow);
224
+ boxModel.name = "boxModel";
225
+ boxGroup.add(boxModel);
226
+ boxModel.layers.disable(0); // it makes the object invisible for the raycaster
227
+ //obj.boundingBox = boxModel;
228
+
229
+ //it needs to clone, to avoid changing the object by reference
230
+ let bb2 = bb.clone();
231
+ //we make the second box flat and at the floor height level
232
+ bb2.max.z = bb2.min.z;
233
+ let boxShadow = new THREE.Box3Helper(bb2, Objects.prototype._defaults.colors.black);
234
+ boxShadow.name = "boxShadow";
235
+
236
+ boxGroup.add(boxShadow);
237
+ boxShadow.layers.disable(0); // it makes the object invisible for the raycaster
238
+ //obj.boundingBoxShadow = boxShadow;
239
+
240
+ boxGroup.visible = false; // visibility is managed from the parent
241
+ obj.scaleGroup.add(boxGroup);
242
+ obj.setBoundingBoxShadowFloor();
243
+ }
244
+
245
+ //[jscastro] added method to position the shadow box on the floor depending the object height
246
+ obj.setBoundingBoxShadowFloor = function () {
247
+ if (obj.boundingBoxShadow) {
248
+ let h = -obj.modelHeight, r = obj.rotation, o = obj.boundingBoxShadow;
249
+ o.box.max.z = o.box.min.z = h;
250
+ o.rotation.y = r.y;
251
+ o.rotation.x = -r.x;
252
+ }
253
+ }
254
+
255
+ //[jscastro] Set the positional and pivotal anchor automatically from string param
256
+ obj.setAnchor = function (anchor) {
257
+ const b = obj.box3();
258
+ //const size = b.getSize(new THREE.Vector3());
259
+ const c = b.getCenter(new THREE.Vector3());
260
+ obj.none = { x: 0, y: 0, z: 0 };
261
+ obj.center = { x: c.x, y: c.y, z: b.min.z };
262
+ obj.bottom = { x: c.x, y: b.max.y, z: b.min.z };
263
+ obj.bottomLeft = { x: b.max.x, y: b.max.y, z: b.min.z };
264
+ obj.bottomRight = { x: b.min.x, y: b.max.y, z: b.min.z };
265
+ obj.top = { x: c.x, y: b.min.y, z: b.min.z };
266
+ obj.topLeft = { x: b.max.x, y: b.min.y, z: b.min.z };
267
+ obj.topRight = { x: b.min.x, y: b.min.y, z: b.min.z };
268
+ obj.left = { x: b.max.x, y: c.y, z: b.min.z };
269
+ obj.right = { x: b.min.x, y: c.y, z: b.min.z };
270
+
271
+ switch (anchor) {
272
+ case 'center':
273
+ obj.anchor = obj.center;
274
+ break;
275
+ case 'top':
276
+ obj.anchor = obj.top;
277
+ break;
278
+ case 'top-left':
279
+ obj.anchor = obj.topLeft;
280
+ break;
281
+ case 'top-right':
282
+ obj.anchor = obj.topRight;
283
+ break;
284
+ case 'left':
285
+ obj.anchor = obj.left;
286
+ break;
287
+ case 'right':
288
+ obj.anchor = obj.right;
289
+ break;
290
+ case 'bottom':
291
+ obj.anchor = obj.bottom;
292
+ break;
293
+ case 'bottom-left':
294
+ default:
295
+ obj.anchor = obj.bottomLeft;
296
+ break;
297
+ case 'bottom-right':
298
+ obj.anchor = obj.bottomRight;
299
+ break;
300
+ case 'auto':
301
+ case 'none':
302
+ obj.anchor = obj.none;
303
+ }
304
+
305
+ obj.model.position.set(-obj.anchor.x, -obj.anchor.y, -obj.anchor.z);
306
+
307
+ }
308
+
309
+ //[jscastro] Set the positional and pivotal anchor based on (x, y, z) size units
310
+ obj.setCenter = function (center) {
311
+ //[jscastro] if the object options have an adjustment to center the 3D Object different to 0
312
+ if (center && (center.x != 0 || center.y != 0 || center.z != 0)) {
313
+ let size = obj.getSize();
314
+ obj.anchor = { x: obj.anchor.x - (size.x * center.x), y: obj.anchor.y - (size.y * center.y), z: obj.anchor.z - (size.z * center.z) };
315
+ obj.model.position.set(-obj.anchor.x, -obj.anchor.y, -obj.anchor.z)
316
+ }
317
+ }
318
+
319
+ //[jscastro] added property for simulated label
320
+ Object.defineProperty(obj, 'label', {
321
+ get() { return obj.getObjectByName(labelName); }
322
+ });
323
+
324
+ //[jscastro] added property for simulated tooltip
325
+ Object.defineProperty(obj, 'tooltip', {
326
+ get() { return obj.getObjectByName(tooltipName); }
327
+ });
328
+
329
+ //[jscastro] added property for help
330
+ Object.defineProperty(obj, 'help', {
331
+ get() { return obj.getObjectByName(helpName); }
332
+ });
333
+
334
+ let _hidden = false;
335
+ //[jscastro] added property for explicitely hidden object to avoid zoom layer behavior
336
+ Object.defineProperty(obj, 'hidden', {
337
+ get() { return _hidden; },
338
+ set(value) {
339
+ if (_hidden != value) {
340
+ _hidden = value;
341
+ obj.visibility = !_hidden;
342
+ }
343
+ }
344
+ });
345
+
346
+ //[jscastro] added property to redefine visible, including the label and tooltip
347
+ Object.defineProperty(obj, 'visibility', {
348
+ get() { return obj.visible; },
349
+ set(value) {
350
+ let _value = value;
351
+ if (value == 'visible' || value == true) {
352
+ _value = true;
353
+ if (obj.label) obj.label.visible = _value;
354
+ }
355
+ else if (value == 'none' || value == false) {
356
+ _value = false;
357
+ if (obj.label && obj.label.alwaysVisible) obj.label.visible = _value;
358
+ if (obj.tooltip) obj.tooltip.visible = _value;
359
+ }
360
+ else return;
361
+ if (obj.visible != _value) {
362
+ if (obj.hidden && _value) return;
363
+
364
+ obj.visible = _value;
365
+
366
+ if (obj.model) {
367
+ obj.model.traverse(function (c) {
368
+ if (c.type == "Mesh" || c.type == "SkinnedMesh") {
369
+ if (_value && obj.raycasted) {
370
+ c.layers.enable(0); //this makes the meshes visible for raycast
371
+ } else {
372
+ c.layers.disable(0); //this makes the meshes invisible for raycast
373
+ }
374
+ }
375
+ if (c.type == "LineSegments") {
376
+ c.layers.disableAll();
377
+ }
378
+ });
379
+ }
380
+ }
381
+ }
382
+ });
383
+
384
+ //[jscastro] add CSS2 label method
385
+ obj.addLabel = function (HTMLElement, visible, center, height) {
386
+ if (HTMLElement) {
387
+ //we add it to the first children to get same boxing and position
388
+ //obj.children[0].add(obj.drawLabel(text, height));
389
+ obj.drawLabelHTML(HTMLElement, visible, center, height);
390
+ }
391
+ }
392
+
393
+ //[jscastro] remove CSS2 label method
394
+ obj.removeLabel = function () {
395
+ obj.removeCSS2D(labelName);
396
+ }
397
+
398
+ //[jscastro] draw label method can be invoked separately
399
+ obj.drawLabelHTML = function (HTMLElement, visible = false, center = obj.anchor, height = 0.5) {
400
+ let divLabel = root.drawLabelHTML(HTMLElement, Objects.prototype._defaults.label.cssClass);
401
+ let label = obj.addCSS2D(divLabel, labelName, center, height) //label.position.set(((-size.x * 0.5) - obj.model.position.x - center.x + bottomLeft.x), ((-size.y * 0.5) - obj.model.position.y - center.y + bottomLeft.y), size.z * 0.5); //middle-centered
402
+ label.alwaysVisible = visible;
403
+ label.visible = visible;
404
+ return label;
405
+ }
406
+
407
+ //[jscastro] add tooltip method
408
+ obj.addTooltip = function (tooltipText, mapboxStyle, center, custom = true, height = 1) {
409
+ let t = obj.addHelp(tooltipText, tooltipName, mapboxStyle, center, height);
410
+ t.visible = false;
411
+ t.custom = custom;
412
+ }
413
+
414
+ //[jscastro] remove CSS2 tooltip method
415
+ obj.removeTooltip = function () {
416
+ obj.removeCSS2D(tooltipName);
417
+ }
418
+
419
+ //[jscastro] add tooltip method
420
+ obj.addHelp = function (helpText, objName = helpName, mapboxStyle = false, center = obj.anchor, height = 0) {
421
+ let divHelp = root.drawTooltip(helpText, mapboxStyle);
422
+ let h = obj.addCSS2D(divHelp, objName, center, height);
423
+ h.visible = true;
424
+ return h;
425
+ }
426
+
427
+ //[jscastro] remove CSS2 tooltip method
428
+ obj.removeHelp = function () {
429
+ obj.removeCSS2D(helpName);
430
+ }
431
+
432
+ //[jscastro] add CSS2D help method
433
+ obj.addCSS2D = function (element, objName, center = obj.anchor, height = 1) {
434
+ if (element) {
435
+ const box = obj.box3();
436
+ const size = box.getSize(new THREE.Vector3());
437
+ let bottomLeft = { x: box.max.x, y: box.max.y, z: box.min.z };
438
+ obj.removeCSS2D(objName);
439
+ let c = new CSS2D.CSS2DObject(element);
440
+ c.name = objName;
441
+ c.position.set(((-size.x * 0.5) - obj.model.position.x - center.x + bottomLeft.x), ((-size.y * 0.5) - obj.model.position.y - center.y + bottomLeft.y), size.z * height);
442
+ c.visible = false; //only visible on mouseover or selected
443
+ obj.scaleGroup.add(c);
444
+ return c;
445
+ }
446
+ }
447
+
448
+ //[jscastro] remove CSS2 help method
449
+ obj.removeCSS2D = function (objName) {
450
+ let css2D = obj.getObjectByName(objName);
451
+ if (css2D) {
452
+ css2D.dispose();
453
+ let g = obj.scaleGroup.children;
454
+ g.splice(g.indexOf(css2D), 1);
455
+ }
456
+ }
457
+
458
+ //[jscastro] added property for help
459
+ Object.defineProperty(obj, 'shadowPlane', {
460
+ get() { return obj.getObjectByName(shadowPlane); }
461
+ });
462
+
463
+ let _castShadow = false;
464
+ //[jscastro] added property for traverse an object to cast a shadow
465
+ Object.defineProperty(obj, 'castShadow', {
466
+ get() { return _castShadow; },
467
+ set(value) {
468
+ if (!obj.model || _castShadow === value) return;
469
+
470
+ obj.model.traverse(function (c) {
471
+ if (c.isMesh) c.castShadow = true;
472
+ });
473
+ if (value) {
474
+ // we add the shadow plane automatically
475
+ const s = obj.modelSize;
476
+ const sz = [s.x, s.y, s.z, obj.modelHeight];
477
+ const pSize = Math.max(...sz) * 10;
478
+ const pGeo = new THREE.PlaneBufferGeometry(pSize, pSize);
479
+ const pMat = new THREE.ShadowMaterial();
480
+ //const pMat = new THREE.MeshStandardMaterial({ color: 0x660000 });
481
+ pMat.opacity = 0.5;
482
+ let p = new THREE.Mesh(pGeo, pMat);
483
+ p.name = shadowPlane;
484
+ p.layers.enable(1); p.layers.disable(0); // it makes the object invisible for the raycaster
485
+ p.receiveShadow = value;
486
+ obj.add(p);
487
+ } else {
488
+ // or we remove it
489
+ obj.traverse(function (c) {
490
+ if (c.isMesh && c.material instanceof THREE.ShadowMaterial)
491
+ obj.remove(c);
492
+ });
493
+
494
+ }
495
+ _castShadow = value;
496
+
497
+ }
498
+ })
499
+
500
+ //[jscastro] added method to position the shadow box on the floor depending the object height
501
+ obj.setReceiveShadowFloor = function () {
502
+ if (obj.castShadow) {
503
+ let sp = obj.shadowPlane, p = sp.position, r = sp.rotation;
504
+ p.z = -obj.modelHeight;
505
+ r.y = obj.rotation.y;
506
+ r.x = -obj.rotation.x;
507
+ if (obj.userData.units === 'meters') {
508
+ const s = obj.modelSize;
509
+ const sz = [s.x, s.y, s.z, -p.z];
510
+ const ps = Math.max(...sz) * 10;
511
+ const sc = ps / sp.geometry.parameters.width;
512
+ sp.scale.set(sc, sc, sc);
513
+ }
514
+ }
515
+ }
516
+
517
+ let _receiveShadow = false;
518
+ //[jscastro] added property for traverse an object to receive a shadow
519
+ Object.defineProperty(obj, 'receiveShadow', {
520
+ get() { return _receiveShadow; },
521
+ set(value) {
522
+ if (!obj.model || _receiveShadow === value) return;
523
+ obj.model.traverse(function (c) {
524
+ if (c.isMesh) c.receiveShadow = true;
525
+ });
526
+ _receiveShadow = value;
527
+ }
528
+ })
529
+
530
+ let _wireframe = false;
531
+ //[jscastro] added property for wireframes state
532
+ Object.defineProperty(obj, 'wireframe', {
533
+ get() { return _wireframe; },
534
+ set(value) {
535
+ if (!obj.model || _wireframe === value) return;
536
+ obj.model.traverse(function (c) {
537
+ if (c.type == "Mesh" || c.type == "SkinnedMesh") {
538
+ let materials = [];
539
+ if (!Array.isArray(c.material)) {
540
+ materials.push(c.material);
541
+ } else {
542
+ materials = c.material;
543
+ }
544
+ let m = materials[0];
545
+ if (value) {
546
+ c.userData.materials = m;
547
+ c.material = m.clone();
548
+ c.material.wireframe = c.material.transparent = value;
549
+ c.material.opacity = 0.3;
550
+ } else {
551
+ c.material.dispose();
552
+ c.material = c.userData.materials;
553
+ c.userData.materials.dispose();
554
+ c.userData.materials = null;
555
+ }
556
+
557
+ if (value) { c.layers.disable(0); c.layers.enable(1); } else { c.layers.disable(1); c.layers.enable(0); }
558
+ }
559
+ if (c.type == "LineSegments") {
560
+ c.layers.disableAll();
561
+ }
562
+ });
563
+ _wireframe = value;
564
+ // Dispatch new event WireFramed
565
+ obj.dispatchEvent({ type: 'Wireframed', detail: obj });
566
+ }
567
+ })
568
+
569
+ let _color = null;
570
+ //[jscastro] added property for wireframes state
571
+ Object.defineProperty(obj, 'color', {
572
+ get() { return _color; },
573
+ set(value) {
574
+ if (!obj.model || _color === value) return;
575
+ obj.model.traverse(function (c) {
576
+ if (c.type == "Mesh" || c.type == "SkinnedMesh") {
577
+ let materials = [];
578
+ if (!Array.isArray(c.material)) {
579
+ materials.push(c.material);
580
+ } else {
581
+ materials = c.material;
582
+ }
583
+ let m = materials[0];
584
+ if (value) {
585
+ c.userData.materials = m;
586
+ c.material = new THREE.MeshStandardMaterial();
587
+ c.material.color.setHex(value);
588
+ } else {
589
+ c.material.dispose();
590
+ c.material = c.userData.materials;
591
+ c.userData.materials.dispose();
592
+ c.userData.materials = null;
593
+ }
594
+
595
+ }
596
+ });
597
+ _color = value;
598
+ }
599
+ })
600
+
601
+
602
+ let _selected = false;
603
+ //[jscastro] added property for selected state
604
+ Object.defineProperty(obj, 'selected', {
605
+ get() { return _selected; },
606
+ set(value) {
607
+ if (value) {
608
+ if (obj.userData.bbox && !obj.boundingBox) obj.drawBoundingBox();
609
+ if (obj.boxGroup) {
610
+ obj.boundingBox.material = Objects.prototype._defaults.materials.boxSelectedMaterial;
611
+ obj.boundingBox.parent.visible = true;
612
+ obj.boundingBox.layers.enable(1);
613
+ obj.boundingBoxShadow.layers.enable(1);
614
+ }
615
+ if (obj.label && !obj.label.alwaysVisible) obj.label.visible = true;
616
+ }
617
+ else {
618
+ if (obj.boxGroup) {
619
+ obj.remove(obj.boxGroup); //remove the box group
620
+ }
621
+ if (obj.label && !obj.label.alwaysVisible) obj.label.visible = false;
622
+ obj.removeHelp();
623
+ }
624
+ if (obj.tooltip) obj.tooltip.visible = value;
625
+ //only fire the event if value is different
626
+ if (_selected != value) {
627
+ _selected = value;
628
+ // Dispatch new event SelectedChange
629
+ obj.dispatchEvent({ type: 'SelectedChange', detail: obj });
630
+ }
631
+ }
632
+ })
633
+
634
+ let _raycasted = true;
635
+ //[jscastro] added property for including/excluding an object from raycast
636
+ Object.defineProperty(obj, 'raycasted', {
637
+ get() { return _raycasted; },
638
+ set(value) {
639
+ if (!obj.model || _raycasted === value) return;
640
+ obj.model.traverse(function (c) {
641
+ if (c.type == "Mesh" || c.type == "SkinnedMesh") {
642
+ if (!value) { c.layers.disable(0); c.layers.enable(1); } else { c.layers.disable(1); c.layers.enable(0); }
643
+ }
644
+ });
645
+ _raycasted = value;
646
+ }
647
+ });
648
+
649
+ let _over = false;
650
+ //[jscastro] added property for over state
651
+ Object.defineProperty(obj, 'over', {
652
+ get() { return _over; },
653
+ set(value) {
654
+ if (value) {
655
+ if (!obj.selected) {
656
+ if (obj.userData.bbox && !obj.boundingBox) obj.drawBoundingBox();
657
+ if (obj.userData.tooltip && !obj.tooltip) obj.addTooltip(obj.uuid, true, obj.anchor, false);
658
+ if (obj.boxGroup) {
659
+ obj.boundingBox.material = Objects.prototype._defaults.materials.boxOverMaterial;
660
+ obj.boundingBox.parent.visible = true;
661
+ obj.boundingBox.layers.enable(1);
662
+ obj.boundingBoxShadow.layers.enable(1);
663
+ }
664
+ }
665
+ if (obj.label && !obj.label.alwaysVisible) { obj.label.visible = true; }
666
+ // Dispatch new event ObjectOver
667
+ obj.dispatchEvent({ type: 'ObjectMouseOver', detail: obj });
668
+
669
+ }
670
+ else {
671
+ if (!obj.selected) {
672
+ if (obj.boxGroup) {
673
+ obj.remove(obj.boxGroup); //remove the box group
674
+ if (obj.tooltip && !obj.tooltip.custom) obj.removeTooltip();
675
+ }
676
+ if (obj.label && !obj.label.alwaysVisible) { obj.label.visible = false; }
677
+ }
678
+ // Dispatch new event ObjectOver
679
+ obj.dispatchEvent({ type: 'ObjectMouseOut', detail: obj });
680
+ }
681
+ if (obj.tooltip) obj.tooltip.visible = value || obj.selected;
682
+ _over = value;
683
+ }
684
+ })
685
+
686
+ //[jscastro] get the object model Box3 in runtime
687
+ obj.box3 = function () {
688
+ //update Matrix and MatrixWorld to avoid issues with transformations not full applied
689
+ obj.updateMatrix();
690
+ obj.updateMatrixWorld(true, true);
691
+ let bounds;
692
+ //clone also the model inside it's the one who keeps the real size
693
+ if (obj.model) {
694
+ //let's clone the object before manipulate it
695
+ let dup = obj.clone(true);
696
+ let model = obj.model.clone();
697
+ //get the size of the model because the object is translated and has boundingBoxShadow
698
+ bounds = new THREE.Box3().setFromObject(model);
699
+ //if the object has parent it's already in the added to world so it's scaled and it could be rotated
700
+ if (obj.parent) {
701
+ //first, we return the object to it's original position of rotation, extract rotation and apply inversed
702
+ let rm = new THREE.Matrix4();
703
+ let rmi = new THREE.Matrix4();
704
+ obj.matrix.extractRotation(rm);
705
+ rmi.copy(rm).invert();
706
+ dup.setRotationFromMatrix(rmi);
707
+ //now the object inside will give us a NAABB Non-Axes Aligned Bounding Box
708
+ bounds = new THREE.Box3().setFromObject(model);
709
+ }
710
+ }
711
+ return bounds;
712
+ };
713
+
714
+ //[jscastro] modelBox
715
+ obj.modelBox = function () {
716
+ return obj.box3();
717
+ }
718
+
719
+ obj.getSize = function () {
720
+ return obj.box3().getSize(new THREE.Vector3(0, 0, 0));
721
+ }
722
+
723
+ //[jscastro]
724
+ let _modelSize = false;
725
+ //[jscastro] added property for wireframes state
726
+ Object.defineProperty(obj, 'modelSize', {
727
+ get() {
728
+ _modelSize = obj.getSize();
729
+ return _modelSize;
730
+ },
731
+ set(value) {
732
+ if (_modelSize != value) {
733
+ _modelSize = value;
734
+ }
735
+ }
736
+ })
737
+
738
+
739
+ //[jscastro] added property to get modelHeight
740
+ Object.defineProperty(obj, 'modelHeight', {
741
+ get() {
742
+ let h = obj.coordinates[2] || 0;
743
+ if (obj.userData.units === 'scene') h *= (obj.unitsPerMeter / obj.scale.x);
744
+ return h;
745
+ }
746
+ });
747
+
748
+ //[jscastro] added property to calculate the units per meter in a given latitude
749
+ //reduced to 7 decimals to avoid deviations on the size of the same object
750
+ Object.defineProperty(obj, 'unitsPerMeter', {
751
+ get() { return Number(utils.projectedUnitsPerMeter(obj.coordinates[1]).toFixed(7)); }
752
+ });
753
+
754
+ let _fixedZoom = null;
755
+ //[jscastro] added property to have a fixed scale for some objects
756
+ Object.defineProperty(obj, 'fixedZoom', {
757
+ get() { return obj.userData.fixedZoom; },
758
+ set(value) {
759
+ if (obj.userData.fixedZoom === value) return;
760
+ obj.userData.fixedZoom = value;
761
+ obj.userData.units = (value ? 'scene' : 'meters');
762
+ }
763
+ });
764
+
765
+ //[jscastro] sets the scale of an object based fixedZoom
766
+ obj.setFixedZoom = function (scale) {
767
+ if (obj.fixedZoom != null && obj.fixedZoom != 0) {
768
+ if (!scale) scale = obj.userData.mapScale;
769
+ let s = zoomScale(obj.fixedZoom);
770
+ if (s > scale) {
771
+ let calc = s / scale;
772
+ obj.scale.set(calc, calc, calc);
773
+ } else {
774
+ obj.scale.set(1, 1, 1);
775
+ }
776
+ }
777
+ }
778
+
779
+ //[jscastro] sets the scale of an object based in the scale and fixedZoom
780
+ obj.setScale = function (scale) {
781
+ // scale the model so that its units are interpreted as meters at the given latitude
782
+ if (obj.userData.units != 'scene') {
783
+ let s = obj.unitsPerMeter;
784
+ obj.scale.set(s, s, s);
785
+ } else if (obj.fixedZoom) {
786
+ if (scale) obj.userData.mapScale = scale;
787
+ obj.setFixedZoom(obj.userData.mapScale); //apply fixed zoom
788
+ } else obj.scale.set(1, 1, 1);
789
+ }
790
+
791
+ function zoomScale(zoom) { return Math.pow(2, zoom); }
792
+
793
+ //[jscastro] sets the scale and shadows position of an object based in the scale
794
+ obj.setObjectScale = function (scale) {
795
+ obj.setScale(scale);
796
+ obj.setBoundingBoxShadowFloor();
797
+ obj.setReceiveShadowFloor();
798
+ }
799
+
800
+ }
801
+
802
+ obj.add = function (o) {
803
+ obj.scaleGroup.add(o);
804
+ o.position.z = (obj.coordinates[2] ? -obj.coordinates[2] : 0);
805
+ return o;
806
+ }
807
+
808
+ obj.remove = function (o) {
809
+ if (!o) return;
810
+ o.traverse(m => {
811
+ //console.log('dispose geometry!')
812
+ if (m.geometry) m.geometry.dispose();
813
+ if (m.material) {
814
+ if (m.material.isMaterial) {
815
+ cleanMaterial(m.material)
816
+ } else {
817
+ // an array of materials
818
+ for (const material of m.material) cleanMaterial(material)
819
+ }
820
+ }
821
+ if (m.dispose) m.dispose();
822
+ })
823
+
824
+ obj.scaleGroup.remove(o);
825
+ map.repaint = true;
826
+ }
827
+
828
+ //[jscastro] clone + assigning all the attributes
829
+ obj.duplicate = function (options) {
830
+
831
+ let dupe = obj.clone(true); //clone the whole threebox object
832
+ dupe.getObjectByName("model").animations = obj.animations; //we must set this explicitly before addMethods
833
+ if (dupe.userData.feature) {
834
+ if (options && options.feature) dupe.userData.feature = options.feature;
835
+ dupe.userData.feature.properties.uuid = dupe.uuid;
836
+ }
837
+ root._addMethods(dupe); // add methods
838
+
839
+ if (!options || utils.equal(options.scale, obj.userData.scale)) {
840
+ //no options, no changes, just return the same object
841
+ dupe.copyAnchor(obj); // copy anchors
842
+ //[jscastro] we add by default a tooltip that can be overriden later or hide it with threebox `enableTooltips`
843
+ return dupe;
844
+ } else {
845
+ dupe.userData = options;
846
+ dupe.userData.isGeoGroup = true;
847
+ dupe.remove(dupe.boxGroup);
848
+ // [jscastro] rotate and scale the model
849
+ const r = utils.types.rotation(options.rotation, [0, 0, 0]);
850
+ const s = utils.types.scale(options.scale, [1, 1, 1]);
851
+ // [jscastro] reposition to 0,0,0
852
+ dupe.model.position.set(0, 0, 0);
853
+ // rotate and scale
854
+ dupe.model.rotation.set(r[0], r[1], r[2]);
855
+ dupe.model.scale.set(s[0], s[1], s[2]);
856
+ //[jscastro] calculate automatically the pivotal center of the object
857
+ dupe.setAnchor(options.anchor);
858
+ //[jscastro] override the center calculated if the object has adjustments
859
+ dupe.setCenter(options.adjustment);
860
+ return dupe;
861
+
862
+ }
863
+
864
+ }
865
+
866
+ //[jscastro] copy anchor values
867
+ obj.copyAnchor = function (o) {
868
+
869
+ obj.anchor = o.anchor;
870
+ obj.none = { x: 0, y: 0, z: 0 };
871
+ obj.center = o.center;
872
+ obj.bottom = o.bottom;
873
+ obj.bottomLeft = o.bottomLeft;
874
+ obj.bottomRight = o.bottomRight;
875
+ obj.top = o.top;
876
+ obj.topLeft = o.topLeft;
877
+ obj.topRight = o.topRight;
878
+ obj.left = o.left;
879
+ obj.right = o.right;
880
+
881
+ }
882
+
883
+ obj.dispose = function () {
884
+
885
+ Objects.prototype.unenroll(obj);
886
+
887
+ obj.traverse(o => {
888
+ //don't dispose th object itself as it will be recursive
889
+ if (o.parent && o.parent.name == "world") return;
890
+ if (o.name === "threeboxObject") return;
891
+
892
+ //console.log('dispose geometry!')
893
+ if (o.geometry) o.geometry.dispose();
894
+
895
+ if (o.material) {
896
+ if (o.material.isMaterial) {
897
+ cleanMaterial(o.material)
898
+ } else {
899
+ // an array of materials
900
+ for (const material of o.material) cleanMaterial(material)
901
+ }
902
+ }
903
+ if (o.dispose) o.dispose();
904
+
905
+ })
906
+
907
+ obj.children = [];
908
+
909
+ }
910
+
911
+ const cleanMaterial = material => {
912
+ //console.log('dispose material!')
913
+ material.dispose()
914
+
915
+ // dispose textures
916
+ for (const key of Object.keys(material)) {
917
+ const value = material[key]
918
+ if (value && typeof value === 'object' && 'minFilter' in value) {
919
+ //console.log('dispose texture!')
920
+ value.dispose()
921
+ }
922
+ }
923
+ let m = material;
924
+ let md = (m.map || m.alphaMap || m.aoMap || m.bumpMap || m.displacementMap || m.emissiveMap || m.envMap || m.lightMap || m.metalnessMap || m.normalMap || m.roughnessMap)
925
+ if (md) {
926
+ if (m.map) m.map.dispose();
927
+ if (m.alphaMap) m.alphaMap.dispose();
928
+ if (m.aoMap) m.aoMap.dispose();
929
+ if (m.bumpMap) m.bumpMap.dispose();
930
+ if (m.displacementMap) m.displacementMap.dispose();
931
+ if (m.emissiveMap) m.emissiveMap.dispose();
932
+ if (m.envMap) m.envMap.dispose();
933
+ if (m.lightMap) m.lightMap.dispose();
934
+ if (m.metalnessMap) m.metalnessMap.dispose();
935
+ if (m.normalMap) m.normalMap.dispose();
936
+ if (m.roughnessMap) m.roughnessMap.dispose();
937
+ }
938
+ }
939
+
940
+ return obj
941
+ },
942
+
943
+ _makeGroup: function (obj, options) {
944
+ let projScaleGroup = new THREE.Group();
945
+ projScaleGroup.name = "scaleGroup";
946
+ projScaleGroup.add(obj)
947
+
948
+ var geoGroup = new THREE.Group();
949
+ geoGroup.userData = options || {};
950
+ geoGroup.userData.isGeoGroup = true;
951
+ if (geoGroup.userData.feature) {
952
+ geoGroup.userData.feature.properties.uuid = geoGroup.uuid;
953
+ }
954
+ var isArrayOfObjects = projScaleGroup.length;
955
+ if (isArrayOfObjects) for (o of projScaleGroup) geoGroup.add(o)
956
+ else geoGroup.add(projScaleGroup);
957
+
958
+ //utils._flipMaterialSides(projScaleGroup);
959
+ geoGroup.name = "threeboxObject";
960
+ return geoGroup
961
+ },
962
+
963
+ animationManager: new AnimationManager,
964
+
965
+ //[jscastro] add tooltip method
966
+ drawTooltip : function (tooltipText, mapboxStyle = false) {
967
+ if (tooltipText) {
968
+ let divToolTip;
969
+ if (mapboxStyle) {
970
+ let divContent = document.createElement('div');
971
+ divContent.className = 'mapboxgl-popup-content';
972
+ let strong = document.createElement('strong');
973
+ strong.innerHTML = tooltipText;
974
+ divContent.appendChild(strong);
975
+ let tip = document.createElement('div');
976
+ tip.className = 'mapboxgl-popup-tip';
977
+ let div = document.createElement('div');
978
+ div.className = 'marker mapboxgl-popup-anchor-bottom';
979
+ div.appendChild(tip);
980
+ div.appendChild(divContent);
981
+ divToolTip = document.createElement('div');
982
+ divToolTip.className += 'label3D';
983
+ divToolTip.appendChild(div);
984
+ }
985
+ else {
986
+ divToolTip = document.createElement('span');
987
+ divToolTip.className = this._defaults.tooltip.cssClass;
988
+ divToolTip.innerHTML = tooltipText;
989
+ }
990
+ return divToolTip;
991
+ }
992
+ },
993
+
994
+ //[jscastro] draw label method can be invoked separately
995
+ drawLabelHTML: function (HTMLElement, cssClass) {
996
+ let div = document.createElement('div');
997
+ div.className += cssClass;
998
+ // [jscastro] create a div [TODO] analize if must be moved
999
+ if (typeof (HTMLElement) == 'string') {
1000
+ div.innerHTML = HTMLElement;
1001
+ } else {
1002
+ div.innerHTML = HTMLElement.outerHTML;
1003
+ }
1004
+ return div;
1005
+ },
1006
+
1007
+ _defaults: {
1008
+ colors: {
1009
+ red: new THREE.Color(0xff0000),
1010
+ yellow: new THREE.Color(0xffff00),
1011
+ green: new THREE.Color(0x00ff00),
1012
+ black: new THREE.Color(0x000000)
1013
+ },
1014
+
1015
+ materials: {
1016
+ boxNormalMaterial: new THREE.LineBasicMaterial({ color: new THREE.Color(0xff0000) }),
1017
+ boxOverMaterial: new THREE.LineBasicMaterial({ color: new THREE.Color(0xffff00) }),
1018
+ boxSelectedMaterial: new THREE.LineBasicMaterial({ color: new THREE.Color(0x00ff00) })
1019
+ },
1020
+
1021
+ line: {
1022
+ geometry: null,
1023
+ color: 'black',
1024
+ width: 1,
1025
+ opacity: 1
1026
+ },
1027
+
1028
+ label: {
1029
+ htmlElement: null,
1030
+ cssClass: " label3D",
1031
+ alwaysVisible: false,
1032
+ topMargin: -0.5
1033
+ },
1034
+
1035
+ tooltip: {
1036
+ text: '',
1037
+ cssClass: 'toolTip text-xs',
1038
+ mapboxStyle: false,
1039
+ topMargin: 0
1040
+ },
1041
+
1042
+ sphere: {
1043
+ position: [0, 0, 0],
1044
+ radius: 1,
1045
+ sides: 20,
1046
+ units: 'scene',
1047
+ material: 'MeshBasicMaterial',
1048
+ anchor: 'bottom-left',
1049
+ bbox: true,
1050
+ tooltip: true,
1051
+ raycasted: true
1052
+
1053
+ },
1054
+
1055
+ tube: {
1056
+ geometry: null,
1057
+ radius: 1,
1058
+ sides: 6,
1059
+ units: 'scene',
1060
+ material: 'MeshBasicMaterial',
1061
+ anchor: 'center',
1062
+ bbox: true,
1063
+ tooltip: true,
1064
+ raycasted: true
1065
+ },
1066
+
1067
+ loadObj: {
1068
+ type: null,
1069
+ obj: null,
1070
+ units: 'scene',
1071
+ scale: 1,
1072
+ rotation: 0,
1073
+ defaultAnimation: 0,
1074
+ anchor: 'bottom-left',
1075
+ bbox: true,
1076
+ tooltip: true,
1077
+ raycasted: true,
1078
+ clone: true
1079
+ },
1080
+
1081
+ Object3D: {
1082
+ obj: null,
1083
+ units: 'scene',
1084
+ anchor: 'bottom-left',
1085
+ bbox: true,
1086
+ tooltip: true,
1087
+ raycasted: true
1088
+ },
1089
+
1090
+ extrusion: {
1091
+ coordinates: [[[]]],
1092
+ geometryOptions: {},
1093
+ height: 100,
1094
+ materials: new THREE.MeshPhongMaterial({ color: 0x660000, side: THREE.DoubleSide }),
1095
+ scale: 1,
1096
+ rotation: 0,
1097
+ units: 'scene',
1098
+ anchor: 'center',
1099
+ bbox: true,
1100
+ tooltip: true,
1101
+ raycasted: true
1102
+
1103
+ }
1104
+ },
1105
+
1106
+ geometries: {
1107
+ line: ['LineString'],
1108
+ tube: ['LineString'],
1109
+ sphere: ['Point'],
1110
+ }
1111
+ }
1112
+ export default Objects
1113
+ //module.exports = exports = Objects;