@woosh/meep-engine 2.67.0 → 2.69.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/bundle-worker-terrain.js +1 -1
- package/build/meep.cjs +698 -1270
- package/build/meep.min.js +1 -1
- package/build/meep.module.js +698 -1270
- package/package.json +1 -1
- package/src/core/bvh2/binary/2/BinaryUint32BVH.js +55 -28
- package/src/core/bvh2/binary/2/BinaryUint32BVH.spec.js +3 -3
- package/src/core/bvh2/binary/2/bvh32_query_user_data_overlaps_clipping_volume.js +94 -0
- package/src/core/bvh2/binary/2/bvh32_query_user_data_ray.js +17 -18
- package/src/core/bvh2/bvh3/query/BVHQueryIntersectsFrustum.js +4 -2
- package/src/core/geom/3d/aabb/AABB3.js +14 -14
- package/src/core/geom/3d/aabb/aabb3_array_intersects_clipping_volume_array.js +30 -0
- package/src/core/geom/3d/aabb/aabb3_intersects_clipping_volume_array.js +51 -0
- package/src/core/geom/3d/frustum/{read_frustum_planes_to_array.js → read_three_planes_to_array.js} +5 -3
- package/src/core/geom/3d/triangle/triangle_intersects_clipping_volume.js +51 -0
- package/src/engine/ecs/terrain/ecs/TerrainSystem.js +2 -2
- package/src/engine/ecs/terrain/ecs/makeTerrainWorkerProxy.js +1 -1
- package/src/engine/ecs/terrain/tiles/TerrainTile.js +9 -46
- package/src/engine/graphics/ecs/mesh/Mesh.d.ts +0 -1
- package/src/engine/graphics/ecs/mesh-v2/ShadedGeometry.d.ts +0 -5
- package/src/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +0 -1
- package/src/engine/graphics/geometry/buffered/query/GeometrySpatialQueryAccelerator.d.ts +2 -2
- package/src/engine/graphics/geometry/buffered/query/GeometrySpatialQueryAccelerator.js +79 -36
- package/src/engine/graphics/geometry/buffered/query/bvh32_geometry_overlap_clipping_volume.js +88 -0
- package/src/engine/graphics/geometry/buffered/query/bvh32_geometry_raycast.js +108 -0
- package/src/engine/graphics/geometry/bvh/buffered/bvh32_from_indexed_geometry.js +4 -30
- package/src/engine/graphics/geometry/bvh/buffered/bvh32_from_unindexed_geometry.js +30 -0
- package/src/engine/graphics/geometry/bvh/buffered/bvh32_set_leaf_from_triangle.js +41 -0
- package/src/engine/graphics/material/optimization/prototypeMaterialOptimizer.js +16 -19
- package/src/engine/graphics/render/forward_plus/LightManager.js +2 -2
- package/src/engine/graphics/render/forward_plus/prototype/prototypeLightManager.js +46 -47
- package/src/engine/graphics/render/forward_plus/query/query_bvh_frustum_from_texture.js +2 -2
- package/src/engine/graphics/render/view/CameraView.js +8 -8
- package/src/core/bvh2/BVHTasks.js +0 -65
- package/src/core/bvh2/BinaryNode.d.ts +0 -13
- package/src/core/bvh2/BinaryNode.js +0 -1188
- package/src/core/bvh2/BinaryNode.spec.js +0 -309
- package/src/core/bvh2/LeafNode.d.ts +0 -7
- package/src/core/bvh2/LeafNode.js +0 -147
- package/src/core/bvh2/Node.d.ts +0 -9
- package/src/core/bvh2/Node.js +0 -196
- package/src/core/bvh2/NodeValidator.js +0 -197
- package/src/core/bvh2/StacklessTraverser.js +0 -154
- package/src/core/bvh2/StacklessTraverser.spec.js +0 -109
- package/src/core/bvh2/binary/BinaryBVH.js +0 -281
- package/src/core/bvh2/binary/IndexedBinaryBVH.js +0 -407
- package/src/core/bvh2/binary/IndexedBinaryBVH.spec.js +0 -27
- package/src/core/bvh2/binary/IndexedBinaryBVHVisitor.js +0 -11
- package/src/core/bvh2/binary/NodeType.js +0 -8
- package/src/core/bvh2/binary/RayLeafIntersectionVisitor.js +0 -59
- package/src/core/bvh2/serialization/deserializeBinaryNode.js +0 -40
- package/src/core/bvh2/serialization/deserializeBinaryNodeFromBinaryBuffer.js +0 -90
- package/src/core/bvh2/serialization/serializeBinaryNode.js +0 -31
- package/src/core/bvh2/serialization/serializeBinaryNodeToBinaryBuffer.js +0 -86
- package/src/core/bvh2/transform/BottomUpOptimizingRebuilder.js +0 -144
- package/src/core/bvh2/transform/RotationOptimizer.js +0 -123
- package/src/core/bvh2/transform/RotationOptimizer.spec.js +0 -303
- package/src/core/bvh2/transform/tryRotateSingleNode.js +0 -260
- package/src/core/bvh2/traversal/BVHVisitor.js +0 -30
- package/src/core/bvh2/traversal/RaycastBVHVisitor.js +0 -66
- package/src/core/bvh2/traversal/ThreeClippingPlaneComputingBVHVisitor.js +0 -384
- package/src/core/bvh2/traversal/ThreeFrustumsIntersectionBVHVisitor.js +0 -52
- package/src/core/bvh2/traversal/bvh_traverse_pre_order_using_stack.js +0 -43
- package/src/core/bvh2/traversal/queryBinaryNode_ClippingPlanes.d.ts +0 -5
- package/src/core/bvh2/traversal/queryBinaryNode_ClippingPlanes.js +0 -66
- package/src/core/bvh2/traversal/queryBinaryNode_CollectData.js +0 -49
- package/src/core/bvh2/traversal/queryBinaryNode_CollectLeaves.js +0 -51
- package/src/core/bvh2/traversal/queryBinaryNode_FrustumIntersections.js +0 -77
- package/src/core/bvh2/traversal/queryBinaryNode_SphereIntersections.js +0 -63
- package/src/core/bvh2/traversal/traverseBinaryNodeUsingVisitor.js +0 -50
- package/src/core/bvh2/traversal/traverseBinaryNodeUsingVisitor_DepthFirst_PreOrder.js +0 -34
- package/src/core/bvh2/util/find_least_common_ancestor.js +0 -34
- package/src/core/bvh2/visual/convert_bvh_to_dot_format_string.js +0 -50
- package/src/core/geom/2d/bvh/BinaryNode2.js +0 -152
- package/src/core/geom/2d/bvh/LeafNode2.js +0 -11
- package/src/core/geom/2d/bvh/Node2.js +0 -51
- package/src/core/geom/3d/aabb/aabb3_array_intersects_frustum_array.js +0 -20
- package/src/core/geom/3d/aabb/aabb3_intersects_frustum_array.js +0 -35
- package/src/engine/ecs/terrain/tiles/FirstRayIntersectionTerrainBVHVisitor.js +0 -74
- package/src/engine/graphics/geometry/buffered/query/ClippingPlaneContainmentComputingVisitor.js +0 -195
- package/src/engine/graphics/geometry/buffered/query/GeometryVisitor.js +0 -87
- package/src/engine/graphics/geometry/buffered/query/RaycastNearestHitComputingVisitor.js +0 -206
- package/src/engine/graphics/geometry/bvh/BVHFromGeometry.js +0 -72
- package/src/engine/graphics/geometry/bvh/buffered/BVHGeometryRaycaster.js +0 -240
- package/src/engine/graphics/geometry/bvh/buffered/BinaryBVHFromBufferGeometry.js +0 -123
- package/src/engine/graphics/geometry/bvh/buffered/IndexedTraingleBoundsComputer.js +0 -43
- package/src/engine/graphics/render/forward_plus/query/query_bvh_frustum_from_objects.js +0 -133
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
import { BinaryNode } from "./BinaryNode.js";
|
|
2
|
-
import { isLeaf } from "./LeafNode.js";
|
|
3
|
-
import { buildShortStringPath } from "./Node.js";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
*
|
|
7
|
-
* @param {Node} node
|
|
8
|
-
* @param {ViolationType} type
|
|
9
|
-
* @param {String} message
|
|
10
|
-
* @constructor
|
|
11
|
-
*/
|
|
12
|
-
function Violation(node, type, message) {
|
|
13
|
-
this.node = node;
|
|
14
|
-
this.type = type;
|
|
15
|
-
this.message = message;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
Violation.prototype.toString = function () {
|
|
20
|
-
return `Path: ${buildShortStringPath(this.node, 5)}, Type: ${this.type}, Message: ${this.message}`;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
*
|
|
25
|
-
* @enum {string}
|
|
26
|
-
*/
|
|
27
|
-
const ViolationType = {
|
|
28
|
-
IllegalChildValue: "illegal child value",
|
|
29
|
-
IllegalParentValue: "illegal parent value",
|
|
30
|
-
Containment: "containment",
|
|
31
|
-
Bounds: "bounds"
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
*
|
|
37
|
-
* @param {BinaryNode} node
|
|
38
|
-
* @param {function(Violation)} violationCallback
|
|
39
|
-
* @returns {boolean}
|
|
40
|
-
*/
|
|
41
|
-
function validateTree(node, violationCallback) {
|
|
42
|
-
const visited = new Set();
|
|
43
|
-
let violatingNodes = 0;
|
|
44
|
-
node.traversePreOrder(function (n) {
|
|
45
|
-
if (visited.has(n)) {
|
|
46
|
-
violatingNodes++;
|
|
47
|
-
addReason(node, ViolationType.Containment, `node is found in multiple locations in the tree`, violationCallback);
|
|
48
|
-
} else {
|
|
49
|
-
visited.add(n);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
let isValid = validateNode(n, violationCallback);
|
|
53
|
-
|
|
54
|
-
if (!isValid) {
|
|
55
|
-
violatingNodes++;
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
return violatingNodes === 0;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function addReason(node, type, message, reasonCallback, reasonCallbackThisArg) {
|
|
62
|
-
if (typeof reasonCallback === "function") {
|
|
63
|
-
const violation = new Violation(node, type, message);
|
|
64
|
-
reasonCallback.call(reasonCallbackThisArg, violation);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
*
|
|
70
|
-
* @param {NodeDescription} node
|
|
71
|
-
* @param {function(Violation)} violationCallback
|
|
72
|
-
* @param reasonCallbackThisArg
|
|
73
|
-
* @returns {boolean}
|
|
74
|
-
*/
|
|
75
|
-
function validateNode(node, violationCallback, reasonCallbackThisArg) {
|
|
76
|
-
let result = true;
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
*
|
|
80
|
-
* @param {*} value
|
|
81
|
-
* @param {string} name
|
|
82
|
-
* @returns {boolean}
|
|
83
|
-
*/
|
|
84
|
-
function validateCoordinate(value, name) {
|
|
85
|
-
let result = true;
|
|
86
|
-
if (typeof value !== "number") {
|
|
87
|
-
addReason(node, ViolationType.Bounds, `${name} must be a number, but instead was ${typeof value}`, violationCallback, reasonCallbackThisArg);
|
|
88
|
-
result = false;
|
|
89
|
-
} else if (Number.isNaN(value)) {
|
|
90
|
-
addReason(node, ViolationType.Bounds, `${name} is NaN`, violationCallback, reasonCallbackThisArg);
|
|
91
|
-
result = false;
|
|
92
|
-
}
|
|
93
|
-
return result;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
function validateAxis(name) {
|
|
97
|
-
const v0Name = name + "0";
|
|
98
|
-
const v1Name = name + "1";
|
|
99
|
-
|
|
100
|
-
const v0 = node[v0Name];
|
|
101
|
-
const v1 = node[v1Name];
|
|
102
|
-
|
|
103
|
-
const valid0 = validateCoordinate(v0, v0Name);
|
|
104
|
-
const valid1 = validateCoordinate(v1, v1Name);
|
|
105
|
-
|
|
106
|
-
if (!valid0 || !valid1) {
|
|
107
|
-
result = false;
|
|
108
|
-
} else if (v0 > v1) {
|
|
109
|
-
addReason(node, ViolationType.Bounds, `${v0Name}(=${v0}) > ${v1Name}(=${v1}), negative size`, violationCallback, reasonCallbackThisArg);
|
|
110
|
-
result = false;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
//check bounds
|
|
115
|
-
validateAxis("x");
|
|
116
|
-
validateAxis("y");
|
|
117
|
-
validateAxis("z");
|
|
118
|
-
|
|
119
|
-
if (!isLeaf(node)) {
|
|
120
|
-
const binaryNodeConstraintsValid = validateBinaryNode(node, violationCallback, reasonCallbackThisArg);
|
|
121
|
-
if (!binaryNodeConstraintsValid) {
|
|
122
|
-
result = false;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
return result;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
*
|
|
131
|
-
* @param {BinaryNode} node
|
|
132
|
-
* @param {function(Violation)} [reasonCallback]
|
|
133
|
-
* @param {*} [reasonCallbackThisArg]
|
|
134
|
-
* @returns {boolean}
|
|
135
|
-
*/
|
|
136
|
-
function validateBinaryNode(node, reasonCallback, reasonCallbackThisArg) {
|
|
137
|
-
|
|
138
|
-
function validateChild(child, name) {
|
|
139
|
-
if (child === null) {
|
|
140
|
-
return true;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
if (child === undefined) {
|
|
144
|
-
addReason(node, ViolationType.IllegalChildValue, name + " child is 'undefined', this is an illegal value.", reasonCallback, reasonCallbackThisArg);
|
|
145
|
-
return false;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
if (child.parentNode !== node) {
|
|
149
|
-
addReason(node, ViolationType.IllegalParentValue, name + " child is parented to different node than this one.", reasonCallback, reasonCallbackThisArg);
|
|
150
|
-
return false;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
if (!node.containsBox(child)) {
|
|
154
|
-
addReason(node, ViolationType.Containment, name + " child violates parent's bounds", reasonCallback, reasonCallbackThisArg);
|
|
155
|
-
return false;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
return true;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
let result = true;
|
|
162
|
-
|
|
163
|
-
result = result && validateChild(node.left, "left");
|
|
164
|
-
result = result && validateChild(node.right, "right");
|
|
165
|
-
|
|
166
|
-
//left and right node must be different nodes
|
|
167
|
-
if (node.left !== null && node.left === node.right) {
|
|
168
|
-
addReason(node, ViolationType.IllegalChildValue, "left and right child are the same non-null node", reasonCallback, reasonCallbackThisArg);
|
|
169
|
-
result = false;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
return result;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
function validateContainment(node, violation) {
|
|
176
|
-
if (node.left !== null) {
|
|
177
|
-
if (!node.containsBox(node.left)) {
|
|
178
|
-
violation(node.left)
|
|
179
|
-
} else if (node.left instanceof BinaryNode) {
|
|
180
|
-
validateContainment(node.left, violation);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
}
|
|
184
|
-
if (node.right !== null) {
|
|
185
|
-
if (!node.containsBox(node.right)) {
|
|
186
|
-
violation(node.right)
|
|
187
|
-
} else if (node.right instanceof BinaryNode) {
|
|
188
|
-
validateContainment(node.right, violation);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
export {
|
|
194
|
-
ViolationType,
|
|
195
|
-
validateNode,
|
|
196
|
-
validateTree
|
|
197
|
-
};
|
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
import { isLeaf } from "./LeafNode.js";
|
|
2
|
-
|
|
3
|
-
const StateFromParent = 0;
|
|
4
|
-
const StateFromSibling = 1;
|
|
5
|
-
const StateFromChild = 2;
|
|
6
|
-
|
|
7
|
-
function getLeft(node) {
|
|
8
|
-
return node.left;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
function parent(node) {
|
|
12
|
-
return node.parentNode;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
function sibling(node) {
|
|
16
|
-
const parentNode = node.parentNode;
|
|
17
|
-
return parentNode.right;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Implementation based on code listing from paper:
|
|
23
|
-
* "Efficient Stack-less BVH Traversal for Ray Tracing" 2011 Michal Hapala et.al
|
|
24
|
-
* http://www.sci.utah.edu/~wald/Publications/2011/StackFree/sccg2011.pdf
|
|
25
|
-
*
|
|
26
|
-
* NOTE: Based on a few quick benchmarks this algorithm is slower than using stack
|
|
27
|
-
* NOTE: this algorithm could be useful for incremental traversal as it retains state
|
|
28
|
-
*/
|
|
29
|
-
function StacklessTraverser() {
|
|
30
|
-
this.state = 0;
|
|
31
|
-
/**
|
|
32
|
-
*
|
|
33
|
-
* @type {BinaryNode|null}
|
|
34
|
-
*/
|
|
35
|
-
this.current = null;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
*
|
|
40
|
-
* @param {BinaryNode} node
|
|
41
|
-
*/
|
|
42
|
-
StacklessTraverser.prototype.init = function (node) {
|
|
43
|
-
this.root = node;
|
|
44
|
-
this.state = StateFromParent;
|
|
45
|
-
this.current = node;
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
*
|
|
50
|
-
* Advanced traverser. Visitor will be invoked only on those advancements that produce a unique visit
|
|
51
|
-
* @param {function(node:NodeDescription):boolean} visitor terminate branch and do no traverse descendants when visitor returns false
|
|
52
|
-
* @param {*} [thisArg]
|
|
53
|
-
* @returns {boolean}
|
|
54
|
-
*/
|
|
55
|
-
StacklessTraverser.prototype.advance = function (visitor, thisArg) {
|
|
56
|
-
let n;
|
|
57
|
-
|
|
58
|
-
let state = this.state, current = this.current;
|
|
59
|
-
|
|
60
|
-
switch (state) {
|
|
61
|
-
case StateFromChild:
|
|
62
|
-
//traversal up
|
|
63
|
-
if (current === this.root) {
|
|
64
|
-
//finished
|
|
65
|
-
return false;
|
|
66
|
-
}
|
|
67
|
-
n = sibling(current);
|
|
68
|
-
if (current === n || n == null) {
|
|
69
|
-
//ascend
|
|
70
|
-
current = parent(current);
|
|
71
|
-
state = StateFromChild;
|
|
72
|
-
} else {
|
|
73
|
-
//move right
|
|
74
|
-
current = n;
|
|
75
|
-
state = StateFromSibling;
|
|
76
|
-
}
|
|
77
|
-
break;
|
|
78
|
-
case StateFromSibling:
|
|
79
|
-
if (visitor.call(thisArg, current) === false || isLeaf(current)) {
|
|
80
|
-
current = parent(current);
|
|
81
|
-
state = StateFromChild;
|
|
82
|
-
} else {
|
|
83
|
-
n = getLeft(current);
|
|
84
|
-
if (n === null) {
|
|
85
|
-
//ascent
|
|
86
|
-
current = parent(current);
|
|
87
|
-
state = StateFromChild;
|
|
88
|
-
} else {
|
|
89
|
-
//descend
|
|
90
|
-
current = n;
|
|
91
|
-
state = StateFromParent;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
break;
|
|
95
|
-
case StateFromParent:
|
|
96
|
-
if (visitor.call(thisArg, current) === false || isLeaf(current)) {
|
|
97
|
-
n = sibling(current);
|
|
98
|
-
if (n == null) {
|
|
99
|
-
//ascend
|
|
100
|
-
current = parent(current);
|
|
101
|
-
state = StateFromChild;
|
|
102
|
-
} else {
|
|
103
|
-
//more right
|
|
104
|
-
current = n;
|
|
105
|
-
state = StateFromSibling;
|
|
106
|
-
}
|
|
107
|
-
} else {
|
|
108
|
-
n = getLeft(current);
|
|
109
|
-
if (n === null) {
|
|
110
|
-
if (current.parentNode === null) {
|
|
111
|
-
//already at root
|
|
112
|
-
n = current.right;
|
|
113
|
-
if (n === null) {
|
|
114
|
-
//put traverser into terminal state
|
|
115
|
-
current = this.root;
|
|
116
|
-
state = StateFromChild;
|
|
117
|
-
} else {
|
|
118
|
-
current = n;
|
|
119
|
-
state = StateFromSibling;
|
|
120
|
-
}
|
|
121
|
-
} else {
|
|
122
|
-
|
|
123
|
-
n = sibling(current);
|
|
124
|
-
if (n === null) {
|
|
125
|
-
//ascent
|
|
126
|
-
current = parent(current);
|
|
127
|
-
state = StateFromChild;
|
|
128
|
-
|
|
129
|
-
} else {
|
|
130
|
-
current = n;
|
|
131
|
-
state = StateFromSibling;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
} else {
|
|
135
|
-
//descend
|
|
136
|
-
current = n;
|
|
137
|
-
state = StateFromParent;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
break;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
this.current = current;
|
|
144
|
-
this.state = state;
|
|
145
|
-
|
|
146
|
-
return true;
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
export {
|
|
150
|
-
StacklessTraverser,
|
|
151
|
-
StateFromParent,
|
|
152
|
-
StateFromSibling,
|
|
153
|
-
StateFromChild
|
|
154
|
-
};
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import { jest } from "@jest/globals";
|
|
2
|
-
import { BinaryNode } from "./BinaryNode.js";
|
|
3
|
-
import { StacklessTraverser } from "./StacklessTraverser.js";
|
|
4
|
-
|
|
5
|
-
test("empty node traversal", () => {
|
|
6
|
-
const node = new BinaryNode();
|
|
7
|
-
|
|
8
|
-
const traverser = new StacklessTraverser();
|
|
9
|
-
|
|
10
|
-
traverser.init(node);
|
|
11
|
-
|
|
12
|
-
const visitor = jest.fn();
|
|
13
|
-
|
|
14
|
-
expect(traverser.advance(visitor)).toBe(true);
|
|
15
|
-
|
|
16
|
-
expect(visitor).toHaveBeenCalledTimes(1);
|
|
17
|
-
expect(visitor).toHaveBeenCalledWith(node);
|
|
18
|
-
|
|
19
|
-
expect(traverser.advance(visitor)).toBe(false);
|
|
20
|
-
|
|
21
|
-
expect(visitor).toHaveBeenCalledTimes(1);
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
test("only left child", () => {
|
|
25
|
-
const node = new BinaryNode();
|
|
26
|
-
node.left = new BinaryNode();
|
|
27
|
-
node.left.parentNode = node;
|
|
28
|
-
|
|
29
|
-
const traverser = new StacklessTraverser();
|
|
30
|
-
|
|
31
|
-
traverser.init(node);
|
|
32
|
-
|
|
33
|
-
const visitor = jest.fn();
|
|
34
|
-
|
|
35
|
-
expect(traverser.advance(visitor)).toBe(true);
|
|
36
|
-
|
|
37
|
-
expect(visitor).toHaveBeenCalledTimes(1);
|
|
38
|
-
expect(visitor).toHaveBeenCalledWith(node);
|
|
39
|
-
|
|
40
|
-
expect(traverser.advance(visitor)).toBe(true);
|
|
41
|
-
|
|
42
|
-
expect(visitor).toHaveBeenCalledTimes(2);
|
|
43
|
-
expect(visitor).toHaveBeenLastCalledWith(node.left);
|
|
44
|
-
|
|
45
|
-
expect(traverser.advance(visitor)).toBe(false);
|
|
46
|
-
|
|
47
|
-
expect(visitor).toHaveBeenCalledTimes(2);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
test("only right child", () => {
|
|
51
|
-
const node = new BinaryNode();
|
|
52
|
-
node.right = new BinaryNode();
|
|
53
|
-
node.right.parentNode = node;
|
|
54
|
-
|
|
55
|
-
const traverser = new StacklessTraverser();
|
|
56
|
-
|
|
57
|
-
traverser.init(node);
|
|
58
|
-
|
|
59
|
-
const visitor = jest.fn();
|
|
60
|
-
|
|
61
|
-
expect(traverser.advance(visitor)).toBe(true);
|
|
62
|
-
|
|
63
|
-
expect(visitor).toHaveBeenCalledTimes(1);
|
|
64
|
-
expect(visitor).toHaveBeenCalledWith(node);
|
|
65
|
-
|
|
66
|
-
expect(traverser.advance(visitor)).toBe(true);
|
|
67
|
-
|
|
68
|
-
expect(visitor).toHaveBeenCalledTimes(2);
|
|
69
|
-
expect(visitor).toHaveBeenLastCalledWith(node.right);
|
|
70
|
-
|
|
71
|
-
expect(traverser.advance(visitor)).toBe(false);
|
|
72
|
-
|
|
73
|
-
expect(visitor).toHaveBeenCalledTimes(2);
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
test("node with left and right child", () => {
|
|
77
|
-
const node = new BinaryNode();
|
|
78
|
-
|
|
79
|
-
node.right = new BinaryNode();
|
|
80
|
-
node.right.parentNode = node;
|
|
81
|
-
|
|
82
|
-
node.left = new BinaryNode();
|
|
83
|
-
node.left.parentNode = node;
|
|
84
|
-
|
|
85
|
-
const traverser = new StacklessTraverser();
|
|
86
|
-
|
|
87
|
-
traverser.init(node);
|
|
88
|
-
|
|
89
|
-
const visitor = jest.fn();
|
|
90
|
-
|
|
91
|
-
expect(traverser.advance(visitor)).toBe(true);
|
|
92
|
-
|
|
93
|
-
expect(visitor).toHaveBeenCalledTimes(1);
|
|
94
|
-
expect(visitor).toHaveBeenCalledWith(node);
|
|
95
|
-
|
|
96
|
-
expect(traverser.advance(visitor)).toBe(true);
|
|
97
|
-
|
|
98
|
-
expect(visitor).toHaveBeenCalledTimes(2);
|
|
99
|
-
expect(visitor).toHaveBeenLastCalledWith(node.left);
|
|
100
|
-
|
|
101
|
-
expect(traverser.advance(visitor)).toBe(true);
|
|
102
|
-
|
|
103
|
-
expect(visitor).toHaveBeenCalledTimes(3);
|
|
104
|
-
expect(visitor).toHaveBeenLastCalledWith(node.right);
|
|
105
|
-
|
|
106
|
-
expect(traverser.advance(visitor)).toBe(false);
|
|
107
|
-
|
|
108
|
-
expect(visitor).toHaveBeenCalledTimes(3);
|
|
109
|
-
});
|