@woosh/meep-engine 2.48.23 → 2.49.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.
- package/editor/tools/GridPaintTool.js +1 -1
- package/editor/tools/paint/TerrainPaintTool.js +1 -1
- package/editor/view/GridPickCoordinateView.js +1 -1
- package/package.json +1 -1
- package/src/core/UUID.js +2 -0
- package/src/core/assert.js +4 -1
- package/src/core/binary/ctz32.js +1 -1
- package/src/core/binary/operations/bitCount.spec.js +19 -0
- package/src/core/binary/uint82float.spec.js +7 -0
- package/src/core/bvh2/binary/IndexedBinaryBVH.spec.js +7 -0
- package/src/core/bvh2/bvh3/EBBVHLeafProxy.js +3 -0
- package/src/core/bvh2/bvh3/query/compute_tight_near_far_clipping_planes.js +5 -4
- package/src/core/bvh2/transform/RotationOptimizer.spec.js +161 -155
- package/src/core/codegen/LineBuilder.js +12 -3
- package/src/core/codegen/LineBuilder.spec.js +7 -0
- package/src/core/collection/CuckooFilter.js +12 -12
- package/src/core/collection/HashMap.js +486 -237
- package/src/core/collection/HashMap.spec.js +110 -1
- package/src/core/collection/array/{typedArrayToDataType.js → typed/typedArrayToDataType.js} +1 -1
- package/src/core/collection/array/weightedRandomFromArray.spec.js +20 -0
- package/src/core/debug/matchers/AnyOf.js +1 -2
- package/src/core/geom/2d/aabb/AABB2.spec.js +1 -1
- package/src/core/geom/2d/aabb/aabb2_compute_center_from_multiple.js +19 -0
- package/src/core/geom/2d/quad-tree/qt_collect_by_circle.js +3 -3
- package/src/core/geom/2d/quad-tree/qt_query_data_nearest_to_point.js +7 -9
- package/src/core/geom/3d/aabb/aabb3_compute_plane_side.js +17 -15
- package/src/core/geom/3d/aabb/aabb3_compute_plane_side.spec.js +25 -0
- package/src/core/geom/3d/aabb/aabb3_detailed_volume_intersection.js +1 -1
- package/src/core/geom/3d/aabb/aabb3_from_v3_array.js +3 -0
- package/src/core/geom/3d/aabb/aabb3_from_v3_array.spec.js +32 -0
- package/src/core/geom/3d/aabb/aabb3_intersects_aabb3.spec.js +115 -0
- package/src/core/geom/3d/aabb/aabb3_raycast.js +6 -1
- package/src/core/geom/3d/aabb/serializeAABB3Encoded_v0.js +6 -6
- package/src/core/geom/3d/{CircleMath.js → compute_circle_bounding_box.js} +1 -1
- package/src/core/geom/3d/decompose_matrix_4_array.js +18 -19
- package/src/core/geom/3d/frustum/frustum3_computeNearestPointToPoint.js +1 -1
- package/src/{engine/graphics/ecs/mesh-v2 → core/geom/3d/matrix}/allocate_transform_m4.js +1 -1
- package/src/core/geom/3d/normal/hemioct/decode_hemioct_to_unit.js +26 -0
- package/src/core/geom/3d/normal/hemioct/encode_unit3_hemioct.js +0 -26
- package/src/core/geom/3d/normal/hemioct/unit_hemioct.spec.js +2 -1
- package/src/core/geom/3d/plane/computePlaneLineIntersection.js +51 -0
- package/src/core/geom/3d/plane/computePlanePlaneIntersection.js +77 -0
- package/src/core/geom/3d/plane/computePlaneRayIntersection.js +55 -0
- package/src/core/geom/3d/plane/plane3_computeLineSegmentIntersection.js +50 -0
- package/src/core/geom/3d/plane/planeRayIntersection.js +14 -0
- package/src/core/geom/3d/{tetrahedra/in_sphere_fast.js → sphere/in_sphere3d_fast.js} +1 -1
- package/src/core/geom/3d/{tetrahedra/in_sphere_robust.js → sphere/in_sphere3d_robust.js} +1 -1
- package/src/core/geom/3d/sphere/sphere_array_intersects_point.js +2 -2
- package/src/core/geom/3d/sphere/{sphereIntersectsPoint.js → sphere_intersects_point.js} +7 -4
- package/src/core/geom/3d/sphere/sphere_intersects_point.spec.js +134 -0
- package/src/core/geom/3d/sphere/sphere_intersects_ray.spec.js +49 -0
- package/src/core/geom/3d/sphere/sphere_radius_sqr_from_v3_array_transformed.js +11 -7
- package/src/core/geom/3d/tetrahedra/delaunay/{debug_validate_mesh.js → debug/debug_validate_mesh.js} +1 -1
- package/src/core/geom/3d/tetrahedra/delaunay/{push_boundary_with_validation.js → debug/push_boundary_with_validation.js} +1 -1
- package/src/core/geom/3d/tetrahedra/delaunay/{validate_cavity_boundary.js → debug/validate_cavity_boundary.js} +2 -2
- package/src/core/geom/3d/tetrahedra/delaunay/tetrahedral_mesh_compute_cavity.js +2 -2
- package/src/core/geom/3d/triangle/computeTriangleRayIntersection.js +0 -164
- package/src/core/geom/3d/triangle/computeTriangleRayIntersectionBarycentric.js +87 -0
- package/src/core/geom/3d/triangle/computeTriangleRayIntersectionBarycentricEdge.js +81 -0
- package/src/core/geom/{rayTriangleIntersection.js → 3d/triangle/rayTriangleIntersection.js} +2 -2
- package/src/core/geom/ConicRay.js +160 -152
- package/src/core/geom/Matrix4.js +2 -0
- package/src/core/geom/Quaternion.js +19 -1
- package/src/core/geom/packing/max-rect/MaxRectangles.js +4 -214
- package/src/core/geom/packing/max-rect/cost/costByBestShortSide.js +11 -0
- package/src/core/geom/packing/max-rect/cost/costByRemainingArea.js +14 -0
- package/src/core/geom/packing/max-rect/cutArea.js +79 -0
- package/src/core/geom/packing/max-rect/findBestContainer.js +58 -0
- package/src/core/geom/packing/max-rect/packOneBox.js +49 -0
- package/src/core/geom/packing/miniball/Miniball.js +12 -12
- package/src/core/geom/packing/miniball/Quality.js +2 -2
- package/src/core/geom/packing/miniball/Subspan.js +13 -13
- package/src/core/geom/v3_dot.js +1 -1
- package/src/core/graph/layout/CircleLayout.js +1 -1
- package/src/core/graph/layout/{BoxLayouter.js → box/BoxLayouter.js} +6 -50
- package/src/core/graph/layout/box/applyCentralGravityAABB2.js +29 -0
- package/src/core/json/resolvePath.spec.js +14 -0
- package/src/core/land/reactive/{compiler/ReactiveCompiler.spec.js → compileReactiveExpression.spec.js} +17 -17
- package/src/core/math/random/MersenneTwister.spec.js +19 -0
- package/src/core/math/random/randomGaussian.spec.js +9 -0
- package/src/core/math/statistics/computeStatisticalMean.js +2 -2
- package/src/core/model/reactive/model/arithmetic/ReactiveAdd.js +1 -1
- package/src/core/model/reactive/model/arithmetic/ReactiveDivide.js +3 -1
- package/src/core/model/reactive/model/arithmetic/ReactiveMultiply.js +1 -1
- package/src/core/model/reactive/model/arithmetic/ReactiveNegate.js +3 -1
- package/src/core/model/reactive/model/arithmetic/ReactiveSubtract.js +1 -1
- package/src/core/model/reactive/model/comparative/ReactiveEquals.js +1 -1
- package/src/core/model/reactive/model/comparative/ReactiveGreaterThan.js +3 -1
- package/src/core/model/reactive/model/comparative/ReactiveGreaterThanOrEqual.js +3 -1
- package/src/core/model/reactive/model/comparative/ReactiveLessThan.js +3 -1
- package/src/core/model/reactive/model/comparative/ReactiveLessThanOrEqual.js +3 -1
- package/src/core/model/reactive/model/comparative/ReactiveNotEquals.js +1 -1
- package/src/core/model/reactive/model/logic/ReactiveAnd.js +1 -1
- package/src/core/model/reactive/model/logic/ReactiveNot.js +3 -1
- package/src/core/model/reactive/model/logic/ReactiveOr.js +1 -1
- package/src/core/primitives/numbers/computeHashFloat.spec.js +7 -0
- package/src/core/process/task/util/iteratorTask.js +3 -1
- package/src/engine/animation/curve/AnimationCurve.js +34 -5
- package/src/engine/animation/curve/AnimationCurve.spec.js +100 -0
- package/src/engine/asset/AssetTransformer.js +1 -0
- package/src/engine/computeStridedIntegerArrayHash.js +4 -2
- package/src/engine/ecs/components/Renderable.d.ts +1 -1
- package/src/{ecs → engine/ecs}/grid/pick.js +4 -4
- package/src/engine/ecs/parent/entity_node_compute_bounding_box.js +1 -1
- package/src/engine/ecs/storage/binary/collection/BinaryCollectionSerializer.js +1 -18
- package/src/engine/ecs/systems/MotionSystem.js +7 -1
- package/src/engine/ecs/systems/SynchronizePositionSystem.js +8 -2
- package/src/engine/ecs/transform/Transform.js +1 -1
- package/src/engine/graphics/camera/makeScreenScissorFrustum.js +3 -3
- package/src/engine/graphics/camera/testClippingPlaneComputation.js +13 -13
- package/src/engine/graphics/ecs/camera/Camera.js +1 -1
- package/src/engine/graphics/ecs/mesh-v2/aggregate/SGMesh.js +1 -1
- package/src/engine/graphics/ecs/mesh-v2/aggregate/SGMeshSystem.js +9 -0
- package/src/engine/graphics/geometry/MikkT/MikkTSpace.js +1 -1
- package/src/engine/graphics/geometry/MikkT/STSpace.js +1 -1
- package/src/engine/graphics/geometry/bvh/buffered/BVHGeometryRaycaster.js +1 -1
- package/src/engine/graphics/material/optimization/MaterialOptimizationContext.js +1 -1
- package/src/engine/graphics/particles/particular/engine/MovingBoundingBox.js +1 -1
- package/src/engine/graphics/particles/particular/engine/parameter/ParameterLookupTable.js +1 -0
- package/src/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +1 -1
- package/src/engine/graphics/postprocess/threejs/postprocessing/TexturePass.js +2 -2
- package/src/engine/graphics/sh3/path_tracer/GeometryBVHBatched.js +2 -2
- package/src/engine/graphics/texture/sampler/Sampler2D.js +1 -1
- package/src/engine/graphics/texture/sampler/sampler2d_compute_texel_value_conversion_scale_to_uint8.js +1 -1
- package/src/engine/intelligence/behavior/Behavior.spec.js +15 -0
- package/src/engine/intelligence/mcts/MoveEdge.js +1 -1
- package/src/engine/reference/v1/ReferenceManager.js +3 -0
- package/src/engine/reference/v2/Reference.js +33 -37
- package/src/engine/sound/sopra/README.md +6 -0
- package/src/generation/automata/CaveGeneratorCellularAutomata.js +10 -7
- package/src/generation/automata/CaveGeneratorCellularAutomata.spec.js +12 -0
- package/src/generation/automata/CellularAutomata.js +5 -4
- package/src/generation/filtering/numeric/complex/CellFilterGaussianBlur.js +25 -9
- package/src/view/minimap/dom/MinimapCameraView.js +1 -1
- package/src/core/geom/Plane.js +0 -250
- package/src/core/land/reactive/ReactiveLexer.js +0 -158
- package/src/core/land/reactive/ReactiveLexer.ts +0 -181
- package/src/core/land/reactive/ReactiveListener.ts +0 -323
- package/src/core/land/reactive/ReactiveParser.js +0 -1573
- package/src/core/land/reactive/ReactiveParser.ts +0 -1776
- package/src/core/land/reactive/ReactiveVisitor.js +0 -1
- package/src/core/land/reactive/ReactiveVisitor.ts +0 -218
- package/src/core/land/reactive/compiler/ReactiveCompiler.js +0 -350
- package/src/core/land/reactive/compiler/ReactiveNearlyCompiler.js +0 -166
- package/src/core/land/reactive/compiler/ReactiveParser.js +0 -34
- package/src/core/land/reactive/nearley/ReactiveNearley.js +0 -187
- /package/src/{engine/graphics/ecs/mesh-v2 → core/geom/3d/vector}/allocate_v3.js +0 -0
|
@@ -12,7 +12,7 @@ import TopDownCameraControllerSystem
|
|
|
12
12
|
from "../../src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.js";
|
|
13
13
|
import { hex2rgb } from "../../src/core/color/hex2rgb.js";
|
|
14
14
|
import { obtainTerrain } from "../../src/engine/ecs/terrain/util/obtainTerrain.js";
|
|
15
|
-
import { pick } from "../../src/ecs/grid/pick.js";
|
|
15
|
+
import { pick } from "../../src/engine/ecs/grid/pick.js";
|
|
16
16
|
|
|
17
17
|
class GridPaintTool extends Tool {
|
|
18
18
|
constructor() {
|
|
@@ -8,7 +8,7 @@ import ObservedString from "../../../src/core/model/ObservedString.js";
|
|
|
8
8
|
import { GameAssetType } from "../../../src/engine/asset/GameAssetType.js";
|
|
9
9
|
import Vector1 from "../../../src/core/geom/Vector1.js";
|
|
10
10
|
import { obtainTerrain } from "../../../src/engine/ecs/terrain/util/obtainTerrain.js";
|
|
11
|
-
import { pick } from "../../../src/ecs/grid/pick.js";
|
|
11
|
+
import { pick } from "../../../src/engine/ecs/grid/pick.js";
|
|
12
12
|
|
|
13
13
|
export class TerrainPaintTool extends Tool {
|
|
14
14
|
constructor() {
|
|
@@ -2,7 +2,7 @@ import View from "../../src/view/View.js";
|
|
|
2
2
|
import domify from "../../src/view/DOM.js";
|
|
3
3
|
import { PointerDevice } from "../../src/engine/input/devices/PointerDevice.js";
|
|
4
4
|
import { obtainTerrain } from "../../src/engine/ecs/terrain/util/obtainTerrain.js";
|
|
5
|
-
import { pick } from "../../src/ecs/grid/pick.js";
|
|
5
|
+
import { pick } from "../../src/engine/ecs/grid/pick.js";
|
|
6
6
|
|
|
7
7
|
class GridPickCoordinateView extends View {
|
|
8
8
|
/**
|
package/package.json
CHANGED
package/src/core/UUID.js
CHANGED
|
@@ -10,6 +10,8 @@ function replacer(c) {
|
|
|
10
10
|
const rx = /[xy]/g;
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
+
* Generates a variant 4 fully random UUID in string format
|
|
14
|
+
* NOTE: Prefer to use UUID component class instead as that implementation is more robust and has better entropy when it comes to randomness
|
|
13
15
|
* @returns {string}
|
|
14
16
|
*/
|
|
15
17
|
function uuid() {
|
package/src/core/assert.js
CHANGED
|
@@ -3,7 +3,10 @@ import { isTypedArray } from "./collection/array/typed/isTypedArray.js";
|
|
|
3
3
|
import { InMemoryDescriptor } from "./debug/InMemoryDescriptor.js";
|
|
4
4
|
|
|
5
5
|
function equal(a, b, m) {
|
|
6
|
-
|
|
6
|
+
if (a !== b) {
|
|
7
|
+
const message = m !== undefined ? m : `${a} !== ${b}`;
|
|
8
|
+
throw new Error(message);
|
|
9
|
+
}
|
|
7
10
|
}
|
|
8
11
|
|
|
9
12
|
function notEqual(a, b, m) {
|
package/src/core/binary/ctz32.js
CHANGED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { bitCount } from "./bitCount.js";
|
|
2
|
+
|
|
3
|
+
test("no set bits", () => {
|
|
4
|
+
expect(bitCount(0)).toBe(0)
|
|
5
|
+
});
|
|
6
|
+
|
|
7
|
+
test("1 set bit", () => {
|
|
8
|
+
|
|
9
|
+
for (let i = 0; i < 32; i++) {
|
|
10
|
+
expect(bitCount(1 << i)).toBe(1)
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
test("2 set bit together", () => {
|
|
15
|
+
|
|
16
|
+
for (let i = 0; i < 31; i++) {
|
|
17
|
+
expect(bitCount(0b11 << i)).toBe(2)
|
|
18
|
+
}
|
|
19
|
+
});
|
|
@@ -32,6 +32,7 @@ export class EBBVHLeafProxy {
|
|
|
32
32
|
* @param {number} data Must be a uint32
|
|
33
33
|
*/
|
|
34
34
|
link(tree, data) {
|
|
35
|
+
assert.equal(this.is_linked, false, 'already linked');
|
|
35
36
|
assert.defined(tree, 'tree');
|
|
36
37
|
assert.isNonNegativeInteger(data, 'data');
|
|
37
38
|
|
|
@@ -47,6 +48,8 @@ export class EBBVHLeafProxy {
|
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
unlink() {
|
|
51
|
+
assert.equal(this.is_linked, true, 'not linked');
|
|
52
|
+
|
|
50
53
|
this.#tree.remove_leaf(this.#node_id);
|
|
51
54
|
this.#tree.release_node(this.#node_id);
|
|
52
55
|
|
|
@@ -27,7 +27,7 @@ export function compute_tight_near_far_clipping_planes(result, result_offset, co
|
|
|
27
27
|
const root = bvh.root;
|
|
28
28
|
|
|
29
29
|
if (root === NULL_NODE) {
|
|
30
|
-
return
|
|
30
|
+
return false;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
/**
|
|
@@ -67,8 +67,8 @@ export function compute_tight_near_far_clipping_planes(result, result_offset, co
|
|
|
67
67
|
const _y1 = scratch_aabb[4];
|
|
68
68
|
const _z1 = scratch_aabb[5];
|
|
69
69
|
|
|
70
|
-
for (let
|
|
71
|
-
const plane_address =
|
|
70
|
+
for (let plane_index = 0; plane_index < 6; plane_index++) {
|
|
71
|
+
const plane_address = plane_index * 4;
|
|
72
72
|
|
|
73
73
|
//read out plane
|
|
74
74
|
const plane_normal_x = frustum[plane_address];
|
|
@@ -112,7 +112,7 @@ export function compute_tight_near_far_clipping_planes(result, result_offset, co
|
|
|
112
112
|
continue node_loop;
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
if ((constrained_planes_mask & (1 <<
|
|
115
|
+
if ((constrained_planes_mask & (1 << plane_index)) !== 0) {
|
|
116
116
|
// plane is constrained, we're done here
|
|
117
117
|
continue;
|
|
118
118
|
}
|
|
@@ -152,4 +152,5 @@ export function compute_tight_near_far_clipping_planes(result, result_offset, co
|
|
|
152
152
|
}
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
+
return true;
|
|
155
156
|
}
|
|
@@ -100,198 +100,204 @@ function pair(left, right) {
|
|
|
100
100
|
return node;
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
test("empty node", () => {
|
|
104
|
-
const node = new BinaryNode();
|
|
105
|
-
node.setInfiniteBounds();
|
|
106
103
|
|
|
107
|
-
|
|
104
|
+
describe.skip("suite", () => {
|
|
108
105
|
|
|
109
|
-
expect(node.left).toBeNull();
|
|
110
|
-
expect(node.right).toBeNull();
|
|
111
|
-
});
|
|
112
106
|
|
|
113
|
-
test("
|
|
114
|
-
|
|
115
|
-
|
|
107
|
+
test("empty node", () => {
|
|
108
|
+
const node = new BinaryNode();
|
|
109
|
+
node.setInfiniteBounds();
|
|
116
110
|
|
|
117
|
-
|
|
111
|
+
optimize(node, 100);
|
|
118
112
|
|
|
119
|
-
|
|
120
|
-
|
|
113
|
+
expect(node.left).toBeNull();
|
|
114
|
+
expect(node.right).toBeNull();
|
|
115
|
+
});
|
|
121
116
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
117
|
+
test("does nothing on optimal 2 child tree", () => {
|
|
118
|
+
const a = leaf(0, 1, "hello");
|
|
119
|
+
const b = leaf(2, 3, "goodbye");
|
|
125
120
|
|
|
126
|
-
|
|
127
|
-
expect(root.left.parentNode).toEqual(root);
|
|
128
|
-
expect(root.right.parentNode).toEqual(root);
|
|
121
|
+
const root = pair(a, b);
|
|
129
122
|
|
|
130
|
-
|
|
131
|
-
|
|
123
|
+
const optimized = optimize(root, 100);
|
|
124
|
+
expect(optimized).toBe(0);
|
|
132
125
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
const c = leaf(0, 1, "c");
|
|
137
|
-
const d = leaf(1, 2, "d");
|
|
126
|
+
//positions preserved
|
|
127
|
+
expect(root.left.object).toEqual(a.object);
|
|
128
|
+
expect(root.right.object).toEqual(b.object);
|
|
138
129
|
|
|
139
|
-
|
|
140
|
-
|
|
130
|
+
//parent node is root
|
|
131
|
+
expect(root.left.parentNode).toEqual(root);
|
|
132
|
+
expect(root.right.parentNode).toEqual(root);
|
|
141
133
|
|
|
142
|
-
|
|
134
|
+
expect(root).toBeValid();
|
|
135
|
+
});
|
|
143
136
|
|
|
144
|
-
|
|
145
|
-
|
|
137
|
+
test("does nothing on optimal depth 2 tree", () => {
|
|
138
|
+
const a = leaf(-2, -1, "a");
|
|
139
|
+
const b = leaf(-1, 0, "b");
|
|
140
|
+
const c = leaf(0, 1, "c");
|
|
141
|
+
const d = leaf(1, 2, "d");
|
|
146
142
|
|
|
147
|
-
|
|
143
|
+
const n0 = pair(a, b);
|
|
144
|
+
const n1 = pair(c, d);
|
|
148
145
|
|
|
149
|
-
|
|
150
|
-
expect(root.right).toBe(n1);
|
|
146
|
+
const root = pair(n0, n1);
|
|
151
147
|
|
|
152
|
-
|
|
153
|
-
|
|
148
|
+
const optimized = optimize(root, 100);
|
|
149
|
+
expect(optimized).toBe(0);
|
|
154
150
|
|
|
155
|
-
|
|
156
|
-
expect(n1.right).toBe(d);
|
|
151
|
+
expect(root.parentNode).toBeNull();
|
|
157
152
|
|
|
158
|
-
|
|
159
|
-
|
|
153
|
+
expect(root.left).toBe(n0);
|
|
154
|
+
expect(root.right).toBe(n1);
|
|
160
155
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
const b = leaf(-1, 0, "b");
|
|
164
|
-
const c = leaf(0, 1, "c");
|
|
165
|
-
const d = leaf(1, 2, "d");
|
|
156
|
+
expect(n0.left).toBe(a);
|
|
157
|
+
expect(n0.right).toBe(b);
|
|
166
158
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
pair(c, d),
|
|
170
|
-
b
|
|
171
|
-
),
|
|
172
|
-
a
|
|
173
|
-
);
|
|
159
|
+
expect(n1.left).toBe(c);
|
|
160
|
+
expect(n1.right).toBe(d);
|
|
174
161
|
|
|
175
|
-
|
|
162
|
+
expect(root).toBeValid();
|
|
163
|
+
});
|
|
176
164
|
|
|
177
|
-
|
|
165
|
+
test("produces a valid tree from left-leaning tree with 4 leaves", () => {
|
|
166
|
+
const a = leaf(-2, -1, "a");
|
|
167
|
+
const b = leaf(-1, 0, "b");
|
|
168
|
+
const c = leaf(0, 1, "c");
|
|
169
|
+
const d = leaf(1, 2, "d");
|
|
178
170
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
171
|
+
const root = pair(
|
|
172
|
+
pair(
|
|
173
|
+
pair(c, d),
|
|
174
|
+
b
|
|
175
|
+
),
|
|
176
|
+
a
|
|
177
|
+
);
|
|
184
178
|
|
|
185
|
-
|
|
186
|
-
const a = leaf(-2, -1, "a");
|
|
187
|
-
const b = leaf(-1, 0, "b");
|
|
188
|
-
const c = leaf(0, 1, "c");
|
|
189
|
-
const d = leaf(1, 2, "d");
|
|
179
|
+
optimize(root, 100);
|
|
190
180
|
|
|
191
|
-
|
|
192
|
-
a,
|
|
193
|
-
pair(
|
|
194
|
-
b,
|
|
195
|
-
pair(c, d)
|
|
196
|
-
)
|
|
197
|
-
);
|
|
181
|
+
expect(root).toBeValid();
|
|
198
182
|
|
|
199
|
-
|
|
183
|
+
expect(root).toContainNode(a);
|
|
184
|
+
expect(root).toContainNode(b);
|
|
185
|
+
expect(root).toContainNode(c);
|
|
186
|
+
expect(root).toContainNode(d);
|
|
187
|
+
});
|
|
200
188
|
|
|
201
|
-
|
|
189
|
+
test("produces a valid tree from right-leaning tree with 4 leaves", () => {
|
|
190
|
+
const a = leaf(-2, -1, "a");
|
|
191
|
+
const b = leaf(-1, 0, "b");
|
|
192
|
+
const c = leaf(0, 1, "c");
|
|
193
|
+
const d = leaf(1, 2, "d");
|
|
202
194
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
195
|
+
const root = pair(
|
|
196
|
+
a,
|
|
197
|
+
pair(
|
|
198
|
+
b,
|
|
199
|
+
pair(c, d)
|
|
200
|
+
)
|
|
201
|
+
);
|
|
208
202
|
|
|
209
|
-
|
|
210
|
-
const random = seededRandom(42);
|
|
203
|
+
optimize(root, 100);
|
|
211
204
|
|
|
212
|
-
|
|
205
|
+
expect(root).toBeValid();
|
|
213
206
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
207
|
+
expect(root).toContainNode(a);
|
|
208
|
+
expect(root).toContainNode(b);
|
|
209
|
+
expect(root).toContainNode(c);
|
|
210
|
+
expect(root).toContainNode(d);
|
|
211
|
+
});
|
|
218
212
|
|
|
219
|
-
|
|
220
|
-
const
|
|
221
|
-
const z1 = z0 + random() * 5;
|
|
213
|
+
test("100 node random tree optimization does not degrade quality", () => {
|
|
214
|
+
const random = seededRandom(42);
|
|
222
215
|
|
|
223
|
-
nodes
|
|
224
|
-
}
|
|
216
|
+
const nodes = [];
|
|
225
217
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
218
|
+
for (let i = 0; i < 100; i++) {
|
|
219
|
+
const x0 = random() * 100;
|
|
220
|
+
const y0 = random() * 100;
|
|
221
|
+
const z0 = random() * 100;
|
|
222
|
+
|
|
223
|
+
const x1 = x0 + random() * 5;
|
|
224
|
+
const y1 = y0 + random() * 5;
|
|
225
|
+
const z1 = z0 + random() * 5;
|
|
231
226
|
|
|
232
|
-
|
|
227
|
+
nodes.push(new LeafNode(i, x0, y0, z0, x1, y1, z1));
|
|
228
|
+
}
|
|
233
229
|
|
|
234
|
-
|
|
230
|
+
while (nodes.length >= 2) {
|
|
231
|
+
const left = nodes.pop();
|
|
232
|
+
const right = nodes.pop();
|
|
233
|
+
nodes.unshift(pair(left, right));
|
|
234
|
+
}
|
|
235
235
|
|
|
236
|
-
|
|
236
|
+
const root = nodes[0];
|
|
237
237
|
|
|
238
|
-
|
|
238
|
+
const oldSAH = root.computeSAH();
|
|
239
239
|
|
|
240
|
-
|
|
240
|
+
optimize(root, 100);
|
|
241
241
|
|
|
242
|
-
|
|
243
|
-
expect(newSAH).toBeLessThanOrEqual(oldSAH);
|
|
244
|
-
});
|
|
242
|
+
expect(root).toBeValid();
|
|
245
243
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
244
|
+
const newSAH = root.computeSAH();
|
|
245
|
+
|
|
246
|
+
//at least not degraded
|
|
247
|
+
expect(newSAH).toBeLessThanOrEqual(oldSAH);
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
test("case 0: 4 node tree optimization does not degrade quality", () => {
|
|
251
|
+
const ll = new LeafNode("ll",
|
|
252
|
+
76.06244471671744,
|
|
253
|
+
7.73902752171125,
|
|
254
|
+
1.925105413576489,
|
|
255
|
+
94.49883157197291,
|
|
256
|
+
50.63123012084361,
|
|
257
|
+
76.75841101302467
|
|
258
|
+
);
|
|
259
|
+
|
|
260
|
+
const lr = new LeafNode("lr",
|
|
261
|
+
76.11310176957886,
|
|
262
|
+
58.65097077867176,
|
|
263
|
+
11.346076624795387,
|
|
264
|
+
97.55653706044541,
|
|
265
|
+
89.91247777413719,
|
|
266
|
+
90.73181902923352
|
|
267
|
+
);
|
|
268
|
+
|
|
269
|
+
const rl = new LeafNode("rl",
|
|
270
|
+
32.4771196630536,
|
|
271
|
+
0.9366270797727339,
|
|
272
|
+
1.378434756588831,
|
|
273
|
+
66.71670340545461,
|
|
274
|
+
99.32784918828929,
|
|
275
|
+
97.52435446605432
|
|
276
|
+
);
|
|
277
|
+
|
|
278
|
+
const rr = new LeafNode("rr",
|
|
279
|
+
1.124263022938976,
|
|
280
|
+
0.13232239543867763,
|
|
281
|
+
2.702786005283997,
|
|
282
|
+
31.51776058888572,
|
|
283
|
+
94.87720282424561,
|
|
284
|
+
101.03932220629758
|
|
285
|
+
);
|
|
286
|
+
|
|
287
|
+
const root = pair(pair(ll, lr), pair(rl, rr));
|
|
288
|
+
|
|
289
|
+
expect(root).toBeValid();
|
|
290
|
+
|
|
291
|
+
const oldSAH = root.computeSAH();
|
|
292
|
+
|
|
293
|
+
optimize(root, 1000);
|
|
294
|
+
|
|
295
|
+
expect(root).toBeValid();
|
|
296
|
+
|
|
297
|
+
const newSAH = root.computeSAH();
|
|
298
|
+
|
|
299
|
+
//at least not degraded
|
|
300
|
+
expect(newSAH).toBeLessThanOrEqual(oldSAH);
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
})
|
|
@@ -16,6 +16,8 @@ class Line {
|
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
const DEFAULT_INDENT_SPACES = 4;
|
|
20
|
+
|
|
19
21
|
/**
|
|
20
22
|
* Useful for creating formatted snippets of code
|
|
21
23
|
*/
|
|
@@ -35,7 +37,7 @@ class LineBuilder {
|
|
|
35
37
|
*
|
|
36
38
|
* @type {number}
|
|
37
39
|
*/
|
|
38
|
-
indentSpaces =
|
|
40
|
+
indentSpaces = DEFAULT_INDENT_SPACES;
|
|
39
41
|
|
|
40
42
|
/**
|
|
41
43
|
*
|
|
@@ -82,8 +84,11 @@ class LineBuilder {
|
|
|
82
84
|
* @returns {LineBuilder}
|
|
83
85
|
*/
|
|
84
86
|
add(line_text) {
|
|
87
|
+
|
|
85
88
|
const line = new Line(line_text, this.indentation);
|
|
89
|
+
|
|
86
90
|
this.lines.push(line);
|
|
91
|
+
|
|
87
92
|
return this;
|
|
88
93
|
}
|
|
89
94
|
|
|
@@ -110,7 +115,7 @@ class LineBuilder {
|
|
|
110
115
|
clear() {
|
|
111
116
|
this.lines = [];
|
|
112
117
|
this.indentation = 0;
|
|
113
|
-
this.indentSpaces =
|
|
118
|
+
this.indentSpaces = DEFAULT_INDENT_SPACES;
|
|
114
119
|
}
|
|
115
120
|
|
|
116
121
|
/**
|
|
@@ -119,14 +124,16 @@ class LineBuilder {
|
|
|
119
124
|
*/
|
|
120
125
|
build() {
|
|
121
126
|
const result = [];
|
|
122
|
-
let i, j, l;
|
|
123
127
|
|
|
128
|
+
let i, j, l;
|
|
124
129
|
|
|
125
130
|
const lines = this.lines;
|
|
131
|
+
|
|
126
132
|
for (i = 0, l = lines.length; i < l; i++) {
|
|
127
133
|
const line = lines[i];
|
|
128
134
|
|
|
129
135
|
let indentString = '';
|
|
136
|
+
|
|
130
137
|
for (j = 0; j < line.indentation * this.indentSpaces; j++) {
|
|
131
138
|
indentString += ' ';
|
|
132
139
|
}
|
|
@@ -149,6 +156,8 @@ class LineBuilder {
|
|
|
149
156
|
|
|
150
157
|
const n = lines.length;
|
|
151
158
|
|
|
159
|
+
// TODO detect indent
|
|
160
|
+
|
|
152
161
|
for (let i = 0; i < n; i++) {
|
|
153
162
|
|
|
154
163
|
r.add(lines[i]);
|
|
@@ -368,9 +368,9 @@ export class CuckooFilter {
|
|
|
368
368
|
}
|
|
369
369
|
|
|
370
370
|
/**
|
|
371
|
-
* Puts an element into this {@
|
|
371
|
+
* Puts an element into this {@link CuckooFilter}. Ensures that subsequent
|
|
372
372
|
* invocations of {@link #mightContain(Object)} with the same element will
|
|
373
|
-
* always return
|
|
373
|
+
* always return `true`.
|
|
374
374
|
* <p>
|
|
375
375
|
* Note that the filter should be considered full after insertion failure.
|
|
376
376
|
* Further inserts <i>may</i> fail, although deleting items can also make
|
|
@@ -380,8 +380,8 @@ export class CuckooFilter {
|
|
|
380
380
|
* insertion failure.
|
|
381
381
|
*
|
|
382
382
|
* @param {number} hash hash of item to insert
|
|
383
|
-
* @returns {boolean}
|
|
384
|
-
* Returns
|
|
383
|
+
* @returns {boolean} `true` if the cuckoo filter inserts this item successfully.
|
|
384
|
+
* Returns `false` if insertion failed.
|
|
385
385
|
*/
|
|
386
386
|
insert(hash) {
|
|
387
387
|
const current_tag = this.__compute_tag_from_hash(hash);
|
|
@@ -461,22 +461,22 @@ export class CuckooFilter {
|
|
|
461
461
|
}
|
|
462
462
|
|
|
463
463
|
/**
|
|
464
|
-
* Deletes an element from this {@
|
|
464
|
+
* Deletes an element from this {@link CuckooFilter}. In most cases you
|
|
465
465
|
* should only delete items that have been previously added to the filter.
|
|
466
466
|
* Attempting to delete non-existent items may successfully delete the wrong
|
|
467
467
|
* item in the filter, causing a false negative. False negatives are defined
|
|
468
|
-
* as( {@
|
|
468
|
+
* as( {@link #mightContain(Object)} returning false for an item that
|
|
469
469
|
* <i>has</i> been added to the filter. Deleting non-existent items doesn't
|
|
470
470
|
* otherwise adversely affect the state of the filter, so attempting to
|
|
471
471
|
* delete items that <i>may not</i> have been inserted is fine if false
|
|
472
472
|
* negatives are acceptable. The false-delete rate is similar to the false
|
|
473
473
|
* positive rate. False deletes can also cause the
|
|
474
|
-
* {@
|
|
474
|
+
* {@link #approximateCount(Object)} to return both lower and higher than
|
|
475
475
|
* the real count
|
|
476
476
|
*
|
|
477
477
|
* @param {number} hash
|
|
478
|
-
* @returns {boolean}
|
|
479
|
-
* Returns
|
|
478
|
+
* @returns {boolean} `true` if the cuckoo filter deleted this item successfully.
|
|
479
|
+
* Returns `false` if the item was not found.
|
|
480
480
|
*/
|
|
481
481
|
remove(hash) {
|
|
482
482
|
const tag = this.__compute_tag_from_hash(hash);
|
|
@@ -508,8 +508,8 @@ export class CuckooFilter {
|
|
|
508
508
|
|
|
509
509
|
|
|
510
510
|
/**
|
|
511
|
-
* Returns
|
|
512
|
-
* Cuckoo filter,
|
|
511
|
+
* Returns `true` if the element <i>might</i> have been put in this
|
|
512
|
+
* Cuckoo filter, `false` if this is <i>definitely</i> not the case.
|
|
513
513
|
*
|
|
514
514
|
* @param {number} hash
|
|
515
515
|
* @returns {boolean}
|
|
@@ -523,4 +523,4 @@ export class CuckooFilter {
|
|
|
523
523
|
|| (this.__victim_exists && this.__victim_tag === tag && (this.__victim_index === i1 || this.__victim_index === i2)) //check the victim
|
|
524
524
|
;
|
|
525
525
|
}
|
|
526
|
-
}
|
|
526
|
+
}
|