NGL@1.0.0-beta.7 Home Manual Reference Source Gallery

src/math/vector-utils.js

  1. /**
  2. * @file Vector Utils
  3. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  4. * @private
  5. */
  6.  
  7. import { Vector3 } from '../../lib/three.es6.js'
  8.  
  9. import { EPS } from './math-constants.js'
  10.  
  11. /**
  12. * Converted to JavaScript from
  13. * {@link http://paulbourke.net/geometry/pointlineplane/lineline.c}
  14. *
  15. * @param {Vector3} p1 - point 1
  16. * @param {Vector3} p2 - point 2
  17. * @param {Vector3} p3 - point 3
  18. * @param {Vector3} p4 - point 4
  19. * @return {Array.<Vector3, Vector3>|null} the two intersection points
  20. */
  21. function lineLineIntersect (p1, p2, p3, p4) {
  22. var p13 = new Vector3()
  23. var p43 = new Vector3()
  24. var p21 = new Vector3()
  25. var d1343, d4321, d1321, d4343, d2121
  26. var denom, numer
  27.  
  28. p13.x = p1.x - p3.x
  29. p13.y = p1.y - p3.y
  30. p13.z = p1.z - p3.z
  31. p43.x = p4.x - p3.x
  32. p43.y = p4.y - p3.y
  33. p43.z = p4.z - p3.z
  34. if (Math.abs(p43.x) < EPS && Math.abs(p43.y) < EPS && Math.abs(p43.z) < EPS) { return null }
  35.  
  36. p21.x = p2.x - p1.x
  37. p21.y = p2.y - p1.y
  38. p21.z = p2.z - p1.z
  39. if (Math.abs(p21.x) < EPS && Math.abs(p21.y) < EPS && Math.abs(p21.z) < EPS) { return null }
  40.  
  41. d1343 = p13.x * p43.x + p13.y * p43.y + p13.z * p43.z
  42. d4321 = p43.x * p21.x + p43.y * p21.y + p43.z * p21.z
  43. d1321 = p13.x * p21.x + p13.y * p21.y + p13.z * p21.z
  44. d4343 = p43.x * p43.x + p43.y * p43.y + p43.z * p43.z
  45. d2121 = p21.x * p21.x + p21.y * p21.y + p21.z * p21.z
  46.  
  47. denom = d2121 * d4343 - d4321 * d4321
  48. if (Math.abs(denom) < EPS) { return null }
  49. numer = d1343 * d4321 - d1321 * d4343
  50.  
  51. var mua = numer / denom
  52. var mub = (d1343 + d4321 * mua) / d4343
  53.  
  54. var pa = new Vector3(
  55. p1.x + mua * p21.x,
  56. p1.y + mua * p21.y,
  57. p1.z + mua * p21.z
  58. )
  59. var pb = new Vector3(
  60. p3.x + mub * p43.x,
  61. p3.y + mub * p43.y,
  62. p3.z + mub * p43.z
  63. )
  64.  
  65. return [ pa, pb ]
  66. }
  67.  
  68. function calculateMeanVector3 (array) {
  69. var n = array.length
  70. var m = array.length / 3
  71.  
  72. var x = 0
  73. var y = 0
  74. var z = 0
  75.  
  76. var i
  77.  
  78. for (i = 0; i < n; i += 3) {
  79. x += array[ i + 0 ]
  80. y += array[ i + 1 ]
  81. z += array[ i + 2 ]
  82. }
  83.  
  84. return new Vector3(x / m, y / m, z / m)
  85. }
  86.  
  87. function isPointOnSegment (p, l1, l2) {
  88. var len = l1.distanceTo(l2)
  89.  
  90. return p.distanceTo(l1) <= len && p.distanceTo(l2) <= len
  91. }
  92.  
  93. function projectPointOnVector (point, vector, origin) {
  94. if (origin) {
  95. point.sub(origin).projectOnVector(vector).add(origin)
  96. } else {
  97. point.projectOnVector(vector)
  98. }
  99.  
  100. return point
  101. }
  102.  
  103. function computeBoundingBox (array) {
  104. var minX = +Infinity
  105. var minY = +Infinity
  106. var minZ = +Infinity
  107. var maxX = -Infinity
  108. var maxY = -Infinity
  109. var maxZ = -Infinity
  110. for (var i = 0, l = array.length; i < l; i += 3) {
  111. var x = array[ i ]
  112. var y = array[ i + 1 ]
  113. var z = array[ i + 2 ]
  114. if (x < minX) minX = x
  115. if (y < minY) minY = y
  116. if (z < minZ) minZ = z
  117. if (x > maxX) maxX = x
  118. if (y > maxY) maxY = y
  119. if (z > maxZ) maxZ = z
  120. }
  121. return [
  122. v3new([ minX, minY, minZ ]),
  123. v3new([ maxX, maxY, maxZ ])
  124. ]
  125. }
  126. v3forEach.__deps = [ v3new ]
  127.  
  128. function applyMatrix4toVector3array (m, a) {
  129. for (var i = 0, il = a.length; i < il; i += 3) {
  130. var x = a[ i ]
  131. var y = a[ i + 1 ]
  132. var z = a[ i + 2 ]
  133. a[ i ] = m[ 0 ] * x + m[ 4 ] * y + m[ 8 ] * z + m[ 12 ]
  134. a[ i + 1 ] = m[ 1 ] * x + m[ 5 ] * y + m[ 9 ] * z + m[ 13 ]
  135. a[ i + 2 ] = m[ 2 ] * x + m[ 6 ] * y + m[ 10 ] * z + m[ 14 ]
  136. }
  137. }
  138.  
  139. function applyMatrix3toVector3array (m, a) {
  140. for (var i = 0, il = a.length; i < il; i += 3) {
  141. var x = a[ i ]
  142. var y = a[ i + 1 ]
  143. var z = a[ i + 2 ]
  144. a[ i ] = m[ 0 ] * x + m[ 3 ] * y + m[ 6 ] * z
  145. a[ i + 1 ] = m[ 1 ] * x + m[ 4 ] * y + m[ 7 ] * z
  146. a[ i + 2 ] = m[ 2 ] * x + m[ 5 ] * y + m[ 8 ] * z
  147. }
  148. }
  149.  
  150. function normalizeVector3array (a) {
  151. for (var i = 0, il = a.length; i < il; i += 3) {
  152. var x = a[ i ]
  153. var y = a[ i + 1 ]
  154. var z = a[ i + 2 ]
  155. var s = 1 / Math.sqrt(x * x + y * y + z * z)
  156. a[ i ] = x * s
  157. a[ i + 1 ] = y * s
  158. a[ i + 2 ] = z * s
  159. }
  160. }
  161.  
  162. function v3new (array) {
  163. return new Float32Array(array || 3)
  164. }
  165.  
  166. function v3cross (out, a, b) {
  167. var ax = a[0]
  168. var ay = a[1]
  169. var az = a[2]
  170. var bx = b[0]
  171. var by = b[1]
  172. var bz = b[2]
  173. out[0] = ay * bz - az * by
  174. out[1] = az * bx - ax * bz
  175. out[2] = ax * by - ay * bx
  176. }
  177.  
  178. function v3dot (a, b) {
  179. return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]
  180. }
  181.  
  182. function v3sub (out, a, b) {
  183. out[0] = a[0] - b[0]
  184. out[1] = a[1] - b[1]
  185. out[2] = a[2] - b[2]
  186. }
  187.  
  188. function v3add (out, a, b) {
  189. out[0] = a[0] + b[0]
  190. out[1] = a[1] + b[1]
  191. out[2] = a[2] + b[2]
  192. }
  193.  
  194. function v3fromArray (out, array, offset) {
  195. out[0] = array[offset]
  196. out[1] = array[offset + 1]
  197. out[2] = array[offset + 2]
  198. }
  199.  
  200. function v3toArray (input, array, offset) {
  201. array[offset] = input[0]
  202. array[offset + 1] = input[1]
  203. array[offset + 2] = input[2]
  204. }
  205.  
  206. function v3forEach (array, fn, b) {
  207. var a = v3new(3)
  208. for (var i = 0, n = array.length; i < n; i += 3) {
  209. v3fromArray(a, array, i)
  210. fn(a, a, b)
  211. v3toArray(a, array, i)
  212. }
  213. }
  214. v3forEach.__deps = [ v3new, v3fromArray, v3toArray ]
  215.  
  216. function v3length (a) {
  217. return Math.sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2])
  218. }
  219.  
  220. function v3divide (out, a, b) {
  221. out[0] = a[0] / b[0]
  222. out[1] = a[1] / b[1]
  223. out[2] = a[2] / b[2]
  224. }
  225.  
  226. function v3multiply (out, a, b) {
  227. out[0] = a[0] * b[0]
  228. out[1] = a[1] * b[1]
  229. out[2] = a[2] * b[2]
  230. }
  231.  
  232. function v3divideScalar (out, a, s) {
  233. v3multiplyScalar(out, a, 1 / s)
  234. }
  235. v3divideScalar.__deps = [ v3multiplyScalar ]
  236.  
  237. function v3multiplyScalar (out, a, s) {
  238. out[0] = a[0] * s
  239. out[1] = a[1] * s
  240. out[2] = a[2] * s
  241. }
  242.  
  243. function v3normalize (out, a) {
  244. v3multiplyScalar(out, a, 1 / v3length(a))
  245. }
  246. v3normalize.__deps = [ v3multiplyScalar, v3length ]
  247.  
  248. function v3subScalar (out, a, s) {
  249. out[0] = a[0] - s
  250. out[1] = a[1] - s
  251. out[2] = a[2] - s
  252. }
  253.  
  254. function v3addScalar (out, a, s) {
  255. out[0] = a[0] + s
  256. out[1] = a[1] + s
  257. out[2] = a[2] + s
  258. }
  259.  
  260. function v3floor (out, a) {
  261. out[0] = Math.floor(a[0])
  262. out[1] = Math.floor(a[1])
  263. out[2] = Math.floor(a[2])
  264. }
  265.  
  266. function v3ceil (out, a) {
  267. out[0] = Math.ceil(a[0])
  268. out[1] = Math.ceil(a[1])
  269. out[2] = Math.ceil(a[2])
  270. }
  271.  
  272. function v3round (out, a) {
  273. out[0] = Math.round(a[0])
  274. out[1] = Math.round(a[1])
  275. out[2] = Math.round(a[2])
  276. }
  277.  
  278. function v3negate (out, a) {
  279. out[0] = -a[0]
  280. out[1] = -a[1]
  281. out[2] = -a[2]
  282. }
  283.  
  284. function v3angle (a, b) {
  285. var ax = a[0]
  286. var ay = a[1]
  287. var az = a[2]
  288. var bx = b[0]
  289. var by = b[1]
  290. var bz = b[2]
  291. var cx = ay * bz - az * by
  292. var cy = az * bx - ax * bz
  293. var cz = ax * by - ay * bx
  294. var s = Math.sqrt(cx * cx + cy * cy + cz * cz)
  295. var c = ax * bx + ay * by + az * bz
  296. return Math.atan2(s, c)
  297. }
  298.  
  299. export {
  300. lineLineIntersect,
  301. calculateMeanVector3,
  302. isPointOnSegment,
  303. projectPointOnVector,
  304. computeBoundingBox,
  305. applyMatrix4toVector3array,
  306. applyMatrix3toVector3array,
  307. normalizeVector3array,
  308.  
  309. v3new,
  310. v3cross,
  311. v3dot,
  312. v3sub,
  313. v3add,
  314. v3fromArray,
  315. v3toArray,
  316. v3forEach,
  317. v3length,
  318. v3divide,
  319. v3multiply,
  320. v3divideScalar,
  321. v3multiplyScalar,
  322. v3normalize,
  323. v3subScalar,
  324. v3addScalar,
  325. v3floor,
  326. v3ceil,
  327. v3round,
  328. v3negate,
  329. v3angle
  330. }