@eturnity/eturnity_3d 8.19.3 → 8.22.0-EPDM-13091.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/config.js +11 -0
- package/src/helper/UpdateRoofModuleFieldRelations.js +171 -0
- package/src/helper/render/clear.js +16 -20
- package/src/helper/render/edge.js +1 -2
- package/src/helper/render/geometryHandler.js +53 -1
- package/src/helper/render/moduleField.js +83 -21
- package/src/helper/renderMixin.js +5 -7
- package/src/store/hydrateData.js +77 -48
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eturnity/eturnity_3d",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "8.
|
|
4
|
+
"version": "8.22.0-EPDM-13091.0",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
7
7
|
"src"
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"merge-remote-master": "node scripts/merge-remote-master.js"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@eturnity/eturnity_maths": "8.19.0",
|
|
19
|
+
"@eturnity/eturnity_maths": "8.19.0-EPDM-13091.1",
|
|
20
20
|
"@originjs/vite-plugin-commonjs": "1.0.3",
|
|
21
21
|
"core-js": "3.30.2",
|
|
22
22
|
"cors": "2.8.5",
|
package/src/config.js
CHANGED
|
@@ -282,3 +282,14 @@ export const hitOptionStroke = {
|
|
|
282
282
|
|
|
283
283
|
export const dragHeightSensitivity = 20
|
|
284
284
|
export const snapLimit = 100
|
|
285
|
+
|
|
286
|
+
export const fittingPanelsColorMap = {
|
|
287
|
+
black: '#000000',
|
|
288
|
+
blue: '#2B3A67',
|
|
289
|
+
brown: '#623A36',
|
|
290
|
+
'rustic red': '#713229',
|
|
291
|
+
terracotta: '#A76448',
|
|
292
|
+
transparent: 'transparent',
|
|
293
|
+
white: '#ffffff',
|
|
294
|
+
default: '#0068DE',
|
|
295
|
+
}
|
|
@@ -3,7 +3,11 @@ import {
|
|
|
3
3
|
verticalProjectionOnPlane,
|
|
4
4
|
intersectOutlines,
|
|
5
5
|
calculateArea,
|
|
6
|
+
isSelfIntersecting,
|
|
7
|
+
isPolygonInsidePolygon,
|
|
8
|
+
getConcaveOutlines,
|
|
6
9
|
} from '@eturnity/eturnity_maths'
|
|
10
|
+
import { fittingPanelsColorMap } from '../config'
|
|
7
11
|
//this function just update the "roof" and "moduleField(s)" properties of panels,moduleFields and roofs
|
|
8
12
|
export function UpdateRoofModuleFieldRelations(state) {
|
|
9
13
|
let moduleFields = state.polygons.filter(
|
|
@@ -78,3 +82,170 @@ export function removeModuleFieldAndPanelsOnNoOrMultipleRoofs(state) {
|
|
|
78
82
|
]
|
|
79
83
|
return state
|
|
80
84
|
}
|
|
85
|
+
|
|
86
|
+
export function updateModuleFieldFittingPanels(moduleField) {
|
|
87
|
+
delete moduleField.fittingPanels
|
|
88
|
+
const { has_fitting_panels, fitting_panel_area_m2 } = moduleField.data
|
|
89
|
+
const hasFittingPanels = has_fitting_panels && fitting_panel_area_m2 > 0
|
|
90
|
+
if (!hasFittingPanels) return
|
|
91
|
+
const polygons = []
|
|
92
|
+
|
|
93
|
+
const outlines = getModuleFieldRoofIntersections(
|
|
94
|
+
moduleField,
|
|
95
|
+
moduleField.roof.margins.innerOutline
|
|
96
|
+
)
|
|
97
|
+
const holes = getModuleFieldHoleOutlines(moduleField)
|
|
98
|
+
|
|
99
|
+
outlines.forEach((outline) => {
|
|
100
|
+
polygons.push({
|
|
101
|
+
outline,
|
|
102
|
+
// Clean up holes outside of the outline
|
|
103
|
+
holes: holes
|
|
104
|
+
.flatMap((hole) => intersectOutlines(hole, outline))
|
|
105
|
+
.filter(Boolean),
|
|
106
|
+
})
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
// map backsheet color to hex color
|
|
110
|
+
const backSheetColor = moduleField.pvData?.backsheet_color || 'default'
|
|
111
|
+
const mappedColor = fittingPanelsColorMap[backSheetColor]
|
|
112
|
+
|
|
113
|
+
moduleField.fittingPanels = {
|
|
114
|
+
polygons,
|
|
115
|
+
visible: true,
|
|
116
|
+
color: mappedColor,
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function getRoofInnerMarginOutline({
|
|
121
|
+
roof,
|
|
122
|
+
moduleField,
|
|
123
|
+
pointer = null,
|
|
124
|
+
} = {}) {
|
|
125
|
+
let roofInnerMarginOutline = roof.margins.innerOutline
|
|
126
|
+
let isOutlineSelfIntersecting = false
|
|
127
|
+
let sumAllArea = 0
|
|
128
|
+
if (isSelfIntersecting(roofInnerMarginOutline)) {
|
|
129
|
+
let selfIntersections = intersectOutlines(
|
|
130
|
+
roof.margins.innerOutline,
|
|
131
|
+
roof.margins.innerOutline
|
|
132
|
+
)
|
|
133
|
+
let sumAllArea = selfIntersections.reduce((acc, cur) => {
|
|
134
|
+
acc += calculateArea(cur)
|
|
135
|
+
return acc
|
|
136
|
+
}, 0)
|
|
137
|
+
if (moduleField) {
|
|
138
|
+
selfIntersections = selfIntersections.filter((i) => {
|
|
139
|
+
if (calculateArea(i) < 0.05 * sumAllArea) {
|
|
140
|
+
return false
|
|
141
|
+
}
|
|
142
|
+
let MFintersections = intersectOutlines(moduleField.outline, i)
|
|
143
|
+
if (MFintersections.length > 0) {
|
|
144
|
+
return true
|
|
145
|
+
}
|
|
146
|
+
})
|
|
147
|
+
} else {
|
|
148
|
+
if (pointer && pointer.reality_x && pointer.reality_y) {
|
|
149
|
+
let P = {
|
|
150
|
+
x: pointer.reality_x,
|
|
151
|
+
y: pointer.reality_y,
|
|
152
|
+
z: 0,
|
|
153
|
+
}
|
|
154
|
+
let pointerIntersections = selfIntersections.filter((outline) =>
|
|
155
|
+
isInsidePolygon(P, outline)
|
|
156
|
+
)
|
|
157
|
+
if (pointerIntersections.length) {
|
|
158
|
+
selfIntersections = pointerIntersections
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
let sortedSelfIntersections = selfIntersections.sort(
|
|
163
|
+
(a, b) => calculateArea(b) - calculateArea(a)
|
|
164
|
+
)
|
|
165
|
+
if (sortedSelfIntersections.length) {
|
|
166
|
+
roofInnerMarginOutline = sortedSelfIntersections[0]
|
|
167
|
+
isOutlineSelfIntersecting = true
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return {
|
|
171
|
+
isSelfIntersecting: isOutlineSelfIntersecting,
|
|
172
|
+
outline: roofInnerMarginOutline,
|
|
173
|
+
totalArea: sumAllArea,
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export function getModuleFieldRoofIntersections(
|
|
178
|
+
moduleField,
|
|
179
|
+
roofInnerMarginOutline
|
|
180
|
+
) {
|
|
181
|
+
const roof = moduleField.roof
|
|
182
|
+
let intersections = intersectOutlines(
|
|
183
|
+
roofInnerMarginOutline,
|
|
184
|
+
moduleField.outline
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
intersections = intersections.map((i) =>
|
|
188
|
+
i.map((v) => {
|
|
189
|
+
return {
|
|
190
|
+
...v,
|
|
191
|
+
z: verticalProjectionOnPlane(v, roof.normalVector, roof.flatOutline[0])
|
|
192
|
+
.z,
|
|
193
|
+
}
|
|
194
|
+
})
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
return intersections
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export function getModuleFieldHoleOutlines(moduleField) {
|
|
201
|
+
const obstacles = []
|
|
202
|
+
const roof = moduleField.roof
|
|
203
|
+
if (roof.moduleFields && roof.moduleFields.length > 0) {
|
|
204
|
+
obstacles.push(
|
|
205
|
+
...roof.moduleFields.filter((obstacle) => {
|
|
206
|
+
return (
|
|
207
|
+
obstacle.id != moduleField.id && //obstacle cannot be MF itself
|
|
208
|
+
obstacle.panels &&
|
|
209
|
+
obstacle.panels.length > 0 && //obstacle cannot be a moduleField without panels on
|
|
210
|
+
!isPolygonInsidePolygon(moduleField.outline, obstacle.outline) && //obstacle cannot be a container of the polygon we try to compute
|
|
211
|
+
(obstacle.priority >= moduleField.priority ||
|
|
212
|
+
isPolygonInsidePolygon(obstacle.outline, moduleField.outline)) //obstacle cannot be a MF with lower prio level (except if fully inside)
|
|
213
|
+
)
|
|
214
|
+
})
|
|
215
|
+
)
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
let groupedConcavePanelOutlines = []
|
|
219
|
+
obstacles.forEach((moduleField) => {
|
|
220
|
+
if (moduleField.panels.length) {
|
|
221
|
+
let groupedConcavePanelData = getConcaveOutlines(
|
|
222
|
+
moduleField.panels,
|
|
223
|
+
moduleField.panels[0].outline
|
|
224
|
+
)
|
|
225
|
+
groupedConcavePanelOutlines.push(...groupedConcavePanelData.outlines)
|
|
226
|
+
}
|
|
227
|
+
})
|
|
228
|
+
|
|
229
|
+
function verticalProjectionOnRoofFlatFace(v) {
|
|
230
|
+
const projectedZ = verticalProjectionOnPlane(
|
|
231
|
+
v,
|
|
232
|
+
roof.normalVector,
|
|
233
|
+
roof.flatOutline[0]
|
|
234
|
+
).z
|
|
235
|
+
return { ...v, z: projectedZ }
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
groupedConcavePanelOutlines = groupedConcavePanelOutlines.map((outline) =>
|
|
239
|
+
outline.map((v) => verticalProjectionOnRoofFlatFace(v)).reverse()
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
const roofObstacleOutlines = roof.holes.map((hole) =>
|
|
243
|
+
hole.margins.outterOutline.map((v) => verticalProjectionOnRoofFlatFace(v))
|
|
244
|
+
)
|
|
245
|
+
const obstacleOutLine = [
|
|
246
|
+
...roofObstacleOutlines,
|
|
247
|
+
...groupedConcavePanelOutlines,
|
|
248
|
+
]
|
|
249
|
+
|
|
250
|
+
return obstacleOutLine
|
|
251
|
+
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import * as THREE from 'three'
|
|
2
|
+
|
|
1
3
|
export default {
|
|
2
4
|
methods: {
|
|
3
5
|
clearThreeObjects(obj) {
|
|
@@ -31,18 +33,7 @@ export default {
|
|
|
31
33
|
return
|
|
32
34
|
}
|
|
33
35
|
scene.remove(mesh)
|
|
34
|
-
|
|
35
|
-
mesh.geometry.dispose()
|
|
36
|
-
mesh.geometry = null
|
|
37
|
-
}
|
|
38
|
-
if (mesh.texture && mesh.texture.dispose) {
|
|
39
|
-
mesh.texture.dispose()
|
|
40
|
-
mesh.texture = null
|
|
41
|
-
}
|
|
42
|
-
if (mesh.material && mesh.material.dispose) {
|
|
43
|
-
mesh.material.dispose()
|
|
44
|
-
mesh.material = null
|
|
45
|
-
}
|
|
36
|
+
this.disposeMesh(mesh)
|
|
46
37
|
if (
|
|
47
38
|
mesh.userData.meshId &&
|
|
48
39
|
this.meshes[mesh.userData.type][mesh.userData.meshId]
|
|
@@ -68,19 +59,24 @@ export default {
|
|
|
68
59
|
})
|
|
69
60
|
},
|
|
70
61
|
clearByType(type) {
|
|
71
|
-
Object.values(this.meshes[type]).forEach((
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
77
|
-
mesh.material = null
|
|
78
|
-
this.scene.remove(mesh)
|
|
62
|
+
Object.values(this.meshes[type]).forEach((object) => {
|
|
63
|
+
object instanceof THREE.Group
|
|
64
|
+
? object.children.forEach((c) => this.disposeMesh(c))
|
|
65
|
+
: this.disposeMesh(object)
|
|
66
|
+
this.scene.remove(object)
|
|
79
67
|
})
|
|
80
68
|
this.meshes[type] = {}
|
|
81
69
|
if (this.renderer) {
|
|
82
70
|
this.renderer.renderLists.dispose()
|
|
83
71
|
}
|
|
84
72
|
},
|
|
73
|
+
disposeMesh(mesh) {
|
|
74
|
+
if (mesh.geometry && mesh.geometry.dispose) mesh.geometry.dispose()
|
|
75
|
+
if (mesh.material && mesh.material.dispose) mesh.material.dispose()
|
|
76
|
+
if (mesh.texture && mesh.texture.dispose) mesh.texture.dispose()
|
|
77
|
+
mesh.geometry = null
|
|
78
|
+
mesh.material = null
|
|
79
|
+
mesh.texture = null
|
|
80
|
+
},
|
|
85
81
|
},
|
|
86
82
|
}
|
|
@@ -88,10 +88,9 @@ export default {
|
|
|
88
88
|
cylinder.userData.type = 'edgeMeshes'
|
|
89
89
|
cylinder.userData.layer = edge.layer
|
|
90
90
|
cylinder.frustumCulled = false
|
|
91
|
-
cylinder.renderOrder = 10
|
|
92
91
|
|
|
93
92
|
cylinder.frustumCulled = false
|
|
94
|
-
cylinder.renderOrder =
|
|
93
|
+
cylinder.renderOrder = 15
|
|
95
94
|
this.meshes.edgeMeshes[edge.id] = cylinder
|
|
96
95
|
this.scene.add(cylinder)
|
|
97
96
|
}
|
|
@@ -410,7 +410,7 @@ export function getBufferObstacleSideGeometry(obstaclePolygon, roofPolygon) {
|
|
|
410
410
|
|
|
411
411
|
export function getBufferModuleFieldGeometry(moduleFieldPolygon) {
|
|
412
412
|
const roofPolygon = moduleFieldPolygon.roof
|
|
413
|
-
const moduleHeight =
|
|
413
|
+
const moduleHeight = 20
|
|
414
414
|
//get lowest verticalProjection
|
|
415
415
|
const normalVector = roofPolygon.normalVector
|
|
416
416
|
|
|
@@ -747,3 +747,55 @@ export function getExtrusionGeometry(
|
|
|
747
747
|
const geometry = new THREE.ExtrudeGeometry(shapes, settings)
|
|
748
748
|
return geometry
|
|
749
749
|
}
|
|
750
|
+
|
|
751
|
+
export function getFittingPanelsBufferGeometry(
|
|
752
|
+
outline,
|
|
753
|
+
holes = [],
|
|
754
|
+
moduleFieldPolygon
|
|
755
|
+
) {
|
|
756
|
+
const croppedHolesOutline = holes
|
|
757
|
+
.map((hole) => {
|
|
758
|
+
const cropedHoleOutline = intersectOutlines(hole, outline)[0] || []
|
|
759
|
+
return cropedHoleOutline.map((p) => {
|
|
760
|
+
return {
|
|
761
|
+
x: p.x,
|
|
762
|
+
y: p.y,
|
|
763
|
+
z: verticalProjectionOnPlane(
|
|
764
|
+
p,
|
|
765
|
+
moduleFieldPolygon.normalVector,
|
|
766
|
+
moduleFieldPolygon.flatOutline[0]
|
|
767
|
+
).z,
|
|
768
|
+
}
|
|
769
|
+
})
|
|
770
|
+
})
|
|
771
|
+
.filter((outline) => !!outline)
|
|
772
|
+
|
|
773
|
+
// add offset to vertices for rendering
|
|
774
|
+
const FITTING_PANELS_OFFSET = 2
|
|
775
|
+
const vectorOffset = multiplyVector(
|
|
776
|
+
FITTING_PANELS_OFFSET,
|
|
777
|
+
moduleFieldPolygon.normalVector
|
|
778
|
+
)
|
|
779
|
+
|
|
780
|
+
const offsetOutline = outline.map((point) => addVector(point, vectorOffset))
|
|
781
|
+
const offsetHolesOutline = croppedHolesOutline.map((outline) =>
|
|
782
|
+
outline.map((point) => addVector(point, vectorOffset))
|
|
783
|
+
)
|
|
784
|
+
|
|
785
|
+
const geometry = new THREE.BufferGeometry()
|
|
786
|
+
const triangleVertices = getTriangleVerticesFromOutline(
|
|
787
|
+
offsetOutline,
|
|
788
|
+
offsetHolesOutline
|
|
789
|
+
)
|
|
790
|
+
if (hasNaN(triangleVertices)) {
|
|
791
|
+
return null
|
|
792
|
+
}
|
|
793
|
+
const vertices = new Float32Array(triangleVertices)
|
|
794
|
+
|
|
795
|
+
const uvs = new Float32Array([1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0])
|
|
796
|
+
geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3))
|
|
797
|
+
geometry.setAttribute('uv', new THREE.BufferAttribute(uvs, 2))
|
|
798
|
+
geometry.computeVertexNormals()
|
|
799
|
+
geometry.userData.version = 0
|
|
800
|
+
return geometry
|
|
801
|
+
}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import * as THREE from 'three'
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
getBufferModuleFieldGeometry,
|
|
4
|
+
getFittingPanelsBufferGeometry,
|
|
5
|
+
} from './geometryHandler'
|
|
6
|
+
|
|
3
7
|
export default {
|
|
4
8
|
data() {
|
|
5
9
|
return {
|
|
@@ -13,31 +17,89 @@ export default {
|
|
|
13
17
|
['moduleField', 'tmpModuleField'].includes(p.layer)
|
|
14
18
|
)
|
|
15
19
|
moduleFieldPolygons.forEach((moduleFieldPolygon) => {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
mesh
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
20
|
+
const panelOverrideMesh =
|
|
21
|
+
this.renderModuleFieldPanelOverride(moduleFieldPolygon)
|
|
22
|
+
const fittingPanelsMesh =
|
|
23
|
+
this.renderModuleFieldFittingPanels(moduleFieldPolygon)
|
|
24
|
+
|
|
25
|
+
if (!panelOverrideMesh && !fittingPanelsMesh) return
|
|
26
|
+
|
|
27
|
+
const meshList = [panelOverrideMesh, fittingPanelsMesh]
|
|
28
|
+
const group = new THREE.Group()
|
|
29
|
+
meshList.forEach((mesh) => {
|
|
30
|
+
if (mesh) group.add(mesh)
|
|
31
|
+
})
|
|
32
|
+
group.matrixAutoUpdate = false
|
|
33
|
+
group.userData.version = moduleFieldPolygon.version
|
|
34
|
+
group.userData.type = 'moduleFieldsMeshes'
|
|
35
|
+
group.userData.layer = moduleFieldPolygon.layer
|
|
36
|
+
group.userData.meshId = moduleFieldPolygon.id
|
|
37
|
+
group.userData.polygonId = moduleFieldPolygon.id
|
|
38
|
+
group.visible = this.areModuleFieldsVisible && this.panelOpacity === 1
|
|
39
|
+
this.scene.add(group)
|
|
40
|
+
this.meshes.moduleFieldsMeshes[moduleFieldPolygon.id] = group
|
|
41
|
+
return
|
|
35
42
|
})
|
|
36
43
|
},
|
|
44
|
+
renderModuleFieldPanelOverride(moduleFieldPolygon) {
|
|
45
|
+
if (!moduleFieldPolygon?.data?.number_of_panels_override) return
|
|
46
|
+
const geometry = getBufferModuleFieldGeometry(moduleFieldPolygon)
|
|
47
|
+
const material = this.material.moduleFieldWithPanelOveride
|
|
48
|
+
if (geometry) {
|
|
49
|
+
const mesh = new THREE.Mesh(geometry, material)
|
|
50
|
+
mesh.matrixAutoUpdate = false
|
|
51
|
+
mesh.userData.version = moduleFieldPolygon.version
|
|
52
|
+
mesh.userData.type = 'moduleFieldsMeshes_panelOverride'
|
|
53
|
+
mesh.userData.layer = moduleFieldPolygon.layer
|
|
54
|
+
mesh.userData.meshId = moduleFieldPolygon.id
|
|
55
|
+
mesh.userData.polygonId = moduleFieldPolygon.id
|
|
56
|
+
mesh.renderOrder = 5
|
|
57
|
+
return mesh
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
renderModuleFieldFittingPanels(moduleFieldPolygon) {
|
|
61
|
+
if (!moduleFieldPolygon?.fittingPanels?.polygons?.length) return
|
|
62
|
+
const { polygons, visible, color } = moduleFieldPolygon.fittingPanels
|
|
63
|
+
|
|
64
|
+
const geometries = []
|
|
65
|
+
polygons.forEach((polygon) => {
|
|
66
|
+
const { outline, holes } = polygon
|
|
67
|
+
const geometry = getFittingPanelsBufferGeometry(
|
|
68
|
+
outline,
|
|
69
|
+
holes,
|
|
70
|
+
moduleFieldPolygon
|
|
71
|
+
)
|
|
72
|
+
geometries.push(geometry)
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
if (!geometries.length) return
|
|
76
|
+
|
|
77
|
+
const mergedGeometry = this.createMergedGeometry(geometries)
|
|
78
|
+
const isTransparent = color === 'transparent'
|
|
79
|
+
const material = new THREE.MeshBasicMaterial({
|
|
80
|
+
color: isTransparent ? '#ffffff' : color,
|
|
81
|
+
side: THREE.DoubleSide,
|
|
82
|
+
transparent: true,
|
|
83
|
+
opacity: isTransparent ? 0.2 : 0.8,
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
const mesh = new THREE.Mesh(mergedGeometry, material)
|
|
87
|
+
mesh.visible = visible
|
|
88
|
+
mesh.matrixAutoUpdate = false
|
|
89
|
+
mesh.userData.version = moduleFieldPolygon.version
|
|
90
|
+
mesh.userData.type = 'moduleFieldsMeshes_fittingPanels'
|
|
91
|
+
mesh.userData.layer = moduleFieldPolygon.layer
|
|
92
|
+
mesh.userData.meshId = moduleFieldPolygon.id
|
|
93
|
+
mesh.userData.polygonId = moduleFieldPolygon.id
|
|
94
|
+
mesh.renderOrder = 5
|
|
95
|
+
return mesh
|
|
96
|
+
},
|
|
37
97
|
updateModuleFieldsVisibility(isVisible) {
|
|
38
98
|
this.areModuleFieldsVisible = isVisible
|
|
39
99
|
Object.values(this.meshes['moduleFieldsMeshes']).forEach(
|
|
40
|
-
(mesh) =>
|
|
100
|
+
(mesh) =>
|
|
101
|
+
(mesh.visible =
|
|
102
|
+
this.areModuleFieldsVisible && this.panelOpacity === 1)
|
|
41
103
|
)
|
|
42
104
|
},
|
|
43
105
|
},
|
|
@@ -302,6 +302,11 @@ export default {
|
|
|
302
302
|
method: this.renderPanels,
|
|
303
303
|
arg: [],
|
|
304
304
|
})
|
|
305
|
+
methodList.push({
|
|
306
|
+
name: 'updateModuleFieldsVisibility',
|
|
307
|
+
method: this.updateModuleFieldsVisibility,
|
|
308
|
+
arg: [this.areModuleFieldsVisible],
|
|
309
|
+
})
|
|
305
310
|
break
|
|
306
311
|
case 'addPointToPolygon': //params.polygon,index
|
|
307
312
|
case 'removeObstacle': //params:obstacle
|
|
@@ -420,13 +425,6 @@ export default {
|
|
|
420
425
|
arg: [],
|
|
421
426
|
})
|
|
422
427
|
break
|
|
423
|
-
case 'updateIsYearlyShadingHeatmapActive':
|
|
424
|
-
methodList.push({
|
|
425
|
-
name: 'updateModuleFieldsVisibility',
|
|
426
|
-
method: this.updateModuleFieldsVisibility,
|
|
427
|
-
arg: [!params.value],
|
|
428
|
-
})
|
|
429
|
-
break
|
|
430
428
|
case 'updateModuleFieldsVisibility':
|
|
431
429
|
methodList.push({
|
|
432
430
|
name: 'updateModuleFieldsVisibility',
|
package/src/store/hydrateData.js
CHANGED
|
@@ -2,13 +2,18 @@
|
|
|
2
2
|
import {
|
|
3
3
|
Polygon,
|
|
4
4
|
updateComputedGeometryPolygon,
|
|
5
|
-
getRoofMarginOutline,
|
|
6
5
|
getObstacleMarginOutline,
|
|
7
|
-
|
|
6
|
+
multiplyVector,
|
|
7
|
+
addVector,
|
|
8
|
+
Vector,
|
|
8
9
|
} from '@eturnity/eturnity_maths'
|
|
9
10
|
import OverlayLayer from '../Overlay/OverlayLayer'
|
|
10
11
|
import getLayers from '../utils/layers'
|
|
11
12
|
import { UpdateRoofObstacleRelations } from '../helper/UpdateRoofObstacleRelations'
|
|
13
|
+
import {
|
|
14
|
+
updateModuleFieldFittingPanels,
|
|
15
|
+
UpdateRoofModuleFieldRelations,
|
|
16
|
+
} from '../helper/UpdateRoofModuleFieldRelations'
|
|
12
17
|
function sanitizedOutline(outline) {
|
|
13
18
|
return outline.reduce((accumulator, currentValue) => {
|
|
14
19
|
if (
|
|
@@ -24,6 +29,33 @@ function sanitizedOutline(outline) {
|
|
|
24
29
|
return accumulator
|
|
25
30
|
}, [])
|
|
26
31
|
}
|
|
32
|
+
export function getModuleOutline({ module, grid, offset }) {
|
|
33
|
+
// const convertedOffset =
|
|
34
|
+
// offset == 33 ? 100 / 3 : offset == 66 ? 200 / 3 : offset
|
|
35
|
+
|
|
36
|
+
const rowIndex = module.row_index
|
|
37
|
+
const colIndex = module.col_index
|
|
38
|
+
const gridRowVector = new Vector(grid.grid_row_vector)
|
|
39
|
+
const gridColVector = new Vector(grid.grid_column_vector)
|
|
40
|
+
// const rowOffsetVector = multiplyVector(
|
|
41
|
+
// (convertedOffset * rowIndex) / 100,
|
|
42
|
+
// gridColVector
|
|
43
|
+
// )
|
|
44
|
+
const panelHeightVector = new Vector(grid.panel_height_vector)
|
|
45
|
+
const panelWidthVector = new Vector(grid.panel_width_vector)
|
|
46
|
+
const gridOrigin = new Vector(grid.grid_origin)
|
|
47
|
+
//const offsetOrigin = addVector(gridOrigin, rowOffsetVector)
|
|
48
|
+
const localA = addVector(
|
|
49
|
+
multiplyVector(rowIndex, gridRowVector),
|
|
50
|
+
multiplyVector(colIndex, gridColVector)
|
|
51
|
+
)
|
|
52
|
+
const A = addVector(gridOrigin, localA)
|
|
53
|
+
const B = addVector(A, panelHeightVector)
|
|
54
|
+
const C = addVector(A, addVector(panelHeightVector, panelWidthVector))
|
|
55
|
+
const D = addVector(A, panelWidthVector)
|
|
56
|
+
return [A, B, C, D]
|
|
57
|
+
}
|
|
58
|
+
|
|
27
59
|
export async function hydratePolygons({
|
|
28
60
|
roofsResponse = [],
|
|
29
61
|
obstaclesResponse = [],
|
|
@@ -128,6 +160,7 @@ export async function hydratePolygons({
|
|
|
128
160
|
moduleField.mountingData = {}
|
|
129
161
|
moduleField.pvData.module_texture_version_id =
|
|
130
162
|
moduleFieldResp.module_texture_version_id
|
|
163
|
+
moduleField.pvData.backsheet_color = moduleFieldResp.backsheet_color
|
|
131
164
|
moduleField.data = {}
|
|
132
165
|
moduleField.data.texture_img_url = moduleFieldResp.texture_img_url
|
|
133
166
|
moduleField.data.col_spacing_mm = moduleFieldResp.col_spacing_mm
|
|
@@ -138,7 +171,8 @@ export async function hydratePolygons({
|
|
|
138
171
|
moduleField.data.row_spacing_valley_mm =
|
|
139
172
|
moduleFieldResp.row_spacing_valley_mm
|
|
140
173
|
moduleField.data.offset_percent = moduleFieldResp.offset_percent
|
|
141
|
-
moduleField.data.fitting_panel_area_m2 =
|
|
174
|
+
moduleField.data.fitting_panel_area_m2 =
|
|
175
|
+
moduleFieldResp.fitting_panel_area_m2
|
|
142
176
|
moduleField.data.has_fitting_panels = moduleFieldResp.has_fitting_panels
|
|
143
177
|
moduleField.data.panel_orientation = moduleFieldResp.panel_orientation
|
|
144
178
|
moduleField.data.panel_direction_degrees =
|
|
@@ -166,56 +200,45 @@ export async function hydratePolygons({
|
|
|
166
200
|
moduleField.pvModuleId = moduleFieldResp.pv_module_id
|
|
167
201
|
moduleField.mountingSystemId = moduleFieldResp.mounting_system_id
|
|
168
202
|
|
|
203
|
+
moduleField.data.moduleGrids = moduleFieldResp.module_grids
|
|
204
|
+
|
|
169
205
|
const modules = []
|
|
170
|
-
moduleFieldResp.
|
|
171
|
-
modules.
|
|
172
|
-
...module,
|
|
173
|
-
status: module.status || 'active',
|
|
174
|
-
clipped: module.clipped === undefined ? false : module.clipped,
|
|
175
|
-
})
|
|
176
|
-
})
|
|
177
|
-
if (moduleFieldResp.user_deactivated_modules) {
|
|
178
|
-
moduleFieldResp.user_deactivated_modules.forEach((module) => {
|
|
206
|
+
moduleFieldResp.module_grids.forEach((grid, gridIndex) => {
|
|
207
|
+
grid.modules.forEach((module) => {
|
|
179
208
|
modules.push({
|
|
180
209
|
...module,
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
modules
|
|
188
|
-
.filter((m) => !m.clipped)
|
|
189
|
-
.forEach((module) => {
|
|
190
|
-
const outline = module.outline.map((p) => {
|
|
191
|
-
return { x: p[0], y: p[1], z: p[2] }
|
|
210
|
+
outline: getModuleOutline({
|
|
211
|
+
module,
|
|
212
|
+
grid,
|
|
213
|
+
offset: moduleFieldResp.offset_percent,
|
|
214
|
+
}),
|
|
215
|
+
gridIndex: gridIndex,
|
|
192
216
|
})
|
|
193
|
-
let panel = new Polygon(outline, '')
|
|
194
|
-
panel.id = module.module_uuid
|
|
195
|
-
panel.row_index = module.row_index
|
|
196
|
-
panel.col_index = module.col_index
|
|
197
|
-
panel.status = module.status
|
|
198
|
-
panel.clipped = module.clipped
|
|
199
|
-
panel.moduleField = moduleField
|
|
200
|
-
panel.poolGroupUuid = module.project_variant_pool_group_uuid
|
|
201
|
-
if (panel.poolGroupUuid) {
|
|
202
|
-
panel.poolGroupUuidColor = `#${panel.poolGroupUuid.slice(0, 6)}`
|
|
203
|
-
}
|
|
204
|
-
panel.available = true
|
|
205
|
-
switch (module.status) {
|
|
206
|
-
case 'active':
|
|
207
|
-
panel.layer = 'panel'
|
|
208
|
-
MFpanels.push(panel)
|
|
209
|
-
panels.push(panel)
|
|
210
|
-
break
|
|
211
|
-
case 'user_deactivated':
|
|
212
|
-
panel.layer = 'user_deactivated_panel'
|
|
213
|
-
MFuserDeactivatedPanels.push(panel)
|
|
214
|
-
userDeactivatedPanels.push(panel)
|
|
215
|
-
break
|
|
216
|
-
}
|
|
217
|
-
panel = updateComputedGeometryPolygon(panel)
|
|
218
217
|
})
|
|
218
|
+
})
|
|
219
|
+
|
|
220
|
+
modules.forEach((module) => {
|
|
221
|
+
const panel = new Polygon(module.outline, '')
|
|
222
|
+
panel.id = module.module_uuid
|
|
223
|
+
panel.row_index = module.row_index
|
|
224
|
+
panel.col_index = module.col_index
|
|
225
|
+
panel.is_active = module.is_active
|
|
226
|
+
panel.moduleField = moduleField
|
|
227
|
+
panel.poolGroupUuid = module.project_variant_pool_group_uuid
|
|
228
|
+
if (panel.poolGroupUuid) {
|
|
229
|
+
panel.poolGroupUuidColor = `#${panel.poolGroupUuid.slice(0, 6)}`
|
|
230
|
+
}
|
|
231
|
+
panel.available = true
|
|
232
|
+
if (module.is_active) {
|
|
233
|
+
panel.layer = 'panel'
|
|
234
|
+
MFpanels.push(panel)
|
|
235
|
+
panels.push(panel)
|
|
236
|
+
} else {
|
|
237
|
+
panel.layer = 'user_deactivated_panel'
|
|
238
|
+
MFuserDeactivatedPanels.push(panel)
|
|
239
|
+
userDeactivatedPanels.push(panel)
|
|
240
|
+
}
|
|
241
|
+
})
|
|
219
242
|
|
|
220
243
|
const roof = roofs.find((r) => r.id == moduleFieldResp.roof_uuid)
|
|
221
244
|
if (roof) {
|
|
@@ -295,4 +318,10 @@ export async function hydrateData({ state, commit }, data) {
|
|
|
295
318
|
state.polygons = hydratationResult.polygons
|
|
296
319
|
|
|
297
320
|
state = UpdateRoofObstacleRelations(state)
|
|
321
|
+
state = UpdateRoofModuleFieldRelations(state)
|
|
322
|
+
state.polygons
|
|
323
|
+
.filter((poly) => poly.layer == 'moduleField')
|
|
324
|
+
.forEach((moduleField) => {
|
|
325
|
+
updateModuleFieldFittingPanels(moduleField)
|
|
326
|
+
})
|
|
298
327
|
}
|