@woosh/meep-engine 2.79.0 → 2.80.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.
- package/build/meep.cjs +179 -199
- package/build/meep.min.js +1 -1
- package/build/meep.module.js +179 -199
- 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/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/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/bell_membership_function.js +1 -1
- package/src/core/math/computeIsoscelesTriangleApexAngle.js +2 -2
- package/src/core/math/computeIsoscelesTriangleApexAngle.spec.js +6 -0
- 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/math/statistics/computeStatisticalPartialMedian.js +7 -1
- package/src/core/math/statistics/computeStatisticalPercentile.js +12 -3
- package/src/core/math/statistics/computeStatisticalPercentile.spec.js +11 -0
- package/src/core/math/statistics/computeStatisticalStandardDeviation.js +12 -0
- package/src/core/math/statistics/{computeSampleStandardDeviation.js → computeStatisticalVariance.js} +4 -6
- package/src/core/math/statistics/computeStatisticalVariance.spec.js +10 -0
- package/src/core/model/node-graph/Connection.js +6 -5
- package/src/core/model/node-graph/Connection.spec.js +12 -0
- package/src/core/model/node-graph/DataType.spec.js +19 -0
- package/src/core/model/node-graph/node/NodeDescription.js +12 -10
- package/src/core/model/node-graph/node/NodeDescription.spec.js +52 -1
- package/src/core/model/node-graph/node/NodeInstancePortReference.spec.js +66 -0
- package/src/core/model/node-graph/util/graph_clone_by_node_subset.js +4 -7
- package/src/core/model/node-graph/util/graph_collect_connections_amongst_nodes.js +0 -2
- package/src/core/model/object/objectKeyByValue.js +3 -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/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/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
|
@@ -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
|
+
}
|
|
@@ -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
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* @see "dbellmf" function from Matlab
|
|
4
4
|
* @see https://codecrucks.com/what-is-fuzzy-membership-function-complete-guide/
|
|
5
5
|
* @see https://researchhubs.com/post/maths/fundamentals/bell-shaped-function.html
|
|
6
|
-
* @param {number} v
|
|
6
|
+
* @param {number} v value to be filtered (have membership adjustment applied to)
|
|
7
7
|
* @param {number} a Controls window, larger value = larger window. Function will return exactly 0.5 at this distance away from center
|
|
8
8
|
* @param {number} b Slope, larger slope makes function's tails sharper, meaning that values fall off faster away from center
|
|
9
9
|
* @param {number} c Controls center of the bell curve
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Compute apex angle of an isosceles triangle (triangle with two equal sides)
|
|
3
3
|
* @param {number} side length of the side
|
|
4
4
|
* @param {number} base length of the base
|
|
5
|
-
* @returns {number}
|
|
5
|
+
* @returns {number} Apex angle in radians
|
|
6
6
|
*/
|
|
7
7
|
export function computeIsoscelesTriangleApexAngle(side, base) {
|
|
8
8
|
const b2 = base * base;
|
|
@@ -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
|
+
}
|
|
@@ -10,15 +10,21 @@ import { number_compare_ascending } from "../../primitives/numbers/number_compar
|
|
|
10
10
|
*/
|
|
11
11
|
export function computeStatisticalPartialMedian(values, start, end) {
|
|
12
12
|
assert.isArrayLike(values, 'values');
|
|
13
|
+
assert.isNumber(start, 'start');
|
|
14
|
+
assert.greaterThanOrEqual(start, 0);
|
|
15
|
+
|
|
16
|
+
assert.isNumber(end, 'end');
|
|
13
17
|
assert.lessThan(end, values.length);
|
|
14
18
|
|
|
19
|
+
assert.lessThanOrEqual(start, end);
|
|
20
|
+
|
|
15
21
|
const copy = values.slice();
|
|
16
22
|
|
|
17
23
|
copy.sort(number_compare_ascending);
|
|
18
24
|
|
|
19
25
|
const range = end - start;
|
|
20
26
|
|
|
21
|
-
const position =
|
|
27
|
+
const position = start + (range >> 1);
|
|
22
28
|
|
|
23
29
|
return copy[position];
|
|
24
30
|
}
|
|
@@ -1,14 +1,23 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { assert } from "../../assert.js";
|
|
2
2
|
import { clamp } from "../clamp.js";
|
|
3
|
+
import { computeStatisticalPartialMedian } from "./computeStatisticalPartialMedian.js";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
*
|
|
6
7
|
* @param {number[]} values
|
|
7
|
-
* @param {number} percentile_low
|
|
8
|
-
* @param {number} percentile_high
|
|
8
|
+
* @param {number} percentile_low 0..1
|
|
9
|
+
* @param {number} percentile_high 0..1
|
|
9
10
|
* @returns {number}
|
|
10
11
|
*/
|
|
11
12
|
export function computeStatisticalPercentile(values, percentile_low, percentile_high) {
|
|
13
|
+
assert.isNumber(percentile_low, 'percentile_low');
|
|
14
|
+
assert.notNaN(percentile_low, 'percentile_low');
|
|
15
|
+
|
|
16
|
+
assert.isNumber(percentile_high, 'percentile_high');
|
|
17
|
+
assert.notNaN(percentile_high, 'percentile_high');
|
|
18
|
+
|
|
19
|
+
assert.greaterThanOrEqual(percentile_high, percentile_low);
|
|
20
|
+
|
|
12
21
|
const n = values.length;
|
|
13
22
|
|
|
14
23
|
const start = clamp(Math.floor(n * percentile_low), 0, n - 1);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { computeStatisticalPercentile } from "./computeStatisticalPercentile.js";
|
|
2
|
+
|
|
3
|
+
test("half", () => {
|
|
4
|
+
expect(computeStatisticalPercentile([
|
|
5
|
+
0, 1, 2, 3, 4, 5, 6, 7, 8, 9
|
|
6
|
+
], 0, 0.5)).toBeCloseTo(2);
|
|
7
|
+
|
|
8
|
+
expect(computeStatisticalPercentile([
|
|
9
|
+
0, 1, 2, 3, 4, 5, 6, 7, 8, 9
|
|
10
|
+
], 0.5, 1)).toBeCloseTo(7);
|
|
11
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { computeStatisticalVariance } from "./computeStatisticalVariance.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* @param {number[]} sample
|
|
6
|
+
* @returns {number}
|
|
7
|
+
*/
|
|
8
|
+
export function computeStatisticalStandardDeviation(sample) {
|
|
9
|
+
const variance = computeStatisticalVariance(sample);
|
|
10
|
+
|
|
11
|
+
return Math.sqrt(variance);
|
|
12
|
+
}
|
package/src/core/math/statistics/{computeSampleStandardDeviation.js → computeStatisticalVariance.js}
RENAMED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { computeStatisticalMean } from "./computeStatisticalMean.js";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* Compute statistical variance for a given sample of numbers
|
|
5
5
|
* @param {number[]} sample
|
|
6
6
|
* @returns {number}
|
|
7
7
|
*/
|
|
8
|
-
export function
|
|
8
|
+
export function computeStatisticalVariance(sample) {
|
|
9
9
|
//compute sample mean
|
|
10
10
|
const mean = computeStatisticalMean(sample);
|
|
11
11
|
|
|
@@ -22,7 +22,5 @@ export function computeSampleStandardDeviation(sample) {
|
|
|
22
22
|
SUM += delta2;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
return Math.sqrt(variance);
|
|
28
|
-
}
|
|
25
|
+
return SUM / N;
|
|
26
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {assert} from "../../assert.js";
|
|
2
|
-
import {noop} from "../../function/Functions.js";
|
|
3
|
-
import {objectKeyByValue} from "../object/objectKeyByValue.js";
|
|
4
|
-
import {PortDirection} from "./node/PortDirection.js";
|
|
1
|
+
import { assert } from "../../assert.js";
|
|
2
|
+
import { noop } from "../../function/Functions.js";
|
|
3
|
+
import { objectKeyByValue } from "../object/objectKeyByValue.js";
|
|
4
|
+
import { PortDirection } from "./node/PortDirection.js";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
*
|
|
@@ -102,7 +102,8 @@ export class Connection {
|
|
|
102
102
|
assert.isNumber(id, 'id');
|
|
103
103
|
assert.isInteger(id, 'id');
|
|
104
104
|
|
|
105
|
-
return this.source
|
|
105
|
+
return this.source?.instance?.id === id
|
|
106
|
+
|| this.target?.instance?.id === id;
|
|
106
107
|
}
|
|
107
108
|
|
|
108
109
|
/**
|
|
@@ -19,3 +19,15 @@ test("equality on self", () => {
|
|
|
19
19
|
|
|
20
20
|
expect(thing.equals(thing)).toBe(true);
|
|
21
21
|
});
|
|
22
|
+
|
|
23
|
+
test("isAttachedToNode", () => {
|
|
24
|
+
const connection = new Connection();
|
|
25
|
+
|
|
26
|
+
expect(connection.isAttachedToNode(0)).toBe(false);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test("toString", () => {
|
|
30
|
+
const ut = new Connection();
|
|
31
|
+
|
|
32
|
+
expect(typeof ut.toString()).toBe("string");
|
|
33
|
+
});
|
|
@@ -26,3 +26,22 @@ test('equals', () => {
|
|
|
26
26
|
|
|
27
27
|
expect(c.equals(d)).toBe(false);
|
|
28
28
|
});
|
|
29
|
+
|
|
30
|
+
test("hash", () => {
|
|
31
|
+
|
|
32
|
+
const a = DataType.from(7, 'kitty');
|
|
33
|
+
const b = DataType.from(7, 'kitty');
|
|
34
|
+
|
|
35
|
+
expect(a.hash()).toEqual(a.hash()); //stability
|
|
36
|
+
expect(typeof a.hash()).toBe("number");
|
|
37
|
+
expect(Number.isInteger(a.hash())).toBe(true);
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
expect(a.hash()).toEqual(b.hash());
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test("toString", () => {
|
|
44
|
+
const type = DataType.from(7, 'kitty');
|
|
45
|
+
|
|
46
|
+
expect(typeof type.toString()).toBe("string");
|
|
47
|
+
});
|
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
import {assert} from "../../../assert.js";
|
|
2
|
-
import {isArrayEqual} from "../../../collection/array/isArrayEqual.js";
|
|
1
|
+
import { assert } from "../../../assert.js";
|
|
2
|
+
import { isArrayEqual } from "../../../collection/array/isArrayEqual.js";
|
|
3
3
|
import Signal from "../../../events/signal/Signal.js";
|
|
4
|
-
import {invokeObjectToJSON} from "../../object/invokeObjectToJSON.js";
|
|
5
|
-
import {NodeParameterDataType} from "./parameter/NodeParameterDataType.js";
|
|
6
|
-
import {NodeParameterDescription} from "./parameter/NodeParameterDescription.js";
|
|
7
|
-
import {Port} from "./Port.js";
|
|
8
|
-
import {PortDirection} from "./PortDirection.js";
|
|
4
|
+
import { invokeObjectToJSON } from "../../object/invokeObjectToJSON.js";
|
|
5
|
+
import { NodeParameterDataType } from "./parameter/NodeParameterDataType.js";
|
|
6
|
+
import { NodeParameterDescription } from "./parameter/NodeParameterDescription.js";
|
|
7
|
+
import { Port } from "./Port.js";
|
|
8
|
+
import { PortDirection } from "./PortDirection.js";
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
+
* @template T
|
|
12
13
|
* @private
|
|
13
|
-
* @param {
|
|
14
|
+
* @param {T[]} things
|
|
14
15
|
* @returns {number}
|
|
15
16
|
*/
|
|
16
17
|
function pickNewSetId(things) {
|
|
@@ -181,7 +182,7 @@ export class NodeDescription {
|
|
|
181
182
|
|
|
182
183
|
/**
|
|
183
184
|
*
|
|
184
|
-
* @param {
|
|
185
|
+
* @param {DataType} type
|
|
185
186
|
* @param {String} name
|
|
186
187
|
* @param {PortDirection} direction
|
|
187
188
|
*/
|
|
@@ -338,6 +339,7 @@ export class NodeDescription {
|
|
|
338
339
|
}
|
|
339
340
|
}
|
|
340
341
|
|
|
342
|
+
// port not found
|
|
341
343
|
return undefined;
|
|
342
344
|
}
|
|
343
345
|
|
|
@@ -380,7 +382,7 @@ export class NodeDescription {
|
|
|
380
382
|
* @param name
|
|
381
383
|
* @param {NodeRegistry} registry
|
|
382
384
|
*/
|
|
383
|
-
fromJSON({ports, id, name}, registry) {
|
|
385
|
+
fromJSON({ ports, id, name }, registry) {
|
|
384
386
|
this.id = id;
|
|
385
387
|
this.name = name;
|
|
386
388
|
this.ports = ports.map(p => Port.fromJSON(p, registry));
|