@eturnity/eturnity_maths 7.42.1 → 7.42.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
package/src/geometry.js
CHANGED
|
@@ -77,6 +77,10 @@ export function getSnapedValue(value, snaps, tolerance) {
|
|
|
77
77
|
)
|
|
78
78
|
return closeSnapsItem.value
|
|
79
79
|
}
|
|
80
|
+
export function getAngleInDegFrom2DENUVector(v) {
|
|
81
|
+
const angle = Math.atan2(v.y, -v.x)
|
|
82
|
+
return ((angle * 180) / Math.PI + 90 + 360) % 360
|
|
83
|
+
}
|
|
80
84
|
export function getAngleInDegFromCanvasVector(v) {
|
|
81
85
|
const angle = Math.atan2(v.y, v.x)
|
|
82
86
|
return ((angle * 180) / Math.PI + 90 + 360) % 360
|
package/src/index.js
CHANGED
package/src/spherical.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { get3DDistanceBetweenPoints, midPoint } from './geometry'
|
|
2
|
+
import {
|
|
3
|
+
normalizeVector,
|
|
4
|
+
substractVector,
|
|
5
|
+
addVector,
|
|
6
|
+
multiplyVector,
|
|
7
|
+
} from './vector'
|
|
8
|
+
|
|
9
|
+
export function fromSphericalCoordinatesToENU(radius, altitude, azimuth) {
|
|
10
|
+
return {
|
|
11
|
+
x: -radius * Math.cos(altitude) * Math.sin(azimuth),
|
|
12
|
+
y: -radius * Math.cos(altitude) * Math.cos(azimuth),
|
|
13
|
+
z: radius * Math.sin(altitude),
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export function getBoundingSphere(cloudPoint) {
|
|
17
|
+
let radius = 0
|
|
18
|
+
let center = { x: 0, y: 0, z: 0 }
|
|
19
|
+
if (cloudPoint.length == 0) {
|
|
20
|
+
return { radius, center }
|
|
21
|
+
}
|
|
22
|
+
const P0 = cloudPoint[0]
|
|
23
|
+
let vMin = { x: P0.x, y: P0.y, z: P0.z }
|
|
24
|
+
let vMax = { x: P0.x, y: P0.y, z: P0.z }
|
|
25
|
+
for (let i = 1; i < cloudPoint.length; i++) {
|
|
26
|
+
let P = cloudPoint[i]
|
|
27
|
+
vMin.x = Math.min(P.x, vMin.x)
|
|
28
|
+
vMin.y = Math.min(P.y, vMin.y)
|
|
29
|
+
vMin.z = Math.min(P.z, vMin.z)
|
|
30
|
+
vMax.x = Math.min(P.x, vMax.x)
|
|
31
|
+
vMax.y = Math.min(P.y, vMax.y)
|
|
32
|
+
vMax.z = Math.min(P.z, vMax.z)
|
|
33
|
+
}
|
|
34
|
+
center = midPoint(vMin, vMax)
|
|
35
|
+
radius = get3DDistanceBetweenPoints(vMin, vMax) / 2
|
|
36
|
+
for (let i = 0; i < cloudPoint.length; i++) {
|
|
37
|
+
let P = cloudPoint[i]
|
|
38
|
+
let distanceToCenter = get3DDistanceBetweenPoints(P, center)
|
|
39
|
+
if (distanceToCenter > radius) {
|
|
40
|
+
let difference = distanceToCenter - radius
|
|
41
|
+
radius = (radius + distanceToCenter) / 2
|
|
42
|
+
center = addVector(
|
|
43
|
+
center,
|
|
44
|
+
multiplyVector(
|
|
45
|
+
difference / 2,
|
|
46
|
+
normalizeVector(substractVector(P, center))
|
|
47
|
+
)
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
radius = distanceToCenter
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return { radius, center }
|
|
54
|
+
}
|
|
@@ -1,75 +1,86 @@
|
|
|
1
|
-
import { getNormalVectortoEdgeTowardPolygon} from '../../index'
|
|
1
|
+
import { getNormalVectortoEdgeTowardPolygon } from '../../index'
|
|
2
2
|
|
|
3
3
|
function toBeCloseToVector(received, expected, tolerance = 0.01) {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const recPoint = received
|
|
8
|
-
const expPoint = expected
|
|
4
|
+
const recPoint = received
|
|
5
|
+
const expPoint = expected
|
|
9
6
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
7
|
+
if (
|
|
8
|
+
Math.abs(recPoint.x - expPoint.x) > tolerance ||
|
|
9
|
+
Math.abs(recPoint.y - expPoint.y) > tolerance ||
|
|
10
|
+
Math.abs(recPoint.z - expPoint.z) > tolerance
|
|
11
|
+
) {
|
|
12
|
+
return {
|
|
13
|
+
message: () =>
|
|
14
|
+
`Expected points to be close, but found ${JSON.stringify(
|
|
15
|
+
recPoint
|
|
16
|
+
)} and ${JSON.stringify(expPoint)}`,
|
|
17
|
+
pass: false,
|
|
18
|
+
}
|
|
19
|
+
}
|
|
22
20
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
21
|
+
return {
|
|
22
|
+
message: () => `Points are close within the given tolerance`,
|
|
23
|
+
pass: true,
|
|
24
|
+
}
|
|
28
25
|
}
|
|
29
26
|
expect.extend({ toBeCloseToVector })
|
|
30
27
|
|
|
31
|
-
const A = {x:0,y:0,z:0}
|
|
32
|
-
const B = {x:10,y:0,z:0}
|
|
33
|
-
const C = {x:10,y:10,z:0}
|
|
34
|
-
const D = {x:0,y:10,z:0}
|
|
35
|
-
const E = {x:5,y:5,z:0}
|
|
36
|
-
const F = {x:2,y:0,z:0}
|
|
37
|
-
const G = {x:3,y
|
|
38
|
-
const H = {x:4,y:0,z:0}
|
|
28
|
+
const A = { x: 0, y: 0, z: 0 }
|
|
29
|
+
const B = { x: 10, y: 0, z: 0 }
|
|
30
|
+
const C = { x: 10, y: 10, z: 0 }
|
|
31
|
+
const D = { x: 0, y: 10, z: 0 }
|
|
32
|
+
const E = { x: 5, y: 5, z: 0 }
|
|
33
|
+
const F = { x: 2, y: 0, z: 0 }
|
|
34
|
+
const G = { x: 3, y: -10, z: 0 }
|
|
35
|
+
const H = { x: 4, y: 0, z: 0 }
|
|
39
36
|
describe('getNormalVectortoEdgeTowardPolygon function', () => {
|
|
40
37
|
test('anti-clockwise outline ABCD', () => {
|
|
41
|
-
const outline = [A,B,C,D]
|
|
42
|
-
const expectedNormalVector={x:0,y:1,z:0}
|
|
43
|
-
expect(getNormalVectortoEdgeTowardPolygon(0,outline)).toBeCloseToVector(
|
|
38
|
+
const outline = [A, B, C, D]
|
|
39
|
+
const expectedNormalVector = { x: 0, y: 1, z: 0 }
|
|
40
|
+
expect(getNormalVectortoEdgeTowardPolygon(0, outline)).toBeCloseToVector(
|
|
41
|
+
expectedNormalVector
|
|
42
|
+
)
|
|
44
43
|
})
|
|
45
44
|
test('clockwise outline', () => {
|
|
46
|
-
const outline = [A,D,C,B]
|
|
47
|
-
const expectedNormalVector={x:1,y:0,z:0}
|
|
48
|
-
expect(getNormalVectortoEdgeTowardPolygon(0,outline)).toBeCloseToVector(
|
|
45
|
+
const outline = [A, D, C, B]
|
|
46
|
+
const expectedNormalVector = { x: 1, y: 0, z: 0 }
|
|
47
|
+
expect(getNormalVectortoEdgeTowardPolygon(0, outline)).toBeCloseToVector(
|
|
48
|
+
expectedNormalVector
|
|
49
|
+
)
|
|
49
50
|
})
|
|
50
51
|
test('anti clockwise concave outline', () => {
|
|
51
|
-
const outline = [A,E,D,C,B]
|
|
52
|
-
const expectedNormalVector={x:0,y
|
|
53
|
-
expect(getNormalVectortoEdgeTowardPolygon(2,outline)).toBeCloseToVector(
|
|
52
|
+
const outline = [A, E, D, C, B]
|
|
53
|
+
const expectedNormalVector = { x: 0, y: -1, z: 0 }
|
|
54
|
+
expect(getNormalVectortoEdgeTowardPolygon(2, outline)).toBeCloseToVector(
|
|
55
|
+
expectedNormalVector
|
|
56
|
+
)
|
|
54
57
|
})
|
|
55
58
|
test('clockwise concave outline', () => {
|
|
56
|
-
const outline = [A,E,B,C,D]
|
|
57
|
-
const expectedNormalVector={x
|
|
58
|
-
expect(getNormalVectortoEdgeTowardPolygon(2,outline)).toBeCloseToVector(
|
|
59
|
+
const outline = [A, E, B, C, D]
|
|
60
|
+
const expectedNormalVector = { x: -1, y: 0, z: 0 }
|
|
61
|
+
expect(getNormalVectortoEdgeTowardPolygon(2, outline)).toBeCloseToVector(
|
|
62
|
+
expectedNormalVector
|
|
63
|
+
)
|
|
59
64
|
})
|
|
60
65
|
test('anti-clockwise concave outline', () => {
|
|
61
|
-
const outline = [A,E,B,C,D]
|
|
62
|
-
const expectedNormalVector={x
|
|
63
|
-
expect(getNormalVectortoEdgeTowardPolygon(2,outline)).toBeCloseToVector(
|
|
66
|
+
const outline = [A, E, B, C, D]
|
|
67
|
+
const expectedNormalVector = { x: -1, y: 0, z: 0 }
|
|
68
|
+
expect(getNormalVectortoEdgeTowardPolygon(2, outline)).toBeCloseToVector(
|
|
69
|
+
expectedNormalVector
|
|
70
|
+
)
|
|
64
71
|
})
|
|
65
72
|
test('clockwise concave outline', () => {
|
|
66
|
-
const outline = [A,E,B,C,D]
|
|
67
|
-
const expectedNormalVector={x:1,y:0,z:0}
|
|
68
|
-
expect(getNormalVectortoEdgeTowardPolygon(4,outline)).toBeCloseToVector(
|
|
73
|
+
const outline = [A, E, B, C, D]
|
|
74
|
+
const expectedNormalVector = { x: 1, y: 0, z: 0 }
|
|
75
|
+
expect(getNormalVectortoEdgeTowardPolygon(4, outline)).toBeCloseToVector(
|
|
76
|
+
expectedNormalVector
|
|
77
|
+
)
|
|
69
78
|
})
|
|
70
79
|
test('anti-clockwise concave on first outline', () => {
|
|
71
|
-
const outline = [A,F,G,B,C,D]
|
|
72
|
-
const expectedNormalVector={x:0,y:1,z:0}
|
|
73
|
-
expect(getNormalVectortoEdgeTowardPolygon(0,outline)).toBeCloseToVector(
|
|
80
|
+
const outline = [A, F, G, B, C, D]
|
|
81
|
+
const expectedNormalVector = { x: 0, y: 1, z: 0 }
|
|
82
|
+
expect(getNormalVectortoEdgeTowardPolygon(0, outline)).toBeCloseToVector(
|
|
83
|
+
expectedNormalVector
|
|
84
|
+
)
|
|
74
85
|
})
|
|
75
|
-
})
|
|
86
|
+
})
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { fromSphericalCoordinatesToENU } from '../../index'
|
|
2
|
+
function toBeCloseToVector(received, expected, tolerance = 0.01) {
|
|
3
|
+
const recPoint = received
|
|
4
|
+
const expPoint = expected
|
|
5
|
+
|
|
6
|
+
if (
|
|
7
|
+
Math.abs(recPoint.x - expPoint.x) > tolerance ||
|
|
8
|
+
Math.abs(recPoint.y - expPoint.y) > tolerance ||
|
|
9
|
+
Math.abs(recPoint.z - expPoint.z) > tolerance
|
|
10
|
+
) {
|
|
11
|
+
return {
|
|
12
|
+
message: () =>
|
|
13
|
+
`Expected points to be close, but found ${JSON.stringify(
|
|
14
|
+
recPoint
|
|
15
|
+
)} and ${JSON.stringify(expPoint)}`,
|
|
16
|
+
pass: false,
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return {
|
|
21
|
+
message: () => `Points are close within the given tolerance`,
|
|
22
|
+
pass: true,
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
expect.extend({ toBeCloseToVector })
|
|
26
|
+
describe('fromSphericalCoordinatesToENU function', () => {
|
|
27
|
+
test('rising on east', () => {
|
|
28
|
+
let radius = 100
|
|
29
|
+
let altitude = 0
|
|
30
|
+
let azimuth = (-90 * Math.PI) / 180
|
|
31
|
+
|
|
32
|
+
expect(
|
|
33
|
+
fromSphericalCoordinatesToENU(radius, altitude, azimuth)
|
|
34
|
+
).toBeCloseToVector({ x: 100, y: 0, z: 0 })
|
|
35
|
+
})
|
|
36
|
+
test('setting on west', () => {
|
|
37
|
+
let radius = 100
|
|
38
|
+
let altitude = 0
|
|
39
|
+
let azimuth = (90 * Math.PI) / 180
|
|
40
|
+
|
|
41
|
+
expect(
|
|
42
|
+
fromSphericalCoordinatesToENU(radius, altitude, azimuth)
|
|
43
|
+
).toBeCloseToVector({ x: -100, y: 0, z: 0 })
|
|
44
|
+
})
|
|
45
|
+
test('high noon', () => {
|
|
46
|
+
let radius = 100
|
|
47
|
+
let altitude = (90 * Math.PI) / 180
|
|
48
|
+
let azimuth = 0
|
|
49
|
+
expect(
|
|
50
|
+
fromSphericalCoordinatesToENU(radius, altitude, azimuth)
|
|
51
|
+
).toBeCloseToVector({ x: 0, y: 0, z: 100 })
|
|
52
|
+
})
|
|
53
|
+
test('winter noon', () => {
|
|
54
|
+
let radius = 100
|
|
55
|
+
let altitude = (45 * Math.PI) / 180
|
|
56
|
+
let azimuth = 0
|
|
57
|
+
|
|
58
|
+
expect(
|
|
59
|
+
fromSphericalCoordinatesToENU(radius, altitude, azimuth)
|
|
60
|
+
).toBeCloseToVector({ x: 0, y: -70.71, z: 70.71 })
|
|
61
|
+
})
|
|
62
|
+
})
|