@eturnity/eturnity_maths 7.20.0 → 7.24.1
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/.eslintrc.js +28 -0
- package/.prettierrc +7 -0
- package/babel.config.js +2 -2
- package/eslint.config.mjs +10 -0
- package/package.json +5 -3
- package/src/config.js +110 -50
- package/src/coords.js +21 -21
- package/src/geo.js +111 -100
- package/src/geometry.js +920 -819
- package/src/index.js +10 -11
- package/src/intersectionPolygon.js +34 -28
- package/src/lib/concaveman.js +181 -181
- package/src/matrix.js +56 -50
- package/src/miscellaneous.js +45 -0
- package/src/objects/Circle.js +76 -41
- package/src/objects/Line.js +275 -177
- package/src/objects/Point.js +30 -27
- package/src/objects/Polygon.js +324 -243
- package/src/objects/derivedState/AddMargin.js +142 -145
- package/src/objects/derivedState/updateComputedGeometryPolygon.js +274 -253
- package/src/objects/graph/DFS.js +69 -69
- package/src/objects/graph/graphCreation.js +47 -44
- package/src/objects/hydrate.js +26 -26
- package/src/snap.js +24 -18
- package/src/splitMergePolygons.js +585 -521
- package/src/test/maths.test.js +7 -7
- package/src/vector.js +66 -66
package/src/matrix.js
CHANGED
|
@@ -1,59 +1,65 @@
|
|
|
1
|
-
import { substractVector } from
|
|
1
|
+
import { substractVector } from './vector'
|
|
2
2
|
export function inverse2x2Matrix([a, b, c, d]) {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
}
|
|
9
|
-
return [d / det, -b / det, -c / det, a / det]
|
|
3
|
+
//inverse matrix |a,c|
|
|
4
|
+
// |b,d|
|
|
5
|
+
const det = a * b - c * b
|
|
6
|
+
if (det == 0) {
|
|
7
|
+
return null
|
|
10
8
|
}
|
|
9
|
+
return [d / det, -b / det, -c / det, a / det]
|
|
10
|
+
}
|
|
11
11
|
|
|
12
12
|
export function inverse3x3matrix(m) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
13
|
+
let [[a, b, c], [d, e, f], [g, h, i]] = m
|
|
14
|
+
let x = e * i - h * f
|
|
15
|
+
let y = f * g - d * i
|
|
16
|
+
let z = d * h - g * e
|
|
17
|
+
let det = a * x + b * y + c * z
|
|
18
|
+
return det != 0
|
|
19
|
+
? [
|
|
20
|
+
[x, c * h - b * i, b * f - c * e],
|
|
21
|
+
[y, a * i - c * g, d * c - a * f],
|
|
22
|
+
[z, g * b - a * h, a * e - d * b]
|
|
23
|
+
].map((r) => r.map((v) => (v /= det)))
|
|
24
|
+
: null
|
|
25
|
+
}
|
|
26
|
+
export function multiplyMatrices(a, b) {
|
|
27
|
+
if (!Array.isArray(a) || !Array.isArray(b) || !a.length || !b.length) {
|
|
28
|
+
throw new Error('arguments should be in 2-dimensional array format')
|
|
25
29
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
let y = b[0].length
|
|
33
|
-
if (b.length !== z) {
|
|
34
|
-
throw new Error(
|
|
35
|
-
'number of columns in the first matrix should be the same as the number of rows in the second'
|
|
36
|
-
)
|
|
37
|
-
}
|
|
38
|
-
let productRow = Array.apply(null, new Array(y)).map(
|
|
39
|
-
Number.prototype.valueOf,
|
|
40
|
-
0
|
|
30
|
+
let x = a.length
|
|
31
|
+
let z = a[0].length
|
|
32
|
+
let y = b[0].length
|
|
33
|
+
if (b.length !== z) {
|
|
34
|
+
throw new Error(
|
|
35
|
+
'number of columns in the first matrix should be the same as the number of rows in the second'
|
|
41
36
|
)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
37
|
+
}
|
|
38
|
+
let productRow = Array.apply(null, new Array(y)).map(
|
|
39
|
+
Number.prototype.valueOf,
|
|
40
|
+
0
|
|
41
|
+
)
|
|
42
|
+
let product = new Array(x)
|
|
43
|
+
for (let p = 0; p < x; p++) {
|
|
44
|
+
product[p] = productRow.slice()
|
|
45
|
+
}
|
|
46
|
+
for (let i = 0; i < x; i++) {
|
|
47
|
+
for (let j = 0; j < y; j++) {
|
|
48
|
+
for (let k = 0; k < z; k++) {
|
|
49
|
+
product[i][j] += a[i][k] * b[k][j]
|
|
51
50
|
}
|
|
52
51
|
}
|
|
53
|
-
return product
|
|
54
52
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
53
|
+
return product
|
|
54
|
+
}
|
|
55
|
+
export function rotateTransformation(point, angle, center = { x: 0, y: 0 }) {
|
|
56
|
+
let rotationMatrix = [
|
|
57
|
+
[Math.cos(angle), Math.sin(angle)],
|
|
58
|
+
[-Math.sin(angle), Math.cos(angle)]
|
|
59
|
+
]
|
|
60
|
+
let k = multiplyMatrices(rotationMatrix, [
|
|
61
|
+
[point.x - center.x],
|
|
62
|
+
[point.y - center.y]
|
|
63
|
+
])
|
|
64
|
+
return { x: k[0][0] + center.x, y: k[1][0] + center.y }
|
|
65
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export function groupIntoConsecutiveBuckets(arr, periodicity) {
|
|
2
|
+
if (arr.length == 0) {
|
|
3
|
+
return []
|
|
4
|
+
}
|
|
5
|
+
// Sort the array
|
|
6
|
+
arr.sort((a, b) => a - b)
|
|
7
|
+
|
|
8
|
+
// Initialize an array to store buckets
|
|
9
|
+
const buckets = []
|
|
10
|
+
|
|
11
|
+
// Initialize the first bucket with the first element of the array
|
|
12
|
+
let currentBucket = [arr[0]]
|
|
13
|
+
|
|
14
|
+
// Iterate through the sorted array
|
|
15
|
+
for (let i = 1; i < arr.length; i++) {
|
|
16
|
+
// Calculate the gap considering the periodicity
|
|
17
|
+
let gap = (arr[i] - arr[i - 1] + periodicity) % periodicity
|
|
18
|
+
|
|
19
|
+
// If the current element is consecutive to the previous one, add it to the current bucket
|
|
20
|
+
if (gap === 1) {
|
|
21
|
+
currentBucket.push(arr[i])
|
|
22
|
+
} else {
|
|
23
|
+
// If there's a gap, start a new bucket
|
|
24
|
+
buckets.push(currentBucket)
|
|
25
|
+
currentBucket = [arr[i]]
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Push the last bucket into the buckets array
|
|
30
|
+
buckets.push(currentBucket)
|
|
31
|
+
|
|
32
|
+
// Check if the last bucket and the first bucket are consecutive
|
|
33
|
+
if (
|
|
34
|
+
(buckets[buckets.length - 1][buckets[buckets.length - 1].length - 1] + 1) %
|
|
35
|
+
periodicity ===
|
|
36
|
+
buckets[0][0]
|
|
37
|
+
) {
|
|
38
|
+
// Merge the last bucket with the first one
|
|
39
|
+
buckets[0] = buckets[buckets.length - 1].concat(buckets[0])
|
|
40
|
+
// Remove the last bucket
|
|
41
|
+
buckets.pop()
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return buckets
|
|
45
|
+
}
|
package/src/objects/Circle.js
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
|
-
|
|
2
1
|
import {
|
|
3
2
|
translate2D,
|
|
4
3
|
verticalProjectionOnPlane,
|
|
5
4
|
get3DDistanceBetweenPoints,
|
|
6
|
-
getDistanceBetweenPoints
|
|
5
|
+
getDistanceBetweenPoints
|
|
7
6
|
} from '../geometry'
|
|
8
7
|
import { v4 as uuidv4 } from 'uuid'
|
|
9
|
-
import {Point} from './Point'
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
import { Point } from './Point'
|
|
9
|
+
import {
|
|
10
|
+
addVector,
|
|
11
|
+
multiplyVector,
|
|
12
|
+
substractVector,
|
|
13
|
+
vectorLength,
|
|
14
|
+
crossProduct,
|
|
15
|
+
dotProduct,
|
|
16
|
+
normalizeVector
|
|
17
|
+
} from '../vector'
|
|
13
18
|
|
|
14
19
|
export class Circle {
|
|
15
20
|
constructor(center, radius, layer) {
|
|
@@ -31,21 +36,33 @@ export class Circle {
|
|
|
31
36
|
circle.id = uuidv4()
|
|
32
37
|
return circle
|
|
33
38
|
}
|
|
34
|
-
getIntersections(object){
|
|
35
|
-
const intersections=[]
|
|
36
|
-
if(!object)return
|
|
37
|
-
if(object.type==
|
|
38
|
-
if(get3DDistanceBetweenPoints(object,this.center)==this.radius){
|
|
39
|
-
intersections.push({...object})
|
|
39
|
+
getIntersections(object) {
|
|
40
|
+
const intersections = []
|
|
41
|
+
if (!object) return
|
|
42
|
+
if (object.type == 'point') {
|
|
43
|
+
if (get3DDistanceBetweenPoints(object, this.center) == this.radius) {
|
|
44
|
+
intersections.push({ ...object })
|
|
40
45
|
}
|
|
41
|
-
}else if(object.type==
|
|
42
|
-
let P=object.getProjectedPoint(this.center)
|
|
43
|
-
let distance = get3DDistanceBetweenPoints(P,this.center)
|
|
44
|
-
if(distance<=this.radius){
|
|
45
|
-
let A=addVector(
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
} else if (object.type == 'line') {
|
|
47
|
+
let P = object.getProjectedPoint(this.center)
|
|
48
|
+
let distance = get3DDistanceBetweenPoints(P, this.center)
|
|
49
|
+
if (distance <= this.radius) {
|
|
50
|
+
let A = addVector(
|
|
51
|
+
P,
|
|
52
|
+
multiplyVector(
|
|
53
|
+
Math.sqrt(Math.pow(this.radius, 2) - Math.pow(distance, 2)),
|
|
54
|
+
object.getDirectionVector()
|
|
55
|
+
)
|
|
56
|
+
)
|
|
57
|
+
let B = addVector(
|
|
58
|
+
P,
|
|
59
|
+
multiplyVector(
|
|
60
|
+
-Math.sqrt(Math.pow(this.radius, 2) - Math.pow(distance, 2)),
|
|
61
|
+
object.getDirectionVector()
|
|
62
|
+
)
|
|
63
|
+
)
|
|
64
|
+
intersections.push({ ...A })
|
|
65
|
+
intersections.push({ ...B })
|
|
49
66
|
}
|
|
50
67
|
}
|
|
51
68
|
return intersections
|
|
@@ -54,35 +71,53 @@ export class Circle {
|
|
|
54
71
|
const toCanvasRef = canvasContext.toCanvasRef
|
|
55
72
|
let pxCenter = toCanvasRef(this.center)
|
|
56
73
|
let pxRadius = this.radius / canvasContext.mmPerPx
|
|
57
|
-
if(this.normalVector){
|
|
58
|
-
point.z=verticalProjectionOnPlane(
|
|
59
|
-
|
|
60
|
-
|
|
74
|
+
if (this.normalVector) {
|
|
75
|
+
point.z = verticalProjectionOnPlane(
|
|
76
|
+
point,
|
|
77
|
+
this.normalVector,
|
|
78
|
+
this.center
|
|
79
|
+
).z
|
|
80
|
+
} else {
|
|
81
|
+
point.z = this.center.z
|
|
61
82
|
}
|
|
62
83
|
return Math.abs(get3DDistanceBetweenPoints(point, pxCenter) - pxRadius)
|
|
63
84
|
}
|
|
64
85
|
getDistanceToPoint(point) {
|
|
65
86
|
return get3DDistanceBetweenPoints(point, this.getProjectedPoint(point))
|
|
66
|
-
}
|
|
67
|
-
getHorizontalDistanceToPoint(point) {
|
|
68
|
-
return getDistanceBetweenPoints(point, this.getVerticalProjectedPoint(point))
|
|
69
87
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
88
|
+
getHorizontalDistanceToPoint(point) {
|
|
89
|
+
return getDistanceBetweenPoints(
|
|
90
|
+
point,
|
|
91
|
+
this.getVerticalProjectedPoint(point)
|
|
92
|
+
)
|
|
93
|
+
}
|
|
94
|
+
isInPlane(plane) {
|
|
95
|
+
if (!plane) return false
|
|
96
|
+
const { point, normalVector } = plane
|
|
97
|
+
const circleNormalVector = this.normalVector || { x: 0, y: 0, z: 1 }
|
|
98
|
+
if (vectorLength(crossProduct(circleNormalVector, normalVector)) > 0.1)
|
|
99
|
+
return false
|
|
100
|
+
if (
|
|
101
|
+
dotProduct(
|
|
102
|
+
normalizeVector(substractVector(point, this.center)),
|
|
103
|
+
normalVector
|
|
104
|
+
) > 0.1
|
|
105
|
+
)
|
|
106
|
+
return false
|
|
76
107
|
return true
|
|
77
|
-
|
|
108
|
+
}
|
|
78
109
|
getProjectedPoint(point) {
|
|
79
|
-
if(this.normalVector){
|
|
80
|
-
point.z=verticalProjectionOnPlane(
|
|
81
|
-
|
|
82
|
-
|
|
110
|
+
if (this.normalVector) {
|
|
111
|
+
point.z = verticalProjectionOnPlane(
|
|
112
|
+
point,
|
|
113
|
+
this.normalVector,
|
|
114
|
+
this.center
|
|
115
|
+
).z
|
|
116
|
+
} else {
|
|
117
|
+
point.z = this.center.z
|
|
83
118
|
}
|
|
84
119
|
let distance = get3DDistanceBetweenPoints(point, this.center)
|
|
85
|
-
|
|
120
|
+
if (distance == 0) {
|
|
86
121
|
console.error("can't project center to cercle", this)
|
|
87
122
|
return null
|
|
88
123
|
}
|
|
@@ -93,9 +128,9 @@ export class Circle {
|
|
|
93
128
|
return P
|
|
94
129
|
}
|
|
95
130
|
getVerticalProjectedPoint(point) {
|
|
96
|
-
|
|
131
|
+
return this.getProjectedPoint(point)
|
|
97
132
|
}
|
|
98
133
|
translate(vectorInMm) {
|
|
99
134
|
this.center = translate2D(this.center, vectorInMm)
|
|
100
135
|
}
|
|
101
|
-
}
|
|
136
|
+
}
|