@eturnity/eturnity_maths 7.2.3 → 7.4.0-EPDM-7379.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 +1 -1
- package/src/config.js +1 -1
- package/src/geometry.js +123 -31
- package/src/intersectionPolygon.js +8 -3
- package/src/objects/Circle.js +41 -3
- package/src/objects/Line.js +73 -2
- package/src/objects/Point.js +37 -1
- package/src/objects/Polygon.js +6 -22
- package/src/objects/derivedState/updateComputedGeometryPolygon.js +21 -7
- package/src/vector.js +6 -0
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()
|
|
@@ -89,7 +98,7 @@ export function getParallelLinePassingByPoint(A, B, C) {
|
|
|
89
98
|
console.error("A == B Can't make a parallel line")
|
|
90
99
|
return null
|
|
91
100
|
}
|
|
92
|
-
const D = new Point(C.x + B.x - A.x, C.y + B.y - A.y)
|
|
101
|
+
const D = new Point(C.x + B.x - A.x, C.y + B.y - A.y, C.z + B.z - A.z)
|
|
93
102
|
return new Line(C, D, '')
|
|
94
103
|
}
|
|
95
104
|
|
|
@@ -101,10 +110,15 @@ export function getDataAboutTwo3DLines(A,u,B,v){
|
|
|
101
110
|
[u.z,v.z,w.z]
|
|
102
111
|
]
|
|
103
112
|
let mInv=inverse3x3matrix(m)
|
|
113
|
+
if(!mInv){
|
|
114
|
+
return null
|
|
115
|
+
}
|
|
104
116
|
let AB=substractVector(B,A)
|
|
105
117
|
let [t1,t2,t3] = multiplyMatrices(mInv,[[AB.x],[AB.y],[AB.z]])
|
|
118
|
+
//M point on Au
|
|
106
119
|
let M=addVector(A,multiplyVector(t1,u))
|
|
107
|
-
|
|
120
|
+
//N point on Bv
|
|
121
|
+
let N=addVector(B,multiplyVector(-t2,v))
|
|
108
122
|
let distance=get3DDistanceBetweenPoints(M,N)
|
|
109
123
|
return {m,mInv,M,N,A,B,u,v,w,distance,t1,t2,t3}
|
|
110
124
|
|
|
@@ -131,11 +145,15 @@ export function get3DDistanceBetweenPoints(firstPoint, secondPoint) {
|
|
|
131
145
|
)
|
|
132
146
|
return distance
|
|
133
147
|
}
|
|
134
|
-
|
|
148
|
+
|
|
149
|
+
export function getDegreeVectors(u,v){
|
|
150
|
+
return getDegree(u,{x:0,y:0,z:0},v)
|
|
151
|
+
}
|
|
152
|
+
|
|
135
153
|
export function getDegree(H, I, J) {
|
|
136
|
-
const a =
|
|
137
|
-
const b =
|
|
138
|
-
const c =
|
|
154
|
+
const a = get3DDistanceBetweenPoints(H, I)
|
|
155
|
+
const b = get3DDistanceBetweenPoints(I, J)
|
|
156
|
+
const c = get3DDistanceBetweenPoints(H, J)
|
|
139
157
|
|
|
140
158
|
let angle = (Math.acos((a * a + b * b - c * c) / (2 * a * b)) * 180) / Math.PI
|
|
141
159
|
|
|
@@ -539,27 +557,56 @@ export function get3DDistanceBetweenPoints(firstPoint, secondPoint) {
|
|
|
539
557
|
return null
|
|
540
558
|
}
|
|
541
559
|
let P = {}
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
560
|
+
if(M.z == undefined || A.z== undefined || B.z== undefined){
|
|
561
|
+
const AM = {
|
|
562
|
+
x: M.x - A.x,
|
|
563
|
+
y: M.y - A.y
|
|
564
|
+
}
|
|
565
|
+
const AB = {
|
|
566
|
+
x: B.x - A.x,
|
|
567
|
+
y: B.y - A.y
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
const dot = AM.x * AB.x + AM.y * AB.y
|
|
571
|
+
const distanceAB = getDistanceBetweenPoints(A, B)
|
|
572
|
+
let param = -1
|
|
573
|
+
if (distanceAB == 0) {
|
|
574
|
+
//A et B sont confondu
|
|
575
|
+
console.error("A and B don't make a line : A==B")
|
|
576
|
+
P = M
|
|
577
|
+
} else {
|
|
578
|
+
// in case of 0 length line
|
|
579
|
+
const distanceAP = dot / distanceAB
|
|
580
|
+
P.x = A.x + (distanceAP * AB.x) / distanceAB
|
|
581
|
+
P.y = A.y + (distanceAP * AB.y) / distanceAB
|
|
582
|
+
}
|
|
583
|
+
}else{
|
|
584
|
+
//make 3D projection on line
|
|
585
|
+
const AM = {
|
|
586
|
+
x: M.x - A.x,
|
|
587
|
+
y: M.y - A.y,
|
|
588
|
+
z: M.z - A.z,
|
|
589
|
+
}
|
|
590
|
+
const AB = {
|
|
591
|
+
x: B.x - A.x,
|
|
592
|
+
y: B.y - A.y,
|
|
593
|
+
z: B.z - A.z
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
const dot = AM.x * AB.x + AM.y * AB.y + AM.z * AB.z
|
|
597
|
+
const distanceAB = get3DDistanceBetweenPoints(A, B)
|
|
598
|
+
let param = -1
|
|
599
|
+
if (distanceAB == 0) {
|
|
600
|
+
//A et B sont confondu
|
|
601
|
+
console.error("A and B don't make a line : A==B")
|
|
602
|
+
P = M
|
|
603
|
+
} else {
|
|
604
|
+
// in case of 0 length line
|
|
605
|
+
const distanceAP = dot / distanceAB
|
|
606
|
+
P.x = A.x + (distanceAP * AB.x) / distanceAB
|
|
607
|
+
P.y = A.y + (distanceAP * AB.y) / distanceAB
|
|
608
|
+
P.z = A.z + (distanceAP * AB.z) / distanceAB
|
|
609
|
+
}
|
|
563
610
|
}
|
|
564
611
|
//projection of the point to the line
|
|
565
612
|
return P
|
|
@@ -719,9 +766,54 @@ export function get3DDistanceBetweenPoints(firstPoint, secondPoint) {
|
|
|
719
766
|
const det = (B.x - A.x) * (C.y - A.y) - (C.x - A.x) * (B.y - A.y)
|
|
720
767
|
return det < 0
|
|
721
768
|
}
|
|
722
|
-
|
|
769
|
+
export function groupAdjacentObjects(objects){
|
|
770
|
+
if(!objects || objects.length==0) return []
|
|
771
|
+
// objects with 2D indexes
|
|
772
|
+
// Check if the objects form an adjacent group
|
|
773
|
+
let numberOfObjects=objects.length
|
|
774
|
+
let indexList=Array.from({length: numberOfObjects}, (e, i)=> i)
|
|
775
|
+
let buckets = []
|
|
776
|
+
let inBucket=0
|
|
777
|
+
while (inBucket<objects.length)
|
|
778
|
+
{
|
|
779
|
+
let detatchedIndex=indexList.find(i=>!buckets.flat().includes(i))
|
|
780
|
+
if(detatchedIndex==null) break
|
|
781
|
+
let queue = [detatchedIndex]
|
|
782
|
+
let visited = []
|
|
783
|
+
while (queue.length > 0) {
|
|
784
|
+
const currentObjectIndex = queue.pop()
|
|
785
|
+
if (visited.indexOf(currentObjectIndex) == -1) {
|
|
786
|
+
//if next queued index hasn't been visited, we mark it as visited and we collect all neighbourg to queue
|
|
787
|
+
visited.push(currentObjectIndex)
|
|
788
|
+
let x = objects[currentObjectIndex].index[0]
|
|
789
|
+
let y = objects[currentObjectIndex].index[1]
|
|
790
|
+
const left = objects.findIndex(
|
|
791
|
+
(o) => o.index[0] == x - 1 && o.index[1] == y
|
|
792
|
+
)
|
|
793
|
+
const right = objects.findIndex(
|
|
794
|
+
(o) => o.index[0] == x + 1 && o.index[1] == y
|
|
795
|
+
)
|
|
796
|
+
const top = objects.findIndex(
|
|
797
|
+
(o) => o.index[0] == x && o.index[1] == y - 1
|
|
798
|
+
)
|
|
799
|
+
const bottom = objects.findIndex(
|
|
800
|
+
(o) => o.index[0] == x && o.index[1] == y + 1
|
|
801
|
+
)
|
|
802
|
+
if (left != -1 && visited.indexOf(left) == -1) queue.push(left)
|
|
803
|
+
if (right != -1 && visited.indexOf(right) == -1) queue.push(right)
|
|
804
|
+
if (top != -1 && visited.indexOf(top) == -1) queue.push(top)
|
|
805
|
+
if (bottom != -1 && visited.indexOf(bottom) == -1) queue.push(bottom)
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
inBucket+=visited.length
|
|
809
|
+
buckets.push(visited)
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
return buckets
|
|
813
|
+
}
|
|
723
814
|
// Function to check if two indexes are adjacent
|
|
724
815
|
export function areAdjacent(objects) {
|
|
816
|
+
if(!objects || objects.length==0) return false
|
|
725
817
|
// objects with 2D indexes
|
|
726
818
|
// Check if the objects form an adjacent group
|
|
727
819
|
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/Circle.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
|
|
2
2
|
import {
|
|
3
|
-
getDistanceBetweenPoints,
|
|
4
3
|
translate2D,
|
|
5
4
|
verticalProjectionOnPlane,
|
|
6
|
-
get3DDistanceBetweenPoints
|
|
5
|
+
get3DDistanceBetweenPoints,
|
|
6
|
+
getDistanceBetweenPoints,
|
|
7
7
|
} from '../geometry'
|
|
8
8
|
import { v4 as uuidv4 } from 'uuid'
|
|
9
9
|
import {Point} from './Point'
|
|
10
|
+
import { addVector, multiplyVector, substractVector,vectorLength,crossProduct,dotProduct,normalizeVector } from '../vector'
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
|
|
@@ -30,6 +31,25 @@ export class Circle {
|
|
|
30
31
|
circle.id = uuidv4()
|
|
31
32
|
return circle
|
|
32
33
|
}
|
|
34
|
+
getIntersections(object){
|
|
35
|
+
const intersections=[]
|
|
36
|
+
if(!object)return
|
|
37
|
+
if(object.type=="point"){
|
|
38
|
+
if(get3DDistanceBetweenPoints(object,this.center)==this.radius){
|
|
39
|
+
intersections.push({...object})
|
|
40
|
+
}
|
|
41
|
+
}else if(object.type=="line"){
|
|
42
|
+
let P=object.getProjectedPoint(this.center)
|
|
43
|
+
let distance = get3DDistanceBetweenPoints(P,this.center)
|
|
44
|
+
if(distance<=this.radius){
|
|
45
|
+
let A=addVector(P,multiplyVector(Math.sqrt(Math.pow(this.radius,2)-Math.pow(distance,2)),object.getDirectionVector()))
|
|
46
|
+
let B=addVector(P,multiplyVector(-Math.sqrt(Math.pow(this.radius,2)-Math.pow(distance,2)),object.getDirectionVector()))
|
|
47
|
+
intersections.push({...A})
|
|
48
|
+
intersections.push({...B})
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return intersections
|
|
52
|
+
}
|
|
33
53
|
getPxDistanceTo(point, canvasContext) {
|
|
34
54
|
const toCanvasRef = canvasContext.toCanvasRef
|
|
35
55
|
let pxCenter = toCanvasRef(this.center)
|
|
@@ -41,6 +61,20 @@ export class Circle {
|
|
|
41
61
|
}
|
|
42
62
|
return Math.abs(get3DDistanceBetweenPoints(point, pxCenter) - pxRadius)
|
|
43
63
|
}
|
|
64
|
+
getDistanceToPoint(point) {
|
|
65
|
+
return get3DDistanceBetweenPoints(point, this.getProjectedPoint(point))
|
|
66
|
+
}
|
|
67
|
+
getHorizontalDistanceToPoint(point) {
|
|
68
|
+
return getDistanceBetweenPoints(point, this.getVerticalProjectedPoint(point))
|
|
69
|
+
}
|
|
70
|
+
isInPlane(plane){
|
|
71
|
+
if(!plane) return false
|
|
72
|
+
const {point,normalVector}=plane
|
|
73
|
+
const circleNormalVector=this.normalVector || {x:0,y:0,z:1}
|
|
74
|
+
if(vectorLength(crossProduct(circleNormalVector,normalVector))>0.1) return false
|
|
75
|
+
if(dotProduct(normalizeVector(substractVector(point,this.center)),normalVector)>0.1) return false
|
|
76
|
+
return true
|
|
77
|
+
}
|
|
44
78
|
getProjectedPoint(point) {
|
|
45
79
|
if(this.normalVector){
|
|
46
80
|
point.z=verticalProjectionOnPlane(point,this.normalVector,this.center).z
|
|
@@ -54,9 +88,13 @@ export class Circle {
|
|
|
54
88
|
}
|
|
55
89
|
let x = this.center.x + (point.x - this.center.x) * (this.radius / distance)
|
|
56
90
|
let y = this.center.y + (point.y - this.center.y) * (this.radius / distance)
|
|
57
|
-
let
|
|
91
|
+
let z = this.center.z + (point.z - this.center.z) * (this.radius / distance)
|
|
92
|
+
let P = new Point(x, y, z, this.layer)
|
|
58
93
|
return P
|
|
59
94
|
}
|
|
95
|
+
getVerticalProjectedPoint(point) {
|
|
96
|
+
return this.getProjectedPoint(point)
|
|
97
|
+
}
|
|
60
98
|
translate(vectorInMm) {
|
|
61
99
|
this.center = translate2D(this.center, vectorInMm)
|
|
62
100
|
}
|
package/src/objects/Line.js
CHANGED
|
@@ -6,9 +6,12 @@ import {
|
|
|
6
6
|
isSamePoint3D,
|
|
7
7
|
translate2D,
|
|
8
8
|
midPoint,
|
|
9
|
+
getDataAboutTwo3DLines,
|
|
10
|
+
isPointBetweenSegment,
|
|
9
11
|
} from '../geometry'
|
|
10
12
|
import { v4 as uuidv4 } from 'uuid'
|
|
11
13
|
import {Point} from './Point'
|
|
14
|
+
import { substractVector,normalizeVector, addVector, multiplyVector,dotProduct } from '../vector'
|
|
12
15
|
|
|
13
16
|
|
|
14
17
|
export class Line {
|
|
@@ -35,6 +38,35 @@ export class Line {
|
|
|
35
38
|
line.infiniteLine = this.infiniteLine
|
|
36
39
|
return line
|
|
37
40
|
}
|
|
41
|
+
getDirectionVector(){
|
|
42
|
+
return normalizeVector(substractVector(this.outline[1],this.outline[0]))
|
|
43
|
+
}
|
|
44
|
+
getIntersections(object){
|
|
45
|
+
const intersections=[]
|
|
46
|
+
if(!object)return
|
|
47
|
+
if(object.type=="point"){
|
|
48
|
+
if(isSamePoint3D(this.getProjectedPoint(object),object)){
|
|
49
|
+
intersections.push({...object})
|
|
50
|
+
}
|
|
51
|
+
}else if(object.type=="line"){
|
|
52
|
+
const data = getDataAboutTwo3DLines(this.outline[0],this.getDirectionVector(),object.outline[0],object.getDirectionVector())
|
|
53
|
+
if(!data){return []}
|
|
54
|
+
let {distance,N} = data
|
|
55
|
+
if(distance<0.1 && !!N){
|
|
56
|
+
intersections.push({...N})
|
|
57
|
+
}
|
|
58
|
+
}else if(object.type=="circle"){
|
|
59
|
+
let P=this.getProjectedPoint(object.center)
|
|
60
|
+
let distance = get3DDistanceBetweenPoints(P,object.center)
|
|
61
|
+
if(distance<=object.radius){
|
|
62
|
+
let A=addVector(P,multiplyVector(Math.sqrt(Math.pow(object.radius,2)-Math.pow(distance,2)),this.getDirectionVector()))
|
|
63
|
+
let B=addVector(P,multiplyVector(-Math.sqrt(Math.pow(object.radius,2)-Math.pow(distance,2)),this.getDirectionVector()))
|
|
64
|
+
intersections.push({...A})
|
|
65
|
+
intersections.push({...B})
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return intersections
|
|
69
|
+
}
|
|
38
70
|
pxLength(canvasContext) {
|
|
39
71
|
return (
|
|
40
72
|
getDistanceBetweenPoints(this.outline[0], this.outline[1]) /
|
|
@@ -69,8 +101,47 @@ export class Line {
|
|
|
69
101
|
}
|
|
70
102
|
|
|
71
103
|
let realityRefPoint = toRealityRef(point)
|
|
72
|
-
let
|
|
73
|
-
|
|
104
|
+
let A={x:this.outline[0].x,y:this.outline[0].y,z:0}
|
|
105
|
+
let B={x:this.outline[1].x,y:this.outline[1].y,z:0}
|
|
106
|
+
let M={x:realityRefPoint.x,y:realityRefPoint.y,z:0}
|
|
107
|
+
let P = getPointOnLine(realityRefPoint, A, B)
|
|
108
|
+
P.z = 0
|
|
109
|
+
return getDistanceBetweenPoints(M, P) / canvasContext.mmPerPx
|
|
110
|
+
}
|
|
111
|
+
isInPlane(plane){
|
|
112
|
+
if(!plane) return false
|
|
113
|
+
const {point,normalVector}=plane
|
|
114
|
+
if(dotProduct(this.getDirectionVector(),normalVector)>0.1) return false
|
|
115
|
+
if(dotProduct(normalizeVector(substractVector(point,this.outline[0])),normalVector)>0.1) return false
|
|
116
|
+
return true
|
|
117
|
+
}
|
|
118
|
+
includesPoint2D(point,tolerance){
|
|
119
|
+
const projection=this.getVerticalProjectedPoint(point)
|
|
120
|
+
return this.getHorizontalDistanceToPoint(point) < tolerance && isPointBetweenSegment( projection, this.outline[0], this.outline[1])
|
|
121
|
+
}
|
|
122
|
+
getDistanceToPoint(point) {
|
|
123
|
+
return get3DDistanceBetweenPoints(point, this.getProjectedPoint(point))
|
|
124
|
+
}
|
|
125
|
+
getHorizontalDistanceToPoint(point) {
|
|
126
|
+
return getDistanceBetweenPoints(point, this.getVerticalProjectedPoint(point))
|
|
127
|
+
}
|
|
128
|
+
getVerticalProjectedPoint(point){
|
|
129
|
+
if (this.outline.length == 0) {
|
|
130
|
+
return null
|
|
131
|
+
}
|
|
132
|
+
if (isSamePoint3D(this.outline[0], this.outline[1])) {
|
|
133
|
+
console.error("A == B Can't project point on Line")
|
|
134
|
+
return null
|
|
135
|
+
}
|
|
136
|
+
let A= {...this.outline[0],z:0}
|
|
137
|
+
let B= {...this.outline[1],z:0}
|
|
138
|
+
let P = getPointOnLine({...point,z:0}, A,B)
|
|
139
|
+
let AP = substractVector(P,A)
|
|
140
|
+
let AB = substractVector(B,A)
|
|
141
|
+
let k=dotProduct(AP,AB)/dotProduct(AB,AB)
|
|
142
|
+
let zP=this.outline[0].z+k*(this.outline[1].z-this.outline[0].z)
|
|
143
|
+
P.z=zP
|
|
144
|
+
return P
|
|
74
145
|
}
|
|
75
146
|
getProjectedPoint(point) {
|
|
76
147
|
if (this.outline.length == 0) {
|
package/src/objects/Point.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
|
|
2
|
+
import { v4 as uuidv4 } from 'uuid'
|
|
2
3
|
import {
|
|
3
4
|
getDistanceBetweenPoints,
|
|
5
|
+
get3DDistanceBetweenPoints,
|
|
6
|
+
isSamePoint3D,
|
|
4
7
|
translate2D,
|
|
5
8
|
} from '../geometry'
|
|
6
|
-
import {
|
|
9
|
+
import { substractVector,dotProduct } from '../vector'
|
|
7
10
|
|
|
8
11
|
export class Point {
|
|
9
12
|
constructor(x = 0, y = 0, z = 0, layer = null) {
|
|
@@ -19,6 +22,24 @@ export class Point {
|
|
|
19
22
|
this.visible = true
|
|
20
23
|
this.hasWarning = false
|
|
21
24
|
}
|
|
25
|
+
getIntersections(object){
|
|
26
|
+
const intersections=[]
|
|
27
|
+
if(!object)return
|
|
28
|
+
if(object.type=="line"){
|
|
29
|
+
if(isSamePoint3D(object.getProjectedPoint(this),this)){
|
|
30
|
+
intersections.push({...this})
|
|
31
|
+
}
|
|
32
|
+
}else if(object.type=="point"){
|
|
33
|
+
if(isSamePoint3D(object,this)){
|
|
34
|
+
intersections.push({...object})
|
|
35
|
+
}
|
|
36
|
+
}else if(object.type=="circle"){
|
|
37
|
+
if(get3DDistanceBetweenPoints(this,object.center)==object.radius){
|
|
38
|
+
intersections.push({...this})
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return intersections
|
|
42
|
+
}
|
|
22
43
|
getPxDistanceTo(point, canvasContext) {
|
|
23
44
|
const toRealityRef = canvasContext.toRealityRef
|
|
24
45
|
const realityPoint = toRealityRef(point)
|
|
@@ -27,6 +48,21 @@ export class Point {
|
|
|
27
48
|
getProjectedPoint(point) {
|
|
28
49
|
return this
|
|
29
50
|
}
|
|
51
|
+
getVerticalProjectedPoint(point) {
|
|
52
|
+
return this
|
|
53
|
+
}
|
|
54
|
+
getDistanceToPoint(point) {
|
|
55
|
+
return get3DDistanceBetweenPoints(point, this.getProjectedPoint(point))
|
|
56
|
+
}
|
|
57
|
+
getHorizontalDistanceToPoint(point) {
|
|
58
|
+
return getDistanceBetweenPoints(point, this.getVerticalProjectedPoint(point))
|
|
59
|
+
}
|
|
60
|
+
isInPlane(plane){
|
|
61
|
+
if(!plane) return false
|
|
62
|
+
const {point,normalVector}=plane
|
|
63
|
+
if(dotProduct(substractVector(point,this),normalVector)>0.1) return false
|
|
64
|
+
return true
|
|
65
|
+
}
|
|
30
66
|
translate(vectorInMm) {
|
|
31
67
|
let translatedPoint = translate2D({ x: this.x, y: this.y }, vectorInMm)
|
|
32
68
|
this.x = translatedPoint.x
|
package/src/objects/Polygon.js
CHANGED
|
@@ -124,7 +124,10 @@ export class Polygon {
|
|
|
124
124
|
x: p.x,
|
|
125
125
|
y: p.y,
|
|
126
126
|
z: p.z,
|
|
127
|
-
|
|
127
|
+
selected:p.selected,
|
|
128
|
+
open:p.open,
|
|
129
|
+
}
|
|
130
|
+
}),
|
|
128
131
|
holes: this.holes.map((p) => p.id),
|
|
129
132
|
layer: this.layer,
|
|
130
133
|
highlight: this.highlight,
|
|
@@ -166,6 +169,7 @@ export class Polygon {
|
|
|
166
169
|
extraSerialization.mountingData = this.mountingData?{...this.mountingData}:null
|
|
167
170
|
extraSerialization.modules = modules
|
|
168
171
|
extraSerialization.needsOptimisation = this.needsOptimisation
|
|
172
|
+
extraSerialization.priority = this.priority
|
|
169
173
|
|
|
170
174
|
} else if (this.layer == 'panel') {
|
|
171
175
|
extraSerialization.index = this.index
|
|
@@ -210,27 +214,7 @@ export class Polygon {
|
|
|
210
214
|
if (!this.userDeactivatedPanels) {
|
|
211
215
|
this.userDeactivatedPanels = []
|
|
212
216
|
}
|
|
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
|
-
})
|
|
217
|
+
const modules = this.data.modules
|
|
234
218
|
return {
|
|
235
219
|
module_field_uuid: this.id,
|
|
236
220
|
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
|
|
package/src/vector.js
CHANGED
|
@@ -25,6 +25,12 @@ export function addVector(u, v) {
|
|
|
25
25
|
const result = u.x * v.x + u.y * v.y + u.z * v.z
|
|
26
26
|
return result
|
|
27
27
|
}
|
|
28
|
+
export function areCollinear(u,v){
|
|
29
|
+
return vectorLength(crossProduct(u,v)) == 0
|
|
30
|
+
}
|
|
31
|
+
export function areAlmostCollinear(u,v,tolerance){
|
|
32
|
+
return vectorLength(crossProduct(u,v)) < tolerance
|
|
33
|
+
}
|
|
28
34
|
export function crossProduct(u, v) {
|
|
29
35
|
const result = {}
|
|
30
36
|
result.x = u.y * v.z - u.z * v.y
|