@woosh/meep-engine 2.76.4 → 2.78.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 +236 -616
- package/build/meep.min.js +1 -1
- package/build/meep.module.js +236 -616
- 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/SquareMatrix.js +4 -2
- package/src/core/graph/WeightedEdge.js +5 -9
- package/src/core/graph/coloring/colorizeGraphGreedy.spec.js +1 -1
- 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/layout/CircleLayout.js +6 -11
- package/src/core/graph/v2/Graph.js +39 -9
- package/src/core/graph/v2/NodeContainer.js +136 -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 +25 -22
- 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/Graph.js +0 -564
- 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,29 +1,37 @@
|
|
|
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
|
-
* @type {N}
|
|
11
|
-
*/
|
|
12
|
-
this.node = null;
|
|
13
|
+
node = null;
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Attached edges
|
|
17
|
+
* @type {Edge<N>[]}
|
|
18
|
+
* @private
|
|
19
|
+
*/
|
|
20
|
+
__edges = [];
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
/**
|
|
23
|
+
*
|
|
24
|
+
* @type {Map<N,number>}
|
|
25
|
+
* @private
|
|
26
|
+
*/
|
|
27
|
+
__neighbors = new Map();
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* NOTE: this method allocates memory internally
|
|
31
|
+
* @returns {N[]}
|
|
32
|
+
*/
|
|
33
|
+
get neighbours() {
|
|
34
|
+
return Array.from(this.__neighbors.keys());
|
|
27
35
|
}
|
|
28
36
|
|
|
29
37
|
/**
|
|
@@ -42,6 +50,110 @@ export class NodeContainer {
|
|
|
42
50
|
return this.__edges;
|
|
43
51
|
}
|
|
44
52
|
|
|
53
|
+
/**
|
|
54
|
+
* NOTE: this method allocates memory internally
|
|
55
|
+
* @returns {N[]}
|
|
56
|
+
*/
|
|
57
|
+
get inNodes() {
|
|
58
|
+
return this.inEdges.map(e => e.other(this.node));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* NOTE: this method allocates memory internally
|
|
63
|
+
* @returns {N[]}
|
|
64
|
+
*/
|
|
65
|
+
get outNodes() {
|
|
66
|
+
return this.outEdges.map(e => e.other(this.node));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* NOTE: this method allocates memory internally
|
|
72
|
+
* @returns {Edge<N>[]}
|
|
73
|
+
*/
|
|
74
|
+
get outEdges() {
|
|
75
|
+
/**
|
|
76
|
+
*
|
|
77
|
+
* @type {Edge<N>[]}
|
|
78
|
+
*/
|
|
79
|
+
const result = [];
|
|
80
|
+
|
|
81
|
+
this.getOutgoingEdges(result);
|
|
82
|
+
|
|
83
|
+
return result;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* NOTE: this method allocates memory internally
|
|
88
|
+
* @returns {Edge<N>[]}
|
|
89
|
+
*/
|
|
90
|
+
get inEdges() {
|
|
91
|
+
/**
|
|
92
|
+
*
|
|
93
|
+
* @type {Edge<N>[]}
|
|
94
|
+
*/
|
|
95
|
+
const result = [];
|
|
96
|
+
|
|
97
|
+
this.getIncomingEdges(result);
|
|
98
|
+
|
|
99
|
+
return result;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
*
|
|
105
|
+
* @param {Edge<N>[]} result
|
|
106
|
+
* @returns {number}
|
|
107
|
+
*/
|
|
108
|
+
getIncomingEdges(result) {
|
|
109
|
+
const edges = this.__edges;
|
|
110
|
+
|
|
111
|
+
const edge_count = edges.length;
|
|
112
|
+
|
|
113
|
+
let result_count = 0;
|
|
114
|
+
|
|
115
|
+
for (let i = 0; i < edge_count; i++) {
|
|
116
|
+
const edge = edges[i];
|
|
117
|
+
|
|
118
|
+
if (edge.isDirectedTowards(this.node)) {
|
|
119
|
+
|
|
120
|
+
result.push(edge);
|
|
121
|
+
result_count++;
|
|
122
|
+
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return result_count;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
*
|
|
132
|
+
* @param {Edge<N>[]} result
|
|
133
|
+
* @returns {number}
|
|
134
|
+
*/
|
|
135
|
+
getOutgoingEdges(result) {
|
|
136
|
+
const edges = this.__edges;
|
|
137
|
+
|
|
138
|
+
const edge_count = edges.length;
|
|
139
|
+
|
|
140
|
+
let result_count = 0;
|
|
141
|
+
|
|
142
|
+
for (let i = 0; i < edge_count; i++) {
|
|
143
|
+
const edge = edges[i];
|
|
144
|
+
|
|
145
|
+
if (edge.isDirectedAwayFrom(this.node)) {
|
|
146
|
+
|
|
147
|
+
result.push(edge);
|
|
148
|
+
result_count++;
|
|
149
|
+
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return result_count;
|
|
155
|
+
}
|
|
156
|
+
|
|
45
157
|
/**
|
|
46
158
|
*
|
|
47
159
|
* @return {number}
|
|
@@ -52,12 +164,14 @@ export class NodeContainer {
|
|
|
52
164
|
const edges = this.__edges;
|
|
53
165
|
const edge_count = edges.length;
|
|
54
166
|
|
|
167
|
+
const current_node = this.node;
|
|
168
|
+
|
|
55
169
|
for (let i = 0; i < edge_count; i++) {
|
|
56
170
|
const edge = edges[i];
|
|
57
171
|
|
|
58
172
|
if (
|
|
59
|
-
(edge.first ===
|
|
60
|
-
|| (edge.second ===
|
|
173
|
+
(edge.first === current_node && edge.direction === EdgeDirectionType.Forward)
|
|
174
|
+
|| (edge.second === current_node && edge.direction === EdgeDirectionType.Backward)
|
|
61
175
|
|
|
62
176
|
) {
|
|
63
177
|
r++;
|
|
@@ -81,7 +195,7 @@ export class NodeContainer {
|
|
|
81
195
|
|
|
82
196
|
/**
|
|
83
197
|
*
|
|
84
|
-
* @param {function(Edge)} visitor
|
|
198
|
+
* @param {function(Edge<N>)} visitor
|
|
85
199
|
* @param {*} [thisArg]
|
|
86
200
|
* @returns {number}
|
|
87
201
|
*/
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { assert } from "../../../../core/assert.js";
|
|
2
|
-
import { Graph } from "../../../../core/graph/Graph.js";
|
|
2
|
+
import { Graph } from "../../../../core/graph/v2/Graph.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Contains serializers for various data types as well as data upgraders which enable support for serialization format changes
|
|
@@ -39,25 +39,27 @@ export class BinarySerializationRegistry {
|
|
|
39
39
|
assert.defined(adapter, 'adapter');
|
|
40
40
|
assert.ok(adapter.isBinaryClassSerializationAdapter, 'adapter is not a BinaryClassSerializationAdapter');
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
let _className = className;
|
|
43
|
+
|
|
44
|
+
if (_className === undefined) {
|
|
43
45
|
const klass = adapter.getClass();
|
|
44
46
|
|
|
45
47
|
if (typeof klass.typeName === "string") {
|
|
46
|
-
|
|
48
|
+
_className = klass.typeName;
|
|
47
49
|
} else {
|
|
48
50
|
throw new Error(`className not specified, could not infer class name from the class itself`);
|
|
49
51
|
}
|
|
50
52
|
}
|
|
51
53
|
|
|
52
|
-
if (this.serializers.has(
|
|
54
|
+
if (this.serializers.has(_className)) {
|
|
53
55
|
//a serializer already exists
|
|
54
56
|
|
|
55
|
-
console.warn(`Serializer for class '${
|
|
57
|
+
console.warn(`Serializer for class '${_className}' already exists, ignoring request`);
|
|
56
58
|
|
|
57
59
|
return false;
|
|
58
60
|
}
|
|
59
61
|
|
|
60
|
-
this.serializers.set(
|
|
62
|
+
this.serializers.set(_className, adapter);
|
|
61
63
|
|
|
62
64
|
return true;
|
|
63
65
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { assert } from "../../../../../../core/assert.js";
|
|
2
|
-
import Graph from "../../../../../../core/graph/Graph.js";
|
|
3
2
|
import { Edge, EdgeDirectionType } from "../../../../../../core/graph/Edge.js";
|
|
3
|
+
import { Graph } from "../../../../../../core/graph/v2/Graph.js";
|
|
4
4
|
import { FunctionModuleReference } from "./FunctionModuleReference.js";
|
|
5
5
|
|
|
6
6
|
export class FunctionModuleRegistry {
|
|
@@ -26,7 +26,7 @@ function index2point(result, index, width) {
|
|
|
26
26
|
* @param {number} height
|
|
27
27
|
* @returns {number}
|
|
28
28
|
*/
|
|
29
|
-
function
|
|
29
|
+
function compute_neighbors(result, index, width, height) {
|
|
30
30
|
const x = index % width;
|
|
31
31
|
const y = (index / width) | 0;
|
|
32
32
|
|
|
@@ -36,14 +36,17 @@ function computeNeighbors(result, index, width, height) {
|
|
|
36
36
|
result[neighbour_count] = index - width;
|
|
37
37
|
neighbour_count++
|
|
38
38
|
}
|
|
39
|
+
|
|
39
40
|
if (x > 0) {
|
|
40
41
|
result[neighbour_count] = index - 1;
|
|
41
42
|
neighbour_count++;
|
|
42
43
|
}
|
|
44
|
+
|
|
43
45
|
if (x < width - 1) {
|
|
44
46
|
result[neighbour_count] = index + 1;
|
|
45
47
|
neighbour_count++;
|
|
46
48
|
}
|
|
49
|
+
|
|
47
50
|
if (y < height - 1) {
|
|
48
51
|
result[neighbour_count] = index + width;
|
|
49
52
|
neighbour_count++
|
|
@@ -60,7 +63,7 @@ function computeNeighbors(result, index, width, height) {
|
|
|
60
63
|
* @param {number} height
|
|
61
64
|
* @returns {number[]}
|
|
62
65
|
*/
|
|
63
|
-
function
|
|
66
|
+
function compute_path(node, g_score, width, height) {
|
|
64
67
|
let v_previous = new Vector2(-1, -1);
|
|
65
68
|
let v_current = new Vector2();
|
|
66
69
|
|
|
@@ -111,7 +114,7 @@ function pathTo(node, g_score, width, height) {
|
|
|
111
114
|
v_current = t;
|
|
112
115
|
|
|
113
116
|
// find next point
|
|
114
|
-
const neighbour_count =
|
|
117
|
+
const neighbour_count = compute_neighbors(neighbors, current, width, height);
|
|
115
118
|
|
|
116
119
|
current = -1;
|
|
117
120
|
|
|
@@ -190,16 +193,16 @@ closed.preventShrink();
|
|
|
190
193
|
* @param {number} height
|
|
191
194
|
* @param {number} start
|
|
192
195
|
* @param {number} goal
|
|
193
|
-
* @param {number}
|
|
194
|
-
* @param {number}
|
|
196
|
+
* @param {number} crossing_penalty
|
|
197
|
+
* @param {number} block_value value in the field that signifies impassible obstacle
|
|
195
198
|
* @returns {Array.<number>} array of indices representing path from start to end
|
|
196
199
|
*/
|
|
197
200
|
export function find_path_on_grid_astar(
|
|
198
201
|
field,
|
|
199
202
|
width, height,
|
|
200
203
|
start, goal,
|
|
201
|
-
|
|
202
|
-
|
|
204
|
+
crossing_penalty,
|
|
205
|
+
block_value
|
|
203
206
|
) {
|
|
204
207
|
|
|
205
208
|
assert.defined(field, 'field');
|
|
@@ -208,8 +211,8 @@ export function find_path_on_grid_astar(
|
|
|
208
211
|
assert.isNonNegativeInteger(start, "start");
|
|
209
212
|
assert.isNonNegativeInteger(goal, "goal");
|
|
210
213
|
|
|
211
|
-
assert.isNumber(
|
|
212
|
-
assert.isNumber(
|
|
214
|
+
assert.isNumber(crossing_penalty, 'crossingPenalty');
|
|
215
|
+
assert.isNumber(block_value, 'blockValue');
|
|
213
216
|
|
|
214
217
|
// prepare sets
|
|
215
218
|
open.clear();
|
|
@@ -232,15 +235,15 @@ export function find_path_on_grid_astar(
|
|
|
232
235
|
const currentNode = open.pop_min();
|
|
233
236
|
|
|
234
237
|
if (currentNode === goal) {
|
|
235
|
-
// End case
|
|
236
|
-
return
|
|
238
|
+
// End case - result has been found, return the traced path.
|
|
239
|
+
return compute_path(currentNode, g_score, width, height);
|
|
237
240
|
}
|
|
238
241
|
|
|
239
242
|
// Normal case -- move currentNode from open to closed, process each of its neighbors.
|
|
240
243
|
closed.set(currentNode, true);
|
|
241
244
|
|
|
242
245
|
// Find all neighbors for the current node.
|
|
243
|
-
const neighbour_count =
|
|
246
|
+
const neighbour_count = compute_neighbors(neighbors, currentNode, width, height);
|
|
244
247
|
|
|
245
248
|
for (let i = 0; i < neighbour_count; ++i) {
|
|
246
249
|
const neighbor = neighbors[i];
|
|
@@ -252,39 +255,39 @@ export function find_path_on_grid_astar(
|
|
|
252
255
|
|
|
253
256
|
// The g score is the shortest distance from start to current node.
|
|
254
257
|
// We need to check if the path we have arrived at this neighbor is the shortest one we have seen yet.
|
|
255
|
-
const
|
|
258
|
+
const neighbor_value = field[neighbor];
|
|
256
259
|
|
|
257
|
-
if (
|
|
260
|
+
if (neighbor_value === block_value) {
|
|
258
261
|
//cell is blocked, close and continue
|
|
259
262
|
closed.set(neighbor, true);
|
|
260
263
|
continue;
|
|
261
264
|
}
|
|
262
265
|
|
|
263
266
|
// Cost of traversing to this neighbour
|
|
264
|
-
const transition_cost =
|
|
267
|
+
const transition_cost = neighbor_value * crossing_penalty + 1;
|
|
265
268
|
|
|
266
269
|
// updated path cost
|
|
267
|
-
const
|
|
270
|
+
const cost_so_far = g_score[currentNode] + transition_cost;
|
|
268
271
|
|
|
269
272
|
const index_in_open_set = open.find_index_by_id(neighbor);
|
|
270
273
|
|
|
271
274
|
const not_in_open_set = index_in_open_set === -1;
|
|
272
275
|
|
|
273
|
-
if (not_in_open_set ||
|
|
276
|
+
if (not_in_open_set || cost_so_far < g_score[neighbor]) {
|
|
274
277
|
|
|
275
278
|
// update refined score
|
|
276
|
-
g_score[neighbor] =
|
|
279
|
+
g_score[neighbor] = cost_so_far;
|
|
277
280
|
|
|
278
|
-
const
|
|
281
|
+
const remaining_heuristic = heuristic(neighbor, goal, width);
|
|
279
282
|
|
|
280
|
-
const
|
|
283
|
+
const refined_heuristic = cost_so_far + remaining_heuristic;
|
|
281
284
|
|
|
282
285
|
if (not_in_open_set) {
|
|
283
286
|
// Pushing to heap will put it in proper place based on the 'f' value.
|
|
284
|
-
open.insert(neighbor,
|
|
287
|
+
open.insert(neighbor, refined_heuristic);
|
|
285
288
|
} else {
|
|
286
289
|
// Already seen the node, but since it has been re-scored we need to reorder it in the heap
|
|
287
|
-
open.__update_score_by_index(index_in_open_set,
|
|
290
|
+
open.__update_score_by_index(index_in_open_set, refined_heuristic);
|
|
288
291
|
}
|
|
289
292
|
}
|
|
290
293
|
}
|
|
@@ -36,7 +36,7 @@ test("path on open 3x3 grid", () => {
|
|
|
36
36
|
expect(path).toEqual([0, 3, 5, 8]);
|
|
37
37
|
});
|
|
38
38
|
|
|
39
|
-
test
|
|
39
|
+
test("performance, 256x256 random", () => {
|
|
40
40
|
const FIELD_SIZE = 256;
|
|
41
41
|
|
|
42
42
|
const field = new Uint8Array(FIELD_SIZE * FIELD_SIZE);
|
|
@@ -45,7 +45,7 @@ test.skip("performance, 256x256 random", () => {
|
|
|
45
45
|
|
|
46
46
|
const last_field_index = field.length - 1;
|
|
47
47
|
|
|
48
|
-
for (let i = 0; i < field.length * 0.
|
|
48
|
+
for (let i = 0; i < field.length * 0.15; i++) {
|
|
49
49
|
const index = randomIntegerBetween(random, 0, last_field_index);
|
|
50
50
|
|
|
51
51
|
field[index] = 255;
|
|
@@ -1,46 +1,30 @@
|
|
|
1
|
+
import { GridTags } from "../../../../../samples/generation/grid/GridTags.js";
|
|
2
|
+
import { MirGridLayers } from "../../../../../samples/generation/grid/MirGridLayers.js";
|
|
3
|
+
import { matcher_tag_traversable } from "../../../../../samples/generation/rules/matcher_tag_traversable.js";
|
|
4
|
+
import { BitSet } from "../../../../core/binary/BitSet.js";
|
|
5
|
+
import { groupArrayBy } from "../../../../core/collection/array/groupArrayBy.js";
|
|
6
|
+
import { collectIteratorValueToArray } from "../../../../core/collection/collectIteratorValueToArray.js";
|
|
7
|
+
import BinaryHeap from "../../../../core/collection/heap/FastBinaryHeap.js";
|
|
8
|
+
import { QuadTreeNode } from "../../../../core/geom/2d/quad-tree/QuadTreeNode.js";
|
|
9
|
+
import { Graph } from "../../../../core/graph/v2/Graph.js";
|
|
1
10
|
import { seededRandom } from "../../../../core/math/random/seededRandom.js";
|
|
2
|
-
import {
|
|
11
|
+
import { remap } from "../../../../core/math/remap.js";
|
|
3
12
|
import TaskGroup from "../../../../core/process/task/TaskGroup.js";
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import { BitSet } from "../../../../core/binary/BitSet.js";
|
|
7
|
-
import { matcher_tag_traversable } from "../../../../../samples/generation/rules/matcher_tag_traversable.js";
|
|
8
|
-
import { buildPathFromDistanceMap } from "../util/buildPathFromDistanceMap.js";
|
|
13
|
+
import { actionTask } from "../../../../core/process/task/util/actionTask.js";
|
|
14
|
+
import { countTask } from "../../../../core/process/task/util/countTask.js";
|
|
9
15
|
import { GridCellActionPlaceTags } from "../../../placement/action/GridCellActionPlaceTags.js";
|
|
10
|
-
import { GridTags } from "../../../../../samples/generation/grid/GridTags.js";
|
|
11
16
|
import { CellMatcher } from "../../../rules/CellMatcher.js";
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import
|
|
17
|
+
import { CellMatcherNot } from "../../../rules/logic/CellMatcherNot.js";
|
|
18
|
+
import { GridTaskGenerator } from "../../GridTaskGenerator.js";
|
|
19
|
+
import { buildPathFromDistanceMap } from "../util/buildPathFromDistanceMap.js";
|
|
20
|
+
import { buildUnsignedDistanceField } from "../util/buildUnsignedDistanceField.js";
|
|
15
21
|
import { PathEndPoint } from "./PathEndPoint.js";
|
|
16
|
-
import { RoadConnection } from "./RoadConnection.js";
|
|
17
22
|
import { readMarkerNodeGroupId } from "./readMarkerNodeGroupId.js";
|
|
18
|
-
import {
|
|
19
|
-
import { CellMatcherNot } from "../../../rules/logic/CellMatcherNot.js";
|
|
23
|
+
import { RoadConnection } from "./RoadConnection.js";
|
|
20
24
|
import { RoadConnectionNetwork } from "./RoadConnectionNetwork.js";
|
|
21
|
-
import { MirGridLayers } from "../../../../../samples/generation/grid/MirGridLayers.js";
|
|
22
|
-
import { actionTask } from "../../../../core/process/task/util/actionTask.js";
|
|
23
|
-
import { countTask } from "../../../../core/process/task/util/countTask.js";
|
|
24
|
-
import { groupArrayBy } from "../../../../core/collection/array/groupArrayBy.js";
|
|
25
|
-
import { remap } from "../../../../core/math/remap.js";
|
|
26
25
|
|
|
27
26
|
const NODE_TYPE_ROAD_CONNECTOR = 'Road Connector';
|
|
28
27
|
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
*
|
|
32
|
-
* @param {QuadTreeNode} tree
|
|
33
|
-
* @param {RoadConnection} path
|
|
34
|
-
* @param {number} gridWidth
|
|
35
|
-
*/
|
|
36
|
-
function addPathToQuadTree(tree, path, gridWidth) {
|
|
37
|
-
const bounds = new AABB2();
|
|
38
|
-
|
|
39
|
-
path.computeBounds(bounds, gridWidth);
|
|
40
|
-
|
|
41
|
-
tree.add(path, bounds.x0, bounds.y0, bounds.x1, bounds.y1);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
28
|
/**
|
|
45
29
|
*
|
|
46
30
|
* @param {MarkerNode[]} array
|