@eturnity/eturnity_maths 7.37.0 → 7.42.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/.husky/pre-push +1 -0
- package/babel.config.js +4 -2
- package/package.json +5 -3
- package/src/intersectionPolygon.js +42 -10
- package/src/tests/geometry/getMarginPoints.spec.waitingList.js +228 -0
- package/src/tests/geometry/{isInsidePolygon.spec.js → isInsidePolygon.spec.waitingList.js} +1 -1
- package/src/tests/intersectionPolygon/logicOperationOnPolygons.spec.waitingList.js +325 -0
- package/src/tests/vector/areAlmostCollinear.spec.js +7 -7
- package/src/test/maths.test.js +0 -10
- package/src/tests/geometry/getMarginPoints.spec.js +0 -233
- package/src/tests/intersectionPolygon/logicOperationOnPolygons.spec.js +0 -324
package/.husky/pre-push
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
npm run test
|
package/babel.config.js
CHANGED
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eturnity/eturnity_maths",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.42.0",
|
|
4
4
|
"author": "Eturnity Team",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"private": false,
|
|
7
7
|
"scripts": {
|
|
8
|
-
"
|
|
9
|
-
"
|
|
8
|
+
"test": "jest",
|
|
9
|
+
"prepare": "husky",
|
|
10
|
+
"lint": "eslint --fix --debug --ext .js,.vue ."
|
|
10
11
|
},
|
|
11
12
|
"repository": {
|
|
12
13
|
"type": "git",
|
|
@@ -28,6 +29,7 @@
|
|
|
28
29
|
"@babel/core": "7.21.4",
|
|
29
30
|
"@babel/preset-env": "7.21.4",
|
|
30
31
|
"babel-jest": "29.5.0",
|
|
32
|
+
"husky": "^9.1.5",
|
|
31
33
|
"@vue/eslint-config-standard": "8.0.1",
|
|
32
34
|
"babel-eslint": "10.1.0",
|
|
33
35
|
"easygettext": "2.17.0",
|
|
@@ -1,15 +1,47 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getPointInsideOutline,
|
|
3
3
|
isInsidePolygon,
|
|
4
|
-
isSamePoint2D
|
|
4
|
+
isSamePoint2D,
|
|
5
5
|
} from './geometry'
|
|
6
6
|
import {
|
|
7
7
|
getIntersections,
|
|
8
8
|
getNodeList,
|
|
9
9
|
getEdgeList,
|
|
10
|
-
getOutlineList
|
|
10
|
+
getOutlineList,
|
|
11
11
|
} from './splitMergePolygons'
|
|
12
12
|
|
|
13
|
+
export function isOutlineTouchingBoundingBox(outline, bbox) {
|
|
14
|
+
const isOutlinePointWithinBbox = outline.some(
|
|
15
|
+
(p) =>
|
|
16
|
+
p.x > bbox.xMin && p.x < bbox.xMax && p.y > bbox.yMin && p.y < bbox.yMax
|
|
17
|
+
)
|
|
18
|
+
if (isOutlinePointWithinBbox) {
|
|
19
|
+
return true
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
let isEdgeInBbox = outline.some((p, index) => {
|
|
23
|
+
let nextIndex = (index + 1) % outline.length
|
|
24
|
+
let nextP = outline[nextIndex]
|
|
25
|
+
return (
|
|
26
|
+
doLineSegmentsIntersect(
|
|
27
|
+
p,
|
|
28
|
+
nextP,
|
|
29
|
+
{ x: bbox.xMin, y: bbox.yMin },
|
|
30
|
+
{ x: bbox.xMax, y: bbox.yMax }
|
|
31
|
+
) ||
|
|
32
|
+
doLineSegmentsIntersect(
|
|
33
|
+
p,
|
|
34
|
+
nextP,
|
|
35
|
+
{ x: bbox.xMax, y: bbox.yMin },
|
|
36
|
+
{ x: bbox.xMin, y: bbox.yMax }
|
|
37
|
+
)
|
|
38
|
+
)
|
|
39
|
+
})
|
|
40
|
+
if (isEdgeInBbox) {
|
|
41
|
+
return true
|
|
42
|
+
}
|
|
43
|
+
return false
|
|
44
|
+
}
|
|
13
45
|
// Determines whether a given polygon is self-intersecting
|
|
14
46
|
//is counterClockwise
|
|
15
47
|
export function isCounterClockwise(A, B, C) {
|
|
@@ -193,7 +225,7 @@ function edgify(fig1, fig2) {
|
|
|
193
225
|
for (var k = 0; k < points.length - 1; k++) {
|
|
194
226
|
var edge = [
|
|
195
227
|
{ x: points[k].x, y: points[k].y },
|
|
196
|
-
{ x: points[k + 1].x, y: points[k + 1].y }
|
|
228
|
+
{ x: points[k + 1].x, y: points[k + 1].y },
|
|
197
229
|
]
|
|
198
230
|
// check for existanse in sec.array
|
|
199
231
|
if (!edgeExists(edge, secEdges)) {
|
|
@@ -231,7 +263,7 @@ function getEdges(fig) {
|
|
|
231
263
|
for (var i = 0; i < len; i++) {
|
|
232
264
|
edges.push([
|
|
233
265
|
{ x: fig[i % len].x, y: fig[i % len].y },
|
|
234
|
-
{ x: fig[(i + 1) % len].x, y: fig[(i + 1) % len].y }
|
|
266
|
+
{ x: fig[(i + 1) % len].x, y: fig[(i + 1) % len].y },
|
|
235
267
|
])
|
|
236
268
|
}
|
|
237
269
|
return edges
|
|
@@ -306,7 +338,7 @@ function classifyPoint(p, edge) {
|
|
|
306
338
|
(polarAngle([edge[1], edge[0]]) -
|
|
307
339
|
polarAngle([
|
|
308
340
|
{ x: edge[1].x, y: edge[1].y },
|
|
309
|
-
{ x: p.x, y: p.y }
|
|
341
|
+
{ x: p.x, y: p.y },
|
|
310
342
|
])) %
|
|
311
343
|
360
|
|
312
344
|
if (theta < 0) {
|
|
@@ -554,7 +586,7 @@ function getPointInsidePolygon(polygon) {
|
|
|
554
586
|
while (!pointsOK) {
|
|
555
587
|
line = [
|
|
556
588
|
{ x: size.x.min - 1, y: y },
|
|
557
|
-
{ x: size.x.max + 1, y: y }
|
|
589
|
+
{ x: size.x.max + 1, y: y },
|
|
558
590
|
]
|
|
559
591
|
//find intersections with all polygon edges
|
|
560
592
|
for (var i = 0; i < edges.length; i++) {
|
|
@@ -587,12 +619,12 @@ function getSize(polygon) {
|
|
|
587
619
|
var size = {
|
|
588
620
|
x: {
|
|
589
621
|
min: polygon[0].x,
|
|
590
|
-
max: polygon[0].x
|
|
622
|
+
max: polygon[0].x,
|
|
591
623
|
},
|
|
592
624
|
y: {
|
|
593
625
|
min: polygon[0].y,
|
|
594
|
-
max: polygon[0].y
|
|
595
|
-
}
|
|
626
|
+
max: polygon[0].y,
|
|
627
|
+
},
|
|
596
628
|
}
|
|
597
629
|
for (var i = 1; i < polygon.length; i++) {
|
|
598
630
|
if (polygon[i].x < size.x.min) size.x.min = polygon[i].x
|
|
@@ -609,7 +641,7 @@ function findPointInsidePolygon(point, polygon) {
|
|
|
609
641
|
var classify
|
|
610
642
|
var org, dest
|
|
611
643
|
for (var i = 0; i < edges.length; i++) {
|
|
612
|
-
[org, dest] = edges[i]
|
|
644
|
+
;[org, dest] = edges[i]
|
|
613
645
|
classify = classifyPoint(point, [org, dest])
|
|
614
646
|
if (
|
|
615
647
|
(classify.loc === 'RIGHT' && org.y < point.y && dest.y >= point.y) ||
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { getMarginPoints, addVector } from '../../index'
|
|
2
|
+
//convex angle <180deg
|
|
3
|
+
//concave angle >180deg
|
|
4
|
+
function toBeCloseToArray(received, expected, tolerance = 0.01) {
|
|
5
|
+
for (let k = 0; k < 2; k++) {
|
|
6
|
+
if (!Array.isArray(received[k]) || !Array.isArray(expected[k])) {
|
|
7
|
+
return {
|
|
8
|
+
message: () => `Expected both inputs to be arrays`,
|
|
9
|
+
pass: false,
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (received[k].length !== expected[k].length) {
|
|
14
|
+
return {
|
|
15
|
+
message: () => `Expected arrays to be of the same length`,
|
|
16
|
+
pass: false,
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
for (let i = 0; i < received[k].length; i++) {
|
|
21
|
+
const recPoint = received[k][i]
|
|
22
|
+
const expPoint = expected[k][i]
|
|
23
|
+
|
|
24
|
+
if (
|
|
25
|
+
Math.abs(recPoint.x - expPoint.x) > tolerance ||
|
|
26
|
+
Math.abs(recPoint.y - expPoint.y) > tolerance ||
|
|
27
|
+
Math.abs(recPoint.z - expPoint.z) > tolerance
|
|
28
|
+
) {
|
|
29
|
+
return {
|
|
30
|
+
message: () =>
|
|
31
|
+
`Expected points at index ${i} to be close, but found ${JSON.stringify(
|
|
32
|
+
recPoint
|
|
33
|
+
)} and ${JSON.stringify(expPoint)}`,
|
|
34
|
+
pass: false,
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
message: () => `Arrays are close within the given tolerance`,
|
|
41
|
+
pass: true,
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
expect.extend({ toBeCloseToArray })
|
|
46
|
+
|
|
47
|
+
//TEST CASE for new margin points rounded prepared in EPDM-11219
|
|
48
|
+
describe('getMarginPoints function', () => {
|
|
49
|
+
// test('returns one point for convexe inner margins with same distance', () => {
|
|
50
|
+
// const Origin = { x: 0, y: 0, z: 0 }
|
|
51
|
+
// const A = { x: 10, y: 0, z: 0 }
|
|
52
|
+
// const B = { x: 10, y: 10, z: 0 }
|
|
53
|
+
// const clockwiseNormalVector = { x: 0, y: 0, z: -1 }
|
|
54
|
+
// const marginA = 1
|
|
55
|
+
// const marginB = 1
|
|
56
|
+
// const expectedResult = [[{ x: 9, y: 1, z: 0 }], [{ x: 9, y: 1, z: 0 }]]
|
|
57
|
+
// expect(
|
|
58
|
+
// getMarginPoints(Origin, A, B, marginA, marginB, clockwiseNormalVector)
|
|
59
|
+
// ).toEqual(expectedResult)
|
|
60
|
+
// })
|
|
61
|
+
// test('returns one point for convexe inner margins with different distances', () => {
|
|
62
|
+
// const Origin = { x: 0, y: 0, z: 0 }
|
|
63
|
+
// const A = { x: 10, y: 0, z: 0 }
|
|
64
|
+
// const B = { x: 10, y: 10, z: 0 }
|
|
65
|
+
// const clockwiseNormalVector = { x: 0, y: 0, z: -1 }
|
|
66
|
+
// const marginA = 1
|
|
67
|
+
// const marginB = 2
|
|
68
|
+
// const expectedResult = [[{ x: 8, y: 1, z: 0 }], [{ x: 8, y: 1, z: 0 }]]
|
|
69
|
+
// expect(
|
|
70
|
+
// getMarginPoints(Origin, A, B, marginA, marginB, clockwiseNormalVector)
|
|
71
|
+
// ).toEqual(expectedResult)
|
|
72
|
+
// })
|
|
73
|
+
// test('90deg convexe inner margins with first distance equal to zero', () => {
|
|
74
|
+
// const Origin = { x: 0, y: 0, z: 0 }
|
|
75
|
+
// const A = { x: 10, y: 0, z: 0 }
|
|
76
|
+
// const B = { x: 10, y: 10, z: 0 }
|
|
77
|
+
// const clockwiseNormalVector = { x: 0, y: 0, z: -1 }
|
|
78
|
+
// const marginA = 0
|
|
79
|
+
// const marginB = 1
|
|
80
|
+
// const expectedResult = [[{ x: 9, y: 0, z: 0 }], [{ x: 9, y: 0, z: 0 }]]
|
|
81
|
+
// expect(
|
|
82
|
+
// getMarginPoints(Origin, A, B, marginA, marginB, clockwiseNormalVector)
|
|
83
|
+
// ).toEqual(expectedResult)
|
|
84
|
+
// })
|
|
85
|
+
// test('90deg convexe inner margins with second distance equal to zero', () => {
|
|
86
|
+
// const Origin = { x: 0, y: 0, z: 0 }
|
|
87
|
+
// const A = { x: 10, y: 0, z: 0 }
|
|
88
|
+
// const B = { x: 10, y: 10, z: 0 }
|
|
89
|
+
// const clockwiseNormalVector = { x: 0, y: 0, z: -1 }
|
|
90
|
+
// const marginA = 1
|
|
91
|
+
// const marginB = 0
|
|
92
|
+
// const expectedResult = [[{ x: 10, y: 1, z: 0 }], [{ x: 10, y: 1, z: 0 }]]
|
|
93
|
+
// expect(
|
|
94
|
+
// getMarginPoints(Origin, A, B, marginA, marginB, clockwiseNormalVector)
|
|
95
|
+
// ).toEqual(expectedResult)
|
|
96
|
+
// })
|
|
97
|
+
// test('45 deg convexe inner margins with same distance equal to zero', () => {
|
|
98
|
+
// const Origin = { x: 0, y: 0, z: 0 }
|
|
99
|
+
// const A = { x: 10, y: 0, z: 0 }
|
|
100
|
+
// const B = { x: 0, y: 10, z: 0 }
|
|
101
|
+
// const clockwiseNormalVector = { x: 0, y: 0, z: -1 }
|
|
102
|
+
// const marginA = 1
|
|
103
|
+
// const marginB = 1
|
|
104
|
+
// const expectedResult = [
|
|
105
|
+
// [{ x: 9 - Math.sqrt(2), y: 1, z: 0 }],
|
|
106
|
+
// [{ x: 9 - Math.sqrt(2), y: 1, z: 0 }],
|
|
107
|
+
// ]
|
|
108
|
+
// expect(
|
|
109
|
+
// getMarginPoints(Origin, A, B, marginA, marginB, clockwiseNormalVector)
|
|
110
|
+
// ).toBeCloseToArray(expectedResult)
|
|
111
|
+
// })
|
|
112
|
+
// test('45deg convexe inner margins with first distance equal to zero', () => {
|
|
113
|
+
// const Origin = { x: 0, y: 0, z: 0 }
|
|
114
|
+
// const A = { x: 10, y: 0, z: 0 }
|
|
115
|
+
// const B = { x: 0, y: 10, z: 0 }
|
|
116
|
+
// const clockwiseNormalVector = { x: 0, y: 0, z: -1 }
|
|
117
|
+
// const marginA = 0
|
|
118
|
+
// const marginB = 1
|
|
119
|
+
// const expectedResult = [
|
|
120
|
+
// [{ x: 10 - Math.sqrt(2), y: 0, z: 0 }],
|
|
121
|
+
// [{ x: 10 - Math.sqrt(2), y: 0, z: 0 }],
|
|
122
|
+
// ]
|
|
123
|
+
// expect(
|
|
124
|
+
// getMarginPoints(Origin, A, B, marginA, marginB, clockwiseNormalVector)
|
|
125
|
+
// ).toBeCloseToArray(expectedResult)
|
|
126
|
+
// })
|
|
127
|
+
// test('90deg convexe outter margins with same distances', () => {
|
|
128
|
+
// const Origin = { x: 0, y: 0, z: 0 }
|
|
129
|
+
// const A = { x: 10, y: 0, z: 0 }
|
|
130
|
+
// const B = { x: 10, y: 10, z: 0 }
|
|
131
|
+
// const clockwiseNormalVector = { x: 0, y: 0, z: 1 }
|
|
132
|
+
// const marginA = 1
|
|
133
|
+
// const marginB = 1
|
|
134
|
+
// const angle = 90
|
|
135
|
+
// const roundedAngle = 180 - Math.abs(angle)
|
|
136
|
+
// const numPointsPerMargin = 2 + Math.round(roundedAngle / 20)
|
|
137
|
+
// const indexesA = Array.from({ length: numPointsPerMargin }, (e, i) => i)
|
|
138
|
+
// const indexesB = Array.from({ length: numPointsPerMargin }, (e, i) => i)
|
|
139
|
+
// const angleIniA = 0
|
|
140
|
+
// const angleIniB = 45
|
|
141
|
+
// const angleA = 45
|
|
142
|
+
// const angleB = 45
|
|
143
|
+
// const expectedResultA = indexesA.map((i) =>
|
|
144
|
+
// addVector(
|
|
145
|
+
// { x: 10, y: 0, z: 0 },
|
|
146
|
+
// {
|
|
147
|
+
// x: Math.sin(
|
|
148
|
+
// (angleIniA * Math.PI) / 180 +
|
|
149
|
+
// (((angleA * Math.PI) / 180) * i) / (numPointsPerMargin - 1)
|
|
150
|
+
// ),
|
|
151
|
+
// y: -Math.cos(
|
|
152
|
+
// (angleIniA * Math.PI) / 180 +
|
|
153
|
+
// (((angleA * Math.PI) / 180) * i) / (numPointsPerMargin - 1)
|
|
154
|
+
// ),
|
|
155
|
+
// z: 0,
|
|
156
|
+
// }
|
|
157
|
+
// )
|
|
158
|
+
// )
|
|
159
|
+
// const expectedResultB = indexesB.map((i) =>
|
|
160
|
+
// addVector(
|
|
161
|
+
// { x: 10, y: 0, z: 0 },
|
|
162
|
+
// {
|
|
163
|
+
// x: Math.sin(
|
|
164
|
+
// (angleIniB * Math.PI) / 180 +
|
|
165
|
+
// (((angleB * Math.PI) / 180) * i) / (numPointsPerMargin - 1)
|
|
166
|
+
// ),
|
|
167
|
+
// y: -Math.cos(
|
|
168
|
+
// (angleIniB * Math.PI) / 180 +
|
|
169
|
+
// (((angleB * Math.PI) / 180) * i) / (numPointsPerMargin - 1)
|
|
170
|
+
// ),
|
|
171
|
+
// z: 0,
|
|
172
|
+
// }
|
|
173
|
+
// )
|
|
174
|
+
// )
|
|
175
|
+
// const expectedResult = [expectedResultA, expectedResultB]
|
|
176
|
+
// expect(
|
|
177
|
+
// getMarginPoints(Origin, A, B, marginA, marginB, clockwiseNormalVector)
|
|
178
|
+
// ).toBeCloseToArray(expectedResult, 0.01)
|
|
179
|
+
// })
|
|
180
|
+
// test('180deg outter margins with same distances', () => {
|
|
181
|
+
// const Origin = { x: 0, y: 0, z: 0 }
|
|
182
|
+
// const A = { x: 10, y: 0, z: 0 }
|
|
183
|
+
// const B = { x: 20, y: 0, z: 0 }
|
|
184
|
+
// const clockwiseNormalVector = { x: 0, y: 0, z: -1 }
|
|
185
|
+
// const marginA = 1
|
|
186
|
+
// const marginB = 1
|
|
187
|
+
// const expectedResult = [[{ x: 10, y: 1, z: 0 }], [{ x: 10, y: 1, z: 0 }]]
|
|
188
|
+
// expect(
|
|
189
|
+
// getMarginPoints(Origin, A, B, marginA, marginB, clockwiseNormalVector)
|
|
190
|
+
// ).toBeCloseToArray(expectedResult)
|
|
191
|
+
// })
|
|
192
|
+
// test('180deg outter margins with different distances', () => {
|
|
193
|
+
// const Origin = { x: 0, y: 0, z: 0 }
|
|
194
|
+
// const A = { x: 10, y: 0, z: 0 }
|
|
195
|
+
// const B = { x: 20, y: 0, z: 0 }
|
|
196
|
+
// const clockwiseNormalVector = { x: 0, y: 0, z: -1 }
|
|
197
|
+
// const marginA = 1
|
|
198
|
+
// const marginB = 2
|
|
199
|
+
// const expectedResult = [[{ x: 10, y: 1, z: 0 }], [{ x: 10, y: 2, z: 0 }]]
|
|
200
|
+
// expect(
|
|
201
|
+
// getMarginPoints(Origin, A, B, marginA, marginB, clockwiseNormalVector)
|
|
202
|
+
// ).toBeCloseToArray(expectedResult, 0.01)
|
|
203
|
+
// })
|
|
204
|
+
// test('180deg outter margins with first distance to zero', () => {
|
|
205
|
+
// const Origin = { x: 0, y: 0, z: 0 }
|
|
206
|
+
// const A = { x: 10, y: 0, z: 0 }
|
|
207
|
+
// const B = { x: 20, y: 0, z: 0 }
|
|
208
|
+
// const clockwiseNormalVector = { x: 0, y: 0, z: -1 }
|
|
209
|
+
// const marginA = 0
|
|
210
|
+
// const marginB = 1
|
|
211
|
+
// const expectedResult = [[{ x: 10, y: 0, z: 0 }], [{ x: 10, y: 1, z: 0 }]]
|
|
212
|
+
// expect(
|
|
213
|
+
// getMarginPoints(Origin, A, B, marginA, marginB, clockwiseNormalVector)
|
|
214
|
+
// ).toBeCloseToArray(expectedResult, 0.01)
|
|
215
|
+
// })
|
|
216
|
+
// test('180deg outter margins with second distance to zero', () => {
|
|
217
|
+
// const Origin = { x: 0, y: 0, z: 0 }
|
|
218
|
+
// const A = { x: 10, y: 0, z: 0 }
|
|
219
|
+
// const B = { x: 20, y: 0, z: 0 }
|
|
220
|
+
// const clockwiseNormalVector = { x: 0, y: 0, z: -1 }
|
|
221
|
+
// const marginA = 0
|
|
222
|
+
// const marginB = 1
|
|
223
|
+
// const expectedResult = [[{ x: 10, y: 0, z: 0 }], [{ x: 10, y: 1, z: 0 }]]
|
|
224
|
+
// expect(
|
|
225
|
+
// getMarginPoints(Origin, A, B, marginA, marginB, clockwiseNormalVector)
|
|
226
|
+
// ).toEqual(expectedResult, 0.01)
|
|
227
|
+
// })
|
|
228
|
+
})
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { isInsidePolygon } from '../../index'
|
|
2
2
|
//convex angle <180deg
|
|
3
3
|
//concave angle >180deg
|
|
4
|
-
|
|
4
|
+
//Should be solved withnew implementation of splitline and EPDM-11219
|
|
5
5
|
describe('isInsidePolygon function', () => {
|
|
6
6
|
test('in square', () => {
|
|
7
7
|
const A = { x: 0, y: 0, z: 0 }
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
import {
|
|
2
|
+
logicOperationOnPolygons,
|
|
3
|
+
calculateArea,
|
|
4
|
+
isSelfIntersecting,
|
|
5
|
+
} from '../../index'
|
|
6
|
+
|
|
7
|
+
//TEST CASE for new implementation of spliting algorithm
|
|
8
|
+
describe('logicOperationOnPolygons function', () => {
|
|
9
|
+
test('returns intersecting polygon', () => {
|
|
10
|
+
const O = { x: 0, y: 0, z: 0 }
|
|
11
|
+
const A = { x: 10, y: 0, z: 0 }
|
|
12
|
+
const B = { x: 10, y: 10, z: 0 }
|
|
13
|
+
const C = { x: 0, y: 10, z: 0 }
|
|
14
|
+
const D = { x: 5, y: 5, z: 0 }
|
|
15
|
+
const E = { x: 15, y: 5, z: 0 }
|
|
16
|
+
const F = { x: 15, y: 15, z: 0 }
|
|
17
|
+
const G = { x: 5, y: 15, z: 0 }
|
|
18
|
+
const I = { x: 10, y: 5, z: 0 }
|
|
19
|
+
const J = { x: 5, y: 10, z: 0 }
|
|
20
|
+
const out1 = [B, C, O, A]
|
|
21
|
+
const out2 = [D, E, F, G]
|
|
22
|
+
const res = [[D, I, B, J]]
|
|
23
|
+
expect(logicOperationOnPolygons(out1, out2)).toEqual(
|
|
24
|
+
expect.arrayContaining(res)
|
|
25
|
+
)
|
|
26
|
+
})
|
|
27
|
+
test('returns intersecting polygon when out1 is included in out2', () => {
|
|
28
|
+
const O = { x: 0, y: 0, z: 0 }
|
|
29
|
+
const A = { x: 20, y: 0, z: 0 }
|
|
30
|
+
const B = { x: 20, y: 20, z: 0 }
|
|
31
|
+
const C = { x: 0, y: 20, z: 0 }
|
|
32
|
+
const D = { x: 5, y: 5, z: 0 }
|
|
33
|
+
const E = { x: 15, y: 5, z: 0 }
|
|
34
|
+
const F = { x: 15, y: 15, z: 0 }
|
|
35
|
+
const G = { x: 5, y: 15, z: 0 }
|
|
36
|
+
const out1 = [B, C, O, A]
|
|
37
|
+
const out2 = [D, E, F, G]
|
|
38
|
+
const res = [[D, E, F, G]]
|
|
39
|
+
expect(logicOperationOnPolygons(out1, out2)).toEqual(
|
|
40
|
+
expect.arrayContaining(res)
|
|
41
|
+
)
|
|
42
|
+
})
|
|
43
|
+
test('returns intersecting polygon when out2 is included in out1', () => {
|
|
44
|
+
const O = { x: 0, y: 0, z: 0 }
|
|
45
|
+
const A = { x: 20, y: 0, z: 0 }
|
|
46
|
+
const B = { x: 20, y: 20, z: 0 }
|
|
47
|
+
const C = { x: 0, y: 20, z: 0 }
|
|
48
|
+
const D = { x: 5, y: 5, z: 0 }
|
|
49
|
+
const E = { x: 15, y: 5, z: 0 }
|
|
50
|
+
const F = { x: 15, y: 15, z: 0 }
|
|
51
|
+
const G = { x: 5, y: 15, z: 0 }
|
|
52
|
+
const out1 = [B, C, O, A]
|
|
53
|
+
const out2 = [D, E, F, G]
|
|
54
|
+
const res = [[D, E, F, G]]
|
|
55
|
+
expect(logicOperationOnPolygons(out2, out1)).toEqual(
|
|
56
|
+
expect.arrayContaining(res)
|
|
57
|
+
)
|
|
58
|
+
})
|
|
59
|
+
test('check intersection at altitude', () => {
|
|
60
|
+
const out1 = [
|
|
61
|
+
{
|
|
62
|
+
x: 2500,
|
|
63
|
+
y: 9000,
|
|
64
|
+
z: 18160,
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
x: 2500,
|
|
68
|
+
y: 10000,
|
|
69
|
+
z: 18160,
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
x: 0,
|
|
73
|
+
y: 10000,
|
|
74
|
+
z: 18160,
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
x: 0,
|
|
78
|
+
y: 9000,
|
|
79
|
+
z: 18160,
|
|
80
|
+
},
|
|
81
|
+
]
|
|
82
|
+
const out2 = [
|
|
83
|
+
{
|
|
84
|
+
x: 1000,
|
|
85
|
+
y: 10000,
|
|
86
|
+
z: 18160,
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
x: 1000,
|
|
90
|
+
y: -1000,
|
|
91
|
+
z: 18160,
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
x: 10000,
|
|
95
|
+
y: -1000,
|
|
96
|
+
z: 18160,
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
x: 10000,
|
|
100
|
+
y: 10000,
|
|
101
|
+
z: 18160,
|
|
102
|
+
},
|
|
103
|
+
]
|
|
104
|
+
expect(
|
|
105
|
+
logicOperationOnPolygons(out2, out1).every(
|
|
106
|
+
(outline) => calculateArea(outline) <= calculateArea(out1)
|
|
107
|
+
)
|
|
108
|
+
).toBe(true)
|
|
109
|
+
})
|
|
110
|
+
test('check intersection at altitude Triangle-Rectangle', () => {
|
|
111
|
+
const out1 = [
|
|
112
|
+
{
|
|
113
|
+
x: 0,
|
|
114
|
+
y: -1800,
|
|
115
|
+
z: 3000,
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
x: 3000,
|
|
119
|
+
y: 9300,
|
|
120
|
+
z: 3000,
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
x: 2500,
|
|
124
|
+
y: 9300,
|
|
125
|
+
z: 3000,
|
|
126
|
+
},
|
|
127
|
+
]
|
|
128
|
+
const out2 = [
|
|
129
|
+
{
|
|
130
|
+
x: 800,
|
|
131
|
+
y: 12000,
|
|
132
|
+
z: 3000,
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
x: 1200,
|
|
136
|
+
y: -6500,
|
|
137
|
+
z: 3000,
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
x: 8800,
|
|
141
|
+
y: -6500,
|
|
142
|
+
z: 3000,
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
x: 8800,
|
|
146
|
+
y: 12000,
|
|
147
|
+
z: 3000,
|
|
148
|
+
},
|
|
149
|
+
]
|
|
150
|
+
expect(
|
|
151
|
+
logicOperationOnPolygons(out2, out1).every(
|
|
152
|
+
(outline) => calculateArea(outline) <= calculateArea(out1)
|
|
153
|
+
)
|
|
154
|
+
).toBe(true)
|
|
155
|
+
})
|
|
156
|
+
test('check intersection david star', () => {
|
|
157
|
+
const out1 = [
|
|
158
|
+
{
|
|
159
|
+
x: 0,
|
|
160
|
+
y: 0,
|
|
161
|
+
z: 3000,
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
x: 2000,
|
|
165
|
+
y: 0,
|
|
166
|
+
z: 3000,
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
x: 1000,
|
|
170
|
+
y: 2000,
|
|
171
|
+
z: 3000,
|
|
172
|
+
},
|
|
173
|
+
]
|
|
174
|
+
const out2 = [
|
|
175
|
+
{
|
|
176
|
+
x: 0,
|
|
177
|
+
y: 1000,
|
|
178
|
+
z: 3000,
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
x: 2000,
|
|
182
|
+
y: 1000,
|
|
183
|
+
z: 3000,
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
x: 1000,
|
|
187
|
+
y: -1000,
|
|
188
|
+
z: 3000,
|
|
189
|
+
},
|
|
190
|
+
]
|
|
191
|
+
expect(
|
|
192
|
+
logicOperationOnPolygons(out2, out1).every(
|
|
193
|
+
(outline) => calculateArea(outline) <= calculateArea(out1)
|
|
194
|
+
)
|
|
195
|
+
).toBe(true)
|
|
196
|
+
})
|
|
197
|
+
test('check intersection two triangle with 2 corner of the 2nd in the first', () => {
|
|
198
|
+
const out1 = [
|
|
199
|
+
{
|
|
200
|
+
x: 0,
|
|
201
|
+
y: 0,
|
|
202
|
+
z: 3000,
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
x: 2000,
|
|
206
|
+
y: 0,
|
|
207
|
+
z: 3000,
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
x: 1000,
|
|
211
|
+
y: 2000,
|
|
212
|
+
z: 3000,
|
|
213
|
+
},
|
|
214
|
+
]
|
|
215
|
+
const out2 = [
|
|
216
|
+
{
|
|
217
|
+
x: 1000,
|
|
218
|
+
y: 200,
|
|
219
|
+
z: 3000,
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
x: 500,
|
|
223
|
+
y: 200,
|
|
224
|
+
z: 3000,
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
x: 1000,
|
|
228
|
+
y: -1000,
|
|
229
|
+
z: 3000,
|
|
230
|
+
},
|
|
231
|
+
]
|
|
232
|
+
expect(
|
|
233
|
+
logicOperationOnPolygons(out2, out1).every(
|
|
234
|
+
(outline) => calculateArea(outline) <= calculateArea(out1)
|
|
235
|
+
)
|
|
236
|
+
).toBe(true)
|
|
237
|
+
})
|
|
238
|
+
test('check intersection two triangle with 1 corner of the 2nd in the first', () => {
|
|
239
|
+
const out1 = [
|
|
240
|
+
{
|
|
241
|
+
x: 0,
|
|
242
|
+
y: 0,
|
|
243
|
+
z: 3000,
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
x: 2000,
|
|
247
|
+
y: 0,
|
|
248
|
+
z: 3000,
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
x: 1000,
|
|
252
|
+
y: 2000,
|
|
253
|
+
z: 3000,
|
|
254
|
+
},
|
|
255
|
+
]
|
|
256
|
+
const out2 = [
|
|
257
|
+
{
|
|
258
|
+
x: 1000,
|
|
259
|
+
y: 200,
|
|
260
|
+
z: 3000,
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
x: 5000,
|
|
264
|
+
y: 200,
|
|
265
|
+
z: 3000,
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
x: 1000,
|
|
269
|
+
y: -1000,
|
|
270
|
+
z: 3000,
|
|
271
|
+
},
|
|
272
|
+
]
|
|
273
|
+
expect(
|
|
274
|
+
logicOperationOnPolygons(out2, out1).every(
|
|
275
|
+
(outline) => calculateArea(outline) <= calculateArea(out1)
|
|
276
|
+
)
|
|
277
|
+
).toBe(true)
|
|
278
|
+
})
|
|
279
|
+
test('check triangle-rectangle', () => {
|
|
280
|
+
const out1 = [
|
|
281
|
+
{
|
|
282
|
+
x: 0,
|
|
283
|
+
y: 0,
|
|
284
|
+
z: 3000,
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
x: 2000,
|
|
288
|
+
y: 0,
|
|
289
|
+
z: 3000,
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
x: 1000,
|
|
293
|
+
y: 2000,
|
|
294
|
+
z: 3000,
|
|
295
|
+
},
|
|
296
|
+
]
|
|
297
|
+
const out2 = [
|
|
298
|
+
{
|
|
299
|
+
x: 500,
|
|
300
|
+
y: 4000,
|
|
301
|
+
z: 3000,
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
x: 500,
|
|
305
|
+
y: -1000,
|
|
306
|
+
z: 3000,
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
x: 1500,
|
|
310
|
+
y: -1000,
|
|
311
|
+
z: 3000,
|
|
312
|
+
},
|
|
313
|
+
{
|
|
314
|
+
x: 1500,
|
|
315
|
+
y: 4000,
|
|
316
|
+
z: 3000,
|
|
317
|
+
},
|
|
318
|
+
]
|
|
319
|
+
expect(
|
|
320
|
+
logicOperationOnPolygons(out2, out1).every(
|
|
321
|
+
(outline) => calculateArea(outline) <= calculateArea(out1)
|
|
322
|
+
)
|
|
323
|
+
).toBe(true)
|
|
324
|
+
})
|
|
325
|
+
})
|
|
@@ -2,15 +2,15 @@ import { areAlmostCollinear } from '../../index'
|
|
|
2
2
|
|
|
3
3
|
describe('areAlmostCollinear function', () => {
|
|
4
4
|
test('returns true for almost collinear vectors', () => {
|
|
5
|
-
const u = { x: 1, y: 0, z: 0 }
|
|
6
|
-
const v = { x: 1, y: 0.1, z: 0 }
|
|
5
|
+
const u = { x: 1, y: 0, z: 0 }
|
|
6
|
+
const v = { x: 1, y: 0.1, z: 0 }
|
|
7
7
|
const tolerance = 0.2
|
|
8
|
-
expect(areAlmostCollinear(u, v, tolerance)).toBe(true)
|
|
8
|
+
expect(areAlmostCollinear(u, v, tolerance)).toBe(true)
|
|
9
9
|
})
|
|
10
10
|
test('returns flase for vector outside of tolerance', () => {
|
|
11
|
-
const u = { x: 1, y: 0, z: 0 }
|
|
12
|
-
const v = { x: 1, y: 0.3, z: 0 }
|
|
11
|
+
const u = { x: 1, y: 0, z: 0 }
|
|
12
|
+
const v = { x: 1, y: 0.3, z: 0 }
|
|
13
13
|
const tolerance = 0.2
|
|
14
|
-
expect(areAlmostCollinear(u, v, tolerance)).toBe(false)
|
|
14
|
+
expect(areAlmostCollinear(u, v, tolerance)).toBe(false)
|
|
15
15
|
})
|
|
16
|
-
})
|
|
16
|
+
})
|
package/src/test/maths.test.js
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { deltaLatLngToDistance, distanceToDeltaLatLng } from '../index'
|
|
2
|
-
|
|
3
|
-
test('deltaLatLngToDistance is inverse of distanceToDeltaLatLng x', () => {
|
|
4
|
-
let { lat, lng } = distanceToDeltaLatLng(1000, 2000, 45)
|
|
5
|
-
expect(deltaLatLngToDistance(lat, lng, 45).x).toBe(1000)
|
|
6
|
-
})
|
|
7
|
-
test('deltaLatLngToDistance is inverse of distanceToDeltaLatLng y', () => {
|
|
8
|
-
let { lat, lng } = distanceToDeltaLatLng(1000, 2000, 45)
|
|
9
|
-
expect(deltaLatLngToDistance(lat, lng, 45).y).toBe(2000)
|
|
10
|
-
})
|
|
@@ -1,233 +0,0 @@
|
|
|
1
|
-
import { getMarginPoints, addVector } from '../../index'
|
|
2
|
-
//convex angle <180deg
|
|
3
|
-
//concave angle >180deg
|
|
4
|
-
function toBeCloseToArray(received, expected, tolerance = 0.01) {
|
|
5
|
-
for (let k = 0; k < 2; k++) {
|
|
6
|
-
if (!Array.isArray(received[k]) || !Array.isArray(expected[k])) {
|
|
7
|
-
return {
|
|
8
|
-
message: () => `Expected both inputs to be arrays`,
|
|
9
|
-
pass: false,
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
if (received[k].length !== expected[k].length) {
|
|
14
|
-
return {
|
|
15
|
-
message: () => `Expected arrays to be of the same length`,
|
|
16
|
-
pass: false,
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
for (let i = 0; i < received[k].length; i++) {
|
|
21
|
-
const recPoint = received[k][i]
|
|
22
|
-
const expPoint = expected[k][i]
|
|
23
|
-
|
|
24
|
-
if (
|
|
25
|
-
Math.abs(recPoint.x - expPoint.x) > tolerance ||
|
|
26
|
-
Math.abs(recPoint.y - expPoint.y) > tolerance ||
|
|
27
|
-
Math.abs(recPoint.z - expPoint.z) > tolerance
|
|
28
|
-
) {
|
|
29
|
-
return {
|
|
30
|
-
message: () =>
|
|
31
|
-
`Expected points at index ${i} to be close, but found ${JSON.stringify(
|
|
32
|
-
recPoint
|
|
33
|
-
)} and ${JSON.stringify(expPoint)}`,
|
|
34
|
-
pass: false,
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
return {
|
|
40
|
-
message: () => `Arrays are close within the given tolerance`,
|
|
41
|
-
pass: true,
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
expect.extend({ toBeCloseToArray })
|
|
46
|
-
|
|
47
|
-
describe('getMarginPoints function', () => {
|
|
48
|
-
test('returns one point for convexe inner margins with same distance', () => {
|
|
49
|
-
const Origin = { x: 0, y: 0, z: 0 }
|
|
50
|
-
const A = { x: 10, y: 0, z: 0 }
|
|
51
|
-
const B = { x: 10, y: 10, z: 0 }
|
|
52
|
-
const clockwiseNormalVector = { x: 0, y: 0, z: -1 }
|
|
53
|
-
const marginA = 1
|
|
54
|
-
const marginB = 1
|
|
55
|
-
const expectedResult = [[{ x: 9, y: 1, z: 0 }], [{ x: 9, y: 1, z: 0 }]]
|
|
56
|
-
expect(
|
|
57
|
-
getMarginPoints(Origin, A, B, marginA, marginB, clockwiseNormalVector)
|
|
58
|
-
).toEqual(expectedResult)
|
|
59
|
-
})
|
|
60
|
-
test('returns one point for convexe inner margins with different distances', () => {
|
|
61
|
-
const Origin = { x: 0, y: 0, z: 0 }
|
|
62
|
-
const A = { x: 10, y: 0, z: 0 }
|
|
63
|
-
const B = { x: 10, y: 10, z: 0 }
|
|
64
|
-
const clockwiseNormalVector = { x: 0, y: 0, z: -1 }
|
|
65
|
-
const marginA = 1
|
|
66
|
-
const marginB = 2
|
|
67
|
-
const expectedResult = [[{ x: 8, y: 1, z: 0 }], [{ x: 8, y: 1, z: 0 }]]
|
|
68
|
-
expect(
|
|
69
|
-
getMarginPoints(Origin, A, B, marginA, marginB, clockwiseNormalVector)
|
|
70
|
-
).toEqual(expectedResult)
|
|
71
|
-
})
|
|
72
|
-
test('90deg convexe inner margins with first distance equal to zero', () => {
|
|
73
|
-
const Origin = { x: 0, y: 0, z: 0 }
|
|
74
|
-
const A = { x: 10, y: 0, z: 0 }
|
|
75
|
-
const B = { x: 10, y: 10, z: 0 }
|
|
76
|
-
const clockwiseNormalVector = { x: 0, y: 0, z: -1 }
|
|
77
|
-
const marginA = 0
|
|
78
|
-
const marginB = 1
|
|
79
|
-
const expectedResult = [[{ x: 9, y: 0, z: 0 }], [{ x: 9, y: 0, z: 0 }]]
|
|
80
|
-
expect(
|
|
81
|
-
getMarginPoints(Origin, A, B, marginA, marginB, clockwiseNormalVector)
|
|
82
|
-
).toEqual(expectedResult)
|
|
83
|
-
})
|
|
84
|
-
test('90deg convexe inner margins with second distance equal to zero', () => {
|
|
85
|
-
const Origin = { x: 0, y: 0, z: 0 }
|
|
86
|
-
const A = { x: 10, y: 0, z: 0 }
|
|
87
|
-
const B = { x: 10, y: 10, z: 0 }
|
|
88
|
-
const clockwiseNormalVector = { x: 0, y: 0, z: -1 }
|
|
89
|
-
const marginA = 1
|
|
90
|
-
const marginB = 0
|
|
91
|
-
const expectedResult = [[{ x: 10, y: 1, z: 0 }], [{ x: 10, y: 1, z: 0 }]]
|
|
92
|
-
expect(
|
|
93
|
-
getMarginPoints(Origin, A, B, marginA, marginB, clockwiseNormalVector)
|
|
94
|
-
).toEqual(expectedResult)
|
|
95
|
-
})
|
|
96
|
-
test('45 deg convexe inner margins with same distance equal to zero', () => {
|
|
97
|
-
const Origin = { x: 0, y: 0, z: 0 }
|
|
98
|
-
const A = { x: 10, y: 0, z: 0 }
|
|
99
|
-
const B = { x: 0, y: 10, z: 0 }
|
|
100
|
-
const clockwiseNormalVector = { x: 0, y: 0, z: -1 }
|
|
101
|
-
const marginA = 1
|
|
102
|
-
const marginB = 1
|
|
103
|
-
const expectedResult = [
|
|
104
|
-
[{ x: 9 - Math.sqrt(2), y: 1, z: 0 }],
|
|
105
|
-
[{ x: 9 - Math.sqrt(2), y: 1, z: 0 }],
|
|
106
|
-
]
|
|
107
|
-
expect(
|
|
108
|
-
getMarginPoints(Origin, A, B, marginA, marginB, clockwiseNormalVector)
|
|
109
|
-
).toBeCloseToArray(expectedResult)
|
|
110
|
-
})
|
|
111
|
-
test('45deg convexe inner margins with first distance equal to zero', () => {
|
|
112
|
-
const Origin = { x: 0, y: 0, z: 0 }
|
|
113
|
-
const A = { x: 10, y: 0, z: 0 }
|
|
114
|
-
const B = { x: 0, y: 10, z: 0 }
|
|
115
|
-
const clockwiseNormalVector = { x: 0, y: 0, z: -1 }
|
|
116
|
-
const marginA = 0
|
|
117
|
-
const marginB = 1
|
|
118
|
-
const expectedResult = [
|
|
119
|
-
[{ x: 10 - Math.sqrt(2), y: 0, z: 0 }],
|
|
120
|
-
[{ x: 10 - Math.sqrt(2), y: 0, z: 0 }],
|
|
121
|
-
]
|
|
122
|
-
expect(
|
|
123
|
-
getMarginPoints(Origin, A, B, marginA, marginB, clockwiseNormalVector)
|
|
124
|
-
).toBeCloseToArray(expectedResult)
|
|
125
|
-
})
|
|
126
|
-
test('90deg convexe outter margins with same distances', () => {
|
|
127
|
-
const Origin = { x: 0, y: 0, z: 0 }
|
|
128
|
-
const A = { x: 10, y: 0, z: 0 }
|
|
129
|
-
const B = { x: 10, y: 10, z: 0 }
|
|
130
|
-
const clockwiseNormalVector = { x: 0, y: 0, z: 1 }
|
|
131
|
-
const marginA = 1
|
|
132
|
-
const marginB = 1
|
|
133
|
-
const angle = 90
|
|
134
|
-
const roundedAngle = 180 - Math.abs(angle)
|
|
135
|
-
const numPointsPerMargin = 2 + Math.round(roundedAngle / 20)
|
|
136
|
-
const indexesA = Array.from({ length: numPointsPerMargin }, (e, i) => i)
|
|
137
|
-
const indexesB = Array.from({ length: numPointsPerMargin }, (e, i) => i)
|
|
138
|
-
const angleIniA = 0
|
|
139
|
-
const angleIniB = 45
|
|
140
|
-
const angleA = 45
|
|
141
|
-
const angleB = 45
|
|
142
|
-
const expectedResultA = indexesA.map((i) =>
|
|
143
|
-
addVector(
|
|
144
|
-
{ x: 10, y: 0, z: 0 },
|
|
145
|
-
{
|
|
146
|
-
x: Math.sin(
|
|
147
|
-
(angleIniA * Math.PI) / 180 +
|
|
148
|
-
(((angleA * Math.PI) / 180) * i) / (numPointsPerMargin - 1)
|
|
149
|
-
),
|
|
150
|
-
y: -Math.cos(
|
|
151
|
-
(angleIniA * Math.PI) / 180 +
|
|
152
|
-
(((angleA * Math.PI) / 180) * i) / (numPointsPerMargin - 1)
|
|
153
|
-
),
|
|
154
|
-
z: 0,
|
|
155
|
-
}
|
|
156
|
-
)
|
|
157
|
-
)
|
|
158
|
-
const expectedResultB = indexesB.map((i) =>
|
|
159
|
-
addVector(
|
|
160
|
-
{ x: 10, y: 0, z: 0 },
|
|
161
|
-
{
|
|
162
|
-
x: Math.sin(
|
|
163
|
-
(angleIniB * Math.PI) / 180 +
|
|
164
|
-
(((angleB * Math.PI) / 180) * i) / (numPointsPerMargin - 1)
|
|
165
|
-
),
|
|
166
|
-
y: -Math.cos(
|
|
167
|
-
(angleIniB * Math.PI) / 180 +
|
|
168
|
-
(((angleB * Math.PI) / 180) * i) / (numPointsPerMargin - 1)
|
|
169
|
-
),
|
|
170
|
-
z: 0,
|
|
171
|
-
}
|
|
172
|
-
)
|
|
173
|
-
)
|
|
174
|
-
const expectedResult = [expectedResultA, expectedResultB]
|
|
175
|
-
|
|
176
|
-
expect(
|
|
177
|
-
getMarginPoints(Origin, A, B, marginA, marginB, clockwiseNormalVector)
|
|
178
|
-
).toBeCloseToArray(expectedResult, 0.01)
|
|
179
|
-
})
|
|
180
|
-
test('180deg outter margins with same distances', () => {
|
|
181
|
-
const Origin = { x: 0, y: 0, z: 0 }
|
|
182
|
-
const A = { x: 10, y: 0, z: 0 }
|
|
183
|
-
const B = { x: 20, y: 0, z: 0 }
|
|
184
|
-
const clockwiseNormalVector = { x: 0, y: 0, z: -1 }
|
|
185
|
-
const marginA = 1
|
|
186
|
-
const marginB = 1
|
|
187
|
-
|
|
188
|
-
const expectedResult = [[{ x: 10, y: 1, z: 0 }], [{ x: 10, y: 1, z: 0 }]]
|
|
189
|
-
expect(
|
|
190
|
-
getMarginPoints(Origin, A, B, marginA, marginB, clockwiseNormalVector)
|
|
191
|
-
).toBeCloseToArray(expectedResult)
|
|
192
|
-
})
|
|
193
|
-
test('180deg outter margins with different distances', () => {
|
|
194
|
-
const Origin = { x: 0, y: 0, z: 0 }
|
|
195
|
-
const A = { x: 10, y: 0, z: 0 }
|
|
196
|
-
const B = { x: 20, y: 0, z: 0 }
|
|
197
|
-
const clockwiseNormalVector = { x: 0, y: 0, z: -1 }
|
|
198
|
-
const marginA = 1
|
|
199
|
-
const marginB = 2
|
|
200
|
-
|
|
201
|
-
const expectedResult = [[{ x: 10, y: 1, z: 0 }], [{ x: 10, y: 2, z: 0 }]]
|
|
202
|
-
|
|
203
|
-
expect(
|
|
204
|
-
getMarginPoints(Origin, A, B, marginA, marginB, clockwiseNormalVector)
|
|
205
|
-
).toBeCloseToArray(expectedResult, 0.01)
|
|
206
|
-
})
|
|
207
|
-
test('180deg outter margins with first distance to zero', () => {
|
|
208
|
-
const Origin = { x: 0, y: 0, z: 0 }
|
|
209
|
-
const A = { x: 10, y: 0, z: 0 }
|
|
210
|
-
const B = { x: 20, y: 0, z: 0 }
|
|
211
|
-
const clockwiseNormalVector = { x: 0, y: 0, z: -1 }
|
|
212
|
-
const marginA = 0
|
|
213
|
-
const marginB = 1
|
|
214
|
-
|
|
215
|
-
const expectedResult = [[{ x: 10, y: 0, z: 0 }], [{ x: 10, y: 1, z: 0 }]]
|
|
216
|
-
expect(
|
|
217
|
-
getMarginPoints(Origin, A, B, marginA, marginB, clockwiseNormalVector)
|
|
218
|
-
).toBeCloseToArray(expectedResult, 0.01)
|
|
219
|
-
})
|
|
220
|
-
test('180deg outter margins with second distance to zero', () => {
|
|
221
|
-
const Origin = { x: 0, y: 0, z: 0 }
|
|
222
|
-
const A = { x: 10, y: 0, z: 0 }
|
|
223
|
-
const B = { x: 20, y: 0, z: 0 }
|
|
224
|
-
const clockwiseNormalVector = { x: 0, y: 0, z: -1 }
|
|
225
|
-
const marginA = 0
|
|
226
|
-
const marginB = 1
|
|
227
|
-
|
|
228
|
-
const expectedResult = [[{ x: 10, y: 0, z: 0 }], [{ x: 10, y: 1, z: 0 }]]
|
|
229
|
-
expect(
|
|
230
|
-
getMarginPoints(Origin, A, B, marginA, marginB, clockwiseNormalVector)
|
|
231
|
-
).toEqual(expectedResult, 0.01)
|
|
232
|
-
})
|
|
233
|
-
})
|
|
@@ -1,324 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
logicOperationOnPolygons,
|
|
3
|
-
calculateArea,
|
|
4
|
-
isSelfIntersecting,
|
|
5
|
-
} from '../../index'
|
|
6
|
-
|
|
7
|
-
describe('logicOperationOnPolygons function', () => {
|
|
8
|
-
// test('returns intersecting polygon', () => {
|
|
9
|
-
// const O = { x: 0, y: 0, z: 0 }
|
|
10
|
-
// const A = { x: 10, y: 0, z: 0 }
|
|
11
|
-
// const B = { x: 10, y: 10, z: 0 }
|
|
12
|
-
// const C = { x: 0, y: 10, z: 0 }
|
|
13
|
-
// const D = { x: 5, y: 5, z: 0 }
|
|
14
|
-
// const E = { x: 15, y: 5, z: 0 }
|
|
15
|
-
// const F = { x: 15, y: 15, z: 0 }
|
|
16
|
-
// const G = { x: 5, y: 15, z: 0 }
|
|
17
|
-
// const I = { x: 10, y: 5, z: 0 }
|
|
18
|
-
// const J = { x: 5, y: 10, z: 0 }
|
|
19
|
-
// const out1 = [B, C, O, A]
|
|
20
|
-
// const out2 = [D, E, F, G]
|
|
21
|
-
// const res = [[D, I, B, J]]
|
|
22
|
-
// expect(logicOperationOnPolygons(out1, out2)).toEqual(
|
|
23
|
-
// expect.arrayContaining(res)
|
|
24
|
-
// )
|
|
25
|
-
// })
|
|
26
|
-
// test('returns intersecting polygon when out1 is included in out2', () => {
|
|
27
|
-
// const O = { x: 0, y: 0, z: 0 }
|
|
28
|
-
// const A = { x: 20, y: 0, z: 0 }
|
|
29
|
-
// const B = { x: 20, y: 20, z: 0 }
|
|
30
|
-
// const C = { x: 0, y: 20, z: 0 }
|
|
31
|
-
// const D = { x: 5, y: 5, z: 0 }
|
|
32
|
-
// const E = { x: 15, y: 5, z: 0 }
|
|
33
|
-
// const F = { x: 15, y: 15, z: 0 }
|
|
34
|
-
// const G = { x: 5, y: 15, z: 0 }
|
|
35
|
-
// const out1 = [B, C, O, A]
|
|
36
|
-
// const out2 = [D, E, F, G]
|
|
37
|
-
// const res = [[D, E, F, G]]
|
|
38
|
-
// expect(logicOperationOnPolygons(out1, out2)).toEqual(
|
|
39
|
-
// expect.arrayContaining(res)
|
|
40
|
-
// )
|
|
41
|
-
// })
|
|
42
|
-
// test('returns intersecting polygon when out2 is included in out1', () => {
|
|
43
|
-
// const O = { x: 0, y: 0, z: 0 }
|
|
44
|
-
// const A = { x: 20, y: 0, z: 0 }
|
|
45
|
-
// const B = { x: 20, y: 20, z: 0 }
|
|
46
|
-
// const C = { x: 0, y: 20, z: 0 }
|
|
47
|
-
// const D = { x: 5, y: 5, z: 0 }
|
|
48
|
-
// const E = { x: 15, y: 5, z: 0 }
|
|
49
|
-
// const F = { x: 15, y: 15, z: 0 }
|
|
50
|
-
// const G = { x: 5, y: 15, z: 0 }
|
|
51
|
-
// const out1 = [B, C, O, A]
|
|
52
|
-
// const out2 = [D, E, F, G]
|
|
53
|
-
// const res = [[D, E, F, G]]
|
|
54
|
-
// expect(logicOperationOnPolygons(out2, out1)).toEqual(
|
|
55
|
-
// expect.arrayContaining(res)
|
|
56
|
-
// )
|
|
57
|
-
// })
|
|
58
|
-
// test('check intersection at altitude', () => {
|
|
59
|
-
// const out1 = [
|
|
60
|
-
// {
|
|
61
|
-
// x: 2500,
|
|
62
|
-
// y: 9000,
|
|
63
|
-
// z: 18160,
|
|
64
|
-
// },
|
|
65
|
-
// {
|
|
66
|
-
// x: 2500,
|
|
67
|
-
// y: 10000,
|
|
68
|
-
// z: 18160,
|
|
69
|
-
// },
|
|
70
|
-
// {
|
|
71
|
-
// x: 0,
|
|
72
|
-
// y: 10000,
|
|
73
|
-
// z: 18160,
|
|
74
|
-
// },
|
|
75
|
-
// {
|
|
76
|
-
// x: 0,
|
|
77
|
-
// y: 9000,
|
|
78
|
-
// z: 18160,
|
|
79
|
-
// },
|
|
80
|
-
// ]
|
|
81
|
-
// const out2 = [
|
|
82
|
-
// {
|
|
83
|
-
// x: 1000,
|
|
84
|
-
// y: 10000,
|
|
85
|
-
// z: 18160,
|
|
86
|
-
// },
|
|
87
|
-
// {
|
|
88
|
-
// x: 1000,
|
|
89
|
-
// y: -1000,
|
|
90
|
-
// z: 18160,
|
|
91
|
-
// },
|
|
92
|
-
// {
|
|
93
|
-
// x: 10000,
|
|
94
|
-
// y: -1000,
|
|
95
|
-
// z: 18160,
|
|
96
|
-
// },
|
|
97
|
-
// {
|
|
98
|
-
// x: 10000,
|
|
99
|
-
// y: 10000,
|
|
100
|
-
// z: 18160,
|
|
101
|
-
// },
|
|
102
|
-
// ]
|
|
103
|
-
// expect(
|
|
104
|
-
// logicOperationOnPolygons(out2, out1).every(
|
|
105
|
-
// (outline) => calculateArea(outline) <= calculateArea(out1)
|
|
106
|
-
// )
|
|
107
|
-
// ).toBe(true)
|
|
108
|
-
// })
|
|
109
|
-
test('check intersection at altitude Triangle-Rectangle', () => {
|
|
110
|
-
const out1 = [
|
|
111
|
-
{
|
|
112
|
-
x: 0,
|
|
113
|
-
y: -1800,
|
|
114
|
-
z: 3000,
|
|
115
|
-
},
|
|
116
|
-
{
|
|
117
|
-
x: 3000,
|
|
118
|
-
y: 9300,
|
|
119
|
-
z: 3000,
|
|
120
|
-
},
|
|
121
|
-
{
|
|
122
|
-
x: 2500,
|
|
123
|
-
y: 9300,
|
|
124
|
-
z: 3000,
|
|
125
|
-
},
|
|
126
|
-
]
|
|
127
|
-
const out2 = [
|
|
128
|
-
{
|
|
129
|
-
x: 800,
|
|
130
|
-
y: 12000,
|
|
131
|
-
z: 3000,
|
|
132
|
-
},
|
|
133
|
-
{
|
|
134
|
-
x: 1200,
|
|
135
|
-
y: -6500,
|
|
136
|
-
z: 3000,
|
|
137
|
-
},
|
|
138
|
-
{
|
|
139
|
-
x: 8800,
|
|
140
|
-
y: -6500,
|
|
141
|
-
z: 3000,
|
|
142
|
-
},
|
|
143
|
-
{
|
|
144
|
-
x: 8800,
|
|
145
|
-
y: 12000,
|
|
146
|
-
z: 3000,
|
|
147
|
-
},
|
|
148
|
-
]
|
|
149
|
-
expect(
|
|
150
|
-
logicOperationOnPolygons(out2, out1).every(
|
|
151
|
-
(outline) => calculateArea(outline) <= calculateArea(out1)
|
|
152
|
-
)
|
|
153
|
-
).toBe(true)
|
|
154
|
-
})
|
|
155
|
-
// test('check intersection david star', () => {
|
|
156
|
-
// const out1 = [
|
|
157
|
-
// {
|
|
158
|
-
// x: 0,
|
|
159
|
-
// y: 0,
|
|
160
|
-
// z: 3000,
|
|
161
|
-
// },
|
|
162
|
-
// {
|
|
163
|
-
// x: 2000,
|
|
164
|
-
// y: 0,
|
|
165
|
-
// z: 3000,
|
|
166
|
-
// },
|
|
167
|
-
// {
|
|
168
|
-
// x: 1000,
|
|
169
|
-
// y: 2000,
|
|
170
|
-
// z: 3000,
|
|
171
|
-
// },
|
|
172
|
-
// ]
|
|
173
|
-
// const out2 = [
|
|
174
|
-
// {
|
|
175
|
-
// x: 0,
|
|
176
|
-
// y: 1000,
|
|
177
|
-
// z: 3000,
|
|
178
|
-
// },
|
|
179
|
-
// {
|
|
180
|
-
// x: 2000,
|
|
181
|
-
// y: 1000,
|
|
182
|
-
// z: 3000,
|
|
183
|
-
// },
|
|
184
|
-
// {
|
|
185
|
-
// x: 1000,
|
|
186
|
-
// y: -1000,
|
|
187
|
-
// z: 3000,
|
|
188
|
-
// },
|
|
189
|
-
// ]
|
|
190
|
-
// expect(
|
|
191
|
-
// logicOperationOnPolygons(out2, out1).every(
|
|
192
|
-
// (outline) => calculateArea(outline) <= calculateArea(out1)
|
|
193
|
-
// )
|
|
194
|
-
// ).toBe(true)
|
|
195
|
-
// })
|
|
196
|
-
// test('check intersection two triangle with 2 corner of the 2nd in the first', () => {
|
|
197
|
-
// const out1 = [
|
|
198
|
-
// {
|
|
199
|
-
// x: 0,
|
|
200
|
-
// y: 0,
|
|
201
|
-
// z: 3000,
|
|
202
|
-
// },
|
|
203
|
-
// {
|
|
204
|
-
// x: 2000,
|
|
205
|
-
// y: 0,
|
|
206
|
-
// z: 3000,
|
|
207
|
-
// },
|
|
208
|
-
// {
|
|
209
|
-
// x: 1000,
|
|
210
|
-
// y: 2000,
|
|
211
|
-
// z: 3000,
|
|
212
|
-
// },
|
|
213
|
-
// ]
|
|
214
|
-
// const out2 = [
|
|
215
|
-
// {
|
|
216
|
-
// x: 1000,
|
|
217
|
-
// y: 200,
|
|
218
|
-
// z: 3000,
|
|
219
|
-
// },
|
|
220
|
-
// {
|
|
221
|
-
// x: 500,
|
|
222
|
-
// y: 200,
|
|
223
|
-
// z: 3000,
|
|
224
|
-
// },
|
|
225
|
-
// {
|
|
226
|
-
// x: 1000,
|
|
227
|
-
// y: -1000,
|
|
228
|
-
// z: 3000,
|
|
229
|
-
// },
|
|
230
|
-
// ]
|
|
231
|
-
// expect(
|
|
232
|
-
// logicOperationOnPolygons(out2, out1).every(
|
|
233
|
-
// (outline) => calculateArea(outline) <= calculateArea(out1)
|
|
234
|
-
// )
|
|
235
|
-
// ).toBe(true)
|
|
236
|
-
// })
|
|
237
|
-
// test('check intersection two triangle with 1 corner of the 2nd in the first', () => {
|
|
238
|
-
// const out1 = [
|
|
239
|
-
// {
|
|
240
|
-
// x: 0,
|
|
241
|
-
// y: 0,
|
|
242
|
-
// z: 3000,
|
|
243
|
-
// },
|
|
244
|
-
// {
|
|
245
|
-
// x: 2000,
|
|
246
|
-
// y: 0,
|
|
247
|
-
// z: 3000,
|
|
248
|
-
// },
|
|
249
|
-
// {
|
|
250
|
-
// x: 1000,
|
|
251
|
-
// y: 2000,
|
|
252
|
-
// z: 3000,
|
|
253
|
-
// },
|
|
254
|
-
// ]
|
|
255
|
-
// const out2 = [
|
|
256
|
-
// {
|
|
257
|
-
// x: 1000,
|
|
258
|
-
// y: 200,
|
|
259
|
-
// z: 3000,
|
|
260
|
-
// },
|
|
261
|
-
// {
|
|
262
|
-
// x: 5000,
|
|
263
|
-
// y: 200,
|
|
264
|
-
// z: 3000,
|
|
265
|
-
// },
|
|
266
|
-
// {
|
|
267
|
-
// x: 1000,
|
|
268
|
-
// y: -1000,
|
|
269
|
-
// z: 3000,
|
|
270
|
-
// },
|
|
271
|
-
// ]
|
|
272
|
-
// expect(
|
|
273
|
-
// logicOperationOnPolygons(out2, out1).every(
|
|
274
|
-
// (outline) => calculateArea(outline) <= calculateArea(out1)
|
|
275
|
-
// )
|
|
276
|
-
// ).toBe(true)
|
|
277
|
-
// })
|
|
278
|
-
// test('check triangle-rectangle', () => {
|
|
279
|
-
// const out1 = [
|
|
280
|
-
// {
|
|
281
|
-
// x: 0,
|
|
282
|
-
// y: 0,
|
|
283
|
-
// z: 3000,
|
|
284
|
-
// },
|
|
285
|
-
// {
|
|
286
|
-
// x: 2000,
|
|
287
|
-
// y: 0,
|
|
288
|
-
// z: 3000,
|
|
289
|
-
// },
|
|
290
|
-
// {
|
|
291
|
-
// x: 1000,
|
|
292
|
-
// y: 2000,
|
|
293
|
-
// z: 3000,
|
|
294
|
-
// },
|
|
295
|
-
// ]
|
|
296
|
-
// const out2 = [
|
|
297
|
-
// {
|
|
298
|
-
// x: 500,
|
|
299
|
-
// y: 4000,
|
|
300
|
-
// z: 3000,
|
|
301
|
-
// },
|
|
302
|
-
// {
|
|
303
|
-
// x: 500,
|
|
304
|
-
// y: -1000,
|
|
305
|
-
// z: 3000,
|
|
306
|
-
// },
|
|
307
|
-
// {
|
|
308
|
-
// x: 1500,
|
|
309
|
-
// y: -1000,
|
|
310
|
-
// z: 3000,
|
|
311
|
-
// },
|
|
312
|
-
// {
|
|
313
|
-
// x: 1500,
|
|
314
|
-
// y: 4000,
|
|
315
|
-
// z: 3000,
|
|
316
|
-
// },
|
|
317
|
-
// ]
|
|
318
|
-
// expect(
|
|
319
|
-
// logicOperationOnPolygons(out2, out1).every(
|
|
320
|
-
// (outline) => calculateArea(outline) <= calculateArea(out1)
|
|
321
|
-
// )
|
|
322
|
-
// ).toBe(true)
|
|
323
|
-
// })
|
|
324
|
-
})
|