FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
mathjs/src/function/geometry/distance.js at develop · husayt/mathjs · GitHub
husayt
/
mathjs
Public
forked from
josdejong/mathjs
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Pull requests
0
Actions
Projects
Security and quality
0
Insights
Additional navigation options
Code
Pull requests
Actions
Projects
Security and quality
Insights
Expand file tree
Breadcrumbs
mathjs
/
src
/
function
/
geometry
/
distance.js
Copy path
More file actions
More file actions
Latest commit
History
History
History
310 lines (292 loc) · 13.3 KB
Breadcrumbs
mathjs
/
src
/
function
/
geometry
/
distance.js
Copy path
File metadata and controls
310 lines (292 loc) · 13.3 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
import
{
isBigNumber
}
from
'../../utils/is.js'
import
{
factory
}
from
'../../utils/factory.js'
const
name
=
'distance'
const
dependencies
=
[
'typed'
,
'addScalar'
,
'subtractScalar'
,
'divideScalar'
,
'multiplyScalar'
,
'deepEqual'
,
'sqrt'
,
'abs'
]
export
const
createDistance
=
/* #__PURE__ */
factory
(
name
,
dependencies
,
(
{
typed
,
addScalar
,
subtractScalar
,
multiplyScalar
,
divideScalar
,
deepEqual
,
sqrt
,
abs
}
)
=>
{
/**
* Calculates:
* The eucledian distance between two points in N-dimensional spaces.
* Distance between point and a line in 2 and 3 dimensional spaces.
* Pairwise distance between a set of 2D or 3D points
* NOTE:
* When substituting coefficients of a line(a, b and c), use ax + by + c = 0 instead of ax + by = c
* For parametric equation of a 3D line, x0, y0, z0, a, b, c are from: (x−x0, y−y0, z−z0) = t(a, b, c)
*
* Syntax:
*
* math.distance([x1,y1], [x2,y2])
* math.distance({pointOneX, pointOneY}, {pointTwoX, pointTwoY})
* math.distance([x1,y1,z1], [x2,y2,z2])
* math.distance({pointOneX, pointOneY, pointOneZ}, {pointTwoX, pointTwoY, pointTwoZ})
* math.distance([x1,y1,z1,a1], [x2,y2,z2,a2])
* math.distance([[x1,y1], [x2,y2], [x3,y3]])
* math.distance([[x1,y1,z1], [x2,y2,z2], [x3,y3,z3]])
* math.distance([pointX,pointY], [a,b,c])
* math.distance([pointX,pointY], [lineOnePtX,lineOnePtY], [lineTwoPtX,lineTwoPtY])
* math.distance({pointX, pointY}, {lineOnePtX, lineOnePtY}, {lineTwoPtX, lineTwoPtY})
* math.distance([pointX,pointY,pointZ], [x0, y0, z0, a, b, c])
* math.distance({pointX, pointY, pointZ}, {x0, y0, z0, a, b, c})
*
* Examples:
* math.distance([0,0], [4,4]) // Returns 5.656854249492381
* math.distance(
* {pointOneX: 0, pointOneY: 0},
* {pointTwoX: 10, pointTwoY: 10}) // Returns 14.142135623730951
* math.distance([1, 0, 1], [4, -2, 2]) // Returns 3.7416573867739413
* math.distance(
* {pointOneX: 4, pointOneY: 5, pointOneZ: 8},
* {pointTwoX: 2, pointTwoY: 7, pointTwoZ: 9}) // Returns 3
* math.distance([1, 0, 1, 0], [0, -1, 0, -1]) // Returns 2
* math.distance([[1, 2], [1, 2], [1, 3]]) // Returns [0, 1, 1]
* math.distance([[1,2,4], [1,2,6], [8,1,3]]) // Returns [2, 7.14142842854285, 7.681145747868608]
* math.distance([10, 10], [8, 1, 3]) // Returns 11.535230316796387
* math.distance([0, 0], [3, 0], [0, 4]) // Returns 2.4
* math.distance(
* {pointX: 0, pointY: 0},
* {lineOnePtX: 3, lineOnePtY: 0},
* {lineTwoPtX: 0, lineTwoPtY: 4}) // Returns 2.4
* math.distance([2, 3, 1], [1, 1, 2, 5, 0, 1]) // Returns 2.3204774044612857
* math.distance(
* {pointX: 2, pointY: 3, pointZ: 1},
* {x0: 1, y0: 1, z0: 2, a: 5, b: 0, c: 1}) // Returns 2.3204774044612857
*
*
@param
{
Array | Matrix | Object
} x Co-ordinates of first point
*
@param
{
Array | Matrix | Object
} y Co-ordinates of second point
*
@return
{
Number | BigNumber
} Returns the distance from two/three points
*/
return
typed
(
name
,
{
'Array, Array, Array'
:
function
(
x
,
y
,
z
)
{
// Point to Line 2D (x=Point, y=LinePoint1, z=LinePoint2)
if
(
x
.
length
===
2
&&
y
.
length
===
2
&&
z
.
length
===
2
)
{
if
(
!
_2d
(
x
)
)
{
throw
new
TypeError
(
'Array with 2 numbers or BigNumbers expected for first argument'
)
}
if
(
!
_2d
(
y
)
)
{
throw
new
TypeError
(
'Array with 2 numbers or BigNumbers expected for second argument'
)
}
if
(
!
_2d
(
z
)
)
{
throw
new
TypeError
(
'Array with 2 numbers or BigNumbers expected for third argument'
)
}
if
(
deepEqual
(
y
,
z
)
)
{
throw
new
TypeError
(
'LinePoint1 should not be same with LinePoint2'
)
}
const
xCoeff
=
subtractScalar
(
z
[
1
]
,
y
[
1
]
)
const
yCoeff
=
subtractScalar
(
y
[
0
]
,
z
[
0
]
)
const
constant
=
subtractScalar
(
multiplyScalar
(
z
[
0
]
,
y
[
1
]
)
,
multiplyScalar
(
y
[
0
]
,
z
[
1
]
)
)
return
_distancePointLine2D
(
x
[
0
]
,
x
[
1
]
,
xCoeff
,
yCoeff
,
constant
)
}
else
{
throw
new
TypeError
(
'Invalid Arguments: Try again'
)
}
}
,
'Object, Object, Object'
:
function
(
x
,
y
,
z
)
{
if
(
Object
.
keys
(
x
)
.
length
===
2
&&
Object
.
keys
(
y
)
.
length
===
2
&&
Object
.
keys
(
z
)
.
length
===
2
)
{
if
(
!
_2d
(
x
)
)
{
throw
new
TypeError
(
'Values of pointX and pointY should be numbers or BigNumbers'
)
}
if
(
!
_2d
(
y
)
)
{
throw
new
TypeError
(
'Values of lineOnePtX and lineOnePtY should be numbers or BigNumbers'
)
}
if
(
!
_2d
(
z
)
)
{
throw
new
TypeError
(
'Values of lineTwoPtX and lineTwoPtY should be numbers or BigNumbers'
)
}
if
(
deepEqual
(
_objectToArray
(
y
)
,
_objectToArray
(
z
)
)
)
{
throw
new
TypeError
(
'LinePoint1 should not be same with LinePoint2'
)
}
if
(
'pointX'
in
x
&&
'pointY'
in
x
&&
'lineOnePtX'
in
y
&&
'lineOnePtY'
in
y
&&
'lineTwoPtX'
in
z
&&
'lineTwoPtY'
in
z
)
{
const
xCoeff
=
subtractScalar
(
z
.
lineTwoPtY
,
y
.
lineOnePtY
)
const
yCoeff
=
subtractScalar
(
y
.
lineOnePtX
,
z
.
lineTwoPtX
)
const
constant
=
subtractScalar
(
multiplyScalar
(
z
.
lineTwoPtX
,
y
.
lineOnePtY
)
,
multiplyScalar
(
y
.
lineOnePtX
,
z
.
lineTwoPtY
)
)
return
_distancePointLine2D
(
x
.
pointX
,
x
.
pointY
,
xCoeff
,
yCoeff
,
constant
)
}
else
{
throw
new
TypeError
(
'Key names do not match'
)
}
}
else
{
throw
new
TypeError
(
'Invalid Arguments: Try again'
)
}
}
,
'Array, Array'
:
function
(
x
,
y
)
{
// Point to Line 2D (x=[pointX, pointY], y=[x-coeff, y-coeff, const])
if
(
x
.
length
===
2
&&
y
.
length
===
3
)
{
if
(
!
_2d
(
x
)
)
{
throw
new
TypeError
(
'Array with 2 numbers or BigNumbers expected for first argument'
)
}
if
(
!
_3d
(
y
)
)
{
throw
new
TypeError
(
'Array with 3 numbers or BigNumbers expected for second argument'
)
}
return
_distancePointLine2D
(
x
[
0
]
,
x
[
1
]
,
y
[
0
]
,
y
[
1
]
,
y
[
2
]
)
}
else
if
(
x
.
length
===
3
&&
y
.
length
===
6
)
{
// Point to Line 3D
if
(
!
_3d
(
x
)
)
{
throw
new
TypeError
(
'Array with 3 numbers or BigNumbers expected for first argument'
)
}
if
(
!
_parametricLine
(
y
)
)
{
throw
new
TypeError
(
'Array with 6 numbers or BigNumbers expected for second argument'
)
}
return
_distancePointLine3D
(
x
[
0
]
,
x
[
1
]
,
x
[
2
]
,
y
[
0
]
,
y
[
1
]
,
y
[
2
]
,
y
[
3
]
,
y
[
4
]
,
y
[
5
]
)
}
else
if
(
x
.
length
===
y
.
length
&&
x
.
length
>
0
)
{
// Point to Point N-dimensions
if
(
!
_containsOnlyNumbers
(
x
)
)
{
throw
new
TypeError
(
'All values of an array should be numbers or BigNumbers'
)
}
if
(
!
_containsOnlyNumbers
(
y
)
)
{
throw
new
TypeError
(
'All values of an array should be numbers or BigNumbers'
)
}
return
_euclideanDistance
(
x
,
y
)
}
else
{
throw
new
TypeError
(
'Invalid Arguments: Try again'
)
}
}
,
'Object, Object'
:
function
(
x
,
y
)
{
if
(
Object
.
keys
(
x
)
.
length
===
2
&&
Object
.
keys
(
y
)
.
length
===
3
)
{
if
(
!
_2d
(
x
)
)
{
throw
new
TypeError
(
'Values of pointX and pointY should be numbers or BigNumbers'
)
}
if
(
!
_3d
(
y
)
)
{
throw
new
TypeError
(
'Values of xCoeffLine, yCoeffLine and constant should be numbers or BigNumbers'
)
}
if
(
'pointX'
in
x
&&
'pointY'
in
x
&&
'xCoeffLine'
in
y
&&
'yCoeffLine'
in
y
&&
'constant'
in
y
)
{
return
_distancePointLine2D
(
x
.
pointX
,
x
.
pointY
,
y
.
xCoeffLine
,
y
.
yCoeffLine
,
y
.
constant
)
}
else
{
throw
new
TypeError
(
'Key names do not match'
)
}
}
else
if
(
Object
.
keys
(
x
)
.
length
===
3
&&
Object
.
keys
(
y
)
.
length
===
6
)
{
// Point to Line 3D
if
(
!
_3d
(
x
)
)
{
throw
new
TypeError
(
'Values of pointX, pointY and pointZ should be numbers or BigNumbers'
)
}
if
(
!
_parametricLine
(
y
)
)
{
throw
new
TypeError
(
'Values of x0, y0, z0, a, b and c should be numbers or BigNumbers'
)
}
if
(
'pointX'
in
x
&&
'pointY'
in
x
&&
'x0'
in
y
&&
'y0'
in
y
&&
'z0'
in
y
&&
'a'
in
y
&&
'b'
in
y
&&
'c'
in
y
)
{
return
_distancePointLine3D
(
x
.
pointX
,
x
.
pointY
,
x
.
pointZ
,
y
.
x0
,
y
.
y0
,
y
.
z0
,
y
.
a
,
y
.
b
,
y
.
c
)
}
else
{
throw
new
TypeError
(
'Key names do not match'
)
}
}
else
if
(
Object
.
keys
(
x
)
.
length
===
2
&&
Object
.
keys
(
y
)
.
length
===
2
)
{
// Point to Point 2D
if
(
!
_2d
(
x
)
)
{
throw
new
TypeError
(
'Values of pointOneX and pointOneY should be numbers or BigNumbers'
)
}
if
(
!
_2d
(
y
)
)
{
throw
new
TypeError
(
'Values of pointTwoX and pointTwoY should be numbers or BigNumbers'
)
}
if
(
'pointOneX'
in
x
&&
'pointOneY'
in
x
&&
'pointTwoX'
in
y
&&
'pointTwoY'
in
y
)
{
return
_euclideanDistance
(
[
x
.
pointOneX
,
x
.
pointOneY
]
,
[
y
.
pointTwoX
,
y
.
pointTwoY
]
)
}
else
{
throw
new
TypeError
(
'Key names do not match'
)
}
}
else
if
(
Object
.
keys
(
x
)
.
length
===
3
&&
Object
.
keys
(
y
)
.
length
===
3
)
{
// Point to Point 3D
if
(
!
_3d
(
x
)
)
{
throw
new
TypeError
(
'Values of pointOneX, pointOneY and pointOneZ should be numbers or BigNumbers'
)
}
if
(
!
_3d
(
y
)
)
{
throw
new
TypeError
(
'Values of pointTwoX, pointTwoY and pointTwoZ should be numbers or BigNumbers'
)
}
if
(
'pointOneX'
in
x
&&
'pointOneY'
in
x
&&
'pointOneZ'
in
x
&&
'pointTwoX'
in
y
&&
'pointTwoY'
in
y
&&
'pointTwoZ'
in
y
)
{
return
_euclideanDistance
(
[
x
.
pointOneX
,
x
.
pointOneY
,
x
.
pointOneZ
]
,
[
y
.
pointTwoX
,
y
.
pointTwoY
,
y
.
pointTwoZ
]
)
}
else
{
throw
new
TypeError
(
'Key names do not match'
)
}
}
else
{
throw
new
TypeError
(
'Invalid Arguments: Try again'
)
}
}
,
Array
:
function
(
arr
)
{
if
(
!
_pairwise
(
arr
)
)
{
throw
new
TypeError
(
'Incorrect array format entered for pairwise distance calculation'
)
}
return
_distancePairwise
(
arr
)
}
}
)
function
_isNumber
(
a
)
{
// distance supports numbers and bignumbers
return
(
typeof
a
===
'number'
||
isBigNumber
(
a
)
)
}
function
_2d
(
a
)
{
// checks if the number of arguments are correct in count and are valid (should be numbers)
if
(
a
.
constructor
!==
Array
)
{
a
=
_objectToArray
(
a
)
}
return
_isNumber
(
a
[
0
]
)
&&
_isNumber
(
a
[
1
]
)
}
function
_3d
(
a
)
{
// checks if the number of arguments are correct in count and are valid (should be numbers)
if
(
a
.
constructor
!==
Array
)
{
a
=
_objectToArray
(
a
)
}
return
_isNumber
(
a
[
0
]
)
&&
_isNumber
(
a
[
1
]
)
&&
_isNumber
(
a
[
2
]
)
}
function
_containsOnlyNumbers
(
a
)
{
// checks if the number of arguments are correct in count and are valid (should be numbers)
if
(
!
Array
.
isArray
(
a
)
)
{
a
=
_objectToArray
(
a
)
}
return
a
.
every
(
_isNumber
)
}
function
_parametricLine
(
a
)
{
if
(
a
.
constructor
!==
Array
)
{
a
=
_objectToArray
(
a
)
}
return
_isNumber
(
a
[
0
]
)
&&
_isNumber
(
a
[
1
]
)
&&
_isNumber
(
a
[
2
]
)
&&
_isNumber
(
a
[
3
]
)
&&
_isNumber
(
a
[
4
]
)
&&
_isNumber
(
a
[
5
]
)
}
function
_objectToArray
(
o
)
{
const
keys
=
Object
.
keys
(
o
)
const
a
=
[
]
for
(
let
i
=
0
;
i
<
keys
.
length
;
i
++
)
{
a
.
push
(
o
[
keys
[
i
]
]
)
}
return
a
}
function
_pairwise
(
a
)
{
// checks for valid arguments passed to _distancePairwise(Array)
if
(
a
[
0
]
.
length
===
2
&&
_isNumber
(
a
[
0
]
[
0
]
)
&&
_isNumber
(
a
[
0
]
[
1
]
)
)
{
if
(
a
.
some
(
aI
=>
aI
.
length
!==
2
||
!
_isNumber
(
aI
[
0
]
)
||
!
_isNumber
(
aI
[
1
]
)
)
)
{
return
false
}
}
else
if
(
a
[
0
]
.
length
===
3
&&
_isNumber
(
a
[
0
]
[
0
]
)
&&
_isNumber
(
a
[
0
]
[
1
]
)
&&
_isNumber
(
a
[
0
]
[
2
]
)
)
{
if
(
a
.
some
(
aI
=>
aI
.
length
!==
3
||
!
_isNumber
(
aI
[
0
]
)
||
!
_isNumber
(
aI
[
1
]
)
||
!
_isNumber
(
aI
[
2
]
)
)
)
{
return
false
}
}
else
{
return
false
}
return
true
}
function
_distancePointLine2D
(
x
,
y
,
a
,
b
,
c
)
{
const
num
=
abs
(
addScalar
(
addScalar
(
multiplyScalar
(
a
,
x
)
,
multiplyScalar
(
b
,
y
)
)
,
c
)
)
const
den
=
sqrt
(
addScalar
(
multiplyScalar
(
a
,
a
)
,
multiplyScalar
(
b
,
b
)
)
)
return
divideScalar
(
num
,
den
)
}
function
_distancePointLine3D
(
x
,
y
,
z
,
x0
,
y0
,
z0
,
a
,
b
,
c
)
{
let
num
=
[
subtractScalar
(
multiplyScalar
(
subtractScalar
(
y0
,
y
)
,
c
)
,
multiplyScalar
(
subtractScalar
(
z0
,
z
)
,
b
)
)
,
subtractScalar
(
multiplyScalar
(
subtractScalar
(
z0
,
z
)
,
a
)
,
multiplyScalar
(
subtractScalar
(
x0
,
x
)
,
c
)
)
,
subtractScalar
(
multiplyScalar
(
subtractScalar
(
x0
,
x
)
,
b
)
,
multiplyScalar
(
subtractScalar
(
y0
,
y
)
,
a
)
)
]
num
=
sqrt
(
addScalar
(
addScalar
(
multiplyScalar
(
num
[
0
]
,
num
[
0
]
)
,
multiplyScalar
(
num
[
1
]
,
num
[
1
]
)
)
,
multiplyScalar
(
num
[
2
]
,
num
[
2
]
)
)
)
const
den
=
sqrt
(
addScalar
(
addScalar
(
multiplyScalar
(
a
,
a
)
,
multiplyScalar
(
b
,
b
)
)
,
multiplyScalar
(
c
,
c
)
)
)
return
divideScalar
(
num
,
den
)
}
function
_euclideanDistance
(
x
,
y
)
{
const
vectorSize
=
x
.
length
let
result
=
0
let
diff
=
0
for
(
let
i
=
0
;
i
<
vectorSize
;
i
++
)
{
diff
=
subtractScalar
(
x
[
i
]
,
y
[
i
]
)
result
=
addScalar
(
multiplyScalar
(
diff
,
diff
)
,
result
)
}
return
sqrt
(
result
)
}
function
_distancePairwise
(
a
)
{
const
result
=
[
]
let
pointA
=
[
]
let
pointB
=
[
]
for
(
let
i
=
0
;
i
<
a
.
length
-
1
;
i
++
)
{
for
(
let
j
=
i
+
1
;
j
<
a
.
length
;
j
++
)
{
if
(
a
[
0
]
.
length
===
2
)
{
pointA
=
[
a
[
i
]
[
0
]
,
a
[
i
]
[
1
]
]
pointB
=
[
a
[
j
]
[
0
]
,
a
[
j
]
[
1
]
]
}
else
if
(
a
[
0
]
.
length
===
3
)
{
pointA
=
[
a
[
i
]
[
0
]
,
a
[
i
]
[
1
]
,
a
[
i
]
[
2
]
]
pointB
=
[
a
[
j
]
[
0
]
,
a
[
j
]
[
1
]
,
a
[
j
]
[
2
]
]
}
result
.
push
(
_euclideanDistance
(
pointA
,
pointB
)
)
}
}
return
result
}
}
)
Back
|
FazBrowse Home
|
New Git URL