math 0.0.3 → 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 (203) 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 -16
  199. package/skills/math/SKILL.md +140 -0
  200. package/AUTHORS +0 -1
  201. package/Cakefile +0 -28
  202. package/math.coffee +0 -112
  203. package/math.js +0 -141
@@ -0,0 +1,605 @@
1
+ /**
2
+ * Incremental Convex Hull 3D implementation based on Three.js ConvexHull.
3
+ *
4
+ * This implements the QuickHull algorithm with an incremental approach that maintains
5
+ * a valid hull at each step using a half-edge data structure (DCEL - Doubly Connected
6
+ * Edge List) for O(1) face adjacency queries.
7
+ *
8
+ * The algorithm is based on John Lloyd's Java implementation and was ported to
9
+ * JavaScript by Mauricio Poppe (quickhull3d), then incorporated into Three.js.
10
+ *
11
+ * References:
12
+ * - Three.js ConvexHull: https://github.com/mrdoob/three.js/blob/dev/examples/jsm/math/ConvexHull.js
13
+ * - quickhull3d by Mauricio Poppe: https://github.com/maurizzzio/quickhull3d/
14
+ * - Original Java by John Lloyd: http://www.cs.ubc.ca/~lloyd/java/quickhull3d.html
15
+ * - Dirk Gregorius presentation: https://archive.org/details/GDC2014Gregorius
16
+ *
17
+ * Algorithm: QuickHull (incremental variant)
18
+ * Time complexity: O(n log n) average, O(n²) worst case
19
+ * Space complexity: O(n + f + e) where f=faces, e=edges (~3x more than basic)
20
+ */
21
+ const EPSILON = 1e-12;
22
+ const VISIBLE = 0;
23
+ const DELETED = 1;
24
+ /**
25
+ * Computes the convex hull of a set of 3D points using an incremental QuickHull algorithm.
26
+ *
27
+ * @param points An array of numbers representing the 3D points (x1, y1, z1, x2, y2, z2, ...)
28
+ * @returns An array of indices representing the triangles of the convex hull (i1, j1, k1, i2, j2, k2, ...).
29
+ */
30
+ function quickhull3(points) {
31
+ const n = points.length / 3;
32
+ if (n < 4)
33
+ return [];
34
+ const state = createHullState(points, n);
35
+ computeInitialHull(state);
36
+ // Incrementally add vertices to hull
37
+ let vertex = nextVertexToAdd(state);
38
+ while (vertex !== null) {
39
+ addVertexToHull(state, vertex);
40
+ vertex = nextVertexToAdd(state);
41
+ }
42
+ reindexFaces(state);
43
+ return getTriangleIndices(state);
44
+ }
45
+ // Hull state management
46
+ function createHullState(points, n) {
47
+ const vertices = [];
48
+ for (let i = 0; i < n; i++) {
49
+ vertices.push(createVertexNode(i));
50
+ }
51
+ return {
52
+ points,
53
+ tolerance: -1,
54
+ faces: [],
55
+ newFaces: [],
56
+ assigned: createVertexList(),
57
+ unassigned: createVertexList(),
58
+ vertices,
59
+ };
60
+ }
61
+ function getTriangleIndices(state) {
62
+ const result = [];
63
+ for (const face of state.faces) {
64
+ if (face.mark === VISIBLE && face.edge) {
65
+ result.push(face.edge.vertex.index, face.edge.next.vertex.index, face.edge.prev.vertex.index);
66
+ }
67
+ }
68
+ return result;
69
+ }
70
+ // Vertex node functions
71
+ function createVertexNode(index) {
72
+ return {
73
+ index,
74
+ prev: null,
75
+ next: null,
76
+ face: null,
77
+ };
78
+ }
79
+ // Vertex list functions
80
+ function createVertexList() {
81
+ return {
82
+ head: null,
83
+ tail: null,
84
+ };
85
+ }
86
+ function vertexListIsEmpty(list) {
87
+ return list.head === null;
88
+ }
89
+ function vertexListClear(list) {
90
+ list.head = null;
91
+ list.tail = null;
92
+ }
93
+ function vertexListAppend(list, vertex) {
94
+ if (list.head === null) {
95
+ list.head = vertex;
96
+ }
97
+ else {
98
+ list.tail.next = vertex;
99
+ }
100
+ vertex.prev = list.tail;
101
+ vertex.next = null;
102
+ list.tail = vertex;
103
+ }
104
+ function vertexListAppendChain(list, vertex) {
105
+ if (list.head === null) {
106
+ list.head = vertex;
107
+ }
108
+ else {
109
+ list.tail.next = vertex;
110
+ }
111
+ vertex.prev = list.tail;
112
+ // Find end of chain
113
+ let current = vertex;
114
+ while (current.next !== null) {
115
+ current = current.next;
116
+ }
117
+ list.tail = current;
118
+ }
119
+ function vertexListInsertBefore(list, target, vertex) {
120
+ vertex.prev = target.prev;
121
+ vertex.next = target;
122
+ if (vertex.prev === null) {
123
+ list.head = vertex;
124
+ }
125
+ else {
126
+ vertex.prev.next = vertex;
127
+ }
128
+ target.prev = vertex;
129
+ }
130
+ function vertexListRemove(list, vertex) {
131
+ if (vertex.prev === null) {
132
+ list.head = vertex.next;
133
+ }
134
+ else {
135
+ vertex.prev.next = vertex.next;
136
+ }
137
+ if (vertex.next === null) {
138
+ list.tail = vertex.prev;
139
+ }
140
+ else {
141
+ vertex.next.prev = vertex.prev;
142
+ }
143
+ }
144
+ function vertexListRemoveSubList(list, a, b) {
145
+ if (a.prev === null) {
146
+ list.head = b.next;
147
+ }
148
+ else {
149
+ a.prev.next = b.next;
150
+ }
151
+ if (b.next === null) {
152
+ list.tail = a.prev;
153
+ }
154
+ else {
155
+ b.next.prev = a.prev;
156
+ }
157
+ }
158
+ // Half-edge functions
159
+ function createHalfEdge(vertex, face) {
160
+ return {
161
+ vertex,
162
+ prev: null,
163
+ next: null,
164
+ twin: null,
165
+ face,
166
+ };
167
+ }
168
+ function halfEdgeHead(edge) {
169
+ return edge.vertex;
170
+ }
171
+ function halfEdgeTail(edge) {
172
+ return edge.prev ? edge.prev.vertex : null;
173
+ }
174
+ function halfEdgeSetTwin(edge, twin) {
175
+ edge.twin = twin;
176
+ twin.twin = edge;
177
+ }
178
+ // Face functions
179
+ function createFace() {
180
+ return {
181
+ normal: [0, 0, 0],
182
+ midpoint: [0, 0, 0],
183
+ area: 0,
184
+ constant: 0,
185
+ outside: null,
186
+ mark: VISIBLE,
187
+ edge: null,
188
+ };
189
+ }
190
+ function faceCreate(a, b, c) {
191
+ const face = createFace();
192
+ const e0 = createHalfEdge(a, face);
193
+ const e1 = createHalfEdge(b, face);
194
+ const e2 = createHalfEdge(c, face);
195
+ // Join edges in a cycle
196
+ e0.next = e1;
197
+ e0.prev = e2;
198
+ e1.next = e2;
199
+ e1.prev = e0;
200
+ e2.next = e0;
201
+ e2.prev = e1;
202
+ face.edge = e0;
203
+ return face;
204
+ }
205
+ function faceGetEdge(face, i) {
206
+ let edge = face.edge;
207
+ if (!edge)
208
+ return null;
209
+ while (i > 0) {
210
+ edge = edge.next;
211
+ i--;
212
+ }
213
+ while (i < 0) {
214
+ edge = edge.prev;
215
+ i++;
216
+ }
217
+ return edge;
218
+ }
219
+ function faceCompute(face, points) {
220
+ const a = halfEdgeTail(face.edge);
221
+ const b = halfEdgeHead(face.edge);
222
+ const c = halfEdgeHead(face.edge.next);
223
+ const aIdx = a.index * 3;
224
+ const bIdx = b.index * 3;
225
+ const cIdx = c.index * 3;
226
+ const ax = points[aIdx], ay = points[aIdx + 1], az = points[aIdx + 2];
227
+ const bx = points[bIdx], by = points[bIdx + 1], bz = points[bIdx + 2];
228
+ const cx = points[cIdx], cy = points[cIdx + 1], cz = points[cIdx + 2];
229
+ // Compute edges
230
+ const e1x = bx - ax, e1y = by - ay, e1z = bz - az;
231
+ const e2x = cx - ax, e2y = cy - ay, e2z = cz - az;
232
+ // Cross product for normal
233
+ const nx = e1y * e2z - e1z * e2y;
234
+ const ny = e1z * e2x - e1x * e2z;
235
+ const nz = e1x * e2y - e1y * e2x;
236
+ // Normalize
237
+ const len = Math.sqrt(nx * nx + ny * ny + nz * nz);
238
+ if (len > EPSILON) {
239
+ face.normal[0] = nx / len;
240
+ face.normal[1] = ny / len;
241
+ face.normal[2] = nz / len;
242
+ }
243
+ // Compute midpoint
244
+ face.midpoint[0] = (ax + bx + cx) / 3;
245
+ face.midpoint[1] = (ay + by + cy) / 3;
246
+ face.midpoint[2] = (az + bz + cz) / 3;
247
+ // Area
248
+ face.area = len / 2;
249
+ // Plane constant
250
+ face.constant = face.normal[0] * face.midpoint[0] + face.normal[1] * face.midpoint[1] + face.normal[2] * face.midpoint[2];
251
+ }
252
+ function faceDistanceToPoint(face, points, vertexIndex) {
253
+ const idx = vertexIndex * 3;
254
+ return face.normal[0] * points[idx] + face.normal[1] * points[idx + 1] + face.normal[2] * points[idx + 2] - face.constant;
255
+ }
256
+ // Hull computation functions
257
+ function computeExtremes(state) {
258
+ const minVertices = [];
259
+ const maxVertices = [];
260
+ const min = [Infinity, Infinity, Infinity];
261
+ const max = [-Infinity, -Infinity, -Infinity];
262
+ // Initialize with first vertex
263
+ for (let i = 0; i < 3; i++) {
264
+ minVertices[i] = state.vertices[0];
265
+ maxVertices[i] = state.vertices[0];
266
+ min[i] = state.points[i];
267
+ max[i] = state.points[i];
268
+ }
269
+ // Find extremal points along each axis
270
+ for (let i = 0; i < state.vertices.length; i++) {
271
+ const vertex = state.vertices[i];
272
+ const idx = vertex.index * 3;
273
+ for (let j = 0; j < 3; j++) {
274
+ const val = state.points[idx + j];
275
+ if (val < min[j]) {
276
+ min[j] = val;
277
+ minVertices[j] = vertex;
278
+ }
279
+ if (val > max[j]) {
280
+ max[j] = val;
281
+ maxVertices[j] = vertex;
282
+ }
283
+ }
284
+ }
285
+ // Compute tolerance based on data range
286
+ state.tolerance =
287
+ 3 *
288
+ Number.EPSILON *
289
+ (Math.max(Math.abs(min[0]), Math.abs(max[0])) +
290
+ Math.max(Math.abs(min[1]), Math.abs(max[1])) +
291
+ Math.max(Math.abs(min[2]), Math.abs(max[2])));
292
+ return { min: minVertices, max: maxVertices };
293
+ }
294
+ function computeInitialHull(state) {
295
+ const extremes = computeExtremes(state);
296
+ const min = extremes.min;
297
+ const max = extremes.max;
298
+ // 1. Find the two vertices with greatest 1D separation
299
+ let maxDistance = 0;
300
+ let index = 0;
301
+ for (let i = 0; i < 3; i++) {
302
+ const idx0 = min[i].index * 3;
303
+ const idx1 = max[i].index * 3;
304
+ const distance = state.points[idx0 + i] - state.points[idx1 + i];
305
+ if (Math.abs(distance) > maxDistance) {
306
+ maxDistance = Math.abs(distance);
307
+ index = i;
308
+ }
309
+ }
310
+ const v0 = min[index];
311
+ const v1 = max[index];
312
+ // 2. Find vertex farthest from line v0-v1
313
+ let v2 = null;
314
+ maxDistance = 0;
315
+ for (const vertex of state.vertices) {
316
+ if (vertex !== v0 && vertex !== v1) {
317
+ const dist = distanceToLineSquared(state.points, vertex.index, v0.index, v1.index);
318
+ if (dist > maxDistance) {
319
+ maxDistance = dist;
320
+ v2 = vertex;
321
+ }
322
+ }
323
+ }
324
+ if (!v2)
325
+ return;
326
+ // 3. Find vertex farthest from plane v0-v1-v2
327
+ let v3 = null;
328
+ maxDistance = -1;
329
+ const normal = [0, 0, 0];
330
+ const offset = computePlane(state.points, v0.index, v1.index, v2.index, normal);
331
+ for (const vertex of state.vertices) {
332
+ if (vertex !== v0 && vertex !== v1 && vertex !== v2) {
333
+ const dist = Math.abs(distanceToPlane(state.points, vertex.index, normal, offset));
334
+ if (dist > maxDistance) {
335
+ maxDistance = dist;
336
+ v3 = vertex;
337
+ }
338
+ }
339
+ }
340
+ if (!v3)
341
+ return;
342
+ // Create initial tetrahedron
343
+ const faces = [];
344
+ if (distanceToPlane(state.points, v3.index, normal, offset) < 0) {
345
+ // Normal points outward
346
+ faces.push(faceCreate(v0, v1, v2), faceCreate(v3, v1, v0), faceCreate(v3, v2, v1), faceCreate(v3, v0, v2));
347
+ // Set twin edges
348
+ for (let i = 0; i < 3; i++) {
349
+ const j = (i + 1) % 3;
350
+ halfEdgeSetTwin(faceGetEdge(faces[i + 1], 2), faceGetEdge(faces[0], j));
351
+ halfEdgeSetTwin(faceGetEdge(faces[i + 1], 1), faceGetEdge(faces[j + 1], 0));
352
+ }
353
+ }
354
+ else {
355
+ // Normal points inward
356
+ faces.push(faceCreate(v0, v2, v1), faceCreate(v3, v0, v1), faceCreate(v3, v1, v2), faceCreate(v3, v2, v0));
357
+ // Set twin edges
358
+ for (let i = 0; i < 3; i++) {
359
+ const j = (i + 1) % 3;
360
+ halfEdgeSetTwin(faceGetEdge(faces[i + 1], 2), faceGetEdge(faces[0], (3 - i) % 3));
361
+ halfEdgeSetTwin(faceGetEdge(faces[i + 1], 0), faceGetEdge(faces[j + 1], 1));
362
+ }
363
+ }
364
+ // Add faces to hull
365
+ for (const face of faces) {
366
+ faceCompute(face, state.points);
367
+ state.faces.push(face);
368
+ }
369
+ // Assign remaining vertices to faces
370
+ for (const vertex of state.vertices) {
371
+ if (vertex !== v0 && vertex !== v1 && vertex !== v2 && vertex !== v3) {
372
+ maxDistance = state.tolerance;
373
+ let maxFace = null;
374
+ for (const face of state.faces) {
375
+ const distance = faceDistanceToPoint(face, state.points, vertex.index);
376
+ if (distance > maxDistance) {
377
+ maxDistance = distance;
378
+ maxFace = face;
379
+ }
380
+ }
381
+ if (maxFace !== null) {
382
+ addVertexToFace(state, vertex, maxFace);
383
+ }
384
+ }
385
+ }
386
+ }
387
+ function addVertexToFace(state, vertex, face) {
388
+ vertex.face = face;
389
+ if (face.outside === null) {
390
+ vertexListAppend(state.assigned, vertex);
391
+ }
392
+ else {
393
+ vertexListInsertBefore(state.assigned, face.outside, vertex);
394
+ }
395
+ face.outside = vertex;
396
+ }
397
+ function removeVertexFromFace(state, vertex, face) {
398
+ if (vertex === face.outside) {
399
+ if (vertex.next !== null && vertex.next.face === face) {
400
+ face.outside = vertex.next;
401
+ }
402
+ else {
403
+ face.outside = null;
404
+ }
405
+ }
406
+ vertexListRemove(state.assigned, vertex);
407
+ }
408
+ function removeAllVerticesFromFace(state, face) {
409
+ if (face.outside !== null) {
410
+ const start = face.outside;
411
+ let end = face.outside;
412
+ while (end.next !== null && end.next.face === face) {
413
+ end = end.next;
414
+ }
415
+ vertexListRemoveSubList(state.assigned, start, end);
416
+ start.prev = null;
417
+ end.next = null;
418
+ face.outside = null;
419
+ return start;
420
+ }
421
+ return null;
422
+ }
423
+ function deleteFaceVertices(state, face, absorbingFace) {
424
+ const faceVertices = removeAllVerticesFromFace(state, face);
425
+ if (faceVertices !== null) {
426
+ {
427
+ vertexListAppendChain(state.unassigned, faceVertices);
428
+ }
429
+ }
430
+ }
431
+ function resolveUnassignedPoints(state, newFaces) {
432
+ if (vertexListIsEmpty(state.unassigned))
433
+ return;
434
+ let vertex = state.unassigned.head;
435
+ while (vertex !== null) {
436
+ const nextVertex = vertex.next;
437
+ let maxDistance = state.tolerance;
438
+ let maxFace = null;
439
+ for (const face of newFaces) {
440
+ if (face.mark === VISIBLE) {
441
+ const distance = faceDistanceToPoint(face, state.points, vertex.index);
442
+ if (distance > maxDistance) {
443
+ maxDistance = distance;
444
+ maxFace = face;
445
+ }
446
+ if (maxDistance > 1000 * state.tolerance)
447
+ break;
448
+ }
449
+ }
450
+ if (maxFace !== null) {
451
+ addVertexToFace(state, vertex, maxFace);
452
+ }
453
+ vertex = nextVertex;
454
+ }
455
+ }
456
+ function nextVertexToAdd(state) {
457
+ if (vertexListIsEmpty(state.assigned))
458
+ return null;
459
+ let eyeVertex = null;
460
+ let maxDistance = 0;
461
+ const eyeFace = state.assigned.head.face;
462
+ let vertex = eyeFace.outside;
463
+ while (vertex !== null && vertex.face === eyeFace) {
464
+ const distance = faceDistanceToPoint(eyeFace, state.points, vertex.index);
465
+ if (distance > maxDistance) {
466
+ maxDistance = distance;
467
+ eyeVertex = vertex;
468
+ }
469
+ vertex = vertex.next;
470
+ }
471
+ return eyeVertex;
472
+ }
473
+ function computeHorizon(state, eyePoint, crossEdge, face, horizon) {
474
+ deleteFaceVertices(state, face);
475
+ face.mark = DELETED;
476
+ let edge;
477
+ if (crossEdge === null) {
478
+ edge = faceGetEdge(face, 0);
479
+ }
480
+ else {
481
+ edge = crossEdge.next;
482
+ }
483
+ const startEdge = edge;
484
+ do {
485
+ const twinEdge = edge.twin;
486
+ const oppositeFace = twinEdge.face;
487
+ if (oppositeFace.mark === VISIBLE) {
488
+ if (faceDistanceToPoint(oppositeFace, state.points, eyePoint) > state.tolerance) {
489
+ computeHorizon(state, eyePoint, twinEdge, oppositeFace, horizon);
490
+ }
491
+ else {
492
+ horizon.push(edge);
493
+ }
494
+ }
495
+ edge = edge.next;
496
+ } while (edge !== startEdge);
497
+ }
498
+ function addAdjoiningFace(state, eyeVertex, horizonEdge) {
499
+ const face = faceCreate(eyeVertex, halfEdgeTail(horizonEdge), halfEdgeHead(horizonEdge));
500
+ faceCompute(face, state.points);
501
+ state.faces.push(face);
502
+ halfEdgeSetTwin(faceGetEdge(face, -1), horizonEdge.twin);
503
+ return faceGetEdge(face, 0);
504
+ }
505
+ function addNewFaces(state, eyeVertex, horizon) {
506
+ state.newFaces = [];
507
+ let firstSideEdge = null;
508
+ let previousSideEdge = null;
509
+ for (const horizonEdge of horizon) {
510
+ const sideEdge = addAdjoiningFace(state, eyeVertex, horizonEdge);
511
+ if (firstSideEdge === null) {
512
+ firstSideEdge = sideEdge;
513
+ }
514
+ else {
515
+ halfEdgeSetTwin(sideEdge.next, previousSideEdge);
516
+ }
517
+ state.newFaces.push(sideEdge.face);
518
+ previousSideEdge = sideEdge;
519
+ }
520
+ halfEdgeSetTwin(firstSideEdge.next, previousSideEdge);
521
+ }
522
+ function addVertexToHull(state, eyeVertex) {
523
+ const horizon = [];
524
+ vertexListClear(state.unassigned);
525
+ removeVertexFromFace(state, eyeVertex, eyeVertex.face);
526
+ computeHorizon(state, eyeVertex.index, null, eyeVertex.face, horizon);
527
+ addNewFaces(state, eyeVertex, horizon);
528
+ resolveUnassignedPoints(state, state.newFaces);
529
+ }
530
+ function reindexFaces(state) {
531
+ const activeFaces = [];
532
+ for (const face of state.faces) {
533
+ if (face.mark === VISIBLE) {
534
+ activeFaces.push(face);
535
+ }
536
+ }
537
+ state.faces = activeFaces;
538
+ }
539
+ // Helper functions
540
+ function computePlane(points, v0, v1, v2, outNormal) {
541
+ const p0x = points[v0 * 3];
542
+ const p0y = points[v0 * 3 + 1];
543
+ const p0z = points[v0 * 3 + 2];
544
+ const p1x = points[v1 * 3];
545
+ const p1y = points[v1 * 3 + 1];
546
+ const p1z = points[v1 * 3 + 2];
547
+ const p2x = points[v2 * 3];
548
+ const p2y = points[v2 * 3 + 1];
549
+ const p2z = points[v2 * 3 + 2];
550
+ const e1x = p1x - p0x;
551
+ const e1y = p1y - p0y;
552
+ const e1z = p1z - p0z;
553
+ const e2x = p2x - p0x;
554
+ const e2y = p2y - p0y;
555
+ const e2z = p2z - p0z;
556
+ const nx = e1y * e2z - e1z * e2y;
557
+ const ny = e1z * e2x - e1x * e2z;
558
+ const nz = e1x * e2y - e1y * e2x;
559
+ const len = Math.sqrt(nx * nx + ny * ny + nz * nz);
560
+ if (len < EPSILON) {
561
+ outNormal[0] = 0;
562
+ outNormal[1] = 0;
563
+ outNormal[2] = 1;
564
+ return 0;
565
+ }
566
+ const invLen = 1 / len;
567
+ outNormal[0] = nx * invLen;
568
+ outNormal[1] = ny * invLen;
569
+ outNormal[2] = nz * invLen;
570
+ return -(outNormal[0] * p0x + outNormal[1] * p0y + outNormal[2] * p0z);
571
+ }
572
+ function distanceToPlane(points, idx, normal, offset) {
573
+ const x = points[idx * 3];
574
+ const y = points[idx * 3 + 1];
575
+ const z = points[idx * 3 + 2];
576
+ return normal[0] * x + normal[1] * y + normal[2] * z + offset;
577
+ }
578
+ function distanceToLineSquared(points, idx, v0, v1) {
579
+ const px = points[idx * 3];
580
+ const py = points[idx * 3 + 1];
581
+ const pz = points[idx * 3 + 2];
582
+ const ax = points[v0 * 3];
583
+ const ay = points[v0 * 3 + 1];
584
+ const az = points[v0 * 3 + 2];
585
+ const bx = points[v1 * 3];
586
+ const by = points[v1 * 3 + 1];
587
+ const bz = points[v1 * 3 + 2];
588
+ const apx = px - ax;
589
+ const apy = py - ay;
590
+ const apz = pz - az;
591
+ const abx = bx - ax;
592
+ const aby = by - ay;
593
+ const abz = bz - az;
594
+ const cx = apy * abz - apz * aby;
595
+ const cy = apz * abx - apx * abz;
596
+ const cz = apx * aby - apy * abx;
597
+ const crossLenSq = cx * cx + cy * cy + cz * cz;
598
+ const abLenSq = abx * abx + aby * aby + abz * abz;
599
+ if (abLenSq < EPSILON)
600
+ return apx * apx + apy * apy + apz * apz;
601
+ return crossLenSq / abLenSq;
602
+ }
603
+
604
+ export { quickhull3 };
605
+ //# sourceMappingURL=quickhull3.js.map