@woosh/meep-engine 2.76.3 → 2.77.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 +202 -621
- package/build/meep.min.js +1 -1
- package/build/meep.module.js +202 -621
- package/editor/view/ecs/components/TerrainController.js +9 -16
- package/package.json +1 -1
- package/src/core/collection/heap/Uint32Heap.js +10 -1
- package/src/core/graph/Edge.js +20 -0
- package/src/core/graph/Graph.js +1 -0
- package/src/core/graph/SquareMatrix.js +4 -2
- package/src/core/graph/WeightedEdge.js +5 -9
- package/src/core/graph/coloring/validateGraphColoring.js +1 -1
- package/src/core/graph/eigen/matrix_eigenvalues_in_place.js +21 -0
- package/src/core/graph/eigen/{eigen.spec.js → matrix_eigenvalues_in_place.spec.js} +2 -2
- package/src/core/graph/eigen/matrix_householder_in_place.js +92 -0
- package/src/core/graph/eigen/{eigen.js → matrix_qr_in_place.js} +2 -113
- package/src/core/graph/v2/Graph.js +16 -9
- package/src/core/graph/v2/NodeContainer.js +120 -22
- package/src/engine/ecs/storage/binary/BinarySerializationRegistry.js +8 -6
- package/src/engine/graphics/particles/node-based/codegen/modules/FunctionModuleRegistry.js +1 -1
- package/src/engine/navigation/grid/find_path_on_grid_astar.js +30 -27
- package/src/engine/navigation/grid/find_path_on_grid_astar.spec.js +2 -2
- package/src/generation/grid/generation/road/GridTaskGenerateRoads.js +17 -33
- package/src/core/graph/GraphUtils.js +0 -284
- package/src/engine/ecs/terrain/ecs/splat/SplatMapMaterialPatch.js +0 -464
- package/src/engine/ecs/terrain/ecs/splat/SplatMapOptimizer.js +0 -622
- package/src/engine/ecs/terrain/ecs/splat/SplatMapOptimizerDebugger.js +0 -383
|
@@ -1,20 +1,19 @@
|
|
|
1
|
-
import
|
|
1
|
+
import Signal from "../../../../src/core/events/signal/Signal.js";
|
|
2
2
|
import Vector2 from "../../../../src/core/geom/Vector2.js";
|
|
3
|
-
import
|
|
4
|
-
import { NativeListController } from "../../../../src/view/controller/controls/NativeListController.js";
|
|
3
|
+
import ObservedValue from "../../../../src/core/model/ObservedValue.js";
|
|
5
4
|
import { TerrainLayer } from "../../../../src/engine/ecs/terrain/ecs/layers/TerrainLayer.js";
|
|
6
5
|
import CheckersTextureURI from "../../../../src/engine/graphics/texture/CheckersTextureURI.js";
|
|
7
|
-
import EmptyView from "../../../../src/view/elements/EmptyView.js";
|
|
8
|
-
import convertSampler2D2Canvas from "../../../../src/engine/graphics/texture/sampler/Sampler2D2Canvas.js";
|
|
9
|
-
import { CanvasView } from "../../../../src/view/elements/CanvasView.js";
|
|
10
6
|
import { sampler2d_scale } from "../../../../src/engine/graphics/texture/sampler/resize/sampler2d_scale.js";
|
|
11
7
|
import { Sampler2D } from "../../../../src/engine/graphics/texture/sampler/Sampler2D.js";
|
|
12
|
-
import
|
|
8
|
+
import convertSampler2D2Canvas from "../../../../src/engine/graphics/texture/sampler/Sampler2D2Canvas.js";
|
|
9
|
+
import LabelView from "../../../../src/view/common/LabelView.js";
|
|
10
|
+
import { NativeListController } from "../../../../src/view/controller/controls/NativeListController.js";
|
|
13
11
|
import Vector2Control from "../../../../src/view/controller/controls/Vector2Control.js";
|
|
12
|
+
import { CanvasView } from "../../../../src/view/elements/CanvasView.js";
|
|
13
|
+
import EmptyView from "../../../../src/view/elements/EmptyView.js";
|
|
14
14
|
import GroupView from "../../../../src/view/elements/Group.js";
|
|
15
|
-
import
|
|
16
|
-
import
|
|
17
|
-
import { SplatMapOptimizer } from "../../../../src/engine/ecs/terrain/ecs/splat/SplatMapOptimizer.js";
|
|
15
|
+
import View from "../../../../src/view/View.js";
|
|
16
|
+
import DatGuiController from "./DatGuiController.js";
|
|
18
17
|
|
|
19
18
|
class LayersController extends View {
|
|
20
19
|
/**
|
|
@@ -173,12 +172,6 @@ export class TerrainController extends View {
|
|
|
173
172
|
model.__tiles.rebuild();
|
|
174
173
|
}, 'Rebuild');
|
|
175
174
|
|
|
176
|
-
controller.addAction(() => {
|
|
177
|
-
|
|
178
|
-
SplatMapOptimizer.optimizeSynchronous(model.splat)
|
|
179
|
-
|
|
180
|
-
}, 'Optimize Textures');
|
|
181
|
-
|
|
182
175
|
controller.add(model, 'size', { step: 1 });
|
|
183
176
|
controller.add(model, 'resolution').step(1);
|
|
184
177
|
controller.add(model, 'gridScale').step(1).name('Gird Size');
|
package/package.json
CHANGED
|
@@ -159,7 +159,7 @@ export class Uint32Heap {
|
|
|
159
159
|
const size = this.__size;
|
|
160
160
|
|
|
161
161
|
while (true) {
|
|
162
|
-
const l = (
|
|
162
|
+
const l = (i << 1) + 1;
|
|
163
163
|
const r = l + 1;
|
|
164
164
|
|
|
165
165
|
let smallest = i;
|
|
@@ -282,6 +282,15 @@ export class Uint32Heap {
|
|
|
282
282
|
return -1;
|
|
283
283
|
}
|
|
284
284
|
|
|
285
|
+
/**
|
|
286
|
+
*
|
|
287
|
+
* @param {number} id
|
|
288
|
+
* @returns {boolean}
|
|
289
|
+
*/
|
|
290
|
+
contains(id){
|
|
291
|
+
return this.find_index_by_id(id) !== -1;
|
|
292
|
+
}
|
|
293
|
+
|
|
285
294
|
/**
|
|
286
295
|
* Clear out all the data, heap will be made empty
|
|
287
296
|
*/
|
package/src/core/graph/Edge.js
CHANGED
|
@@ -86,6 +86,26 @@ export class Edge {
|
|
|
86
86
|
return (this.direction & EdgeDirectionType.Backward) !== 0;
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
+
/**
|
|
90
|
+
* Checks direction of the edge, if the edge is directed towards supplied node - returns true, false otherwise
|
|
91
|
+
* @param {N} node
|
|
92
|
+
* @returns {boolean}
|
|
93
|
+
*/
|
|
94
|
+
isDirectedTowards(node) {
|
|
95
|
+
return (this.first === node && this.direction === EdgeDirectionType.Backward)
|
|
96
|
+
|| (this.second === node && this.direction === EdgeDirectionType.Forward);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Checks direction of the edge, if the edge is directed away from the supplied node - returns true, false otherwise
|
|
101
|
+
* @param {N} node
|
|
102
|
+
* @returns {boolean}
|
|
103
|
+
*/
|
|
104
|
+
isDirectedAwayFrom(node) {
|
|
105
|
+
return (this.first === node && this.direction === EdgeDirectionType.Forward)
|
|
106
|
+
|| (this.second === node && this.direction === EdgeDirectionType.Backward)
|
|
107
|
+
}
|
|
108
|
+
|
|
89
109
|
/**
|
|
90
110
|
* @deprecated
|
|
91
111
|
* @returns {number}
|
package/src/core/graph/Graph.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { DataType2TypedArrayConstructorMapping } from "../binary/type/DataType2TypedArrayConstructorMapping.js";
|
|
2
1
|
import { assert } from "../assert.js";
|
|
2
|
+
import { DataType2TypedArrayConstructorMapping } from "../binary/type/DataType2TypedArrayConstructorMapping.js";
|
|
3
3
|
import { array_copy } from "../collection/array/array_copy.js";
|
|
4
4
|
|
|
5
5
|
export class SquareMatrix {
|
|
@@ -9,6 +9,8 @@ export class SquareMatrix {
|
|
|
9
9
|
* @param {BinaryDataType|string} type
|
|
10
10
|
*/
|
|
11
11
|
constructor(size, type) {
|
|
12
|
+
assert.isNonNegativeInteger(size, 'size');
|
|
13
|
+
|
|
12
14
|
const TypedArray = DataType2TypedArrayConstructorMapping[type];
|
|
13
15
|
|
|
14
16
|
if (TypedArray === undefined) {
|
|
@@ -162,7 +164,7 @@ export class SquareMatrix {
|
|
|
162
164
|
* @param {number[]} [destination]
|
|
163
165
|
* @param {number} [offset]
|
|
164
166
|
*/
|
|
165
|
-
toArray(destination = new Array(this.length), offset=0) {
|
|
167
|
+
toArray(destination = new Array(this.length), offset = 0) {
|
|
166
168
|
array_copy(this.data, 0, destination, offset, this.length);
|
|
167
169
|
|
|
168
170
|
return destination;
|
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
import { Edge } from "./Edge.js";
|
|
2
2
|
|
|
3
3
|
export class WeightedEdge extends Edge {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
* @type {number}
|
|
10
|
-
*/
|
|
11
|
-
this.weight = 0;
|
|
12
|
-
}
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
* @type {number}
|
|
7
|
+
*/
|
|
8
|
+
weight = 0;
|
|
13
9
|
|
|
14
10
|
/**
|
|
15
11
|
*
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { matrix_householder_in_place } from "./matrix_householder_in_place.js";
|
|
2
|
+
import { matrix_qr_in_place } from "./matrix_qr_in_place.js";
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* list of eigen values square matrix (allow non symmetric)
|
|
7
|
+
* NOTE: Modifies input matrix
|
|
8
|
+
* @param {SquareMatrix} mat
|
|
9
|
+
* @return {number[]}
|
|
10
|
+
*/
|
|
11
|
+
export function matrix_eigenvalues_in_place(mat) {
|
|
12
|
+
const n = mat.size;
|
|
13
|
+
matrix_householder_in_place(mat.data, n);
|
|
14
|
+
matrix_qr_in_place(mat.data, n);
|
|
15
|
+
|
|
16
|
+
const result = new Float32Array(n);
|
|
17
|
+
|
|
18
|
+
mat.readDiagonal(result);
|
|
19
|
+
|
|
20
|
+
return result;
|
|
21
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { SquareMatrix } from "../SquareMatrix.js";
|
|
2
1
|
import { BinaryDataType } from "../../binary/type/BinaryDataType.js";
|
|
3
|
-
import {
|
|
2
|
+
import { SquareMatrix } from "../SquareMatrix.js";
|
|
3
|
+
import { matrix_eigenvalues_in_place } from "./matrix_eigenvalues_in_place.js";
|
|
4
4
|
|
|
5
5
|
function roughly_equal_array_vectors(actual, expected) {
|
|
6
6
|
expect(actual.length).toBe(expected.length);
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
const EPSILON = 1e-10;
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* NxN matrix Householder reduction
|
|
5
|
+
* Return subfunction to upper Hessenberg matrix by Householder transformation
|
|
6
|
+
* @see http://www-in.aut.ac.jp/~minemura/pub/Csimu/C/QRmethod.html
|
|
7
|
+
* @param {number[]} a
|
|
8
|
+
* @param {number} n
|
|
9
|
+
*/
|
|
10
|
+
export function matrix_householder_in_place(a, n) {
|
|
11
|
+
const u = new Float64Array(n);
|
|
12
|
+
const d = new Float64Array(n);
|
|
13
|
+
const ds = new Float64Array(n);
|
|
14
|
+
|
|
15
|
+
let i, j, k;
|
|
16
|
+
let sum;
|
|
17
|
+
|
|
18
|
+
for (k = 0; k <= n - 3; k++) {
|
|
19
|
+
|
|
20
|
+
for (i = 0; i <= k; i++) {
|
|
21
|
+
u[i] = 0;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
for (i = k + 1; i < n; i++) {
|
|
25
|
+
u[i] = a[n * i + k];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Build transformation matrix H
|
|
29
|
+
sum = 0.0;
|
|
30
|
+
|
|
31
|
+
for (i = k + 1; i < n; i++) {
|
|
32
|
+
sum = sum + u[i] * u[i];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const u_k_1 = u[k + 1];
|
|
36
|
+
|
|
37
|
+
const u_k_1_abs = Math.abs(u_k_1);
|
|
38
|
+
if (u_k_1_abs < EPSILON) {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const sigma = Math.sqrt(sum) * u_k_1 / u_k_1_abs;
|
|
43
|
+
|
|
44
|
+
u[k + 1] += sigma;
|
|
45
|
+
|
|
46
|
+
const v_norm = Math.sqrt(2.0 * sigma * u[k + 1]);
|
|
47
|
+
|
|
48
|
+
for (i = k + 1; i < n; i++) {
|
|
49
|
+
u[i] /= v_norm;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Similarity transformation
|
|
53
|
+
for (i = 0; i < n; i++) {
|
|
54
|
+
d[i] = 0.0;
|
|
55
|
+
ds[i] = 0.0;
|
|
56
|
+
for (j = k + 1; j <= n - 1; j++) {
|
|
57
|
+
const u_j = u[j];
|
|
58
|
+
|
|
59
|
+
d[i] += a[n * i + j] * u_j;
|
|
60
|
+
ds[i] += a[n * j + i] * u_j;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
let ud = 0.0;
|
|
65
|
+
let uds = 0.0;
|
|
66
|
+
|
|
67
|
+
for (i = k + 1; i < n; i++) {
|
|
68
|
+
const u_i = u[i];
|
|
69
|
+
|
|
70
|
+
ud += u_i * d[i];
|
|
71
|
+
uds += u_i * ds[i];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
for (i = 0; i < n; i++) {
|
|
75
|
+
const u_i = u[i];
|
|
76
|
+
|
|
77
|
+
d[i] = 2.0 * (d[i] - ud * u_i);
|
|
78
|
+
ds[i] = 2.0 * (ds[i] - uds * u_i);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
for (i = 0; i < n; i++) {
|
|
82
|
+
const u_i = u[i];
|
|
83
|
+
const d_i = d[i];
|
|
84
|
+
|
|
85
|
+
const n_i = n * i;
|
|
86
|
+
|
|
87
|
+
for (j = 0; j < n; j++) {
|
|
88
|
+
a[n_i + j] -= u_i * ds[j] + d_i * u[j];
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -1,97 +1,5 @@
|
|
|
1
1
|
const EPSILON = 1e-10;
|
|
2
2
|
|
|
3
|
-
/**
|
|
4
|
-
* NxN matrix Householder reduction
|
|
5
|
-
* Return subfunction to upper Hessenberg matrix by Householder transformation
|
|
6
|
-
* @see http://www-in.aut.ac.jp/~minemura/pub/Csimu/C/QRmethod.html
|
|
7
|
-
* @param {number[]} a
|
|
8
|
-
* @param {number} n
|
|
9
|
-
*/
|
|
10
|
-
function householder_in_place(a, n) {
|
|
11
|
-
const u = new Float64Array(n);
|
|
12
|
-
const d = new Float64Array(n);
|
|
13
|
-
const ds = new Float64Array(n);
|
|
14
|
-
|
|
15
|
-
let i, j, k;
|
|
16
|
-
let sum;
|
|
17
|
-
|
|
18
|
-
for (k = 0; k <= n - 3; k++) {
|
|
19
|
-
|
|
20
|
-
for (i = 0; i <= k; i++) {
|
|
21
|
-
u[i] = 0;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
for (i = k + 1; i < n; i++) {
|
|
25
|
-
u[i] = a[n * i + k];
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// Build transformation matrix H
|
|
29
|
-
sum = 0.0;
|
|
30
|
-
|
|
31
|
-
for (i = k + 1; i < n; i++) {
|
|
32
|
-
sum = sum + u[i] * u[i];
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const u_k_1 = u[k + 1];
|
|
36
|
-
|
|
37
|
-
const u_k_1_abs = Math.abs(u_k_1);
|
|
38
|
-
if (u_k_1_abs < EPSILON) {
|
|
39
|
-
continue;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const sigma = Math.sqrt(sum) * u_k_1 / u_k_1_abs;
|
|
43
|
-
|
|
44
|
-
u[k + 1] += sigma;
|
|
45
|
-
|
|
46
|
-
const v_norm = Math.sqrt(2.0 * sigma * u[k + 1]);
|
|
47
|
-
|
|
48
|
-
for (i = k + 1; i < n; i++) {
|
|
49
|
-
u[i] /= v_norm;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// Similarity transformation
|
|
53
|
-
for (i = 0; i < n; i++) {
|
|
54
|
-
d[i] = 0.0;
|
|
55
|
-
ds[i] = 0.0;
|
|
56
|
-
for (j = k + 1; j <= n - 1; j++) {
|
|
57
|
-
const u_j = u[j];
|
|
58
|
-
|
|
59
|
-
d[i] += a[n * i + j] * u_j;
|
|
60
|
-
ds[i] += a[n * j + i] * u_j;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
let ud = 0.0;
|
|
65
|
-
let uds = 0.0;
|
|
66
|
-
|
|
67
|
-
for (i = k + 1; i < n; i++) {
|
|
68
|
-
const u_i = u[i];
|
|
69
|
-
|
|
70
|
-
ud += u_i * d[i];
|
|
71
|
-
uds += u_i * ds[i];
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
for (i = 0; i < n; i++) {
|
|
75
|
-
const u_i = u[i];
|
|
76
|
-
|
|
77
|
-
d[i] = 2.0 * (d[i] - ud * u_i);
|
|
78
|
-
ds[i] = 2.0 * (ds[i] - uds * u_i);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
for (i = 0; i < n; i++) {
|
|
82
|
-
const u_i = u[i];
|
|
83
|
-
const d_i = d[i];
|
|
84
|
-
|
|
85
|
-
const n_i = n * i;
|
|
86
|
-
|
|
87
|
-
for (j = 0; j < n; j++) {
|
|
88
|
-
a[n_i + j] -= u_i * ds[j] + d_i * u[j];
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
|
|
95
3
|
/**
|
|
96
4
|
* Perform QR factorization in-place
|
|
97
5
|
* Subfunction that analyzes eigenvalues by QR decomposition
|
|
@@ -99,7 +7,7 @@ function householder_in_place(a, n) {
|
|
|
99
7
|
* @param {number[]} a Square matrix
|
|
100
8
|
* @param {number} n size of the matrix in single dimension
|
|
101
9
|
*/
|
|
102
|
-
function
|
|
10
|
+
export function matrix_qr_in_place(a, n) {
|
|
103
11
|
const q = new Float64Array(n * n);
|
|
104
12
|
const w = new Float64Array(n);
|
|
105
13
|
|
|
@@ -207,23 +115,4 @@ function qr_in_place(a, n) {
|
|
|
207
115
|
a[n * i + i] += mu;
|
|
208
116
|
}
|
|
209
117
|
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* list of eigen values square matrix (allow non symmetric)
|
|
215
|
-
* NOTE: Modifies input matrix
|
|
216
|
-
* @param {SquareMatrix} mat
|
|
217
|
-
* @return {number[]}
|
|
218
|
-
*/
|
|
219
|
-
export function matrix_eigenvalues_in_place(mat) {
|
|
220
|
-
const n = mat.size;
|
|
221
|
-
householder_in_place(mat.data, n);
|
|
222
|
-
qr_in_place(mat.data, n);
|
|
223
|
-
|
|
224
|
-
const result = new Float32Array(n);
|
|
225
|
-
|
|
226
|
-
mat.readDiagonal(result);
|
|
227
|
-
|
|
228
|
-
return result;
|
|
229
|
-
}
|
|
118
|
+
}
|
|
@@ -1,20 +1,23 @@
|
|
|
1
1
|
import { assert } from "../../assert.js";
|
|
2
2
|
import Signal from "../../events/signal/Signal.js";
|
|
3
|
-
import { NodeContainer } from "./NodeContainer.js";
|
|
4
3
|
import { Edge, EdgeDirectionType } from "../Edge.js";
|
|
4
|
+
import { NodeContainer } from "./NodeContainer.js";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
+
* Reconstruct path from search metadata
|
|
7
8
|
* @template T
|
|
8
9
|
* @param {NodeContainer<T>} goal_node_container
|
|
9
|
-
* @param {Map<NodeContainer<T>,NodeContainer<T>>}
|
|
10
|
-
* @returns {T[]}
|
|
10
|
+
* @param {Map<NodeContainer<T>,NodeContainer<T>>} came_from
|
|
11
|
+
* @returns {T[]} Nodes comprising the path from start to goal
|
|
11
12
|
*/
|
|
12
|
-
function construct_path(goal_node_container,
|
|
13
|
+
function construct_path(goal_node_container, came_from) {
|
|
13
14
|
const result = [];
|
|
15
|
+
|
|
14
16
|
let c = goal_node_container;
|
|
17
|
+
|
|
15
18
|
do {
|
|
16
19
|
result.unshift(c.node);
|
|
17
|
-
c =
|
|
20
|
+
c = came_from.get(c);
|
|
18
21
|
} while (c !== undefined);
|
|
19
22
|
|
|
20
23
|
return result;
|
|
@@ -28,16 +31,21 @@ export class Graph {
|
|
|
28
31
|
/**
|
|
29
32
|
*
|
|
30
33
|
* @type {Map<N, NodeContainer<N>>}
|
|
34
|
+
* @readonly
|
|
31
35
|
* @private
|
|
32
36
|
*/
|
|
33
37
|
__nodes = new Map();
|
|
34
38
|
/**
|
|
35
39
|
*
|
|
36
40
|
* @type {Set<Edge<N>>}
|
|
41
|
+
* @readonly
|
|
37
42
|
* @private
|
|
38
43
|
*/
|
|
39
44
|
__edges = new Set();
|
|
40
45
|
|
|
46
|
+
/**
|
|
47
|
+
* @readonly
|
|
48
|
+
*/
|
|
41
49
|
on = {
|
|
42
50
|
/**
|
|
43
51
|
* @type {Signal<N,this>}
|
|
@@ -191,10 +199,10 @@ export class Graph {
|
|
|
191
199
|
*
|
|
192
200
|
* @param {N} source
|
|
193
201
|
* @param {N} target
|
|
194
|
-
* @param {EdgeDirectionType} type
|
|
202
|
+
* @param {EdgeDirectionType} [type] Undirected by default
|
|
195
203
|
* @returns {Edge<N>}
|
|
196
204
|
*/
|
|
197
|
-
createEdge(source, target, type) {
|
|
205
|
+
createEdge(source, target, type = EdgeDirectionType.Undirected) {
|
|
198
206
|
const edge = new Edge(source, target);
|
|
199
207
|
|
|
200
208
|
edge.direction = type;
|
|
@@ -376,8 +384,7 @@ export class Graph {
|
|
|
376
384
|
const edge_count = edges.length;
|
|
377
385
|
|
|
378
386
|
for (let i = 0; i < edge_count; i++) {
|
|
379
|
-
|
|
380
|
-
result[i] = edge;
|
|
387
|
+
result[i] = edges[i];
|
|
381
388
|
}
|
|
382
389
|
|
|
383
390
|
return edge_count;
|
|
@@ -1,45 +1,141 @@
|
|
|
1
1
|
import { EdgeDirectionType } from "../Edge.js";
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Supplementary structure to `Graph`, holds edges and neighbour nodes for fast access
|
|
5
|
+
* Used internally by `Graph`
|
|
6
|
+
* @template N
|
|
7
|
+
*/
|
|
3
8
|
export class NodeContainer {
|
|
4
9
|
/**
|
|
5
|
-
*
|
|
10
|
+
* Node being described
|
|
11
|
+
* @type {N}
|
|
6
12
|
*/
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
node = null;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Attached edges
|
|
17
|
+
* @type {Edge<N>[]}
|
|
18
|
+
* @private
|
|
19
|
+
*/
|
|
20
|
+
__edges = [];
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
*
|
|
24
|
+
* @type {Map<N,number>}
|
|
25
|
+
* @private
|
|
26
|
+
*/
|
|
27
|
+
__neighbors = new Map();
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
*
|
|
31
|
+
* @return {number}
|
|
32
|
+
*/
|
|
33
|
+
getEdgeCount() {
|
|
34
|
+
return this.__edges.length;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Do not modify the returned value
|
|
39
|
+
* @return {Edge<N>[]}
|
|
40
|
+
*/
|
|
41
|
+
getEdges() {
|
|
42
|
+
return this.__edges;
|
|
43
|
+
}
|
|
13
44
|
|
|
45
|
+
/**
|
|
46
|
+
*
|
|
47
|
+
* @returns {N[]}
|
|
48
|
+
*/
|
|
49
|
+
get inNodes() {
|
|
50
|
+
return this.inEdges.map(e => e.other(this.node));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
*
|
|
55
|
+
* @returns {N[]}
|
|
56
|
+
*/
|
|
57
|
+
get outNodes() {
|
|
58
|
+
return this.outEdges.map(e => e.other(this.node));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
get outEdges() {
|
|
14
63
|
/**
|
|
15
64
|
*
|
|
16
65
|
* @type {Edge<N>[]}
|
|
17
|
-
* @private
|
|
18
66
|
*/
|
|
19
|
-
|
|
67
|
+
const result = [];
|
|
20
68
|
|
|
69
|
+
this.getOutgoingEdges(result);
|
|
70
|
+
|
|
71
|
+
return result;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
get inEdges() {
|
|
21
75
|
/**
|
|
22
76
|
*
|
|
23
|
-
* @type {
|
|
24
|
-
* @private
|
|
77
|
+
* @type {Edge<N>[]}
|
|
25
78
|
*/
|
|
26
|
-
|
|
79
|
+
const result = [];
|
|
80
|
+
|
|
81
|
+
this.getIncomingEdges(result);
|
|
82
|
+
|
|
83
|
+
return result;
|
|
27
84
|
}
|
|
28
85
|
|
|
86
|
+
|
|
29
87
|
/**
|
|
30
88
|
*
|
|
31
|
-
* @
|
|
89
|
+
* @param {Edge<N>[]} result
|
|
90
|
+
* @returns {number}
|
|
32
91
|
*/
|
|
33
|
-
|
|
34
|
-
|
|
92
|
+
getIncomingEdges(result) {
|
|
93
|
+
const edges = this.__edges;
|
|
94
|
+
|
|
95
|
+
const edge_count = edges.length;
|
|
96
|
+
|
|
97
|
+
let result_count = 0;
|
|
98
|
+
|
|
99
|
+
for (let i = 0; i < edge_count; i++) {
|
|
100
|
+
const edge = edges[i];
|
|
101
|
+
|
|
102
|
+
if (edge.isDirectedTowards(this.node)) {
|
|
103
|
+
|
|
104
|
+
result.push(edge);
|
|
105
|
+
result_count++;
|
|
106
|
+
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return result_count;
|
|
35
112
|
}
|
|
36
113
|
|
|
37
114
|
/**
|
|
38
|
-
*
|
|
39
|
-
* @
|
|
115
|
+
*
|
|
116
|
+
* @param {Edge<N>[]} result
|
|
117
|
+
* @returns {number}
|
|
40
118
|
*/
|
|
41
|
-
|
|
42
|
-
|
|
119
|
+
getOutgoingEdges(result) {
|
|
120
|
+
const edges = this.__edges;
|
|
121
|
+
|
|
122
|
+
const edge_count = edges.length;
|
|
123
|
+
|
|
124
|
+
let result_count = 0;
|
|
125
|
+
|
|
126
|
+
for (let i = 0; i < edge_count; i++) {
|
|
127
|
+
const edge = edges[i];
|
|
128
|
+
|
|
129
|
+
if (edge.isDirectedAwayFrom(this.node)) {
|
|
130
|
+
|
|
131
|
+
result.push(edge);
|
|
132
|
+
result_count++;
|
|
133
|
+
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return result_count;
|
|
43
139
|
}
|
|
44
140
|
|
|
45
141
|
/**
|
|
@@ -52,12 +148,14 @@ export class NodeContainer {
|
|
|
52
148
|
const edges = this.__edges;
|
|
53
149
|
const edge_count = edges.length;
|
|
54
150
|
|
|
151
|
+
const current_node = this.node;
|
|
152
|
+
|
|
55
153
|
for (let i = 0; i < edge_count; i++) {
|
|
56
154
|
const edge = edges[i];
|
|
57
155
|
|
|
58
156
|
if (
|
|
59
|
-
(edge.first ===
|
|
60
|
-
|| (edge.second ===
|
|
157
|
+
(edge.first === current_node && edge.direction === EdgeDirectionType.Forward)
|
|
158
|
+
|| (edge.second === current_node && edge.direction === EdgeDirectionType.Backward)
|
|
61
159
|
|
|
62
160
|
) {
|
|
63
161
|
r++;
|
|
@@ -81,7 +179,7 @@ export class NodeContainer {
|
|
|
81
179
|
|
|
82
180
|
/**
|
|
83
181
|
*
|
|
84
|
-
* @param {function(Edge)} visitor
|
|
182
|
+
* @param {function(Edge<N>)} visitor
|
|
85
183
|
* @param {*} [thisArg]
|
|
86
184
|
* @returns {number}
|
|
87
185
|
*/
|