@woosh/meep-engine 2.71.0 → 2.73.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.
Files changed (37) hide show
  1. package/build/bundle-worker-terrain.js +1 -1
  2. package/build/meep.cjs +36 -187
  3. package/build/meep.min.js +1 -1
  4. package/build/meep.module.js +36 -187
  5. package/package.json +3 -2
  6. package/src/core/collection/array/array_get_index_in_range.js +1 -1
  7. package/src/core/collection/array/array_swap.js +2 -2
  8. package/src/core/geom/3d/v3_compute_triangle_normal.js +7 -1
  9. package/src/core/geom/vec3/v3_normalize_array.js +27 -0
  10. package/src/engine/ecs/terrain/BufferedGeometryArraysBuilder.js +2 -2
  11. package/src/engine/graphics/ecs/camera/FrustumProjector.js +31 -182
  12. package/src/engine/graphics/geometry/buffered/ComputeNormals.js +11 -26
  13. package/src/engine/graphics/texture/virtual/v2/NOTES.md +27 -0
  14. package/src/engine/graphics/texture/virtual/v2/ShaderUsage.js +51 -26
  15. package/src/engine/graphics/texture/virtual/v2/SparseTexture.js +182 -0
  16. package/src/engine/graphics/texture/virtual/v2/TextureTile.js +31 -0
  17. package/src/engine/graphics/texture/virtual/v2/TileLoader.js +215 -0
  18. package/src/engine/graphics/texture/virtual/v2/UsageDebugView.js +64 -0
  19. package/src/engine/graphics/texture/virtual/v2/UsageMetadata.js +153 -0
  20. package/src/engine/graphics/texture/virtual/v2/UsagePyramidDebugView.js +252 -0
  21. package/src/engine/graphics/texture/virtual/v2/VirtualTextureManager.js +257 -0
  22. package/src/engine/graphics/texture/virtual/v2/compose_finger_print.js +13 -0
  23. package/src/engine/graphics/texture/virtual/v2/finger_print_to_tile_index.js +37 -0
  24. package/src/engine/graphics/texture/virtual/v2/prototype.js +122 -31
  25. package/src/engine/graphics/texture/virtual/v2/tile_index_to_finger_print.js +31 -0
  26. package/src/core/geom/2d/quad-tree/PointQuadTree.js +0 -478
  27. package/src/core/math/random/makeRangedRandom.js +0 -19
  28. package/src/engine/ecs/terrain/TerrainGeometryBuilder.js +0 -152
  29. package/src/engine/ecs/terrain/ecs/PromiseSamplerHeight.js +0 -66
  30. package/src/engine/ecs/terrain/ecs/TerrainClassifier.js +0 -125
  31. package/src/engine/graphics/clouds/MaterialTransformer.js +0 -0
  32. package/src/engine/graphics/clouds/TerrainCloudsPlugin.js +0 -0
  33. package/src/engine/graphics/clouds/cs_build_fragment_shader.js +0 -0
  34. package/src/engine/graphics/clouds/cs_build_vertex_shader.js +0 -0
  35. package/src/engine/graphics/ecs/camera/TiltCameraController.js +0 -69
  36. package/src/engine/graphics/ecs/camera/is_valid_distance_value.js +0 -11
  37. package/src/engine/graphics/texture/sampler/SampleTraverser.js +0 -165
@@ -1,56 +1,125 @@
1
- import * as THREE from "three";
2
- import { fragment, vertex } from "./ShaderUsage.js";
1
+ import { GUI } from "dat.gui";
2
+ import {
3
+ AmbientLight,
4
+ Clock,
5
+ DirectionalLight,
6
+ Mesh,
7
+ MeshStandardMaterial,
8
+ PerspectiveCamera,
9
+ Scene,
10
+ TextureLoader,
11
+ TorusGeometry,
12
+ Vector2,
13
+ WebGLRenderer
14
+ } from "three";
3
15
  import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
16
+ import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
17
+ import EmptyView from "../../../../../view/elements/EmptyView.js";
18
+ import { AssetManager } from "../../../../asset/AssetManager.js";
19
+ import { GameAssetType } from "../../../../asset/GameAssetType.js";
20
+ import { ImageRGBADataLoader } from "../../../../asset/loaders/image/ImageRGBADataLoader.js";
21
+ import { SparseTexture } from "./SparseTexture.js";
22
+ import { UsageDebugView } from "./UsageDebugView.js";
23
+ import { VirtualTextureManager } from "./VirtualTextureManager.js";
24
+
25
+ let camera,
26
+ /**
27
+ * @type {WebGLRenderer}
28
+ */
29
+ renderer,
30
+ clock,
31
+ /**
32
+ * @type {Scene}
33
+ */
34
+ scene;
35
+
36
+ let mesh;
37
+
38
+ const am = new AssetManager();
39
+ am.registerLoader(GameAssetType.Image, new ImageRGBADataLoader());
40
+ am.startup();
41
+
42
+ const virtualTextureManager = new VirtualTextureManager();
43
+ virtualTextureManager.setTextureParameters(
44
+ // 2048,
45
+ 16384,
46
+ 128,
47
+ 3
48
+ );
49
+
50
+ const sparseTexture = new SparseTexture();
51
+ sparseTexture.page_texture_size = [1024, 1024];
52
+ sparseTexture.tile_resolution = virtualTextureManager.tile_resolution;
53
+ sparseTexture.asset_manager = am;
54
+
55
+ console.log(sparseTexture);
56
+
57
+ // const TEXTURE_URL = "data/textures/utility/uv_map_reference.png";
58
+ // const TEXTURE_URL = "data/textures/utility/4096x4096TexelDensityTexture1.png";
59
+ // const TEXTURE_URL = "data/textures/utility/Lenna.png";
60
+ // const TEXTURE_URL = "data/textures/utility/TESTIMAGES/SAMPLING/8BIT/RGB/2448x2448/SRC/img_2448x2448_3x8bit_SRC_RGB_cards_a.png";
61
+ const TEXTURE_URL = "data/models/LowPolyTownshipSet/Town_Hall//diffuse_2048.png";
62
+
63
+ const container_view = new EmptyView();
64
+ //
65
+ const usageDebugView = new UsageDebugView();
66
+ usageDebugView.mip_levels = virtualTextureManager.max_mip_level;
67
+ container_view.addChild(usageDebugView);
68
+
4
69
 
5
- let camera, renderer, clock, scene;
70
+ // const usagePyramidDebugView = new UsagePyramidDebugView();
71
+ // usagePyramidDebugView.setImageURL(TEXTURE_URL);
72
+ //
73
+ // container_view.addChild(usagePyramidDebugView);
6
74
 
7
- let uniforms, mesh;
75
+ const options = {
76
+ spin: true
77
+ };
8
78
 
9
79
  init();
10
80
  animate();
11
81
 
82
+
83
+ function makeTorus() {
84
+ const size = 0.65;
85
+ mesh = new Mesh(new TorusGeometry(size, 0.3, 30, 30), new MeshStandardMaterial({
86
+ roughness: 0.4,
87
+ map: new TextureLoader().load(TEXTURE_URL)
88
+ }));
89
+ mesh.rotation.x = 0.3;
90
+ }
91
+
12
92
  function init() {
13
93
 
14
94
  const container = document.body;
15
95
 
16
- camera = new THREE.PerspectiveCamera(35, window.innerWidth / window.innerHeight, 1, 3000);
17
- camera.position.z = 4;
96
+ container.style.margin = "0";
18
97
 
19
- scene = new THREE.Scene();
98
+ container.appendChild(container_view.el);
99
+ container_view.link();
20
100
 
21
- clock = new THREE.Clock();
101
+ camera = new PerspectiveCamera(35, window.innerWidth / window.innerHeight, 0.1, 300);
102
+ camera.position.z = 4;
22
103
 
23
- const textureLoader = new THREE.TextureLoader();
104
+ scene = new Scene();
24
105
 
25
- uniforms = {
26
- "u_mt_params": { value: new THREE.Vector2(0.1, 6) },
27
- /**
28
- * Format: VT_WIDTH, VT_HEIGHT, VT_TILE_SIZE, VT_ID
29
- * - VT_WIDTH : width of the virtual texture
30
- * - VT_HEIGHT : height of the virtual texture
31
- * - VT_TILE_SIZE : resolution of a single tile
32
- * - VT_ID : multiple different virtual textures may be used, this identifies current texture
33
- */
34
- "u_mt_tex": { value: new THREE.Vector4(16384, 16384, 256, 1) }
35
- };
106
+ clock = new Clock();
36
107
 
37
- const size = 0.65;
38
108
 
39
- const material = new THREE.ShaderMaterial({
109
+ new GLTFLoader().load("data/models/LowPolyTownshipSet/Town_Hall/model.gltf", (gltf) => {
40
110
 
41
- uniforms: uniforms,
42
- vertexShader: vertex(),
43
- fragmentShader: fragment()
111
+ mesh = gltf.scene;
112
+ scene.add(mesh);
44
113
 
45
114
  });
46
115
 
47
- mesh = new THREE.Mesh(new THREE.TorusGeometry(size, 0.3, 30, 30), material);
48
- mesh.rotation.x = 0.3;
49
- scene.add(mesh);
116
+ scene.add(new DirectionalLight(0xFFFFFF, 0.7));
117
+ scene.add(new AmbientLight(0xFFFFFF, 0.2));
118
+
50
119
 
51
120
  //
52
121
 
53
- renderer = new THREE.WebGLRenderer({ antialias: true });
122
+ renderer = new WebGLRenderer({ antialias: true });
54
123
  renderer.setPixelRatio(window.devicePixelRatio);
55
124
  container.appendChild(renderer.domElement);
56
125
  renderer.autoClear = false;
@@ -67,6 +136,14 @@ function init() {
67
136
 
68
137
  new OrbitControls(camera, renderer.domElement);
69
138
 
139
+
140
+ const gui = new GUI();
141
+
142
+ Object.keys(options).forEach(key => {
143
+ gui.add(options, key);
144
+ });
145
+
146
+
70
147
  }
71
148
 
72
149
  function onWindowResize() {
@@ -92,10 +169,24 @@ function render() {
92
169
 
93
170
  const delta = 5 * clock.getDelta();
94
171
 
95
- mesh.rotation.y += 0.0125 * delta;
96
- mesh.rotation.x += 0.05 * delta;
172
+ if (options.spin && mesh !== undefined) {
173
+ mesh.rotation.y += 0.0125 * delta;
174
+ mesh.rotation.x += 0.05 * delta;
175
+ }
176
+
177
+ const view_port_size = renderer.getSize(new Vector2());
178
+ view_port_size.multiplyScalar(renderer.getPixelRatio());
179
+
180
+
181
+ virtualTextureManager.setViewportResolution(view_port_size.x, view_port_size.y);
182
+ virtualTextureManager.updateUsage(renderer, scene, camera);
183
+ sparseTexture.update_usage(virtualTextureManager.usage_metadata);
97
184
 
98
185
  renderer.clear();
99
186
  renderer.render(scene, camera)
100
187
 
188
+ usageDebugView.usage = virtualTextureManager.usage_metadata;
189
+
190
+ // usagePyramidDebugView.setTextureParameters(virtualTextureManager.texture_resolution, virtualTextureManager.tile_resolution);
191
+ // usagePyramidDebugView.usage = virtualTextureManager.usage_metadata;
101
192
  }
@@ -0,0 +1,31 @@
1
+ import { split_by_2 } from "../../../../../core/geom/3d/morton/split_by_2.js";
2
+ import { compose_finger_print } from "./compose_finger_print.js";
3
+
4
+ /**
5
+ *
6
+ * @param {number} index
7
+ * @returns {number}
8
+ */
9
+ export function tile_index_to_finger_print(index) {
10
+ for (let mip = 0; mip < 99; mip++) {
11
+ const resolution = 1 << mip;
12
+
13
+ const mip_mask = resolution - 1;
14
+
15
+ const index_offset = split_by_2(mip_mask);
16
+
17
+ if (index > index_offset) {
18
+ continue;
19
+ }
20
+
21
+ const local_index = index - index_offset;
22
+
23
+ const y = (local_index / resolution) | 0;
24
+ const x = local_index % resolution;
25
+
26
+ return compose_finger_print(mip, x, y,);
27
+ }
28
+
29
+ // not found
30
+ return -1;
31
+ }
@@ -1,478 +0,0 @@
1
- /**
2
- * Created by Alex on 31/10/2014.
3
- */
4
-
5
-
6
- import { assert } from "../../../assert.js";
7
-
8
- const maxElements = 12;
9
- const minElements = 1;
10
-
11
- /**
12
- *
13
- * @param {*} obj
14
- * @param {number} x
15
- * @param {number} y
16
- * @constructor
17
- */
18
- const Element = function (obj, x, y) {
19
- /**
20
- *
21
- * @type {number}
22
- */
23
- this.x = x;
24
- /**
25
- *
26
- * @type {number}
27
- */
28
- this.y = y;
29
-
30
- this.value = obj;
31
-
32
- /**
33
- *
34
- * @type {PointQuadTree|null}
35
- */
36
- this.parentNode = null;
37
- };
38
-
39
- /**
40
- *
41
- * @param {number} x
42
- * @param {number} y
43
- */
44
- Element.prototype.move = function (x, y) {
45
- this.x = x;
46
- this.y = y;
47
- //check if new position is outside of the parent node
48
- const parentNode = this.parentNode;
49
- let node = parentNode;
50
- while (x <= node.x0 || x > node.x1 || y <= node.y0 || y > node.y1) {
51
- if (node.parentNode === null) {
52
- //root
53
- node.resizeToFit(x, y);
54
- break;
55
- }
56
- //outside of the node
57
- node = node.parentNode;
58
- }
59
- //found containing node
60
- if (node === parentNode) {
61
- //still inside the parent node
62
- return;
63
- }
64
- parentNode.removeElement(this);
65
- node.insertElement(this);
66
- };
67
-
68
- Element.prototype.remove = function () {
69
- assert.notEqual(this.parentNode, null, 'parentNode is null');
70
-
71
- this.parentNode.removeElement(this);
72
- };
73
-
74
- /**
75
- * Prefer to use {@link QuadTreeNode} instead as that is more robust and has better performance
76
- */
77
- class PointQuadTree {
78
- /**
79
- * @param {number} [x0]
80
- * @param {number} [y0]
81
- * @param {number} [x1]
82
- * @param {number} [y1]
83
- * @constructor
84
- */
85
- constructor(x0 = 0, y0 = 0, x1 = 0, y1 = 0) {
86
- //
87
- this.x0 = x0;
88
- this.y0 = y0;
89
- this.x1 = x1;
90
- this.y1 = y1;
91
-
92
- this.parentNode = null;
93
-
94
- this.setHalfSize(this.x0, this.y0, this.x1, this.y1);
95
-
96
-
97
- this.elements = [];
98
- this.numElements = 0;
99
-
100
- this.tl = void 0;
101
- this.tr = void 0;
102
- this.bl = void 0;
103
- this.br = void 0;
104
- }
105
-
106
- reduce() {
107
- if (this.isLeaf()) {
108
- //leaf
109
- this.bubbleElementsUp();
110
- } else {
111
- const tl = this.tl;
112
- const tr = this.tr;
113
- const bl = this.bl;
114
- const br = this.br;
115
- tl.reduce();
116
- tr.reduce();
117
- bl.reduce();
118
- br.reduce();
119
- //
120
- if (tl.isLeaf() && tr.isLeaf() && bl.isLeaf() && br.isLeaf()
121
- && tl.numElements === 0 && tr.numElements === 0 && bl.numElements === 0 && br.numElements === 0) {
122
- this.tl = void 0;
123
- this.tr = void 0;
124
- this.bl = void 0;
125
- this.br = void 0;
126
- }
127
- }
128
- }
129
-
130
- insertElement(element) {
131
- if (this.numElements < maxElements) {
132
-
133
- this.numElements++;
134
- this.elements.push(element);
135
- element.parentNode = this;
136
-
137
- } else {
138
-
139
- //check for split
140
- if (this.tl === void 0) {
141
- this.split();
142
- }
143
-
144
- //find suitable child to take element
145
- const x = element.x;
146
- const y = element.y;
147
-
148
- if (x < this.hx) {
149
- if (y < this.hy) {
150
- this.tl.insertElement(element);
151
- } else {
152
- this.bl.insertElement(element);
153
- }
154
- } else {
155
- if (y < this.hy) {
156
- this.tr.insertElement(element);
157
- } else {
158
- this.br.insertElement(element);
159
- }
160
- }
161
- }
162
- }
163
-
164
- clear() {
165
- this.elemenets = [];
166
-
167
- this.tl = undefined;
168
- this.tr = undefined;
169
- this.bl = undefined;
170
- this.br = undefined;
171
- }
172
-
173
- /**
174
- *
175
- * @param {T} p
176
- * @param {number} x
177
- * @param {number} y
178
- * @return {Element}
179
- */
180
- insert(p, x, y) {
181
- assert.isNumber(x, 'x');
182
- assert.isNumber(y, 'y');
183
-
184
- const element = new Element(p, x, y);
185
-
186
- this.resizeToFit(x, y); //adjust size if needed
187
-
188
- this.insertElement(element);
189
-
190
- return element;
191
- }
192
-
193
- traversePreOrder(visitor) {
194
- const keepGoing = visitor(this);
195
- if (keepGoing !== false && this.tl !== void 0) {
196
- this.tl.traversePreOrder(visitor);
197
- this.tr.traversePreOrder(visitor);
198
- this.bl.traversePreOrder(visitor);
199
- this.br.traversePreOrder(visitor);
200
- }
201
- }
202
-
203
- absorbElement(element) {
204
- this.elements.push(element);
205
- this.numElements++;
206
- }
207
-
208
- resizeToFit(x, y) {
209
- let _x0 = this.x0,
210
- _y0 = this.y0,
211
- _x1 = this.x1,
212
- _y1 = this.y1;
213
-
214
- if (x < _x0) {
215
- _x0 = x;
216
- } else if (x > _x1) {
217
- _x1 = x;
218
- }
219
-
220
- if (y < _y0) {
221
- _y0 = y;
222
- } else if (y > _y1) {
223
- _y1 = y;
224
- }
225
-
226
- if (this.x0 !== _x0 || this.y0 !== _y0 || this.x1 !== _x1 || this.y1 !== _y1) {
227
- this.resize(_x0, _y0, _x1, _y1);
228
- }
229
-
230
- }
231
-
232
- isLeaf() {
233
- return this.tl === void 0;
234
- }
235
-
236
- setHalfSize(x0, y0, x1, y1) {
237
- this.hx = (x1 + x0) / 2;
238
- this.hy = (y1 + y0) / 2;
239
- }
240
-
241
- traverseRect(_x0, _y0, _x1, _y1, visitor) {
242
- //check elements
243
- for (let i = 0; i < this.numElements; i++) {
244
- const element = this.elements[i];
245
- const x = element.x;
246
- const y = element.y;
247
- if (x > _x0 && x < _x1 && y > _y0 && y < _y1) {
248
- visitor(element);
249
- }
250
- }
251
- if (!this.isLeaf()) {
252
- //if we have children - check them
253
- if (_x0 <= this.hx) {
254
- if (_y0 <= this.hy) {
255
- this.tl.traverseRect(_x0, _y0, _x1, _y1, visitor);
256
- }
257
- if (_y1 >= this.hy) {
258
- this.bl.traverseRect(_x0, _y0, _x1, _y1, visitor);
259
- }
260
- }
261
- if (_x1 >= this.hx) {
262
- if (_y0 <= this.hy) {
263
- this.tr.traverseRect(_x0, _y0, _x1, _y1, visitor);
264
- }
265
- if (_y1 >= this.hy) {
266
- this.br.traverseRect(_x0, _y0, _x1, _y1, visitor);
267
- }
268
- }
269
- }
270
- }
271
-
272
- traverse(visitor, thisArg) {
273
- this.elements.forEach(visitor, thisArg);
274
- if (this.tl !== void 0) {
275
- this.tl.traverse(visitor, thisArg);
276
- this.tr.traverse(visitor, thisArg);
277
- this.bl.traverse(visitor, thisArg);
278
- this.br.traverse(visitor, thisArg);
279
- }
280
- }
281
-
282
- traverseCircle(cX, cY, r, visitor) {
283
- this.traverseCircleSqr(cX, cY, r, r * r, visitor);
284
- }
285
-
286
- split() {
287
- //generate children
288
- const hx = this.hx;
289
- const hy = this.hy;
290
-
291
- this.tl = new PointQuadTree(this.x0, this.y0, hx, hy);
292
- this.tr = new PointQuadTree(hx, this.y0, this.x1, hy);
293
- this.bl = new PointQuadTree(this.x0, hy, hx, this.y1);
294
- this.br = new PointQuadTree(hx, hy, this.x1, this.y1);
295
-
296
- //set parent node
297
- this.tl.parentNode = this;
298
- this.tr.parentNode = this;
299
- this.bl.parentNode = this;
300
- this.br.parentNode = this;
301
- }
302
-
303
- merge() {
304
- //check if split at all
305
- if (this.isLeaf()) {
306
- return; //not split
307
- }
308
-
309
-
310
- //merge children
311
- this.tl.traverse(this.absorbElement, this);
312
- this.tr.traverse(this.absorbElement, this);
313
- this.bl.traverse(this.absorbElement, this);
314
- this.br.traverse(this.absorbElement, this);
315
- //
316
- this.tl = void 0;
317
- this.tr = void 0;
318
- this.bl = void 0;
319
- this.br = void 0;
320
- }
321
-
322
- validateNode() {
323
- if (this.hx !== (this.x0 + this.x1) / 2) {
324
- return false;
325
- }
326
- if (this.hy !== (this.y0 + this.y1) / 2) {
327
- return false;
328
- }
329
- if (!this.isLeaf()) {
330
- if (this.tl.parentNode !== this
331
- || this.tr.parentNode !== this
332
- || this.bl.parentNode !== this
333
- || this.br.parentNode !== this) {
334
- return false;
335
- }
336
- if (this.tl.x0 !== this.x0 || this.tl.x1 !== this.hx || this.tl.y0 !== this.y0 || this.tl.y1 !== this.hy) {
337
- return false;
338
- }
339
- if (this.tr.x0 !== this.hx || this.tr.x1 !== this.x1 || this.tr.y0 !== this.y0 || this.tr.y1 !== this.hy) {
340
- return false;
341
- }
342
- if (this.bl.x0 !== this.x0 || this.bl.x1 !== this.hx || this.bl.y0 !== this.hy || this.bl.y1 !== this.y1) {
343
- return false;
344
- }
345
- if (this.br.x0 !== this.hx || this.br.x1 !== this.x1 || this.br.y0 !== this.hy || this.br.y1 !== this.y1) {
346
- return false;
347
- }
348
- } else if (this.elements !== void 0) {
349
-
350
- //check containment of elements
351
- for (let i = 0; i < this.elements.length; i++) {
352
- const e = this.elements[i];
353
- if (e.x < this.x0 || e.x > this.x1 || e.y < this.y0 || e.y > this.y1) {
354
- return false;
355
- }
356
- }
357
-
358
- }
359
- return true;
360
- }
361
-
362
- traverseCircleSqr(cX, cY, r, r2, visitor) {
363
- for (let i = 0; i < this.numElements; i++) {
364
- const element = this.elements[i];
365
- const x = element.x;
366
- const y = element.y;
367
- const dx = cX - x;
368
- const dy = cY - y;
369
- const d2 = dx * dx + dy * dy;
370
- if (d2 < r2) {
371
- visitor(element);
372
- }
373
- }
374
-
375
- if (cX - r < this.hx) {
376
- if (cY - r < this.hy) {
377
- this.tl.traverseCircleSqr(cX, cY, r, r2, visitor);
378
- }
379
- if (cY + r >= this.hy) {
380
- this.bl.traverseCircleSqr(cX, cY, r, r2, visitor);
381
- }
382
- }
383
- if (cX + r >= this.hx) {
384
- if (cY - r < this.hy) {
385
- this.tr.traverseCircleSqr(cX, cY, r, r2, visitor);
386
- }
387
- if (cY + r >= this.hy) {
388
- this.br.traverseCircleSqr(cX, cY, r, r2, visitor);
389
- }
390
- }
391
- }
392
-
393
- resize(_x0, _y0, _x1, _y1) {
394
- const parentNode = this.parentNode;
395
- if (parentNode !== null) {
396
- const w = _x1 - _x0;
397
- const h = _y1 - _y0;
398
- if (this === parentNode.tl) {
399
- parentNode.resize(_x0, _y0, _x1 + w, _y1 + h);
400
- } else if (this === parentNode.tr) {
401
- parentNode.resize(_x0 - w, _y0, _x1, _y1 + h);
402
- } else if (this === parentNode.bl) {
403
- parentNode.resize(_x0, _y0 - h, _x1 + w, _y1);
404
- } else if (this === parentNode.br) {
405
- parentNode.resize(_x0 - w, _y0 - h, _x1, _y1);
406
- } else {
407
- throw new Error("Specified 'parent' does not own this node");
408
- }
409
- return;
410
- }
411
- this.x0 = this.x0 = _x0;
412
- this.y0 = this.y0 = _y0;
413
- this.x1 = this.x1 = _x1;
414
- this.y1 = this.y1 = _y1;
415
-
416
- this.setHalfSize(_x0, _y0, _x1, _y1);
417
-
418
- this.merge();
419
- //reinsert all elements
420
- const l = this.numElements;
421
- const els = this.elements;
422
- this.elements = [];
423
- this.numElements = 0;
424
- for (let i = 0; i < l; i++) {
425
- this.insertElement(els[i]);
426
- }
427
- }
428
-
429
- removeElement(e) {
430
-
431
- const i = this.elements.indexOf(e);
432
-
433
- this.elements.splice(i, 1);
434
-
435
- // reset parent
436
- e.parentNode = null;
437
-
438
- this.numElements--;
439
-
440
- if (this.numElements < minElements) {
441
- // number of elements in the current bucket is too small, attempt reduction
442
- this.reduce();
443
- }
444
-
445
- }
446
-
447
- bubbleElementsUp() {
448
- let targetNode = this;
449
- while (this.numElements > 0 && targetNode.parentNode !== null) {
450
- targetNode = targetNode.parentNode;
451
- const parentElements = targetNode.numElements;
452
- const capacityLeft = maxElements - parentElements;
453
- if (capacityLeft > 0) {
454
- const transferNumber = Math.min(capacityLeft, this.numElements);
455
- for (let i = this.numElements - transferNumber; i < this.numElements; i++) {
456
- const element = this.elements[i];
457
- targetNode.insertElement(element);
458
- }
459
- this.numElements -= transferNumber;
460
- }
461
- }
462
- this.elements.length = this.numElements;
463
- }
464
-
465
- validate() {
466
- let v = true;
467
- this.traversePreOrder(function (node) {
468
- let isValid = node.validateNode();
469
- if (!isValid && v !== false) {
470
- v = false;
471
- }
472
- return isValid;
473
- });
474
- return v;
475
- }
476
- }
477
-
478
- export default PointQuadTree;