@woosh/meep-engine 2.78.1 → 2.80.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/meep.cjs +235 -233
- package/build/meep.min.js +1 -1
- package/build/meep.module.js +235 -233
- package/package.json +1 -1
- package/src/core/geom/2d/aabb/AABB2.js +6 -18
- package/src/core/geom/3d/SurfacePoint3.spec.js +1 -1
- package/src/core/geom/3d/{matrix → mat4}/m4_multiply.spec.js +3 -4
- package/src/core/geom/3d/{matrix → mat4}/m4_multiply_alphatensor.spec.js +3 -3
- package/src/core/geom/3d/morton/v3_morton_encode_transformed.spec.js +1 -1
- package/src/core/geom/3d/sphere/sphere_radius_sqr_from_v3_array_transformed.spec.js +1 -1
- package/src/core/geom/Quaternion.js +1 -1
- package/src/core/geom/Vector3.js +2 -2
- package/src/core/geom/Vector3.spec.js +2 -2
- package/src/core/geom/packing/max-rect/{MaxRectangles.js → MaxRectanglesPacker.js} +25 -32
- package/src/core/geom/packing/max-rect/MaxRectanglesPacker.spec.js +60 -0
- package/src/core/geom/packing/max-rect/packMaxRectangles.js +19 -0
- package/src/core/geom/vec3/v3_angle_between.js +15 -4
- package/src/core/geom/vec3/{v3_computeOffsetVector.js → v3_displace_in_direction.js} +11 -2
- package/src/core/graph/cluster_mesh_metis.js +3 -3
- package/src/core/graph/metis/metis.js +16 -1
- package/src/core/graph/metis/metis_options.js +32 -29
- package/src/core/math/interval/overlap1D.js +7 -0
- package/src/core/math/noise/create_simplex_noise_2d.js +4 -0
- package/src/core/math/spline/computeCatmullRomSplineUniformDistance.js +3 -3
- package/src/core/math/spline/v3_computeCatmullRomSplineUniformDistance.js +42 -0
- package/src/core/model/node-graph/node/NodeDescription.js +12 -10
- package/src/core/model/node-graph/node/NodeDescription.spec.js +14 -1
- package/src/core/model/object/objectKeyByValue.js +3 -2
- package/src/engine/ecs/ik/OneBoneSurfaceAlignmentSolver.js +2 -2
- package/src/engine/ecs/ik/TwoBoneInverseKinematicsSolver.js +2 -2
- package/src/engine/ecs/renderable/Renderable.js +1 -1
- package/src/engine/ecs/terrain/ecs/TerrainSystem.js +1 -1
- package/src/engine/ecs/terrain/tiles/TerrainTile.spec.js +2 -2
- package/src/engine/ecs/transform/Transform.js +3 -3
- package/src/engine/ecs/transform/Transform.spec.js +3 -3
- package/src/engine/ecs/transform-attachment/TransformAttachment.js +2 -1
- package/src/engine/ecs/transform-attachment/TransformAttachmentSystem.js +45 -33
- package/src/engine/graphics/ecs/path/entity/testEntityPath.js +16 -10
- package/src/engine/graphics/material/optimization/MaterialOptimizationContext.js +1 -1
- package/src/engine/graphics/texture/atlas/TextureAtlas.js +1 -1
- package/src/engine/graphics/texture/atlas/gpu/WebGLTextureAtlas.js +3 -3
- package/src/engine/graphics/three/expand_aabb_by_transformed_three_object.js +1 -1
- package/src/engine/graphics/three/expand_aabb_by_transformed_three_object.spec.js +2 -2
- package/src/engine/navigation/ecs/components/Path.js +5 -12
- package/src/engine/simulation/Ticker.js +40 -61
- package/src/core/geom/LineSegment.js +0 -207
- package/src/core/primitives/strings/prefixTree/PrefixTree.js +0 -225
- package/src/core/primitives/strings/prefixTree/PrefixTree.spec.js +0 -39
- package/src/core/primitives/strings/prefixTree/PrefixTreeLeaf.js +0 -25
- package/src/core/primitives/strings/prefixTree/PrefixTreeNode.js +0 -16
- /package/src/core/geom/3d/{matrix → mat4}/MATRIX_4_IDENTITY.js +0 -0
- /package/src/core/geom/3d/{matrix → mat4}/MATRIX_4_IDENTITY.spec.js +0 -0
- /package/src/core/geom/3d/{matrix → mat4}/allocate_transform_m4.js +0 -0
- /package/src/core/geom/3d/{matrix → mat4}/m4_make_translation.js +0 -0
- /package/src/core/geom/3d/{matrix → mat4}/m4_multiply.js +0 -0
- /package/src/core/geom/3d/{matrix → mat4}/m4_multiply_alphatensor.js +0 -0
package/package.json
CHANGED
|
@@ -9,11 +9,11 @@ import { clamp } from "../../../math/clamp.js";
|
|
|
9
9
|
import { max2 } from "../../../math/max2.js";
|
|
10
10
|
import { min2 } from "../../../math/min2.js";
|
|
11
11
|
import Vector2 from "../../Vector2.js";
|
|
12
|
-
import { aabb2_compute_overlap } from "./aabb2_compute_overlap.js";
|
|
13
|
-
import { aabb2_overlap_exists } from "./aabb2_overlap_exists.js";
|
|
14
12
|
import {
|
|
15
13
|
line_segment_compute_line_segment_intersection_2d
|
|
16
14
|
} from "../line/line_segment_compute_line_segment_intersection_2d.js";
|
|
15
|
+
import { aabb2_compute_overlap } from "./aabb2_compute_overlap.js";
|
|
16
|
+
import { aabb2_overlap_exists } from "./aabb2_overlap_exists.js";
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
*
|
|
@@ -146,7 +146,7 @@ class AABB2 {
|
|
|
146
146
|
/**
|
|
147
147
|
*
|
|
148
148
|
* @param {AABB2} other
|
|
149
|
-
* @returns {
|
|
149
|
+
* @returns {boolean}
|
|
150
150
|
*/
|
|
151
151
|
overlapExists(other) {
|
|
152
152
|
const ax0 = this.x0;
|
|
@@ -173,6 +173,7 @@ class AABB2 {
|
|
|
173
173
|
_expandToFit(x0, y0, x1, y1) {
|
|
174
174
|
this.x0 = min2(this.x0, x0);
|
|
175
175
|
this.y0 = min2(this.y0, y0);
|
|
176
|
+
|
|
176
177
|
this.x1 = max2(this.x1, x1);
|
|
177
178
|
this.y1 = max2(this.y1, y1);
|
|
178
179
|
}
|
|
@@ -183,21 +184,8 @@ class AABB2 {
|
|
|
183
184
|
* @param {number} y
|
|
184
185
|
*/
|
|
185
186
|
_expandToFitPoint(x, y) {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
if (x > this.x1) {
|
|
191
|
-
this.x1 = x;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
if (y < this.y0) {
|
|
195
|
-
this.y0 = y;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
if (y > this.y1) {
|
|
199
|
-
this.y1 = y;
|
|
200
|
-
}
|
|
187
|
+
// shortcut, use a 0-size box
|
|
188
|
+
this._expandToFit(x, y, x, y);
|
|
201
189
|
}
|
|
202
190
|
|
|
203
191
|
/**
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {m4_multiply} from "./m4_multiply.js";
|
|
3
|
-
import {
|
|
4
|
-
import {number_pretty_print} from "../../../primitives/numbers/number_pretty_print.js";
|
|
1
|
+
import { number_pretty_print } from "../../../primitives/numbers/number_pretty_print.js";
|
|
2
|
+
import { m4_multiply } from "./m4_multiply.js";
|
|
3
|
+
import { MATRIX_4_IDENTITY } from "./MATRIX_4_IDENTITY.js";
|
|
5
4
|
|
|
6
5
|
test("identity multiplication", () => {
|
|
7
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { number_pretty_print } from "../../../primitives/numbers/number_pretty_print.js";
|
|
2
|
+
import { m4_multiply_alphatensor } from "./m4_multiply_alphatensor.js";
|
|
3
|
+
import { MATRIX_4_IDENTITY } from "./MATRIX_4_IDENTITY.js";
|
|
4
4
|
|
|
5
5
|
test("identity multiplication", () => {
|
|
6
6
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { MATRIX_4_IDENTITY } from "../mat4/MATRIX_4_IDENTITY.js";
|
|
1
2
|
import { v3_morton_encode_transformed } from "./v3_morton_encode_transformed.js";
|
|
2
|
-
import { MATRIX_4_IDENTITY } from "../matrix/MATRIX_4_IDENTITY.js";
|
|
3
3
|
|
|
4
4
|
test("valid number with identity transform", () => {
|
|
5
5
|
const v = v3_morton_encode_transformed(0, 0, 0, MATRIX_4_IDENTITY);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { MATRIX_4_IDENTITY } from "../mat4/MATRIX_4_IDENTITY.js";
|
|
1
2
|
import { sphere_radius_sqr_from_v3_array_transformed } from "./sphere_radius_sqr_from_v3_array_transformed.js";
|
|
2
|
-
import { MATRIX_4_IDENTITY } from "../matrix/MATRIX_4_IDENTITY.js";
|
|
3
3
|
|
|
4
4
|
test("base case", () => {
|
|
5
5
|
expect(sphere_radius_sqr_from_v3_array_transformed([0, 0, 0], 3, MATRIX_4_IDENTITY)).toBe(0);
|
|
@@ -1546,7 +1546,7 @@ class Quaternion {
|
|
|
1546
1546
|
* @param {Quaternion} result
|
|
1547
1547
|
* @param {Quaternion} from
|
|
1548
1548
|
* @param {Quaternion} to
|
|
1549
|
-
* @param {number} max_delta
|
|
1549
|
+
* @param {number} max_delta in radians
|
|
1550
1550
|
*/
|
|
1551
1551
|
static rotateTowards(result, from, to, max_delta) {
|
|
1552
1552
|
assert.isNumber(max_delta, 'max_delta');
|
package/src/core/geom/Vector3.js
CHANGED
|
@@ -37,7 +37,7 @@ class Vector3 {
|
|
|
37
37
|
|
|
38
38
|
/**
|
|
39
39
|
*
|
|
40
|
-
* @param {number[]} array
|
|
40
|
+
* @param {number[]|Float32Array} array
|
|
41
41
|
* @param {number} offset
|
|
42
42
|
*/
|
|
43
43
|
readFromArray(array, offset = 0) {
|
|
@@ -50,7 +50,7 @@ class Vector3 {
|
|
|
50
50
|
|
|
51
51
|
/**
|
|
52
52
|
*
|
|
53
|
-
* @param {number[]} array
|
|
53
|
+
* @param {number[]|Float32Array} array
|
|
54
54
|
* @param {number} offset
|
|
55
55
|
*/
|
|
56
56
|
writeToArray(array, offset = 0) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {MATRIX_4_IDENTITY} from "./3d/
|
|
2
|
-
import {v3_slerp} from "./vec3/v3_slerp.js";
|
|
1
|
+
import { MATRIX_4_IDENTITY } from "./3d/mat4/MATRIX_4_IDENTITY.js";
|
|
2
|
+
import { v3_slerp } from "./vec3/v3_slerp.js";
|
|
3
3
|
import Vector3 from "./Vector3.js";
|
|
4
4
|
|
|
5
5
|
test('slerp', () => {
|
|
@@ -1,15 +1,19 @@
|
|
|
1
|
-
import BinaryHeap from "../../../collection/heap/FastBinaryHeap.js";
|
|
2
1
|
import { assert } from "../../../assert.js";
|
|
2
|
+
import BinaryHeap from "../../../collection/heap/FastBinaryHeap.js";
|
|
3
|
+
import AABB2 from "../../2d/aabb/AABB2.js";
|
|
3
4
|
import { QuadTreeDatum } from "../../2d/quad-tree/QuadTreeDatum.js";
|
|
4
5
|
import { QuadTreeNode } from "../../2d/quad-tree/QuadTreeNode.js";
|
|
5
|
-
import AABB2 from "../../2d/aabb/AABB2.js";
|
|
6
6
|
import Vector2 from "../../Vector2.js";
|
|
7
|
-
import { removeRedundantBoxes } from "./removeRedundantBoxes.js";
|
|
8
7
|
import { costByRemainingArea } from "./cost/costByRemainingArea.js";
|
|
9
8
|
import { findBestContainer } from "./findBestContainer.js";
|
|
10
9
|
import { packOneBox } from "./packOneBox.js";
|
|
10
|
+
import { removeRedundantBoxes } from "./removeRedundantBoxes.js";
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Packs rectangles into a finite area, packer is incremental and supports both insertions and removals of rectangles
|
|
14
|
+
* Implementation of "max rectangles" packing algorithm.
|
|
15
|
+
* Useful for packing texture atlases
|
|
16
|
+
*/
|
|
13
17
|
export class MaxRectanglesPacker {
|
|
14
18
|
/**
|
|
15
19
|
*
|
|
@@ -24,6 +28,8 @@ export class MaxRectanglesPacker {
|
|
|
24
28
|
* @type {QuadTreeNode}
|
|
25
29
|
*/
|
|
26
30
|
this.free = new QuadTreeNode(0, 0, width, height);
|
|
31
|
+
|
|
32
|
+
// initialize a with a free space occupying the entire area
|
|
27
33
|
this.free.add(null, 0, 0, width, height);
|
|
28
34
|
|
|
29
35
|
/**
|
|
@@ -98,7 +104,8 @@ export class MaxRectanglesPacker {
|
|
|
98
104
|
}
|
|
99
105
|
|
|
100
106
|
/**
|
|
101
|
-
*
|
|
107
|
+
* Tests whether a rectangle of given dimensions can be packed into remaining space
|
|
108
|
+
* Essentially, if this method succeeds - insertion will succeed as well, and if it fails - insertion will fail too
|
|
102
109
|
* @param {number} w
|
|
103
110
|
* @param {number} h
|
|
104
111
|
* @return {boolean}
|
|
@@ -184,9 +191,10 @@ export class MaxRectanglesPacker {
|
|
|
184
191
|
}
|
|
185
192
|
|
|
186
193
|
/**
|
|
187
|
-
* Resize the packer canvas
|
|
194
|
+
* Resize the packer canvas, may trigger repacking if new dimensions are smaller than the existing ones
|
|
188
195
|
* @param {number} width
|
|
189
196
|
* @param {number} height
|
|
197
|
+
* @returns {boolean} false if packing fails after resize, true otherwise
|
|
190
198
|
*/
|
|
191
199
|
resize(width, height) {
|
|
192
200
|
|
|
@@ -199,18 +207,20 @@ export class MaxRectanglesPacker {
|
|
|
199
207
|
|
|
200
208
|
if (oldWidth > width || oldHeight > height) {
|
|
201
209
|
//canvas was made smaller in at least one dimension, re-pack is required
|
|
202
|
-
this.repack();
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
210
|
+
return this.repack();
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
//canvas was enlarged, we can simply add new free areas
|
|
214
|
+
if (width > oldWidth) {
|
|
215
|
+
this.free.insertDatum(new QuadTreeDatum(oldWidth, 0, width, height));
|
|
216
|
+
}
|
|
217
|
+
if (height > oldHeight) {
|
|
218
|
+
this.free.insertDatum(new QuadTreeDatum(0, oldHeight, width, height))
|
|
211
219
|
}
|
|
212
220
|
|
|
213
221
|
// assert.ok(this.validate());
|
|
222
|
+
|
|
223
|
+
return true;
|
|
214
224
|
}
|
|
215
225
|
|
|
216
226
|
validate() {
|
|
@@ -239,20 +249,3 @@ export class MaxRectanglesPacker {
|
|
|
239
249
|
}
|
|
240
250
|
|
|
241
251
|
|
|
242
|
-
/**
|
|
243
|
-
* Packs {@link AABB2} boxes into defined bounds
|
|
244
|
-
*
|
|
245
|
-
* Based on paper "A Thousand Ways to Pack the Bin - A Practical Approach to Two-Dimensional Rectangle Bin Packing" 2010 Jukka Jylänki
|
|
246
|
-
* Method presented called Maximal Rectangles
|
|
247
|
-
*
|
|
248
|
-
* @param {number} width
|
|
249
|
-
* @param {number} height
|
|
250
|
-
* @param {AABB2[]} boxes
|
|
251
|
-
* @returns {boolean} true if packing was successful, false otherwise
|
|
252
|
-
*/
|
|
253
|
-
export function packMaxRectangles(width, height, boxes) {
|
|
254
|
-
|
|
255
|
-
const packer = new MaxRectanglesPacker(width, height);
|
|
256
|
-
|
|
257
|
-
return packer.addMany(boxes);
|
|
258
|
-
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import AABB2 from "../../2d/aabb/AABB2.js";
|
|
2
|
+
import { MaxRectanglesPacker } from "./MaxRectanglesPacker.js";
|
|
3
|
+
|
|
4
|
+
test("constructor does not throw", () => {
|
|
5
|
+
new MaxRectanglesPacker(1, 1)
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
test("pack 1 box that takes up entire available area", () => {
|
|
9
|
+
const packer = new MaxRectanglesPacker(1, 1);
|
|
10
|
+
|
|
11
|
+
const box = new AABB2(3, 5, 4, 6);
|
|
12
|
+
|
|
13
|
+
expect(packer.add(box)).toBe(true);
|
|
14
|
+
|
|
15
|
+
expect(box.x0).toBe(0);
|
|
16
|
+
expect(box.y0).toBe(0);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test("packing a box larger than available area", () => {
|
|
20
|
+
|
|
21
|
+
const packer = new MaxRectanglesPacker(1, 1);
|
|
22
|
+
|
|
23
|
+
const box = new AABB2(0, 0, 2, 1);
|
|
24
|
+
|
|
25
|
+
expect(packer.add(box)).toBe(false);
|
|
26
|
+
|
|
27
|
+
box.set(0, 0, 1, 2);
|
|
28
|
+
|
|
29
|
+
expect(packer.add(box)).toBe(false);
|
|
30
|
+
|
|
31
|
+
box.set(0, 0, 2, 2)
|
|
32
|
+
|
|
33
|
+
expect(packer.add(box)).toBe(false);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test("pack 4 squares that fit exactly", () => {
|
|
37
|
+
|
|
38
|
+
const packer = new MaxRectanglesPacker(2, 2);
|
|
39
|
+
|
|
40
|
+
const boxes = [
|
|
41
|
+
new AABB2(0, 0, 1, 1),
|
|
42
|
+
new AABB2(0, 0, 1, 1),
|
|
43
|
+
new AABB2(0, 0, 1, 1),
|
|
44
|
+
new AABB2(0, 0, 1, 1)
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
for (let i = 0; i < boxes.length; i++) {
|
|
48
|
+
expect(packer.add(boxes[i])).toBe(true);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// validate overlap constraints
|
|
52
|
+
for (let i = 0; i < boxes.length; i++) {
|
|
53
|
+
const box_0 = boxes[i];
|
|
54
|
+
for (let j = i + 1; j < boxes.length; j++) {
|
|
55
|
+
const box_1 = boxes[j];
|
|
56
|
+
|
|
57
|
+
expect(box_0.overlapExists(box_1)).toBe(false);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { MaxRectanglesPacker } from "./MaxRectanglesPacker.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Packs {@link AABB2} boxes into defined bounds
|
|
5
|
+
*
|
|
6
|
+
* Based on paper "A Thousand Ways to Pack the Bin - A Practical Approach to Two-Dimensional Rectangle Bin Packing" 2010 Jukka Jylänki
|
|
7
|
+
* Method presented called Maximal Rectangles
|
|
8
|
+
*
|
|
9
|
+
* @param {number} width
|
|
10
|
+
* @param {number} height
|
|
11
|
+
* @param {AABB2[]} boxes
|
|
12
|
+
* @returns {boolean} true if packing was successful, false otherwise
|
|
13
|
+
*/
|
|
14
|
+
export function packMaxRectangles(width, height, boxes) {
|
|
15
|
+
|
|
16
|
+
const packer = new MaxRectanglesPacker(width, height);
|
|
17
|
+
|
|
18
|
+
return packer.addMany(boxes);
|
|
19
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { clamp } from "../../math/clamp.js";
|
|
1
2
|
import { v3_dot } from "./v3_dot.js";
|
|
2
3
|
import { v3_length } from "./v3_length.js";
|
|
3
|
-
import { clamp } from "../../math/clamp.js";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
*
|
|
@@ -12,10 +12,15 @@ import { clamp } from "../../math/clamp.js";
|
|
|
12
12
|
* @param {number} z1
|
|
13
13
|
* @returns {number}
|
|
14
14
|
*/
|
|
15
|
-
export function v3_angle_between(
|
|
15
|
+
export function v3_angle_between(
|
|
16
|
+
x0, y0, z0,
|
|
17
|
+
x1, y1, z1
|
|
18
|
+
) {
|
|
19
|
+
|
|
16
20
|
const theta = v3_angle_cos_between(x0, y0, z0, x1, y1, z1);
|
|
17
21
|
|
|
18
22
|
return Math.acos(theta);
|
|
23
|
+
|
|
19
24
|
}
|
|
20
25
|
|
|
21
26
|
/**
|
|
@@ -26,9 +31,13 @@ export function v3_angle_between(x0, y0, z0, x1, y1, z1) {
|
|
|
26
31
|
* @param {number} x1
|
|
27
32
|
* @param {number} y1
|
|
28
33
|
* @param {number} z1
|
|
29
|
-
* @returns {number}
|
|
34
|
+
* @returns {number} value between -1 and 1, cosine of the angle between vectors
|
|
30
35
|
*/
|
|
31
|
-
export function v3_angle_cos_between(
|
|
36
|
+
export function v3_angle_cos_between(
|
|
37
|
+
x0, y0, z0,
|
|
38
|
+
x1, y1, z1
|
|
39
|
+
) {
|
|
40
|
+
|
|
32
41
|
const d = v3_dot(x0, y0, z0, x1, y1, z1);
|
|
33
42
|
|
|
34
43
|
const magnitude_0 = v3_length(x0, y0, z0);
|
|
@@ -38,10 +47,12 @@ export function v3_angle_cos_between(x0, y0, z0, x1, y1, z1){
|
|
|
38
47
|
|
|
39
48
|
if (l === 0) {
|
|
40
49
|
// collective magnitude is 0, provide arbitrary angle
|
|
50
|
+
// avoid division by 0
|
|
41
51
|
return 0;
|
|
42
52
|
}
|
|
43
53
|
|
|
44
54
|
return clamp(d / l, -1, 1);
|
|
55
|
+
|
|
45
56
|
}
|
|
46
57
|
|
|
47
58
|
/**
|
|
@@ -8,8 +8,9 @@
|
|
|
8
8
|
* @param {number} directionX
|
|
9
9
|
* @param {number} directionY
|
|
10
10
|
* @param {number} directionZ
|
|
11
|
+
* @returns {boolean} true if displaced successfully, false if direction had 0 magnitude
|
|
11
12
|
*/
|
|
12
|
-
export function
|
|
13
|
+
export function v3_displace_in_direction(
|
|
13
14
|
result,
|
|
14
15
|
distance,
|
|
15
16
|
sourceX, sourceY, sourceZ,
|
|
@@ -17,13 +18,19 @@ export function v3_computeOffsetVector(
|
|
|
17
18
|
) {
|
|
18
19
|
if (distance === 0) {
|
|
19
20
|
result.set(sourceX, sourceY, sourceZ);
|
|
20
|
-
return;
|
|
21
|
+
return true;
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
//scale direction to have length equal to distance
|
|
24
25
|
|
|
25
26
|
const directionLength = Math.sqrt(directionX * directionX + directionY * directionY + directionZ * directionZ);
|
|
26
27
|
|
|
28
|
+
if(directionLength === 0){
|
|
29
|
+
// direction vector is zero length, avoid division by zero, clamp to source instead
|
|
30
|
+
result.set(sourceX, sourceY, sourceZ);
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
|
|
27
34
|
const m = distance / directionLength;
|
|
28
35
|
|
|
29
36
|
const x = sourceX + directionX * m;
|
|
@@ -31,4 +38,6 @@ export function v3_computeOffsetVector(
|
|
|
31
38
|
const z = sourceZ + directionZ * m;
|
|
32
39
|
|
|
33
40
|
result.set(x, y, z);
|
|
41
|
+
|
|
42
|
+
return true;
|
|
34
43
|
}
|
|
@@ -12,12 +12,12 @@ const MAX_STEPS = 50;
|
|
|
12
12
|
* @param {Uint32Array} result
|
|
13
13
|
* @param {number} node_count
|
|
14
14
|
* @param {Uint32Array} edge_addresses
|
|
15
|
-
* @param {Uint32Array}
|
|
15
|
+
* @param {Uint32Array} adjacency_uint32
|
|
16
16
|
* @param {Uint32Array} edge_weights_uint32
|
|
17
17
|
* @param {number} patch_size
|
|
18
18
|
* @returns {Promise<number>}
|
|
19
19
|
*/
|
|
20
|
-
export async function metis_cluster_bs(result, node_count, edge_addresses,
|
|
20
|
+
export async function metis_cluster_bs(result, node_count, edge_addresses, adjacency_uint32, edge_weights_uint32, patch_size) {
|
|
21
21
|
|
|
22
22
|
const metis = Metis.INSTANCE;
|
|
23
23
|
|
|
@@ -46,7 +46,7 @@ export async function metis_cluster_bs(result, node_count, edge_addresses, adjec
|
|
|
46
46
|
node_count,
|
|
47
47
|
partition_count,
|
|
48
48
|
edge_addresses,
|
|
49
|
-
|
|
49
|
+
adjacency_uint32,
|
|
50
50
|
edge_weights_uint32,
|
|
51
51
|
metisOptions
|
|
52
52
|
);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import WorkerBuilder from "../../process/worker/WorkerBuilder.js";
|
|
2
1
|
import { OnDemandWorkerManager } from "../../process/worker/OnDemandWorkerManager.js";
|
|
2
|
+
import WorkerBuilder from "../../process/worker/WorkerBuilder.js";
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
export class Metis {
|
|
@@ -13,6 +13,16 @@ export class Metis {
|
|
|
13
13
|
this.service = manager;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
*
|
|
18
|
+
* @param {number} n_vertices
|
|
19
|
+
* @param {number} n_parts
|
|
20
|
+
* @param {Uint32Array} edge_addresses
|
|
21
|
+
* @param {Uint32Array} adjacency
|
|
22
|
+
* @param {Uint32Array} edge_weights
|
|
23
|
+
* @param {metis_options} options
|
|
24
|
+
* @returns {Promise<T>}
|
|
25
|
+
*/
|
|
16
26
|
partition(
|
|
17
27
|
n_vertices,
|
|
18
28
|
n_parts,
|
|
@@ -32,4 +42,9 @@ export class Metis {
|
|
|
32
42
|
}
|
|
33
43
|
}
|
|
34
44
|
|
|
45
|
+
/**
|
|
46
|
+
* Singleton instance
|
|
47
|
+
* @readonly
|
|
48
|
+
* @type {Metis}
|
|
49
|
+
*/
|
|
35
50
|
Metis.INSTANCE = new Metis();
|
|
@@ -1,33 +1,36 @@
|
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* See metis.h for more details
|
|
4
|
+
* -1 is the used to signal absence of value, in which case a default will be used
|
|
5
|
+
*/
|
|
1
6
|
export class metis_options {
|
|
7
|
+
ptype = -1;
|
|
8
|
+
objtype = -1;
|
|
2
9
|
/**
|
|
3
|
-
*
|
|
4
|
-
* -
|
|
10
|
+
* Coarsening scheme
|
|
11
|
+
* 0 - METIS_CTYPE_RM
|
|
12
|
+
* 1 - METIS_CTYPE_SHEM
|
|
13
|
+
* @type {number}
|
|
5
14
|
*/
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
this.pfactor = -1;
|
|
28
|
-
this.nseps = -1;
|
|
29
|
-
this.ufactor = -1;
|
|
30
|
-
this.numbering = -1;
|
|
31
|
-
|
|
32
|
-
}
|
|
15
|
+
ctype = -1;
|
|
16
|
+
iptype = -1;
|
|
17
|
+
rtype = -1;
|
|
18
|
+
dbglvl = -1;
|
|
19
|
+
niter = -1;
|
|
20
|
+
ncuts = -1;
|
|
21
|
+
/**
|
|
22
|
+
* Random seed
|
|
23
|
+
* Integer
|
|
24
|
+
* @type {number}
|
|
25
|
+
*/
|
|
26
|
+
seed = -1;
|
|
27
|
+
no2hop = -1;
|
|
28
|
+
minconn = -1;
|
|
29
|
+
contig = -1;
|
|
30
|
+
ccorder = -1;
|
|
31
|
+
pfactor = -1;
|
|
32
|
+
nseps = -1;
|
|
33
|
+
ufactor = -1;
|
|
34
|
+
numbering = -1;
|
|
35
|
+
compress = - 1;
|
|
33
36
|
}
|
|
@@ -12,8 +12,15 @@ import { assert } from "../../assert.js";
|
|
|
12
12
|
export function overlap1D(a0, a1, b0, b1) {
|
|
13
13
|
assert.isNumber(a0, "a0");
|
|
14
14
|
assert.isNumber(a1, "a1");
|
|
15
|
+
|
|
15
16
|
assert.isNumber(b0, "b0");
|
|
16
17
|
assert.isNumber(b1, "b1");
|
|
17
18
|
|
|
19
|
+
assert.notNaN(a0, 'a0');
|
|
20
|
+
assert.notNaN(a1, 'a1');
|
|
21
|
+
|
|
22
|
+
assert.notNaN(b0, 'b0');
|
|
23
|
+
assert.notNaN(b1, 'b1');
|
|
24
|
+
|
|
18
25
|
return a1 > b0 && b1 > a0;
|
|
19
26
|
}
|
|
@@ -73,6 +73,10 @@ export function create_simplex_noise_2d(random = Math.random) {
|
|
|
73
73
|
permMod12[i] = (perm[i] % 12) * 2;
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
+
/**
|
|
77
|
+
* @param {number} x
|
|
78
|
+
* @param {number} y
|
|
79
|
+
*/
|
|
76
80
|
return function noise2D(x, y) {
|
|
77
81
|
// if(!isFinite(x) || !isFinite(y)) return 0;
|
|
78
82
|
let n0 = 0; // Noise contributions from the three corners
|
|
@@ -30,9 +30,9 @@ const p2 = [];
|
|
|
30
30
|
const p3 = [];
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
|
-
* Takes distances between points into account and samples at equal intervals along linear distance along the point sequence. Computationally slightly more expensive, but produces very predictable and
|
|
34
|
-
* @param {number[]} result
|
|
35
|
-
* @param {number[]} input
|
|
33
|
+
* Takes distances between points into account and samples at equal intervals along linear distance along the point sequence. Computationally slightly more expensive, but produces very predictable and stable results
|
|
34
|
+
* @param {number[]|Float32Array} result
|
|
35
|
+
* @param {number[]|Float32Array} input
|
|
36
36
|
* @param {number} input_length number of points in the input
|
|
37
37
|
* @param {number} dimensions number of dimensions per vertex
|
|
38
38
|
* @param {number} sample_count number of discrete points to be generated
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import Vector3 from "../../geom/Vector3.js";
|
|
2
|
+
import { computeCatmullRomSplineUniformDistance } from "./computeCatmullRomSplineUniformDistance.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
* @param {Vector3[]} inputs
|
|
7
|
+
* @param {number} samples
|
|
8
|
+
* @returns {Vector3[]}
|
|
9
|
+
*/
|
|
10
|
+
export function v3_computeCatmullRomSplineUniformDistance(
|
|
11
|
+
inputs, samples
|
|
12
|
+
) {
|
|
13
|
+
|
|
14
|
+
const input_count = inputs.length;
|
|
15
|
+
|
|
16
|
+
const inputs_array = new Float32Array(3 * input_count);
|
|
17
|
+
const result_array = new Float32Array(3 * samples);
|
|
18
|
+
|
|
19
|
+
for (let i = 0; i < input_count; i++) {
|
|
20
|
+
const v3 = inputs[i];
|
|
21
|
+
|
|
22
|
+
v3.writeToArray(inputs_array, i * 3);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
computeCatmullRomSplineUniformDistance(
|
|
26
|
+
result_array, inputs_array, input_count, 3, samples
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
// convert numeric result to array of Vector3 objects
|
|
30
|
+
const result = [];
|
|
31
|
+
|
|
32
|
+
for (let i = 0; i < samples; i++) {
|
|
33
|
+
const v3 = new Vector3();
|
|
34
|
+
|
|
35
|
+
v3.readFromArray(result_array, i * 3);
|
|
36
|
+
|
|
37
|
+
result[i] = v3;
|
|
38
|
+
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return result;
|
|
42
|
+
}
|