@woosh/meep-engine 2.80.0 → 2.81.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 +1 -1
- package/build/meep.min.js +1 -1
- package/build/meep.module.js +1 -1
- package/package.json +2 -2
- 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/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.spec.js +38 -0
- 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/build/meep.module.js
CHANGED
|
@@ -86056,7 +86056,7 @@ function computeStatisticalPartialMedian(values, start, end) {
|
|
|
86056
86056
|
|
|
86057
86057
|
const range = end - start;
|
|
86058
86058
|
|
|
86059
|
-
const position =
|
|
86059
|
+
const position = start + (range >> 1);
|
|
86060
86060
|
|
|
86061
86061
|
return copy[position];
|
|
86062
86062
|
}
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"description": "Fully featured ECS game engine written in JavaScript",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"author": "Alexander Goldring",
|
|
8
|
-
"version": "2.
|
|
8
|
+
"version": "2.81.0",
|
|
9
9
|
"main": "build/meep.module.js",
|
|
10
10
|
"module": "build/meep.module.js",
|
|
11
11
|
"exports": {
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"pako": "2.0.3"
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|
|
46
|
-
"three": ">=0.135.0
|
|
46
|
+
"three": ">=0.135.0"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@babel/core": "7.22.9",
|
|
@@ -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;
|
|
@@ -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
|
+
});
|
|
@@ -24,4 +24,42 @@ test("get port by ID", () => {
|
|
|
24
24
|
|
|
25
25
|
expect(port).not.toBeNull();
|
|
26
26
|
expect(port.name).toBe("a");
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test("get ports by name", () => {
|
|
30
|
+
|
|
31
|
+
const node = new NodeDescription();
|
|
32
|
+
|
|
33
|
+
expect(node.getPortsByName("a")).toEqual([]);
|
|
34
|
+
|
|
35
|
+
node.createPort(DUMMY_TYPE, "a", PortDirection.In);
|
|
36
|
+
|
|
37
|
+
const result_0 = node.getPortsByName("a");
|
|
38
|
+
expect(result_0.length).toBe(1);
|
|
39
|
+
expect(result_0[0].name).toBe("a");
|
|
40
|
+
|
|
41
|
+
node.createPort(DUMMY_TYPE, "b", PortDirection.In);
|
|
42
|
+
|
|
43
|
+
const result_1 = node.getPortsByName("a");
|
|
44
|
+
expect(result_1.length).toBe(1);
|
|
45
|
+
expect(result_1[0].name).toBe("a");
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test("delete port", () => {
|
|
49
|
+
const node = new NodeDescription();
|
|
50
|
+
|
|
51
|
+
expect(node.deletePort(1)).toBe(false);
|
|
52
|
+
|
|
53
|
+
const id = node.createPort(DUMMY_TYPE, "a", PortDirection.In);
|
|
54
|
+
|
|
55
|
+
expect(node.deletePort(id)).toBe(true);
|
|
56
|
+
|
|
57
|
+
expect(node.getPorts()).toEqual([]);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test("toString", () => {
|
|
61
|
+
const node = new NodeDescription();
|
|
62
|
+
|
|
63
|
+
expect(typeof node.toString()).toBe("string");
|
|
64
|
+
expect(node.toString().length).toBeGreaterThan(0);
|
|
27
65
|
});
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { DataType } from "../DataType.js";
|
|
2
|
+
import { NodeGraph } from "../NodeGraph.js";
|
|
3
|
+
import { NodeDescription } from "./NodeDescription.js";
|
|
4
|
+
import { NodeInstancePortReference } from "./NodeInstancePortReference.js";
|
|
5
|
+
import { PortDirection } from "./PortDirection.js";
|
|
6
|
+
|
|
7
|
+
const DUMMY_TYPE = DataType.from(0, 'dummy');
|
|
8
|
+
test("constructor does not throw", () => {
|
|
9
|
+
new NodeInstancePortReference()
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
test("outgoing connections", () => {
|
|
13
|
+
const nd = new NodeDescription();
|
|
14
|
+
const port_a_id = nd.createPort(DUMMY_TYPE, "a", PortDirection.Out);
|
|
15
|
+
const port_b_id = nd.createPort(DUMMY_TYPE, "b", PortDirection.In);
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
const graph = new NodeGraph();
|
|
19
|
+
const node_instance_id = graph.createNode(nd);
|
|
20
|
+
|
|
21
|
+
const port_a_ref = graph.getConnectionEndpoint(node_instance_id, port_a_id);
|
|
22
|
+
|
|
23
|
+
expect(port_a_ref.outConnections).toEqual([]);
|
|
24
|
+
|
|
25
|
+
const connection_id = graph.createConnection(node_instance_id, port_a_id, node_instance_id, port_b_id);
|
|
26
|
+
|
|
27
|
+
const connection = graph.getConnection(connection_id);
|
|
28
|
+
|
|
29
|
+
expect(port_a_ref.outConnections).toEqual([connection]);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test("incoming connections", () => {
|
|
33
|
+
const nd = new NodeDescription();
|
|
34
|
+
const port_a_id = nd.createPort(DUMMY_TYPE, "a", PortDirection.Out);
|
|
35
|
+
const port_b_id = nd.createPort(DUMMY_TYPE, "b", PortDirection.In);
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
const graph = new NodeGraph();
|
|
39
|
+
const node_instance_id = graph.createNode(nd);
|
|
40
|
+
|
|
41
|
+
const port_b_ref = graph.getConnectionEndpoint(node_instance_id, port_b_id);
|
|
42
|
+
|
|
43
|
+
expect(port_b_ref.inConnections).toEqual([]);
|
|
44
|
+
|
|
45
|
+
const connection_id = graph.createConnection(node_instance_id, port_a_id, node_instance_id, port_b_id);
|
|
46
|
+
|
|
47
|
+
const connection = graph.getConnection(connection_id);
|
|
48
|
+
|
|
49
|
+
expect(port_b_ref.inConnections).toEqual([connection]);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test("hash", () => {
|
|
53
|
+
|
|
54
|
+
const nd = new NodeDescription();
|
|
55
|
+
const port_a_id = nd.createPort(DUMMY_TYPE, "a", PortDirection.Out);
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
const graph = new NodeGraph();
|
|
59
|
+
const node_instance_id = graph.createNode(nd);
|
|
60
|
+
|
|
61
|
+
const port_a_ref = graph.getConnectionEndpoint(node_instance_id, port_a_id);
|
|
62
|
+
|
|
63
|
+
expect(port_a_ref.hash()).toEqual(port_a_ref.hash());
|
|
64
|
+
expect(typeof port_a_ref.hash()).toBe("number");
|
|
65
|
+
expect(Number.isInteger(port_a_ref.hash())).toBe(true);
|
|
66
|
+
});
|
|
@@ -1,16 +1,13 @@
|
|
|
1
|
-
import { NodeGraph } from "../NodeGraph.js";
|
|
2
1
|
import { assert } from "../../../assert.js";
|
|
2
|
+
import { NodeGraph } from "../NodeGraph.js";
|
|
3
3
|
import { graph_collect_connections_amongst_nodes } from "./graph_collect_connections_amongst_nodes.js";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Clone portion of a graph as a new graph, retaining connections amongst those nodes
|
|
7
|
-
* @param {NodeGraph} graph
|
|
8
7
|
* @param {NodeInstance[]} nodes
|
|
8
|
+
* @returns {NodeGraph}
|
|
9
9
|
*/
|
|
10
|
-
export function graph_clone_by_node_subset({
|
|
11
|
-
|
|
12
|
-
assert.defined(graph, 'graph');
|
|
13
|
-
assert.notNull(graph, 'graph');
|
|
10
|
+
export function graph_clone_by_node_subset({ nodes }) {
|
|
14
11
|
|
|
15
12
|
assert.defined(nodes, 'nodes');
|
|
16
13
|
assert.notNull(nodes, 'nodes');
|
|
@@ -18,7 +15,7 @@ export function graph_clone_by_node_subset({ graph, nodes }) {
|
|
|
18
15
|
|
|
19
16
|
const result = new NodeGraph();
|
|
20
17
|
|
|
21
|
-
const connections = graph_collect_connections_amongst_nodes({
|
|
18
|
+
const connections = graph_collect_connections_amongst_nodes({ nodes });
|
|
22
19
|
|
|
23
20
|
result.mergeFragment({
|
|
24
21
|
nodes,
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Given a graph and a set of nodes, get all connections that connect these nodes amongst themselves
|
|
3
|
-
* @param {NodeGraph} graph
|
|
4
3
|
* @param {NodeInstance[]} nodes
|
|
5
4
|
* @returns {Connection[]}
|
|
6
5
|
*/
|
|
7
6
|
export function graph_collect_connections_amongst_nodes({
|
|
8
|
-
graph,
|
|
9
7
|
nodes
|
|
10
8
|
}) {
|
|
11
9
|
|