@woosh/meep-engine 2.87.3 → 2.87.5
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 +4 -4
- package/build/meep.min.js +1 -1
- package/build/meep.module.js +4 -4
- package/package.json +1 -1
- package/src/core/binary/align_4.d.ts +7 -0
- package/src/core/binary/align_4.d.ts.map +1 -0
- package/src/core/binary/align_4.js +14 -0
- package/src/core/geom/2d/aabb/aabb2_intersects_ray.d.ts +14 -0
- package/src/core/geom/2d/aabb/aabb2_intersects_ray.d.ts.map +1 -0
- package/src/core/geom/2d/aabb/aabb2_intersects_ray.js +50 -0
- package/src/core/geom/2d/aabb/aabb2_intersects_ray.spec.d.ts +2 -0
- package/src/core/geom/2d/aabb/aabb2_intersects_ray.spec.d.ts.map +1 -0
- package/src/core/geom/2d/aabb/aabb2_intersects_ray.spec.js +28 -0
- package/src/core/geom/2d/hash-grid/SpatialHashGrid.d.ts +52 -0
- package/src/core/geom/2d/hash-grid/SpatialHashGrid.d.ts.map +1 -0
- package/src/core/geom/2d/hash-grid/SpatialHashGrid.js +317 -0
- package/src/core/geom/2d/hash-grid/SpatialHashGrid.spec.d.ts +2 -0
- package/src/core/geom/2d/hash-grid/SpatialHashGrid.spec.d.ts.map +1 -0
- package/src/core/geom/2d/hash-grid/SpatialHashGrid.spec.js +158 -0
- package/src/core/geom/2d/hash-grid/shg_query_raycast.d.ts +14 -0
- package/src/core/geom/2d/hash-grid/shg_query_raycast.d.ts.map +1 -0
- package/src/core/geom/2d/hash-grid/shg_query_raycast.js +21 -0
- package/src/core/geom/2d/lt-grid/LooseTightGrid.d.ts +55 -0
- package/src/core/geom/2d/lt-grid/LooseTightGrid.d.ts.map +1 -0
- package/src/core/geom/2d/lt-grid/LooseTightGrid.js +221 -0
- package/src/core/geom/2d/quad-tree/QuadTreeNode.js +3 -3
- package/src/core/geom/2d/quad-tree/qt_query_data_raycast.d.ts.map +1 -1
- package/src/core/geom/2d/quad-tree/qt_query_data_raycast.js +19 -6
- package/src/core/geom/2d/quad-tree-binary/QuadTree.d.ts +94 -0
- package/src/core/geom/2d/quad-tree-binary/QuadTree.d.ts.map +1 -0
- package/src/core/geom/2d/quad-tree-binary/QuadTree.js +715 -0
- package/src/core/geom/2d/quad-tree-binary/QuadTree.spec.d.ts +2 -0
- package/src/core/geom/2d/quad-tree-binary/QuadTree.spec.d.ts.map +1 -0
- package/src/core/geom/2d/quad-tree-binary/QuadTree.spec.js +53 -0
- package/src/core/geom/3d/morton/de_interleave_2_bits.spec.d.ts +2 -0
- package/src/core/geom/3d/morton/de_interleave_2_bits.spec.d.ts.map +1 -0
- package/src/core/geom/3d/morton/de_interleave_2_bits.spec.js +21 -0
- package/src/core/geom/3d/morton/de_interleave_bits_by_2.d.ts +7 -0
- package/src/core/geom/3d/morton/de_interleave_bits_by_2.d.ts.map +1 -0
- package/src/core/geom/3d/morton/de_interleave_bits_by_2.js +15 -0
- package/src/core/geom/3d/morton/split_by_2.d.ts +1 -1
- package/src/core/geom/3d/morton/split_by_2.js +1 -1
- package/src/core/geom/3d/morton/split_by_3.d.ts +1 -1
- package/src/core/geom/3d/morton/split_by_3.js +1 -1
- package/src/core/geom/3d/topology/struct/binary/BinaryElementPool.d.ts +7 -0
- package/src/core/geom/3d/topology/struct/binary/BinaryElementPool.d.ts.map +1 -1
- package/src/core/geom/3d/topology/struct/binary/BinaryElementPool.js +14 -14
package/build/meep.module.js
CHANGED
|
@@ -54997,7 +54997,7 @@ function aabb3_compute_half_surface_area(x0, y0, z0, x1, y1, z1) {
|
|
|
54997
54997
|
* method to separate bits from a given integer 3 positions apart
|
|
54998
54998
|
* we only look at the first 10 bits
|
|
54999
54999
|
*
|
|
55000
|
-
* @example when input is ABC, output bits are
|
|
55000
|
+
* @example when input is ABC, output bits are 00A00B00C
|
|
55001
55001
|
* @param {number} a
|
|
55002
55002
|
* @returns {number}
|
|
55003
55003
|
*/
|
|
@@ -105806,8 +105806,8 @@ class QuadTreeNode extends AABB2 {
|
|
|
105806
105806
|
}
|
|
105807
105807
|
}
|
|
105808
105808
|
|
|
105809
|
-
const xm = (x0 + x1)
|
|
105810
|
-
const ym = (y0 + y1)
|
|
105809
|
+
const xm = (x0 + x1) *0.5;
|
|
105810
|
+
const ym = (y0 + y1) *0.5;
|
|
105811
105811
|
|
|
105812
105812
|
if (datum.y1 < ym) {
|
|
105813
105813
|
//top
|
|
@@ -105821,7 +105821,7 @@ class QuadTreeNode extends AABB2 {
|
|
|
105821
105821
|
this.addDatum(datum);
|
|
105822
105822
|
}
|
|
105823
105823
|
} else if (datum.y0 >= ym) {
|
|
105824
|
-
//
|
|
105824
|
+
//bottom
|
|
105825
105825
|
if (datum.x1 < xm) {
|
|
105826
105826
|
//left
|
|
105827
105827
|
this.bottomLeft.insertDatum(datum);
|
package/package.json
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"align_4.d.ts","sourceRoot":"","sources":["../../../../src/core/binary/align_4.js"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,2BAHW,MAAM,GACL,MAAM,CAQjB"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { assert } from "../assert.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Align on 4 byte boundary
|
|
5
|
+
* @param {number} n
|
|
6
|
+
* @return {number}
|
|
7
|
+
*/
|
|
8
|
+
export function align_4(n) {
|
|
9
|
+
const result = ((n + 0x3) >> 2) << 2;
|
|
10
|
+
|
|
11
|
+
assert.greaterThanOrEqual(result, n, 'aligned result must be >= input');
|
|
12
|
+
|
|
13
|
+
return result;
|
|
14
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* @param {number} x0
|
|
4
|
+
* @param {number} y0
|
|
5
|
+
* @param {number} x1
|
|
6
|
+
* @param {number} y1
|
|
7
|
+
* @param {number} origin_x
|
|
8
|
+
* @param {number} origin_y
|
|
9
|
+
* @param {number} direction_x
|
|
10
|
+
* @param {number} direction_y
|
|
11
|
+
* @return {boolean} true if hit found and false otherwise
|
|
12
|
+
*/
|
|
13
|
+
export function aabb2_intersects_ray(x0: number, y0: number, x1: number, y1: number, origin_x: number, origin_y: number, direction_x: number, direction_y: number): boolean;
|
|
14
|
+
//# sourceMappingURL=aabb2_intersects_ray.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aabb2_intersects_ray.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/2d/aabb/aabb2_intersects_ray.js"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AACH,yCAVW,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,YACN,MAAM,YACN,MAAM,eACN,MAAM,eACN,MAAM,GACL,OAAO,CAqClB"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { fabsf } from "../../../math/fabsf.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* @param {number} x0
|
|
6
|
+
* @param {number} y0
|
|
7
|
+
* @param {number} x1
|
|
8
|
+
* @param {number} y1
|
|
9
|
+
* @param {number} origin_x
|
|
10
|
+
* @param {number} origin_y
|
|
11
|
+
* @param {number} direction_x
|
|
12
|
+
* @param {number} direction_y
|
|
13
|
+
* @return {boolean} true if hit found and false otherwise
|
|
14
|
+
*/
|
|
15
|
+
export function aabb2_intersects_ray(
|
|
16
|
+
x0, y0,
|
|
17
|
+
x1, y1,
|
|
18
|
+
origin_x, origin_y,
|
|
19
|
+
direction_x, direction_y
|
|
20
|
+
) {
|
|
21
|
+
// Z Projection
|
|
22
|
+
const extents_x = (x1 - x0) * 0.5;
|
|
23
|
+
|
|
24
|
+
const center_x = x0 + extents_x;
|
|
25
|
+
|
|
26
|
+
const diff_x = origin_x - center_x;
|
|
27
|
+
|
|
28
|
+
if (diff_x * direction_x >= 0.0 && fabsf(diff_x) > extents_x) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Y projection
|
|
33
|
+
const extents_y = (y1 - y0) * 0.5;
|
|
34
|
+
|
|
35
|
+
const center_y = y0 + extents_y;
|
|
36
|
+
|
|
37
|
+
const diff_y = origin_y - center_y;
|
|
38
|
+
|
|
39
|
+
if (diff_y * direction_y >= 0.0 && fabsf(diff_y) > extents_y) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const abs_direction_y = fabsf(direction_y);
|
|
44
|
+
|
|
45
|
+
const abs_direction_x = fabsf(direction_x);
|
|
46
|
+
|
|
47
|
+
const f2 = fabsf(direction_x * diff_y - direction_y * diff_x);
|
|
48
|
+
|
|
49
|
+
return f2 <= extents_x * abs_direction_y + extents_y * abs_direction_x;
|
|
50
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aabb2_intersects_ray.spec.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/2d/aabb/aabb2_intersects_ray.spec.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { aabb2_intersects_ray } from "./aabb2_intersects_ray.js";
|
|
2
|
+
|
|
3
|
+
test("diagonal ray hit", () => {
|
|
4
|
+
|
|
5
|
+
expect(
|
|
6
|
+
aabb2_intersects_ray(
|
|
7
|
+
1, 1, 2, 2, 0, 0,
|
|
8
|
+
Math.SQRT2, Math.SQRT2
|
|
9
|
+
)
|
|
10
|
+
).toBe(true);
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
expect(
|
|
14
|
+
aabb2_intersects_ray(
|
|
15
|
+
1, 1, 2, 2, 3, 3,
|
|
16
|
+
-Math.SQRT2, -Math.SQRT2
|
|
17
|
+
)
|
|
18
|
+
).toBe(true);
|
|
19
|
+
|
|
20
|
+
expect(
|
|
21
|
+
aabb2_intersects_ray(
|
|
22
|
+
1, 1, 2, 2, 3, 0,
|
|
23
|
+
-Math.SQRT2, Math.SQRT2
|
|
24
|
+
)
|
|
25
|
+
).toBe(true);
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
});
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export class SpatialHashGrid {
|
|
2
|
+
constructor(size_x?: number, size_y?: number, scale?: number);
|
|
3
|
+
element_allocate(): number;
|
|
4
|
+
element_set_user_data(element: any, user_data: any): void;
|
|
5
|
+
/**
|
|
6
|
+
* You have to remove the element from the grid before changing its bounds
|
|
7
|
+
* @param {number} element
|
|
8
|
+
* @param {number} x0
|
|
9
|
+
* @param {number} y0
|
|
10
|
+
* @param {number} x1
|
|
11
|
+
* @param {number} y1
|
|
12
|
+
*/
|
|
13
|
+
element_set_bounds_primitive(element: number, x0: number, y0: number, x1: number, y1: number): void;
|
|
14
|
+
/**
|
|
15
|
+
*
|
|
16
|
+
* @param {number} element
|
|
17
|
+
*/
|
|
18
|
+
element_release(element: number): void;
|
|
19
|
+
/**
|
|
20
|
+
*
|
|
21
|
+
* @param {number} element
|
|
22
|
+
*/
|
|
23
|
+
element_insert(element: number): void;
|
|
24
|
+
/**
|
|
25
|
+
*
|
|
26
|
+
* @param {number} x
|
|
27
|
+
* @param {number} y
|
|
28
|
+
* @returns {number}
|
|
29
|
+
*/
|
|
30
|
+
cell_position_to_index(x: number, y: number): number;
|
|
31
|
+
/**
|
|
32
|
+
*
|
|
33
|
+
* @param {number[]} out
|
|
34
|
+
* @param {number} out_offset
|
|
35
|
+
* @param {number} index
|
|
36
|
+
*/
|
|
37
|
+
cell_index_to_position(out: number[], out_offset: number, index: number): void;
|
|
38
|
+
/**
|
|
39
|
+
*
|
|
40
|
+
* @param {number} cell_x
|
|
41
|
+
* @param {number} cell_y
|
|
42
|
+
* @return {boolean}
|
|
43
|
+
*/
|
|
44
|
+
is_cell_empty(cell_x: number, cell_y: number): boolean;
|
|
45
|
+
/**
|
|
46
|
+
*
|
|
47
|
+
* @param {number} element
|
|
48
|
+
*/
|
|
49
|
+
element_remove(element: number): void;
|
|
50
|
+
#private;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=SpatialHashGrid.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SpatialHashGrid.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/2d/hash-grid/SpatialHashGrid.js"],"names":[],"mappings":"AAsCA;IAWI,8DAYC;IAQD,2BAIC;IAED,0DAKC;IAED;;;;;;;OAOG;IACH,sCANW,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,QAYhB;IAED;;;OAGG;IACH,yBAFW,MAAM,QAIhB;IAED;;;OAGG;IACH,wBAFW,MAAM,QA8BhB;IAED;;;;;OAKG;IACH,0BAJW,MAAM,KACN,MAAM,GACJ,MAAM,CAalB;IAED;;;;;OAKG;IACH,4BAJW,MAAM,EAAE,cACR,MAAM,SACN,MAAM,QAOhB;IAED;;;;;OAKG;IACH,sBAJW,MAAM,UACN,MAAM,GACL,OAAO,CAclB;IA0FD;;;OAGG;IACH,wBAFW,MAAM,QA6BhB;;CACJ"}
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
import { assert } from "../../../assert.js";
|
|
2
|
+
import { UINT32_MAX } from "../../../binary/UINT32_MAX.js";
|
|
3
|
+
import { de_interleave_2_bits } from "../../3d/morton/de_interleave_bits_by_2.js";
|
|
4
|
+
import { BinaryElementPool } from "../../3d/topology/struct/binary/BinaryElementPool.js";
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
const NULL_POINTER = UINT32_MAX;
|
|
8
|
+
/**
|
|
9
|
+
* Single-linked list
|
|
10
|
+
* Pointer to next NODE in the same grid cell
|
|
11
|
+
* @type {number}
|
|
12
|
+
*/
|
|
13
|
+
const COLUMN_NODE_SAME_NODE_NEXT = 0;
|
|
14
|
+
/**
|
|
15
|
+
* Single-linked list
|
|
16
|
+
* Pointer to next NODE containing the same element
|
|
17
|
+
* @type {number}
|
|
18
|
+
*/
|
|
19
|
+
const COLUMN_NODE_SAME_ELEMENT_NEXT = 1;
|
|
20
|
+
/**
|
|
21
|
+
* Pointer to ELEMENT
|
|
22
|
+
* @type {number}
|
|
23
|
+
*/
|
|
24
|
+
const COLUMN_NODE_ELEMENT = 2;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Points to grid cell that stores this node
|
|
28
|
+
* @type {number}
|
|
29
|
+
*/
|
|
30
|
+
const COLUMN_NODE_GRID_INDEX = 3;
|
|
31
|
+
|
|
32
|
+
const COLUMN_ELEMENT_DATA = 0;
|
|
33
|
+
const COLUMN_ELEMENT_NODE_FIRST = 1;
|
|
34
|
+
const COLUMN_ELEMENT_X0 = 2;
|
|
35
|
+
const COLUMN_ELEMENT_Y0 = 3;
|
|
36
|
+
const COLUMN_ELEMENT_X1 = 4;
|
|
37
|
+
const COLUMN_ELEMENT_Y1 = 5;
|
|
38
|
+
|
|
39
|
+
export class SpatialHashGrid {
|
|
40
|
+
#element_pool = new BinaryElementPool(24)
|
|
41
|
+
#node_pool = new BinaryElementPool(16);
|
|
42
|
+
#grid_data = new Uint32Array(0);
|
|
43
|
+
|
|
44
|
+
#size_x = 0;
|
|
45
|
+
#size_y = 0;
|
|
46
|
+
|
|
47
|
+
#scale = 1;
|
|
48
|
+
#scale_inverse = 1;
|
|
49
|
+
|
|
50
|
+
constructor(size_x = 1, size_y = 1, scale = 8) {
|
|
51
|
+
|
|
52
|
+
assert.notNaN(scale, "scale");
|
|
53
|
+
assert.isFiniteNumber(scale, 'scale');
|
|
54
|
+
assert.greaterThan(scale, 0, 'scale must be greater than 0');
|
|
55
|
+
|
|
56
|
+
this.#size_x = size_x;
|
|
57
|
+
this.#size_y = size_y;
|
|
58
|
+
this.#scale = scale;
|
|
59
|
+
this.#scale_inverse = 1 / scale;
|
|
60
|
+
|
|
61
|
+
this.#build();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
#build() {
|
|
65
|
+
this.#grid_data = new Uint32Array(this.#size_x * this.#size_y);
|
|
66
|
+
|
|
67
|
+
this.#grid_data.fill(NULL_POINTER);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
element_allocate() {
|
|
71
|
+
const element = this.#element_pool.allocate();
|
|
72
|
+
|
|
73
|
+
return element;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
element_set_user_data(element, user_data) {
|
|
77
|
+
const pool = this.#element_pool;
|
|
78
|
+
const address = pool.element_word(element);
|
|
79
|
+
|
|
80
|
+
pool.data_uint32[address + COLUMN_ELEMENT_DATA] = user_data;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* You have to remove the element from the grid before changing its bounds
|
|
85
|
+
* @param {number} element
|
|
86
|
+
* @param {number} x0
|
|
87
|
+
* @param {number} y0
|
|
88
|
+
* @param {number} x1
|
|
89
|
+
* @param {number} y1
|
|
90
|
+
*/
|
|
91
|
+
element_set_bounds_primitive(element, x0, y0, x1, y1) {
|
|
92
|
+
const pool = this.#element_pool;
|
|
93
|
+
const address = pool.element_word(element);
|
|
94
|
+
|
|
95
|
+
const float32 = pool.data_float32;
|
|
96
|
+
|
|
97
|
+
float32[address + COLUMN_ELEMENT_X0] = x0;
|
|
98
|
+
float32[address + COLUMN_ELEMENT_Y0] = y0;
|
|
99
|
+
float32[address + COLUMN_ELEMENT_X1] = x1;
|
|
100
|
+
float32[address + COLUMN_ELEMENT_Y1] = y1;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
*
|
|
105
|
+
* @param {number} element
|
|
106
|
+
*/
|
|
107
|
+
element_release(element) {
|
|
108
|
+
this.#element_pool.release(element);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
*
|
|
113
|
+
* @param {number} element
|
|
114
|
+
*/
|
|
115
|
+
element_insert(element) {
|
|
116
|
+
const pool = this.#element_pool;
|
|
117
|
+
const address = pool.element_word(element);
|
|
118
|
+
|
|
119
|
+
const uint32 = pool.data_uint32;
|
|
120
|
+
|
|
121
|
+
// make sure that we don't point at anything yet
|
|
122
|
+
uint32[address + COLUMN_ELEMENT_NODE_FIRST] = NULL_POINTER;
|
|
123
|
+
|
|
124
|
+
const float32 = pool.data_float32;
|
|
125
|
+
|
|
126
|
+
const x0 = float32[address + COLUMN_ELEMENT_X0];
|
|
127
|
+
const y0 = float32[address + COLUMN_ELEMENT_Y0];
|
|
128
|
+
const x1 = float32[address + COLUMN_ELEMENT_X1];
|
|
129
|
+
const y1 = float32[address + COLUMN_ELEMENT_Y1];
|
|
130
|
+
|
|
131
|
+
// convert to grid coordinates
|
|
132
|
+
const grid_x0 = Math.floor(x0 * this.#scale_inverse);
|
|
133
|
+
const grid_y0 = Math.floor(y0 * this.#scale_inverse);
|
|
134
|
+
|
|
135
|
+
const grid_x1 = Math.floor(x1 * this.#scale_inverse);
|
|
136
|
+
const grid_y1 = Math.floor(y1 * this.#scale_inverse);
|
|
137
|
+
|
|
138
|
+
for (let y = grid_y0; y <= grid_y1; y++) {
|
|
139
|
+
for (let x = grid_x0; x <= grid_x1; x++) {
|
|
140
|
+
this.#element_insert_into_cell(element, x, y);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
*
|
|
147
|
+
* @param {number} x
|
|
148
|
+
* @param {number} y
|
|
149
|
+
* @returns {number}
|
|
150
|
+
*/
|
|
151
|
+
cell_position_to_index(x, y) {
|
|
152
|
+
assert.isNonNegativeInteger(x, 'x');
|
|
153
|
+
assert.isNonNegativeInteger(y, 'y');
|
|
154
|
+
|
|
155
|
+
return y* this.#size_x + x;
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
// const _x = split_by_2(x);
|
|
159
|
+
// const _y = split_by_2(y);
|
|
160
|
+
//
|
|
161
|
+
// return _x | (_y << 1);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
*
|
|
166
|
+
* @param {number[]} out
|
|
167
|
+
* @param {number} out_offset
|
|
168
|
+
* @param {number} index
|
|
169
|
+
*/
|
|
170
|
+
cell_index_to_position(out, out_offset, index) {
|
|
171
|
+
|
|
172
|
+
out[out_offset] = de_interleave_2_bits(index)
|
|
173
|
+
out[out_offset + 1] = de_interleave_2_bits(index >> 1)
|
|
174
|
+
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
*
|
|
179
|
+
* @param {number} cell_x
|
|
180
|
+
* @param {number} cell_y
|
|
181
|
+
* @return {boolean}
|
|
182
|
+
*/
|
|
183
|
+
is_cell_empty(cell_x, cell_y) {
|
|
184
|
+
assert.isNonNegativeInteger(cell_x, 'cell_x');
|
|
185
|
+
assert.lessThan(cell_x, this.#size_x, 'cell_x overflow');
|
|
186
|
+
|
|
187
|
+
assert.isNonNegativeInteger(cell_y, 'cell_y');
|
|
188
|
+
assert.lessThan(cell_y, this.#size_y, 'cell_y overflow');
|
|
189
|
+
|
|
190
|
+
const index = this.cell_position_to_index(cell_x, cell_y);
|
|
191
|
+
|
|
192
|
+
const grid = this.#grid_data;
|
|
193
|
+
|
|
194
|
+
return grid[index] === NULL_POINTER;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
*
|
|
199
|
+
* @param {number} element
|
|
200
|
+
* @param {number} grid_x
|
|
201
|
+
* @param {number} grid_y
|
|
202
|
+
*/
|
|
203
|
+
#element_insert_into_cell(element, grid_x, grid_y) {
|
|
204
|
+
|
|
205
|
+
// create a node
|
|
206
|
+
const node_pool = this.#node_pool;
|
|
207
|
+
const node = node_pool.allocate();
|
|
208
|
+
|
|
209
|
+
const node_address = node_pool.element_word(node);
|
|
210
|
+
const node_data_uint32 = node_pool.data_uint32;
|
|
211
|
+
|
|
212
|
+
node_data_uint32[node_address + COLUMN_NODE_ELEMENT] = element;
|
|
213
|
+
|
|
214
|
+
// link node to the element
|
|
215
|
+
const element_pool = this.#element_pool;
|
|
216
|
+
const element_address = element_pool.element_word(element);
|
|
217
|
+
|
|
218
|
+
const element_data_uint32 = element_pool.data_uint32;
|
|
219
|
+
|
|
220
|
+
const element_first_node = element_data_uint32[element_address + COLUMN_ELEMENT_NODE_FIRST];
|
|
221
|
+
|
|
222
|
+
// point to previous first
|
|
223
|
+
node_data_uint32[node_address + COLUMN_NODE_SAME_ELEMENT_NEXT] = element_first_node;
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
element_data_uint32[element_address + COLUMN_ELEMENT_NODE_FIRST] = node;
|
|
227
|
+
|
|
228
|
+
// link node to the cell
|
|
229
|
+
const cell_index = this.cell_position_to_index(grid_x, grid_y);
|
|
230
|
+
|
|
231
|
+
node_data_uint32[node_address + COLUMN_NODE_GRID_INDEX] = cell_index;
|
|
232
|
+
|
|
233
|
+
const grid_data = this.#grid_data;
|
|
234
|
+
|
|
235
|
+
const cell_first_node = grid_data[cell_index];
|
|
236
|
+
|
|
237
|
+
node_data_uint32[node_address + COLUMN_NODE_SAME_NODE_NEXT] = cell_first_node;
|
|
238
|
+
|
|
239
|
+
grid_data[cell_index] = node;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
*
|
|
244
|
+
* @param {number} cell_index
|
|
245
|
+
* @param {number} node
|
|
246
|
+
* @returns {boolean}
|
|
247
|
+
*/
|
|
248
|
+
#grid_cell_remove_node(cell_index, node) {
|
|
249
|
+
assert.isNonNegativeInteger(cell_index, 'cell_index');
|
|
250
|
+
assert.isNonNegativeInteger(node, 'node');
|
|
251
|
+
|
|
252
|
+
const pool = this.#node_pool;
|
|
253
|
+
const node_data_uint32 = pool.data_uint32;
|
|
254
|
+
|
|
255
|
+
const grid_data = this.#grid_data;
|
|
256
|
+
let n = grid_data[cell_index]
|
|
257
|
+
let previous = NULL_POINTER;
|
|
258
|
+
|
|
259
|
+
while (n !== NULL_POINTER) {
|
|
260
|
+
const address = pool.element_word(n);
|
|
261
|
+
const next = node_data_uint32[address + COLUMN_NODE_SAME_NODE_NEXT];
|
|
262
|
+
|
|
263
|
+
if (n === node) {
|
|
264
|
+
// found the node to cut
|
|
265
|
+
|
|
266
|
+
if (previous === NULL_POINTER) {
|
|
267
|
+
// first element in the list
|
|
268
|
+
grid_data[cell_index] = next;
|
|
269
|
+
} else {
|
|
270
|
+
const previous_address = pool.element_word(previous);
|
|
271
|
+
|
|
272
|
+
node_data_uint32[previous_address + COLUMN_NODE_SAME_NODE_NEXT] = next;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
return true;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
previous = n;
|
|
279
|
+
n = next;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
return false;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
*
|
|
287
|
+
* @param {number} element
|
|
288
|
+
*/
|
|
289
|
+
element_remove(element) {
|
|
290
|
+
assert.isNonNegativeInteger(element, 'element');
|
|
291
|
+
|
|
292
|
+
const element_pool = this.#element_pool;
|
|
293
|
+
const address = element_pool.element_word(element);
|
|
294
|
+
|
|
295
|
+
let node = element_pool.data_uint32[address + COLUMN_ELEMENT_NODE_FIRST];
|
|
296
|
+
|
|
297
|
+
const node_pool = this.#node_pool;
|
|
298
|
+
const node_data_uint32 = node_pool.data_uint32;
|
|
299
|
+
|
|
300
|
+
do {
|
|
301
|
+
|
|
302
|
+
const node_address = node_pool.element_word(node);
|
|
303
|
+
|
|
304
|
+
const next = node_data_uint32[node_address + COLUMN_NODE_SAME_ELEMENT_NEXT];
|
|
305
|
+
|
|
306
|
+
const grid_index = node_data_uint32[node_address + COLUMN_NODE_GRID_INDEX];
|
|
307
|
+
|
|
308
|
+
// cut this node from CELL list
|
|
309
|
+
this.#grid_cell_remove_node(grid_index, node);
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
// advance onto next
|
|
313
|
+
node = next;
|
|
314
|
+
} while (node !== NULL_POINTER)
|
|
315
|
+
|
|
316
|
+
}
|
|
317
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SpatialHashGrid.spec.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/2d/hash-grid/SpatialHashGrid.spec.js"],"names":[],"mappings":""}
|