three-stdlib 2.14.3 → 2.15.1

Sign up to get free protection for your applications and to get access to all the features.
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 };