@eturnity/eturnity_3d 7.2.3 → 7.2.4-qa-7.6.0

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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@eturnity/eturnity_3d",
3
3
  "private": false,
4
- "version": "7.2.3",
4
+ "version": "7.2.4-qa-7.6.0",
5
5
  "main": "dist/main.js",
6
6
  "scripts": {
7
7
  "dev": "vue-cli-service serve --skip-plugins @vue/cli-plugin-eslint",
@@ -10,7 +10,7 @@
10
10
  "prettier": "prettier --write \"**/*.{js,vue}\""
11
11
  },
12
12
  "dependencies": {
13
- "@eturnity/eturnity_maths": "7.2.3",
13
+ "@eturnity/eturnity_maths": "7.2.3-qa-7.6.0",
14
14
  "core-js": "^2.6.12",
15
15
  "cors": "^2.8.5",
16
16
  "earcut": "^2.2.4",
@@ -25,15 +25,6 @@ export default {
25
25
  data() {
26
26
  return {
27
27
  scene: new THREE.Scene(),
28
- camera: new THREE.PerspectiveCamera(50, 300 / 300, 0.1, 100000),
29
- orthographicCamera: new THREE.OrthographicCamera(
30
- 10 / -2,
31
- 10 / 2,
32
- 10 / 2,
33
- 10 / -2,
34
- 1,
35
- 1000
36
- ),
37
28
  layers: null,
38
29
  provider: null,
39
30
  cameraProjection: null,
@@ -61,13 +52,14 @@ export default {
61
52
  },
62
53
  screenshotable: false,
63
54
  areModuleFieldsVisible: false,
55
+ areUserDeactivatedPanelsVisible: false,
56
+ animationFrameId: null,
64
57
  intervalId: null,
65
- requestAnimationFrameId: null,
66
58
  }
67
59
  },
68
60
  beforeDestroy() {
69
61
  clearInterval(this.intervalId)
70
- cancelAnimationFrame(this.requestAnimationFrameId)
62
+ cancelAnimationFrame(this.animationFrameId)
71
63
  },
72
64
  mixins: [renderMixin, threeMixin, materialMixin],
73
65
  async mounted() {
@@ -288,7 +280,7 @@ export default {
288
280
  },
289
281
  animate() {
290
282
  this.render()
291
- this.requestAnimationFrameId = requestAnimationFrame(this.animate)
283
+ this.animationFrameId = requestAnimationFrame(this.animate)
292
284
  },
293
285
  render() {
294
286
  this.renderer.clear()
package/src/config.js CHANGED
@@ -4,7 +4,7 @@ export const snapToPointTolerance = 15
4
4
  export const snapToIntersectionPointTolerance = 15
5
5
  export const snapToLineTolerance = 10
6
6
  export const distanceToCloseNode = 70
7
- export const mmTolerance = 50
7
+ export const mmTolerance = 1
8
8
  export const earthRadius = 6371008
9
9
 
10
10
  export const layerColors = {
@@ -139,8 +139,8 @@ export const maxMargin = 2500
139
139
  export const node3DRadius = 0.05
140
140
  export const beamColor = '#ffffff'
141
141
  export const node3DColor = 'white'
142
- export const beamOpacity = 0.4
143
- export const node3dOpacity = 0.3
142
+ export const beamOpacity = 0.1
143
+ export const node3dOpacity = 0.1
144
144
  export const dimMarginColor = '#ff000020'
145
145
  export const defaultTextureUrl = require('./assets/images/panels/reneSola_Virtus_2_JC320S_24_Bbw.png')
146
146
  const textureImageDomain = 'https://public-data.eturnity.io/'
@@ -33,7 +33,7 @@ export function UpdateRoofModuleFieldRelations(state) {
33
33
  //check if everypoint is in the same roof and if they are not too far from the flat surface.(at least above)
34
34
  let roofPolygonCandidates = roofPolygons.filter((roof) => {
35
35
  const intersection = intersectOutlines(moduleField.outline, roof.outline)
36
- if (intersection.length == 0) return false
36
+ if (intersection.length == 0) return false
37
37
  const intersectionArea = calculateArea(intersection[0])
38
38
  return intersectionArea > 100 && moduleField.area <= roof.area
39
39
  })
@@ -1,12 +1,135 @@
1
1
  import TWEEN from 'tween'
2
+ import * as THREE from 'three'
3
+ import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
2
4
  import {
3
5
  addVector,
6
+ getDistanceBetweenPoints,
4
7
  multiplyVector,
5
8
  substractVector
6
9
  } from '@eturnity/eturnity_maths'
7
10
 
8
11
  export default {
12
+ data() {
13
+ return {
14
+ camera: null,
15
+ perspectiveCamera: new THREE.PerspectiveCamera(50, 300 / 300, 1, 50000),
16
+ orthographicCamera: new THREE.OrthographicCamera(10, 10, 10, 10, 1, 1000)
17
+ }
18
+ },
9
19
  methods: {
20
+ turnPerspectiveCameraToOrthogonal() {
21
+ const cameraPosition = new THREE.Vector3(
22
+ this.camera.position.x,
23
+ this.camera.position.y,
24
+ this.camera.position.z
25
+ )
26
+ var halfHeightDistance =
27
+ (this.camera.position.z * this.camera.fov * Math.PI) / 180
28
+
29
+ // Create an orthographic camera aligned to look down
30
+ this.orthographicCamera.left =
31
+ (-this.camera.aspect * halfHeightDistance) / 2
32
+ this.orthographicCamera.right =
33
+ (this.camera.aspect * halfHeightDistance) / 2
34
+ this.orthographicCamera.top = halfHeightDistance / 2
35
+ this.orthographicCamera.bottom = -halfHeightDistance / 2
36
+ this.orthographicCamera.near = 1
37
+ this.orthographicCamera.far = 1000
38
+ this.orthographicCamera.up = new THREE.Vector3(0, 1, 0)
39
+ this.orthographicCamera.position.set(
40
+ cameraPosition.x,
41
+ cameraPosition.y,
42
+ 100
43
+ )
44
+ this.camera = this.orthographicCamera
45
+ this.camera.position.set(
46
+ cameraPosition.x,
47
+ cameraPosition.y,
48
+ cameraPosition.z
49
+ )
50
+ this.camera.position.set(
51
+ cameraPosition.x,
52
+ cameraPosition.y,
53
+ cameraPosition.z
54
+ )
55
+ this.camera.updateProjectionMatrix()
56
+ this.renderer.camera = this.camera
57
+ this.composer.renderCamera = this.camera
58
+
59
+ this.renderPass.camera = this.camera
60
+ this.overlayRenderPass.camera = this.camera
61
+ this.outlinePassHighlight.renderCamera = this.camera
62
+ this.outlinePassSelected.renderCamera = this.camera
63
+
64
+ this.orbitControl.screenSpacePanning = true
65
+ this.orbitControl.object = this.camera
66
+ this.orbitControl.target.set(cameraPosition.x, cameraPosition.y, 0)
67
+ this.orbitControl.mouseButtons = {
68
+ LEFT: THREE.MOUSE.PAN,
69
+ MIDDLE: THREE.MOUSE.DOLLY,
70
+ RIGHT: THREE.MOUSE.ROTATE
71
+ }
72
+ this.orbitControl.enableRotate = false
73
+ this.orbitControl.addEventListener('change', () => {
74
+ this.orbitControlChange()
75
+ })
76
+ this.orbitControl.update()
77
+ this.camera.position.set(
78
+ cameraPosition.x,
79
+ cameraPosition.y,
80
+ cameraPosition.z
81
+ )
82
+ this.camera.lookAt(
83
+ new THREE.Vector3(cameraPosition.x, cameraPosition.y, 0)
84
+ ) // Set look at coordinate like this
85
+ this.camera.updateProjectionMatrix()
86
+ this.nodesVisible = true
87
+ this.renderNodes()
88
+ this.composer.render()
89
+ },
90
+ turnOrthogonalCameraToPerspective() {
91
+ this.camera = this.perspectiveCamera
92
+ let altitude =
93
+ (this.orthographicCamera.right - this.orthographicCamera.left) /
94
+ ((this.perspectiveCamera.fov * Math.PI) / 180) /
95
+ this.perspectiveCamera.aspect
96
+
97
+ this.camera.position.set(
98
+ this.orthographicCamera.position.x,
99
+ this.orthographicCamera.position.y,
100
+ altitude
101
+ )
102
+
103
+ this.camera.up = new THREE.Vector3(0, 0, 1)
104
+ this.camera.updateProjectionMatrix()
105
+
106
+ this.renderer.camera = this.camera
107
+ this.composer.renderer.camera = this.camera
108
+ this.composer.renderCamera = this.camera
109
+ this.renderPass.camera = this.camera
110
+ this.overlayRenderPass.camera = this.camera
111
+ this.outlinePassHighlight.camera = this.camera
112
+ this.outlinePassHighlight.renderCamera = this.camera
113
+ this.outlinePassSelected.camera = this.camera
114
+ this.outlinePassSelected.renderCamera = this.camera
115
+ this.orbitControl.camera = this.camera
116
+ this.orbitControl.object = this.camera
117
+ this.orbitControl.target.set(
118
+ this.camera.position.x,
119
+ this.camera.position.y,
120
+ 0
121
+ )
122
+ this.orbitControl.screenSpacePanning = false
123
+ this.orbitControl.enableRotate = true
124
+ this.orbitControl.mouseButtons = {
125
+ LEFT: THREE.MOUSE.ROTATE,
126
+ MIDDLE: THREE.MOUSE.DOLLY,
127
+ RIGHT: THREE.MOUSE.PAN
128
+ }
129
+ this.orbitControl.update()
130
+
131
+ this.composer.render()
132
+ },
10
133
  zoomIn3D() {
11
134
  let target = this.orbitControl.target
12
135
  let curentPosition = this.camera.position
@@ -39,6 +162,7 @@ export default {
39
162
  },
40
163
  setCameraGlobalPosition() {
41
164
  if (this.roofs.length == 0) return
165
+ let newFov = 50
42
166
  let bounds = this.roofsBounds
43
167
  let targetVector = {
44
168
  x: (bounds.xMax + bounds.xMin) / 2000,
@@ -50,7 +174,7 @@ export default {
50
174
  (bounds.yMax - bounds.yMin) / 2000
51
175
  )
52
176
  let distance =
53
- 5 + objectRadius_m / Math.sin(((this.camera.fov / 2) * Math.PI) / 180)
177
+ 5 + objectRadius_m / Math.sin(((newFov / 2) * Math.PI) / 180)
54
178
  let cameraMoveVector = { x: 0, y: 0, z: distance }
55
179
  const positionVector = addVector(targetVector, cameraMoveVector)
56
180
  const position = [
@@ -59,8 +183,39 @@ export default {
59
183
  positionVector.z
60
184
  ]
61
185
  let target = [targetVector.x, targetVector.y, targetVector.z]
186
+ this.setTweenTo(position, target, newFov)
187
+ },
188
+ setCameraGlobalVerticalPosition() {
189
+ let position, target
190
+ let newFov = 10
191
+ if (this.roofs.length != 0) {
192
+ let bounds = this.roofsBounds
193
+ let targetVector = {
194
+ x: (bounds.xMax + bounds.xMin) / 2000,
195
+ y: (bounds.yMax + bounds.yMin) / 2000,
196
+ z: 0
197
+ }
198
+ let objectRadius_m = Math.max(
199
+ (bounds.xMax - bounds.xMin) / 2000,
200
+ (bounds.yMax - bounds.yMin) / 2000
201
+ )
62
202
 
63
- this.setTweenTo(position, target)
203
+ let distance =
204
+ 2 * (objectRadius_m / Math.sin(((newFov / 2) * Math.PI) / 180))
205
+ let cameraMoveVector = { x: 0, y: 0, z: distance }
206
+ const positionVector = addVector(targetVector, cameraMoveVector)
207
+ position = [positionVector.x, positionVector.y, positionVector.z]
208
+ target = [targetVector.x, targetVector.y, targetVector.z]
209
+ } else {
210
+ position = [0, 0, 300]
211
+ target = [0, 0, 0]
212
+ }
213
+ this.setTweenTo(
214
+ position,
215
+ target,
216
+ newFov,
217
+ this.turnPerspectiveCameraToOrthogonal
218
+ )
64
219
  },
65
220
  setCameraOrthogonalTo(polygon) {
66
221
  if (polygon) {
@@ -109,23 +264,125 @@ export default {
109
264
  this.setTweenTo(position, target)
110
265
  }
111
266
  },
112
- setTweenTo(position, target, speed = 2000) {
267
+ setTweenTo(position, target, fov = 50, onCompleteCallback = () => {}) {
113
268
  TWEEN.removeAll()
114
- if (this.orbitControl) {
115
- this.tweenOrbit = new TWEEN.Tween(this.orbitControl.target)
116
- .to({ x: target[0], y: target[1], z: target[2] }, speed)
117
- .easing(TWEEN.Easing.Sinusoidal.Out)
118
- .start()
119
- }
120
269
  if (this.camera) {
121
- this.tweenCamera = new TWEEN.Tween(this.camera.position)
122
- .to({ x: position[0], y: position[1], z: position[2] }, speed)
123
- .easing(TWEEN.Easing.Sinusoidal.Out)
124
- .onUpdate(() => {
125
- if (this.orbitControl && this.orbitControl.update)
126
- this.orbitControl.update()
127
- })
128
- .start()
270
+ const currentTweenVar = {
271
+ t: 0
272
+ }
273
+ const initialTarget = {
274
+ x: this.orbitControl.target.x,
275
+ y: this.orbitControl.target.y,
276
+ z: this.orbitControl.target.z
277
+ }
278
+ const initialFov = this.camera.fov
279
+ const initialCameraPosition = {
280
+ x: this.camera.position.x,
281
+ y: this.camera.position.y,
282
+ z: this.camera.position.z
283
+ }
284
+ const finalCameraPosition = {
285
+ x: position[0],
286
+ y: position[1],
287
+ z: position[2]
288
+ }
289
+ if (position[0] == target[0] && position[1] == target[1]) {
290
+ const distance2D = getDistanceBetweenPoints(
291
+ finalCameraPosition,
292
+ initialCameraPosition
293
+ )
294
+ //angle from south
295
+ const angle2D = Math.atan2(
296
+ initialCameraPosition.y - finalCameraPosition.y,
297
+ initialCameraPosition.x - finalCameraPosition.x
298
+ )
299
+ this.tweenCamera = new TWEEN.Tween(currentTweenVar)
300
+ .to({ t: 1 }, 2000)
301
+ .easing(TWEEN.Easing.Sinusoidal.Out)
302
+ .onUpdate(() => {
303
+ const t = currentTweenVar.t
304
+ this.camera.fov = initialFov + Math.sqrt(t) * (fov - initialFov)
305
+
306
+ const newDistance = distance2D * (1 - t)
307
+ const newAngle = (angle2D + Math.PI / 2) * (1 - t) - Math.PI / 2
308
+ const newAltitude =
309
+ finalCameraPosition.z +
310
+ (1 - t) * (initialCameraPosition.z - finalCameraPosition.z)
311
+ const nextPosition = {
312
+ x: finalCameraPosition.x + newDistance * Math.cos(newAngle),
313
+ y: finalCameraPosition.y + newDistance * Math.sin(newAngle),
314
+ z: newAltitude
315
+ }
316
+ this.camera.position.set(
317
+ nextPosition.x,
318
+ nextPosition.y,
319
+ nextPosition.z
320
+ )
321
+ this.camera.up = new THREE.Vector3(
322
+ 0,
323
+ Math.sin((t * Math.PI) / 2),
324
+ Math.cos((t * Math.PI) / 2)
325
+ )
326
+
327
+ this.camera.updateProjectionMatrix()
328
+ const nextTarget = {
329
+ x: initialTarget.x + t * (target[0] - initialTarget.x),
330
+ y: initialTarget.y + t * (target[1] - initialTarget.y),
331
+ z: initialTarget.z + t * (target[2] - initialTarget.z)
332
+ }
333
+
334
+ this.orbitControl.target.set(
335
+ nextTarget.x,
336
+ nextTarget.y,
337
+ nextTarget.z
338
+ )
339
+ if (this.orbitControl && this.orbitControl.update)
340
+ this.orbitControl.update()
341
+ })
342
+ .onComplete(() => {
343
+ onCompleteCallback()
344
+ })
345
+ } else {
346
+ this.camera.up = { x: 0, y: 0, z: 1 }
347
+ this.tweenCamera = new TWEEN.Tween(currentTweenVar)
348
+ .to({ t: 1 }, 2000)
349
+ .easing(TWEEN.Easing.Sinusoidal.Out)
350
+ .onUpdate(() => {
351
+ const t = currentTweenVar.t
352
+ this.camera.fov = initialFov + t * t * (fov - initialFov)
353
+ this.camera.updateProjectionMatrix()
354
+
355
+ const nextPosition = {
356
+ x:
357
+ finalCameraPosition.x +
358
+ (1 - t) * (initialCameraPosition.x - finalCameraPosition.x),
359
+ y:
360
+ finalCameraPosition.y +
361
+ (1 - t) * (initialCameraPosition.y - finalCameraPosition.y),
362
+ z:
363
+ finalCameraPosition.z +
364
+ (1 - t) * (initialCameraPosition.z - finalCameraPosition.z)
365
+ }
366
+ this.camera.position.set(
367
+ nextPosition.x,
368
+ nextPosition.y,
369
+ nextPosition.z
370
+ )
371
+ const nextTarget = {
372
+ x: initialTarget.x + t * (target[0] - initialTarget.x),
373
+ y: initialTarget.y + t * (target[1] - initialTarget.y),
374
+ z: initialTarget.z + t * (target[2] - initialTarget.z)
375
+ }
376
+ this.orbitControl.target.set(
377
+ nextTarget.x,
378
+ nextTarget.y,
379
+ nextTarget.z
380
+ )
381
+ if (this.orbitControl && this.orbitControl.update)
382
+ this.orbitControl.update()
383
+ })
384
+ }
385
+ this.tweenCamera.start()
129
386
  }
130
387
  }
131
388
  },
@@ -32,18 +32,32 @@ export default {
32
32
  side: THREE.DoubleSide
33
33
  })
34
34
 
35
- this.material.edge = new THREE.MeshPhongMaterial({
35
+ this.material.edge = new THREE.MeshBasicMaterial({
36
36
  color: beamColor,
37
37
  transparent: true,
38
38
  opacity: beamOpacity
39
39
  })
40
+ //Creating dot alpha texture for nodes
41
+ const canvas = document.createElement('canvas'),
42
+ ctx = canvas.getContext('2d');
43
+ canvas.width = 64
44
+ canvas.height = 64
45
+ ctx.fillStyle = 'black'
46
+ ctx.fillRect(0, 0, 64, 64)
47
+ ctx.strokeStyle = 'white'
48
+ ctx.beginPath()
49
+ ctx.lineWidth = 10
50
+ ctx.arc(32, 32, 16, 0, Math.PI * 2)
51
+ ctx.stroke()
52
+ const texture = new THREE.CanvasTexture(canvas)
40
53
 
41
54
  this.material.node = new THREE.PointsMaterial({
42
- size: 0.05,
43
- sizeAttenuation: true,
44
- color: node3DColor,
45
- opacity: node3dOpacity,
46
- transparent: true
55
+ alphaMap: texture,
56
+ size: 25,
57
+ sizeAttenuation: false,
58
+ transparent: true,
59
+ color: "0xffffff",
60
+ opacity: 1,
47
61
  })
48
62
 
49
63
  this.material.panel = {}
@@ -58,6 +72,13 @@ export default {
58
72
  side: THREE.DoubleSide
59
73
  })
60
74
  }
75
+ this.material.panel['userDeactivatedPanel'] = new THREE.MeshBasicMaterial({
76
+ color: 0xffffff,
77
+ transparent: true,
78
+ alphaTest: 0,
79
+ opacity: 0.2,
80
+ side: THREE.DoubleSide
81
+ })
61
82
  this.material.roof = [this.material.wall]
62
83
 
63
84
  this.material.flatRoof = new THREE.MeshPhongMaterial({
@@ -94,7 +115,8 @@ export default {
94
115
  color: 0xffffff,
95
116
  transparent: true,
96
117
  alphaTest: 1,
97
- opacity: 0
118
+ opacity: 0.2,
119
+ side: THREE.DoubleSide
98
120
  })
99
121
  this.material.moduleField = new THREE.MeshBasicMaterial({
100
122
  color: 0xe0e0ff,
Binary file
@@ -43,7 +43,6 @@ export default {
43
43
  )
44
44
  },
45
45
  clearMesh(mesh) {
46
-
47
46
  if (!mesh || !this.scene) {
48
47
  return
49
48
  }
@@ -77,13 +76,6 @@ export default {
77
76
  }
78
77
  })
79
78
  },
80
- clearNodesRemovedOnes() {
81
- Object.values(this.meshes['nodeMeshes']).forEach((mesh) => {
82
- if (!this.nodeIds.includes(mesh.userData.nodeId)) {
83
- this.clearMesh(mesh)
84
- }
85
- })
86
- },
87
79
  clearRemovedOnes(type) {
88
80
  Object.values(this.meshes[type]).forEach((mesh) => {
89
81
  if (!this.polygonIds.includes(mesh.userData.polygonId)) {
@@ -36,30 +36,62 @@ export default {
36
36
  },
37
37
  renderEdges() {
38
38
  this.clearEdgesRemovedOnes('edgeMeshes')
39
+ if(this.renderLineEdges){
40
+ this.renderLineEdges()
41
+ }
39
42
  let cylinder
40
- //this.clearByType('edgeMeshes')
41
- // const material = new THREE.LineBasicMaterial( { color: beamColor,transparent:true,opacity:beamOpacity ,sizeAttenuation: true} );
42
- // material.linewidth=5
43
43
  const material = this.material.edge
44
- this.edges
45
- .filter((edge) => edge.layer == 'roof')
46
- .forEach((edge) => {
47
- cylinder = this.meshes.edgeMeshes[edge.id]
48
- if (cylinder) {
49
- //update
50
- this.setCylinderPosition(cylinder, edge)
51
- //change cylinder length
52
- } else {
53
- const geometry = new THREE.CylinderGeometry(0.1, 0.1, 1, 6)
54
- cylinder = new THREE.Mesh(geometry, material)
55
- cylinder = this.setCylinderPosition(cylinder, edge)
44
+ this.edges.forEach((edge) => {
45
+ cylinder = this.meshes.edgeMeshes[edge.id]
46
+ if (cylinder) {
47
+ cylinder.visible = false
48
+ }
49
+ if (['obstacle', 'construction'].includes(edge.layer)) return
50
+ if (
51
+ ['selectRoof'].includes(this.selectedTool) &&
52
+ edge.layer != 'roof'
53
+ ) {
54
+ return
55
+ }
56
+ if (
57
+ ['selectModuleField'].includes(this.selectedTool) &&
58
+ (edge.layer != 'moduleField' ||
59
+ !this.selectedModuleField ||
60
+ !edge.belongsTo
61
+ .map((i) => i.polygonId)
62
+ .includes(this.selectedModuleField.id))
63
+ ) {
64
+ return
65
+ }
66
+ cylinder = this.meshes.edgeMeshes[edge.id]
67
+ if (cylinder) {
68
+ //update
69
+ cylinder.visible = true
70
+ this.setCylinderPosition(cylinder, edge)
71
+ //change cylinder length
72
+ } else {
73
+ const edgeRadius = this.edgeRadius || 0.1
74
+ const geometry = new THREE.CylinderGeometry(
75
+ edgeRadius,
76
+ edgeRadius,
77
+ 1,
78
+ 6
79
+ )
80
+ if (this.edgeOpacity != undefined) {
81
+ material.opacity = this.edgeOpacity
82
+ }
83
+ cylinder = new THREE.Mesh(geometry, material.clone())
84
+ cylinder = this.setCylinderPosition(cylinder, edge)
56
85
 
57
- cylinder.userData.edgeId = edge.id
86
+ cylinder.userData.meshId = edge.id
87
+ cylinder.userData.edgeId = edge.id
88
+ cylinder.userData.type = 'edgeMeshes'
89
+ cylinder.userData.layer = edge.layer
58
90
 
59
- this.meshes.edgeMeshes[edge.id] = cylinder
60
- this.scene.add(cylinder)
61
- }
62
- })
91
+ this.meshes.edgeMeshes[edge.id] = cylinder
92
+ this.scene.add(cylinder)
93
+ }
94
+ })
63
95
  }
64
96
  }
65
97
  }
@@ -6,13 +6,58 @@ export default {
6
6
  renderRoofsMargin() {
7
7
  this.clearByType('roofMarginMeshes')
8
8
 
9
- if (this.selectedTool == 'selectMargin') {
10
- this.roofs.forEach((roofPolygon) => {
11
- const geometries = getBufferRoofMarginGeometry(roofPolygon)
9
+ if (
10
+ ![
11
+ 'selectMargin',
12
+ 'selectModuleField',
13
+ 'drawRoof',
14
+ 'drawObstacle'
15
+ ].includes(this.selectedTool)
16
+ ) {
17
+ return
18
+ }
19
+ let showableRoofs = []
20
+ if (['drawRoof', 'drawObstacle'].includes(this.selectedTool)) {
21
+ if (this.selectedRoof) {
22
+ showableRoofs = [this.selectedRoof]
23
+ }
24
+ if (this.selectedObstacle) {
25
+ showableRoofs = this.selectedObstacle.roofs
26
+ }
27
+ } else {
28
+ showableRoofs = this.roofs
29
+ }
30
+ showableRoofs.forEach((roofPolygon) => {
31
+ const geometries = getBufferRoofMarginGeometry(roofPolygon)
12
32
 
33
+ geometries.forEach((geometry, index) => {
34
+ if (geometry) {
35
+ const marginColor = roofPolygon.margins.isSameMargin
36
+ ? colorArrayBase[0]
37
+ : colorArrayBase[index % colorArrayBase.length]
38
+ let material = new THREE.MeshPhongMaterial({
39
+ color: marginColor,
40
+ specular: 0x009900,
41
+ shininess: 0,
42
+ flatShading: true,
43
+ side: THREE.DoubleSide,
44
+ transparent: true,
45
+ opacity: 0.8
46
+ })
47
+ const mesh = new THREE.Mesh(geometry, material)
48
+ geometry.dispose()
49
+ this.scene.add(mesh)
50
+ this.meshes.roofMarginMeshes[roofPolygon.id + '_' + index] = mesh
51
+ }
52
+ })
53
+ roofPolygon.holes.forEach((obstaclePolygon) => {
54
+ const geometries = getBufferRoofMarginGeometry(
55
+ obstaclePolygon,
56
+ roofPolygon
57
+ )
13
58
  geometries.forEach((geometry, index) => {
14
59
  if (geometry) {
15
- const marginColor = roofPolygon.margins.isSameMargin
60
+ const marginColor = obstaclePolygon.margins.isSameMargin
16
61
  ? colorArrayBase[0]
17
62
  : colorArrayBase[index % colorArrayBase.length]
18
63
  let material = new THREE.MeshPhongMaterial({
@@ -26,43 +71,17 @@ export default {
26
71
  })
27
72
  const mesh = new THREE.Mesh(geometry, material)
28
73
  geometry.dispose()
74
+ geometry = null
75
+ material.dispose()
76
+ material = null
29
77
  this.scene.add(mesh)
30
- this.meshes.roofMarginMeshes[roofPolygon.id + '_' + index] = mesh
78
+ this.meshes.roofMarginMeshes[
79
+ obstaclePolygon.id + '_' + roofPolygon.id + '_' + index
80
+ ] = mesh
31
81
  }
32
82
  })
33
- roofPolygon.holes.forEach((obstaclePolygon) => {
34
- const geometries = getBufferRoofMarginGeometry(
35
- obstaclePolygon,
36
- roofPolygon
37
- )
38
- geometries.forEach((geometry, index) => {
39
- if (geometry) {
40
- const marginColor = obstaclePolygon.margins.isSameMargin
41
- ? colorArrayBase[0]
42
- : colorArrayBase[index % colorArrayBase.length]
43
- let material = new THREE.MeshPhongMaterial({
44
- color: marginColor,
45
- specular: 0x009900,
46
- shininess: 0,
47
- flatShading: true,
48
- side: THREE.DoubleSide,
49
- transparent: true,
50
- opacity: 0.8
51
- })
52
- const mesh = new THREE.Mesh(geometry, material)
53
- geometry.dispose()
54
- geometry = null
55
- material.dispose()
56
- material = null
57
- this.scene.add(mesh)
58
- this.meshes.roofMarginMeshes[
59
- obstaclePolygon.id + '_' + roofPolygon.id + '_' + index
60
- ] = mesh
61
- }
62
- })
63
- })
64
83
  })
65
- }
84
+ })
66
85
  }
67
86
  }
68
87
  }
@@ -10,9 +10,9 @@ export default {
10
10
  geometries.forEach((geometry) => {
11
11
  const positions = geometry.attributes.position.array
12
12
  const normals = geometry.attributes.normal.array
13
+ mergedVertices.push(...positions.slice(0, 3 * geometry.drawRange.count))
14
+ mergedNormals.push(...normals.slice(0, 3 * geometry.drawRange.count))
13
15
 
14
- mergedVertices.push(...positions.slice(0, geometry.drawRange.count * 3))
15
- mergedNormals.push(...normals.slice(0, geometry.drawRange.count * 3))
16
16
  if (geometry.attributes.uv) {
17
17
  const uvs = geometry.attributes.uv.array
18
18
  mergedUvs.push(...uvs)
@@ -41,12 +41,12 @@ export default {
41
41
  for (let k in mergedNormals) {
42
42
  normals[k] = mergedNormals[k]
43
43
  }
44
+ mergedGeometry.setDrawRange(0, mergedVertices.length / 3)
44
45
  } else {
45
46
  mergedGeometry.dispose()
46
47
  mergedGeometry = null
47
48
  mergedGeometry = this.createMergedGeometry(geometries)
48
49
  }
49
- mergedGeometry.setDrawRange(0, mergedVertices.length / 3)
50
50
  mergedGeometry.attributes.position.needsUpdate = true
51
51
  mergedGeometry.attributes.normal.needsUpdate = true
52
52
  mergedGeometry.needsUpdate = true
@@ -100,6 +100,7 @@ export default {
100
100
  )
101
101
  mesh.geometry = mergedGeometry
102
102
  }
103
+ mesh.frustumCulled = false
103
104
  return mesh
104
105
  }
105
106
  }
@@ -7,19 +7,23 @@ export default {
7
7
  if (!this.areModuleFieldsVisible) {
8
8
  return
9
9
  }
10
- this.moduleFields.forEach((moduleFieldPolygon) => {
10
+ const moduleFieldPolygons = this.polygons.filter((p) =>
11
+ ['moduleField', 'tmpModuleField'].includes(p.layer)
12
+ )
13
+ moduleFieldPolygons.forEach((moduleFieldPolygon) => {
11
14
  const geometry = getBufferModuleFieldGeometry(moduleFieldPolygon)
12
15
  if (geometry) {
13
16
  let material
14
- if(moduleFieldPolygon.data.number_of_panels_override){
15
- material=this.material.moduleFieldWithPanelOveride
16
- }else{
17
- material=this.material.moduleField
17
+ if (moduleFieldPolygon.data.number_of_panels_override) {
18
+ material = this.material.moduleFieldWithPanelOveride
19
+ } else {
20
+ material = this.material.moduleField
18
21
  }
19
22
  const mesh = new THREE.Mesh(geometry, this.material.moduleField)
20
23
  mesh.matrixAutoUpdate = false
21
24
  mesh.userData.version = moduleFieldPolygon.version
22
25
  mesh.userData.type = 'moduleFieldsMeshes'
26
+ mesh.userData.layer = moduleFieldPolygon.layer
23
27
  mesh.userData.meshId = moduleFieldPolygon.id
24
28
  mesh.userData.polygonId = moduleFieldPolygon.id
25
29
  this.scene.add(mesh)
@@ -1,10 +1,17 @@
1
1
  import * as THREE from 'three'
2
-
3
2
  export default {
4
3
  methods: {
5
4
  renderNodes() {
5
+ if (!this.nodesVisible) {
6
+ if (this.meshes.nodeMeshes) {
7
+ this.meshes.nodeMeshes.visible = false
8
+ }
9
+ return
10
+ }
11
+
6
12
  let geometry
7
13
  if (this.meshes.nodeMeshes) {
14
+ this.meshes.nodeMeshes.visible = true
8
15
  geometry = this.meshes.nodeMeshes.geometry
9
16
  geometry.attributes.position.needsUpdate = true
10
17
  } else {
@@ -40,8 +47,11 @@ export default {
40
47
  nodeMeshes.userData.meshId = null
41
48
  nodeMeshes.userData.polygonId = null
42
49
  nodeMeshes.matrixAutoUpdate = false
50
+ nodeMeshes.renderOrder = 10
43
51
  this.meshes.nodeMeshes = nodeMeshes
44
- this.scene.add(nodeMeshes)
52
+ if (this.overlayScene) {
53
+ this.overlayScene.add(nodeMeshes)
54
+ }
45
55
  }
46
56
  }
47
57
  }
@@ -35,9 +35,10 @@ export default {
35
35
  },
36
36
  renderPanels() {
37
37
  this.clearRemovedOnes('panelsMeshes')
38
+ //clear mesh of userDeactivated panels && panels with overriden # of panels
38
39
  Object.values(this.meshes.panelsMeshes).forEach((mesh) => {
39
- //clear UserDeactivatedModules
40
40
  if (
41
+ !this.areUserDeactivatedPanelsVisible &&
41
42
  this.polygons.find(
42
43
  (poly) =>
43
44
  poly.id == mesh.userData.polygonId &&
@@ -54,53 +55,80 @@ export default {
54
55
  this.clearMesh(mesh)
55
56
  }
56
57
  })
58
+
57
59
  let panelSideGeometries = []
58
60
  let panelTopGeometries = {}
59
- this.panels.forEach((panelPolygon) => {
61
+ let panels = this.panels
62
+ if (this.areUserDeactivatedPanelsVisible) {
63
+ panels = this.polygons.filter((polygon) => {
64
+ return ['panel', 'user_deactivated_panel'].includes(polygon.layer)
65
+ })
66
+ }
67
+ panels.forEach((panelPolygon) => {
68
+ //for each visible panels
69
+ //1. define materialId and material
70
+ //2. create or update individual meshes
71
+ // 2a. Fill in panelTopGeometries & panelSideGeometries
60
72
  if (!panelPolygon.visible) {
61
73
  return
62
74
  }
63
- //definition of the material
64
75
  if (panelPolygon.moduleField.data.number_of_panels_override) {
65
76
  return
66
77
  }
67
- const moduleTextureId = panelPolygon.moduleField.pvData.hasOwnProperty(
68
- 'module_texture_version_id'
69
- ) && panelPolygon.moduleField.pvData.module_texture_version_id
70
- ? panelPolygon.moduleField.pvData.module_texture_version_id
71
- : 0
72
- let materialId = 'default_' + moduleTextureId
73
- let material = this.material.panel[materialId]
74
- material.transparent = true
75
- material.opacity = this.panelOpacity
76
- if (panelPolygon.moduleField.data) {
77
- if (
78
- this.material.panel[
79
- panelPolygon.moduleField.data.component_id_pv_module
80
- ]
81
- ) {
82
- materialId = panelPolygon.moduleField.data.component_id_pv_module
83
- material = this.material.panel[materialId]
84
- }
85
- } else if (panelPolygon.moduleField.pvData) {
86
- if (this.material.panel[panelPolygon.moduleField.pvData.id]) {
87
- materialId = panelPolygon.moduleField.pvData.id
88
- material = this.material.panel[materialId]
78
+ //1.define materialId and material
79
+ let material
80
+ let materialId
81
+ if (panelPolygon.layer == 'user_deactivated_panel') {
82
+ materialId = 'userDeactivatedPanel'
83
+ material = this.material.panel[materialId]
84
+ material.opacity = this.panelOpacity
85
+ } else {
86
+ const moduleTextureId =
87
+ panelPolygon.moduleField.pvData.hasOwnProperty(
88
+ 'module_texture_version_id'
89
+ ) && panelPolygon.moduleField.pvData.module_texture_version_id
90
+ ? panelPolygon.moduleField.pvData.module_texture_version_id
91
+ : 0
92
+
93
+ materialId = 'default_' + moduleTextureId
94
+ material = this.material.panel[materialId]
95
+ material.transparent = true
96
+ material.opacity = this.panelOpacity
97
+ if (panelPolygon.moduleField.data) {
98
+ if (
99
+ this.material.panel[
100
+ panelPolygon.moduleField.data.component_id_pv_module
101
+ ]
102
+ ) {
103
+ materialId = panelPolygon.moduleField.data.component_id_pv_module
104
+ material = this.material.panel[materialId]
105
+ }
106
+ } else if (panelPolygon.moduleField.pvData) {
107
+ if (this.material.panel[panelPolygon.moduleField.pvData.id]) {
108
+ materialId = panelPolygon.moduleField.pvData.id
109
+ material = this.material.panel[materialId]
110
+ }
89
111
  }
90
112
  }
113
+ //2. create or update individual meshes
91
114
  if (
92
115
  !this.meshes.panelsMeshes[panelPolygon.id + '_top'] ||
93
116
  !this.meshes.panelsMeshes[panelPolygon.id + '_side']
94
117
  ) {
118
+ //mesh creation
95
119
  const geometry = getBufferPanelGeometry(panelPolygon)
96
120
  const geometrySide = getBufferPanelSideGeometry(panelPolygon)
121
+ //2a.Fill in panelTopGeometries & panelSideGeometries
122
+ //gather all geometry with similar material together to merge them for faster rendering
97
123
  if (!panelTopGeometries[materialId]) {
98
124
  panelTopGeometries[materialId] = []
99
125
  }
100
126
  panelTopGeometries[materialId].push(geometry)
101
- panelSideGeometries.push(geometrySide)
127
+ if (panelPolygon.layer != 'user_deactivated_panel') {
128
+ panelSideGeometries.push(geometrySide)
129
+ }
102
130
  if (geometry && geometrySide) {
103
- const mesh = new THREE.Mesh(geometry, material)
131
+ const mesh = new THREE.Mesh(geometry, this.material.hidden)
104
132
  const meshSide = new THREE.Mesh(
105
133
  geometrySide,
106
134
  this.material.panelSide
@@ -109,18 +137,18 @@ export default {
109
137
  mesh.userData.type = 'panelsMeshes'
110
138
  mesh.userData.meshId = panelPolygon.id + '_top'
111
139
  mesh.userData.polygonId = panelPolygon.id
140
+ this.scene.add(mesh)
112
141
  meshSide.userData.version = panelPolygon.version
113
142
  meshSide.userData.type = 'panelsMeshes'
114
143
  meshSide.userData.meshId = panelPolygon.id + '_side'
115
144
  meshSide.userData.polygonId = panelPolygon.id
116
- geometry.dispose()
117
- geometrySide.dispose()
118
145
  mesh.matrixAutoUpdate = false
119
146
  meshSide.matrixAutoUpdate = false
120
147
  this.meshes.panelsMeshes[panelPolygon.id + '_top'] = mesh
121
148
  this.meshes.panelsMeshes[panelPolygon.id + '_side'] = meshSide
122
149
  }
123
150
  } else {
151
+ //update existing geometry
124
152
  const topMesh = this.meshes.panelsMeshes[panelPolygon.id + '_top']
125
153
  const sideMesh = this.meshes.panelsMeshes[panelPolygon.id + '_side']
126
154
  if (panelPolygon.version > topMesh.userData.version) {
@@ -136,7 +164,9 @@ export default {
136
164
  topMesh.geometry = topGeometry
137
165
  sideMesh.geometry = sideGeometry
138
166
  }
139
- panelSideGeometries.push(sideMesh.geometry)
167
+ if (panelPolygon.layer != 'user_deactivated_panel') {
168
+ panelSideGeometries.push(sideMesh.geometry)
169
+ }
140
170
  if (!panelTopGeometries[materialId]) {
141
171
  panelTopGeometries[materialId] = []
142
172
  }
@@ -145,7 +175,7 @@ export default {
145
175
  }
146
176
  })
147
177
 
148
- //removing unused mesh
178
+ //removing unused mergedmesh
149
179
  const materialIds = Object.keys(panelTopGeometries)
150
180
  const materialIdsToRemove = Object.keys(this.mergedPanelTopMeshes).filter(
151
181
  (key) => !materialIds.includes(key)
@@ -130,17 +130,35 @@ export default {
130
130
  this.applyTextureOnMesh(this.material.roof, this.mergedRoofMesh)
131
131
  },
132
132
  renderFlatRoofs() {
133
- this.clearByType('flatRoofMeshes')
133
+ this.clearRemovedOnes('flatRoofMeshes')
134
+ let geometry
134
135
  this.roofs.forEach((roofPolygon) => {
135
- if (roofPolygon.maximumGap < maximumGapLimit) return
136
- let geometry = getBufferRoofGeometry(roofPolygon.flatOutline)
137
- if (geometry) {
138
- const material = this.material.curvedRoof
139
- const mesh = new THREE.Mesh(geometry, material)
140
- mesh.itemData = roofPolygon
141
- mesh.frustumCulled = false
142
- this.scene.add(mesh)
143
- this.meshes.flatRoofMeshes[roofPolygon.id] = mesh
136
+ let mesh = this.meshes.flatRoofMeshes[roofPolygon.id]
137
+ if (mesh) {
138
+ if (mesh.userData.version < roofPolygon.version) {
139
+ geometry = updateBufferRoofGeometry(
140
+ roofPolygon.flatOutline,
141
+ [],
142
+ mesh.geometry
143
+ )
144
+ mesh.geometry = geometry
145
+ mesh.userData.version = roofPolygon.version
146
+ }
147
+ mesh.visible = roofPolygon.maximumGap > maximumGapLimit
148
+ } else {
149
+ geometry = getBufferRoofGeometry(roofPolygon.flatOutline)
150
+ if (geometry) {
151
+ const material = this.material.curvedRoof
152
+ mesh = new THREE.Mesh(geometry, material)
153
+ mesh.userData.polygonId = roofPolygon.id
154
+ mesh.userData.version = roofPolygon.version
155
+ mesh.userData.type = 'flatRoofMeshes'
156
+ mesh.userData.meshId = roofPolygon.id
157
+
158
+ mesh.visible = roofPolygon.maximumGap > maximumGapLimit
159
+ this.scene.add(mesh)
160
+ this.meshes.flatRoofMeshes[roofPolygon.id] = mesh
161
+ }
144
162
  }
145
163
  })
146
164
  }
@@ -56,6 +56,13 @@ export default {
56
56
  nodeIds() {
57
57
  return this.nodes.map((p) => p.id)
58
58
  },
59
+ setGlobalPositionRenderNeeded() {
60
+ return !!this.geometryEvents.find(
61
+ (e) =>
62
+ e.id > this.lastGeometryEventIdDone &&
63
+ e.name == 'setCameraGlobalPosition'
64
+ )
65
+ },
59
66
  fullRenderNeeded() {
60
67
  return !!this.geometryEvents.find(
61
68
  (e) => e.id > this.lastGeometryEventIdDone && e.name == 'full'
@@ -72,6 +79,11 @@ export default {
72
79
  let methodList = []
73
80
  if (this.fullRenderNeeded) {
74
81
  methodList = this.renderingMethodsByEvent({ name: 'full' })
82
+ if (this.setGlobalPositionRenderNeeded) {
83
+ methodList.push(
84
+ ...this.renderingMethodsByEvent({ name: 'setCameraGlobalPosition' })
85
+ )
86
+ }
75
87
  } else {
76
88
  for (let geometryEvent of this.geometryEventsToDo) {
77
89
  for (let renderingMethod of this.renderingMethodsByEvent(
@@ -94,6 +106,7 @@ export default {
94
106
  const name = geometryEvent.name
95
107
  const params = geometryEvent.params
96
108
  let methodList = []
109
+ console.log(name)
97
110
  switch (name) {
98
111
  case 'zoomIn3D':
99
112
  methodList.push({
@@ -118,6 +131,11 @@ export default {
118
131
  })
119
132
  break
120
133
  case 'toolChange': //params.toolName
134
+ methodList.push({
135
+ name: 'renderEdges',
136
+ method: this.renderEdges,
137
+ arg: []
138
+ })
121
139
  case 'marginIsSameChange': //params.polygon
122
140
  case 'marginDifferentChange': //params.polygon,index
123
141
  case 'marginSameChange': //params.polygon
@@ -132,6 +150,13 @@ export default {
132
150
  case 'removeNodes': //params.nodes
133
151
  case 'removeEdges': //params.edges
134
152
  case 'translate': //params.edges
153
+ if (this.removeConstructionPolylineMesh) {
154
+ methodList.push({
155
+ name: 'removeConstructionPolyline',
156
+ method: this.removeConstructionPolylineMesh,
157
+ arg: []
158
+ })
159
+ }
135
160
  methodList.push({
136
161
  name: 'renderGeometry',
137
162
  method: this.renderGeometry,
@@ -187,6 +212,11 @@ export default {
187
212
  method: this.renderObstacles,
188
213
  arg: []
189
214
  })
215
+ methodList.push({
216
+ name: 'renderNodes',
217
+ method: this.renderNodes,
218
+ arg: []
219
+ })
190
220
  } else if (params.layer == 'obstacle') {
191
221
  methodList.push({
192
222
  name: 'renderBase',
@@ -232,11 +262,24 @@ export default {
232
262
  arg: []
233
263
  })
234
264
  case 'selectedRoofChange':
265
+ case 'selectedObstacleChange':
235
266
  methodList.push({
236
267
  name: 'renderFlatRoofs',
237
268
  method: this.renderFlatRoofs,
238
269
  arg: []
239
270
  })
271
+ methodList.push({
272
+ name: 'renderRoofsMargin',
273
+ method: this.renderRoofsMargin,
274
+ arg: []
275
+ })
276
+ break
277
+ case 'selectedModuleFieldChange':
278
+ methodList.push({
279
+ name: 'renderEdges',
280
+ method: this.renderEdges,
281
+ arg: []
282
+ })
240
283
  break
241
284
  case 'subHandleSelectionChange':
242
285
  case 'masterHandleSelectionChange':
@@ -321,12 +364,28 @@ export default {
321
364
  arg: [params.roofIds]
322
365
  })
323
366
  break
367
+ case 'selectedPanelChange':
368
+ methodList.push({
369
+ name: 'renderModuleFields',
370
+ method: this.renderModuleFields,
371
+ arg: []
372
+ })
373
+ break
374
+ case 'removeConstruction':
375
+ methodList.push({
376
+ name: 'removeConstructionPolyline',
377
+ method: this.removeConstructionPolyline,
378
+ arg: []
379
+ })
380
+ break
324
381
  }
325
382
  return methodList
326
383
  },
327
384
  async renderMethods(methodList) {
328
385
  for (let item of methodList) {
329
- await item.method(...item.arg)
386
+ if (item.method) {
387
+ await item.method(...item.arg)
388
+ }
330
389
  }
331
390
  },
332
391
  renderGeometry() {
@@ -406,17 +465,12 @@ export default {
406
465
  },
407
466
  geometryEventsToDo(val) {
408
467
  if (val.length > 0) {
468
+ console.log(val)
409
469
  this.refreshRendering()
410
470
  }
411
471
  }
412
472
  },
413
473
  beforeDestroy() {
414
- if (this.tweenOrbit) {
415
- this.tweenOrbit = null
416
- }
417
- if (this.tweenCamera) {
418
- this.tweenCamera = null
419
- }
420
474
  this.clearThreeObjects(this.scene)
421
475
 
422
476
  if (this.three_map) {
@@ -62,7 +62,7 @@ export default {
62
62
  },
63
63
  initialiseThree(isInteractive = true) {
64
64
  this.scene.background = new THREE.Color(0xb0b0b0)
65
-
65
+ this.camera = this.perspectiveCamera
66
66
  this.camera.position.set(0, -100, 50)
67
67
  this.camera.up.set(0, 0, 1)
68
68
 
@@ -80,6 +80,10 @@ export default {
80
80
 
81
81
  // const axesHelper = new THREE.AxesHelper( 20 );
82
82
  // this.scene.add( axesHelper );
83
+
84
+ this.scene.add(this.perspectiveCamera)
85
+ this.scene.add(this.orthographicCamera)
86
+
83
87
  //Light
84
88
  const ambientLight = new THREE.AmbientLight(0xf0f0f0, 0.5)
85
89
  this.scene.add(ambientLight)
@@ -102,7 +106,13 @@ export default {
102
106
  this.camera,
103
107
  this.renderer.domElement
104
108
  )
105
- this.orbitControl.maxPolarAngle = (Math.PI / 2) * (87 / 90)
109
+ this.orbitControl.maxPolarAngle = Math.PI / 2
110
+ this.orbitControl.mouseButtons = {
111
+ LEFT: THREE.MOUSE.PAN,
112
+ RIGHT: THREE.MOUSE.ROTATE,
113
+ MIDDLE: THREE.MOUSE.DOLLY
114
+ }
115
+ this.orbitControl.screenSpacePanning = false
106
116
  this.orbitControl.addEventListener('change', () => {
107
117
  this.orbitControlChange()
108
118
  })
@@ -114,16 +124,7 @@ export default {
114
124
  directionalLight2.dispose()
115
125
  },
116
126
  orbitControlChange() {
117
- if (this.orbitControl.target.z != 0) {
118
- this.orbitControl.target.set(
119
- this.orbitControl.target.x,
120
- this.orbitControl.target.y,
121
- 0
122
- )
123
- this.orbitControl.update()
124
- } else {
125
- this.render()
126
- }
127
+ this.render()
127
128
  },
128
129
  onWindowResize() {
129
130
  this.camera.aspect = window.innerWidth / window.innerHeight
@@ -7,6 +7,21 @@ import {
7
7
  } from '@eturnity/eturnity_maths'
8
8
  import getLayers from '../utils/layers'
9
9
  import { UpdateRoofObstacleRelations } from '../helper/UpdateRoofObstacleRelations'
10
+ function sanitizedOutline(outline) {
11
+ return outline.reduce((accumulator, currentValue) => {
12
+ if (
13
+ !accumulator.find(
14
+ (p) =>
15
+ p[0] == currentValue[0] &&
16
+ p[1] == currentValue[1] &&
17
+ p[2] == currentValue[2]
18
+ )
19
+ ) {
20
+ accumulator.push(currentValue)
21
+ }
22
+ return accumulator
23
+ }, [])
24
+ }
10
25
  export async function hydratePolygons({
11
26
  roofsResponse,
12
27
  obstaclesResponse,
@@ -17,18 +32,24 @@ export async function hydratePolygons({
17
32
  //removing empty roof,obstacle and modulefield generated by BE on variant creation
18
33
  roofsResponse = roofsResponse.reduce((acc, cur) => {
19
34
  if (cur.roof_outline.length > 0) {
35
+ let outline = sanitizedOutline(cur.roof_outline)
36
+ cur.roof_outline = outline
20
37
  acc.push(cur)
21
38
  }
22
39
  return acc
23
40
  }, [])
24
41
  obstaclesResponse = obstaclesResponse.reduce((acc, cur) => {
25
42
  if (cur.obstacle_outline.length > 0) {
43
+ let outline = sanitizedOutline(cur.obstacle_outline)
44
+ cur.obstacle_outline = outline
26
45
  acc.push(cur)
27
46
  }
28
47
  return acc
29
48
  }, [])
30
49
  moduleFieldsResponse = moduleFieldsResponse.reduce((acc, cur) => {
31
50
  if (cur.module_field_outline.length > 0) {
51
+ let outline = sanitizedOutline(cur.module_field_outline)
52
+ cur.module_field_outline = outline
32
53
  acc.push(cur)
33
54
  }
34
55
  return acc
@@ -47,6 +68,7 @@ export async function hydratePolygons({
47
68
  })
48
69
  let roof = new Polygon(roof_outline, 'roof')
49
70
  roof.id = roofResp.roof_uuid
71
+ roof.version = roofResp.version
50
72
  roof.name = roofResp.roof_name
51
73
  roof.shadingData = roofResp.shading_data
52
74
  roof.systemSolarSizeKWp = roofResp.system_solar_size_kWp
@@ -67,6 +89,7 @@ export async function hydratePolygons({
67
89
  })
68
90
  let obstacle = new Polygon(obstacle_outline, 'obstacle')
69
91
  obstacle.id = obstacleResp.obstacle_uuid
92
+ obstacle.version = obstacleResp.version
70
93
  obstacle.height = obstacleResp.obstacle_height_above_ground_mm
71
94
  obstacle.isParallel = obstacleResp.obstacle_slope_is_parallel_to_roof
72
95
  obstacle = updateComputedGeometryPolygon(obstacle)
@@ -114,10 +114,9 @@ export function generateNodes3D(polygons) {
114
114
  node3D.masterHandle.open =
115
115
  node3D.belongsTo.filter((item) => item.polygon.outline[item.index].open)
116
116
  .length > 0
117
- node3D.masterHandle.selected =
118
- node3D.belongsTo.filter(
119
- (item) => item.polygon.outline[item.index].selected
120
- ).length > node3D.belongsTo.length
117
+ node3D.masterHandle.selected = node3D.belongsTo.every(
118
+ (item) => item.polygon.outline[item.index].selected
119
+ )
121
120
  }
122
121
  })
123
122
  return nodes3D
@@ -180,11 +179,13 @@ export function generateEdges3D(polygons) {
180
179
  //check if edge2D already exist
181
180
  const nextPoint = outline[(i + 1) % outline.length]
182
181
  let edge3D = edges3D.find((edge) => {
183
- isAlmostSameSegment3D(
184
- [point, nextPoint],
185
- edge.outline,
186
- mmTolerance
187
- ) && edge.layer == polygon.layer
182
+ return (
183
+ isAlmostSameSegment3D(
184
+ [point, nextPoint],
185
+ edge.outline,
186
+ mmTolerance
187
+ ) && edge.layer == polygon.layer
188
+ )
188
189
  })
189
190
  if (!edge3D) {
190
191
  //create an edge at this position