@eturnity/eturnity_3d 0.0.4

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 (78) hide show
  1. package/.babelrc +3 -0
  2. package/.env +0 -0
  3. package/.eslintrc +18 -0
  4. package/.eslintrc.json +18 -0
  5. package/.prettierrc +7 -0
  6. package/Dockerfile +17 -0
  7. package/README.md +18 -0
  8. package/bitbucket-pipelines.yml +681 -0
  9. package/dist/assets/images/panels/longiSolarLR4_60HPH_350M.png +0 -0
  10. package/dist/assets/images/panels/longiSolarLR4_60HPH_370M.png +0 -0
  11. package/dist/assets/images/panels/reneSola_Virtus_2_JC320S_24_Bbw copy.png +0 -0
  12. package/dist/assets/images/panels/reneSola_Virtus_2_JC320S_24_Bbw.png +0 -0
  13. package/dist/assets/images/panels/uv.png +0 -0
  14. package/dist/assets/panels/longiSolarLR4_60HPH_350M.png +0 -0
  15. package/dist/assets/panels/longiSolarLR4_60HPH_370M.png +0 -0
  16. package/dist/assets/panels/reneSola_Virtus_2_JC320S_24_Bbw.png +0 -0
  17. package/dist/assets/panels/uv.png +0 -0
  18. package/dist/assets/theme.js +43 -0
  19. package/dist/assets/vue.svg +1 -0
  20. package/dist/css/main.1f8fe45d.css +1 -0
  21. package/dist/img/longiSolarLR4_60HPH_350M.85a84b2e.png +0 -0
  22. package/dist/img/longiSolarLR4_60HPH_370M.bf6b1f4e.png +0 -0
  23. package/dist/img/reneSola_Virtus_2_JC320S_24_Bbw.8b1892e0.png +0 -0
  24. package/dist/index.html +26 -0
  25. package/dist/main.js +60230 -0
  26. package/dist/main.js.map +1 -0
  27. package/dist/vite.svg +1 -0
  28. package/docker_conf/nginx/nginx.conf +16 -0
  29. package/index.html +26 -0
  30. package/package.json +71 -0
  31. package/postcss.config.js +1 -0
  32. package/preview.html +55 -0
  33. package/public/assets/images/panels/longiSolarLR4_60HPH_350M.png +0 -0
  34. package/public/assets/images/panels/longiSolarLR4_60HPH_370M.png +0 -0
  35. package/public/assets/images/panels/reneSola_Virtus_2_JC320S_24_Bbw copy.png +0 -0
  36. package/public/assets/images/panels/reneSola_Virtus_2_JC320S_24_Bbw.png +0 -0
  37. package/public/assets/images/panels/uv.png +0 -0
  38. package/public/assets/panels/longiSolarLR4_60HPH_350M.png +0 -0
  39. package/public/assets/panels/longiSolarLR4_60HPH_370M.png +0 -0
  40. package/public/assets/panels/reneSola_Virtus_2_JC320S_24_Bbw.png +0 -0
  41. package/public/assets/panels/uv.png +0 -0
  42. package/public/assets/theme.js +43 -0
  43. package/public/assets/vue.svg +1 -0
  44. package/public/vite.svg +1 -0
  45. package/server.js +17 -0
  46. package/src/App.vue +28 -0
  47. package/src/assets/images/panels/longiSolarLR4_60HPH_350M.png +0 -0
  48. package/src/assets/images/panels/longiSolarLR4_60HPH_370M.png +0 -0
  49. package/src/assets/images/panels/reneSola_Virtus_2_JC320S_24_Bbw copy.png +0 -0
  50. package/src/assets/images/panels/reneSola_Virtus_2_JC320S_24_Bbw.png +0 -0
  51. package/src/assets/images/panels/uv.png +0 -0
  52. package/src/assets/images/white_tile.png +0 -0
  53. package/src/assets/theme.js +43 -0
  54. package/src/components/ThreeCanvasViewer.vue +247 -0
  55. package/src/config.js +104 -0
  56. package/src/functions.js +2 -0
  57. package/src/helper/DFS.js +80 -0
  58. package/src/helper/MapView.js +253 -0
  59. package/src/helper/UpdateRoofModuleFieldRelations.js +119 -0
  60. package/src/helper/UpdateRoofObstacleRelations.js +86 -0
  61. package/src/helper/clearThreeObjects.js +21 -0
  62. package/src/helper/customProvider.js +57 -0
  63. package/src/helper/geometryHandler.js +606 -0
  64. package/src/helper/graphCreation.js +43 -0
  65. package/src/helper/materials.js +55 -0
  66. package/src/helper/projectedMaterial.js +502 -0
  67. package/src/helper/renderMixin.js +1132 -0
  68. package/src/helper/threeMixin.js +171 -0
  69. package/src/main.js +28 -0
  70. package/src/store/AddMargin.js +107 -0
  71. package/src/store/hydrateData.js +209 -0
  72. package/src/store/nodesEdgesCreation.js +216 -0
  73. package/src/store/store.js +10 -0
  74. package/src/store/three-d-module.js +142 -0
  75. package/src/style.css +96 -0
  76. package/src/utils/layers.js +265 -0
  77. package/src/utils/leaflet-config.service.js +67 -0
  78. package/vue.config.js +46 -0
@@ -0,0 +1,1132 @@
1
+ import {mapState, mapGetters } from 'vuex'
2
+ import * as THREE from 'three'
3
+ import TWEEN from 'tween'
4
+ import {
5
+ maximumGapLimit,
6
+ colorArrayBase,
7
+ } from '../config'
8
+ import {
9
+ addVector,
10
+ multiplyVector,
11
+ verticalProjectionOnPlane,
12
+ } from '@eturnity/eturnity_maths'
13
+ import {
14
+ getBufferWallGeometry,
15
+ updateBufferWallGeometry,
16
+ getBufferRoofGeometry,
17
+ updateBufferRoofGeometry,
18
+ getBufferObstacleGeometry,
19
+ getBufferObstacleSideGeometry,
20
+ getBufferModuleFieldGeometry,
21
+ getBufferPanelGeometry,
22
+ updateBufferPanelGeometry,
23
+ getBufferPanelSideGeometry,
24
+ updateBufferPanelSideGeometry,
25
+ getBufferRoofMarginGeometry
26
+ } from './geometryHandler'
27
+ import ProjectedMaterial from 'three-projected-material'
28
+ import { material } from './materials'
29
+ import { intersectOutlines } from '@eturnity/eturnity_maths'
30
+ import clearThreeObjects from './clearThreeObjects'
31
+ const meshTypes = [
32
+ 'baseMeshes',
33
+ 'backgroundMesh',
34
+ 'roofMeshes',
35
+ 'flatRoofMeshes',
36
+ 'obstacleMeshes',
37
+ 'panelsMeshes',
38
+ 'nodeMeshes',
39
+ 'edgeMeshes',
40
+ 'roofMarginMeshes',
41
+ 'moduleFieldsMeshes'
42
+ ]
43
+
44
+ export default {
45
+ data() {
46
+ return {
47
+ meshes: {
48
+ baseMeshes: {},
49
+ backgroundMesh: null,
50
+ roofMeshes: {},
51
+ flatRoofMeshes: {},
52
+ obstacleMeshes: {},
53
+ panelsMeshes: {},
54
+ nodeMeshes: null,
55
+ edgeMeshes: {},
56
+ roofMarginMeshes: {},
57
+ moduleFieldsMeshes: {}
58
+ },
59
+ lastTic: new Date().getTime() * 1e4,
60
+ //lastTic:(new Date()).getTime()
61
+ lastGeometryEventIdDone: -1,
62
+ backgroundImagesizeInMm:null,
63
+ }
64
+ },
65
+ created() {
66
+ this.meshes = {
67
+ baseMeshes: {},
68
+ backgroundMesh: null,
69
+ roofMeshes: {},
70
+ flatRoofMeshes: {},
71
+ obstacleMeshes: {},
72
+ panelsMeshes: {},
73
+ nodeMeshes: null,
74
+ edgeMeshes: {},
75
+ roofMarginMeshes: {},
76
+ moduleFieldsMeshes: {}
77
+ }
78
+ },
79
+
80
+ computed: {
81
+ ...mapState({
82
+ module_texture_version_id: (state) => state.threeDModule.module_texture_version_id,
83
+ selectedMapLayer: (state) => state.threeDModule.selectedMapLayer,
84
+ pvDataMemo: (state) => state.threeDModule.pvDataMemo
85
+ }),
86
+ ...mapGetters({
87
+ selectedTool: 'getSelectedTool',
88
+ roofs: 'getRoofs',
89
+ lastGeometryEventId: 'getLastGeometryEventId',
90
+ roofsBounds:'getRoofsBounds',
91
+ geometryEvents: 'getGeometryEvents'
92
+ }),
93
+ layerKey(){
94
+ if(this.selectedMapLayer){
95
+ return this.selectedMapLayer.key
96
+ }else{
97
+ return null
98
+ }
99
+ },
100
+ polygonIds() {
101
+ return this.polygons.map((p) => p.id)
102
+ },
103
+ edgeIds() {
104
+ return this.edges.map((p) => p.id)
105
+ },
106
+ nodeIds() {
107
+ return this.nodes.map((p) => p.id)
108
+ },
109
+ fullRenderNeeded() {
110
+ return !!this.geometryEvents.find(
111
+ (e) => e.id > this.lastGeometryEventIdDone && e.name == 'full'
112
+ )
113
+ },
114
+ geometryEventsToDo() {
115
+ return this.geometryEvents.filter(
116
+ (e) => e.id > this.lastGeometryEventIdDone
117
+ )
118
+ }
119
+ },
120
+ methods: {
121
+ refreshRendering(e) {
122
+ let methodList = []
123
+ if (this.fullRenderNeeded) {
124
+ methodList = this.renderingMethodsByEvent({ name: 'full' })
125
+ this.renderMethods(methodList)
126
+ } else {
127
+ for (let geometryEvent of this.geometryEventsToDo) {
128
+ for (let renderingMethod of this.renderingMethodsByEvent(
129
+ geometryEvent
130
+ )) {
131
+ if (!methodList.map((m) => m.name).includes(renderingMethod.name)) {
132
+ methodList.push(renderingMethod)
133
+ }
134
+ }
135
+ }
136
+ if (methodList.length) {
137
+ this.renderMethods(methodList)
138
+ }
139
+ }
140
+
141
+
142
+ this.lastGeometryEventIdDone = this.lastGeometryEventId
143
+ },
144
+ renderingMethodsByEvent(geometryEvent) {
145
+ const name = geometryEvent.name
146
+ const params = geometryEvent.params
147
+ let methodList = []
148
+ switch (name) {
149
+ case 'setCameraGlobalPosition':
150
+ methodList.push({
151
+ name: 'setCameraGlobalPosition',
152
+ method: this.setCameraGlobalPosition,
153
+ arg: []
154
+ })
155
+ break
156
+ case 'toolChange': //params.toolName
157
+ case 'marginIsSameChange': //params.polygon
158
+ case 'marginDifferentChange': //params.polygon,index
159
+ case 'marginSameChange': //params.polygon
160
+ methodList.push({
161
+ name: 'renderRoofsMargin',
162
+ method: this.renderRoofsMargin,
163
+ arg: []
164
+ })
165
+ break
166
+ case 'full':
167
+ case 'removeNodes': //params.nodes
168
+ case 'removeEdges': //params.edges
169
+ case 'translate': //params.edges
170
+ case 'updateOutlineXY': //params.polygon,?index
171
+ methodList.push({
172
+ name: 'renderGeometry',
173
+ method: this.renderGeometry,
174
+ arg: []
175
+ })
176
+ break
177
+ case 'removePanels': //params.panels
178
+ case 'removeModuleField': //params:moduleField
179
+ case 'textureLoaded':
180
+ case 'alignOnSelectedEdge':
181
+ case 'newModuleField':
182
+ case 'reactivatePanel':
183
+ case 'deactivatePanels': //params.panels
184
+ methodList.push({
185
+ name: 'renderPanels',
186
+ method: this.renderPanels,
187
+ arg: []
188
+ })
189
+ break
190
+ case 'addPointToPolygon': //params.polygon,index
191
+ case 'removeObstacle': //params:obstacle
192
+ case 'removeRoof': //params:roof
193
+ case 'newObstacle':
194
+ case 'newRoofs':
195
+ case 'moveNodesZ': //params.nodes
196
+ case 'solveFlatness': //params.roof
197
+ methodList.push({
198
+ name: 'renderBuilding',
199
+ method: this.renderBuilding,
200
+ arg: []
201
+ })
202
+ methodList.push({
203
+ name: 'renderPanels',
204
+ method: this.renderPanels,
205
+ arg: []
206
+ })
207
+ break
208
+ case 'selectedRoofChange':
209
+ methodList.push({
210
+ name: 'renderFlatRoofs',
211
+ method: this.renderFlatRoofs,
212
+ arg: []
213
+ })
214
+ break
215
+ case 'subHandleSelectionChange':
216
+ case 'masterHandleSelectionChange':
217
+ case 'unselectAllHandle':
218
+ methodList.push({
219
+ name: 'renderBuilding',
220
+ method: this.renderBuilding,
221
+ arg: []
222
+ })
223
+ break
224
+ case 'parallelChange': //params.obstacle
225
+ case 'obstacleHeightChange': //params.obstacle
226
+ methodList.push({
227
+ name: 'renderObstacles',
228
+ method: this.renderObstacles,
229
+ arg: []
230
+ })
231
+ break
232
+ case 'roofInclineDirectionChange':
233
+ methodList.push({
234
+ name: 'renderBuilding',
235
+ method: this.renderBuilding,
236
+ arg: []
237
+ })
238
+ break
239
+ case 'backgroundTextureChange':
240
+ methodList.push({
241
+ name: 'initialiseThreeMap',
242
+ method: this.initialiseThreeMap,
243
+ arg: []
244
+ })
245
+ methodList.push({
246
+ name: 'updateProjectionMaterial',
247
+ method: this.updateProjectionMaterial,
248
+ arg: []
249
+ })
250
+ break
251
+ }
252
+ return methodList
253
+ },
254
+ async renderMethods(methodList) {
255
+ for (let item of methodList) {
256
+ await item.method(...item.arg)
257
+ }
258
+ },
259
+ renderGeometry() {
260
+ // if (this.mapConfig.sizeInMm) {
261
+ // if (!this.meshes.backgroundMesh) {
262
+ this.renderBackground()
263
+ // }
264
+ // }
265
+ this.renderBuilding()
266
+ this.renderPanels()
267
+ this.renderRoofsMargin()
268
+ },
269
+ renderBuilding() {
270
+ this.renderBase()
271
+ this.renderRoofs()
272
+ this.renderObstacles()
273
+ this.renderNodes()
274
+ this.renderEdges()
275
+ this.renderFlatRoofs()
276
+ },
277
+
278
+ renderBackground() {
279
+ if(this.meshes.backgroundMesh){
280
+ let sizeInMm={width:2000000,height:2000000}
281
+ let positionInMm={x:0,y:0}
282
+ if(this.layoutSettings.background_map_settings && this.layoutSettings.background_map_settings.sizeInMm){
283
+ sizeInMm=this.layoutSettings.background_map_settings.sizeInMm
284
+ positionInMm=this.layoutSettings.background_map_settings.positionInMm
285
+ }
286
+
287
+ this.meshes.backgroundMesh.geometry.dispose()
288
+ let xMin=positionInMm.x/1000-sizeInMm.width/2000
289
+ let xMax=positionInMm.x/1000+sizeInMm.width/2000
290
+ let yMin=positionInMm.y/1000-sizeInMm.height/2000
291
+ let yMax=positionInMm.y/1000+sizeInMm.height/2000
292
+ let c1=[xMin,yMax,0.1]
293
+ let c2=[xMax,yMax,0.1]
294
+ let c3=[xMax,yMin,0.1]
295
+ let c4=[xMin,yMin,0.1]
296
+ let geometry = new THREE.BufferGeometry();
297
+ const vertices = new Float32Array( [
298
+ ...c1,
299
+ ...c4,
300
+ ...c3,
301
+ ...c3,
302
+ ...c2,
303
+ ...c1
304
+ ] );
305
+ geometry.setAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
306
+ geometry.computeVertexNormals()
307
+ this.meshes.backgroundMesh.geometry=geometry
308
+ }else{
309
+ this.initialiseThreeMap()
310
+ // let geometry = new THREE.PlaneGeometry(this.backgroundImagesizeInMm.width / 1000,this.backgroundImagesizeInMm.height / 1000)
311
+ // const backgroundMesh = new THREE.Mesh(geometry, this.material.roof)
312
+ // this.material.roof.project(backgroundMesh)
313
+ // this.scene.add(backgroundMesh)
314
+ // // this.scene.remove(this.meshes.backgroundMesh)
315
+ // this.meshes.backgroundMesh = backgroundMesh
316
+ // backgroundMesh.matrixAutoUpdate = true
317
+ }
318
+ },
319
+ applyTextureOnRoofs(){
320
+ this.roofs.forEach(roof=>{
321
+ //roofs
322
+ let mesh=this.meshes.roofMeshes[roof.id]
323
+ mesh.material=this.material.roof
324
+ this.material.roof.project(mesh)
325
+ //obstacle on roof
326
+ roof.holes.filter(p=>p.layer=="obstacle").forEach(obstacle=>{
327
+ let meshObstacle=this.meshes.obstacleMeshes[obstacle.id + '-' + roof.id + '_top']
328
+ meshObstacle.material=this.material.roof
329
+ this.material.roof.project(meshObstacle)
330
+ })
331
+ })
332
+ //background tile
333
+ this.meshes.backgroundMesh.material=this.material.roof
334
+ this.material.roof.project(this.meshes.backgroundMesh)
335
+ },
336
+ renderBase() {
337
+ //rendering of walls
338
+ //this.clearByType('baseMeshes')
339
+ this.clearRemovedOnes('baseMeshes')
340
+ let geometry
341
+ let mesh
342
+ this.roofs.forEach((roofPolygon) => {
343
+ //everythime the essencials data are changed, version goes up. we compare polygon version and mesh version to know if we have to rerender
344
+ if (
345
+ this.meshes.baseMeshes[roofPolygon.id] &&
346
+ this.meshes.baseMeshes[roofPolygon.id].userData.version <
347
+ roofPolygon.version
348
+ ) {
349
+ //this.clearMesh(this.meshes.baseMeshes[roofPolygon.id])
350
+ mesh = this.meshes.baseMeshes[roofPolygon.id]
351
+ geometry = mesh.geometry
352
+ geometry = updateBufferWallGeometry(roofPolygon, geometry)
353
+ mesh.geometry = geometry
354
+ mesh.updateMatrix()
355
+ }
356
+ if (!this.meshes.baseMeshes[roofPolygon.id]) {
357
+ //create
358
+ geometry = getBufferWallGeometry(roofPolygon)
359
+ mesh = new THREE.Mesh(geometry, this.material.wall)
360
+ mesh.userData.version = roofPolygon.version
361
+ mesh.userData.type = 'baseMeshes'
362
+ mesh.userData.meshId = roofPolygon.id
363
+ mesh.userData.polygonId = roofPolygon.id
364
+ mesh.matrixAutoUpdate = false
365
+ mesh.frustumCulled = false
366
+ //geometry.dispose()
367
+ //geometry=null
368
+ this.scene.add(mesh)
369
+ this.meshes.baseMeshes[roofPolygon.id] = mesh
370
+ }
371
+ })
372
+ },
373
+ updateRoofGeometry(geometry, roofPolygon) {
374
+ const roofOutline = roofPolygon.outline
375
+ let cropedHolesOutline = roofPolygon.holes
376
+ .filter((h) => h.layer == 'obstacle')
377
+ .map((h) => {
378
+ //let's crop obstacle with roof outline
379
+ const cropedHoleOutline =
380
+ intersectOutlines(h.outline, roofPolygon.outline)[0] || []
381
+ const outline = cropedHoleOutline.map((p) => {
382
+ return {
383
+ x: p.x,
384
+ y: p.y,
385
+ z: verticalProjectionOnPlane(
386
+ p,
387
+ roofPolygon.normalVector,
388
+ roofPolygon.flatOutline[0]
389
+ ).z
390
+ }
391
+ })
392
+ return outline
393
+ })
394
+
395
+ cropedHolesOutline = cropedHolesOutline.filter((outline) => !!outline)
396
+ geometry = updateBufferRoofGeometry(
397
+ roofOutline,
398
+ cropedHolesOutline,
399
+ geometry
400
+ )
401
+
402
+ return geometry
403
+ },
404
+ createRoofGeometry(roofPolygon) {
405
+ const roofOutline = roofPolygon.outline
406
+ let cropedHolesOutline = roofPolygon.holes
407
+ .filter((h) => h.layer == 'obstacle')
408
+ .map((h) => {
409
+ //let's crop obstacle with roof outline
410
+ const cropedHoleOutline =
411
+ intersectOutlines(h.outline, roofPolygon.outline)[0] || []
412
+ const outline = cropedHoleOutline.map((p) => {
413
+ return {
414
+ x: p.x,
415
+ y: p.y,
416
+ z: verticalProjectionOnPlane(
417
+ p,
418
+ roofPolygon.normalVector,
419
+ roofPolygon.flatOutline[0]
420
+ ).z
421
+ }
422
+ })
423
+ return outline
424
+ })
425
+
426
+ cropedHolesOutline = cropedHolesOutline.filter((outline) => !!outline)
427
+ let geometry = getBufferRoofGeometry(roofOutline, cropedHolesOutline)
428
+
429
+ return geometry
430
+ },
431
+ renderRoofs() {
432
+ this.clearRemovedOnes('roofMeshes')
433
+ this.roofs.forEach((roofPolygon) => {
434
+ let mesh
435
+ let geometry
436
+ if (
437
+ this.meshes.roofMeshes[roofPolygon.id] &&
438
+ this.meshes.roofMeshes[roofPolygon.id].userData.version <
439
+ roofPolygon.version
440
+ ) {
441
+ //update mesh
442
+ mesh = this.meshes.roofMeshes[roofPolygon.id]
443
+ geometry = mesh.geometry
444
+ geometry = this.updateRoofGeometry(geometry, roofPolygon)
445
+ mesh.geometry = geometry
446
+ if(this.material.roof){
447
+ mesh.material=this.material.roof
448
+ this.material.roof.project(mesh)
449
+ }
450
+ mesh.frustumCulled = false
451
+ mesh.updateMatrix()
452
+ }
453
+ if (!this.meshes.roofMeshes[roofPolygon.id]) {
454
+ //create
455
+ geometry = this.createRoofGeometry(roofPolygon)
456
+ if (geometry) {
457
+ mesh = new THREE.Mesh(geometry, this.material.roof)
458
+ mesh.userData.version = roofPolygon.version
459
+ mesh.userData.type = 'roofMeshes'
460
+ mesh.userData.meshId = roofPolygon.id
461
+ mesh.userData.polygonId = roofPolygon.id
462
+ mesh.matrixAutoUpdate = false
463
+ this.scene.add(mesh)
464
+ if(this.material.roof){
465
+ mesh.material=this.material.roof
466
+ this.material.roof.project(mesh)
467
+ }
468
+ mesh.frustumCulled = false
469
+ this.meshes.roofMeshes[roofPolygon.id] = mesh
470
+ }
471
+ }
472
+ })
473
+ },
474
+ renderFlatRoofs() {
475
+ //this.clearRemovedOnes('flatRoofMeshes')
476
+ this.clearByType('flatRoofMeshes')
477
+ this.roofs.forEach((roofPolygon) => {
478
+ //if(this.meshes.flatRoofMeshes[roofPolygon.id])
479
+ if(roofPolygon.maximumGap < maximumGapLimit) return
480
+ let geometry = getBufferRoofGeometry(roofPolygon.flatOutline)
481
+ if (geometry) {
482
+ const material =this.material.curvedRoof
483
+ const mesh = new THREE.Mesh(geometry, material)
484
+ geometry.dispose()
485
+ geometry = null
486
+ mesh.itemData = roofPolygon
487
+ mesh.frustumCulled = false
488
+ this.scene.add(mesh)
489
+ this.meshes.flatRoofMeshes[roofPolygon.id] = mesh
490
+ }
491
+ })
492
+ },
493
+ renderRoofsMargin() {
494
+ this.clearByType('roofMarginMeshes')
495
+
496
+ if (this.selectedTool == 'selectMargin') {
497
+ this.roofs.forEach((roofPolygon) => {
498
+ const geometries = getBufferRoofMarginGeometry(roofPolygon)
499
+
500
+ geometries.forEach((geometry, index) => {
501
+ if (geometry) {
502
+ const marginColor = roofPolygon.margins.isSameMargin
503
+ ? colorArrayBase[0]
504
+ : colorArrayBase[index % colorArrayBase.length]
505
+ let material = new THREE.MeshPhongMaterial({
506
+ color: marginColor,
507
+ specular: 0x009900,
508
+ shininess: 0,
509
+ flatShading: true,
510
+ side: THREE.DoubleSide,
511
+ transparent: true,
512
+ opacity: 0.8
513
+ })
514
+ const mesh = new THREE.Mesh(geometry, material)
515
+ geometry.dispose()
516
+ this.scene.add(mesh)
517
+ this.meshes.roofMarginMeshes[roofPolygon.id + '_' + index] = mesh
518
+ }
519
+ })
520
+ roofPolygon.holes.forEach((obstaclePolygon) => {
521
+ const geometries = getBufferRoofMarginGeometry(
522
+ obstaclePolygon,
523
+ roofPolygon
524
+ )
525
+ geometries.forEach((geometry, index) => {
526
+ if (geometry) {
527
+ const marginColor = obstaclePolygon.margins.isSameMargin
528
+ ? colorArrayBase[0]
529
+ : colorArrayBase[index % colorArrayBase.length]
530
+ let material = new THREE.MeshPhongMaterial({
531
+ color: marginColor,
532
+ specular: 0x009900,
533
+ shininess: 0,
534
+ flatShading: true,
535
+ side: THREE.DoubleSide,
536
+ transparent: true,
537
+ opacity: 0.8
538
+ })
539
+ const mesh = new THREE.Mesh(geometry, material)
540
+ geometry.dispose()
541
+ geometry = null
542
+ material.dispose()
543
+ material = null
544
+ this.scene.add(mesh)
545
+ this.meshes.roofMarginMeshes[
546
+ obstaclePolygon.id + '_' + roofPolygon.id + '_' + index
547
+ ] = mesh
548
+ }
549
+ })
550
+ })
551
+ })
552
+ }
553
+ },
554
+ renderNodes() {
555
+ let geometry
556
+ if (this.meshes.nodeMeshes) {
557
+ geometry = this.meshes.nodeMeshes.geometry
558
+ geometry.attributes.position.needsUpdate = true
559
+ } else {
560
+ geometry = new THREE.BufferGeometry()
561
+ }
562
+ // let geometry = new THREE.SphereGeometry(node3DRadius, 4, 4)
563
+ const vertices = []
564
+ this.nodes
565
+ .filter((node) => node.layer == 'roof')
566
+ .forEach((node) => {
567
+ vertices.push(node.x / 1000, node.y / 1000, node.z / 1000)
568
+ })
569
+
570
+ if (
571
+ geometry.attributes.position &&
572
+ geometry.attributes.position.array.length <= vertices.length
573
+ ) {
574
+ let positions = geometry.attributes.position.array
575
+ for (let k in vertices) {
576
+ positions[k] = vertices[k]
577
+ }
578
+ geometry.setDrawRange(0, vertices.length / 3)
579
+ } else {
580
+ geometry.setAttribute(
581
+ 'position',
582
+ new THREE.Float32BufferAttribute(vertices, 3)
583
+ )
584
+ }
585
+ let material = this.material.node
586
+ const nodeMeshes = new THREE.Points(geometry, material)
587
+ nodeMeshes.userData.version = 0
588
+ nodeMeshes.userData.type = 'nodeMeshes'
589
+ nodeMeshes.userData.meshId = null
590
+ nodeMeshes.userData.polygonId = null
591
+ nodeMeshes.matrixAutoUpdate = false
592
+ this.meshes.nodeMeshes = nodeMeshes
593
+ this.scene.add(nodeMeshes)
594
+
595
+ },
596
+ renderEdges() {
597
+ this.clearEdgesRemovedOnes('edgeMeshes')
598
+ let cylinder
599
+ //this.clearByType('edgeMeshes')
600
+ // const material = new THREE.LineBasicMaterial( { color: beamColor,transparent:true,opacity:beamOpacity ,sizeAttenuation: true} );
601
+ // material.linewidth=5
602
+ const material = this.material.edge
603
+ this.edges
604
+ .filter((edge) => edge.layer == 'roof')
605
+ .forEach((edge) => {
606
+ cylinder = this.meshes.edgeMeshes[edge.id]
607
+ if (cylinder) {
608
+ //update
609
+ const point_0 = new THREE.Vector3(
610
+ edge.outline[0].x / 1000,
611
+ edge.outline[0].y / 1000,
612
+ edge.outline[0].z / 1000
613
+ )
614
+ const point_1 = new THREE.Vector3(
615
+ edge.outline[1].x / 1000,
616
+ edge.outline[1].y / 1000,
617
+ edge.outline[1].z / 1000
618
+ )
619
+ const midPoint = point_0.clone().add(point_1).multiplyScalar(0.5)
620
+ var direction = new THREE.Vector3().subVectors(point_1, point_0)
621
+ let length = direction.length()
622
+ //cylinder.rotation.set(arrow.rotation)
623
+ var axis = new THREE.Vector3(0, 1, 0)
624
+ cylinder.quaternion.setFromUnitVectors(
625
+ axis,
626
+ direction.clone().normalize()
627
+ )
628
+ //cylinder.position.set(new THREE.Vector3().addVectors( pointX, direction.multiplyScalar(0.5) ))
629
+ cylinder.position.copy(midPoint.clone())
630
+ let oldLength = cylinder.userData.cylinderLength
631
+ let newLength = length
632
+ if (oldLength != 0) {
633
+ let scaleRatio = newLength / oldLength
634
+ //let scaleVector=direction.multiplyScalar(scaleRatio-1)
635
+ cylinder.scale.set(1, newLength, 1)
636
+ cylinder.userData.cylinderLength = newLength
637
+ }
638
+ cylinder.updateMatrix()
639
+ //change cylinder length
640
+ } else {
641
+ const point_0 = new THREE.Vector3(
642
+ edge.outline[0].x / 1000,
643
+ edge.outline[0].y / 1000,
644
+ edge.outline[0].z / 1000
645
+ )
646
+ const point_1 = new THREE.Vector3(
647
+ edge.outline[1].x / 1000,
648
+ edge.outline[1].y / 1000,
649
+ edge.outline[1].z / 1000
650
+ )
651
+
652
+ const midPoint = point_0.clone().add(point_1).multiplyScalar(0.5)
653
+ var direction = new THREE.Vector3().subVectors(point_1, point_0)
654
+ let length = direction.length()
655
+ const geometry = new THREE.CylinderGeometry(0.1, 0.1, 1, 6)
656
+ cylinder = new THREE.Mesh(geometry, material)
657
+ cylinder.scale.set(1, length, 1)
658
+ cylinder.userData.cylinderLength = length
659
+ //cylinder.rotation.set(arrow.rotation)
660
+ var axis = new THREE.Vector3(0, 1, 0)
661
+ cylinder.quaternion.setFromUnitVectors(
662
+ axis,
663
+ direction.clone().normalize()
664
+ )
665
+ //cylinder.position.set(new THREE.Vector3().addVectors( pointX, direction.multiplyScalar(0.5) ))
666
+ cylinder.position.copy(midPoint.clone())
667
+ //cylinder.position.set(edge.outline[0].x/1000, edge.outline[0].y/1000, edge.outline[0].z/1000);
668
+ cylinder.userData.edgeId = edge.id
669
+ cylinder.matrixAutoUpdate = false
670
+ this.meshes.edgeMeshes[edge.id] = cylinder
671
+ this.scene.add(cylinder)
672
+
673
+ }
674
+ })
675
+ },
676
+
677
+ renderObstacles() {
678
+ this.clearByType('obstacleMeshes')
679
+
680
+ this.roofs.forEach((roofPolygon) => {
681
+ roofPolygon.holes
682
+ .filter((poly) => poly.layer == 'obstacle')
683
+ .forEach((obstaclePolygon) => {
684
+ const geometry = getBufferObstacleGeometry(
685
+ obstaclePolygon,
686
+ roofPolygon
687
+ )
688
+
689
+ const geometrySide = getBufferObstacleSideGeometry(
690
+ obstaclePolygon,
691
+ roofPolygon
692
+ )
693
+ if (geometry && geometrySide) {
694
+ const mesh = new THREE.Mesh(geometry, this.material.roof)
695
+ const meshSide = new THREE.Mesh(geometrySide, material.wall)
696
+ geometry.dispose()
697
+ geometrySide.dispose()
698
+ if(this.material.roof){
699
+ mesh.material=this.material.roof
700
+ this.material.roof.project(mesh)
701
+ }
702
+ mesh.matrixAutoUpdate = false
703
+ meshSide.matrixAutoUpdate = false
704
+ mesh.frustumCulled = false
705
+ meshSide.frustumCulled = false
706
+ this.scene.add(mesh)
707
+ this.scene.add(meshSide)
708
+ this.meshes.obstacleMeshes[
709
+ obstaclePolygon.id + '-' + roofPolygon.id + '_top'
710
+ ] = mesh
711
+ this.meshes.obstacleMeshes[
712
+ obstaclePolygon.id + '-' + roofPolygon.id + '_side'
713
+ ] = meshSide
714
+ }
715
+ })
716
+ })
717
+ },
718
+ renderModuleFields() {
719
+ this.clearByType('moduleFieldsMeshes')
720
+
721
+ this.moduleFields.forEach((moduleFieldPolygon) => {
722
+ const geometry = getBufferModuleFieldGeometry(moduleFieldPolygon)
723
+ if (geometry) {
724
+ const mesh = new THREE.Mesh(geometry, this.material.moduleField)
725
+ geometry.dispose()
726
+ mesh.matrixAutoUpdate = false
727
+ this.scene.add(mesh)
728
+ this.meshes.moduleFieldsMeshes[moduleFieldPolygon.id] = mesh
729
+ }
730
+ })
731
+ },
732
+ renderPanels() {
733
+ this.clearRemovedOnes('panelsMeshes')
734
+ //clear UserDeactivatedModules
735
+ Object.values(this.meshes.panelsMeshes).forEach((mesh) => {
736
+ if (
737
+ this.polygons.find(
738
+ (poly) =>
739
+ poly.id == mesh.userData.polygonId &&
740
+ poly.layer == 'user_deactivated_panel'
741
+ )
742
+ ) {
743
+ this.clearMesh(mesh)
744
+ }
745
+ })
746
+
747
+ this.panels.forEach((panelPolygon) => {
748
+
749
+ //definition of the material
750
+ let material = this.material.panel['default_'+this.module_texture_version_id]
751
+ console.log("material Texture",panelPolygon,panelPolygon.moduleField,panelPolygon.moduleField.pvData)
752
+ if (panelPolygon.moduleField.pvData) {
753
+ let pvId = panelPolygon.moduleField.pvData.id
754
+ if (this.material.panel[pvId]) {
755
+ material = this.material.panel[pvId]
756
+ }
757
+ }else if(panelPolygon.moduleField.data){
758
+ let pvId = panelPolygon.moduleField.data.component_id_pv_module
759
+ if (this.material.panel[pvId]) {
760
+ material = this.material.panel[pvId]
761
+ }
762
+ }
763
+
764
+ if (
765
+ !this.meshes.panelsMeshes[panelPolygon.id + '_top'] ||
766
+ !this.meshes.panelsMeshes[panelPolygon.id + '_side']
767
+ ) {
768
+ const geometry = getBufferPanelGeometry(panelPolygon)
769
+ const geometrySide = getBufferPanelSideGeometry(panelPolygon)
770
+
771
+ if (geometry && geometrySide) {
772
+
773
+ const mesh = new THREE.Mesh(geometry, material)
774
+ const meshSide = new THREE.Mesh(geometrySide, this.material.wall)
775
+ mesh.userData.version = panelPolygon.version
776
+ mesh.userData.type = 'panelsMeshes'
777
+ mesh.userData.meshId = panelPolygon.id + '_top'
778
+ mesh.userData.polygonId = panelPolygon.id
779
+ meshSide.userData.version = panelPolygon.version
780
+ meshSide.userData.type = 'panelsMeshes'
781
+ meshSide.userData.meshId = panelPolygon.id + '_side'
782
+ meshSide.userData.polygonId = panelPolygon.id
783
+ geometry.dispose()
784
+ geometrySide.dispose()
785
+ this.scene.add(mesh)
786
+ this.scene.add(meshSide)
787
+ mesh.matrixAutoUpdate = false
788
+ meshSide.matrixAutoUpdate = false
789
+ this.meshes.panelsMeshes[panelPolygon.id + '_top'] = mesh
790
+ this.meshes.panelsMeshes[panelPolygon.id + '_side'] = meshSide
791
+ }
792
+ }else{
793
+ const topMesh=this.meshes.panelsMeshes[panelPolygon.id + '_top']
794
+ const sideMesh=this.meshes.panelsMeshes[panelPolygon.id + '_side']
795
+ if(panelPolygon.version>topMesh.userData.version){
796
+ topMesh.geometry=updateBufferPanelGeometry(panelPolygon,topMesh.geometry)
797
+ sideMesh.geometry=updateBufferPanelSideGeometry(panelPolygon,sideMesh.geometry)
798
+ }
799
+ let pvId = panelPolygon.moduleField.pvData.id
800
+ topMesh.material= material
801
+
802
+ }
803
+ })
804
+ },
805
+ async updateProjectionMaterial(){
806
+ await this.loadProjectionMaterial()
807
+ this.applyTextureOnRoofs()
808
+ this.renderBackground()
809
+ },
810
+ async loadProjectionMaterial() {
811
+ if(!this.layoutSettings.base64_image_url) return
812
+ const _this=this
813
+ let projectedMaterialLoaded= await new Promise((resolve,reject) => {
814
+ this.loader.load(this.layoutSettings.base64_image_url,(texture)=>{
815
+ let backgroundImageZoomLvl=_this.layoutSettings.map_zoom
816
+ let backgroundImageCenter={
817
+ lat:_this.layoutSettings.layout_latitude,
818
+ lng:_this.layoutSettings.layout_longitude
819
+ }
820
+ if(_this.layoutSettings.background_map_settings){
821
+ backgroundImageZoomLvl=_this.layoutSettings.background_map_settings.zoom_lvl
822
+ backgroundImageCenter={
823
+ lat:_this.layoutSettings.background_map_settings.lat,
824
+ lng:_this.layoutSettings.background_map_settings.lng
825
+ }
826
+ }
827
+ _this.backgroundImagesizeInMm=_this.layoutSettings.background_map_settings.sizeInMm
828
+ if (_this.backgroundImagesizeInMm) {
829
+ _this.cameraprojection.aspect =
830
+ _this.backgroundImagesizeInMm.width / _this.backgroundImagesizeInMm.height
831
+ let projectionAltitude =
832
+ _this.backgroundImagesizeInMm.height /
833
+ (2 * Math.tan((_this.cameraprojection.fov * Math.PI) / 360))
834
+
835
+
836
+ //set projection camera over background_map_center
837
+ let cameraProjectionPosition={x:0,y:0,z:projectionAltitude / 1000}
838
+ if(_this.layoutSettings.background_map_settings && _this.layoutSettings.background_map_settings.positionInMm){
839
+ // let averageLat=(_this.layoutSettings.layout_latitude+_this.layoutSettings.background_map_settings.lat)/2
840
+ // let deltaLat=_this.layoutSettings.background_map_settings.lat-_this.layoutSettings.layout_latitude
841
+ // let deltaLng=_this.layoutSettings.background_map_settings.lng-_this.layoutSettings.layout_longitude
842
+ // let {x:x_mm,y:y_mm}=deltaLatLngToDistance(deltaLat,deltaLng,averageLat)
843
+ let positionInMm=this.layoutSettings.background_map_settings.positionInMm
844
+ cameraProjectionPosition.x=positionInMm.x/1000
845
+ cameraProjectionPosition.y=positionInMm.y/1000
846
+ }
847
+
848
+ _this.cameraprojection.position.set(cameraProjectionPosition.x, cameraProjectionPosition.y, projectionAltitude / 1000)
849
+ _this.cameraprojection.far = projectionAltitude * 16
850
+ _this.cameraprojection.updateProjectionMatrix()
851
+ }
852
+
853
+ let projectionMaterial = new ProjectedMaterial({
854
+ camera: _this.cameraprojection,
855
+ texture: texture
856
+ })
857
+ resolve(projectionMaterial)
858
+ })
859
+ })
860
+ this.material.roof =projectedMaterialLoaded
861
+ },
862
+ setCameraGlobalPosition() {
863
+ if(this.roofs.length==0)return
864
+ let bounds=this.roofsBounds
865
+ let targetVector={x:(bounds.xMax+bounds.xMin)/2000,y:(bounds.yMax+bounds.yMin)/2000,z:0}
866
+ let objectRadius_m=Math.max((bounds.xMax-bounds.xMin)/2000,(bounds.yMax-bounds.yMin)/2000)
867
+ let distance =
868
+ 5 + objectRadius_m / Math.sin(((this.camera.fov / 2) * Math.PI) / 180)
869
+ let cameraMoveVector = { x: 0, y: 0, z: distance }
870
+ const positionVector = addVector(targetVector, cameraMoveVector)
871
+ const position = [
872
+ positionVector.x,
873
+ positionVector.y - distance,
874
+ positionVector.z
875
+ ]
876
+ let target=[
877
+ targetVector.x,
878
+ targetVector.y,
879
+ targetVector.z
880
+ ]
881
+
882
+ this.setTweenTo(position,target)
883
+ },
884
+ setCameraOrthogonalTo(polygon) {
885
+ if (polygon) {
886
+ let polygonRef = polygon
887
+ const targetVector = polygonRef.meanPoint
888
+ const target = [
889
+ targetVector.x / 1000,
890
+ targetVector.y / 1000,
891
+ targetVector.z / 1000
892
+ ]
893
+ const positionVector = addVector(
894
+ polygonRef.meanPoint,
895
+ multiplyVector(45000, polygonRef.normalVector)
896
+ )
897
+ const position = [
898
+ positionVector.x / 1000,
899
+ positionVector.y / 1000 - 1,
900
+ positionVector.z / 1000
901
+ ]
902
+ this.setTweenTo(position,target)
903
+ }
904
+ },
905
+ setCameraSideTo(polygon) {
906
+ if (polygon) {
907
+ let polygonRef = polygon
908
+ const targetVector = polygonRef.meanPoint
909
+ const target = [
910
+ targetVector.x / 1000,
911
+ targetVector.y / 1000,
912
+ targetVector.z / 1000
913
+ ]
914
+ let sideVector={x:-Math.cos((polygonRef.direction+45)*Math.PI/180),y:Math.sin((polygonRef.direction+45)*Math.PI/180),z: 0}
915
+ const positionVector = addVector(
916
+ polygonRef.meanPoint,
917
+ multiplyVector(45000, sideVector)
918
+ )
919
+ const position = [
920
+ positionVector.x / 1000,
921
+ positionVector.y / 1000,
922
+ positionVector.z / 1000 +5
923
+ ]
924
+ this.setTweenTo(position,target)
925
+ }
926
+ },
927
+ setTweenTo(position,target){
928
+ if (this.orbitControl) {
929
+ this.tweenOrbit = new TWEEN.Tween(this.orbitControl.target)
930
+ .to({ x: target[0], y: target[1], z: target[2] }, 2000)
931
+ .easing(TWEEN.Easing.Sinusoidal.Out)
932
+ .onUpdate(() => {
933
+ this.orbitControl.update()
934
+ })
935
+ .start()
936
+ }
937
+ if (this.camera) {
938
+ this.tweenCamera = new TWEEN.Tween(this.camera.position)
939
+ .to({ x: position[0], y: position[1], z: position[2] }, 2000)
940
+ .easing(TWEEN.Easing.Sinusoidal.Out)
941
+ .onUpdate(() => {
942
+ this.orbitControl.update()
943
+ })
944
+ .start()
945
+ }
946
+ },
947
+ getCanvasOffset() {
948
+ if (!this.$refs.canvas3DContainer) return { top: 0, left: 0 }
949
+ var box = this.$refs.canvas3DContainer.getBoundingClientRect()
950
+
951
+ var body = document.body
952
+ var docEl = document.documentElement
953
+
954
+ var scrollTop = window.pageYOffset || docEl.scrollTop || body.scrollTop
955
+ var scrollLeft = window.pageXOffset || docEl.scrollLeft || body.scrollLeft
956
+
957
+ var clientTop = docEl.clientTop || body.clientTop || 0
958
+ var clientLeft = docEl.clientLeft || body.clientLeft || 0
959
+
960
+ var top = box.top + scrollTop - clientTop
961
+ var left = box.left + scrollLeft - clientLeft
962
+ body = null
963
+ docEl = null
964
+ box = null
965
+ return { top: Math.round(top), left: Math.round(left) }
966
+ },
967
+ onWindowResize() {
968
+ this.camera.aspect = window.innerWidth / window.innerHeight
969
+ this.camera.updateProjectionMatrix()
970
+ this.canvasOffset = this.getCanvasOffset()
971
+ this.canvasHeight = this.$refs.canvas3DContainer.clientHeight
972
+ this.canvasWidth = this.$refs.canvas3DContainer.clientWidth
973
+ this.resizeCanvasToDisplaySize()
974
+ //this.renderer.setSize(window.innerWidth / 2, window.innerHeight / 2)
975
+ },
976
+ resizeCanvasToDisplaySize() {
977
+ let canvas = this.renderer.domElement
978
+ // look up the size the canvas is being displayed
979
+ const width = canvas.clientWidth
980
+ const height = canvas.clientHeight
981
+
982
+ // adjust displayBuffer size to match
983
+ if (canvas.width !== width || canvas.height !== height) {
984
+ // you must pass false here or three.js sadly fights the browser
985
+ this.renderer.setSize(width, height, false)
986
+ this.renderer.setViewport(0, 0, width, height)
987
+
988
+ this.camera.aspect = width / height
989
+ this.camera.updateProjectionMatrix()
990
+
991
+ // update any render target sizes here
992
+ }
993
+ canvas = null
994
+ },
995
+ clearMesh(mesh) {
996
+ if (!mesh) return
997
+ this.scene.remove(mesh)
998
+ if (mesh.geometry && mesh.geometry.dispose) {
999
+ mesh.geometry.dispose()
1000
+ mesh.geometry = null
1001
+ }
1002
+ if (mesh.material && mesh.material.dispose) {
1003
+ mesh.material.dispose()
1004
+ mesh.material = null
1005
+ }
1006
+ if (
1007
+ mesh.userData.meshId &&
1008
+ this.meshes[mesh.userData.type][mesh.userData.meshId]
1009
+ ) {
1010
+ delete this.meshes[mesh.userData.type][mesh.userData.meshId]
1011
+ } else {
1012
+ this.meshes[mesh.userData.type] = null
1013
+ }
1014
+ mesh = null
1015
+ },
1016
+ clearEdgesRemovedOnes() {
1017
+ Object.values(this.meshes['edgeMeshes']).forEach((mesh) => {
1018
+ if (!this.edgeIds.includes(mesh.userData.edgeId)) {
1019
+ this.clearMesh(mesh)
1020
+ }
1021
+ })
1022
+ },
1023
+ clearNodesRemovedOnes() {
1024
+ Object.values(this.meshes['nodeMeshes']).forEach((mesh) => {
1025
+ if (!this.nodeIds.includes(mesh.userData.nodeId)) {
1026
+ this.clearMesh(mesh)
1027
+ }
1028
+ })
1029
+ },
1030
+ clearRemovedOnes(type) {
1031
+ Object.values(this.meshes[type]).forEach((mesh) => {
1032
+ if (!this.polygonIds.includes(mesh.userData.polygonId)) {
1033
+ this.clearMesh(mesh)
1034
+ }
1035
+ })
1036
+ },
1037
+ clearByType(type) {
1038
+ Object.values(this.meshes[type]).forEach((mesh) => {
1039
+ mesh.geometry.dispose()
1040
+ mesh.geometry = null
1041
+ if (mesh.material.dispose) {
1042
+ mesh.material.dispose()
1043
+ }
1044
+ mesh.material = null
1045
+ this.scene.remove(mesh)
1046
+ })
1047
+ this.meshes[type] = {}
1048
+ this.renderer.renderLists.dispose()
1049
+ },
1050
+ loadNewTexture(){
1051
+ Object.values(this.pvDataMemo).forEach((component) => {
1052
+ const pvId = component.id
1053
+ if (!this.material.panel[pvId]) {
1054
+ if (!component.texture_img_url) {
1055
+ this.material.panel[pvId] = this.material.panel.default
1056
+ } else {
1057
+ let texture = this.loader.load(component.texture_img_url)
1058
+ this.material.panel[pvId] = new THREE.MeshBasicMaterial({
1059
+ map: texture,
1060
+ side: THREE.DoubleSide
1061
+ })
1062
+ }
1063
+ }
1064
+ })
1065
+ },
1066
+ async loadTextureFromModuleFields(){
1067
+ for(let k=0;k<this.moduleFields.length;k++){
1068
+ let mf=this.moduleFields[k]
1069
+ const pvId = mf.data.component_id_pv_module
1070
+ if (!this.material.panel[pvId]) {
1071
+ console.log('TEXTURE NOT YET in material',this.material)
1072
+ if (!mf.data.texture_img_url) {
1073
+ console.log('no texture for this mf=>go to default')
1074
+ this.material.panel[pvId] = this.material.panel.default
1075
+ } else {
1076
+ console.log('load texture ...')
1077
+ let texture = await this.loader.load(mf.data.texture_img_url)
1078
+ this.material.panel[pvId] = new THREE.MeshBasicMaterial({
1079
+ map: texture,
1080
+ side: THREE.DoubleSide
1081
+ })
1082
+ }
1083
+ }
1084
+ }
1085
+ }
1086
+ },
1087
+ watch: {
1088
+ pvDataMemo: {
1089
+ handler(val) {
1090
+ this.loadNewTexture()
1091
+ }
1092
+ },
1093
+ 'material.panel':{
1094
+ handler(){
1095
+ this.renderPanels()
1096
+ }
1097
+ },
1098
+ geometryEventsToDo(val) {
1099
+ if (val.length > 0) {
1100
+ this.refreshRendering()
1101
+ }
1102
+ }
1103
+ },
1104
+ beforeDestroy() {
1105
+ if (this.tweenOrbit) {
1106
+ this.tweenOrbit = null
1107
+ }
1108
+ if (this.tweenCamera) {
1109
+ this.tweenCamera = null
1110
+ }
1111
+ clearThreeObjects(this.scene)
1112
+ if(this.three_map){
1113
+ this.three_map.clear()
1114
+ clearThreeObjects(this.three_map)
1115
+ }
1116
+ this.renderer.clear()
1117
+ this.renderer.dispose()
1118
+ this.orbitControl.dispose()
1119
+
1120
+ this.renderer = null
1121
+ this.scene = null
1122
+ this.camera = null
1123
+ this.cameraprojection = null
1124
+ this.material.forEach((m) => m.dispose())
1125
+ this.material = null
1126
+ this.orbitControl = null
1127
+ this.raycaster = null
1128
+ this.loader = null
1129
+ this.provider = null
1130
+ window.removeEventListener('resize', this.onWindowResize, false)
1131
+ }
1132
+ }