@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.
Files changed (147) hide show
  1. package/editor/tools/GridPaintTool.js +1 -1
  2. package/editor/tools/paint/TerrainPaintTool.js +1 -1
  3. package/editor/view/GridPickCoordinateView.js +1 -1
  4. package/package.json +1 -1
  5. package/src/core/UUID.js +2 -0
  6. package/src/core/assert.js +4 -1
  7. package/src/core/binary/ctz32.js +1 -1
  8. package/src/core/binary/operations/bitCount.spec.js +19 -0
  9. package/src/core/binary/uint82float.spec.js +7 -0
  10. package/src/core/bvh2/binary/IndexedBinaryBVH.spec.js +7 -0
  11. package/src/core/bvh2/bvh3/EBBVHLeafProxy.js +3 -0
  12. package/src/core/bvh2/bvh3/query/compute_tight_near_far_clipping_planes.js +5 -4
  13. package/src/core/bvh2/transform/RotationOptimizer.spec.js +161 -155
  14. package/src/core/codegen/LineBuilder.js +12 -3
  15. package/src/core/codegen/LineBuilder.spec.js +7 -0
  16. package/src/core/collection/CuckooFilter.js +12 -12
  17. package/src/core/collection/HashMap.js +486 -237
  18. package/src/core/collection/HashMap.spec.js +110 -1
  19. package/src/core/collection/array/{typedArrayToDataType.js → typed/typedArrayToDataType.js} +1 -1
  20. package/src/core/collection/array/weightedRandomFromArray.spec.js +20 -0
  21. package/src/core/debug/matchers/AnyOf.js +1 -2
  22. package/src/core/geom/2d/aabb/AABB2.spec.js +1 -1
  23. package/src/core/geom/2d/aabb/aabb2_compute_center_from_multiple.js +19 -0
  24. package/src/core/geom/2d/quad-tree/qt_collect_by_circle.js +3 -3
  25. package/src/core/geom/2d/quad-tree/qt_query_data_nearest_to_point.js +7 -9
  26. package/src/core/geom/3d/aabb/aabb3_compute_plane_side.js +17 -15
  27. package/src/core/geom/3d/aabb/aabb3_compute_plane_side.spec.js +25 -0
  28. package/src/core/geom/3d/aabb/aabb3_detailed_volume_intersection.js +1 -1
  29. package/src/core/geom/3d/aabb/aabb3_from_v3_array.js +3 -0
  30. package/src/core/geom/3d/aabb/aabb3_from_v3_array.spec.js +32 -0
  31. package/src/core/geom/3d/aabb/aabb3_intersects_aabb3.spec.js +115 -0
  32. package/src/core/geom/3d/aabb/aabb3_raycast.js +6 -1
  33. package/src/core/geom/3d/aabb/serializeAABB3Encoded_v0.js +6 -6
  34. package/src/core/geom/3d/{CircleMath.js → compute_circle_bounding_box.js} +1 -1
  35. package/src/core/geom/3d/decompose_matrix_4_array.js +18 -19
  36. package/src/core/geom/3d/frustum/frustum3_computeNearestPointToPoint.js +1 -1
  37. package/src/{engine/graphics/ecs/mesh-v2 → core/geom/3d/matrix}/allocate_transform_m4.js +1 -1
  38. package/src/core/geom/3d/normal/hemioct/decode_hemioct_to_unit.js +26 -0
  39. package/src/core/geom/3d/normal/hemioct/encode_unit3_hemioct.js +0 -26
  40. package/src/core/geom/3d/normal/hemioct/unit_hemioct.spec.js +2 -1
  41. package/src/core/geom/3d/plane/computePlaneLineIntersection.js +51 -0
  42. package/src/core/geom/3d/plane/computePlanePlaneIntersection.js +77 -0
  43. package/src/core/geom/3d/plane/computePlaneRayIntersection.js +55 -0
  44. package/src/core/geom/3d/plane/plane3_computeLineSegmentIntersection.js +50 -0
  45. package/src/core/geom/3d/plane/planeRayIntersection.js +14 -0
  46. package/src/core/geom/3d/{tetrahedra/in_sphere_fast.js → sphere/in_sphere3d_fast.js} +1 -1
  47. package/src/core/geom/3d/{tetrahedra/in_sphere_robust.js → sphere/in_sphere3d_robust.js} +1 -1
  48. package/src/core/geom/3d/sphere/sphere_array_intersects_point.js +2 -2
  49. package/src/core/geom/3d/sphere/{sphereIntersectsPoint.js → sphere_intersects_point.js} +7 -4
  50. package/src/core/geom/3d/sphere/sphere_intersects_point.spec.js +134 -0
  51. package/src/core/geom/3d/sphere/sphere_intersects_ray.spec.js +49 -0
  52. package/src/core/geom/3d/sphere/sphere_radius_sqr_from_v3_array_transformed.js +11 -7
  53. package/src/core/geom/3d/tetrahedra/delaunay/{debug_validate_mesh.js → debug/debug_validate_mesh.js} +1 -1
  54. package/src/core/geom/3d/tetrahedra/delaunay/{push_boundary_with_validation.js → debug/push_boundary_with_validation.js} +1 -1
  55. package/src/core/geom/3d/tetrahedra/delaunay/{validate_cavity_boundary.js → debug/validate_cavity_boundary.js} +2 -2
  56. package/src/core/geom/3d/tetrahedra/delaunay/tetrahedral_mesh_compute_cavity.js +2 -2
  57. package/src/core/geom/3d/triangle/computeTriangleRayIntersection.js +0 -164
  58. package/src/core/geom/3d/triangle/computeTriangleRayIntersectionBarycentric.js +87 -0
  59. package/src/core/geom/3d/triangle/computeTriangleRayIntersectionBarycentricEdge.js +81 -0
  60. package/src/core/geom/{rayTriangleIntersection.js → 3d/triangle/rayTriangleIntersection.js} +2 -2
  61. package/src/core/geom/ConicRay.js +160 -152
  62. package/src/core/geom/Matrix4.js +2 -0
  63. package/src/core/geom/Quaternion.js +19 -1
  64. package/src/core/geom/packing/max-rect/MaxRectangles.js +4 -214
  65. package/src/core/geom/packing/max-rect/cost/costByBestShortSide.js +11 -0
  66. package/src/core/geom/packing/max-rect/cost/costByRemainingArea.js +14 -0
  67. package/src/core/geom/packing/max-rect/cutArea.js +79 -0
  68. package/src/core/geom/packing/max-rect/findBestContainer.js +58 -0
  69. package/src/core/geom/packing/max-rect/packOneBox.js +49 -0
  70. package/src/core/geom/packing/miniball/Miniball.js +12 -12
  71. package/src/core/geom/packing/miniball/Quality.js +2 -2
  72. package/src/core/geom/packing/miniball/Subspan.js +13 -13
  73. package/src/core/geom/v3_dot.js +1 -1
  74. package/src/core/graph/layout/CircleLayout.js +1 -1
  75. package/src/core/graph/layout/{BoxLayouter.js → box/BoxLayouter.js} +6 -50
  76. package/src/core/graph/layout/box/applyCentralGravityAABB2.js +29 -0
  77. package/src/core/json/resolvePath.spec.js +14 -0
  78. package/src/core/land/reactive/{compiler/ReactiveCompiler.spec.js → compileReactiveExpression.spec.js} +17 -17
  79. package/src/core/math/random/MersenneTwister.spec.js +19 -0
  80. package/src/core/math/random/randomGaussian.spec.js +9 -0
  81. package/src/core/math/statistics/computeStatisticalMean.js +2 -2
  82. package/src/core/model/reactive/model/arithmetic/ReactiveAdd.js +1 -1
  83. package/src/core/model/reactive/model/arithmetic/ReactiveDivide.js +3 -1
  84. package/src/core/model/reactive/model/arithmetic/ReactiveMultiply.js +1 -1
  85. package/src/core/model/reactive/model/arithmetic/ReactiveNegate.js +3 -1
  86. package/src/core/model/reactive/model/arithmetic/ReactiveSubtract.js +1 -1
  87. package/src/core/model/reactive/model/comparative/ReactiveEquals.js +1 -1
  88. package/src/core/model/reactive/model/comparative/ReactiveGreaterThan.js +3 -1
  89. package/src/core/model/reactive/model/comparative/ReactiveGreaterThanOrEqual.js +3 -1
  90. package/src/core/model/reactive/model/comparative/ReactiveLessThan.js +3 -1
  91. package/src/core/model/reactive/model/comparative/ReactiveLessThanOrEqual.js +3 -1
  92. package/src/core/model/reactive/model/comparative/ReactiveNotEquals.js +1 -1
  93. package/src/core/model/reactive/model/logic/ReactiveAnd.js +1 -1
  94. package/src/core/model/reactive/model/logic/ReactiveNot.js +3 -1
  95. package/src/core/model/reactive/model/logic/ReactiveOr.js +1 -1
  96. package/src/core/primitives/numbers/computeHashFloat.spec.js +7 -0
  97. package/src/core/process/task/util/iteratorTask.js +3 -1
  98. package/src/engine/animation/curve/AnimationCurve.js +34 -5
  99. package/src/engine/animation/curve/AnimationCurve.spec.js +100 -0
  100. package/src/engine/asset/AssetTransformer.js +1 -0
  101. package/src/engine/computeStridedIntegerArrayHash.js +4 -2
  102. package/src/engine/ecs/components/Renderable.d.ts +1 -1
  103. package/src/{ecs → engine/ecs}/grid/pick.js +4 -4
  104. package/src/engine/ecs/parent/entity_node_compute_bounding_box.js +1 -1
  105. package/src/engine/ecs/storage/binary/collection/BinaryCollectionSerializer.js +1 -18
  106. package/src/engine/ecs/systems/MotionSystem.js +7 -1
  107. package/src/engine/ecs/systems/SynchronizePositionSystem.js +8 -2
  108. package/src/engine/ecs/transform/Transform.js +1 -1
  109. package/src/engine/graphics/camera/makeScreenScissorFrustum.js +3 -3
  110. package/src/engine/graphics/camera/testClippingPlaneComputation.js +13 -13
  111. package/src/engine/graphics/ecs/camera/Camera.js +1 -1
  112. package/src/engine/graphics/ecs/mesh-v2/aggregate/SGMesh.js +1 -1
  113. package/src/engine/graphics/ecs/mesh-v2/aggregate/SGMeshSystem.js +9 -0
  114. package/src/engine/graphics/geometry/MikkT/MikkTSpace.js +1 -1
  115. package/src/engine/graphics/geometry/MikkT/STSpace.js +1 -1
  116. package/src/engine/graphics/geometry/bvh/buffered/BVHGeometryRaycaster.js +1 -1
  117. package/src/engine/graphics/material/optimization/MaterialOptimizationContext.js +1 -1
  118. package/src/engine/graphics/particles/particular/engine/MovingBoundingBox.js +1 -1
  119. package/src/engine/graphics/particles/particular/engine/parameter/ParameterLookupTable.js +1 -0
  120. package/src/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +1 -1
  121. package/src/engine/graphics/postprocess/threejs/postprocessing/TexturePass.js +2 -2
  122. package/src/engine/graphics/sh3/path_tracer/GeometryBVHBatched.js +2 -2
  123. package/src/engine/graphics/texture/sampler/Sampler2D.js +1 -1
  124. package/src/engine/graphics/texture/sampler/sampler2d_compute_texel_value_conversion_scale_to_uint8.js +1 -1
  125. package/src/engine/intelligence/behavior/Behavior.spec.js +15 -0
  126. package/src/engine/intelligence/mcts/MoveEdge.js +1 -1
  127. package/src/engine/reference/v1/ReferenceManager.js +3 -0
  128. package/src/engine/reference/v2/Reference.js +33 -37
  129. package/src/engine/sound/sopra/README.md +6 -0
  130. package/src/generation/automata/CaveGeneratorCellularAutomata.js +10 -7
  131. package/src/generation/automata/CaveGeneratorCellularAutomata.spec.js +12 -0
  132. package/src/generation/automata/CellularAutomata.js +5 -4
  133. package/src/generation/filtering/numeric/complex/CellFilterGaussianBlur.js +25 -9
  134. package/src/view/minimap/dom/MinimapCameraView.js +1 -1
  135. package/src/core/geom/Plane.js +0 -250
  136. package/src/core/land/reactive/ReactiveLexer.js +0 -158
  137. package/src/core/land/reactive/ReactiveLexer.ts +0 -181
  138. package/src/core/land/reactive/ReactiveListener.ts +0 -323
  139. package/src/core/land/reactive/ReactiveParser.js +0 -1573
  140. package/src/core/land/reactive/ReactiveParser.ts +0 -1776
  141. package/src/core/land/reactive/ReactiveVisitor.js +0 -1
  142. package/src/core/land/reactive/ReactiveVisitor.ts +0 -218
  143. package/src/core/land/reactive/compiler/ReactiveCompiler.js +0 -350
  144. package/src/core/land/reactive/compiler/ReactiveNearlyCompiler.js +0 -166
  145. package/src/core/land/reactive/compiler/ReactiveParser.js +0 -34
  146. package/src/core/land/reactive/nearley/ReactiveNearley.js +0 -187
  147. /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
@@ -5,7 +5,7 @@
5
5
  "description": "Fully featured ECS game engine written in JavaScript",
6
6
  "type": "module",
7
7
  "author": "Alexander Goldring",
8
- "version": "2.48.23",
8
+ "version": "2.49.1",
9
9
  "main": "build/meep.module.js",
10
10
  "module": "build/meep.module.js",
11
11
  "exports": {
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() {
@@ -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
- assert(a === b, m) // eslint-disable-line eqeqeq
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) {
@@ -4,7 +4,7 @@
4
4
  * @param {number} x expected to be an integer
5
5
  * @return {number}
6
6
  */
7
- function ctz32(x) {
7
+ export function ctz32(x) {
8
8
  let n = 0;
9
9
 
10
10
  if ((x & 0xffff) === 0) {
@@ -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
+ });
@@ -0,0 +1,7 @@
1
+ import { uint82float } from "./uint82float.js";
2
+
3
+ test("correctness", () => {
4
+ expect(uint82float(0)).toBe(0);
5
+ expect(uint82float(1)).toBeCloseTo(1 / 255);
6
+ expect(uint82float(255)).toBe(1);
7
+ });
@@ -0,0 +1,7 @@
1
+ import IndexedBinaryBVH from "./IndexedBinaryBVH.js";
2
+
3
+ test("constructor does not throw", () => {
4
+ expect(() => new IndexedBinaryBVH()).not.toThrow();
5
+ });
6
+
7
+
@@ -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 0;
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 i = 0; i < 6; i++) {
71
- const plane_address = i * 4;
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 << i)) !== 0) {
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
- optimize(node, 100);
104
+ describe.skip("suite", () => {
108
105
 
109
- expect(node.left).toBeNull();
110
- expect(node.right).toBeNull();
111
- });
112
106
 
113
- test("does nothing on optimal 2 child tree", () => {
114
- const a = leaf(0, 1, "hello");
115
- const b = leaf(2, 3, "goodbye");
107
+ test("empty node", () => {
108
+ const node = new BinaryNode();
109
+ node.setInfiniteBounds();
116
110
 
117
- const root = pair(a, b);
111
+ optimize(node, 100);
118
112
 
119
- const optimized = optimize(root, 100);
120
- expect(optimized).toBe(0);
113
+ expect(node.left).toBeNull();
114
+ expect(node.right).toBeNull();
115
+ });
121
116
 
122
- //positions preserved
123
- expect(root.left.object).toEqual(a.object);
124
- expect(root.right.object).toEqual(b.object);
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
- //parent node is root
127
- expect(root.left.parentNode).toEqual(root);
128
- expect(root.right.parentNode).toEqual(root);
121
+ const root = pair(a, b);
129
122
 
130
- expect(root).toBeValid();
131
- });
123
+ const optimized = optimize(root, 100);
124
+ expect(optimized).toBe(0);
132
125
 
133
- test("does nothing on optimal depth 2 tree", () => {
134
- const a = leaf(-2, -1, "a");
135
- const b = leaf(-1, 0, "b");
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
- const n0 = pair(a, b);
140
- const n1 = pair(c, d);
130
+ //parent node is root
131
+ expect(root.left.parentNode).toEqual(root);
132
+ expect(root.right.parentNode).toEqual(root);
141
133
 
142
- const root = pair(n0, n1);
134
+ expect(root).toBeValid();
135
+ });
143
136
 
144
- const optimized = optimize(root, 100);
145
- expect(optimized).toBe(0);
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
- expect(root.parentNode).toBeNull();
143
+ const n0 = pair(a, b);
144
+ const n1 = pair(c, d);
148
145
 
149
- expect(root.left).toBe(n0);
150
- expect(root.right).toBe(n1);
146
+ const root = pair(n0, n1);
151
147
 
152
- expect(n0.left).toBe(a);
153
- expect(n0.right).toBe(b);
148
+ const optimized = optimize(root, 100);
149
+ expect(optimized).toBe(0);
154
150
 
155
- expect(n1.left).toBe(c);
156
- expect(n1.right).toBe(d);
151
+ expect(root.parentNode).toBeNull();
157
152
 
158
- expect(root).toBeValid();
159
- });
153
+ expect(root.left).toBe(n0);
154
+ expect(root.right).toBe(n1);
160
155
 
161
- test("produces a valid tree from left-leaning tree with 4 leaves", () => {
162
- const a = leaf(-2, -1, "a");
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
- const root = pair(
168
- pair(
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
- optimize(root, 100);
162
+ expect(root).toBeValid();
163
+ });
176
164
 
177
- expect(root).toBeValid();
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
- expect(root).toContainNode(a);
180
- expect(root).toContainNode(b);
181
- expect(root).toContainNode(c);
182
- expect(root).toContainNode(d);
183
- });
171
+ const root = pair(
172
+ pair(
173
+ pair(c, d),
174
+ b
175
+ ),
176
+ a
177
+ );
184
178
 
185
- test("produces a valid tree from right-leaning tree with 4 leaves", () => {
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
- const root = pair(
192
- a,
193
- pair(
194
- b,
195
- pair(c, d)
196
- )
197
- );
181
+ expect(root).toBeValid();
198
182
 
199
- optimize(root, 100);
183
+ expect(root).toContainNode(a);
184
+ expect(root).toContainNode(b);
185
+ expect(root).toContainNode(c);
186
+ expect(root).toContainNode(d);
187
+ });
200
188
 
201
- expect(root).toBeValid();
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
- expect(root).toContainNode(a);
204
- expect(root).toContainNode(b);
205
- expect(root).toContainNode(c);
206
- expect(root).toContainNode(d);
207
- });
195
+ const root = pair(
196
+ a,
197
+ pair(
198
+ b,
199
+ pair(c, d)
200
+ )
201
+ );
208
202
 
209
- test("100 node random tree optimization does not degrade quality", () => {
210
- const random = seededRandom(42);
203
+ optimize(root, 100);
211
204
 
212
- const nodes = [];
205
+ expect(root).toBeValid();
213
206
 
214
- for (let i = 0; i < 100; i++) {
215
- const x0 = random() * 100;
216
- const y0 = random() * 100;
217
- const z0 = random() * 100;
207
+ expect(root).toContainNode(a);
208
+ expect(root).toContainNode(b);
209
+ expect(root).toContainNode(c);
210
+ expect(root).toContainNode(d);
211
+ });
218
212
 
219
- const x1 = x0 + random() * 5;
220
- const y1 = y0 + random() * 5;
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.push(new LeafNode(i, x0, y0, z0, x1, y1, z1));
224
- }
216
+ const nodes = [];
225
217
 
226
- while (nodes.length >= 2) {
227
- const left = nodes.pop();
228
- const right = nodes.pop();
229
- nodes.unshift(pair(left, right));
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
- const root = nodes[0];
227
+ nodes.push(new LeafNode(i, x0, y0, z0, x1, y1, z1));
228
+ }
233
229
 
234
- const oldSAH = root.computeSAH();
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
- optimize(root, 100);
236
+ const root = nodes[0];
237
237
 
238
- expect(root).toBeValid();
238
+ const oldSAH = root.computeSAH();
239
239
 
240
- const newSAH = root.computeSAH();
240
+ optimize(root, 100);
241
241
 
242
- //at least not degraded
243
- expect(newSAH).toBeLessThanOrEqual(oldSAH);
244
- });
242
+ expect(root).toBeValid();
245
243
 
246
- test("case 0: 4 node tree optimization does not degrade quality", () => {
247
- const ll = new LeafNode("ll",
248
- 76.06244471671744,
249
- 7.73902752171125,
250
- 1.925105413576489,
251
- 94.49883157197291,
252
- 50.63123012084361,
253
- 76.75841101302467
254
- );
255
-
256
- const lr = new LeafNode("lr",
257
- 76.11310176957886,
258
- 58.65097077867176,
259
- 11.346076624795387,
260
- 97.55653706044541,
261
- 89.91247777413719,
262
- 90.73181902923352
263
- );
264
-
265
- const rl = new LeafNode("rl",
266
- 32.4771196630536,
267
- 0.9366270797727339,
268
- 1.378434756588831,
269
- 66.71670340545461,
270
- 99.32784918828929,
271
- 97.52435446605432
272
- );
273
-
274
- const rr = new LeafNode("rr",
275
- 1.124263022938976,
276
- 0.13232239543867763,
277
- 2.702786005283997,
278
- 31.51776058888572,
279
- 94.87720282424561,
280
- 101.03932220629758
281
- );
282
-
283
- const root = pair(pair(ll, lr), pair(rl, rr));
284
-
285
- expect(root).toBeValid();
286
-
287
- const oldSAH = root.computeSAH();
288
-
289
- optimize(root, 1000);
290
-
291
- expect(root).toBeValid();
292
-
293
- const newSAH = root.computeSAH();
294
-
295
- //at least not degraded
296
- expect(newSAH).toBeLessThanOrEqual(oldSAH);
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 = 4;
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 = 4;
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]);
@@ -0,0 +1,7 @@
1
+ import LineBuilder from "./LineBuilder.js";
2
+
3
+ test("Empty builder should produce empty string", () => {
4
+ const b = new LineBuilder();
5
+
6
+ expect(b.build()).toEqual("");
7
+ });
@@ -368,9 +368,9 @@ export class CuckooFilter {
368
368
  }
369
369
 
370
370
  /**
371
- * Puts an element into this {@code CuckooFilter}. Ensures that subsequent
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 {@code true}.
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} {@code true} if the cuckoo filter inserts this item successfully.
384
- * Returns {@code false} if insertion failed.
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 {@code CuckooFilter}. In most cases you
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( {@code #mightContain(Object)} returning false for an item that
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
- * {@code #approximateCount(Object)} to return both lower and higher than
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} {@code true} if the cuckoo filter deleted this item successfully.
479
- * Returns {@code false} if the item was not found.
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 {@code true} if the element <i>might</i> have been put in this
512
- * Cuckoo filter, {@code false} if this is <i>definitely</i> not the case.
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
+ }