@eturnity/eturnity_maths 9.19.0 → 9.25.0-EPDM-19998.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 +13 -12
- package/src/config.js +0 -5
- package/src/geometry.js +39 -0
- package/src/objects/Polygon.js +7 -9
- package/src/objects/derivedState/updateComputedGeometryPolygon.js +0 -1
- package/src/objects/hydrate.js +0 -5
- package/src/panelFunctions.js +34 -0
- package/src/plane.js +15 -1
package/package.json
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eturnity/eturnity_maths",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.25.0-EPDM-19998.0",
|
|
4
4
|
"author": "Eturnity Team",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"private": false,
|
|
7
|
+
"scripts": {
|
|
8
|
+
"test": "jest",
|
|
9
|
+
"prepare": "husky",
|
|
10
|
+
"lint": "eslint --fix --debug --ext .js,.vue .",
|
|
11
|
+
"merge-remote-master": "node scripts/merge-master.js"
|
|
12
|
+
},
|
|
7
13
|
"repository": {
|
|
8
14
|
"type": "git",
|
|
9
15
|
"url": "git+ssh://git@bitbucket.org/eturnitydevs/eturnity_maths.git"
|
|
@@ -22,8 +28,8 @@
|
|
|
22
28
|
"uuid": "9.0.0"
|
|
23
29
|
},
|
|
24
30
|
"devDependencies": {
|
|
25
|
-
"@babel/core": "7.
|
|
26
|
-
"@babel/preset-env": "7.
|
|
31
|
+
"@babel/core": "7.22.0",
|
|
32
|
+
"@babel/preset-env": "7.22.0",
|
|
27
33
|
"babel-jest": "29.5.0",
|
|
28
34
|
"husky": "^9.1.5",
|
|
29
35
|
"@vue/eslint-config-standard": "8.0.1",
|
|
@@ -34,13 +40,8 @@
|
|
|
34
40
|
"eslint-plugin-prettier": "4.2.1",
|
|
35
41
|
"eslint-plugin-vue": "9.14.1",
|
|
36
42
|
"jest": "29.5.0",
|
|
37
|
-
"prettier": "
|
|
38
|
-
"prettier-plugin-vue": "
|
|
43
|
+
"prettier": "2.8.4",
|
|
44
|
+
"prettier-plugin-vue": "1.1.6"
|
|
39
45
|
},
|
|
40
|
-
"description": ""
|
|
41
|
-
|
|
42
|
-
"test": "jest",
|
|
43
|
-
"lint": "eslint --fix --debug --ext .js,.vue .",
|
|
44
|
-
"merge-remote-master": "node scripts/merge-master.js"
|
|
45
|
-
}
|
|
46
|
-
}
|
|
46
|
+
"description": ""
|
|
47
|
+
}
|
package/src/config.js
CHANGED
|
@@ -32,11 +32,6 @@ export const layerColors = {
|
|
|
32
32
|
strokeColor: '#ffffff',
|
|
33
33
|
strokeWidth: 1,
|
|
34
34
|
},
|
|
35
|
-
user_deactivated_panel: {
|
|
36
|
-
fillColor: 'rgba(115, 115, 229, 0.1)',
|
|
37
|
-
strokeColor: 'white',
|
|
38
|
-
strokeWidth: 4,
|
|
39
|
-
},
|
|
40
35
|
selectedPanel: {
|
|
41
36
|
fillColor: '#0068DE80',
|
|
42
37
|
strokeColor: theme.colors.blue,
|
package/src/geometry.js
CHANGED
|
@@ -887,6 +887,45 @@ export function verticalProjectionOnPlane(p, n, o) {
|
|
|
887
887
|
const projectedPoint = { ...p, z: projectedHeight }
|
|
888
888
|
return projectedPoint
|
|
889
889
|
}
|
|
890
|
+
|
|
891
|
+
// 2D convex hull (Andrew's monotone chain). Input/output: array of [x, y].
|
|
892
|
+
// Returns the hull in counter-clockwise order; passes through collinear points
|
|
893
|
+
// only at the endpoints. Used to grow a module-field outline so it encloses
|
|
894
|
+
// newly added panels.
|
|
895
|
+
export function convexHull2D(points) {
|
|
896
|
+
const pts = points
|
|
897
|
+
.map((p) => [p[0], p[1]])
|
|
898
|
+
.sort((a, b) => a[0] - b[0] || a[1] - b[1])
|
|
899
|
+
if (pts.length < 3) {
|
|
900
|
+
return pts
|
|
901
|
+
}
|
|
902
|
+
const cross = (o, a, b) =>
|
|
903
|
+
(a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0])
|
|
904
|
+
const lower = []
|
|
905
|
+
for (const p of pts) {
|
|
906
|
+
while (
|
|
907
|
+
lower.length >= 2 &&
|
|
908
|
+
cross(lower[lower.length - 2], lower[lower.length - 1], p) <= 0
|
|
909
|
+
) {
|
|
910
|
+
lower.pop()
|
|
911
|
+
}
|
|
912
|
+
lower.push(p)
|
|
913
|
+
}
|
|
914
|
+
const upper = []
|
|
915
|
+
for (let i = pts.length - 1; i >= 0; i--) {
|
|
916
|
+
const p = pts[i]
|
|
917
|
+
while (
|
|
918
|
+
upper.length >= 2 &&
|
|
919
|
+
cross(upper[upper.length - 2], upper[upper.length - 1], p) <= 0
|
|
920
|
+
) {
|
|
921
|
+
upper.pop()
|
|
922
|
+
}
|
|
923
|
+
upper.push(p)
|
|
924
|
+
}
|
|
925
|
+
lower.pop()
|
|
926
|
+
upper.pop()
|
|
927
|
+
return lower.concat(upper)
|
|
928
|
+
}
|
|
890
929
|
export function projectionOnPlaneFollowingVector(p, n, o, v) {
|
|
891
930
|
// if p belongs to (n,o) plane return p
|
|
892
931
|
const opn = dotProduct(substractVector(p, o), n)
|
package/src/objects/Polygon.js
CHANGED
|
@@ -50,6 +50,11 @@ export class Polygon {
|
|
|
50
50
|
this.isParallel = true
|
|
51
51
|
} else if (this.layer == 'roof') {
|
|
52
52
|
this.moduleFields = []
|
|
53
|
+
} else if (['moduleField', 'tmpModuleField'].includes(this.layer)) {
|
|
54
|
+
// Transient validation state — never serialized / sent to BE.
|
|
55
|
+
this.warnings = []
|
|
56
|
+
this.hasWarnings = false
|
|
57
|
+
this.hasError = false
|
|
53
58
|
}
|
|
54
59
|
}
|
|
55
60
|
|
|
@@ -60,7 +65,6 @@ export class Polygon {
|
|
|
60
65
|
})
|
|
61
66
|
if (['tmpModuleField', 'moduleField'].includes(this.layer)) {
|
|
62
67
|
polygon.panels = []
|
|
63
|
-
polygon.userDeactivatedPanels = []
|
|
64
68
|
polygon.data?.moduleGrids?.forEach((grid) => {
|
|
65
69
|
grid.project_variant_module_grid_3d_id = null
|
|
66
70
|
})
|
|
@@ -394,10 +398,7 @@ export class Polygon {
|
|
|
394
398
|
extraSerialization.needsOptimisation = this.needsOptimisation
|
|
395
399
|
extraSerialization.priority = this.priority
|
|
396
400
|
} else if (this.layer == 'panel') {
|
|
397
|
-
extraSerialization.
|
|
398
|
-
extraSerialization.col_index = this.col_index
|
|
399
|
-
extraSerialization.moduleField = { id: this.moduleField.id }
|
|
400
|
-
} else if (this.layer == 'user_deactivated_panel') {
|
|
401
|
+
extraSerialization.gridIndex = this.gridIndex
|
|
401
402
|
extraSerialization.row_index = this.row_index
|
|
402
403
|
extraSerialization.col_index = this.col_index
|
|
403
404
|
extraSerialization.moduleField = { id: this.moduleField.id }
|
|
@@ -442,9 +443,6 @@ export class Polygon {
|
|
|
442
443
|
if (!this.panels) {
|
|
443
444
|
this.panels = []
|
|
444
445
|
}
|
|
445
|
-
if (!this.userDeactivatedPanels) {
|
|
446
|
-
this.userDeactivatedPanels = []
|
|
447
|
-
}
|
|
448
446
|
return {
|
|
449
447
|
module_field_uuid: this.id,
|
|
450
448
|
roof_uuid: this.roof ? this.roof.id : null,
|
|
@@ -472,7 +470,7 @@ export class Polygon {
|
|
|
472
470
|
yearly_yield_kwh_kwp: this.data.yearly_yield_kwh_kwp,
|
|
473
471
|
yearly_yield_kwh_kwp_2: this.data.yearly_yield_kwh_kwp_2,
|
|
474
472
|
}
|
|
475
|
-
} else if (
|
|
473
|
+
} else if (this.layer == 'panel') {
|
|
476
474
|
return {
|
|
477
475
|
id: this.id,
|
|
478
476
|
row_index: this.row_index,
|
package/src/objects/hydrate.js
CHANGED
|
@@ -36,15 +36,10 @@ export function hydratePolygon(serializedPolygon) {
|
|
|
36
36
|
polygon.pvData = serializedPolygon.pvData
|
|
37
37
|
polygon.mountingData = serializedPolygon.mountingData
|
|
38
38
|
polygon.panels = []
|
|
39
|
-
polygon.userDeactivatedPanels = []
|
|
40
39
|
} else if (layer == 'panel') {
|
|
41
40
|
polygon.row_index = serializedPolygon.row_index
|
|
42
41
|
polygon.col_index = serializedPolygon.col_index
|
|
43
42
|
polygon.moduleField = serializedPolygon.moduleField
|
|
44
|
-
} else if (layer == 'user_deactivated_panel') {
|
|
45
|
-
polygon.row_index = serializedPolygon.row_index
|
|
46
|
-
polygon.col_index = serializedPolygon.col_index
|
|
47
|
-
polygon.moduleField = serializedPolygon.moduleField
|
|
48
43
|
} else if (layer == 'roof_plan_item') {
|
|
49
44
|
polygon.shape = 'polygon'
|
|
50
45
|
polygon.colorIndex = serializedPolygon.colorIndex
|
package/src/panelFunctions.js
CHANGED
|
@@ -1,3 +1,37 @@
|
|
|
1
|
+
// Normalise a grid vector that may be stored as a [x,y,z] array (backend
|
|
2
|
+
// format) or a {x,y,z} object. Used internally by canonicalGridCoords.
|
|
3
|
+
function _normalizeVec(v) {
|
|
4
|
+
if (Array.isArray(v)) return { x: v[0] ?? 0, y: v[1] ?? 0, z: v[2] ?? 0 }
|
|
5
|
+
return { x: v?.x ?? 0, y: v?.y ?? 0, z: v?.z ?? 0 }
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Return the canonical (row, col) position of `module` in firstGrid's
|
|
10
|
+
* coordinate system. Modules on firstGrid map 1-to-1; modules on other grids
|
|
11
|
+
* get their origin-offset projected onto firstGrid's row/column axes so that
|
|
12
|
+
* all panels of a multi-grid module field share one comparable coordinate space.
|
|
13
|
+
*
|
|
14
|
+
* Grid vectors may be stored as [x,y,z] arrays or {x,y,z} objects — both
|
|
15
|
+
* forms are normalised internally.
|
|
16
|
+
*/
|
|
17
|
+
export function canonicalGridCoords(module, grid, firstGrid) {
|
|
18
|
+
if (grid === firstGrid)
|
|
19
|
+
return { row: module.row_index, col: module.col_index }
|
|
20
|
+
const rowVec = _normalizeVec(firstGrid.grid_row_vector)
|
|
21
|
+
const colVec = _normalizeVec(firstGrid.grid_column_vector)
|
|
22
|
+
const rowLen2 = rowVec.x * rowVec.x + rowVec.y * rowVec.y + rowVec.z * rowVec.z
|
|
23
|
+
const colLen2 = colVec.x * colVec.x + colVec.y * colVec.y + colVec.z * colVec.z
|
|
24
|
+
const originA = _normalizeVec(grid.grid_origin)
|
|
25
|
+
const originB = _normalizeVec(firstGrid.grid_origin)
|
|
26
|
+
const dx = originA.x - originB.x
|
|
27
|
+
const dy = originA.y - originB.y
|
|
28
|
+
const dz = originA.z - originB.z
|
|
29
|
+
return {
|
|
30
|
+
row: (dx * rowVec.x + dy * rowVec.y + dz * rowVec.z) / rowLen2 + module.row_index,
|
|
31
|
+
col: (dx * colVec.x + dy * colVec.y + dz * colVec.z) / colLen2 + module.col_index,
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
1
35
|
export function arePanelsAdjacent(panelA, panelB) {
|
|
2
36
|
const areSameModuleField = panelA.moduleField.id == panelB.moduleField.id
|
|
3
37
|
const areVerticalyAdjacent =
|
package/src/plane.js
CHANGED
|
@@ -42,7 +42,7 @@ export function getPlaneFromPolygon(polygon) {
|
|
|
42
42
|
const origin = pointProjectionOnPlane(
|
|
43
43
|
{ x: 0, y: 0, z: 0 },
|
|
44
44
|
polygon.normalVector,
|
|
45
|
-
polygon.outline[0]
|
|
45
|
+
polygon.flatOutline?.[0] || polygon.outline[0]
|
|
46
46
|
)
|
|
47
47
|
const normalVector = polygon.normalVector
|
|
48
48
|
const { edgeDirectionVector } = getLongestEdgeData(polygon.outline)
|
|
@@ -74,3 +74,17 @@ export function getPlaneFromPolygon(polygon) {
|
|
|
74
74
|
upVector,
|
|
75
75
|
})
|
|
76
76
|
}
|
|
77
|
+
|
|
78
|
+
export function isOnSamePlane(polygon0, polygon1) {
|
|
79
|
+
const plane0 = getPlaneFromPolygon(polygon0)
|
|
80
|
+
const plane1 = getPlaneFromPolygon(polygon1)
|
|
81
|
+
if (polygon0.outline.length < polygon1.outline.length) {
|
|
82
|
+
return (polygon0.flatOutline || polygon0.outline).every((p) =>
|
|
83
|
+
plane1.isPointOnPlane(p)
|
|
84
|
+
)
|
|
85
|
+
} else {
|
|
86
|
+
return (polygon1.flatOutline || polygon1.outline).every((p) =>
|
|
87
|
+
plane0.isPointOnPlane(p)
|
|
88
|
+
)
|
|
89
|
+
}
|
|
90
|
+
}
|