@eturnity/eturnity_maths 1.0.6 → 1.0.7
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
package/src/objects/Polygon.js
CHANGED
|
@@ -226,7 +226,7 @@ export class Polygon {
|
|
|
226
226
|
base_line_index: this.data.base_line_index,
|
|
227
227
|
justify_percent: this.data.justify_percent,
|
|
228
228
|
|
|
229
|
-
|
|
229
|
+
number_of_panels_override:this.data.number_of_panels_override,
|
|
230
230
|
number_of_panel:this.data.number_of_panels,
|
|
231
231
|
yearly_yield_manual_entr:this.data.yearly_yield_manual_entry,
|
|
232
232
|
yearly_yield_kwh_kw:this.data.yearly_yield_kwh_kwp,
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
isInsidePolygon,
|
|
3
|
-
verticalProjectionOnPlane,
|
|
4
|
-
} from '../../geometry'
|
|
5
|
-
//this function just update the "roof" and "moduleField(s)" properties of panels,moduleFields and roofs
|
|
6
|
-
export function UpdateRoofModuleFieldRelations(state) {
|
|
7
|
-
const roofPolygons = state.polygons.filter((poly) => poly.layer == 'roof')
|
|
8
|
-
const moduleFieldPolygons = state.polygons.filter(
|
|
9
|
-
(poly) => poly.layer == 'moduleField'
|
|
10
|
-
)
|
|
11
|
-
const panelPolygons = state.polygons.filter((poly) =>
|
|
12
|
-
['panel', 'user_deactivated_panel'].includes(poly.layer)
|
|
13
|
-
)
|
|
14
|
-
//let's remove all moduleFields from roofs
|
|
15
|
-
roofPolygons.forEach((roofPolygon) => {
|
|
16
|
-
//breaking circular reference for memory management
|
|
17
|
-
for (let k in roofPolygon.moduleFields) {
|
|
18
|
-
roofPolygon.moduleFields[k] = null
|
|
19
|
-
}
|
|
20
|
-
roofPolygon.moduleFields = []
|
|
21
|
-
})
|
|
22
|
-
moduleFieldPolygons.forEach((moduleFieldPolygon) => {
|
|
23
|
-
moduleFieldPolygon.roof = null
|
|
24
|
-
})
|
|
25
|
-
panelPolygons.forEach((panelPolygon) => {
|
|
26
|
-
panelPolygon.roof = null
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
for (let k in moduleFieldPolygons) {
|
|
30
|
-
const moduleField = moduleFieldPolygons[k]
|
|
31
|
-
//check if everypoint is in the same roof and if they are not too far from the flat surface.(at least above)
|
|
32
|
-
const roofPolygonCandidates = roofPolygons.filter((roof) =>
|
|
33
|
-
{
|
|
34
|
-
return moduleField.outline.every(p=>isInsidePolygon(p, roof.margins.innerOutline))
|
|
35
|
-
}
|
|
36
|
-
)
|
|
37
|
-
//roofs on roof can lead to multiple roof under a point. moduleField is in the smallest
|
|
38
|
-
let smallestRoof = null
|
|
39
|
-
for (let roof of roofPolygonCandidates) {
|
|
40
|
-
if (!smallestRoof || smallestRoof.area > roof.area) {
|
|
41
|
-
smallestRoof = roof
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
let roofPolygon = smallestRoof
|
|
45
|
-
|
|
46
|
-
if (!roofPolygon) {
|
|
47
|
-
//no roof found under first node of moduleField => moduleField will be deleted
|
|
48
|
-
continue
|
|
49
|
-
}
|
|
50
|
-
let moduleFieldBelongsToRoof = true
|
|
51
|
-
moduleField.outline.forEach((p) => {
|
|
52
|
-
const distanceToFlatRoof =
|
|
53
|
-
p.z -
|
|
54
|
-
verticalProjectionOnPlane(
|
|
55
|
-
p,
|
|
56
|
-
roofPolygon.normalVector,
|
|
57
|
-
roofPolygon.flatOutline[0]
|
|
58
|
-
).z
|
|
59
|
-
if (
|
|
60
|
-
!isInsidePolygon(p, roofPolygon.margins.innerOutline) ||
|
|
61
|
-
distanceToFlatRoof < -1 ||
|
|
62
|
-
distanceToFlatRoof > 50
|
|
63
|
-
) {
|
|
64
|
-
// one point from moduleField is not inside the roof or too far from it's flat surface => moduleField will be deleted
|
|
65
|
-
moduleFieldBelongsToRoof = false
|
|
66
|
-
}
|
|
67
|
-
})
|
|
68
|
-
if (moduleFieldBelongsToRoof) {
|
|
69
|
-
roofPolygon.moduleFields.push(moduleField)
|
|
70
|
-
moduleField.roof = roofPolygon
|
|
71
|
-
moduleField.panels.forEach((panel) => (panel.roof = roofPolygon))
|
|
72
|
-
panelPolygons.forEach((p) => {
|
|
73
|
-
if (p.moduleField.id == moduleField.id) {
|
|
74
|
-
p.roof = roofPolygon
|
|
75
|
-
}
|
|
76
|
-
})
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
let newPolygons = state.polygons.map((p) => {
|
|
81
|
-
if (
|
|
82
|
-
!['roof', 'moduleField', 'panel', 'user_deactivated_panel'].includes(
|
|
83
|
-
p.layer
|
|
84
|
-
)
|
|
85
|
-
)
|
|
86
|
-
return p
|
|
87
|
-
if (p.layer == 'roof') return roofPolygons.find((r) => r.id == p.id)
|
|
88
|
-
if (p.layer == 'moduleField')
|
|
89
|
-
return moduleFieldPolygons.find((mf) => mf.id == p.id)
|
|
90
|
-
if (['panel', 'user_deactivated_panel'].includes(p.layer))
|
|
91
|
-
return panelPolygons.find((panel) => panel.id == p.id)
|
|
92
|
-
})
|
|
93
|
-
state = { ...state, polygons: newPolygons }
|
|
94
|
-
state = removeModuleFieldAndPanelsOnNoOrMultipleRoofs(state)
|
|
95
|
-
return state
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
export function removeModuleFieldAndPanelsOnNoOrMultipleRoofs(state) {
|
|
99
|
-
const remainingPolygons = state.polygons.filter((polygon) =>
|
|
100
|
-
['roof', 'obstacle'].includes(polygon.layer)
|
|
101
|
-
)
|
|
102
|
-
const remainingModuleFields = state.polygons.filter(
|
|
103
|
-
(polygon) => polygon.layer == 'moduleField' && !!polygon.roof
|
|
104
|
-
)
|
|
105
|
-
const remainingPanels = state.polygons.filter(
|
|
106
|
-
(polygon) => polygon.layer == 'panel' && !!polygon.roof
|
|
107
|
-
)
|
|
108
|
-
const remainingUserDeactivatedPanels = state.polygons.filter(
|
|
109
|
-
(polygon) => polygon.layer == 'user_deactivated_panel' && !!polygon.roof
|
|
110
|
-
)
|
|
111
|
-
|
|
112
|
-
state.polygons = [
|
|
113
|
-
...remainingPolygons,
|
|
114
|
-
...remainingModuleFields,
|
|
115
|
-
...remainingPanels,
|
|
116
|
-
...remainingUserDeactivatedPanels
|
|
117
|
-
]
|
|
118
|
-
return state
|
|
119
|
-
}
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
verticalProjectionOnPlane,
|
|
3
|
-
calculateArea
|
|
4
|
-
} from '../../geometry'
|
|
5
|
-
import {
|
|
6
|
-
intersectOutlines
|
|
7
|
-
} from '../../intersectionPolygon'
|
|
8
|
-
//this function just update the "roof" and "holes" properties of roofs and obstacles
|
|
9
|
-
export function UpdateRoofObstacleRelations(state,updateVersionEnable=true) {
|
|
10
|
-
//let's remove all holes from roofs which are not obstacle then check for every obstacle and add them to roofs
|
|
11
|
-
const roofPolygons = state.polygons.filter((poly) => poly.layer == 'roof')
|
|
12
|
-
const initialRelation={}
|
|
13
|
-
|
|
14
|
-
roofPolygons.forEach((roofPolygon) => {
|
|
15
|
-
initialRelation[roofPolygon.id]=[]
|
|
16
|
-
//breaking circular reference for memory management
|
|
17
|
-
for (let k in roofPolygon.holes) {
|
|
18
|
-
initialRelation[roofPolygon.id].push(roofPolygon.holes.id)
|
|
19
|
-
roofPolygon.holes[k] = null
|
|
20
|
-
}
|
|
21
|
-
roofPolygon.holes = []
|
|
22
|
-
})
|
|
23
|
-
const holePolygons = state.polygons.filter((poly) =>
|
|
24
|
-
['roof','obstacle'].includes(poly.layer)
|
|
25
|
-
)
|
|
26
|
-
|
|
27
|
-
holePolygons.forEach((obstacle) => {
|
|
28
|
-
//breaking circular reference for memory management
|
|
29
|
-
for (let k in obstacle.roofs) {
|
|
30
|
-
obstacle.roofs[k] = null
|
|
31
|
-
}
|
|
32
|
-
obstacle.roofs = []
|
|
33
|
-
|
|
34
|
-
let roofsWithObstacle=roofPolygons.filter(roof=>{
|
|
35
|
-
let intersection=intersectOutlines(obstacle.outline,roof.outline)[0]||[]
|
|
36
|
-
if(intersection.length==0)return false
|
|
37
|
-
if(obstacle.layer=='obstacle')return true
|
|
38
|
-
|
|
39
|
-
let deltaArea=calculateArea(roof.outline)-calculateArea(intersection)
|
|
40
|
-
if(deltaArea<100)return false
|
|
41
|
-
return true
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
let heightReference = 0
|
|
45
|
-
for (let roof of roofsWithObstacle) {
|
|
46
|
-
|
|
47
|
-
heightReference = obstacle.outline.reduce((acc,cur)=>{
|
|
48
|
-
acc=Math.max(
|
|
49
|
-
acc,
|
|
50
|
-
verticalProjectionOnPlane(cur, roof.normalVector, roof.flatOutline[0])
|
|
51
|
-
.z
|
|
52
|
-
)
|
|
53
|
-
return acc
|
|
54
|
-
},0)
|
|
55
|
-
|
|
56
|
-
if (!obstacle.roofs.map((r) => r.id).includes(roof.id) && obstacle.id!=roof.id) {
|
|
57
|
-
obstacle.roofs.push(roof)
|
|
58
|
-
}
|
|
59
|
-
if (!roof.holes.map((h) => h.id).includes(obstacle.id) && obstacle.id!=roof.id) {
|
|
60
|
-
roof.holes.push(obstacle)
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
obstacle.heightReference = heightReference
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
roofPolygons.forEach((roof)=>{
|
|
69
|
-
if(roof.holes.map(h=>h.id).sort().join()!=initialRelation[roof.id].sort().join()){
|
|
70
|
-
if(updateVersionEnable){
|
|
71
|
-
roof.version++
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
state = removeStandaloneObstacles(state)
|
|
77
|
-
|
|
78
|
-
return state
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export function removeStandaloneObstacles(state) {
|
|
82
|
-
state.polygons = state.polygons.filter(
|
|
83
|
-
(polygon) => polygon.layer != 'obstacle' || polygon.roofs.length > 0
|
|
84
|
-
)
|
|
85
|
-
return state
|
|
86
|
-
}
|