three-stdlib 2.14.3 → 2.15.1

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 (72) hide show
  1. package/csm/CSM.cjs.js +1 -1
  2. package/csm/CSM.js +8 -8
  3. package/csm/CSMFrustum.cjs.js +1 -0
  4. package/csm/CSMFrustum.d.ts +19 -0
  5. package/csm/{Frustum.js → CSMFrustum.js} +8 -7
  6. package/csm/CSMShader.cjs.js +1 -0
  7. package/csm/CSMShader.d.ts +4 -0
  8. package/csm/{Shader.js → CSMShader.js} +52 -36
  9. package/curves/CurveExtras.d.ts +52 -54
  10. package/geometries/ConvexGeometry.cjs.js +1 -1
  11. package/geometries/ConvexGeometry.js +1 -1
  12. package/geometries/ParametricGeometries.cjs.js +1 -1
  13. package/geometries/ParametricGeometries.js +91 -99
  14. package/geometries/ParametricGeometry.cjs.js +1 -0
  15. package/geometries/ParametricGeometry.d.ts +18 -0
  16. package/geometries/ParametricGeometry.js +87 -0
  17. package/index.cjs.js +1 -1
  18. package/index.d.ts +57 -77
  19. package/index.js +55 -52
  20. package/interactive/InteractiveGroup.cjs.js +1 -0
  21. package/interactive/InteractiveGroup.d.ts +5 -0
  22. package/interactive/InteractiveGroup.js +87 -0
  23. package/loaders/GLTFLoader.d.ts +2 -9
  24. package/loaders/LUT3dlLoader.d.ts +2 -2
  25. package/loaders/LUTCubeLoader.d.ts +2 -2
  26. package/loaders/VOXLoader.d.ts +2 -2
  27. package/math/ConvexHull.cjs.js +1 -1
  28. package/math/ConvexHull.js +639 -603
  29. package/objects/Reflector.d.ts +1 -0
  30. package/objects/ReflectorForSSRPass.d.ts +4 -4
  31. package/objects/Refractor.d.ts +1 -0
  32. package/objects/Water2.d.ts +1 -1
  33. package/package.json +2 -1
  34. package/postprocessing/LUTPass.d.ts +3 -3
  35. package/postprocessing/SSAARenderPass.d.ts +1 -1
  36. package/postprocessing/SSRPass.d.ts +3 -3
  37. package/shaders/BokehShader2.d.ts +27 -72
  38. package/shaders/BokehShader2.js +0 -1
  39. package/csm/Frustum.cjs.js +0 -1
  40. package/csm/Shader.cjs.js +0 -1
  41. package/loaders/VRMLoader.d.ts +0 -19
  42. package/nodes/Nodes.d.ts +0 -106
  43. package/nodes/accessors/CameraNode.d.ts +0 -29
  44. package/nodes/accessors/NormalNode.d.ts +0 -13
  45. package/nodes/accessors/PositionNode.d.ts +0 -15
  46. package/nodes/accessors/ReflectNode.d.ts +0 -12
  47. package/nodes/accessors/UVNode.d.ts +0 -10
  48. package/nodes/core/AttributeNode.d.ts +0 -13
  49. package/nodes/core/ConstNode.d.ts +0 -22
  50. package/nodes/core/ExpressionNode.d.ts +0 -5
  51. package/nodes/core/FunctionCallNode.d.ts +0 -17
  52. package/nodes/core/FunctionNode.d.ts +0 -28
  53. package/nodes/core/InputNode.d.ts +0 -12
  54. package/nodes/core/Node.d.ts +0 -34
  55. package/nodes/core/NodeBuilder.d.ts +0 -149
  56. package/nodes/core/NodeFrame.d.ts +0 -17
  57. package/nodes/core/NodeUniform.d.ts +0 -17
  58. package/nodes/core/NodeUtils.d.ts +0 -7
  59. package/nodes/core/TempNode.d.ts +0 -23
  60. package/nodes/core/VarNode.d.ts +0 -12
  61. package/nodes/materials/MeshStandardNodeMaterial.d.ts +0 -21
  62. package/nodes/materials/NodeMaterial.d.ts +0 -28
  63. package/nodes/math/CondNode.d.ts +0 -26
  64. package/nodes/math/MathNode.d.ts +0 -57
  65. package/nodes/math/OperatorNode.d.ts +0 -17
  66. package/nodes/procedural/CheckerNode.d.ts +0 -17
  67. package/nodes/utils/JoinNode.d.ts +0 -15
  68. package/nodes/utils/TimerNode.d.ts +0 -19
  69. package/objects/ReflectorRTT.d.ts +0 -6
  70. package/shaders/index.cjs.js +0 -1
  71. package/shaders/index.d.ts +0 -53
  72. package/shaders/index.js +0 -53
@@ -4,12 +4,21 @@ import { Vector3, Line3, Plane, Triangle } from 'three';
4
4
  * Ported from: https://github.com/maurizzzio/quickhull3d/ by Mauricio Poppe (https://github.com/maurizzzio)
5
5
  */
6
6
 
7
- var ConvexHull = function () {
8
- var Visible = 0;
9
- var Deleted = 1;
10
- var v1 = new Vector3();
7
+ const Visible = 0;
8
+ const Deleted = 1;
11
9
 
12
- function ConvexHull() {
10
+ const _v1 = new Vector3();
11
+
12
+ const _line3 = new Line3();
13
+
14
+ const _plane = new Plane();
15
+
16
+ const _closestPoint = new Vector3();
17
+
18
+ const _triangle = new Triangle();
19
+
20
+ class ConvexHull {
21
+ constructor() {
13
22
  this.tolerance = -1;
14
23
  this.faces = []; // the generated faces of the convex hull
15
24
 
@@ -30,16 +39,9 @@ var ConvexHull = function () {
30
39
  this.vertices = []; // vertices of the hull (internal representation of given geometry data)
31
40
  }
32
41
 
33
- Object.assign(ConvexHull.prototype, {
34
- setFromPoints: function (points) {
35
- if (Array.isArray(points) !== true) {
36
- console.error('THREE.ConvexHull: Points parameter is not an array.');
37
- }
38
-
39
- if (points.length < 4) {
40
- console.error('THREE.ConvexHull: The algorithm needs at least four points.');
41
- }
42
-
42
+ setFromPoints(points) {
43
+ // The algorithm needs at least four points.
44
+ if (points.length >= 4) {
43
45
  this.makeEmpty();
44
46
 
45
47
  for (let i = 0, l = points.length; i < l; i++) {
@@ -47,528 +49,543 @@ var ConvexHull = function () {
47
49
  }
48
50
 
49
51
  this.compute();
50
- return this;
51
- },
52
- setFromObject: function (object) {
53
- var points = [];
54
- object.updateMatrixWorld(true);
55
- object.traverse(function (node) {
56
- var i, l, point;
57
- var geometry = node.geometry;
58
-
59
- if (geometry !== undefined) {
60
- if (geometry.isGeometry) {
61
- console.error('THREE.ConvexHull no longer supports Geometry. Use THREE.BufferGeometry instead.');
62
- return;
63
- } else if (geometry.isBufferGeometry) {
64
- var attribute = geometry.attributes.position;
65
-
66
- if (attribute !== undefined) {
67
- for (i = 0, l = attribute.count; i < l; i++) {
68
- point = new Vector3();
69
- point.fromBufferAttribute(attribute, i).applyMatrix4(node.matrixWorld);
70
- points.push(point);
71
- }
52
+ }
53
+
54
+ return this;
55
+ }
56
+
57
+ setFromObject(object) {
58
+ const points = [];
59
+ object.updateMatrixWorld(true);
60
+ object.traverse(function (node) {
61
+ const geometry = node.geometry;
62
+
63
+ if (geometry !== undefined) {
64
+ if (geometry.isGeometry) {
65
+ console.error('THREE.ConvexHull no longer supports Geometry. Use THREE.BufferGeometry instead.');
66
+ return;
67
+ } else if (geometry.isBufferGeometry) {
68
+ const attribute = geometry.attributes.position;
69
+
70
+ if (attribute !== undefined) {
71
+ for (let i = 0, l = attribute.count; i < l; i++) {
72
+ const point = new Vector3();
73
+ point.fromBufferAttribute(attribute, i).applyMatrix4(node.matrixWorld);
74
+ points.push(point);
72
75
  }
73
76
  }
74
77
  }
75
- });
76
- return this.setFromPoints(points);
77
- },
78
- containsPoint: function (point) {
79
- var faces = this.faces;
80
-
81
- for (let i = 0, l = faces.length; i < l; i++) {
82
- var face = faces[i]; // compute signed distance and check on what half space the point lies
83
-
84
- if (face.distanceToPoint(point) > this.tolerance) return false;
85
78
  }
79
+ });
80
+ return this.setFromPoints(points);
81
+ }
86
82
 
87
- return true;
88
- },
89
- intersectRay: function (ray, target) {
90
- // based on "Fast Ray-Convex Polyhedron Intersection" by Eric Haines, GRAPHICS GEMS II
91
- var faces = this.faces;
92
- var tNear = -Infinity;
93
- var tFar = Infinity;
83
+ containsPoint(point) {
84
+ const faces = this.faces;
94
85
 
95
- for (let i = 0, l = faces.length; i < l; i++) {
96
- var face = faces[i]; // interpret faces as planes for the further computation
86
+ for (let i = 0, l = faces.length; i < l; i++) {
87
+ const face = faces[i]; // compute signed distance and check on what half space the point lies
97
88
 
98
- var vN = face.distanceToPoint(ray.origin);
99
- var vD = face.normal.dot(ray.direction); // if the origin is on the positive side of a plane (so the plane can "see" the origin) and
100
- // the ray is turned away or parallel to the plane, there is no intersection
89
+ if (face.distanceToPoint(point) > this.tolerance) return false;
90
+ }
101
91
 
102
- if (vN > 0 && vD >= 0) return null; // compute the distance from the ray’s origin to the intersection with the plane
92
+ return true;
93
+ }
103
94
 
104
- var t = vD !== 0 ? -vN / vD : 0; // only proceed if the distance is positive. a negative distance means the intersection point
105
- // lies "behind" the origin
95
+ intersectRay(ray, target) {
96
+ // based on "Fast Ray-Convex Polyhedron Intersection" by Eric Haines, GRAPHICS GEMS II
97
+ const faces = this.faces;
98
+ let tNear = -Infinity;
99
+ let tFar = Infinity;
106
100
 
107
- if (t <= 0) continue; // now categorized plane as front-facing or back-facing
101
+ for (let i = 0, l = faces.length; i < l; i++) {
102
+ const face = faces[i]; // interpret faces as planes for the further computation
108
103
 
109
- if (vD > 0) {
110
- // plane faces away from the ray, so this plane is a back-face
111
- tFar = Math.min(t, tFar);
112
- } else {
113
- // front-face
114
- tNear = Math.max(t, tNear);
115
- }
104
+ const vN = face.distanceToPoint(ray.origin);
105
+ const vD = face.normal.dot(ray.direction); // if the origin is on the positive side of a plane (so the plane can "see" the origin) and
106
+ // the ray is turned away or parallel to the plane, there is no intersection
116
107
 
117
- if (tNear > tFar) {
118
- // if tNear ever is greater than tFar, the ray must miss the convex hull
119
- return null;
120
- }
121
- } // evaluate intersection point
122
- // always try tNear first since its the closer intersection point
108
+ if (vN > 0 && vD >= 0) return null; // compute the distance from the ray’s origin to the intersection with the plane
123
109
 
110
+ const t = vD !== 0 ? -vN / vD : 0; // only proceed if the distance is positive. a negative distance means the intersection point
111
+ // lies "behind" the origin
124
112
 
125
- if (tNear !== -Infinity) {
126
- ray.at(tNear, target);
127
- } else {
128
- ray.at(tFar, target);
129
- }
113
+ if (t <= 0) continue; // now categorized plane as front-facing or back-facing
130
114
 
131
- return target;
132
- },
133
- intersectsRay: function (ray) {
134
- return this.intersectRay(ray, v1) !== null;
135
- },
136
- makeEmpty: function () {
137
- this.faces = [];
138
- this.vertices = [];
139
- return this;
140
- },
141
- // Adds a vertex to the 'assigned' list of vertices and assigns it to the given face
142
- addVertexToFace: function (vertex, face) {
143
- vertex.face = face;
144
-
145
- if (face.outside === null) {
146
- this.assigned.append(vertex);
115
+ if (vD > 0) {
116
+ // plane faces away from the ray, so this plane is a back-face
117
+ tFar = Math.min(t, tFar);
147
118
  } else {
148
- this.assigned.insertBefore(face.outside, vertex);
119
+ // front-face
120
+ tNear = Math.max(t, tNear);
149
121
  }
150
122
 
151
- face.outside = vertex;
152
- return this;
153
- },
154
- // Removes a vertex from the 'assigned' list of vertices and from the given face
155
- removeVertexFromFace: function (vertex, face) {
156
- if (vertex === face.outside) {
157
- // fix face.outside link
158
- if (vertex.next !== null && vertex.next.face === face) {
159
- // face has at least 2 outside vertices, move the 'outside' reference
160
- face.outside = vertex.next;
161
- } else {
162
- // vertex was the only outside vertex that face had
163
- face.outside = null;
164
- }
123
+ if (tNear > tFar) {
124
+ // if tNear ever is greater than tFar, the ray must miss the convex hull
125
+ return null;
165
126
  }
127
+ } // evaluate intersection point
128
+ // always try tNear first since its the closer intersection point
166
129
 
167
- this.assigned.remove(vertex);
168
- return this;
169
- },
170
- // Removes all the visible vertices that a given face is able to see which are stored in the 'assigned' vertext list
171
- removeAllVerticesFromFace: function (face) {
172
- if (face.outside !== null) {
173
- // reference to the first and last vertex of this face
174
- var start = face.outside;
175
- var end = face.outside;
176
-
177
- while (end.next !== null && end.next.face === face) {
178
- end = end.next;
179
- }
180
130
 
181
- this.assigned.removeSubList(start, end); // fix references
131
+ if (tNear !== -Infinity) {
132
+ ray.at(tNear, target);
133
+ } else {
134
+ ray.at(tFar, target);
135
+ }
182
136
 
183
- start.prev = end.next = null;
137
+ return target;
138
+ }
139
+
140
+ intersectsRay(ray) {
141
+ return this.intersectRay(ray, _v1) !== null;
142
+ }
143
+
144
+ makeEmpty() {
145
+ this.faces = [];
146
+ this.vertices = [];
147
+ return this;
148
+ } // Adds a vertex to the 'assigned' list of vertices and assigns it to the given face
149
+
150
+
151
+ addVertexToFace(vertex, face) {
152
+ vertex.face = face;
153
+
154
+ if (face.outside === null) {
155
+ this.assigned.append(vertex);
156
+ } else {
157
+ this.assigned.insertBefore(face.outside, vertex);
158
+ }
159
+
160
+ face.outside = vertex;
161
+ return this;
162
+ } // Removes a vertex from the 'assigned' list of vertices and from the given face
163
+
164
+
165
+ removeVertexFromFace(vertex, face) {
166
+ if (vertex === face.outside) {
167
+ // fix face.outside link
168
+ if (vertex.next !== null && vertex.next.face === face) {
169
+ // face has at least 2 outside vertices, move the 'outside' reference
170
+ face.outside = vertex.next;
171
+ } else {
172
+ // vertex was the only outside vertex that face had
184
173
  face.outside = null;
185
- return start;
186
174
  }
187
- },
188
- // Removes all the visible vertices that 'face' is able to see
189
- deleteFaceVertices: function (face, absorbingFace) {
190
- var faceVertices = this.removeAllVerticesFromFace(face);
191
-
192
- if (faceVertices !== undefined) {
193
- if (absorbingFace === undefined) {
194
- // mark the vertices to be reassigned to some other face
195
- this.unassigned.appendChain(faceVertices);
196
- } else {
197
- // if there's an absorbing face try to assign as many vertices as possible to it
198
- var vertex = faceVertices;
175
+ }
199
176
 
200
- do {
201
- // we need to buffer the subsequent vertex at this point because the 'vertex.next' reference
202
- // will be changed by upcoming method calls
203
- var nextVertex = vertex.next;
204
- var distance = absorbingFace.distanceToPoint(vertex.point); // check if 'vertex' is able to see 'absorbingFace'
177
+ this.assigned.remove(vertex);
178
+ return this;
179
+ } // Removes all the visible vertices that a given face is able to see which are stored in the 'assigned' vertext list
205
180
 
206
- if (distance > this.tolerance) {
207
- this.addVertexToFace(vertex, absorbingFace);
208
- } else {
209
- this.unassigned.append(vertex);
210
- } // now assign next vertex
211
181
 
182
+ removeAllVerticesFromFace(face) {
183
+ if (face.outside !== null) {
184
+ // reference to the first and last vertex of this face
185
+ const start = face.outside;
186
+ let end = face.outside;
212
187
 
213
- vertex = nextVertex;
214
- } while (vertex !== null);
215
- }
188
+ while (end.next !== null && end.next.face === face) {
189
+ end = end.next;
216
190
  }
217
191
 
218
- return this;
219
- },
220
- // Reassigns as many vertices as possible from the unassigned list to the new faces
221
- resolveUnassignedPoints: function (newFaces) {
222
- if (this.unassigned.isEmpty() === false) {
223
- var vertex = this.unassigned.first();
192
+ this.assigned.removeSubList(start, end); // fix references
224
193
 
225
- do {
226
- // buffer 'next' reference, see .deleteFaceVertices()
227
- var nextVertex = vertex.next;
228
- var maxDistance = this.tolerance;
229
- var maxFace = null;
194
+ start.prev = end.next = null;
195
+ face.outside = null;
196
+ return start;
197
+ }
198
+ } // Removes all the visible vertices that 'face' is able to see
230
199
 
231
- for (let i = 0; i < newFaces.length; i++) {
232
- var face = newFaces[i];
233
200
 
234
- if (face.mark === Visible) {
235
- var distance = face.distanceToPoint(vertex.point);
201
+ deleteFaceVertices(face, absorbingFace) {
202
+ const faceVertices = this.removeAllVerticesFromFace(face);
236
203
 
237
- if (distance > maxDistance) {
238
- maxDistance = distance;
239
- maxFace = face;
240
- }
204
+ if (faceVertices !== undefined) {
205
+ if (absorbingFace === undefined) {
206
+ // mark the vertices to be reassigned to some other face
207
+ this.unassigned.appendChain(faceVertices);
208
+ } else {
209
+ // if there's an absorbing face try to assign as many vertices as possible to it
210
+ let vertex = faceVertices;
241
211
 
242
- if (maxDistance > 1000 * this.tolerance) break;
243
- }
244
- } // 'maxFace' can be null e.g. if there are identical vertices
212
+ do {
213
+ // we need to buffer the subsequent vertex at this point because the 'vertex.next' reference
214
+ // will be changed by upcoming method calls
215
+ const nextVertex = vertex.next;
216
+ const distance = absorbingFace.distanceToPoint(vertex.point); // check if 'vertex' is able to see 'absorbingFace'
245
217
 
218
+ if (distance > this.tolerance) {
219
+ this.addVertexToFace(vertex, absorbingFace);
220
+ } else {
221
+ this.unassigned.append(vertex);
222
+ } // now assign next vertex
246
223
 
247
- if (maxFace !== null) {
248
- this.addVertexToFace(vertex, maxFace);
249
- }
250
224
 
251
225
  vertex = nextVertex;
252
226
  } while (vertex !== null);
253
227
  }
228
+ }
254
229
 
255
- return this;
256
- },
257
- // Computes the extremes of a simplex which will be the initial hull
258
- computeExtremes: function () {
259
- var min = new Vector3();
260
- var max = new Vector3();
261
- var minVertices = [];
262
- var maxVertices = [];
263
- var i, l, j; // initially assume that the first vertex is the min/max
264
-
265
- for (i = 0; i < 3; i++) {
266
- minVertices[i] = maxVertices[i] = this.vertices[0];
267
- }
230
+ return this;
231
+ } // Reassigns as many vertices as possible from the unassigned list to the new faces
268
232
 
269
- min.copy(this.vertices[0].point);
270
- max.copy(this.vertices[0].point); // compute the min/max vertex on all six directions
271
233
 
272
- for (i = 0, l = this.vertices.length; i < l; i++) {
273
- var vertex = this.vertices[i];
274
- var point = vertex.point; // update the min coordinates
234
+ resolveUnassignedPoints(newFaces) {
235
+ if (this.unassigned.isEmpty() === false) {
236
+ let vertex = this.unassigned.first();
275
237
 
276
- for (j = 0; j < 3; j++) {
277
- if (point.getComponent(j) < min.getComponent(j)) {
278
- min.setComponent(j, point.getComponent(j));
279
- minVertices[j] = vertex;
280
- }
281
- } // update the max coordinates
238
+ do {
239
+ // buffer 'next' reference, see .deleteFaceVertices()
240
+ const nextVertex = vertex.next;
241
+ let maxDistance = this.tolerance;
242
+ let maxFace = null;
282
243
 
244
+ for (let i = 0; i < newFaces.length; i++) {
245
+ const face = newFaces[i];
283
246
 
284
- for (j = 0; j < 3; j++) {
285
- if (point.getComponent(j) > max.getComponent(j)) {
286
- max.setComponent(j, point.getComponent(j));
287
- maxVertices[j] = vertex;
288
- }
289
- }
290
- } // use min/max vectors to compute an optimal epsilon
291
-
292
-
293
- this.tolerance = 3 * Number.EPSILON * (Math.max(Math.abs(min.x), Math.abs(max.x)) + Math.max(Math.abs(min.y), Math.abs(max.y)) + Math.max(Math.abs(min.z), Math.abs(max.z)));
294
- return {
295
- min: minVertices,
296
- max: maxVertices
297
- };
298
- },
299
- // Computes the initial simplex assigning to its faces all the points
300
- // that are candidates to form part of the hull
301
- computeInitialHull: function () {
302
- var line3, plane, closestPoint;
303
- return function computeInitialHull() {
304
- if (line3 === undefined) {
305
- line3 = new Line3();
306
- plane = new Plane();
307
- closestPoint = new Vector3();
308
- }
247
+ if (face.mark === Visible) {
248
+ const distance = face.distanceToPoint(vertex.point);
309
249
 
310
- var vertex,
311
- vertices = this.vertices;
312
- var extremes = this.computeExtremes();
313
- var min = extremes.min;
314
- var max = extremes.max;
315
- var v0, v1, v2, v3;
316
- var i, l, j; // 1. Find the two vertices 'v0' and 'v1' with the greatest 1d separation
317
- // (max.x - min.x)
318
- // (max.y - min.y)
319
- // (max.z - min.z)
250
+ if (distance > maxDistance) {
251
+ maxDistance = distance;
252
+ maxFace = face;
253
+ }
320
254
 
321
- var distance,
322
- maxDistance = 0;
323
- var index = 0;
255
+ if (maxDistance > 1000 * this.tolerance) break;
256
+ }
257
+ } // 'maxFace' can be null e.g. if there are identical vertices
324
258
 
325
- for (i = 0; i < 3; i++) {
326
- distance = max[i].point.getComponent(i) - min[i].point.getComponent(i);
327
259
 
328
- if (distance > maxDistance) {
329
- maxDistance = distance;
330
- index = i;
331
- }
260
+ if (maxFace !== null) {
261
+ this.addVertexToFace(vertex, maxFace);
332
262
  }
333
263
 
334
- v0 = min[index];
335
- v1 = max[index]; // 2. The next vertex 'v2' is the one farthest to the line formed by 'v0' and 'v1'
264
+ vertex = nextVertex;
265
+ } while (vertex !== null);
266
+ }
336
267
 
337
- maxDistance = 0;
338
- line3.set(v0.point, v1.point);
268
+ return this;
269
+ } // Computes the extremes of a simplex which will be the initial hull
339
270
 
340
- for (i = 0, l = this.vertices.length; i < l; i++) {
341
- vertex = vertices[i];
342
271
 
343
- if (vertex !== v0 && vertex !== v1) {
344
- line3.closestPointToPoint(vertex.point, true, closestPoint);
345
- distance = closestPoint.distanceToSquared(vertex.point);
272
+ computeExtremes() {
273
+ const min = new Vector3();
274
+ const max = new Vector3();
275
+ const minVertices = [];
276
+ const maxVertices = []; // initially assume that the first vertex is the min/max
346
277
 
347
- if (distance > maxDistance) {
348
- maxDistance = distance;
349
- v2 = vertex;
350
- }
351
- }
352
- } // 3. The next vertex 'v3' is the one farthest to the plane 'v0', 'v1', 'v2'
278
+ for (let i = 0; i < 3; i++) {
279
+ minVertices[i] = maxVertices[i] = this.vertices[0];
280
+ }
353
281
 
282
+ min.copy(this.vertices[0].point);
283
+ max.copy(this.vertices[0].point); // compute the min/max vertex on all six directions
354
284
 
355
- maxDistance = -1;
356
- plane.setFromCoplanarPoints(v0.point, v1.point, v2.point);
285
+ for (let i = 0, l = this.vertices.length; i < l; i++) {
286
+ const vertex = this.vertices[i];
287
+ const point = vertex.point; // update the min coordinates
357
288
 
358
- for (i = 0, l = this.vertices.length; i < l; i++) {
359
- vertex = vertices[i];
289
+ for (let j = 0; j < 3; j++) {
290
+ if (point.getComponent(j) < min.getComponent(j)) {
291
+ min.setComponent(j, point.getComponent(j));
292
+ minVertices[j] = vertex;
293
+ }
294
+ } // update the max coordinates
360
295
 
361
- if (vertex !== v0 && vertex !== v1 && vertex !== v2) {
362
- distance = Math.abs(plane.distanceToPoint(vertex.point));
363
296
 
364
- if (distance > maxDistance) {
365
- maxDistance = distance;
366
- v3 = vertex;
367
- }
368
- }
297
+ for (let j = 0; j < 3; j++) {
298
+ if (point.getComponent(j) > max.getComponent(j)) {
299
+ max.setComponent(j, point.getComponent(j));
300
+ maxVertices[j] = vertex;
369
301
  }
302
+ }
303
+ } // use min/max vectors to compute an optimal epsilon
370
304
 
371
- var faces = [];
372
305
 
373
- if (plane.distanceToPoint(v3.point) < 0) {
374
- // the face is not able to see the point so 'plane.normal' is pointing outside the tetrahedron
375
- faces.push(Face.create(v0, v1, v2), Face.create(v3, v1, v0), Face.create(v3, v2, v1), Face.create(v3, v0, v2)); // set the twin edge
306
+ this.tolerance = 3 * Number.EPSILON * (Math.max(Math.abs(min.x), Math.abs(max.x)) + Math.max(Math.abs(min.y), Math.abs(max.y)) + Math.max(Math.abs(min.z), Math.abs(max.z)));
307
+ return {
308
+ min: minVertices,
309
+ max: maxVertices
310
+ };
311
+ } // Computes the initial simplex assigning to its faces all the points
312
+ // that are candidates to form part of the hull
376
313
 
377
- for (i = 0; i < 3; i++) {
378
- j = (i + 1) % 3; // join face[ i ] i > 0, with the first face
379
314
 
380
- faces[i + 1].getEdge(2).setTwin(faces[0].getEdge(j)); // join face[ i ] with face[ i + 1 ], 1 <= i <= 3
315
+ computeInitialHull() {
316
+ const vertices = this.vertices;
317
+ const extremes = this.computeExtremes();
318
+ const min = extremes.min;
319
+ const max = extremes.max; // 1. Find the two vertices 'v0' and 'v1' with the greatest 1d separation
320
+ // (max.x - min.x)
321
+ // (max.y - min.y)
322
+ // (max.z - min.z)
381
323
 
382
- faces[i + 1].getEdge(1).setTwin(faces[j + 1].getEdge(0));
383
- }
384
- } else {
385
- // the face is able to see the point so 'plane.normal' is pointing inside the tetrahedron
386
- faces.push(Face.create(v0, v2, v1), Face.create(v3, v0, v1), Face.create(v3, v1, v2), Face.create(v3, v2, v0)); // set the twin edge
324
+ let maxDistance = 0;
325
+ let index = 0;
387
326
 
388
- for (i = 0; i < 3; i++) {
389
- j = (i + 1) % 3; // join face[ i ] i > 0, with the first face
327
+ for (let i = 0; i < 3; i++) {
328
+ const distance = max[i].point.getComponent(i) - min[i].point.getComponent(i);
390
329
 
391
- faces[i + 1].getEdge(2).setTwin(faces[0].getEdge((3 - i) % 3)); // join face[ i ] with face[ i + 1 ]
330
+ if (distance > maxDistance) {
331
+ maxDistance = distance;
332
+ index = i;
333
+ }
334
+ }
392
335
 
393
- faces[i + 1].getEdge(0).setTwin(faces[j + 1].getEdge(1));
394
- }
395
- } // the initial hull is the tetrahedron
336
+ const v0 = min[index];
337
+ const v1 = max[index];
338
+ let v2;
339
+ let v3; // 2. The next vertex 'v2' is the one farthest to the line formed by 'v0' and 'v1'
340
+
341
+ maxDistance = 0;
396
342
 
343
+ _line3.set(v0.point, v1.point);
397
344
 
398
- for (i = 0; i < 4; i++) {
399
- this.faces.push(faces[i]);
400
- } // initial assignment of vertices to the faces of the tetrahedron
345
+ for (let i = 0, l = this.vertices.length; i < l; i++) {
346
+ const vertex = vertices[i];
401
347
 
348
+ if (vertex !== v0 && vertex !== v1) {
349
+ _line3.closestPointToPoint(vertex.point, true, _closestPoint);
402
350
 
403
- for (i = 0, l = vertices.length; i < l; i++) {
404
- vertex = vertices[i];
351
+ const distance = _closestPoint.distanceToSquared(vertex.point);
405
352
 
406
- if (vertex !== v0 && vertex !== v1 && vertex !== v2 && vertex !== v3) {
407
- maxDistance = this.tolerance;
408
- var maxFace = null;
353
+ if (distance > maxDistance) {
354
+ maxDistance = distance;
355
+ v2 = vertex;
356
+ }
357
+ }
358
+ } // 3. The next vertex 'v3' is the one farthest to the plane 'v0', 'v1', 'v2'
409
359
 
410
- for (j = 0; j < 4; j++) {
411
- distance = this.faces[j].distanceToPoint(vertex.point);
412
360
 
413
- if (distance > maxDistance) {
414
- maxDistance = distance;
415
- maxFace = this.faces[j];
416
- }
417
- }
361
+ maxDistance = -1;
418
362
 
419
- if (maxFace !== null) {
420
- this.addVertexToFace(vertex, maxFace);
421
- }
422
- }
423
- }
363
+ _plane.setFromCoplanarPoints(v0.point, v1.point, v2.point);
424
364
 
425
- return this;
426
- };
427
- }(),
428
- // Removes inactive faces
429
- reindexFaces: function () {
430
- var activeFaces = [];
365
+ for (let i = 0, l = this.vertices.length; i < l; i++) {
366
+ const vertex = vertices[i];
431
367
 
432
- for (let i = 0; i < this.faces.length; i++) {
433
- var face = this.faces[i];
368
+ if (vertex !== v0 && vertex !== v1 && vertex !== v2) {
369
+ const distance = Math.abs(_plane.distanceToPoint(vertex.point));
434
370
 
435
- if (face.mark === Visible) {
436
- activeFaces.push(face);
371
+ if (distance > maxDistance) {
372
+ maxDistance = distance;
373
+ v3 = vertex;
437
374
  }
438
375
  }
376
+ }
377
+
378
+ const faces = [];
379
+
380
+ if (_plane.distanceToPoint(v3.point) < 0) {
381
+ // the face is not able to see the point so 'plane.normal' is pointing outside the tetrahedron
382
+ faces.push(Face.create(v0, v1, v2), Face.create(v3, v1, v0), Face.create(v3, v2, v1), Face.create(v3, v0, v2)); // set the twin edge
383
+
384
+ for (let i = 0; i < 3; i++) {
385
+ const j = (i + 1) % 3; // join face[ i ] i > 0, with the first face
386
+
387
+ faces[i + 1].getEdge(2).setTwin(faces[0].getEdge(j)); // join face[ i ] with face[ i + 1 ], 1 <= i <= 3
388
+
389
+ faces[i + 1].getEdge(1).setTwin(faces[j + 1].getEdge(0));
390
+ }
391
+ } else {
392
+ // the face is able to see the point so 'plane.normal' is pointing inside the tetrahedron
393
+ faces.push(Face.create(v0, v2, v1), Face.create(v3, v0, v1), Face.create(v3, v1, v2), Face.create(v3, v2, v0)); // set the twin edge
439
394
 
440
- this.faces = activeFaces;
441
- return this;
442
- },
443
- // Finds the next vertex to create faces with the current hull
444
- nextVertexToAdd: function () {
445
- // if the 'assigned' list of vertices is empty, no vertices are left. return with 'undefined'
446
- if (this.assigned.isEmpty() === false) {
447
- var eyeVertex,
448
- maxDistance = 0; // grap the first available face and start with the first visible vertex of that face
395
+ for (let i = 0; i < 3; i++) {
396
+ const j = (i + 1) % 3; // join face[ i ] i > 0, with the first face
449
397
 
450
- var eyeFace = this.assigned.first().face;
451
- var vertex = eyeFace.outside; // now calculate the farthest vertex that face can see
398
+ faces[i + 1].getEdge(2).setTwin(faces[0].getEdge((3 - i) % 3)); // join face[ i ] with face[ i + 1 ]
452
399
 
453
- do {
454
- var distance = eyeFace.distanceToPoint(vertex.point);
400
+ faces[i + 1].getEdge(0).setTwin(faces[j + 1].getEdge(1));
401
+ }
402
+ } // the initial hull is the tetrahedron
403
+
404
+
405
+ for (let i = 0; i < 4; i++) {
406
+ this.faces.push(faces[i]);
407
+ } // initial assignment of vertices to the faces of the tetrahedron
408
+
409
+
410
+ for (let i = 0, l = vertices.length; i < l; i++) {
411
+ const vertex = vertices[i];
412
+
413
+ if (vertex !== v0 && vertex !== v1 && vertex !== v2 && vertex !== v3) {
414
+ maxDistance = this.tolerance;
415
+ let maxFace = null;
416
+
417
+ for (let j = 0; j < 4; j++) {
418
+ const distance = this.faces[j].distanceToPoint(vertex.point);
455
419
 
456
420
  if (distance > maxDistance) {
457
421
  maxDistance = distance;
458
- eyeVertex = vertex;
422
+ maxFace = this.faces[j];
459
423
  }
424
+ }
460
425
 
461
- vertex = vertex.next;
462
- } while (vertex !== null && vertex.face === eyeFace);
463
-
464
- return eyeVertex;
426
+ if (maxFace !== null) {
427
+ this.addVertexToFace(vertex, maxFace);
428
+ }
465
429
  }
466
- },
467
- // Computes a chain of half edges in CCW order called the 'horizon'.
468
- // For an edge to be part of the horizon it must join a face that can see
469
- // 'eyePoint' and a face that cannot see 'eyePoint'.
470
- computeHorizon: function (eyePoint, crossEdge, face, horizon) {
471
- // moves face's vertices to the 'unassigned' vertex list
472
- this.deleteFaceVertices(face);
473
- face.mark = Deleted;
474
- var edge;
475
-
476
- if (crossEdge === null) {
477
- edge = crossEdge = face.getEdge(0);
478
- } else {
479
- // start from the next edge since 'crossEdge' was already analyzed
480
- // (actually 'crossEdge.twin' was the edge who called this method recursively)
481
- edge = crossEdge.next;
430
+ }
431
+
432
+ return this;
433
+ } // Removes inactive faces
434
+
435
+
436
+ reindexFaces() {
437
+ const activeFaces = [];
438
+
439
+ for (let i = 0; i < this.faces.length; i++) {
440
+ const face = this.faces[i];
441
+
442
+ if (face.mark === Visible) {
443
+ activeFaces.push(face);
482
444
  }
445
+ }
446
+
447
+ this.faces = activeFaces;
448
+ return this;
449
+ } // Finds the next vertex to create faces with the current hull
450
+
451
+
452
+ nextVertexToAdd() {
453
+ // if the 'assigned' list of vertices is empty, no vertices are left. return with 'undefined'
454
+ if (this.assigned.isEmpty() === false) {
455
+ let eyeVertex,
456
+ maxDistance = 0; // grap the first available face and start with the first visible vertex of that face
457
+
458
+ const eyeFace = this.assigned.first().face;
459
+ let vertex = eyeFace.outside; // now calculate the farthest vertex that face can see
483
460
 
484
461
  do {
485
- var twinEdge = edge.twin;
486
- var oppositeFace = twinEdge.face;
462
+ const distance = eyeFace.distanceToPoint(vertex.point);
487
463
 
488
- if (oppositeFace.mark === Visible) {
489
- if (oppositeFace.distanceToPoint(eyePoint) > this.tolerance) {
490
- // the opposite face can see the vertex, so proceed with next edge
491
- this.computeHorizon(eyePoint, twinEdge, oppositeFace, horizon);
492
- } else {
493
- // the opposite face can't see the vertex, so this edge is part of the horizon
494
- horizon.push(edge);
495
- }
464
+ if (distance > maxDistance) {
465
+ maxDistance = distance;
466
+ eyeVertex = vertex;
496
467
  }
497
468
 
498
- edge = edge.next;
499
- } while (edge !== crossEdge);
500
-
501
- return this;
502
- },
503
- // Creates a face with the vertices 'eyeVertex.point', 'horizonEdge.tail' and 'horizonEdge.head' in CCW order
504
- addAdjoiningFace: function (eyeVertex, horizonEdge) {
505
- // all the half edges are created in ccw order thus the face is always pointing outside the hull
506
- var face = Face.create(eyeVertex, horizonEdge.tail(), horizonEdge.head());
507
- this.faces.push(face); // join face.getEdge( - 1 ) with the horizon's opposite edge face.getEdge( - 1 ) = face.getEdge( 2 )
508
-
509
- face.getEdge(-1).setTwin(horizonEdge.twin);
510
- return face.getEdge(0); // the half edge whose vertex is the eyeVertex
511
- },
512
- // Adds 'horizon.length' faces to the hull, each face will be linked with the
513
- // horizon opposite face and the face on the left/right
514
- addNewFaces: function (eyeVertex, horizon) {
515
- this.newFaces = [];
516
- var firstSideEdge = null;
517
- var previousSideEdge = null;
518
-
519
- for (let i = 0; i < horizon.length; i++) {
520
- var horizonEdge = horizon[i]; // returns the right side edge
521
-
522
- var sideEdge = this.addAdjoiningFace(eyeVertex, horizonEdge);
523
-
524
- if (firstSideEdge === null) {
525
- firstSideEdge = sideEdge;
469
+ vertex = vertex.next;
470
+ } while (vertex !== null && vertex.face === eyeFace);
471
+
472
+ return eyeVertex;
473
+ }
474
+ } // Computes a chain of half edges in CCW order called the 'horizon'.
475
+ // For an edge to be part of the horizon it must join a face that can see
476
+ // 'eyePoint' and a face that cannot see 'eyePoint'.
477
+
478
+
479
+ computeHorizon(eyePoint, crossEdge, face, horizon) {
480
+ // moves face's vertices to the 'unassigned' vertex list
481
+ this.deleteFaceVertices(face);
482
+ face.mark = Deleted;
483
+ let edge;
484
+
485
+ if (crossEdge === null) {
486
+ edge = crossEdge = face.getEdge(0);
487
+ } else {
488
+ // start from the next edge since 'crossEdge' was already analyzed
489
+ // (actually 'crossEdge.twin' was the edge who called this method recursively)
490
+ edge = crossEdge.next;
491
+ }
492
+
493
+ do {
494
+ const twinEdge = edge.twin;
495
+ const oppositeFace = twinEdge.face;
496
+
497
+ if (oppositeFace.mark === Visible) {
498
+ if (oppositeFace.distanceToPoint(eyePoint) > this.tolerance) {
499
+ // the opposite face can see the vertex, so proceed with next edge
500
+ this.computeHorizon(eyePoint, twinEdge, oppositeFace, horizon);
526
501
  } else {
527
- // joins face.getEdge( 1 ) with previousFace.getEdge( 0 )
528
- sideEdge.next.setTwin(previousSideEdge);
502
+ // the opposite face can't see the vertex, so this edge is part of the horizon
503
+ horizon.push(edge);
529
504
  }
505
+ }
506
+
507
+ edge = edge.next;
508
+ } while (edge !== crossEdge);
509
+
510
+ return this;
511
+ } // Creates a face with the vertices 'eyeVertex.point', 'horizonEdge.tail' and 'horizonEdge.head' in CCW order
512
+
513
+
514
+ addAdjoiningFace(eyeVertex, horizonEdge) {
515
+ // all the half edges are created in ccw order thus the face is always pointing outside the hull
516
+ const face = Face.create(eyeVertex, horizonEdge.tail(), horizonEdge.head());
517
+ this.faces.push(face); // join face.getEdge( - 1 ) with the horizon's opposite edge face.getEdge( - 1 ) = face.getEdge( 2 )
518
+
519
+ face.getEdge(-1).setTwin(horizonEdge.twin);
520
+ return face.getEdge(0); // the half edge whose vertex is the eyeVertex
521
+ } // Adds 'horizon.length' faces to the hull, each face will be linked with the
522
+ // horizon opposite face and the face on the left/right
523
+
530
524
 
531
- this.newFaces.push(sideEdge.face);
532
- previousSideEdge = sideEdge;
533
- } // perform final join of new faces
534
-
535
-
536
- firstSideEdge.next.setTwin(previousSideEdge);
537
- return this;
538
- },
539
- // Adds a vertex to the hull
540
- addVertexToHull: function (eyeVertex) {
541
- var horizon = [];
542
- this.unassigned.clear(); // remove 'eyeVertex' from 'eyeVertex.face' so that it can't be added to the 'unassigned' vertex list
543
-
544
- this.removeVertexFromFace(eyeVertex, eyeVertex.face);
545
- this.computeHorizon(eyeVertex.point, null, eyeVertex.face, horizon);
546
- this.addNewFaces(eyeVertex, horizon); // reassign 'unassigned' vertices to the new faces
547
-
548
- this.resolveUnassignedPoints(this.newFaces);
549
- return this;
550
- },
551
- cleanup: function () {
552
- this.assigned.clear();
553
- this.unassigned.clear();
554
- this.newFaces = [];
555
- return this;
556
- },
557
- compute: function () {
558
- var vertex;
559
- this.computeInitialHull(); // add all available vertices gradually to the hull
560
-
561
- while ((vertex = this.nextVertexToAdd()) !== undefined) {
562
- this.addVertexToHull(vertex);
525
+ addNewFaces(eyeVertex, horizon) {
526
+ this.newFaces = [];
527
+ let firstSideEdge = null;
528
+ let previousSideEdge = null;
529
+
530
+ for (let i = 0; i < horizon.length; i++) {
531
+ const horizonEdge = horizon[i]; // returns the right side edge
532
+
533
+ const sideEdge = this.addAdjoiningFace(eyeVertex, horizonEdge);
534
+
535
+ if (firstSideEdge === null) {
536
+ firstSideEdge = sideEdge;
537
+ } else {
538
+ // joins face.getEdge( 1 ) with previousFace.getEdge( 0 )
539
+ sideEdge.next.setTwin(previousSideEdge);
563
540
  }
564
541
 
565
- this.reindexFaces();
566
- this.cleanup();
567
- return this;
542
+ this.newFaces.push(sideEdge.face);
543
+ previousSideEdge = sideEdge;
544
+ } // perform final join of new faces
545
+
546
+
547
+ firstSideEdge.next.setTwin(previousSideEdge);
548
+ return this;
549
+ } // Adds a vertex to the hull
550
+
551
+
552
+ addVertexToHull(eyeVertex) {
553
+ const horizon = [];
554
+ this.unassigned.clear(); // remove 'eyeVertex' from 'eyeVertex.face' so that it can't be added to the 'unassigned' vertex list
555
+
556
+ this.removeVertexFromFace(eyeVertex, eyeVertex.face);
557
+ this.computeHorizon(eyeVertex.point, null, eyeVertex.face, horizon);
558
+ this.addNewFaces(eyeVertex, horizon); // reassign 'unassigned' vertices to the new faces
559
+
560
+ this.resolveUnassignedPoints(this.newFaces);
561
+ return this;
562
+ }
563
+
564
+ cleanup() {
565
+ this.assigned.clear();
566
+ this.unassigned.clear();
567
+ this.newFaces = [];
568
+ return this;
569
+ }
570
+
571
+ compute() {
572
+ let vertex;
573
+ this.computeInitialHull(); // add all available vertices gradually to the hull
574
+
575
+ while ((vertex = this.nextVertexToAdd()) !== undefined) {
576
+ this.addVertexToHull(vertex);
568
577
  }
569
- }); //
570
578
 
571
- function Face() {
579
+ this.reindexFaces();
580
+ this.cleanup();
581
+ return this;
582
+ }
583
+
584
+ } //
585
+
586
+
587
+ class Face {
588
+ constructor() {
572
589
  this.normal = new Vector3();
573
590
  this.midpoint = new Vector3();
574
591
  this.area = 0;
@@ -580,58 +597,61 @@ var ConvexHull = function () {
580
597
  this.edge = null;
581
598
  }
582
599
 
583
- Object.assign(Face, {
584
- create: function (a, b, c) {
585
- var face = new Face();
586
- var e0 = new HalfEdge(a, face);
587
- var e1 = new HalfEdge(b, face);
588
- var e2 = new HalfEdge(c, face); // join edges
600
+ static create(a, b, c) {
601
+ const face = new Face();
602
+ const e0 = new HalfEdge(a, face);
603
+ const e1 = new HalfEdge(b, face);
604
+ const e2 = new HalfEdge(c, face); // join edges
589
605
 
590
- e0.next = e2.prev = e1;
591
- e1.next = e0.prev = e2;
592
- e2.next = e1.prev = e0; // main half edge reference
606
+ e0.next = e2.prev = e1;
607
+ e1.next = e0.prev = e2;
608
+ e2.next = e1.prev = e0; // main half edge reference
593
609
 
594
- face.edge = e0;
595
- return face.compute();
596
- }
597
- });
598
- Object.assign(Face.prototype, {
599
- getEdge: function (i) {
600
- var edge = this.edge;
601
-
602
- while (i > 0) {
603
- edge = edge.next;
604
- i--;
605
- }
610
+ face.edge = e0;
611
+ return face.compute();
612
+ }
606
613
 
607
- while (i < 0) {
608
- edge = edge.prev;
609
- i++;
610
- }
614
+ getEdge(i) {
615
+ let edge = this.edge;
611
616
 
612
- return edge;
613
- },
614
- compute: function () {
615
- var triangle;
616
- return function compute() {
617
- if (triangle === undefined) triangle = new Triangle();
618
- var a = this.edge.tail();
619
- var b = this.edge.head();
620
- var c = this.edge.next.head();
621
- triangle.set(a.point, b.point, c.point);
622
- triangle.getNormal(this.normal);
623
- triangle.getMidpoint(this.midpoint);
624
- this.area = triangle.getArea();
625
- this.constant = this.normal.dot(this.midpoint);
626
- return this;
627
- };
628
- }(),
629
- distanceToPoint: function (point) {
630
- return this.normal.dot(point) - this.constant;
617
+ while (i > 0) {
618
+ edge = edge.next;
619
+ i--;
631
620
  }
632
- }); // Entity for a Doubly-Connected Edge List (DCEL).
633
621
 
634
- function HalfEdge(vertex, face) {
622
+ while (i < 0) {
623
+ edge = edge.prev;
624
+ i++;
625
+ }
626
+
627
+ return edge;
628
+ }
629
+
630
+ compute() {
631
+ const a = this.edge.tail();
632
+ const b = this.edge.head();
633
+ const c = this.edge.next.head();
634
+
635
+ _triangle.set(a.point, b.point, c.point);
636
+
637
+ _triangle.getNormal(this.normal);
638
+
639
+ _triangle.getMidpoint(this.midpoint);
640
+
641
+ this.area = _triangle.getArea();
642
+ this.constant = this.normal.dot(this.midpoint);
643
+ return this;
644
+ }
645
+
646
+ distanceToPoint(point) {
647
+ return this.normal.dot(point) - this.constant;
648
+ }
649
+
650
+ } // Entity for a Doubly-Connected Edge List (DCEL).
651
+
652
+
653
+ class HalfEdge {
654
+ constructor(vertex, face) {
635
655
  this.vertex = vertex;
636
656
  this.prev = null;
637
657
  this.next = null;
@@ -639,160 +659,176 @@ var ConvexHull = function () {
639
659
  this.face = face;
640
660
  }
641
661
 
642
- Object.assign(HalfEdge.prototype, {
643
- head: function () {
644
- return this.vertex;
645
- },
646
- tail: function () {
647
- return this.prev ? this.prev.vertex : null;
648
- },
649
- length: function () {
650
- var head = this.head();
651
- var tail = this.tail();
652
-
653
- if (tail !== null) {
654
- return tail.point.distanceTo(head.point);
655
- }
662
+ head() {
663
+ return this.vertex;
664
+ }
656
665
 
657
- return -1;
658
- },
659
- lengthSquared: function () {
660
- var head = this.head();
661
- var tail = this.tail();
666
+ tail() {
667
+ return this.prev ? this.prev.vertex : null;
668
+ }
662
669
 
663
- if (tail !== null) {
664
- return tail.point.distanceToSquared(head.point);
665
- }
670
+ length() {
671
+ const head = this.head();
672
+ const tail = this.tail();
666
673
 
667
- return -1;
668
- },
669
- setTwin: function (edge) {
670
- this.twin = edge;
671
- edge.twin = this;
672
- return this;
674
+ if (tail !== null) {
675
+ return tail.point.distanceTo(head.point);
673
676
  }
674
- }); // A vertex as a double linked list node.
675
677
 
676
- function VertexNode(point) {
678
+ return -1;
679
+ }
680
+
681
+ lengthSquared() {
682
+ const head = this.head();
683
+ const tail = this.tail();
684
+
685
+ if (tail !== null) {
686
+ return tail.point.distanceToSquared(head.point);
687
+ }
688
+
689
+ return -1;
690
+ }
691
+
692
+ setTwin(edge) {
693
+ this.twin = edge;
694
+ edge.twin = this;
695
+ return this;
696
+ }
697
+
698
+ } // A vertex as a double linked list node.
699
+
700
+
701
+ class VertexNode {
702
+ constructor(point) {
677
703
  this.point = point;
678
704
  this.prev = null;
679
705
  this.next = null;
680
706
  this.face = null; // the face that is able to see this vertex
681
- } // A double linked list that contains vertex nodes.
707
+ }
708
+
709
+ } // A double linked list that contains vertex nodes.
682
710
 
683
711
 
684
- function VertexList() {
712
+ class VertexList {
713
+ constructor() {
685
714
  this.head = null;
686
715
  this.tail = null;
687
716
  }
688
717
 
689
- Object.assign(VertexList.prototype, {
690
- first: function () {
691
- return this.head;
692
- },
693
- last: function () {
694
- return this.tail;
695
- },
696
- clear: function () {
697
- this.head = this.tail = null;
698
- return this;
699
- },
700
- // Inserts a vertex before the target vertex
701
- insertBefore: function (target, vertex) {
702
- vertex.prev = target.prev;
703
- vertex.next = target;
704
-
705
- if (vertex.prev === null) {
706
- this.head = vertex;
707
- } else {
708
- vertex.prev.next = vertex;
709
- }
718
+ first() {
719
+ return this.head;
720
+ }
710
721
 
711
- target.prev = vertex;
712
- return this;
713
- },
714
- // Inserts a vertex after the target vertex
715
- insertAfter: function (target, vertex) {
716
- vertex.prev = target;
717
- vertex.next = target.next;
722
+ last() {
723
+ return this.tail;
724
+ }
718
725
 
719
- if (vertex.next === null) {
720
- this.tail = vertex;
721
- } else {
722
- vertex.next.prev = vertex;
723
- }
726
+ clear() {
727
+ this.head = this.tail = null;
728
+ return this;
729
+ } // Inserts a vertex before the target vertex
724
730
 
725
- target.next = vertex;
726
- return this;
727
- },
728
- // Appends a vertex to the end of the linked list
729
- append: function (vertex) {
730
- if (this.head === null) {
731
- this.head = vertex;
732
- } else {
733
- this.tail.next = vertex;
734
- }
735
731
 
736
- vertex.prev = this.tail;
737
- vertex.next = null; // the tail has no subsequent vertex
732
+ insertBefore(target, vertex) {
733
+ vertex.prev = target.prev;
734
+ vertex.next = target;
738
735
 
739
- this.tail = vertex;
740
- return this;
741
- },
742
- // Appends a chain of vertices where 'vertex' is the head.
743
- appendChain: function (vertex) {
744
- if (this.head === null) {
745
- this.head = vertex;
746
- } else {
747
- this.tail.next = vertex;
748
- }
736
+ if (vertex.prev === null) {
737
+ this.head = vertex;
738
+ } else {
739
+ vertex.prev.next = vertex;
740
+ }
749
741
 
750
- vertex.prev = this.tail; // ensure that the 'tail' reference points to the last vertex of the chain
742
+ target.prev = vertex;
743
+ return this;
744
+ } // Inserts a vertex after the target vertex
751
745
 
752
- while (vertex.next !== null) {
753
- vertex = vertex.next;
754
- }
755
746
 
747
+ insertAfter(target, vertex) {
748
+ vertex.prev = target;
749
+ vertex.next = target.next;
750
+
751
+ if (vertex.next === null) {
756
752
  this.tail = vertex;
757
- return this;
758
- },
759
- // Removes a vertex from the linked list
760
- remove: function (vertex) {
761
- if (vertex.prev === null) {
762
- this.head = vertex.next;
763
- } else {
764
- vertex.prev.next = vertex.next;
765
- }
753
+ } else {
754
+ vertex.next.prev = vertex;
755
+ }
766
756
 
767
- if (vertex.next === null) {
768
- this.tail = vertex.prev;
769
- } else {
770
- vertex.next.prev = vertex.prev;
771
- }
757
+ target.next = vertex;
758
+ return this;
759
+ } // Appends a vertex to the end of the linked list
772
760
 
773
- return this;
774
- },
775
- // Removes a list of vertices whose 'head' is 'a' and whose 'tail' is b
776
- removeSubList: function (a, b) {
777
- if (a.prev === null) {
778
- this.head = b.next;
779
- } else {
780
- a.prev.next = b.next;
781
- }
782
761
 
783
- if (b.next === null) {
784
- this.tail = a.prev;
785
- } else {
786
- b.next.prev = a.prev;
787
- }
762
+ append(vertex) {
763
+ if (this.head === null) {
764
+ this.head = vertex;
765
+ } else {
766
+ this.tail.next = vertex;
767
+ }
768
+
769
+ vertex.prev = this.tail;
770
+ vertex.next = null; // the tail has no subsequent vertex
771
+
772
+ this.tail = vertex;
773
+ return this;
774
+ } // Appends a chain of vertices where 'vertex' is the head.
788
775
 
789
- return this;
790
- },
791
- isEmpty: function () {
792
- return this.head === null;
776
+
777
+ appendChain(vertex) {
778
+ if (this.head === null) {
779
+ this.head = vertex;
780
+ } else {
781
+ this.tail.next = vertex;
782
+ }
783
+
784
+ vertex.prev = this.tail; // ensure that the 'tail' reference points to the last vertex of the chain
785
+
786
+ while (vertex.next !== null) {
787
+ vertex = vertex.next;
793
788
  }
794
- });
795
- return ConvexHull;
796
- }();
789
+
790
+ this.tail = vertex;
791
+ return this;
792
+ } // Removes a vertex from the linked list
793
+
794
+
795
+ remove(vertex) {
796
+ if (vertex.prev === null) {
797
+ this.head = vertex.next;
798
+ } else {
799
+ vertex.prev.next = vertex.next;
800
+ }
801
+
802
+ if (vertex.next === null) {
803
+ this.tail = vertex.prev;
804
+ } else {
805
+ vertex.next.prev = vertex.prev;
806
+ }
807
+
808
+ return this;
809
+ } // Removes a list of vertices whose 'head' is 'a' and whose 'tail' is b
810
+
811
+
812
+ removeSubList(a, b) {
813
+ if (a.prev === null) {
814
+ this.head = b.next;
815
+ } else {
816
+ a.prev.next = b.next;
817
+ }
818
+
819
+ if (b.next === null) {
820
+ this.tail = a.prev;
821
+ } else {
822
+ b.next.prev = a.prev;
823
+ }
824
+
825
+ return this;
826
+ }
827
+
828
+ isEmpty() {
829
+ return this.head === null;
830
+ }
831
+
832
+ }
797
833
 
798
834
  export { ConvexHull };