@eturnity/eturnity_maths 7.2.3 → 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
CHANGED
package/src/config.js
CHANGED
|
@@ -5,7 +5,7 @@ export const snapToPointTolerance = 15
|
|
|
5
5
|
export const snapToIntersectionPointTolerance = 15
|
|
6
6
|
export const snapToLineTolerance = 10
|
|
7
7
|
export const distanceToCloseNode = 70
|
|
8
|
-
export const mmTolerance=
|
|
8
|
+
export const mmTolerance=1
|
|
9
9
|
export const earthRadius=6371008
|
|
10
10
|
|
|
11
11
|
export const layerColors = {
|
package/src/geometry.js
CHANGED
|
@@ -15,13 +15,22 @@ import {Point} from './objects/Point'
|
|
|
15
15
|
import {Line} from './objects/Line'
|
|
16
16
|
import concaveman from 'concaveman'
|
|
17
17
|
|
|
18
|
-
export function
|
|
18
|
+
export function getConcaveOutlines(selectedPanels,onePanelOutline){
|
|
19
|
+
let buckets=groupAdjacentObjects(selectedPanels)
|
|
20
|
+
const outlines = []
|
|
21
|
+
for(let bucketIndex=0;bucketIndex<buckets.length;bucketIndex++){
|
|
22
|
+
outlines.push(getConcaveOutline(selectedPanels.filter((p,i)=>buckets[bucketIndex].includes(i)),onePanelOutline))
|
|
23
|
+
}
|
|
24
|
+
return {outlines,buckets}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function getConcaveOutline(selectedPanels,onePanelOutline){
|
|
19
28
|
const points = selectedPanels.reduce((acc, cur) => {
|
|
20
29
|
acc.push(...cur.outline.map((p) => [p.x, p.y]))
|
|
21
30
|
return acc
|
|
22
31
|
}, [])
|
|
23
|
-
let AB = getDistanceBetweenPoints(
|
|
24
|
-
let AD = getDistanceBetweenPoints(
|
|
32
|
+
let AB = getDistanceBetweenPoints(onePanelOutline[0], onePanelOutline[1])
|
|
33
|
+
let AD = getDistanceBetweenPoints(onePanelOutline[0], onePanelOutline[3])
|
|
25
34
|
let longEdgeLength = Math.max(AB, AD)+100
|
|
26
35
|
var concaveResult = concaveman(points, 1, longEdgeLength)
|
|
27
36
|
concaveResult.pop()
|
|
@@ -719,9 +728,54 @@ export function get3DDistanceBetweenPoints(firstPoint, secondPoint) {
|
|
|
719
728
|
const det = (B.x - A.x) * (C.y - A.y) - (C.x - A.x) * (B.y - A.y)
|
|
720
729
|
return det < 0
|
|
721
730
|
}
|
|
722
|
-
|
|
731
|
+
export function groupAdjacentObjects(objects){
|
|
732
|
+
if(!objects || objects.length==0) return []
|
|
733
|
+
// objects with 2D indexes
|
|
734
|
+
// Check if the objects form an adjacent group
|
|
735
|
+
let numberOfObjects=objects.length
|
|
736
|
+
let indexList=Array.from({length: numberOfObjects}, (e, i)=> i)
|
|
737
|
+
let buckets = []
|
|
738
|
+
let inBucket=0
|
|
739
|
+
while (inBucket<objects.length)
|
|
740
|
+
{
|
|
741
|
+
let detatchedIndex=indexList.find(i=>!buckets.flat().includes(i))
|
|
742
|
+
if(detatchedIndex==null) break
|
|
743
|
+
let queue = [detatchedIndex]
|
|
744
|
+
let visited = []
|
|
745
|
+
while (queue.length > 0) {
|
|
746
|
+
const currentObjectIndex = queue.pop()
|
|
747
|
+
if (visited.indexOf(currentObjectIndex) == -1) {
|
|
748
|
+
//if next queued index hasn't been visited, we mark it as visited and we collect all neighbourg to queue
|
|
749
|
+
visited.push(currentObjectIndex)
|
|
750
|
+
let x = objects[currentObjectIndex].index[0]
|
|
751
|
+
let y = objects[currentObjectIndex].index[1]
|
|
752
|
+
const left = objects.findIndex(
|
|
753
|
+
(o) => o.index[0] == x - 1 && o.index[1] == y
|
|
754
|
+
)
|
|
755
|
+
const right = objects.findIndex(
|
|
756
|
+
(o) => o.index[0] == x + 1 && o.index[1] == y
|
|
757
|
+
)
|
|
758
|
+
const top = objects.findIndex(
|
|
759
|
+
(o) => o.index[0] == x && o.index[1] == y - 1
|
|
760
|
+
)
|
|
761
|
+
const bottom = objects.findIndex(
|
|
762
|
+
(o) => o.index[0] == x && o.index[1] == y + 1
|
|
763
|
+
)
|
|
764
|
+
if (left != -1 && visited.indexOf(left) == -1) queue.push(left)
|
|
765
|
+
if (right != -1 && visited.indexOf(right) == -1) queue.push(right)
|
|
766
|
+
if (top != -1 && visited.indexOf(top) == -1) queue.push(top)
|
|
767
|
+
if (bottom != -1 && visited.indexOf(bottom) == -1) queue.push(bottom)
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
inBucket+=visited.length
|
|
771
|
+
buckets.push(visited)
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
return buckets
|
|
775
|
+
}
|
|
723
776
|
// Function to check if two indexes are adjacent
|
|
724
777
|
export function areAdjacent(objects) {
|
|
778
|
+
if(!objects || objects.length==0) return false
|
|
725
779
|
// objects with 2D indexes
|
|
726
780
|
// Check if the objects form an adjacent group
|
|
727
781
|
let visited = []
|
|
@@ -73,6 +73,7 @@ export function logicOperationOnPolygons(outline1,outline2,mode='intersect')
|
|
|
73
73
|
return {outline:[p,fig2[(index+1)%fig2.length]]}
|
|
74
74
|
})
|
|
75
75
|
let intersections = getIntersections({outline:fig1}, edges)
|
|
76
|
+
|
|
76
77
|
//2. gather all nodes+intersection in a list[[x,y],[x,y]]
|
|
77
78
|
const nodeList = getNodeList(intersections, edges, {outline:fig1})
|
|
78
79
|
//3. generate all edges not cut, those cut and those from construction polyline
|
|
@@ -86,9 +87,13 @@ export function logicOperationOnPolygons(outline1,outline2,mode='intersect')
|
|
|
86
87
|
1
|
|
87
88
|
)
|
|
88
89
|
//4. run planar-face-discovery to get all cycles and rebuild our polygons
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
90
|
+
try{
|
|
91
|
+
const outlineList = getOutlineList(nodeList, edgeList)
|
|
92
|
+
return filterPolygons(outlineList, fig1, fig2, mode)
|
|
93
|
+
}catch(err){
|
|
94
|
+
console.error("error with getOutlineList",nodeList, edgeList,err)
|
|
95
|
+
return []
|
|
96
|
+
}
|
|
92
97
|
}
|
|
93
98
|
|
|
94
99
|
function filterPolygons(polygons, fig1, fig2, mode) {
|
package/src/objects/Polygon.js
CHANGED
|
@@ -166,6 +166,7 @@ export class Polygon {
|
|
|
166
166
|
extraSerialization.mountingData = this.mountingData?{...this.mountingData}:null
|
|
167
167
|
extraSerialization.modules = modules
|
|
168
168
|
extraSerialization.needsOptimisation = this.needsOptimisation
|
|
169
|
+
extraSerialization.priority = this.priority
|
|
169
170
|
|
|
170
171
|
} else if (this.layer == 'panel') {
|
|
171
172
|
extraSerialization.index = this.index
|
|
@@ -210,27 +211,7 @@ export class Polygon {
|
|
|
210
211
|
if (!this.userDeactivatedPanels) {
|
|
211
212
|
this.userDeactivatedPanels = []
|
|
212
213
|
}
|
|
213
|
-
const modules = this.
|
|
214
|
-
return {
|
|
215
|
-
index: p.index,
|
|
216
|
-
outline: p.outline.map((v) => [v.x, v.y, v.z]),
|
|
217
|
-
status: p.status || "active",
|
|
218
|
-
clipped: p.clipped === undefined ? false : p.clipped
|
|
219
|
-
}
|
|
220
|
-
})
|
|
221
|
-
const user_deactivated_modules = this.userDeactivatedPanels.map((p) => {
|
|
222
|
-
return {
|
|
223
|
-
index: p.index,
|
|
224
|
-
outline: p.outline.map((v) => [v.x, v.y, v.z]),
|
|
225
|
-
}
|
|
226
|
-
})
|
|
227
|
-
user_deactivated_modules.forEach(p=>{
|
|
228
|
-
modules.push({
|
|
229
|
-
...p,
|
|
230
|
-
status: p.status || "user_deactivated",
|
|
231
|
-
clipped: p.clipped === undefined ? false : p.clipped
|
|
232
|
-
})
|
|
233
|
-
})
|
|
214
|
+
const modules = this.data.modules
|
|
234
215
|
return {
|
|
235
216
|
module_field_uuid: this.id,
|
|
236
217
|
roof_uuid: this.roof.id,
|
|
@@ -16,9 +16,10 @@ import {
|
|
|
16
16
|
isAlmostSamePoint2D,
|
|
17
17
|
getDistanceBetweenPoints
|
|
18
18
|
} from '../../geometry'
|
|
19
|
-
import { maximumGapLimit } from '../../config'
|
|
19
|
+
import { maximumGapLimit, mmTolerance } from '../../config'
|
|
20
20
|
import { SVD } from 'svd-js'
|
|
21
21
|
import {updateMarginOutlinePolygon} from './AddMargin'
|
|
22
|
+
import { isSelfIntersecting } from '../../intersectionPolygon'
|
|
22
23
|
|
|
23
24
|
//This function calculate derived field from polygon outline and margin outline
|
|
24
25
|
export function updateComputedGeometryState(state) {
|
|
@@ -100,28 +101,41 @@ export function updateComputedGeometryPolygon(polygon) {
|
|
|
100
101
|
export function calculateValidOutlineFromPolygon(outline){
|
|
101
102
|
//check if two nodes are same
|
|
102
103
|
const nodeIndexToSplit=[]
|
|
104
|
+
const nodesToRemove=[]
|
|
103
105
|
for(let k=0;k<outline.length-1;k++){
|
|
104
106
|
for(let i=k+1;i<outline.length;i++){
|
|
105
|
-
if(isAlmostSamePoint2D(outline[k],outline[i],
|
|
106
|
-
|
|
107
|
+
if(isAlmostSamePoint2D(outline[k],outline[i],2*mmTolerance)){
|
|
108
|
+
if(i==k+1){
|
|
109
|
+
nodesToRemove.push(i)
|
|
110
|
+
}else{
|
|
111
|
+
nodeIndexToSplit.push([k,i])
|
|
112
|
+
}
|
|
107
113
|
}
|
|
108
114
|
}
|
|
109
115
|
}
|
|
116
|
+
|
|
110
117
|
for(let coupleToSplit of nodeIndexToSplit){
|
|
111
118
|
const A = outline[(coupleToSplit[0]-1+outline.length)%outline.length]
|
|
112
119
|
const B = outline[coupleToSplit[0]]
|
|
113
120
|
const C = outline[(coupleToSplit[0]+1)%outline.length]
|
|
114
|
-
|
|
115
|
-
|
|
121
|
+
const D = outline[(coupleToSplit[1]-1+outline.length)%outline.length]
|
|
122
|
+
const E = outline[coupleToSplit[1]]
|
|
123
|
+
const F = outline[(coupleToSplit[1]+1)%outline.length]
|
|
124
|
+
let u = normalizedVectorTowardInsideAngle(A,B,C)
|
|
125
|
+
let v = normalizedVectorTowardInsideAngle(D,E,F)
|
|
126
|
+
|
|
116
127
|
outline[coupleToSplit[0]] = {
|
|
117
|
-
...addVector(multiplyVector(-
|
|
128
|
+
...addVector(multiplyVector(-mmTolerance,u),B),
|
|
118
129
|
z:outline[coupleToSplit[0]].z
|
|
119
130
|
}
|
|
120
131
|
outline[coupleToSplit[1]] = {
|
|
121
|
-
...addVector(multiplyVector(
|
|
132
|
+
...addVector(multiplyVector(mmTolerance,v),E),
|
|
122
133
|
z:outline[coupleToSplit[1]].z
|
|
123
134
|
}
|
|
124
135
|
}
|
|
136
|
+
for(let index=nodesToRemove.length-1;index>=0;index--){
|
|
137
|
+
outline.splice(nodesToRemove[index],1)
|
|
138
|
+
}
|
|
125
139
|
return outline
|
|
126
140
|
}
|
|
127
141
|
|