@eturnity/eturnity_3d 7.2.4 → 7.4.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 +2 -2
- package/src/components/ThreeCanvasViewer.vue +4 -12
- package/src/config.js +3 -3
- package/src/helper/UpdateRoofModuleFieldRelations.js +1 -1
- package/src/helper/cameraMixin.js +276 -17
- package/src/helper/materialMixin.js +29 -7
- package/src/helper/render/circle.png +0 -0
- package/src/helper/render/clear.js +0 -8
- package/src/helper/render/edge.js +52 -20
- package/src/helper/render/margin.js +56 -37
- package/src/helper/render/mergedGeometry.js +4 -3
- package/src/helper/render/moduleField.js +9 -5
- package/src/helper/render/node.js +12 -2
- package/src/helper/render/panel.js +61 -31
- package/src/helper/render/roof.js +28 -10
- package/src/helper/renderMixin.js +59 -7
- package/src/helper/threeMixin.js +13 -12
- package/src/store/hydrateData.js +21 -0
- package/src/store/nodesEdgesCreation.js +10 -9
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eturnity/eturnity_3d",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "7.
|
|
4
|
+
"version": "7.4.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.
|
|
13
|
+
"@eturnity/eturnity_maths": "7.4.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.
|
|
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.
|
|
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 =
|
|
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.
|
|
143
|
-
export const node3dOpacity = 0.
|
|
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
|
-
|
|
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,136 @@
|
|
|
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
|
+
console.log(this.orthographicCamera)
|
|
93
|
+
let altitude =
|
|
94
|
+
(this.orthographicCamera.right - this.orthographicCamera.left) /
|
|
95
|
+
((this.perspectiveCamera.fov * Math.PI) / 180) /
|
|
96
|
+
this.perspectiveCamera.aspect
|
|
97
|
+
|
|
98
|
+
this.camera.position.set(
|
|
99
|
+
this.orthographicCamera.position.x,
|
|
100
|
+
this.orthographicCamera.position.y,
|
|
101
|
+
altitude
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
this.camera.up = new THREE.Vector3(0, 0, 1)
|
|
105
|
+
this.camera.updateProjectionMatrix()
|
|
106
|
+
|
|
107
|
+
this.renderer.camera = this.camera
|
|
108
|
+
this.composer.renderer.camera = this.camera
|
|
109
|
+
this.composer.renderCamera = this.camera
|
|
110
|
+
this.renderPass.camera = this.camera
|
|
111
|
+
this.overlayRenderPass.camera = this.camera
|
|
112
|
+
this.outlinePassHighlight.camera = this.camera
|
|
113
|
+
this.outlinePassHighlight.renderCamera = this.camera
|
|
114
|
+
this.outlinePassSelected.camera = this.camera
|
|
115
|
+
this.outlinePassSelected.renderCamera = this.camera
|
|
116
|
+
this.orbitControl.camera = this.camera
|
|
117
|
+
this.orbitControl.object = this.camera
|
|
118
|
+
this.orbitControl.target.set(
|
|
119
|
+
this.camera.position.x,
|
|
120
|
+
this.camera.position.y,
|
|
121
|
+
0
|
|
122
|
+
)
|
|
123
|
+
this.orbitControl.screenSpacePanning = false
|
|
124
|
+
this.orbitControl.enableRotate = true
|
|
125
|
+
this.orbitControl.mouseButtons = {
|
|
126
|
+
LEFT: THREE.MOUSE.ROTATE,
|
|
127
|
+
MIDDLE: THREE.MOUSE.DOLLY,
|
|
128
|
+
RIGHT: THREE.MOUSE.PAN
|
|
129
|
+
}
|
|
130
|
+
this.orbitControl.update()
|
|
131
|
+
|
|
132
|
+
this.composer.render()
|
|
133
|
+
},
|
|
10
134
|
zoomIn3D() {
|
|
11
135
|
let target = this.orbitControl.target
|
|
12
136
|
let curentPosition = this.camera.position
|
|
@@ -39,6 +163,7 @@ export default {
|
|
|
39
163
|
},
|
|
40
164
|
setCameraGlobalPosition() {
|
|
41
165
|
if (this.roofs.length == 0) return
|
|
166
|
+
let newFov = 50
|
|
42
167
|
let bounds = this.roofsBounds
|
|
43
168
|
let targetVector = {
|
|
44
169
|
x: (bounds.xMax + bounds.xMin) / 2000,
|
|
@@ -50,7 +175,7 @@ export default {
|
|
|
50
175
|
(bounds.yMax - bounds.yMin) / 2000
|
|
51
176
|
)
|
|
52
177
|
let distance =
|
|
53
|
-
5 + objectRadius_m / Math.sin(((
|
|
178
|
+
5 + objectRadius_m / Math.sin(((newFov / 2) * Math.PI) / 180)
|
|
54
179
|
let cameraMoveVector = { x: 0, y: 0, z: distance }
|
|
55
180
|
const positionVector = addVector(targetVector, cameraMoveVector)
|
|
56
181
|
const position = [
|
|
@@ -59,8 +184,39 @@ export default {
|
|
|
59
184
|
positionVector.z
|
|
60
185
|
]
|
|
61
186
|
let target = [targetVector.x, targetVector.y, targetVector.z]
|
|
187
|
+
this.setTweenTo(position, target, newFov)
|
|
188
|
+
},
|
|
189
|
+
setCameraGlobalVerticalPosition() {
|
|
190
|
+
let position, target
|
|
191
|
+
let newFov = 10
|
|
192
|
+
if (this.roofs.length != 0) {
|
|
193
|
+
let bounds = this.roofsBounds
|
|
194
|
+
let targetVector = {
|
|
195
|
+
x: (bounds.xMax + bounds.xMin) / 2000,
|
|
196
|
+
y: (bounds.yMax + bounds.yMin) / 2000,
|
|
197
|
+
z: 0
|
|
198
|
+
}
|
|
199
|
+
let objectRadius_m = Math.max(
|
|
200
|
+
(bounds.xMax - bounds.xMin) / 2000,
|
|
201
|
+
(bounds.yMax - bounds.yMin) / 2000
|
|
202
|
+
)
|
|
62
203
|
|
|
63
|
-
|
|
204
|
+
let distance =
|
|
205
|
+
2 * (objectRadius_m / Math.sin(((newFov / 2) * Math.PI) / 180))
|
|
206
|
+
let cameraMoveVector = { x: 0, y: 0, z: distance }
|
|
207
|
+
const positionVector = addVector(targetVector, cameraMoveVector)
|
|
208
|
+
position = [positionVector.x, positionVector.y, positionVector.z]
|
|
209
|
+
target = [targetVector.x, targetVector.y, targetVector.z]
|
|
210
|
+
} else {
|
|
211
|
+
position = [0, 0, 300]
|
|
212
|
+
target = [0, 0, 0]
|
|
213
|
+
}
|
|
214
|
+
this.setTweenTo(
|
|
215
|
+
position,
|
|
216
|
+
target,
|
|
217
|
+
newFov,
|
|
218
|
+
this.turnPerspectiveCameraToOrthogonal
|
|
219
|
+
)
|
|
64
220
|
},
|
|
65
221
|
setCameraOrthogonalTo(polygon) {
|
|
66
222
|
if (polygon) {
|
|
@@ -109,23 +265,126 @@ export default {
|
|
|
109
265
|
this.setTweenTo(position, target)
|
|
110
266
|
}
|
|
111
267
|
},
|
|
112
|
-
setTweenTo(position, target,
|
|
268
|
+
setTweenTo(position, target, fov = 50, onCompleteCallback = () => {}) {
|
|
113
269
|
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
270
|
if (this.camera) {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
271
|
+
const currentTweenVar = {
|
|
272
|
+
t: 0
|
|
273
|
+
}
|
|
274
|
+
const initialTarget = {
|
|
275
|
+
x: this.orbitControl.target.x,
|
|
276
|
+
y: this.orbitControl.target.y,
|
|
277
|
+
z: this.orbitControl.target.z
|
|
278
|
+
}
|
|
279
|
+
const initialFov = this.camera.fov
|
|
280
|
+
const initialCameraPosition = {
|
|
281
|
+
x: this.camera.position.x,
|
|
282
|
+
y: this.camera.position.y,
|
|
283
|
+
z: this.camera.position.z
|
|
284
|
+
}
|
|
285
|
+
const finalCameraPosition = {
|
|
286
|
+
x: position[0],
|
|
287
|
+
y: position[1],
|
|
288
|
+
z: position[2]
|
|
289
|
+
}
|
|
290
|
+
if (position[0] == target[0] && position[1] == target[1]) {
|
|
291
|
+
const distance2D = getDistanceBetweenPoints(
|
|
292
|
+
finalCameraPosition,
|
|
293
|
+
initialCameraPosition
|
|
294
|
+
)
|
|
295
|
+
//angle from south
|
|
296
|
+
const angle2D = Math.atan2(
|
|
297
|
+
initialCameraPosition.y - finalCameraPosition.y,
|
|
298
|
+
initialCameraPosition.x - finalCameraPosition.x
|
|
299
|
+
)
|
|
300
|
+
this.tweenCamera = new TWEEN.Tween(currentTweenVar)
|
|
301
|
+
.to({ t: 1 }, 2000)
|
|
302
|
+
.easing(TWEEN.Easing.Sinusoidal.Out)
|
|
303
|
+
.onUpdate(() => {
|
|
304
|
+
const t = currentTweenVar.t
|
|
305
|
+
this.camera.fov = initialFov + Math.sqrt(t) * (fov - initialFov)
|
|
306
|
+
|
|
307
|
+
const newDistance = distance2D * (1 - t)
|
|
308
|
+
const newAngle = (angle2D + Math.PI / 2) * (1 - t) - Math.PI / 2
|
|
309
|
+
const newAltitude =
|
|
310
|
+
finalCameraPosition.z +
|
|
311
|
+
(1 - t) * (initialCameraPosition.z - finalCameraPosition.z)
|
|
312
|
+
const nextPosition = {
|
|
313
|
+
x: finalCameraPosition.x + newDistance * Math.cos(newAngle),
|
|
314
|
+
y: finalCameraPosition.y + newDistance * Math.sin(newAngle),
|
|
315
|
+
z: newAltitude
|
|
316
|
+
}
|
|
317
|
+
this.camera.position.set(
|
|
318
|
+
nextPosition.x,
|
|
319
|
+
nextPosition.y,
|
|
320
|
+
nextPosition.z
|
|
321
|
+
)
|
|
322
|
+
this.camera.up = new THREE.Vector3(
|
|
323
|
+
0,
|
|
324
|
+
Math.sin((t * Math.PI) / 2),
|
|
325
|
+
Math.cos((t * Math.PI) / 2)
|
|
326
|
+
)
|
|
327
|
+
|
|
328
|
+
this.camera.updateProjectionMatrix()
|
|
329
|
+
const nextTarget = {
|
|
330
|
+
x: initialTarget.x + t * (target[0] - initialTarget.x),
|
|
331
|
+
y: initialTarget.y + t * (target[1] - initialTarget.y),
|
|
332
|
+
z: initialTarget.z + t * (target[2] - initialTarget.z)
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
this.orbitControl.target.set(
|
|
336
|
+
nextTarget.x,
|
|
337
|
+
nextTarget.y,
|
|
338
|
+
nextTarget.z
|
|
339
|
+
)
|
|
340
|
+
if (this.orbitControl && this.orbitControl.update)
|
|
341
|
+
this.orbitControl.update()
|
|
342
|
+
})
|
|
343
|
+
.onComplete(() => {
|
|
344
|
+
onCompleteCallback()
|
|
345
|
+
})
|
|
346
|
+
} else {
|
|
347
|
+
console.log('setTween Camera not Vertical')
|
|
348
|
+
this.camera.up = { x: 0, y: 0, z: 1 }
|
|
349
|
+
this.tweenCamera = new TWEEN.Tween(currentTweenVar)
|
|
350
|
+
.to({ t: 1 }, 2000)
|
|
351
|
+
.easing(TWEEN.Easing.Sinusoidal.Out)
|
|
352
|
+
.onUpdate(() => {
|
|
353
|
+
const t = currentTweenVar.t
|
|
354
|
+
this.camera.fov = initialFov + t * t * (fov - initialFov)
|
|
355
|
+
this.camera.updateProjectionMatrix()
|
|
356
|
+
|
|
357
|
+
const nextPosition = {
|
|
358
|
+
x:
|
|
359
|
+
finalCameraPosition.x +
|
|
360
|
+
(1 - t) * (initialCameraPosition.x - finalCameraPosition.x),
|
|
361
|
+
y:
|
|
362
|
+
finalCameraPosition.y +
|
|
363
|
+
(1 - t) * (initialCameraPosition.y - finalCameraPosition.y),
|
|
364
|
+
z:
|
|
365
|
+
finalCameraPosition.z +
|
|
366
|
+
(1 - t) * (initialCameraPosition.z - finalCameraPosition.z)
|
|
367
|
+
}
|
|
368
|
+
this.camera.position.set(
|
|
369
|
+
nextPosition.x,
|
|
370
|
+
nextPosition.y,
|
|
371
|
+
nextPosition.z
|
|
372
|
+
)
|
|
373
|
+
const nextTarget = {
|
|
374
|
+
x: initialTarget.x + t * (target[0] - initialTarget.x),
|
|
375
|
+
y: initialTarget.y + t * (target[1] - initialTarget.y),
|
|
376
|
+
z: initialTarget.z + t * (target[2] - initialTarget.z)
|
|
377
|
+
}
|
|
378
|
+
this.orbitControl.target.set(
|
|
379
|
+
nextTarget.x,
|
|
380
|
+
nextTarget.y,
|
|
381
|
+
nextTarget.z
|
|
382
|
+
)
|
|
383
|
+
if (this.orbitControl && this.orbitControl.update)
|
|
384
|
+
this.orbitControl.update()
|
|
385
|
+
})
|
|
386
|
+
}
|
|
387
|
+
this.tweenCamera.start()
|
|
129
388
|
}
|
|
130
389
|
}
|
|
131
390
|
},
|
|
@@ -32,18 +32,32 @@ export default {
|
|
|
32
32
|
side: THREE.DoubleSide
|
|
33
33
|
})
|
|
34
34
|
|
|
35
|
-
this.material.edge = new THREE.
|
|
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
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
-
|
|
46
|
-
|
|
47
|
-
cylinder =
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
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
|
-
|
|
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
|
-
|
|
60
|
-
|
|
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 (
|
|
10
|
-
|
|
11
|
-
|
|
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 =
|
|
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[
|
|
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.
|
|
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.
|
|
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
|
|
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
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
panelPolygon.moduleField.
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
if (
|
|
87
|
-
|
|
88
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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.
|
|
133
|
+
this.clearRemovedOnes('flatRoofMeshes')
|
|
134
|
+
let geometry
|
|
134
135
|
this.roofs.forEach((roofPolygon) => {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
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(
|
|
@@ -118,6 +130,11 @@ export default {
|
|
|
118
130
|
})
|
|
119
131
|
break
|
|
120
132
|
case 'toolChange': //params.toolName
|
|
133
|
+
methodList.push({
|
|
134
|
+
name: 'renderEdges',
|
|
135
|
+
method: this.renderEdges,
|
|
136
|
+
arg: []
|
|
137
|
+
})
|
|
121
138
|
case 'marginIsSameChange': //params.polygon
|
|
122
139
|
case 'marginDifferentChange': //params.polygon,index
|
|
123
140
|
case 'marginSameChange': //params.polygon
|
|
@@ -132,6 +149,13 @@ export default {
|
|
|
132
149
|
case 'removeNodes': //params.nodes
|
|
133
150
|
case 'removeEdges': //params.edges
|
|
134
151
|
case 'translate': //params.edges
|
|
152
|
+
if (this.removeConstructionPolylineMesh) {
|
|
153
|
+
methodList.push({
|
|
154
|
+
name: 'removeConstructionPolyline',
|
|
155
|
+
method: this.removeConstructionPolylineMesh,
|
|
156
|
+
arg: []
|
|
157
|
+
})
|
|
158
|
+
}
|
|
135
159
|
methodList.push({
|
|
136
160
|
name: 'renderGeometry',
|
|
137
161
|
method: this.renderGeometry,
|
|
@@ -204,6 +228,11 @@ export default {
|
|
|
204
228
|
arg: []
|
|
205
229
|
})
|
|
206
230
|
}
|
|
231
|
+
methodList.push({
|
|
232
|
+
name: 'renderRoofsMargin',
|
|
233
|
+
method: this.renderRoofsMargin,
|
|
234
|
+
arg: []
|
|
235
|
+
})
|
|
207
236
|
break
|
|
208
237
|
case 'removePanels': //params.panels
|
|
209
238
|
case 'removeModuleField': //params:moduleField
|
|
@@ -232,11 +261,24 @@ export default {
|
|
|
232
261
|
arg: []
|
|
233
262
|
})
|
|
234
263
|
case 'selectedRoofChange':
|
|
264
|
+
case 'selectedObstacleChange':
|
|
235
265
|
methodList.push({
|
|
236
266
|
name: 'renderFlatRoofs',
|
|
237
267
|
method: this.renderFlatRoofs,
|
|
238
268
|
arg: []
|
|
239
269
|
})
|
|
270
|
+
methodList.push({
|
|
271
|
+
name: 'renderRoofsMargin',
|
|
272
|
+
method: this.renderRoofsMargin,
|
|
273
|
+
arg: []
|
|
274
|
+
})
|
|
275
|
+
break
|
|
276
|
+
case 'selectedModuleFieldChange':
|
|
277
|
+
methodList.push({
|
|
278
|
+
name: 'renderEdges',
|
|
279
|
+
method: this.renderEdges,
|
|
280
|
+
arg: []
|
|
281
|
+
})
|
|
240
282
|
break
|
|
241
283
|
case 'subHandleSelectionChange':
|
|
242
284
|
case 'masterHandleSelectionChange':
|
|
@@ -321,12 +363,28 @@ export default {
|
|
|
321
363
|
arg: [params.roofIds]
|
|
322
364
|
})
|
|
323
365
|
break
|
|
366
|
+
case 'selectedPanelChange':
|
|
367
|
+
methodList.push({
|
|
368
|
+
name: 'renderModuleFields',
|
|
369
|
+
method: this.renderModuleFields,
|
|
370
|
+
arg: []
|
|
371
|
+
})
|
|
372
|
+
break
|
|
373
|
+
case 'removeConstruction':
|
|
374
|
+
methodList.push({
|
|
375
|
+
name: 'removeConstructionPolyline',
|
|
376
|
+
method: this.removeConstructionPolyline,
|
|
377
|
+
arg: []
|
|
378
|
+
})
|
|
379
|
+
break
|
|
324
380
|
}
|
|
325
381
|
return methodList
|
|
326
382
|
},
|
|
327
383
|
async renderMethods(methodList) {
|
|
328
384
|
for (let item of methodList) {
|
|
329
|
-
|
|
385
|
+
if (item.method) {
|
|
386
|
+
await item.method(...item.arg)
|
|
387
|
+
}
|
|
330
388
|
}
|
|
331
389
|
},
|
|
332
390
|
renderGeometry() {
|
|
@@ -411,12 +469,6 @@ export default {
|
|
|
411
469
|
}
|
|
412
470
|
},
|
|
413
471
|
beforeDestroy() {
|
|
414
|
-
if (this.tweenOrbit) {
|
|
415
|
-
this.tweenOrbit = null
|
|
416
|
-
}
|
|
417
|
-
if (this.tweenCamera) {
|
|
418
|
-
this.tweenCamera = null
|
|
419
|
-
}
|
|
420
472
|
this.clearThreeObjects(this.scene)
|
|
421
473
|
|
|
422
474
|
if (this.three_map) {
|
package/src/helper/threeMixin.js
CHANGED
|
@@ -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
|
|
109
|
+
this.orbitControl.maxPolarAngle = (0.95 * Math.PI) / 2
|
|
110
|
+
this.orbitControl.mouseButtons = {
|
|
111
|
+
RIGHT: THREE.MOUSE.PAN,
|
|
112
|
+
LEFT: 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
|
-
|
|
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
|
package/src/store/hydrateData.js
CHANGED
|
@@ -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
|
|
@@ -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
|
-
|
|
119
|
-
|
|
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
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
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
|