@eturnity/eturnity_maths 9.7.0 → 9.10.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/coords.js +44 -11
- package/src/geometry.js +47 -14
- package/src/geometryShortDistance.js +442 -0
- package/src/index.js +3 -0
- package/src/intersectionCheck.js +165 -0
- package/src/intersectionPolygon.js +24 -1
- package/src/matrix.js +15 -1
- package/src/objects/Circle.js +55 -5
- package/src/objects/Line.js +530 -264
- package/src/objects/Measurement.js +335 -0
- package/src/objects/Plane.js +176 -0
- package/src/objects/Point.js +16 -7
- package/src/objects/Polygon.js +130 -2
- package/src/objects/derivedState/nodesEdgesCreation.js +112 -35
- package/src/objects/derivedState/updateComputedGeometryPolygon.js +1 -0
- package/src/objects/graph/graphCreation.js +5 -5
- package/src/objects/hydrate.js +229 -0
- package/src/objects/index.js +2 -0
- package/src/plane.js +76 -0
- package/src/splitMergePolygons.js +8 -8
- package/src/tests/Line/isTouchingLine.spec.js +233 -0
- package/src/tests/Plane/CoordinateChange.spec.js +32 -0
- package/src/tests/coords/toRealityRefFunction.spec.js +25 -0
- package/src/tests/geometry/getAngleInDegFrom2DENUVector.spec.js +60 -0
- package/src/tests/geometry/projectionOnPlaneFollowingVector.spec.js +215 -0
- package/src/tests/geometryShortDistance/areObjectsIntersecting.spec.js +426 -0
- package/src/tests/geometryShortDistance/findClosestPoint.spec.js +53 -0
- package/src/tests/geometryShortDistance/getShortestSegmentCircleCircle.spec.js +126 -0
- package/src/tests/geometryShortDistance/getShortestSegmentLineCircle.spec.js +124 -0
- package/src/tests/geometryShortDistance/getShortestSegmentPointLine.spec.js +133 -0
- package/src/tests/geometryShortDistance/getShortestSegmentPointPoint.spec.js +115 -0
package/package.json
CHANGED
package/src/coords.js
CHANGED
|
@@ -1,13 +1,33 @@
|
|
|
1
|
-
|
|
1
|
+
import { multiplyMatrices } from './matrix'
|
|
2
|
+
import { Point } from './objects/Point'
|
|
3
|
+
import { defaultPlane } from './objects/Plane'
|
|
4
|
+
export function toRealityRefFunction(
|
|
5
|
+
canvasSize,
|
|
6
|
+
mmPerPx,
|
|
7
|
+
layoutOffset,
|
|
8
|
+
plane = defaultPlane
|
|
9
|
+
) {
|
|
2
10
|
return (point) => {
|
|
3
|
-
let
|
|
4
|
-
|
|
5
|
-
let
|
|
6
|
-
|
|
7
|
-
|
|
11
|
+
let xMm = (point.x - layoutOffset.x) * mmPerPx
|
|
12
|
+
let yMm = -(point.y - layoutOffset.y) * mmPerPx
|
|
13
|
+
let zMm = 0
|
|
14
|
+
if (plane) {
|
|
15
|
+
const pointInRealityCoordinates = plane.toRealityCoordinates({
|
|
16
|
+
x: xMm,
|
|
17
|
+
y: yMm,
|
|
18
|
+
z: zMm,
|
|
19
|
+
})
|
|
20
|
+
return pointInRealityCoordinates
|
|
21
|
+
}
|
|
22
|
+
return { x: xMm, y: yMm, z: point.z }
|
|
8
23
|
}
|
|
9
24
|
}
|
|
10
|
-
export function toCanvasRefFunction(
|
|
25
|
+
export function toCanvasRefFunction(
|
|
26
|
+
canvasSize,
|
|
27
|
+
mmPerPx,
|
|
28
|
+
layoutOffset,
|
|
29
|
+
plane = defaultPlane
|
|
30
|
+
) {
|
|
11
31
|
return (point) => {
|
|
12
32
|
if (!point) {
|
|
13
33
|
console.error('no point', point)
|
|
@@ -16,9 +36,22 @@ export function toCanvasRefFunction(canvasSize, mmPerPx, layoutOffset) {
|
|
|
16
36
|
console.error('no canvas Size')
|
|
17
37
|
return null
|
|
18
38
|
}
|
|
19
|
-
let
|
|
20
|
-
let
|
|
21
|
-
|
|
22
|
-
|
|
39
|
+
let xMm = point.x
|
|
40
|
+
let yMm = point.y
|
|
41
|
+
if (point.z === undefined || isNaN(point.z)) {
|
|
42
|
+
point.z = 0
|
|
43
|
+
}
|
|
44
|
+
if (plane) {
|
|
45
|
+
const pointInPlaneCoordinates = plane.toPlaneCoordinates({
|
|
46
|
+
x: point.x,
|
|
47
|
+
y: point.y,
|
|
48
|
+
z: point.z,
|
|
49
|
+
})
|
|
50
|
+
xMm = pointInPlaneCoordinates.x
|
|
51
|
+
yMm = pointInPlaneCoordinates.y
|
|
52
|
+
}
|
|
53
|
+
let canvasX = layoutOffset.x + xMm / mmPerPx
|
|
54
|
+
let canvasY = layoutOffset.y - yMm / mmPerPx
|
|
55
|
+
return new Point(canvasX, canvasY, 0)
|
|
23
56
|
}
|
|
24
57
|
}
|
package/src/geometry.js
CHANGED
|
@@ -102,8 +102,8 @@ export function getSnapedValue(value, snaps, tolerance) {
|
|
|
102
102
|
return closeSnapsItem.value
|
|
103
103
|
}
|
|
104
104
|
export function getAngleInDegFrom2DENUVector(v) {
|
|
105
|
-
const angle = Math.atan2(v.
|
|
106
|
-
return ((angle * 180) / Math.PI +
|
|
105
|
+
const angle = Math.atan2(v.x, v.y)
|
|
106
|
+
return ((angle * 180) / Math.PI + 360) % 360
|
|
107
107
|
}
|
|
108
108
|
export function getAngleInDegFromCanvasVector(v) {
|
|
109
109
|
const angle = Math.atan2(v.y, v.x)
|
|
@@ -135,8 +135,15 @@ export function getParallelLinePassingByPoint(A, B, C) {
|
|
|
135
135
|
const D = new Point(C.x + B.x - A.x, C.y + B.y - A.y, C.z + B.z - A.z)
|
|
136
136
|
return new Line(C, D, '')
|
|
137
137
|
}
|
|
138
|
-
|
|
139
|
-
|
|
138
|
+
export function getDistanceBetweenTwoParallelInfiniteLines(line0, line1) {
|
|
139
|
+
const A = line0.outline[0]
|
|
140
|
+
const u = line0.getDirectionVector()
|
|
141
|
+
const B = line1.outline[0]
|
|
142
|
+
const AB = substractVector(B, A)
|
|
143
|
+
const distance = vectorLength(crossProduct(AB, u))
|
|
144
|
+
return distance
|
|
145
|
+
}
|
|
146
|
+
export function getDataAboutTwo3DLines(A, u, B, v, isInfinite = true) {
|
|
140
147
|
let w = crossProduct(u, v)
|
|
141
148
|
let m = [
|
|
142
149
|
[u.x, v.x, w.x],
|
|
@@ -150,12 +157,17 @@ export function getDataAboutTwo3DLines(A, u, B, v) {
|
|
|
150
157
|
let AB = substractVector(B, A)
|
|
151
158
|
let [t1, t2, t3] = multiplyMatrices(mInv, [[AB.x], [AB.y], [AB.z]])
|
|
152
159
|
//M point on Au
|
|
160
|
+
if (!isInfinite) {
|
|
161
|
+
t1 = Math.max(0, Math.min(t1, 1))
|
|
162
|
+
t2 = Math.max(0, Math.min(t2, -1))
|
|
163
|
+
}
|
|
153
164
|
let M = addVector(A, multiplyVector(t1, u))
|
|
154
165
|
//N point on Bv
|
|
155
166
|
let N = addVector(B, multiplyVector(-t2, v))
|
|
156
167
|
let distance = get3DDistanceBetweenPoints(M, N)
|
|
157
168
|
return { m, mInv, M, N, A, B, u, v, w, distance, t1, t2, t3 }
|
|
158
169
|
}
|
|
170
|
+
|
|
159
171
|
export function vectorFromAngleInDegCanvas(angle) {
|
|
160
172
|
return {
|
|
161
173
|
x: Math.sin((angle * Math.PI) / 180),
|
|
@@ -540,7 +552,6 @@ export function isOnBorderOfPolygon(point, vs) {
|
|
|
540
552
|
export function isStrictlyInsidePolygon(point, vs) {
|
|
541
553
|
return isInsidePolygon(point, vs) && !isOnBorderOfPolygon(point, vs)
|
|
542
554
|
}
|
|
543
|
-
|
|
544
555
|
export function isInsidePolygon(point, vs) {
|
|
545
556
|
// ray-casting algorithm based on
|
|
546
557
|
// https://wrf.ecse.rpi.edu/Research/Short_Notes/pnpoly.html/pnpoly.html
|
|
@@ -676,7 +687,7 @@ export function get2PolygonsOutlineFrom3Paths(path1, path2, path3) {
|
|
|
676
687
|
return [poly1, poly2]
|
|
677
688
|
}
|
|
678
689
|
|
|
679
|
-
export function getPointOnLine(M, A, B) {
|
|
690
|
+
export function getPointOnLine(M, A, B, isIncludedInSegment = false) {
|
|
680
691
|
function zValueNotDefined(P) {
|
|
681
692
|
return P.z == undefined || isNaN(P.z)
|
|
682
693
|
}
|
|
@@ -705,9 +716,12 @@ export function getPointOnLine(M, A, B) {
|
|
|
705
716
|
P = M
|
|
706
717
|
} else {
|
|
707
718
|
// in case of 0 length line
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
719
|
+
let normalizedDot = dot / (distanceAB * distanceAB)
|
|
720
|
+
if (isIncludedInSegment) {
|
|
721
|
+
normalizedDot = Math.max(0, Math.min(normalizedDot, 1))
|
|
722
|
+
}
|
|
723
|
+
P.x = A.x + normalizedDot * AB.x
|
|
724
|
+
P.y = A.y + normalizedDot * AB.y
|
|
711
725
|
}
|
|
712
726
|
} else {
|
|
713
727
|
//make 3D projection on line
|
|
@@ -731,10 +745,13 @@ export function getPointOnLine(M, A, B) {
|
|
|
731
745
|
P = M
|
|
732
746
|
} else {
|
|
733
747
|
// in case of 0 length line
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
748
|
+
let normalizedDot = dot / (distanceAB * distanceAB)
|
|
749
|
+
if (isIncludedInSegment) {
|
|
750
|
+
normalizedDot = Math.max(0, Math.min(normalizedDot, 1))
|
|
751
|
+
}
|
|
752
|
+
P.x = A.x + normalizedDot * AB.x
|
|
753
|
+
P.y = A.y + normalizedDot * AB.y
|
|
754
|
+
P.z = A.z + normalizedDot * AB.z
|
|
738
755
|
}
|
|
739
756
|
}
|
|
740
757
|
//projection of the point to the line
|
|
@@ -768,7 +785,7 @@ export function isPointBetweenSegment(A, B, C) {
|
|
|
768
785
|
const AB = getDistanceBetweenPoints(A, B)
|
|
769
786
|
const AC = getDistanceBetweenPoints(A, C)
|
|
770
787
|
const BC = getDistanceBetweenPoints(C, B)
|
|
771
|
-
const isBetween = AB
|
|
788
|
+
const isBetween = AB <= BC && AC <= BC
|
|
772
789
|
return isBetween
|
|
773
790
|
}
|
|
774
791
|
export function get3pointNotAlignedFromOutline(outline) {
|
|
@@ -870,6 +887,22 @@ export function verticalProjectionOnPlane(p, n, o) {
|
|
|
870
887
|
const projectedPoint = { ...p, z: projectedHeight }
|
|
871
888
|
return projectedPoint
|
|
872
889
|
}
|
|
890
|
+
export function projectionOnPlaneFollowingVector(p, n, o, v) {
|
|
891
|
+
// if p belongs to (n,o) plane return p
|
|
892
|
+
const opn = dotProduct(substractVector(p, o), n)
|
|
893
|
+
if (opn == 0) {
|
|
894
|
+
return p
|
|
895
|
+
}
|
|
896
|
+
//if n and v are normal to each other, return error
|
|
897
|
+
const nv = dotProduct(n, v)
|
|
898
|
+
if (nv == 0) {
|
|
899
|
+
console.warn('projection plane and vector are coplanar')
|
|
900
|
+
throw new Error('Cannot project: normal vector and direction vector are perpendicular')
|
|
901
|
+
}
|
|
902
|
+
const lambda = -opn / nv
|
|
903
|
+
const projectedPoint = addVector(p, multiplyVector(lambda, v))
|
|
904
|
+
return projectedPoint
|
|
905
|
+
}
|
|
873
906
|
|
|
874
907
|
export function calcPolygonArea(vertices) {
|
|
875
908
|
var total = 0
|
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getDistanceBetweenPoints,
|
|
3
|
+
get3DDistanceBetweenPoints,
|
|
4
|
+
isSamePoint3D,
|
|
5
|
+
getDataAboutTwo3DLines,
|
|
6
|
+
verticalProjectionOnPlane,
|
|
7
|
+
getDistanceBetweenTwoParallelInfiniteLines,
|
|
8
|
+
} from './geometry'
|
|
9
|
+
import { areAlmostCollinear, substractVector, dotProduct } from './vector'
|
|
10
|
+
import { Point } from './objects/Point'
|
|
11
|
+
import { Line } from './objects/Line'
|
|
12
|
+
import { Circle } from './objects/Circle'
|
|
13
|
+
import { Polygon } from './objects/Polygon'
|
|
14
|
+
import { areObjectsIntersecting } from './intersectionCheck'
|
|
15
|
+
import { defaultPlane } from './objects/Plane'
|
|
16
|
+
/**
|
|
17
|
+
* Returns the shortest segment between two objects
|
|
18
|
+
* @param {Object} obj0 - First object (Point, Line, Circle, or Polygon)
|
|
19
|
+
* @param {Object} obj1 - Second object (Point, Line, Circle, or Polygon)
|
|
20
|
+
* @param {Object} point - Reference point (used to disambiguate when multiple segments exist)
|
|
21
|
+
* @returns {Array} [pointOnObj0, pointOnObj1] - Two points forming the shortest segment
|
|
22
|
+
*/
|
|
23
|
+
export function getShortestSegmentBetweenObjects(
|
|
24
|
+
obj0,
|
|
25
|
+
obj1,
|
|
26
|
+
point,
|
|
27
|
+
projectionPlane = defaultPlane
|
|
28
|
+
) {
|
|
29
|
+
// Check if objects intersect
|
|
30
|
+
if (areObjectsIntersecting(obj0, obj1)) {
|
|
31
|
+
if (point) {
|
|
32
|
+
point = new Point(point.x, point.y, point.z)
|
|
33
|
+
return getShortestSegmentBetweenObjects(
|
|
34
|
+
obj0,
|
|
35
|
+
point,
|
|
36
|
+
null,
|
|
37
|
+
projectionPlane
|
|
38
|
+
)
|
|
39
|
+
} else if (obj1.type === 'point') {
|
|
40
|
+
return [obj1, obj1]
|
|
41
|
+
} else if (obj0.type === 'point') {
|
|
42
|
+
return [obj0, obj0]
|
|
43
|
+
} else {
|
|
44
|
+
return null
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Handle Point cases
|
|
49
|
+
if (obj0.type === 'point' && obj1.type === 'point') {
|
|
50
|
+
return getShortestSegmentPointPoint(obj0, obj1, point, projectionPlane)
|
|
51
|
+
}
|
|
52
|
+
if (obj0.type === 'point' && obj1.type === 'line') {
|
|
53
|
+
return getShortestSegmentPointLine(obj0, obj1, point, projectionPlane)
|
|
54
|
+
}
|
|
55
|
+
if (obj0.type === 'point' && obj1.type === 'circle') {
|
|
56
|
+
return getShortestSegmentPointCircle(obj0, obj1, point, projectionPlane)
|
|
57
|
+
}
|
|
58
|
+
if (obj0.type === 'point' && obj1.type === 'polygon') {
|
|
59
|
+
return getShortestSegmentPointPolygon(obj0, obj1, point, projectionPlane)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Handle Line cases
|
|
63
|
+
if (obj0.type === 'line' && obj1.type === 'point') {
|
|
64
|
+
const result = getShortestSegmentPointLine(
|
|
65
|
+
obj1,
|
|
66
|
+
obj0,
|
|
67
|
+
point,
|
|
68
|
+
projectionPlane
|
|
69
|
+
)
|
|
70
|
+
if (result) {
|
|
71
|
+
return [result[1], result[0]]
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (obj0.type === 'line' && obj1.type === 'line') {
|
|
75
|
+
return getShortestSegmentLineLine(obj0, obj1, point, projectionPlane)
|
|
76
|
+
}
|
|
77
|
+
if (obj0.type === 'line' && obj1.type === 'circle') {
|
|
78
|
+
return getShortestSegmentLineCircle(obj0, obj1, point, projectionPlane)
|
|
79
|
+
}
|
|
80
|
+
if (obj0.type === 'line' && obj1.type === 'polygon') {
|
|
81
|
+
return getShortestSegmentLinePolygon(obj0, obj1, point, projectionPlane)
|
|
82
|
+
}
|
|
83
|
+
// Handle Circle cases
|
|
84
|
+
if (obj0.type === 'circle' && obj1.type === 'point') {
|
|
85
|
+
const result = getShortestSegmentPointCircle(
|
|
86
|
+
obj1,
|
|
87
|
+
obj0,
|
|
88
|
+
point,
|
|
89
|
+
projectionPlane
|
|
90
|
+
)
|
|
91
|
+
if (result) {
|
|
92
|
+
return [result[1], result[0]]
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (obj0.type === 'circle' && obj1.type === 'line') {
|
|
96
|
+
const result = getShortestSegmentLineCircle(
|
|
97
|
+
obj1,
|
|
98
|
+
obj0,
|
|
99
|
+
point,
|
|
100
|
+
projectionPlane
|
|
101
|
+
)
|
|
102
|
+
if (result) {
|
|
103
|
+
return [result[1], result[0]]
|
|
104
|
+
}
|
|
105
|
+
return [result[1], result[0]]
|
|
106
|
+
}
|
|
107
|
+
if (obj0.type === 'circle' && obj1.type === 'circle') {
|
|
108
|
+
return getShortestSegmentCircleCircle(obj0, obj1, point, projectionPlane)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (obj0.type === 'circle' && obj1.type === 'polygon') {
|
|
112
|
+
return getShortestSegmentCirclePolygon(obj0, obj1, point, projectionPlane)
|
|
113
|
+
}
|
|
114
|
+
//handle polygon cases
|
|
115
|
+
if (obj0.type === 'polygon' && obj1.type === 'point') {
|
|
116
|
+
const result = getShortestSegmentPointPolygon(
|
|
117
|
+
obj1,
|
|
118
|
+
obj0,
|
|
119
|
+
point,
|
|
120
|
+
projectionPlane
|
|
121
|
+
)
|
|
122
|
+
if (result) {
|
|
123
|
+
return [result[1], result[0]]
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
if (obj0.type === 'polygon' && obj1.type === 'line') {
|
|
127
|
+
const result = getShortestSegmentLinePolygon(
|
|
128
|
+
obj1,
|
|
129
|
+
obj0,
|
|
130
|
+
point,
|
|
131
|
+
projectionPlane
|
|
132
|
+
)
|
|
133
|
+
if (result) {
|
|
134
|
+
return [result[1], result[0]]
|
|
135
|
+
} else {
|
|
136
|
+
return null
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
if (obj0.type === 'polygon' && obj1.type === 'circle') {
|
|
140
|
+
const result = getShortestSegmentCirclePolygon(
|
|
141
|
+
obj1,
|
|
142
|
+
obj0,
|
|
143
|
+
point,
|
|
144
|
+
projectionPlane
|
|
145
|
+
)
|
|
146
|
+
return [result[1], result[0]]
|
|
147
|
+
}
|
|
148
|
+
if (obj0.type === 'polygon' && obj1.type === 'polygon') {
|
|
149
|
+
return getShortestSegmentPolygonPolygon(obj0, obj1, point, projectionPlane)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
console.error('Unsupported object types get shortest:', obj0.type, obj1.type)
|
|
153
|
+
console.trace()
|
|
154
|
+
return [point, point]
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Check if two objects intersect
|
|
159
|
+
* @param {Object} obj0 - First object
|
|
160
|
+
* @param {Object} obj1 - Second object
|
|
161
|
+
* @returns {Boolean} True if objects intersect
|
|
162
|
+
*/
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Get shortest segment between two points
|
|
166
|
+
* @param {Point} p0 - First point
|
|
167
|
+
* @param {Point} p1 - Second point
|
|
168
|
+
* @param {Object} refPoint - Reference point
|
|
169
|
+
* @returns {Array} [point0, point1]
|
|
170
|
+
*/
|
|
171
|
+
export function getShortestSegmentPointPoint(
|
|
172
|
+
p0,
|
|
173
|
+
p1,
|
|
174
|
+
refPoint,
|
|
175
|
+
projectionPlane = defaultPlane
|
|
176
|
+
) {
|
|
177
|
+
// The segment is just the two points
|
|
178
|
+
return [p0, p1]
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Get shortest segment between point and line
|
|
183
|
+
* @param {Point} point - Point object
|
|
184
|
+
* @param {Line} line - Line object
|
|
185
|
+
* @param {Object} refPoint - Reference point
|
|
186
|
+
* @returns {Array} [pointOnPoint, pointOnLine]
|
|
187
|
+
*/
|
|
188
|
+
export function getShortestSegmentPointLine(
|
|
189
|
+
point,
|
|
190
|
+
line,
|
|
191
|
+
refPoint,
|
|
192
|
+
projectionPlane = defaultPlane
|
|
193
|
+
) {
|
|
194
|
+
return [
|
|
195
|
+
point,
|
|
196
|
+
line.getProjectedPointFromPlane(point, {
|
|
197
|
+
isIncludedInSegment: false,
|
|
198
|
+
plane: projectionPlane,
|
|
199
|
+
}),
|
|
200
|
+
]
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Get shortest segment between point and circle
|
|
205
|
+
* @param {Point} point - Point object
|
|
206
|
+
* @param {Circle} circle - Circle object
|
|
207
|
+
* @param {Object} refPoint - Reference point
|
|
208
|
+
* @returns {Array} [pointOnPoint, pointOnCircle]
|
|
209
|
+
*/
|
|
210
|
+
export function getShortestSegmentPointCircle(
|
|
211
|
+
point,
|
|
212
|
+
circle,
|
|
213
|
+
refPoint,
|
|
214
|
+
projectionPlane = defaultPlane
|
|
215
|
+
) {
|
|
216
|
+
if (get3DDistanceBetweenPoints(point, circle.center) <= circle.radius) {
|
|
217
|
+
return circle.getCircleDiameterPoints(point, { plane: projectionPlane })
|
|
218
|
+
}
|
|
219
|
+
return [
|
|
220
|
+
point,
|
|
221
|
+
circle.getProjectedPointFromPlane(point, { plane: projectionPlane }),
|
|
222
|
+
]
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Get shortest segment between point and polygon
|
|
227
|
+
* @param {Point} point - Point object
|
|
228
|
+
* @param {Polygon} polygon - Polygon object
|
|
229
|
+
* @param {Object} refPoint - Reference point
|
|
230
|
+
* @returns {Array} [pointOnPoint, pointOnPolygon]
|
|
231
|
+
*/
|
|
232
|
+
export function getShortestSegmentPointPolygon(
|
|
233
|
+
point,
|
|
234
|
+
polygon,
|
|
235
|
+
refPoint,
|
|
236
|
+
projectionPlane = defaultPlane
|
|
237
|
+
) {
|
|
238
|
+
// TODO: Find the point on the polygon (vertex or edge) closest to the point
|
|
239
|
+
// TODO: If multiple solutions exist, choose the one closest to refPoint
|
|
240
|
+
const P = verticalProjectionOnPlane(
|
|
241
|
+
point,
|
|
242
|
+
polygon.normalVector,
|
|
243
|
+
polygon.outline[0]
|
|
244
|
+
)
|
|
245
|
+
const pointInPlane = new Point(P.x, P.y, P.z)
|
|
246
|
+
const closestEdge = polygon.getClosestPolygonEdgeFromPlane(
|
|
247
|
+
pointInPlane,
|
|
248
|
+
projectionPlane
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
if (refPoint) {
|
|
252
|
+
const projectedPointOnPolygonEdge = closestEdge.getProjectedPointFromPlane(
|
|
253
|
+
refPoint,
|
|
254
|
+
true,
|
|
255
|
+
projectionPlane
|
|
256
|
+
)
|
|
257
|
+
// const closestPoint = findClosestPoint(projectedPoints, refPoint)
|
|
258
|
+
return [pointInPlane, projectedPointOnPolygonEdge]
|
|
259
|
+
} else {
|
|
260
|
+
const projectedPointOnPolygonEdge = closestEdge.getProjectedPointFromPlane(
|
|
261
|
+
pointInPlane,
|
|
262
|
+
true,
|
|
263
|
+
projectionPlane
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
return [pointInPlane, projectedPointOnPolygonEdge]
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Get shortest segment between two lines
|
|
272
|
+
* @param {Line} line0 - First line
|
|
273
|
+
* @param {Line} line1 - Second line
|
|
274
|
+
* @param {Object} refPoint - Reference point
|
|
275
|
+
* @returns {Array} [pointOnLine0, pointOnLine1]
|
|
276
|
+
*/
|
|
277
|
+
export function getShortestSegmentLineLine(
|
|
278
|
+
line0,
|
|
279
|
+
line1,
|
|
280
|
+
refPoint,
|
|
281
|
+
projectionPlane = defaultPlane
|
|
282
|
+
) {
|
|
283
|
+
if (line0.id == line1.id) {
|
|
284
|
+
return [line0.outline[0], line0.outline[1]]
|
|
285
|
+
}
|
|
286
|
+
const A = line0.outline[0]
|
|
287
|
+
const u = substractVector(line0.outline[1], line0.outline[0])
|
|
288
|
+
const B = line1.outline[0]
|
|
289
|
+
const v = substractVector(line1.outline[1], line1.outline[0])
|
|
290
|
+
let P1 = line0.getProjectedPointFromPlane(refPoint, {
|
|
291
|
+
isIncludedInSegment: false,
|
|
292
|
+
plane: projectionPlane,
|
|
293
|
+
})
|
|
294
|
+
const P2 = line1.getIntersectionWithPointVectorLineFromPlane(
|
|
295
|
+
P1,
|
|
296
|
+
line0.getNormalVectorInPlane(projectionPlane),
|
|
297
|
+
projectionPlane
|
|
298
|
+
)
|
|
299
|
+
if (P2 && P1) {
|
|
300
|
+
return [P1, P2]
|
|
301
|
+
}
|
|
302
|
+
return null
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Get shortest segment between line and circle
|
|
307
|
+
* @param {Line} line - Line object
|
|
308
|
+
* @param {Circle} circle - Circle object
|
|
309
|
+
* @param {Object} refPoint - Reference point
|
|
310
|
+
* @returns {Array} [pointOnLine, pointOnCircle]
|
|
311
|
+
*/
|
|
312
|
+
export function getShortestSegmentLineCircle(
|
|
313
|
+
line,
|
|
314
|
+
circle,
|
|
315
|
+
refPoint,
|
|
316
|
+
projectionPlane = defaultPlane
|
|
317
|
+
) {
|
|
318
|
+
const A = line.getProjectedPointFromPlane(circle.center, {
|
|
319
|
+
isIncludedInSegment: false,
|
|
320
|
+
plane: projectionPlane,
|
|
321
|
+
})
|
|
322
|
+
const B = circle.getProjectedPointFromPlane(A, { plane: projectionPlane })
|
|
323
|
+
return [A, B]
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Get shortest segment between line and polygon
|
|
328
|
+
* @param {Line} line - Line object
|
|
329
|
+
* @param {Polygon} polygon - Polygon object
|
|
330
|
+
* @param {Object} refPoint - Reference point
|
|
331
|
+
* @returns {Array} [pointOnLine, pointOnPolygon] or null
|
|
332
|
+
*/
|
|
333
|
+
export function getShortestSegmentLinePolygon(
|
|
334
|
+
line,
|
|
335
|
+
polygon,
|
|
336
|
+
refPoint,
|
|
337
|
+
projectionPlane = defaultPlane
|
|
338
|
+
) {
|
|
339
|
+
const polygonEdges = polygon.outline.map((p, index) => {
|
|
340
|
+
const nextP = polygon.outline[(index + 1) % polygon.outline.length]
|
|
341
|
+
return new Line(p, nextP)
|
|
342
|
+
})
|
|
343
|
+
let polygonEdgesData = polygonEdges
|
|
344
|
+
.map((edge) => {
|
|
345
|
+
const data = getShortestSegmentLineLine(
|
|
346
|
+
line,
|
|
347
|
+
edge,
|
|
348
|
+
refPoint,
|
|
349
|
+
projectionPlane
|
|
350
|
+
)
|
|
351
|
+
if (!!data) {
|
|
352
|
+
const [M, N] = data
|
|
353
|
+
const distance = getDistanceBetweenPoints(M, N)
|
|
354
|
+
return { distance, M, N }
|
|
355
|
+
} else {
|
|
356
|
+
return null
|
|
357
|
+
}
|
|
358
|
+
})
|
|
359
|
+
.filter((data) => !!data)
|
|
360
|
+
polygonEdgesData.sort((a, b) => a.distance - b.distance)
|
|
361
|
+
if (polygonEdgesData.length) {
|
|
362
|
+
//intersection between a line orthogonal to the line and one of the polygon edges
|
|
363
|
+
return [polygonEdgesData[0].M, polygonEdgesData[0].N]
|
|
364
|
+
} else {
|
|
365
|
+
//get the polygon outline closest to the line and its projection on the line
|
|
366
|
+
const polygonOutline = polygon.outline
|
|
367
|
+
const distances = polygonOutline.map((p) => {
|
|
368
|
+
return line.getHorizontalDistanceToPoint(p)
|
|
369
|
+
})
|
|
370
|
+
const minDistance = Math.min(...distances)
|
|
371
|
+
const minIndex = distances.indexOf(minDistance)
|
|
372
|
+
const minPoint = polygonOutline[minIndex]
|
|
373
|
+
const projectionPoint = line.getProjectedPointFromPlane(minPoint, {
|
|
374
|
+
isIncludedInSegment: true,
|
|
375
|
+
plane: projectionPlane,
|
|
376
|
+
})
|
|
377
|
+
return [projectionPoint, minPoint]
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Get shortest segment between two circles
|
|
383
|
+
* @param {Circle} circle0 - First circle
|
|
384
|
+
* @param {Circle} circle1 - Second circle
|
|
385
|
+
* @param {Object} refPoint - Reference point
|
|
386
|
+
* @returns {Array} [pointOnCircle0, pointOnCircle1]
|
|
387
|
+
*/
|
|
388
|
+
export function getShortestSegmentCircleCircle(
|
|
389
|
+
circle0,
|
|
390
|
+
circle1,
|
|
391
|
+
refPoint,
|
|
392
|
+
projectionPlane = defaultPlane
|
|
393
|
+
) {
|
|
394
|
+
return [circle0.center, circle1.center]
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Get shortest segment between circle and polygon
|
|
399
|
+
* @param {Circle} circle - Circle object
|
|
400
|
+
* @param {Polygon} polygon - Polygon object
|
|
401
|
+
* @param {Object} refPoint - Reference point
|
|
402
|
+
* @returns {Array} [pointOnCircle, pointOnPolygon]
|
|
403
|
+
*/
|
|
404
|
+
export function getShortestSegmentCirclePolygon(
|
|
405
|
+
circle,
|
|
406
|
+
polygon,
|
|
407
|
+
refPoint,
|
|
408
|
+
projectionPlane = defaultPlane
|
|
409
|
+
) {
|
|
410
|
+
return getShortestSegmentPointPolygon(circle.center, polygon, refPoint)
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* Get shortest segment between two polygons
|
|
415
|
+
* @param {Polygon} polygon0 - First polygon
|
|
416
|
+
* @param {Polygon} polygon1 - Second polygon
|
|
417
|
+
* @param {Object} refPoint - Reference point
|
|
418
|
+
* @returns {Array} [pointOnPolygon0, pointOnPolygon1]
|
|
419
|
+
*/
|
|
420
|
+
export function getShortestSegmentPolygonPolygon(
|
|
421
|
+
polygon0,
|
|
422
|
+
polygon1,
|
|
423
|
+
refPoint,
|
|
424
|
+
projectionPlane = defaultPlane
|
|
425
|
+
) {
|
|
426
|
+
const pointsP0 = polygon0.getProjectedPoints(refPoint, true)
|
|
427
|
+
const closestPoint0 = findClosestPoint(pointsP0, refPoint)
|
|
428
|
+
const pointsP1 = polygon1.getProjectedPoints(closestPoint0, true)
|
|
429
|
+
const closestPoint1 = findClosestPoint(pointsP1, refPoint)
|
|
430
|
+
return [closestPoint0, closestPoint1]
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
export function findClosestPoint(
|
|
434
|
+
points,
|
|
435
|
+
refPoint,
|
|
436
|
+
projectionPlane = defaultPlane
|
|
437
|
+
) {
|
|
438
|
+
const distances = points.map((p) => getDistanceBetweenPoints(refPoint, p))
|
|
439
|
+
const minDistance = Math.min(...distances)
|
|
440
|
+
const minIndex = distances.indexOf(minDistance)
|
|
441
|
+
return points[minIndex]
|
|
442
|
+
}
|
package/src/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export * from './coords'
|
|
2
2
|
export * from './geo'
|
|
3
3
|
export * from './geometry'
|
|
4
|
+
export * from './geometryShortDistance'
|
|
5
|
+
export * from './intersectionCheck'
|
|
4
6
|
export * from './matrix'
|
|
5
7
|
export * from './vector'
|
|
6
8
|
export * from './snap'
|
|
@@ -14,3 +16,4 @@ export * from './spherical'
|
|
|
14
16
|
export * from './SHPSolver'
|
|
15
17
|
export * from './panelFunctions'
|
|
16
18
|
export * from './stringPatchMatching'
|
|
19
|
+
export * from './plane'
|