@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eturnity/eturnity_maths",
3
- "version": "7.2.3",
3
+ "version": "7.4.0-EPDM-7379.0",
4
4
  "author": "Eturnity Team",
5
5
  "main": "src/index.js",
6
6
  "private": false,
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=50
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 getConcaveOutline(selectedPanels,onPanelOutline){
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(onPanelOutline[0], onPanelOutline[1])
24
- let AD = getDistanceBetweenPoints(onPanelOutline[0], onPanelOutline[3])
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
- let N=addVector(B,multiplyVector(t2,v))
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 = getDistanceBetweenPoints(H, I)
137
- const b = getDistanceBetweenPoints(I, J)
138
- const c = getDistanceBetweenPoints(H, J)
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
- const AM = {
543
- x: M.x - A.x,
544
- y: M.y - A.y
545
- }
546
- const AB = {
547
- x: B.x - A.x,
548
- y: B.y - A.y
549
- }
550
-
551
- const dot = AM.x * AB.x + AM.y * AB.y
552
- const distanceAB = getDistanceBetweenPoints(A, B)
553
- let param = -1
554
- if (distanceAB == 0) {
555
- //A et B sont confondu
556
- console.error("A and B don't make a line : A==B")
557
- P = M
558
- } else {
559
- // in case of 0 length line
560
- const distanceAP = dot / distanceAB
561
- P.x = A.x + (distanceAP * AB.x) / distanceAB
562
- P.y = A.y + (distanceAP * AB.y) / distanceAB
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
- const outlineList = getOutlineList(nodeList, edgeList)
90
-
91
- return filterPolygons(outlineList, fig1, fig2, mode)
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) {
@@ -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 P = new Point(x, y, 0, this.layer)
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
  }
@@ -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 P = getPointOnLine(realityRefPoint, this.outline[0], this.outline[1])
73
- return getDistanceBetweenPoints(realityRefPoint, P) / canvasContext.mmPerPx
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) {
@@ -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 { v4 as uuidv4 } from 'uuid'
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
@@ -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.panels.map((p) => {
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],100)){
106
- nodeIndexToSplit.push([k,i])
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
- let v = normalizedVectorTowardInsideAngle(A,B,C)
115
- // let v0=normalizeVector(substractVector())
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(-50,v),B),
128
+ ...addVector(multiplyVector(-mmTolerance,u),B),
118
129
  z:outline[coupleToSplit[0]].z
119
130
  }
120
131
  outline[coupleToSplit[1]] = {
121
- ...addVector(multiplyVector(50,v),B),
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