math 0.0.0 → 0.1.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.
Files changed (201) hide show
  1. package/API.md +1605 -0
  2. package/LICENSE +21 -0
  3. package/README.md +197 -0
  4. package/dist/color/color.js +136 -0
  5. package/dist/color/color.js.map +1 -0
  6. package/dist/color/colorspace.js +43 -0
  7. package/dist/color/colorspace.js.map +1 -0
  8. package/dist/color/hsl.js +123 -0
  9. package/dist/color/hsl.js.map +1 -0
  10. package/dist/color/index.js +7 -0
  11. package/dist/color/index.js.map +1 -0
  12. package/dist/color/parse.js +276 -0
  13. package/dist/color/parse.js.map +1 -0
  14. package/dist/core/angle.js +43 -0
  15. package/dist/core/angle.js.map +1 -0
  16. package/dist/core/euler.js +212 -0
  17. package/dist/core/euler.js.map +1 -0
  18. package/dist/core/mat2.js +385 -0
  19. package/dist/core/mat2.js.map +1 -0
  20. package/dist/core/mat2d.js +422 -0
  21. package/dist/core/mat2d.js.map +1 -0
  22. package/dist/core/mat3.js +749 -0
  23. package/dist/core/mat3.js.map +1 -0
  24. package/dist/core/mat4.js +2197 -0
  25. package/dist/core/mat4.js.map +1 -0
  26. package/dist/core/polar.js +200 -0
  27. package/dist/core/polar.js.map +1 -0
  28. package/dist/core/quat.js +730 -0
  29. package/dist/core/quat.js.map +1 -0
  30. package/dist/core/quat2.js +883 -0
  31. package/dist/core/quat2.js.map +1 -0
  32. package/dist/core/scalar.js +112 -0
  33. package/dist/core/scalar.js.map +1 -0
  34. package/dist/core/spherical.js +248 -0
  35. package/dist/core/spherical.js.map +1 -0
  36. package/dist/core/vec2.js +597 -0
  37. package/dist/core/vec2.js.map +1 -0
  38. package/dist/core/vec3.js +916 -0
  39. package/dist/core/vec3.js.map +1 -0
  40. package/dist/core/vec4.js +573 -0
  41. package/dist/core/vec4.js.map +1 -0
  42. package/dist/geometry/circumcircle.js +39 -0
  43. package/dist/geometry/circumcircle.js.map +1 -0
  44. package/dist/geometry/index.js +6 -0
  45. package/dist/geometry/index.js.map +1 -0
  46. package/dist/geometry/polygon2-decompose.js +411 -0
  47. package/dist/geometry/polygon2-decompose.js.map +1 -0
  48. package/dist/geometry/polygon2-triangulate.js +222 -0
  49. package/dist/geometry/polygon2-triangulate.js.map +1 -0
  50. package/dist/geometry/quickhull2.js +123 -0
  51. package/dist/geometry/quickhull2.js.map +1 -0
  52. package/dist/geometry/quickhull3.js +605 -0
  53. package/dist/geometry/quickhull3.js.map +1 -0
  54. package/dist/ik/fabrik2.js +675 -0
  55. package/dist/ik/fabrik2.js.map +1 -0
  56. package/dist/ik/fabrik3.js +912 -0
  57. package/dist/ik/fabrik3.js.map +1 -0
  58. package/dist/ik/index.js +5 -0
  59. package/dist/ik/index.js.map +1 -0
  60. package/dist/index.js +27 -0
  61. package/dist/index.js.map +1 -0
  62. package/dist/noise/fractal.js +185 -0
  63. package/dist/noise/fractal.js.map +1 -0
  64. package/dist/noise/index.js +16 -0
  65. package/dist/noise/index.js.map +1 -0
  66. package/dist/noise/perlin2d.js +50 -0
  67. package/dist/noise/perlin2d.js.map +1 -0
  68. package/dist/noise/perlin3d.js +72 -0
  69. package/dist/noise/perlin3d.js.map +1 -0
  70. package/dist/noise/permutation.js +120 -0
  71. package/dist/noise/permutation.js.map +1 -0
  72. package/dist/noise/simplex2d.js +84 -0
  73. package/dist/noise/simplex2d.js.map +1 -0
  74. package/dist/noise/simplex3d.js +147 -0
  75. package/dist/noise/simplex3d.js.map +1 -0
  76. package/dist/noise/simplex4d.js +149 -0
  77. package/dist/noise/simplex4d.js.map +1 -0
  78. package/dist/noise/worley2d.js +50 -0
  79. package/dist/noise/worley2d.js.map +1 -0
  80. package/dist/noise/worley3d.js +61 -0
  81. package/dist/noise/worley3d.js.map +1 -0
  82. package/dist/random/index.js +9 -0
  83. package/dist/random/index.js.map +1 -0
  84. package/dist/random/isaac32.js +164 -0
  85. package/dist/random/isaac32.js.map +1 -0
  86. package/dist/random/isaac64.js +215 -0
  87. package/dist/random/isaac64.js.map +1 -0
  88. package/dist/random/mulberry32.js +48 -0
  89. package/dist/random/mulberry32.js.map +1 -0
  90. package/dist/random/random.js +120 -0
  91. package/dist/random/random.js.map +1 -0
  92. package/dist/shapes/box2.js +300 -0
  93. package/dist/shapes/box2.js.map +1 -0
  94. package/dist/shapes/box3.js +550 -0
  95. package/dist/shapes/box3.js.map +1 -0
  96. package/dist/shapes/circle.js +6 -0
  97. package/dist/shapes/circle.js.map +1 -0
  98. package/dist/shapes/frustum.js +662 -0
  99. package/dist/shapes/frustum.js.map +1 -0
  100. package/dist/shapes/index.js +25 -0
  101. package/dist/shapes/index.js.map +1 -0
  102. package/dist/shapes/obb3.js +557 -0
  103. package/dist/shapes/obb3.js.map +1 -0
  104. package/dist/shapes/plane3.js +267 -0
  105. package/dist/shapes/plane3.js.map +1 -0
  106. package/dist/shapes/polygon2.js +451 -0
  107. package/dist/shapes/polygon2.js.map +1 -0
  108. package/dist/shapes/raycast3.js +164 -0
  109. package/dist/shapes/raycast3.js.map +1 -0
  110. package/dist/shapes/segment2.js +82 -0
  111. package/dist/shapes/segment2.js.map +1 -0
  112. package/dist/shapes/sphere.js +23 -0
  113. package/dist/shapes/sphere.js.map +1 -0
  114. package/dist/shapes/triangle2.js +79 -0
  115. package/dist/shapes/triangle2.js.map +1 -0
  116. package/dist/shapes/triangle3.js +60 -0
  117. package/dist/shapes/triangle3.js.map +1 -0
  118. package/dist/src/color/color.d.ts +50 -0
  119. package/dist/src/color/colorspace.d.ts +15 -0
  120. package/dist/src/color/hsl.d.ts +28 -0
  121. package/dist/src/color/index.d.ts +5 -0
  122. package/dist/src/color/parse.d.ts +15 -0
  123. package/dist/src/core/angle.d.ts +29 -0
  124. package/dist/src/core/arrays.d.ts +4 -0
  125. package/dist/src/core/euler.d.ts +78 -0
  126. package/dist/src/core/index.d.ts +27 -0
  127. package/dist/src/core/mat2.d.ts +217 -0
  128. package/dist/src/core/mat2d.d.ts +218 -0
  129. package/dist/src/core/mat3.d.ts +295 -0
  130. package/dist/src/core/mat4.d.ts +667 -0
  131. package/dist/src/core/polar.d.ts +151 -0
  132. package/dist/src/core/quat.d.ts +370 -0
  133. package/dist/src/core/quat2.d.ts +344 -0
  134. package/dist/src/core/scalar.d.ts +75 -0
  135. package/dist/src/core/spherical.d.ts +165 -0
  136. package/dist/src/core/vec2.d.ts +403 -0
  137. package/dist/src/core/vec3.d.ts +493 -0
  138. package/dist/src/core/vec4.d.ts +336 -0
  139. package/dist/src/geometry/circumcircle.d.ts +9 -0
  140. package/dist/src/geometry/index.d.ts +5 -0
  141. package/dist/src/geometry/polygon2-decompose.d.ts +25 -0
  142. package/dist/src/geometry/polygon2-triangulate.d.ts +15 -0
  143. package/dist/src/geometry/quickhull2.d.ts +10 -0
  144. package/dist/src/geometry/quickhull3.d.ts +27 -0
  145. package/dist/src/ik/fabrik2.d.ts +314 -0
  146. package/dist/src/ik/fabrik3.d.ts +371 -0
  147. package/dist/src/ik/index.d.ts +2 -0
  148. package/dist/src/index.d.ts +1 -0
  149. package/dist/src/noise/fractal.d.ts +95 -0
  150. package/dist/src/noise/index.d.ts +9 -0
  151. package/dist/src/noise/perlin2d.d.ts +19 -0
  152. package/dist/src/noise/perlin3d.d.ts +20 -0
  153. package/dist/src/noise/permutation.d.ts +22 -0
  154. package/dist/src/noise/simplex2d.d.ts +19 -0
  155. package/dist/src/noise/simplex3d.d.ts +20 -0
  156. package/dist/src/noise/simplex4d.d.ts +24 -0
  157. package/dist/src/noise/worley2d.d.ts +22 -0
  158. package/dist/src/noise/worley3d.d.ts +23 -0
  159. package/dist/src/random/index.d.ts +8 -0
  160. package/dist/src/random/isaac32.d.ts +62 -0
  161. package/dist/src/random/isaac64.d.ts +75 -0
  162. package/dist/src/random/mulberry32.d.ts +43 -0
  163. package/dist/src/random/random.d.ts +67 -0
  164. package/dist/src/shapes/box2.d.ts +174 -0
  165. package/dist/src/shapes/box3.d.ts +213 -0
  166. package/dist/src/shapes/circle.d.ts +7 -0
  167. package/dist/src/shapes/frustum.d.ts +147 -0
  168. package/dist/src/shapes/index.d.ts +20 -0
  169. package/dist/src/shapes/obb3.d.ts +105 -0
  170. package/dist/src/shapes/plane3.d.ts +130 -0
  171. package/dist/src/shapes/polygon2.d.ts +155 -0
  172. package/dist/src/shapes/raycast3.d.ts +42 -0
  173. package/dist/src/shapes/segment2.d.ts +34 -0
  174. package/dist/src/shapes/sphere.d.ts +19 -0
  175. package/dist/src/shapes/triangle2.d.ts +53 -0
  176. package/dist/src/shapes/triangle3.d.ts +29 -0
  177. package/dist/src/time/easing.d.ts +21 -0
  178. package/dist/src/time/index.d.ts +6 -0
  179. package/dist/src/time/spring-core.d.ts +15 -0
  180. package/dist/src/time/spring.d.ts +36 -0
  181. package/dist/src/time/spring2.d.ts +11 -0
  182. package/dist/src/time/spring3.d.ts +11 -0
  183. package/dist/src/time/spring4.d.ts +11 -0
  184. package/dist/time/easing.js +24 -0
  185. package/dist/time/easing.js.map +1 -0
  186. package/dist/time/index.js +11 -0
  187. package/dist/time/index.js.map +1 -0
  188. package/dist/time/spring-core.js +48 -0
  189. package/dist/time/spring-core.js.map +1 -0
  190. package/dist/time/spring.js +62 -0
  191. package/dist/time/spring.js.map +1 -0
  192. package/dist/time/spring2.js +31 -0
  193. package/dist/time/spring2.js.map +1 -0
  194. package/dist/time/spring3.js +32 -0
  195. package/dist/time/spring3.js.map +1 -0
  196. package/dist/time/spring4.js +32 -0
  197. package/dist/time/spring4.js.map +1 -0
  198. package/package.json +90 -12
  199. package/skills/math/SKILL.md +140 -0
  200. package/math.coffee +0 -36
  201. package/math.js +0 -67
@@ -0,0 +1,451 @@
1
+ /**
2
+ * A 2D polygon is represented as a flat array of vertex coordinates laid out as
3
+ * `[x0, y0, x1, y1, ...]`, together with an explicit vertex count `n`.
4
+ *
5
+ * The count is passed separately (rather than derived from `verts.length`) so a
6
+ * single scratch buffer can be reused across polygons of different sizes: only
7
+ * the first `n` vertices are read, and any trailing slots are ignored. Vertices
8
+ * are assumed to be ordered (clockwise or counter-clockwise) around the polygon.
9
+ */
10
+ /**
11
+ * Returns the signed area of the polygon using the shoelace formula.
12
+ * The result is positive when the vertices wind counter-clockwise and negative
13
+ * when they wind clockwise, so the sign can be used to determine winding order.
14
+ *
15
+ * @param vertices polygon vertices as a flat array `[x0, y0, x1, y1, ...]`
16
+ * @param n number of vertices to read from `vertices`
17
+ * @returns the signed area
18
+ */
19
+ function signedArea(vertices, n) {
20
+ let area = 0;
21
+ for (let i = 0, j = n - 1; i < n; j = i++) {
22
+ const xi = vertices[i * 2];
23
+ const yi = vertices[i * 2 + 1];
24
+ const xj = vertices[j * 2];
25
+ const yj = vertices[j * 2 + 1];
26
+ area += xj * yi - xi * yj;
27
+ }
28
+ return area / 2;
29
+ }
30
+ /**
31
+ * Returns the (non-negative) area of the polygon.
32
+ *
33
+ * @param vertices polygon vertices as a flat array `[x0, y0, x1, y1, ...]`
34
+ * @param n number of vertices to read from `vertices`
35
+ * @returns the absolute area
36
+ */
37
+ function area(vertices, n) {
38
+ return Math.abs(signedArea(vertices, n));
39
+ }
40
+ /**
41
+ * Tests whether a point lies inside the polygon. Works for both convex and
42
+ * concave polygons. Points exactly on an edge or vertex are considered inside.
43
+ *
44
+ * @param vertices polygon vertices as a flat array `[x0, y0, x1, y1, ...]`
45
+ * @param n number of vertices to read from `vertices`
46
+ * @param point the point to test
47
+ * @returns true if the point is inside (or on the boundary of) the polygon
48
+ */
49
+ function containsPoint(vertices, n, point) {
50
+ let inside = false;
51
+ const x = point[0];
52
+ const y = point[1];
53
+ for (let i = 0, j = n - 1; i < n; j = i++) {
54
+ const xi = vertices[i * 2];
55
+ const yi = vertices[i * 2 + 1];
56
+ const xj = vertices[j * 2];
57
+ const yj = vertices[j * 2 + 1];
58
+ // Signed area of the triangle (j, i, point): zero when the point lies on
59
+ // the edge, sign tells which side it is on.
60
+ const where = (yi - yj) * (x - xi) - (xi - xj) * (y - yi);
61
+ if (yj < yi) {
62
+ // Upward edge: count a crossing when the point's y is within [yj, yi).
63
+ if (y >= yj && y < yi) {
64
+ if (where === 0)
65
+ return true; // on edge
66
+ if (where > 0) {
67
+ if (y === yj) {
68
+ // Ray passes exactly through vertex j; only toggle when the
69
+ // previous vertex is below, to avoid double-counting.
70
+ if (y > vertices[(j === 0 ? n - 1 : j - 1) * 2 + 1])
71
+ inside = !inside;
72
+ }
73
+ else {
74
+ inside = !inside;
75
+ }
76
+ }
77
+ }
78
+ }
79
+ else if (yi < yj) {
80
+ // Downward edge: count a crossing when the point's y is within (yi, yj].
81
+ if (y > yi && y <= yj) {
82
+ if (where === 0)
83
+ return true; // on edge
84
+ if (where < 0) {
85
+ if (y === yj) {
86
+ if (y < vertices[(j === 0 ? n - 1 : j - 1) * 2 + 1])
87
+ inside = !inside;
88
+ }
89
+ else {
90
+ inside = !inside;
91
+ }
92
+ }
93
+ }
94
+ }
95
+ else if (y === yi && ((x >= xj && x <= xi) || (x >= xi && x <= xj))) {
96
+ // Point lies on a horizontal edge.
97
+ return true;
98
+ }
99
+ }
100
+ return inside;
101
+ }
102
+ /**
103
+ * Computes the area-weighted centroid (center of mass) of the polygon.
104
+ * For a degenerate (zero-area) polygon this falls back to the average of the
105
+ * vertices.
106
+ *
107
+ * @param out the vector to store the centroid
108
+ * @param vertices polygon vertices as a flat array `[x0, y0, x1, y1, ...]`
109
+ * @param n number of vertices to read from `vertices`
110
+ * @returns out
111
+ */
112
+ function centroid(out, vertices, n) {
113
+ let cx = 0;
114
+ let cy = 0;
115
+ let a2 = 0; // twice the signed area
116
+ for (let i = 0, j = n - 1; i < n; j = i++) {
117
+ const xi = vertices[i * 2];
118
+ const yi = vertices[i * 2 + 1];
119
+ const xj = vertices[j * 2];
120
+ const yj = vertices[j * 2 + 1];
121
+ const cross = xj * yi - xi * yj;
122
+ a2 += cross;
123
+ cx += (xj + xi) * cross;
124
+ cy += (yj + yi) * cross;
125
+ }
126
+ if (a2 === 0) {
127
+ // Degenerate polygon (collinear vertices): use the vertex average.
128
+ let sx = 0;
129
+ let sy = 0;
130
+ for (let i = 0; i < n; i++) {
131
+ sx += vertices[i * 2];
132
+ sy += vertices[i * 2 + 1];
133
+ }
134
+ out[0] = sx / n;
135
+ out[1] = sy / n;
136
+ return out;
137
+ }
138
+ const inv = 1 / (3 * a2);
139
+ out[0] = cx * inv;
140
+ out[1] = cy * inv;
141
+ return out;
142
+ }
143
+ /**
144
+ * Returns the perimeter (sum of edge lengths) of the polygon.
145
+ *
146
+ * @param vertices polygon vertices as a flat array `[x0, y0, x1, y1, ...]`
147
+ * @param n number of vertices to read from `vertices`
148
+ * @returns the perimeter
149
+ */
150
+ function perimeter(vertices, n) {
151
+ let total = 0;
152
+ for (let i = 0, j = n - 1; i < n; j = i++) {
153
+ const dx = vertices[i * 2] - vertices[j * 2];
154
+ const dy = vertices[i * 2 + 1] - vertices[j * 2 + 1];
155
+ total += Math.sqrt(dx * dx + dy * dy);
156
+ }
157
+ return total;
158
+ }
159
+ /**
160
+ * Returns the winding order of the polygon from the sign of its signed area:
161
+ * `1` for counter-clockwise, `-1` for clockwise, and `0` for a degenerate
162
+ * (zero-area) polygon.
163
+ *
164
+ * @param vertices polygon vertices as a flat array `[x0, y0, x1, y1, ...]`
165
+ * @param n number of vertices to read from `vertices`
166
+ * @returns 1 (CCW), -1 (CW), or 0 (degenerate)
167
+ */
168
+ function winding(vertices, n) {
169
+ const a = signedArea(vertices, n);
170
+ if (a > 0)
171
+ return 1;
172
+ if (a < 0)
173
+ return -1;
174
+ return 0;
175
+ }
176
+ /**
177
+ * Tests whether the polygon is convex. Works for both winding orders. Assumes a
178
+ * simple (non-self-intersecting) polygon; collinear vertices are allowed.
179
+ *
180
+ * @param vertices polygon vertices as a flat array `[x0, y0, x1, y1, ...]`
181
+ * @param n number of vertices to read from `vertices`
182
+ * @returns true if the polygon is convex
183
+ */
184
+ function isConvex(vertices, n) {
185
+ if (n < 3)
186
+ return false;
187
+ let sign = 0;
188
+ for (let i = 0; i < n; i++) {
189
+ const p = ((i - 1 + n) % n) * 2;
190
+ const c = i * 2;
191
+ const q = ((i + 1) % n) * 2;
192
+ // Cross product of the incoming and outgoing edges at vertex i.
193
+ const ax = vertices[c] - vertices[p];
194
+ const ay = vertices[c + 1] - vertices[p + 1];
195
+ const bx = vertices[q] - vertices[c];
196
+ const by = vertices[q + 1] - vertices[c + 1];
197
+ const cross = ax * by - ay * bx;
198
+ if (cross !== 0) {
199
+ const s = cross > 0 ? 1 : -1;
200
+ if (sign === 0)
201
+ sign = s;
202
+ else if (s !== sign)
203
+ return false;
204
+ }
205
+ }
206
+ return true;
207
+ }
208
+ /**
209
+ * Tests whether vertex `i` is a reflex (concave) vertex of the polygon — the
210
+ * interior angle at that vertex exceeds 180°. Assumes the polygon is wound
211
+ * counter-clockwise and that `0 <= i < n`.
212
+ *
213
+ * @param vertices polygon vertices as a flat array `[x0, y0, x1, y1, ...]`
214
+ * @param n number of vertices to read from `vertices`
215
+ * @param i index of the vertex to test
216
+ * @returns true if vertex `i` is reflex
217
+ */
218
+ function isReflexVertex(vertices, n, i) {
219
+ const p = ((i - 1 + n) % n) * 2;
220
+ const c = i * 2;
221
+ const q = ((i + 1) % n) * 2;
222
+ // Cross product of the incoming and outgoing edges; negative = right turn = reflex (CCW).
223
+ const ax = vertices[c] - vertices[p];
224
+ const ay = vertices[c + 1] - vertices[p + 1];
225
+ const bx = vertices[q] - vertices[c];
226
+ const by = vertices[q + 1] - vertices[c + 1];
227
+ return ax * by - ay * bx < 0;
228
+ }
229
+ /**
230
+ * Reverses the winding order of the polygon, writing the result into `out`.
231
+ * `out` may be the same array as `vertices` to reverse in place.
232
+ *
233
+ * @param out the array to write the reversed polygon into
234
+ * @param vertices polygon vertices as a flat array `[x0, y0, x1, y1, ...]`
235
+ * @param n number of vertices to read from `vertices`
236
+ * @returns out
237
+ */
238
+ function reverse(out, vertices, n) {
239
+ for (let lo = 0, hi = n - 1; lo < hi; lo++, hi--) {
240
+ const x = vertices[lo * 2];
241
+ const y = vertices[lo * 2 + 1];
242
+ out[lo * 2] = vertices[hi * 2];
243
+ out[lo * 2 + 1] = vertices[hi * 2 + 1];
244
+ out[hi * 2] = x;
245
+ out[hi * 2 + 1] = y;
246
+ }
247
+ // Copy the untouched middle vertex when writing to a different buffer.
248
+ if (out !== vertices && n % 2 === 1) {
249
+ const mid = (n >> 1) * 2;
250
+ out[mid] = vertices[mid];
251
+ out[mid + 1] = vertices[mid + 1];
252
+ }
253
+ return out;
254
+ }
255
+ /**
256
+ * Writes the axis-aligned bounding box of the polygon into `out` as a Box2
257
+ * `[minX, minY, maxX, maxY]`.
258
+ *
259
+ * @param out the box to store the result
260
+ * @param vertices polygon vertices as a flat array `[x0, y0, x1, y1, ...]`
261
+ * @param n number of vertices to read from `vertices`
262
+ * @returns out
263
+ */
264
+ function bounds(out, vertices, n) {
265
+ let minX = Number.POSITIVE_INFINITY;
266
+ let minY = Number.POSITIVE_INFINITY;
267
+ let maxX = Number.NEGATIVE_INFINITY;
268
+ let maxY = Number.NEGATIVE_INFINITY;
269
+ for (let i = 0; i < n; i++) {
270
+ const x = vertices[i * 2];
271
+ const y = vertices[i * 2 + 1];
272
+ if (x < minX)
273
+ minX = x;
274
+ if (x > maxX)
275
+ maxX = x;
276
+ if (y < minY)
277
+ minY = y;
278
+ if (y > maxY)
279
+ maxY = y;
280
+ }
281
+ out[0] = minX;
282
+ out[1] = minY;
283
+ out[2] = maxX;
284
+ out[3] = maxY;
285
+ return out;
286
+ }
287
+ /**
288
+ * Finds the point on the polygon's boundary closest to `point` and writes it to
289
+ * `out`. `point` may lie inside, outside, or on the polygon; the result is
290
+ * always on an edge.
291
+ *
292
+ * @param out the vector to store the closest point
293
+ * @param vertices polygon vertices as a flat array `[x0, y0, x1, y1, ...]`
294
+ * @param n number of vertices to read from `vertices`
295
+ * @param point the query point
296
+ * @returns out
297
+ */
298
+ function closestPoint(out, vertices, n, point) {
299
+ const px = point[0];
300
+ const py = point[1];
301
+ let bestDistSq = Number.POSITIVE_INFINITY;
302
+ let bestX = px;
303
+ let bestY = py;
304
+ for (let i = 0, j = n - 1; i < n; j = i++) {
305
+ const ax = vertices[j * 2];
306
+ const ay = vertices[j * 2 + 1];
307
+ const abx = vertices[i * 2] - ax;
308
+ const aby = vertices[i * 2 + 1] - ay;
309
+ // Project the point onto edge (a -> b), clamped to the segment.
310
+ const d = abx * abx + aby * aby;
311
+ let t = d > 0 ? ((px - ax) * abx + (py - ay) * aby) / d : 0;
312
+ if (t < 0)
313
+ t = 0;
314
+ else if (t > 1)
315
+ t = 1;
316
+ const cx = ax + t * abx;
317
+ const cy = ay + t * aby;
318
+ const dx = px - cx;
319
+ const dy = py - cy;
320
+ const distSq = dx * dx + dy * dy;
321
+ if (distSq < bestDistSq) {
322
+ bestDistSq = distSq;
323
+ bestX = cx;
324
+ bestY = cy;
325
+ }
326
+ }
327
+ out[0] = bestX;
328
+ out[1] = bestY;
329
+ return out;
330
+ }
331
+ /**
332
+ * Returns the distance from `point` to the polygon's boundary, signed so that
333
+ * points inside the polygon get a negative distance and points outside get a
334
+ * positive one.
335
+ *
336
+ * @param vertices polygon vertices as a flat array `[x0, y0, x1, y1, ...]`
337
+ * @param n number of vertices to read from `vertices`
338
+ * @param point the query point
339
+ * @returns the signed distance (negative inside, positive outside)
340
+ */
341
+ function signedDistance(vertices, n, point) {
342
+ const px = point[0];
343
+ const py = point[1];
344
+ let bestDistSq = Number.POSITIVE_INFINITY;
345
+ for (let i = 0, j = n - 1; i < n; j = i++) {
346
+ const ax = vertices[j * 2];
347
+ const ay = vertices[j * 2 + 1];
348
+ const abx = vertices[i * 2] - ax;
349
+ const aby = vertices[i * 2 + 1] - ay;
350
+ const d = abx * abx + aby * aby;
351
+ let t = d > 0 ? ((px - ax) * abx + (py - ay) * aby) / d : 0;
352
+ if (t < 0)
353
+ t = 0;
354
+ else if (t > 1)
355
+ t = 1;
356
+ const dx = px - (ax + t * abx);
357
+ const dy = py - (ay + t * aby);
358
+ const distSq = dx * dx + dy * dy;
359
+ if (distSq < bestDistSq)
360
+ bestDistSq = distSq;
361
+ }
362
+ const dist = Math.sqrt(bestDistSq);
363
+ return containsPoint(vertices, n, point) ? -dist : dist;
364
+ }
365
+ const _projA = [0, 0];
366
+ const _projB = [0, 0];
367
+ /** Projects a polygon onto the axis (nx, ny), storing [min, max] in `out`. */
368
+ function projectOntoAxis(out, nx, ny, vertices, n) {
369
+ let min = nx * vertices[0] + ny * vertices[1];
370
+ let max = min;
371
+ for (let i = 1; i < n; i++) {
372
+ const d = nx * vertices[i * 2] + ny * vertices[i * 2 + 1];
373
+ if (d < min)
374
+ min = d;
375
+ else if (d > max)
376
+ max = d;
377
+ }
378
+ out[0] = min;
379
+ out[1] = max;
380
+ }
381
+ /** Returns true if the two polygons are separated along any edge normal of A. */
382
+ function separatedByEdgesOf(verticesA, numA, verticesB, numB) {
383
+ for (let i = 0, j = numA - 1; i < numA; j = i++) {
384
+ // Normal of edge (a -> b); orientation does not matter for separation.
385
+ const nx = verticesA[i * 2 + 1] - verticesA[j * 2 + 1];
386
+ const ny = -(verticesA[i * 2] - verticesA[j * 2]);
387
+ projectOntoAxis(_projA, nx, ny, verticesA, numA);
388
+ projectOntoAxis(_projB, nx, ny, verticesB, numB);
389
+ if (_projA[0] > _projB[1] || _projB[0] > _projA[1])
390
+ return true;
391
+ }
392
+ return false;
393
+ }
394
+ /**
395
+ * Tests whether two convex polygons overlap, using the separating axis theorem.
396
+ * Both polygons must be convex; results are undefined for concave input.
397
+ * Polygons that touch along an edge or vertex are considered overlapping.
398
+ *
399
+ * @param verticesA vertices of the first polygon `[x0, y0, x1, y1, ...]`
400
+ * @param numA number of vertices in the first polygon
401
+ * @param verticesB vertices of the second polygon `[x0, y0, x1, y1, ...]`
402
+ * @param numB number of vertices in the second polygon
403
+ * @returns true if the polygons overlap
404
+ */
405
+ function overlapConvex(verticesA, numA, verticesB, numB) {
406
+ if (separatedByEdgesOf(verticesA, numA, verticesB, numB))
407
+ return false;
408
+ if (separatedByEdgesOf(verticesB, numB, verticesA, numA))
409
+ return false;
410
+ return true;
411
+ }
412
+ /**
413
+ * Tests whether the segment `a`-`b` intersects the polygon, i.e. it has an
414
+ * endpoint inside the polygon or crosses one of its edges. Works for convex and
415
+ * concave polygons.
416
+ *
417
+ * @param vertices polygon vertices as a flat array `[x0, y0, x1, y1, ...]`
418
+ * @param n number of vertices to read from `vertices`
419
+ * @param a start of the segment
420
+ * @param b end of the segment
421
+ * @returns true if the segment intersects the polygon
422
+ */
423
+ function intersectsSegment(vertices, n, a, b) {
424
+ if (containsPoint(vertices, n, a) || containsPoint(vertices, n, b))
425
+ return true;
426
+ const ax = a[0];
427
+ const ay = a[1];
428
+ const abx = b[0] - ax;
429
+ const aby = b[1] - ay;
430
+ for (let i = 0, j = n - 1; i < n; j = i++) {
431
+ const cx = vertices[j * 2];
432
+ const cy = vertices[j * 2 + 1];
433
+ const dx = vertices[i * 2];
434
+ const dy = vertices[i * 2 + 1];
435
+ // Proper segment intersection via perp products (sign-of-area test).
436
+ const a1 = abx * (dy - ay) - aby * (dx - ax); // (b-a) x (d-a)
437
+ const a2 = abx * (cy - ay) - aby * (cx - ax); // (b-a) x (c-a)
438
+ if (a1 * a2 < 0) {
439
+ const cdx = dx - cx;
440
+ const cdy = dy - cy;
441
+ const a3 = cdx * (ay - cy) - cdy * (ax - cx); // (d-c) x (a-c)
442
+ const a4 = a3 + a2 - a1;
443
+ if (a3 * a4 < 0)
444
+ return true;
445
+ }
446
+ }
447
+ return false;
448
+ }
449
+
450
+ export { area, bounds, centroid, closestPoint, containsPoint, intersectsSegment, isConvex, isReflexVertex, overlapConvex, perimeter, reverse, signedArea, signedDistance, winding };
451
+ //# sourceMappingURL=polygon2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"polygon2.js","sources":["../../src/shapes/polygon2.ts"],"sourcesContent":["import type { Vec2 } from '../core/vec2';\nimport type { Box2 } from './box2';\n\n/**\n * A 2D polygon is represented as a flat array of vertex coordinates laid out as\n * `[x0, y0, x1, y1, ...]`, together with an explicit vertex count `n`.\n *\n * The count is passed separately (rather than derived from `verts.length`) so a\n * single scratch buffer can be reused across polygons of different sizes: only\n * the first `n` vertices are read, and any trailing slots are ignored. Vertices\n * are assumed to be ordered (clockwise or counter-clockwise) around the polygon.\n */\n\n/**\n * Returns the signed area of the polygon using the shoelace formula.\n * The result is positive when the vertices wind counter-clockwise and negative\n * when they wind clockwise, so the sign can be used to determine winding order.\n *\n * @param vertices polygon vertices as a flat array `[x0, y0, x1, y1, ...]`\n * @param n number of vertices to read from `vertices`\n * @returns the signed area\n */\nexport function signedArea(vertices: number[], n: number): number {\n let area = 0;\n for (let i = 0, j = n - 1; i < n; j = i++) {\n const xi = vertices[i * 2];\n const yi = vertices[i * 2 + 1];\n const xj = vertices[j * 2];\n const yj = vertices[j * 2 + 1];\n area += xj * yi - xi * yj;\n }\n return area / 2;\n}\n\n/**\n * Returns the (non-negative) area of the polygon.\n *\n * @param vertices polygon vertices as a flat array `[x0, y0, x1, y1, ...]`\n * @param n number of vertices to read from `vertices`\n * @returns the absolute area\n */\nexport function area(vertices: number[], n: number): number {\n return Math.abs(signedArea(vertices, n));\n}\n\n/**\n * Tests whether a point lies inside the polygon. Works for both convex and\n * concave polygons. Points exactly on an edge or vertex are considered inside.\n *\n * @param vertices polygon vertices as a flat array `[x0, y0, x1, y1, ...]`\n * @param n number of vertices to read from `vertices`\n * @param point the point to test\n * @returns true if the point is inside (or on the boundary of) the polygon\n */\nexport function containsPoint(vertices: number[], n: number, point: Vec2): boolean {\n let inside = false;\n const x = point[0];\n const y = point[1];\n\n for (let i = 0, j = n - 1; i < n; j = i++) {\n const xi = vertices[i * 2];\n const yi = vertices[i * 2 + 1];\n const xj = vertices[j * 2];\n const yj = vertices[j * 2 + 1];\n\n // Signed area of the triangle (j, i, point): zero when the point lies on\n // the edge, sign tells which side it is on.\n const where = (yi - yj) * (x - xi) - (xi - xj) * (y - yi);\n\n if (yj < yi) {\n // Upward edge: count a crossing when the point's y is within [yj, yi).\n if (y >= yj && y < yi) {\n if (where === 0) return true; // on edge\n if (where > 0) {\n if (y === yj) {\n // Ray passes exactly through vertex j; only toggle when the\n // previous vertex is below, to avoid double-counting.\n if (y > vertices[(j === 0 ? n - 1 : j - 1) * 2 + 1]) inside = !inside;\n } else {\n inside = !inside;\n }\n }\n }\n } else if (yi < yj) {\n // Downward edge: count a crossing when the point's y is within (yi, yj].\n if (y > yi && y <= yj) {\n if (where === 0) return true; // on edge\n if (where < 0) {\n if (y === yj) {\n if (y < vertices[(j === 0 ? n - 1 : j - 1) * 2 + 1]) inside = !inside;\n } else {\n inside = !inside;\n }\n }\n }\n } else if (y === yi && ((x >= xj && x <= xi) || (x >= xi && x <= xj))) {\n // Point lies on a horizontal edge.\n return true;\n }\n }\n\n return inside;\n}\n\n/**\n * Computes the area-weighted centroid (center of mass) of the polygon.\n * For a degenerate (zero-area) polygon this falls back to the average of the\n * vertices.\n *\n * @param out the vector to store the centroid\n * @param vertices polygon vertices as a flat array `[x0, y0, x1, y1, ...]`\n * @param n number of vertices to read from `vertices`\n * @returns out\n */\nexport function centroid(out: Vec2, vertices: number[], n: number): Vec2 {\n let cx = 0;\n let cy = 0;\n let a2 = 0; // twice the signed area\n\n for (let i = 0, j = n - 1; i < n; j = i++) {\n const xi = vertices[i * 2];\n const yi = vertices[i * 2 + 1];\n const xj = vertices[j * 2];\n const yj = vertices[j * 2 + 1];\n const cross = xj * yi - xi * yj;\n a2 += cross;\n cx += (xj + xi) * cross;\n cy += (yj + yi) * cross;\n }\n\n if (a2 === 0) {\n // Degenerate polygon (collinear vertices): use the vertex average.\n let sx = 0;\n let sy = 0;\n for (let i = 0; i < n; i++) {\n sx += vertices[i * 2];\n sy += vertices[i * 2 + 1];\n }\n out[0] = sx / n;\n out[1] = sy / n;\n return out;\n }\n\n const inv = 1 / (3 * a2);\n out[0] = cx * inv;\n out[1] = cy * inv;\n return out;\n}\n\n/**\n * Returns the perimeter (sum of edge lengths) of the polygon.\n *\n * @param vertices polygon vertices as a flat array `[x0, y0, x1, y1, ...]`\n * @param n number of vertices to read from `vertices`\n * @returns the perimeter\n */\nexport function perimeter(vertices: number[], n: number): number {\n let total = 0;\n for (let i = 0, j = n - 1; i < n; j = i++) {\n const dx = vertices[i * 2] - vertices[j * 2];\n const dy = vertices[i * 2 + 1] - vertices[j * 2 + 1];\n total += Math.sqrt(dx * dx + dy * dy);\n }\n return total;\n}\n\n/**\n * Returns the winding order of the polygon from the sign of its signed area:\n * `1` for counter-clockwise, `-1` for clockwise, and `0` for a degenerate\n * (zero-area) polygon.\n *\n * @param vertices polygon vertices as a flat array `[x0, y0, x1, y1, ...]`\n * @param n number of vertices to read from `vertices`\n * @returns 1 (CCW), -1 (CW), or 0 (degenerate)\n */\nexport function winding(vertices: number[], n: number): number {\n const a = signedArea(vertices, n);\n if (a > 0) return 1;\n if (a < 0) return -1;\n return 0;\n}\n\n/**\n * Tests whether the polygon is convex. Works for both winding orders. Assumes a\n * simple (non-self-intersecting) polygon; collinear vertices are allowed.\n *\n * @param vertices polygon vertices as a flat array `[x0, y0, x1, y1, ...]`\n * @param n number of vertices to read from `vertices`\n * @returns true if the polygon is convex\n */\nexport function isConvex(vertices: number[], n: number): boolean {\n if (n < 3) return false;\n\n let sign = 0;\n for (let i = 0; i < n; i++) {\n const p = ((i - 1 + n) % n) * 2;\n const c = i * 2;\n const q = ((i + 1) % n) * 2;\n\n // Cross product of the incoming and outgoing edges at vertex i.\n const ax = vertices[c] - vertices[p];\n const ay = vertices[c + 1] - vertices[p + 1];\n const bx = vertices[q] - vertices[c];\n const by = vertices[q + 1] - vertices[c + 1];\n const cross = ax * by - ay * bx;\n\n if (cross !== 0) {\n const s = cross > 0 ? 1 : -1;\n if (sign === 0) sign = s;\n else if (s !== sign) return false;\n }\n }\n\n return true;\n}\n\n/**\n * Tests whether vertex `i` is a reflex (concave) vertex of the polygon — the\n * interior angle at that vertex exceeds 180°. Assumes the polygon is wound\n * counter-clockwise and that `0 <= i < n`.\n *\n * @param vertices polygon vertices as a flat array `[x0, y0, x1, y1, ...]`\n * @param n number of vertices to read from `vertices`\n * @param i index of the vertex to test\n * @returns true if vertex `i` is reflex\n */\nexport function isReflexVertex(vertices: number[], n: number, i: number): boolean {\n const p = ((i - 1 + n) % n) * 2;\n const c = i * 2;\n const q = ((i + 1) % n) * 2;\n\n // Cross product of the incoming and outgoing edges; negative = right turn = reflex (CCW).\n const ax = vertices[c] - vertices[p];\n const ay = vertices[c + 1] - vertices[p + 1];\n const bx = vertices[q] - vertices[c];\n const by = vertices[q + 1] - vertices[c + 1];\n return ax * by - ay * bx < 0;\n}\n\n/**\n * Reverses the winding order of the polygon, writing the result into `out`.\n * `out` may be the same array as `vertices` to reverse in place.\n *\n * @param out the array to write the reversed polygon into\n * @param vertices polygon vertices as a flat array `[x0, y0, x1, y1, ...]`\n * @param n number of vertices to read from `vertices`\n * @returns out\n */\nexport function reverse(out: number[], vertices: number[], n: number): number[] {\n for (let lo = 0, hi = n - 1; lo < hi; lo++, hi--) {\n const x = vertices[lo * 2];\n const y = vertices[lo * 2 + 1];\n out[lo * 2] = vertices[hi * 2];\n out[lo * 2 + 1] = vertices[hi * 2 + 1];\n out[hi * 2] = x;\n out[hi * 2 + 1] = y;\n }\n // Copy the untouched middle vertex when writing to a different buffer.\n if (out !== vertices && n % 2 === 1) {\n const mid = (n >> 1) * 2;\n out[mid] = vertices[mid];\n out[mid + 1] = vertices[mid + 1];\n }\n return out;\n}\n\n/**\n * Writes the axis-aligned bounding box of the polygon into `out` as a Box2\n * `[minX, minY, maxX, maxY]`.\n *\n * @param out the box to store the result\n * @param vertices polygon vertices as a flat array `[x0, y0, x1, y1, ...]`\n * @param n number of vertices to read from `vertices`\n * @returns out\n */\nexport function bounds(out: Box2, vertices: number[], n: number): Box2 {\n let minX = Number.POSITIVE_INFINITY;\n let minY = Number.POSITIVE_INFINITY;\n let maxX = Number.NEGATIVE_INFINITY;\n let maxY = Number.NEGATIVE_INFINITY;\n\n for (let i = 0; i < n; i++) {\n const x = vertices[i * 2];\n const y = vertices[i * 2 + 1];\n if (x < minX) minX = x;\n if (x > maxX) maxX = x;\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n }\n\n out[0] = minX;\n out[1] = minY;\n out[2] = maxX;\n out[3] = maxY;\n return out;\n}\n\n/**\n * Finds the point on the polygon's boundary closest to `point` and writes it to\n * `out`. `point` may lie inside, outside, or on the polygon; the result is\n * always on an edge.\n *\n * @param out the vector to store the closest point\n * @param vertices polygon vertices as a flat array `[x0, y0, x1, y1, ...]`\n * @param n number of vertices to read from `vertices`\n * @param point the query point\n * @returns out\n */\nexport function closestPoint(out: Vec2, vertices: number[], n: number, point: Vec2): Vec2 {\n const px = point[0];\n const py = point[1];\n let bestDistSq = Number.POSITIVE_INFINITY;\n let bestX = px;\n let bestY = py;\n\n for (let i = 0, j = n - 1; i < n; j = i++) {\n const ax = vertices[j * 2];\n const ay = vertices[j * 2 + 1];\n const abx = vertices[i * 2] - ax;\n const aby = vertices[i * 2 + 1] - ay;\n\n // Project the point onto edge (a -> b), clamped to the segment.\n const d = abx * abx + aby * aby;\n let t = d > 0 ? ((px - ax) * abx + (py - ay) * aby) / d : 0;\n if (t < 0) t = 0;\n else if (t > 1) t = 1;\n\n const cx = ax + t * abx;\n const cy = ay + t * aby;\n const dx = px - cx;\n const dy = py - cy;\n const distSq = dx * dx + dy * dy;\n if (distSq < bestDistSq) {\n bestDistSq = distSq;\n bestX = cx;\n bestY = cy;\n }\n }\n\n out[0] = bestX;\n out[1] = bestY;\n return out;\n}\n\n/**\n * Returns the distance from `point` to the polygon's boundary, signed so that\n * points inside the polygon get a negative distance and points outside get a\n * positive one.\n *\n * @param vertices polygon vertices as a flat array `[x0, y0, x1, y1, ...]`\n * @param n number of vertices to read from `vertices`\n * @param point the query point\n * @returns the signed distance (negative inside, positive outside)\n */\nexport function signedDistance(vertices: number[], n: number, point: Vec2): number {\n const px = point[0];\n const py = point[1];\n let bestDistSq = Number.POSITIVE_INFINITY;\n\n for (let i = 0, j = n - 1; i < n; j = i++) {\n const ax = vertices[j * 2];\n const ay = vertices[j * 2 + 1];\n const abx = vertices[i * 2] - ax;\n const aby = vertices[i * 2 + 1] - ay;\n\n const d = abx * abx + aby * aby;\n let t = d > 0 ? ((px - ax) * abx + (py - ay) * aby) / d : 0;\n if (t < 0) t = 0;\n else if (t > 1) t = 1;\n\n const dx = px - (ax + t * abx);\n const dy = py - (ay + t * aby);\n const distSq = dx * dx + dy * dy;\n if (distSq < bestDistSq) bestDistSq = distSq;\n }\n\n const dist = Math.sqrt(bestDistSq);\n return containsPoint(vertices, n, point) ? -dist : dist;\n}\n\nconst _projA: [number, number] = [0, 0];\nconst _projB: [number, number] = [0, 0];\n\n/** Projects a polygon onto the axis (nx, ny), storing [min, max] in `out`. */\nfunction projectOntoAxis(out: [number, number], nx: number, ny: number, vertices: number[], n: number): void {\n let min = nx * vertices[0] + ny * vertices[1];\n let max = min;\n for (let i = 1; i < n; i++) {\n const d = nx * vertices[i * 2] + ny * vertices[i * 2 + 1];\n if (d < min) min = d;\n else if (d > max) max = d;\n }\n out[0] = min;\n out[1] = max;\n}\n\n/** Returns true if the two polygons are separated along any edge normal of A. */\nfunction separatedByEdgesOf(verticesA: number[], numA: number, verticesB: number[], numB: number): boolean {\n for (let i = 0, j = numA - 1; i < numA; j = i++) {\n // Normal of edge (a -> b); orientation does not matter for separation.\n const nx = verticesA[i * 2 + 1] - verticesA[j * 2 + 1];\n const ny = -(verticesA[i * 2] - verticesA[j * 2]);\n\n projectOntoAxis(_projA, nx, ny, verticesA, numA);\n projectOntoAxis(_projB, nx, ny, verticesB, numB);\n\n if (_projA[0] > _projB[1] || _projB[0] > _projA[1]) return true;\n }\n return false;\n}\n\n/**\n * Tests whether two convex polygons overlap, using the separating axis theorem.\n * Both polygons must be convex; results are undefined for concave input.\n * Polygons that touch along an edge or vertex are considered overlapping.\n *\n * @param verticesA vertices of the first polygon `[x0, y0, x1, y1, ...]`\n * @param numA number of vertices in the first polygon\n * @param verticesB vertices of the second polygon `[x0, y0, x1, y1, ...]`\n * @param numB number of vertices in the second polygon\n * @returns true if the polygons overlap\n */\nexport function overlapConvex(verticesA: number[], numA: number, verticesB: number[], numB: number): boolean {\n if (separatedByEdgesOf(verticesA, numA, verticesB, numB)) return false;\n if (separatedByEdgesOf(verticesB, numB, verticesA, numA)) return false;\n return true;\n}\n\n/**\n * Tests whether the segment `a`-`b` intersects the polygon, i.e. it has an\n * endpoint inside the polygon or crosses one of its edges. Works for convex and\n * concave polygons.\n *\n * @param vertices polygon vertices as a flat array `[x0, y0, x1, y1, ...]`\n * @param n number of vertices to read from `vertices`\n * @param a start of the segment\n * @param b end of the segment\n * @returns true if the segment intersects the polygon\n */\nexport function intersectsSegment(vertices: number[], n: number, a: Vec2, b: Vec2): boolean {\n if (containsPoint(vertices, n, a) || containsPoint(vertices, n, b)) return true;\n\n const ax = a[0];\n const ay = a[1];\n const abx = b[0] - ax;\n const aby = b[1] - ay;\n\n for (let i = 0, j = n - 1; i < n; j = i++) {\n const cx = vertices[j * 2];\n const cy = vertices[j * 2 + 1];\n const dx = vertices[i * 2];\n const dy = vertices[i * 2 + 1];\n\n // Proper segment intersection via perp products (sign-of-area test).\n const a1 = abx * (dy - ay) - aby * (dx - ax); // (b-a) x (d-a)\n const a2 = abx * (cy - ay) - aby * (cx - ax); // (b-a) x (c-a)\n if (a1 * a2 < 0) {\n const cdx = dx - cx;\n const cdy = dy - cy;\n const a3 = cdx * (ay - cy) - cdy * (ax - cx); // (d-c) x (a-c)\n const a4 = a3 + a2 - a1;\n if (a3 * a4 < 0) return true;\n }\n }\n\n return false;\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,164 @@
1
+ /**
2
+ * Creates a new IntersectsTriangleResult with default values.
3
+ * @returns A new IntersectsTriangleResult.
4
+ */
5
+ function createIntersectsTriangleResult() {
6
+ return {
7
+ fraction: 0,
8
+ hit: false,
9
+ frontFacing: false,
10
+ };
11
+ }
12
+ /**
13
+ * Ray-triangle intersection test.
14
+ * Based on https://github.com/pmjoniak/GeometricTools/blob/master/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h
15
+ *
16
+ * @param out output object to store result (hit boolean, fraction, frontFacing)
17
+ * @param origin ray origin
18
+ * @param direction ray direction
19
+ * @param length ray length
20
+ * @param a first vertex of triangle
21
+ * @param b second vertex of triangle
22
+ * @param c third vertex of triangle
23
+ * @param backfaceCulling if true, backfaces will not be considered hits
24
+ */
25
+ function intersectsTriangle(out, origin, direction, length, a, b, c, backfaceCulling) {
26
+ // compute edge1 = b - a
27
+ const e1x = b[0] - a[0];
28
+ const e1y = b[1] - a[1];
29
+ const e1z = b[2] - a[2];
30
+ // compute edge2 = c - a
31
+ const e2x = c[0] - a[0];
32
+ const e2y = c[1] - a[1];
33
+ const e2z = c[2] - a[2];
34
+ // compute normal = edge1 × edge2
35
+ const nx = e1y * e2z - e1z * e2y;
36
+ const ny = e1z * e2x - e1x * e2z;
37
+ const nz = e1x * e2y - e1y * e2x;
38
+ // determine front vs back facing
39
+ const dx = direction[0];
40
+ const dy = direction[1];
41
+ const dz = direction[2];
42
+ let DdN = dx * nx + dy * ny + dz * nz;
43
+ let sign;
44
+ if (DdN > 0) {
45
+ // backface
46
+ if (backfaceCulling) {
47
+ out.hit = false;
48
+ out.fraction = 0;
49
+ out.frontFacing = false;
50
+ return;
51
+ }
52
+ sign = 1;
53
+ }
54
+ else if (DdN < 0) {
55
+ // frontface
56
+ sign = -1;
57
+ DdN = -DdN;
58
+ }
59
+ else {
60
+ // ray is parallel to triangle
61
+ out.hit = false;
62
+ out.fraction = 0;
63
+ out.frontFacing = false;
64
+ return;
65
+ }
66
+ // compute diff = origin - a
67
+ const diffx = origin[0] - a[0];
68
+ const diffy = origin[1] - a[1];
69
+ const diffz = origin[2] - a[2];
70
+ // compute barycentric coordinate b1
71
+ // DdQxE2 = sign * D · (diff × edge2)
72
+ const diffCrossE2x = diffy * e2z - diffz * e2y;
73
+ const diffCrossE2y = diffz * e2x - diffx * e2z;
74
+ const diffCrossE2z = diffx * e2y - diffy * e2x;
75
+ const DdQxE2 = sign * (dx * diffCrossE2x + dy * diffCrossE2y + dz * diffCrossE2z);
76
+ if (DdQxE2 < 0) {
77
+ out.hit = false;
78
+ out.fraction = 0;
79
+ out.frontFacing = false;
80
+ return;
81
+ }
82
+ // compute barycentric coordinate b2
83
+ // DdE1xQ = sign * D · (edge1 × diff)
84
+ const e1CrossDiffx = e1y * diffz - e1z * diffy;
85
+ const e1CrossDiffy = e1z * diffx - e1x * diffz;
86
+ const e1CrossDiffz = e1x * diffy - e1y * diffx;
87
+ const DdE1xQ = sign * (dx * e1CrossDiffx + dy * e1CrossDiffy + dz * e1CrossDiffz);
88
+ if (DdE1xQ < 0) {
89
+ out.hit = false;
90
+ out.fraction = 0;
91
+ out.frontFacing = false;
92
+ return;
93
+ }
94
+ // check if b1 + b2 > 1
95
+ if (DdQxE2 + DdE1xQ > DdN) {
96
+ out.hit = false;
97
+ out.fraction = 0;
98
+ out.frontFacing = false;
99
+ return;
100
+ }
101
+ // compute intersection distance
102
+ const QdN = -sign * (diffx * nx + diffy * ny + diffz * nz);
103
+ if (QdN < 0) {
104
+ out.hit = false;
105
+ out.fraction = 0;
106
+ out.frontFacing = false;
107
+ return;
108
+ }
109
+ const t = QdN / DdN;
110
+ // check if intersection is within ray length
111
+ if (t <= length) {
112
+ out.hit = true;
113
+ out.fraction = t / length;
114
+ out.frontFacing = sign < 0;
115
+ }
116
+ else {
117
+ out.hit = false;
118
+ out.fraction = 0;
119
+ out.frontFacing = false;
120
+ }
121
+ }
122
+ /**
123
+ * Test if a ray intersects an axis-aligned bounding box.
124
+ * Uses slab-based algorithm that handles parallel rays correctly.
125
+ *
126
+ * @param origin ray origin
127
+ * @param direction ray direction
128
+ * @param length ray length
129
+ * @param aabb AABB to test against
130
+ * @returns true if ray intersects the AABB, false otherwise
131
+ */
132
+ function intersectsBox3(origin, direction, length, aabb) {
133
+ let tmin = 0;
134
+ let tmax = length;
135
+ for (let i = 0; i < 3; i++) {
136
+ const d = direction[i];
137
+ if (Math.abs(d) < 1e-10) {
138
+ // ray is parallel to slab: check if origin is within slab
139
+ if (origin[i] < aabb[i] || origin[i] > aabb[i + 3]) {
140
+ return false;
141
+ }
142
+ }
143
+ else {
144
+ // compute intersection times with slab
145
+ const invD = 1 / d;
146
+ let t0 = (aabb[i] - origin[i]) * invD;
147
+ let t1 = (aabb[i + 3] - origin[i]) * invD;
148
+ if (invD < 0) {
149
+ const temp = t0;
150
+ t0 = t1;
151
+ t1 = temp;
152
+ }
153
+ tmin = Math.max(tmin, t0);
154
+ tmax = Math.min(tmax, t1);
155
+ if (tmax < tmin) {
156
+ return false;
157
+ }
158
+ }
159
+ }
160
+ return true;
161
+ }
162
+
163
+ export { createIntersectsTriangleResult, intersectsBox3, intersectsTriangle };
164
+ //# sourceMappingURL=raycast3.js.map