@woosh/meep-engine 2.77.0 → 2.78.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.
@@ -70583,10 +70583,19 @@ class Edge {
70583
70583
  return this.first === node || this.second === node;
70584
70584
  }
70585
70585
 
70586
+ /**
70587
+ *
70588
+ * @param {N} source
70589
+ * @param {N} target
70590
+ * @returns {boolean} True iff the edge contains both source and target and allows transition from source to target
70591
+ */
70586
70592
  validateTransition(source, target) {
70587
70593
  const a = this.first;
70588
70594
  const b = this.second;
70589
- return (a === source && b === target && this.traversableForward()) || (b === source && a === target && this.traversableBackward());
70595
+
70596
+ return (a === source && b === target && this.traversableForward())
70597
+ || (b === source && a === target && this.traversableBackward())
70598
+ ;
70590
70599
  }
70591
70600
 
70592
70601
  /**
@@ -70634,16 +70643,6 @@ class Edge {
70634
70643
  || (this.second === node && this.direction === EdgeDirectionType.Backward)
70635
70644
  }
70636
70645
 
70637
- /**
70638
- * @deprecated
70639
- * @returns {number}
70640
- */
70641
- angle() {
70642
-
70643
- const delta = this.second.clone().sub(this.first);
70644
- return Math.atan2(delta.y, delta.x);
70645
- }
70646
-
70647
70646
  /**
70648
70647
  *
70649
70648
  * @returns {N[]}
@@ -70652,15 +70651,6 @@ class Edge {
70652
70651
  return [this.first, this.second];
70653
70652
  }
70654
70653
 
70655
-
70656
- /**
70657
- * @deprecated
70658
- * @returns {number}
70659
- */
70660
- get length() {
70661
-
70662
- return this.first.distanceTo(this.second);
70663
- }
70664
70654
  }
70665
70655
 
70666
70656
  /**
@@ -70691,10 +70681,19 @@ class NodeContainer {
70691
70681
  /**
70692
70682
  *
70693
70683
  * @type {Map<N,number>}
70684
+ * Maps neighbour node to number of edges to that node from this one
70694
70685
  * @private
70695
70686
  */
70696
70687
  __neighbors = new Map();
70697
70688
 
70689
+ /**
70690
+ * NOTE: this method allocates memory internally
70691
+ * @returns {N[]}
70692
+ */
70693
+ get neighbours() {
70694
+ return Array.from(this.__neighbors.keys());
70695
+ }
70696
+
70698
70697
  /**
70699
70698
  *
70700
70699
  * @return {number}
@@ -70712,7 +70711,7 @@ class NodeContainer {
70712
70711
  }
70713
70712
 
70714
70713
  /**
70715
- *
70714
+ * NOTE: this method allocates memory internally
70716
70715
  * @returns {N[]}
70717
70716
  */
70718
70717
  get inNodes() {
@@ -70720,7 +70719,7 @@ class NodeContainer {
70720
70719
  }
70721
70720
 
70722
70721
  /**
70723
- *
70722
+ * NOTE: this method allocates memory internally
70724
70723
  * @returns {N[]}
70725
70724
  */
70726
70725
  get outNodes() {
@@ -70728,6 +70727,10 @@ class NodeContainer {
70728
70727
  }
70729
70728
 
70730
70729
 
70730
+ /**
70731
+ * NOTE: this method allocates memory internally
70732
+ * @returns {Edge<N>[]}
70733
+ */
70731
70734
  get outEdges() {
70732
70735
  /**
70733
70736
  *
@@ -70740,6 +70743,10 @@ class NodeContainer {
70740
70743
  return result;
70741
70744
  }
70742
70745
 
70746
+ /**
70747
+ * NOTE: this method allocates memory internally
70748
+ * @returns {Edge<N>[]}
70749
+ */
70743
70750
  get inEdges() {
70744
70751
  /**
70745
70752
  *
@@ -71068,6 +71075,7 @@ class Graph {
71068
71075
  /**
71069
71076
  *
71070
71077
  * @param {N} node
71078
+ * @returns {boolean}
71071
71079
  */
71072
71080
  removeNode(node) {
71073
71081
 
@@ -71141,7 +71149,7 @@ class Graph {
71141
71149
  }
71142
71150
 
71143
71151
  /**
71144
- *
71152
+ * Node degree is the number of attached edges
71145
71153
  * @param {N} node
71146
71154
  * @return {number}
71147
71155
  */
@@ -71155,6 +71163,14 @@ class Graph {
71155
71163
  return container.getEdgeCount();
71156
71164
  }
71157
71165
 
71166
+ /**
71167
+ *
71168
+ * @returns {N[]}
71169
+ */
71170
+ get nodes() {
71171
+ return Array.from(this.getNodes());
71172
+ }
71173
+
71158
71174
  /**
71159
71175
  * Do not modify this set directly
71160
71176
  * @return {Iterable<N>}
@@ -71175,13 +71191,18 @@ class Graph {
71175
71191
  *
71176
71192
  * @param {N} source
71177
71193
  * @param {N} target
71178
- * @param {EdgeDirectionType} [type] Undirected by default
71194
+ * @param {EdgeDirectionType} [direction] Undirected by default
71179
71195
  * @returns {Edge<N>}
71180
71196
  */
71181
- createEdge(source, target, type = EdgeDirectionType.Undirected) {
71197
+ createEdge(
71198
+ source,
71199
+ target,
71200
+ direction = EdgeDirectionType.Undirected
71201
+ ) {
71202
+
71182
71203
  const edge = new Edge(source, target);
71183
71204
 
71184
- edge.direction = type;
71205
+ edge.direction = direction;
71185
71206
 
71186
71207
  this.addEdge(edge);
71187
71208
 
@@ -71189,9 +71210,10 @@ class Graph {
71189
71210
  }
71190
71211
 
71191
71212
  /**
71192
- *
71213
+ * Both nodes that the edge is attached to must be present
71193
71214
  * @param {Edge<N>} edge
71194
- * @returns {boolean}
71215
+ * @returns {boolean} true if edge was added, false if edge was already present
71216
+ * @throws if one or both nodes are not contained in the graph
71195
71217
  */
71196
71218
  addEdge(edge) {
71197
71219
  if (this.hasEdge(edge)) {
@@ -71360,6 +71382,21 @@ class Graph {
71360
71382
  return edge_count;
71361
71383
  }
71362
71384
 
71385
+ /**
71386
+ *
71387
+ * @param {N} node
71388
+ * @returns {N[]}
71389
+ */
71390
+ getNeighbours(node) {
71391
+ const container = this.__nodes.get(node);
71392
+
71393
+ if (container === undefined) {
71394
+ return [];
71395
+ }
71396
+
71397
+ return container.neighbours;
71398
+ }
71399
+
71363
71400
  /**
71364
71401
  *
71365
71402
  * @param {N} node
@@ -71378,10 +71415,10 @@ class Graph {
71378
71415
  }
71379
71416
 
71380
71417
  /**
71381
- *
71418
+ * Find a path through the graph
71382
71419
  * @param {N} start
71383
71420
  * @param {N} goal
71384
- * @returns {null|N[]}
71421
+ * @returns {null|N[]} null if no path exists
71385
71422
  */
71386
71423
  findPath(start, goal) {
71387
71424
  const start_node_container = this.__nodes.get(start);
@@ -71421,6 +71458,7 @@ class Graph {
71421
71458
  const b = edge.second;
71422
71459
 
71423
71460
  let other = null;
71461
+
71424
71462
  if (a === current_node && (edge.direction === EdgeDirectionType.Forward || edge.direction === EdgeDirectionType.Undirected)) {
71425
71463
  other = b;
71426
71464
  } else if (b === current_node && (edge.direction === EdgeDirectionType.Backward || edge.direction === EdgeDirectionType.Undirected)) {
@@ -71449,6 +71487,9 @@ class Graph {
71449
71487
  return null;
71450
71488
  }
71451
71489
 
71490
+ /**
71491
+ * Remove all data from the graph, resetting it to empty state
71492
+ */
71452
71493
  clear() {
71453
71494
  this.__nodes.clear();
71454
71495
  this.__edges.clear();
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.77.0",
8
+ "version": "2.78.1",
9
9
  "main": "build/meep.module.js",
10
10
  "module": "build/meep.module.js",
11
11
  "exports": {
@@ -1,8 +1,8 @@
1
- import { Graph } from "./v2/Graph.js";
2
- import { MultiNode } from "./MultiNode.js";
3
- import { compute_face_connection_weight } from "../geom/3d/topology/util/compute_face_connection_weight.js";
4
- import { WeightedEdge } from "./WeightedEdge.js";
5
- import { graph_compute_disconnected_clusters } from "./graph_compute_disconnected_clusters.js";
1
+ import { graph_compute_disconnected_clusters } from "../../../graph/graph_compute_disconnected_clusters.js";
2
+ import { MultiNode } from "../../../graph/MultiNode.js";
3
+ import { Graph } from "../../../graph/v2/Graph.js";
4
+ import { WeightedEdge } from "../../../graph/WeightedEdge.js";
5
+ import { compute_face_connection_weight } from "./util/compute_face_connection_weight.js";
6
6
 
7
7
 
8
8
  /**
@@ -55,10 +55,19 @@ export class Edge {
55
55
  return this.first === node || this.second === node;
56
56
  }
57
57
 
58
+ /**
59
+ *
60
+ * @param {N} source
61
+ * @param {N} target
62
+ * @returns {boolean} True iff the edge contains both source and target and allows transition from source to target
63
+ */
58
64
  validateTransition(source, target) {
59
65
  const a = this.first;
60
66
  const b = this.second;
61
- return (a === source && b === target && this.traversableForward()) || (b === source && a === target && this.traversableBackward());
67
+
68
+ return (a === source && b === target && this.traversableForward())
69
+ || (b === source && a === target && this.traversableBackward())
70
+ ;
62
71
  }
63
72
 
64
73
  /**
@@ -106,17 +115,6 @@ export class Edge {
106
115
  || (this.second === node && this.direction === EdgeDirectionType.Backward)
107
116
  }
108
117
 
109
- /**
110
- * @deprecated
111
- * @returns {number}
112
- */
113
- angle() {
114
- console.error('method is deprecated, do not use');
115
-
116
- const delta = this.second.clone().sub(this.first);
117
- return Math.atan2(delta.y, delta.x);
118
- }
119
-
120
118
  /**
121
119
  *
122
120
  * @returns {N[]}
@@ -125,16 +123,6 @@ export class Edge {
125
123
  return [this.first, this.second];
126
124
  }
127
125
 
128
-
129
- /**
130
- * @deprecated
131
- * @returns {number}
132
- */
133
- get length() {
134
- console.error('method is deprecated, do not use');
135
-
136
- return this.first.distanceTo(this.second);
137
- }
138
126
  }
139
127
 
140
128
  /**
@@ -48,3 +48,38 @@ test('other', () => {
48
48
  expect(edge.other(3)).toBe(7);
49
49
  expect(edge.other(7)).toBe(3);
50
50
  });
51
+
52
+
53
+ test("isDirectedTowards", () => {
54
+ const e = new Edge(1, 3);
55
+
56
+ e.direction = EdgeDirectionType.Forward;
57
+
58
+ expect(e.isDirectedTowards(3)).toBe(true);
59
+ expect(e.isDirectedTowards(1)).toBe(false);
60
+
61
+ e.direction = EdgeDirectionType.Backward;
62
+
63
+ expect(e.isDirectedTowards(3)).toBe(false);
64
+ expect(e.isDirectedTowards(1)).toBe(true);
65
+ });
66
+
67
+ test("isDirectedAwayFrom", () => {
68
+ const e = new Edge(1, 3);
69
+
70
+ e.direction = EdgeDirectionType.Forward;
71
+
72
+ expect(e.isDirectedAwayFrom(3)).toBe(false);
73
+ expect(e.isDirectedAwayFrom(1)).toBe(true);
74
+
75
+ e.direction = EdgeDirectionType.Backward;
76
+
77
+ expect(e.isDirectedAwayFrom(3)).toBe(true);
78
+ expect(e.isDirectedAwayFrom(1)).toBe(false);
79
+ });
80
+
81
+ test("nodes accessor", () => {
82
+ const e = new Edge(1, 3);
83
+
84
+ expect(e.nodes).toEqual([1, 3]);
85
+ });
@@ -1,14 +1,13 @@
1
1
  /**
2
+ * A grouping node, intended mainly for meta-graphs, or hierarchical graphs
2
3
  * @template T
3
4
  */
4
5
  export class MultiNode {
5
- constructor() {
6
- /**
7
- *
8
- * @type {T[]}
9
- */
10
- this.source_nodes = [];
11
- }
6
+ /**
7
+ *
8
+ * @type {T[]}
9
+ */
10
+ source_nodes = [];
12
11
 
13
12
  /**
14
13
  *
@@ -1,4 +1,4 @@
1
- import Graph from "../Graph.js";
1
+ import { Graph } from "../v2/Graph.js";
2
2
  import { colorizeGraphGreedy } from "./colorizeGraphGreedy.js";
3
3
 
4
4
  test('empty graph', () => {
@@ -1,21 +1,16 @@
1
- /**
2
- *
3
- * @param {Array.<Circle>} input
4
- * @param {Graph} graph
5
- */
6
1
  import { assert } from "../../assert.js";
7
- import Circle from "../../geom/2d/circle/Circle.js";
8
2
  import AABB2 from "../../geom/2d/aabb/AABB2.js";
3
+ import Circle from "../../geom/2d/circle/Circle.js";
4
+ import {
5
+ line_segment_line_segment_intersection_exists_2d
6
+ } from "../../geom/2d/line/line_segment_line_segment_intersection_exists_2d.js";
9
7
  import Vector2, { v2_distance } from "../../geom/Vector2.js";
10
8
  import { max2 } from "../../math/max2.js";
11
9
  import { min2 } from "../../math/min2.js";
10
+ import { applyCentralGravityAABB2 } from "./box/applyCentralGravityAABB2.js";
11
+ import { resolveAABB2Overlap } from "./box/resolveAABB2Overlap.js";
12
12
  import { computeDisconnectedSubGraphs } from "./computeDisconnectedSubGraphs.js";
13
13
  import { Connection } from "./Connection.js";
14
- import { resolveAABB2Overlap } from "./box/resolveAABB2Overlap.js";
15
- import { applyCentralGravityAABB2 } from "./box/applyCentralGravityAABB2.js";
16
- import {
17
- line_segment_line_segment_intersection_exists_2d
18
- } from "../../geom/2d/line/line_segment_line_segment_intersection_exists_2d.js";
19
14
 
20
15
 
21
16
  /**
@@ -92,6 +92,7 @@ export class Graph {
92
92
  /**
93
93
  *
94
94
  * @param {N} node
95
+ * @returns {boolean}
95
96
  */
96
97
  removeNode(node) {
97
98
 
@@ -165,7 +166,7 @@ export class Graph {
165
166
  }
166
167
 
167
168
  /**
168
- *
169
+ * Node degree is the number of attached edges
169
170
  * @param {N} node
170
171
  * @return {number}
171
172
  */
@@ -179,6 +180,14 @@ export class Graph {
179
180
  return container.getEdgeCount();
180
181
  }
181
182
 
183
+ /**
184
+ *
185
+ * @returns {N[]}
186
+ */
187
+ get nodes() {
188
+ return Array.from(this.getNodes());
189
+ }
190
+
182
191
  /**
183
192
  * Do not modify this set directly
184
193
  * @return {Iterable<N>}
@@ -199,13 +208,19 @@ export class Graph {
199
208
  *
200
209
  * @param {N} source
201
210
  * @param {N} target
202
- * @param {EdgeDirectionType} [type] Undirected by default
211
+ * @param {EdgeDirectionType} [direction] Undirected by default
203
212
  * @returns {Edge<N>}
204
213
  */
205
- createEdge(source, target, type = EdgeDirectionType.Undirected) {
214
+ createEdge(
215
+ source,
216
+ target,
217
+ direction = EdgeDirectionType.Undirected
218
+ ) {
219
+ assert.enum(direction, EdgeDirectionType, 'direction');
220
+
206
221
  const edge = new Edge(source, target);
207
222
 
208
- edge.direction = type;
223
+ edge.direction = direction;
209
224
 
210
225
  this.addEdge(edge);
211
226
 
@@ -213,9 +228,10 @@ export class Graph {
213
228
  }
214
229
 
215
230
  /**
216
- *
231
+ * Both nodes that the edge is attached to must be present
217
232
  * @param {Edge<N>} edge
218
- * @returns {boolean}
233
+ * @returns {boolean} true if edge was added, false if edge was already present
234
+ * @throws if one or both nodes are not contained in the graph
219
235
  */
220
236
  addEdge(edge) {
221
237
  if (this.hasEdge(edge)) {
@@ -390,6 +406,21 @@ export class Graph {
390
406
  return edge_count;
391
407
  }
392
408
 
409
+ /**
410
+ *
411
+ * @param {N} node
412
+ * @returns {N[]}
413
+ */
414
+ getNeighbours(node) {
415
+ const container = this.__nodes.get(node);
416
+
417
+ if (container === undefined) {
418
+ return [];
419
+ }
420
+
421
+ return container.neighbours;
422
+ }
423
+
393
424
  /**
394
425
  *
395
426
  * @param {N} node
@@ -408,10 +439,10 @@ export class Graph {
408
439
  }
409
440
 
410
441
  /**
411
- *
442
+ * Find a path through the graph
412
443
  * @param {N} start
413
444
  * @param {N} goal
414
- * @returns {null|N[]}
445
+ * @returns {null|N[]} null if no path exists
415
446
  */
416
447
  findPath(start, goal) {
417
448
  const start_node_container = this.__nodes.get(start);
@@ -451,6 +482,7 @@ export class Graph {
451
482
  const b = edge.second;
452
483
 
453
484
  let other = null;
485
+
454
486
  if (a === current_node && (edge.direction === EdgeDirectionType.Forward || edge.direction === EdgeDirectionType.Undirected)) {
455
487
  other = b;
456
488
  } else if (b === current_node && (edge.direction === EdgeDirectionType.Backward || edge.direction === EdgeDirectionType.Undirected)) {
@@ -479,6 +511,9 @@ export class Graph {
479
511
  return null;
480
512
  }
481
513
 
514
+ /**
515
+ * Remove all data from the graph, resetting it to empty state
516
+ */
482
517
  clear() {
483
518
  this.__nodes.clear();
484
519
  this.__edges.clear();
@@ -22,10 +22,19 @@ export class NodeContainer {
22
22
  /**
23
23
  *
24
24
  * @type {Map<N,number>}
25
+ * Maps neighbour node to number of edges to that node from this one
25
26
  * @private
26
27
  */
27
28
  __neighbors = new Map();
28
29
 
30
+ /**
31
+ * NOTE: this method allocates memory internally
32
+ * @returns {N[]}
33
+ */
34
+ get neighbours() {
35
+ return Array.from(this.__neighbors.keys());
36
+ }
37
+
29
38
  /**
30
39
  *
31
40
  * @return {number}
@@ -43,7 +52,7 @@ export class NodeContainer {
43
52
  }
44
53
 
45
54
  /**
46
- *
55
+ * NOTE: this method allocates memory internally
47
56
  * @returns {N[]}
48
57
  */
49
58
  get inNodes() {
@@ -51,7 +60,7 @@ export class NodeContainer {
51
60
  }
52
61
 
53
62
  /**
54
- *
63
+ * NOTE: this method allocates memory internally
55
64
  * @returns {N[]}
56
65
  */
57
66
  get outNodes() {
@@ -59,6 +68,10 @@ export class NodeContainer {
59
68
  }
60
69
 
61
70
 
71
+ /**
72
+ * NOTE: this method allocates memory internally
73
+ * @returns {Edge<N>[]}
74
+ */
62
75
  get outEdges() {
63
76
  /**
64
77
  *
@@ -71,6 +84,10 @@ export class NodeContainer {
71
84
  return result;
72
85
  }
73
86
 
87
+ /**
88
+ * NOTE: this method allocates memory internally
89
+ * @returns {Edge<N>[]}
90
+ */
74
91
  get inEdges() {
75
92
  /**
76
93
  *
@@ -1,11 +0,0 @@
1
- /**
2
- *
3
- * @enum {number}
4
- */
5
- const EdgeDirection = {
6
- Out: 0,
7
- In: 1
8
- };
9
-
10
-
11
- export default EdgeDirection;