diff --git a/dist/main.cjs b/dist/main.cjs
index c3ace59..9ed46e1 100644
--- a/dist/main.cjs
+++ b/dist/main.cjs
@@ -1070,7 +1070,7 @@ function intersectShape2Shape(shape1, shape2) {
function intersectShape2Multiline(shape, multiline) {
let ip = [];
for (let edge of multiline) {
- ip = [...ip, ...intersectShape2Shape(edge, edge.shape)];
+ ip = [...ip, ...intersectShape2Shape(shape, edge.shape)];
}
return ip;
}
@@ -3359,7 +3359,7 @@ Flatten.matrix = matrix;
/**
* Interval is a pair of numbers or a pair of any comparable objects on which may be defined predicates
* *equal*, *less* and method *max(p1, p1)* that returns maximum in a pair.
- * When interval is an object rather than a pair of numbers, this object should have properties *low*, *high*, *max*
+ * When interval is an object rather than pair of numbers, this object should have properties *low*, *high*, *max*
* and implement methods *less_than(), equal_to(), intersect(), not_intersect(), clone(), output()*.
* Two static methods *comparable_max(), comparable_less_than()* define how to compare values in pair.
* This interface is described in typescript definition file *index.d.ts*
@@ -3405,7 +3405,7 @@ const Interval = class Interval {
*/
less_than(other_interval) {
return this.low < other_interval.low ||
- this.low === other_interval.low && this.high < other_interval.high;
+ this.low == other_interval.low && this.high < other_interval.high;
}
/**
@@ -3414,7 +3414,7 @@ const Interval = class Interval {
* @returns {boolean}
*/
equal_to(other_interval) {
- return this.low === other_interval.low && this.high === other_interval.high;
+ return this.low == other_interval.low && this.high == other_interval.high;
}
/**
@@ -3437,15 +3437,13 @@ const Interval = class Interval {
/**
* Returns new interval merged with other interval
- * @param {Interval} other_interval - Other interval to merge with
+ * @param {Interval} interval - Other interval to merge with
* @returns {Interval}
*/
merge(other_interval) {
return new Interval(
- this.low === undefined ?
- other_interval.low : (this.low < other_interval.low ? this.low : other_interval.low),
- this.high === undefined ?
- other_interval.high : (this.high > other_interval.high ? this.high : other_interval.high)
+ this.low === undefined ? other_interval.low : Math.min(this.low, other_interval.low),
+ this.high === undefined ? other_interval.high : Math.max(this.high, other_interval.high)
);
}
@@ -3506,11 +3504,9 @@ class Node {
this.item = {key: key, value: value}; // key is supposed to be instance of Interval
/* If not, this should by an array of two numbers */
- if (key && key instanceof Array && key.length === 2) {
+ if (key && key instanceof Array && key.length == 2) {
if (!Number.isNaN(key[0]) && !Number.isNaN(key[1])) {
- let [low, high] = key;
- if (low > high) [low, high] = [high, low];
- this.item.key = new Interval(low, high);
+ this.item.key = new Interval(Math.min(key[0], key[1]), Math.max(key[0], key[1]));
}
}
@@ -3542,7 +3538,7 @@ class Node {
_value_equal(other_node) {
return this.item.value && other_node.item.value && this.item.value.equal_to ?
this.item.value.equal_to(other_node.item.value) :
- this.item.value === other_node.item.value;
+ this.item.value == other_node.item.value;
}
equal_to(other_node) {
// if tree stores only keys
@@ -3662,7 +3658,7 @@ class IntervalTree {
* @returns {boolean}
*/
isEmpty() {
- return (this.root == null || this.root === this.nil_node);
+ return (this.root == null || this.root == this.nil_node);
}
/**
@@ -3694,7 +3690,7 @@ class IntervalTree {
*/
exist(key, value = key) {
let search_node = new Node(key, value);
- return !!this.tree_search(this.root, search_node);
+ return this.tree_search(this.root, search_node) ? true : false;
}
/**
@@ -3733,7 +3729,8 @@ class IntervalTree {
*/
intersect_any(interval) {
let search_node = new Node(interval);
- return this.tree_find_any_interval(this.root, search_node);
+ let found = this.tree_find_any_interval(this.root, search_node);
+ return found;
}
/**
@@ -3745,34 +3742,15 @@ class IntervalTree {
this.tree_walk(this.root, (node) => visitor(node.item.key, node.item.value));
}
- /**
- * Value Mapper. Walk through every node and map node value to another value
- * @param callback(value,key) - function to be called for each tree item
- */
+ /** Value Mapper. Walk through every node and map node value to another value
+ * @param callback(value,key) - function to be called for each tree item
+ */
map(callback) {
const tree = new IntervalTree();
this.tree_walk(this.root, (node) => tree.insert(node.item.key, callback(node.item.value, node.item.key)));
return tree;
}
- /**
- * @param {Interval} interval - optional if the iterator is intended to start from the beginning
- * @param outputMapperFn(value,key) - optional function that maps (value, key) to custom output
- * @returns {Iterator}
- */
- *iterate(interval, outputMapperFn = (value, key) => value === key ? key.output() : value) {
- let node;
- if (interval) {
- node = this.tree_search_nearest_forward(this.root, new Node(interval));
- } else if (this.root) {
- node = this.local_minimum(this.root);
- }
- while (node) {
- yield outputMapperFn(node.item.value, node.item.key);
- node = this.tree_successor(node);
- }
- }
-
recalc_max(node) {
let node_current = node;
while (node_current.parent != null) {
@@ -3785,11 +3763,11 @@ class IntervalTree {
let current_node = this.root;
let parent_node = null;
- if (this.root == null || this.root === this.nil_node) {
+ if (this.root == null || this.root == this.nil_node) {
this.root = insert_node;
}
else {
- while (current_node !== this.nil_node) {
+ while (current_node != this.nil_node) {
parent_node = current_node;
if (insert_node.less_than(current_node)) {
current_node = current_node.left;
@@ -3819,10 +3797,10 @@ class IntervalTree {
let uncle_node;
current_node = insert_node;
- while (current_node !== this.root && current_node.parent.color === RB_TREE_COLOR_RED) {
- if (current_node.parent === current_node.parent.parent.left) { // parent is left child of grandfather
+ while (current_node != this.root && current_node.parent.color == RB_TREE_COLOR_RED) {
+ if (current_node.parent == current_node.parent.parent.left) { // parent is left child of grandfather
uncle_node = current_node.parent.parent.right; // right brother of parent
- if (uncle_node.color === RB_TREE_COLOR_RED) { // Case 1. Uncle is red
+ if (uncle_node.color == RB_TREE_COLOR_RED) { // Case 1. Uncle is red
// re-color father and uncle into black
current_node.parent.color = RB_TREE_COLOR_BLACK;
uncle_node.color = RB_TREE_COLOR_BLACK;
@@ -3830,7 +3808,7 @@ class IntervalTree {
current_node = current_node.parent.parent;
}
else { // Case 2 & 3. Uncle is black
- if (current_node === current_node.parent.right) { // Case 2. Current if right child
+ if (current_node == current_node.parent.right) { // Case 2. Current if right child
// This case is transformed into Case 3.
current_node = current_node.parent;
this.rotate_left(current_node);
@@ -3843,7 +3821,7 @@ class IntervalTree {
}
else { // parent is right child of grandfather
uncle_node = current_node.parent.parent.left; // left brother of parent
- if (uncle_node.color === RB_TREE_COLOR_RED) { // Case 4. Uncle is red
+ if (uncle_node.color == RB_TREE_COLOR_RED) { // Case 4. Uncle is red
// re-color father and uncle into black
current_node.parent.color = RB_TREE_COLOR_BLACK;
uncle_node.color = RB_TREE_COLOR_BLACK;
@@ -3851,7 +3829,7 @@ class IntervalTree {
current_node = current_node.parent.parent;
}
else {
- if (current_node === current_node.parent.left) { // Case 5. Current is left child
+ if (current_node == current_node.parent.left) { // Case 5. Current is left child
// Transform into case 6
current_node = current_node.parent;
this.rotate_right(current_node);
@@ -3871,7 +3849,7 @@ class IntervalTree {
let cut_node; // node to be cut - either delete_node or successor_node ("y" from 14.4)
let fix_node; // node to fix rb tree property ("x" from 14.4)
- if (delete_node.left === this.nil_node || delete_node.right === this.nil_node) { // delete_node has less then 2 children
+ if (delete_node.left == this.nil_node || delete_node.right == this.nil_node) { // delete_node has less then 2 children
cut_node = delete_node;
}
else { // delete_node has 2 children
@@ -3879,7 +3857,7 @@ class IntervalTree {
}
// fix_node if single child of cut_node
- if (cut_node.left !== this.nil_node) {
+ if (cut_node.left != this.nil_node) {
fix_node = cut_node.left;
}
else {
@@ -3891,11 +3869,11 @@ class IntervalTree {
fix_node.parent = cut_node.parent;
/*}*/
- if (cut_node === this.root) {
+ if (cut_node == this.root) {
this.root = fix_node;
}
else {
- if (cut_node === cut_node.parent.left) {
+ if (cut_node == cut_node.parent.left) {
cut_node.parent.left = fix_node;
}
else {
@@ -3909,13 +3887,13 @@ class IntervalTree {
// COPY DATA !!!
// Delete_node becomes cut_node, it means that we cannot hold reference
// to node in outer structure and we will have to delete by key, additional search need
- if (cut_node !== delete_node) {
+ if (cut_node != delete_node) {
delete_node.copy_data(cut_node);
delete_node.update_max(); // update max property of the cut node at the new place
this.recalc_max(delete_node); // update max property upward from delete_node to root
}
- if (/*fix_node != this.nil_node && */cut_node.color === RB_TREE_COLOR_BLACK) {
+ if (/*fix_node != this.nil_node && */cut_node.color == RB_TREE_COLOR_BLACK) {
this.delete_fixup(fix_node);
}
}
@@ -3924,23 +3902,23 @@ class IntervalTree {
let current_node = fix_node;
let brother_node;
- while (current_node !== this.root && current_node.parent != null && current_node.color === RB_TREE_COLOR_BLACK) {
- if (current_node === current_node.parent.left) { // fix node is left child
+ while (current_node != this.root && current_node.parent != null && current_node.color == RB_TREE_COLOR_BLACK) {
+ if (current_node == current_node.parent.left) { // fix node is left child
brother_node = current_node.parent.right;
- if (brother_node.color === RB_TREE_COLOR_RED) { // Case 1. Brother is red
+ if (brother_node.color == RB_TREE_COLOR_RED) { // Case 1. Brother is red
brother_node.color = RB_TREE_COLOR_BLACK; // re-color brother
current_node.parent.color = RB_TREE_COLOR_RED; // re-color father
this.rotate_left(current_node.parent);
brother_node = current_node.parent.right; // update brother
}
// Derive to cases 2..4: brother is black
- if (brother_node.left.color === RB_TREE_COLOR_BLACK &&
- brother_node.right.color === RB_TREE_COLOR_BLACK) { // case 2: both nephews black
+ if (brother_node.left.color == RB_TREE_COLOR_BLACK &&
+ brother_node.right.color == RB_TREE_COLOR_BLACK) { // case 2: both nephews black
brother_node.color = RB_TREE_COLOR_RED; // re-color brother
current_node = current_node.parent; // continue iteration
}
else {
- if (brother_node.right.color === RB_TREE_COLOR_BLACK) { // case 3: left nephew red, right nephew black
+ if (brother_node.right.color == RB_TREE_COLOR_BLACK) { // case 3: left nephew red, right nephew black
brother_node.color = RB_TREE_COLOR_RED; // re-color brother
brother_node.left.color = RB_TREE_COLOR_BLACK; // re-color nephew
this.rotate_right(brother_node);
@@ -3957,20 +3935,20 @@ class IntervalTree {
}
else { // fix node is right child
brother_node = current_node.parent.left;
- if (brother_node.color === RB_TREE_COLOR_RED) { // Case 1. Brother is red
+ if (brother_node.color == RB_TREE_COLOR_RED) { // Case 1. Brother is red
brother_node.color = RB_TREE_COLOR_BLACK; // re-color brother
current_node.parent.color = RB_TREE_COLOR_RED; // re-color father
this.rotate_right(current_node.parent);
brother_node = current_node.parent.left; // update brother
}
// Go to cases 2..4
- if (brother_node.left.color === RB_TREE_COLOR_BLACK &&
- brother_node.right.color === RB_TREE_COLOR_BLACK) { // case 2
+ if (brother_node.left.color == RB_TREE_COLOR_BLACK &&
+ brother_node.right.color == RB_TREE_COLOR_BLACK) { // case 2
brother_node.color = RB_TREE_COLOR_RED; // re-color brother
current_node = current_node.parent; // continue iteration
}
else {
- if (brother_node.left.color === RB_TREE_COLOR_BLACK) { // case 3: right nephew red, left nephew black
+ if (brother_node.left.color == RB_TREE_COLOR_BLACK) { // case 3: right nephew red, left nephew black
brother_node.color = RB_TREE_COLOR_RED; // re-color brother
brother_node.right.color = RB_TREE_COLOR_BLACK; // re-color nephew
this.rotate_left(brother_node);
@@ -3991,7 +3969,7 @@ class IntervalTree {
}
tree_search(node, search_node) {
- if (node == null || node === this.nil_node)
+ if (node == null || node == this.nil_node)
return undefined;
if (search_node.equal_to(node)) {
@@ -4005,31 +3983,12 @@ class IntervalTree {
}
}
- tree_search_nearest_forward(node, search_node) {
- let best;
- let curr = node;
- while (curr && curr !== this.nil_node) {
- if (curr.less_than(search_node)) {
- if (curr.intersect(search_node)) {
- best = curr;
- curr = curr.left;
- } else {
- curr = curr.right;
- }
- } else {
- if (!best || curr.less_than(best)) best = curr;
- curr = curr.left;
- }
- }
- return best || null;
- }
-
// Original search_interval method; container res support push() insertion
// Search all intervals intersecting given one
tree_search_interval(node, search_node, res) {
- if (node != null && node !== this.nil_node) {
+ if (node != null && node != this.nil_node) {
// if (node->left != this.nil_node && node->left->max >= low) {
- if (node.left !== this.nil_node && !node.not_intersect_left_subtree(search_node)) {
+ if (node.left != this.nil_node && !node.not_intersect_left_subtree(search_node)) {
this.tree_search_interval(node.left, search_node, res);
}
// if (low <= node->high && node->low <= high) {
@@ -4037,7 +3996,7 @@ class IntervalTree {
res.push(node);
}
// if (node->right != this.nil_node && node->low <= high) {
- if (node.right !== this.nil_node && !node.not_intersect_right_subtree(search_node)) {
+ if (node.right != this.nil_node && !node.not_intersect_right_subtree(search_node)) {
this.tree_search_interval(node.right, search_node, res);
}
}
@@ -4045,14 +4004,17 @@ class IntervalTree {
tree_find_any_interval(node, search_node) {
let found = false;
- if (node != null && node !== this.nil_node) {
- if (node.left !== this.nil_node && !node.not_intersect_left_subtree(search_node)) {
+ if (node != null && node != this.nil_node) {
+ // if (node->left != this.nil_node && node->left->max >= low) {
+ if (node.left != this.nil_node && !node.not_intersect_left_subtree(search_node)) {
found = this.tree_find_any_interval(node.left, search_node);
}
+ // if (low <= node->high && node->low <= high) {
if (!found) {
found = node.intersect(search_node);
}
- if (!found && node.right !== this.nil_node && !node.not_intersect_right_subtree(search_node)) {
+ // if (node->right != this.nil_node && node->low <= high) {
+ if (!found && node.right != this.nil_node && !node.not_intersect_right_subtree(search_node)) {
found = this.tree_find_any_interval(node.right, search_node);
}
}
@@ -4061,7 +4023,7 @@ class IntervalTree {
local_minimum(node) {
let node_min = node;
- while (node_min.left != null && node_min.left !== this.nil_node) {
+ while (node_min.left != null && node_min.left != this.nil_node) {
node_min = node_min.left;
}
return node_min;
@@ -4070,7 +4032,7 @@ class IntervalTree {
// not in use
local_maximum(node) {
let node_max = node;
- while (node_max.right != null && node_max.right !== this.nil_node) {
+ while (node_max.right != null && node_max.right != this.nil_node) {
node_max = node_max.right;
}
return node_max;
@@ -4081,13 +4043,13 @@ class IntervalTree {
let current_node;
let parent_node;
- if (node.right !== this.nil_node) {
+ if (node.right != this.nil_node) {
node_successor = this.local_minimum(node.right);
}
else {
current_node = node;
parent_node = node.parent;
- while (parent_node != null && parent_node.right === current_node) {
+ while (parent_node != null && parent_node.right == current_node) {
current_node = parent_node;
parent_node = parent_node.parent;
}
@@ -4108,16 +4070,16 @@ class IntervalTree {
x.right = y.left; // b goes to x.right
- if (y.left !== this.nil_node) {
+ if (y.left != this.nil_node) {
y.left.parent = x; // x becomes parent of b
}
y.parent = x.parent; // move parent
- if (x === this.root) {
+ if (x == this.root) {
this.root = y; // y becomes root
}
else { // y becomes child of x.parent
- if (x === x.parent.left) {
+ if (x == x.parent.left) {
x.parent.left = y;
}
else {
@@ -4127,12 +4089,12 @@ class IntervalTree {
y.left = x; // x becomes left child of y
x.parent = y; // and y becomes parent of x
- if (x != null && x !== this.nil_node) {
+ if (x != null && x != this.nil_node) {
x.update_max();
}
y = x.parent;
- if (y != null && y !== this.nil_node) {
+ if (y != null && y != this.nil_node) {
y.update_max();
}
}
@@ -4142,16 +4104,16 @@ class IntervalTree {
y.left = x.right; // b goes to y.left
- if (x.right !== this.nil_node) {
+ if (x.right != this.nil_node) {
x.right.parent = y; // y becomes parent of b
}
x.parent = y.parent; // move parent
- if (y === this.root) { // x becomes root
+ if (y == this.root) { // x becomes root
this.root = x;
}
else { // y becomes child of x.parent
- if (y === y.parent.left) {
+ if (y == y.parent.left) {
y.parent.left = x;
}
else {
@@ -4161,18 +4123,18 @@ class IntervalTree {
x.right = y; // y becomes right child of x
y.parent = x; // and x becomes parent of y
- if (y !== null && y !== this.nil_node) {
+ if (y != null && y != this.nil_node) {
y.update_max();
}
x = y.parent;
- if (x != null && x !== this.nil_node) {
+ if (x != null && x != this.nil_node) {
x.update_max();
}
}
tree_walk(node, action) {
- if (node != null && node !== this.nil_node) {
+ if (node != null && node != this.nil_node) {
this.tree_walk(node.left, action);
// arr.push(node.toArray());
action(node);
@@ -4184,8 +4146,8 @@ class IntervalTree {
testRedBlackProperty() {
let res = true;
this.tree_walk(this.root, function (node) {
- if (node.color === RB_TREE_COLOR_RED) {
- if (!(node.left.color === RB_TREE_COLOR_BLACK && node.right.color === RB_TREE_COLOR_BLACK)) {
+ if (node.color == RB_TREE_COLOR_RED) {
+ if (!(node.left.color == RB_TREE_COLOR_BLACK && node.right.color == RB_TREE_COLOR_BLACK)) {
res = false;
}
}
@@ -4198,27 +4160,27 @@ class IntervalTree {
let height = 0;
let heightLeft = 0;
let heightRight = 0;
- if (node.color === RB_TREE_COLOR_BLACK) {
+ if (node.color == RB_TREE_COLOR_BLACK) {
height++;
}
- if (node.left !== this.nil_node) {
+ if (node.left != this.nil_node) {
heightLeft = this.testBlackHeightProperty(node.left);
}
else {
heightLeft = 1;
}
- if (node.right !== this.nil_node) {
+ if (node.right != this.nil_node) {
heightRight = this.testBlackHeightProperty(node.right);
}
else {
heightRight = 1;
}
- if (heightLeft !== heightRight) {
+ if (heightLeft != heightRight) {
throw new Error('Red-black height property violated');
}
height += heightLeft;
return height;
- }
+ };
}
/**
diff --git a/dist/main.mjs b/dist/main.mjs
index a57b25f..0d1bec8 100644
--- a/dist/main.mjs
+++ b/dist/main.mjs
@@ -1066,7 +1066,7 @@ function intersectShape2Shape(shape1, shape2) {
function intersectShape2Multiline(shape, multiline) {
let ip = [];
for (let edge of multiline) {
- ip = [...ip, ...intersectShape2Shape(edge, edge.shape)];
+ ip = [...ip, ...intersectShape2Shape(shape, edge.shape)];
}
return ip;
}
@@ -3355,7 +3355,7 @@ Flatten.matrix = matrix;
/**
* Interval is a pair of numbers or a pair of any comparable objects on which may be defined predicates
* *equal*, *less* and method *max(p1, p1)* that returns maximum in a pair.
- * When interval is an object rather than a pair of numbers, this object should have properties *low*, *high*, *max*
+ * When interval is an object rather than pair of numbers, this object should have properties *low*, *high*, *max*
* and implement methods *less_than(), equal_to(), intersect(), not_intersect(), clone(), output()*.
* Two static methods *comparable_max(), comparable_less_than()* define how to compare values in pair.
* This interface is described in typescript definition file *index.d.ts*
@@ -3401,7 +3401,7 @@ const Interval = class Interval {
*/
less_than(other_interval) {
return this.low < other_interval.low ||
- this.low === other_interval.low && this.high < other_interval.high;
+ this.low == other_interval.low && this.high < other_interval.high;
}
/**
@@ -3410,7 +3410,7 @@ const Interval = class Interval {
* @returns {boolean}
*/
equal_to(other_interval) {
- return this.low === other_interval.low && this.high === other_interval.high;
+ return this.low == other_interval.low && this.high == other_interval.high;
}
/**
@@ -3433,15 +3433,13 @@ const Interval = class Interval {
/**
* Returns new interval merged with other interval
- * @param {Interval} other_interval - Other interval to merge with
+ * @param {Interval} interval - Other interval to merge with
* @returns {Interval}
*/
merge(other_interval) {
return new Interval(
- this.low === undefined ?
- other_interval.low : (this.low < other_interval.low ? this.low : other_interval.low),
- this.high === undefined ?
- other_interval.high : (this.high > other_interval.high ? this.high : other_interval.high)
+ this.low === undefined ? other_interval.low : Math.min(this.low, other_interval.low),
+ this.high === undefined ? other_interval.high : Math.max(this.high, other_interval.high)
);
}
@@ -3502,11 +3500,9 @@ class Node {
this.item = {key: key, value: value}; // key is supposed to be instance of Interval
/* If not, this should by an array of two numbers */
- if (key && key instanceof Array && key.length === 2) {
+ if (key && key instanceof Array && key.length == 2) {
if (!Number.isNaN(key[0]) && !Number.isNaN(key[1])) {
- let [low, high] = key;
- if (low > high) [low, high] = [high, low];
- this.item.key = new Interval(low, high);
+ this.item.key = new Interval(Math.min(key[0], key[1]), Math.max(key[0], key[1]));
}
}
@@ -3538,7 +3534,7 @@ class Node {
_value_equal(other_node) {
return this.item.value && other_node.item.value && this.item.value.equal_to ?
this.item.value.equal_to(other_node.item.value) :
- this.item.value === other_node.item.value;
+ this.item.value == other_node.item.value;
}
equal_to(other_node) {
// if tree stores only keys
@@ -3658,7 +3654,7 @@ class IntervalTree {
* @returns {boolean}
*/
isEmpty() {
- return (this.root == null || this.root === this.nil_node);
+ return (this.root == null || this.root == this.nil_node);
}
/**
@@ -3690,7 +3686,7 @@ class IntervalTree {
*/
exist(key, value = key) {
let search_node = new Node(key, value);
- return !!this.tree_search(this.root, search_node);
+ return this.tree_search(this.root, search_node) ? true : false;
}
/**
@@ -3729,7 +3725,8 @@ class IntervalTree {
*/
intersect_any(interval) {
let search_node = new Node(interval);
- return this.tree_find_any_interval(this.root, search_node);
+ let found = this.tree_find_any_interval(this.root, search_node);
+ return found;
}
/**
@@ -3741,34 +3738,15 @@ class IntervalTree {
this.tree_walk(this.root, (node) => visitor(node.item.key, node.item.value));
}
- /**
- * Value Mapper. Walk through every node and map node value to another value
- * @param callback(value,key) - function to be called for each tree item
- */
+ /** Value Mapper. Walk through every node and map node value to another value
+ * @param callback(value,key) - function to be called for each tree item
+ */
map(callback) {
const tree = new IntervalTree();
this.tree_walk(this.root, (node) => tree.insert(node.item.key, callback(node.item.value, node.item.key)));
return tree;
}
- /**
- * @param {Interval} interval - optional if the iterator is intended to start from the beginning
- * @param outputMapperFn(value,key) - optional function that maps (value, key) to custom output
- * @returns {Iterator}
- */
- *iterate(interval, outputMapperFn = (value, key) => value === key ? key.output() : value) {
- let node;
- if (interval) {
- node = this.tree_search_nearest_forward(this.root, new Node(interval));
- } else if (this.root) {
- node = this.local_minimum(this.root);
- }
- while (node) {
- yield outputMapperFn(node.item.value, node.item.key);
- node = this.tree_successor(node);
- }
- }
-
recalc_max(node) {
let node_current = node;
while (node_current.parent != null) {
@@ -3781,11 +3759,11 @@ class IntervalTree {
let current_node = this.root;
let parent_node = null;
- if (this.root == null || this.root === this.nil_node) {
+ if (this.root == null || this.root == this.nil_node) {
this.root = insert_node;
}
else {
- while (current_node !== this.nil_node) {
+ while (current_node != this.nil_node) {
parent_node = current_node;
if (insert_node.less_than(current_node)) {
current_node = current_node.left;
@@ -3815,10 +3793,10 @@ class IntervalTree {
let uncle_node;
current_node = insert_node;
- while (current_node !== this.root && current_node.parent.color === RB_TREE_COLOR_RED) {
- if (current_node.parent === current_node.parent.parent.left) { // parent is left child of grandfather
+ while (current_node != this.root && current_node.parent.color == RB_TREE_COLOR_RED) {
+ if (current_node.parent == current_node.parent.parent.left) { // parent is left child of grandfather
uncle_node = current_node.parent.parent.right; // right brother of parent
- if (uncle_node.color === RB_TREE_COLOR_RED) { // Case 1. Uncle is red
+ if (uncle_node.color == RB_TREE_COLOR_RED) { // Case 1. Uncle is red
// re-color father and uncle into black
current_node.parent.color = RB_TREE_COLOR_BLACK;
uncle_node.color = RB_TREE_COLOR_BLACK;
@@ -3826,7 +3804,7 @@ class IntervalTree {
current_node = current_node.parent.parent;
}
else { // Case 2 & 3. Uncle is black
- if (current_node === current_node.parent.right) { // Case 2. Current if right child
+ if (current_node == current_node.parent.right) { // Case 2. Current if right child
// This case is transformed into Case 3.
current_node = current_node.parent;
this.rotate_left(current_node);
@@ -3839,7 +3817,7 @@ class IntervalTree {
}
else { // parent is right child of grandfather
uncle_node = current_node.parent.parent.left; // left brother of parent
- if (uncle_node.color === RB_TREE_COLOR_RED) { // Case 4. Uncle is red
+ if (uncle_node.color == RB_TREE_COLOR_RED) { // Case 4. Uncle is red
// re-color father and uncle into black
current_node.parent.color = RB_TREE_COLOR_BLACK;
uncle_node.color = RB_TREE_COLOR_BLACK;
@@ -3847,7 +3825,7 @@ class IntervalTree {
current_node = current_node.parent.parent;
}
else {
- if (current_node === current_node.parent.left) { // Case 5. Current is left child
+ if (current_node == current_node.parent.left) { // Case 5. Current is left child
// Transform into case 6
current_node = current_node.parent;
this.rotate_right(current_node);
@@ -3867,7 +3845,7 @@ class IntervalTree {
let cut_node; // node to be cut - either delete_node or successor_node ("y" from 14.4)
let fix_node; // node to fix rb tree property ("x" from 14.4)
- if (delete_node.left === this.nil_node || delete_node.right === this.nil_node) { // delete_node has less then 2 children
+ if (delete_node.left == this.nil_node || delete_node.right == this.nil_node) { // delete_node has less then 2 children
cut_node = delete_node;
}
else { // delete_node has 2 children
@@ -3875,7 +3853,7 @@ class IntervalTree {
}
// fix_node if single child of cut_node
- if (cut_node.left !== this.nil_node) {
+ if (cut_node.left != this.nil_node) {
fix_node = cut_node.left;
}
else {
@@ -3887,11 +3865,11 @@ class IntervalTree {
fix_node.parent = cut_node.parent;
/*}*/
- if (cut_node === this.root) {
+ if (cut_node == this.root) {
this.root = fix_node;
}
else {
- if (cut_node === cut_node.parent.left) {
+ if (cut_node == cut_node.parent.left) {
cut_node.parent.left = fix_node;
}
else {
@@ -3905,13 +3883,13 @@ class IntervalTree {
// COPY DATA !!!
// Delete_node becomes cut_node, it means that we cannot hold reference
// to node in outer structure and we will have to delete by key, additional search need
- if (cut_node !== delete_node) {
+ if (cut_node != delete_node) {
delete_node.copy_data(cut_node);
delete_node.update_max(); // update max property of the cut node at the new place
this.recalc_max(delete_node); // update max property upward from delete_node to root
}
- if (/*fix_node != this.nil_node && */cut_node.color === RB_TREE_COLOR_BLACK) {
+ if (/*fix_node != this.nil_node && */cut_node.color == RB_TREE_COLOR_BLACK) {
this.delete_fixup(fix_node);
}
}
@@ -3920,23 +3898,23 @@ class IntervalTree {
let current_node = fix_node;
let brother_node;
- while (current_node !== this.root && current_node.parent != null && current_node.color === RB_TREE_COLOR_BLACK) {
- if (current_node === current_node.parent.left) { // fix node is left child
+ while (current_node != this.root && current_node.parent != null && current_node.color == RB_TREE_COLOR_BLACK) {
+ if (current_node == current_node.parent.left) { // fix node is left child
brother_node = current_node.parent.right;
- if (brother_node.color === RB_TREE_COLOR_RED) { // Case 1. Brother is red
+ if (brother_node.color == RB_TREE_COLOR_RED) { // Case 1. Brother is red
brother_node.color = RB_TREE_COLOR_BLACK; // re-color brother
current_node.parent.color = RB_TREE_COLOR_RED; // re-color father
this.rotate_left(current_node.parent);
brother_node = current_node.parent.right; // update brother
}
// Derive to cases 2..4: brother is black
- if (brother_node.left.color === RB_TREE_COLOR_BLACK &&
- brother_node.right.color === RB_TREE_COLOR_BLACK) { // case 2: both nephews black
+ if (brother_node.left.color == RB_TREE_COLOR_BLACK &&
+ brother_node.right.color == RB_TREE_COLOR_BLACK) { // case 2: both nephews black
brother_node.color = RB_TREE_COLOR_RED; // re-color brother
current_node = current_node.parent; // continue iteration
}
else {
- if (brother_node.right.color === RB_TREE_COLOR_BLACK) { // case 3: left nephew red, right nephew black
+ if (brother_node.right.color == RB_TREE_COLOR_BLACK) { // case 3: left nephew red, right nephew black
brother_node.color = RB_TREE_COLOR_RED; // re-color brother
brother_node.left.color = RB_TREE_COLOR_BLACK; // re-color nephew
this.rotate_right(brother_node);
@@ -3953,20 +3931,20 @@ class IntervalTree {
}
else { // fix node is right child
brother_node = current_node.parent.left;
- if (brother_node.color === RB_TREE_COLOR_RED) { // Case 1. Brother is red
+ if (brother_node.color == RB_TREE_COLOR_RED) { // Case 1. Brother is red
brother_node.color = RB_TREE_COLOR_BLACK; // re-color brother
current_node.parent.color = RB_TREE_COLOR_RED; // re-color father
this.rotate_right(current_node.parent);
brother_node = current_node.parent.left; // update brother
}
// Go to cases 2..4
- if (brother_node.left.color === RB_TREE_COLOR_BLACK &&
- brother_node.right.color === RB_TREE_COLOR_BLACK) { // case 2
+ if (brother_node.left.color == RB_TREE_COLOR_BLACK &&
+ brother_node.right.color == RB_TREE_COLOR_BLACK) { // case 2
brother_node.color = RB_TREE_COLOR_RED; // re-color brother
current_node = current_node.parent; // continue iteration
}
else {
- if (brother_node.left.color === RB_TREE_COLOR_BLACK) { // case 3: right nephew red, left nephew black
+ if (brother_node.left.color == RB_TREE_COLOR_BLACK) { // case 3: right nephew red, left nephew black
brother_node.color = RB_TREE_COLOR_RED; // re-color brother
brother_node.right.color = RB_TREE_COLOR_BLACK; // re-color nephew
this.rotate_left(brother_node);
@@ -3987,7 +3965,7 @@ class IntervalTree {
}
tree_search(node, search_node) {
- if (node == null || node === this.nil_node)
+ if (node == null || node == this.nil_node)
return undefined;
if (search_node.equal_to(node)) {
@@ -4001,31 +3979,12 @@ class IntervalTree {
}
}
- tree_search_nearest_forward(node, search_node) {
- let best;
- let curr = node;
- while (curr && curr !== this.nil_node) {
- if (curr.less_than(search_node)) {
- if (curr.intersect(search_node)) {
- best = curr;
- curr = curr.left;
- } else {
- curr = curr.right;
- }
- } else {
- if (!best || curr.less_than(best)) best = curr;
- curr = curr.left;
- }
- }
- return best || null;
- }
-
// Original search_interval method; container res support push() insertion
// Search all intervals intersecting given one
tree_search_interval(node, search_node, res) {
- if (node != null && node !== this.nil_node) {
+ if (node != null && node != this.nil_node) {
// if (node->left != this.nil_node && node->left->max >= low) {
- if (node.left !== this.nil_node && !node.not_intersect_left_subtree(search_node)) {
+ if (node.left != this.nil_node && !node.not_intersect_left_subtree(search_node)) {
this.tree_search_interval(node.left, search_node, res);
}
// if (low <= node->high && node->low <= high) {
@@ -4033,7 +3992,7 @@ class IntervalTree {
res.push(node);
}
// if (node->right != this.nil_node && node->low <= high) {
- if (node.right !== this.nil_node && !node.not_intersect_right_subtree(search_node)) {
+ if (node.right != this.nil_node && !node.not_intersect_right_subtree(search_node)) {
this.tree_search_interval(node.right, search_node, res);
}
}
@@ -4041,14 +4000,17 @@ class IntervalTree {
tree_find_any_interval(node, search_node) {
let found = false;
- if (node != null && node !== this.nil_node) {
- if (node.left !== this.nil_node && !node.not_intersect_left_subtree(search_node)) {
+ if (node != null && node != this.nil_node) {
+ // if (node->left != this.nil_node && node->left->max >= low) {
+ if (node.left != this.nil_node && !node.not_intersect_left_subtree(search_node)) {
found = this.tree_find_any_interval(node.left, search_node);
}
+ // if (low <= node->high && node->low <= high) {
if (!found) {
found = node.intersect(search_node);
}
- if (!found && node.right !== this.nil_node && !node.not_intersect_right_subtree(search_node)) {
+ // if (node->right != this.nil_node && node->low <= high) {
+ if (!found && node.right != this.nil_node && !node.not_intersect_right_subtree(search_node)) {
found = this.tree_find_any_interval(node.right, search_node);
}
}
@@ -4057,7 +4019,7 @@ class IntervalTree {
local_minimum(node) {
let node_min = node;
- while (node_min.left != null && node_min.left !== this.nil_node) {
+ while (node_min.left != null && node_min.left != this.nil_node) {
node_min = node_min.left;
}
return node_min;
@@ -4066,7 +4028,7 @@ class IntervalTree {
// not in use
local_maximum(node) {
let node_max = node;
- while (node_max.right != null && node_max.right !== this.nil_node) {
+ while (node_max.right != null && node_max.right != this.nil_node) {
node_max = node_max.right;
}
return node_max;
@@ -4077,13 +4039,13 @@ class IntervalTree {
let current_node;
let parent_node;
- if (node.right !== this.nil_node) {
+ if (node.right != this.nil_node) {
node_successor = this.local_minimum(node.right);
}
else {
current_node = node;
parent_node = node.parent;
- while (parent_node != null && parent_node.right === current_node) {
+ while (parent_node != null && parent_node.right == current_node) {
current_node = parent_node;
parent_node = parent_node.parent;
}
@@ -4104,16 +4066,16 @@ class IntervalTree {
x.right = y.left; // b goes to x.right
- if (y.left !== this.nil_node) {
+ if (y.left != this.nil_node) {
y.left.parent = x; // x becomes parent of b
}
y.parent = x.parent; // move parent
- if (x === this.root) {
+ if (x == this.root) {
this.root = y; // y becomes root
}
else { // y becomes child of x.parent
- if (x === x.parent.left) {
+ if (x == x.parent.left) {
x.parent.left = y;
}
else {
@@ -4123,12 +4085,12 @@ class IntervalTree {
y.left = x; // x becomes left child of y
x.parent = y; // and y becomes parent of x
- if (x != null && x !== this.nil_node) {
+ if (x != null && x != this.nil_node) {
x.update_max();
}
y = x.parent;
- if (y != null && y !== this.nil_node) {
+ if (y != null && y != this.nil_node) {
y.update_max();
}
}
@@ -4138,16 +4100,16 @@ class IntervalTree {
y.left = x.right; // b goes to y.left
- if (x.right !== this.nil_node) {
+ if (x.right != this.nil_node) {
x.right.parent = y; // y becomes parent of b
}
x.parent = y.parent; // move parent
- if (y === this.root) { // x becomes root
+ if (y == this.root) { // x becomes root
this.root = x;
}
else { // y becomes child of x.parent
- if (y === y.parent.left) {
+ if (y == y.parent.left) {
y.parent.left = x;
}
else {
@@ -4157,18 +4119,18 @@ class IntervalTree {
x.right = y; // y becomes right child of x
y.parent = x; // and x becomes parent of y
- if (y !== null && y !== this.nil_node) {
+ if (y != null && y != this.nil_node) {
y.update_max();
}
x = y.parent;
- if (x != null && x !== this.nil_node) {
+ if (x != null && x != this.nil_node) {
x.update_max();
}
}
tree_walk(node, action) {
- if (node != null && node !== this.nil_node) {
+ if (node != null && node != this.nil_node) {
this.tree_walk(node.left, action);
// arr.push(node.toArray());
action(node);
@@ -4180,8 +4142,8 @@ class IntervalTree {
testRedBlackProperty() {
let res = true;
this.tree_walk(this.root, function (node) {
- if (node.color === RB_TREE_COLOR_RED) {
- if (!(node.left.color === RB_TREE_COLOR_BLACK && node.right.color === RB_TREE_COLOR_BLACK)) {
+ if (node.color == RB_TREE_COLOR_RED) {
+ if (!(node.left.color == RB_TREE_COLOR_BLACK && node.right.color == RB_TREE_COLOR_BLACK)) {
res = false;
}
}
@@ -4194,27 +4156,27 @@ class IntervalTree {
let height = 0;
let heightLeft = 0;
let heightRight = 0;
- if (node.color === RB_TREE_COLOR_BLACK) {
+ if (node.color == RB_TREE_COLOR_BLACK) {
height++;
}
- if (node.left !== this.nil_node) {
+ if (node.left != this.nil_node) {
heightLeft = this.testBlackHeightProperty(node.left);
}
else {
heightLeft = 1;
}
- if (node.right !== this.nil_node) {
+ if (node.right != this.nil_node) {
heightRight = this.testBlackHeightProperty(node.right);
}
else {
heightRight = 1;
}
- if (heightLeft !== heightRight) {
+ if (heightLeft != heightRight) {
throw new Error('Red-black height property violated');
}
height += heightLeft;
return height;
- }
+ };
}
/**
diff --git a/dist/main.umd.js b/dist/main.umd.js
index e63f4d7..a886341 100644
--- a/dist/main.umd.js
+++ b/dist/main.umd.js
@@ -1072,7 +1072,7 @@
function intersectShape2Multiline(shape, multiline) {
let ip = [];
for (let edge of multiline) {
- ip = [...ip, ...intersectShape2Shape(edge, edge.shape)];
+ ip = [...ip, ...intersectShape2Shape(shape, edge.shape)];
}
return ip;
}
@@ -3361,7 +3361,7 @@
/**
* Interval is a pair of numbers or a pair of any comparable objects on which may be defined predicates
* *equal*, *less* and method *max(p1, p1)* that returns maximum in a pair.
- * When interval is an object rather than a pair of numbers, this object should have properties *low*, *high*, *max*
+ * When interval is an object rather than pair of numbers, this object should have properties *low*, *high*, *max*
* and implement methods *less_than(), equal_to(), intersect(), not_intersect(), clone(), output()*.
* Two static methods *comparable_max(), comparable_less_than()* define how to compare values in pair.
* This interface is described in typescript definition file *index.d.ts*
@@ -3407,7 +3407,7 @@
*/
less_than(other_interval) {
return this.low < other_interval.low ||
- this.low === other_interval.low && this.high < other_interval.high;
+ this.low == other_interval.low && this.high < other_interval.high;
}
/**
@@ -3416,7 +3416,7 @@
* @returns {boolean}
*/
equal_to(other_interval) {
- return this.low === other_interval.low && this.high === other_interval.high;
+ return this.low == other_interval.low && this.high == other_interval.high;
}
/**
@@ -3439,15 +3439,13 @@
/**
* Returns new interval merged with other interval
- * @param {Interval} other_interval - Other interval to merge with
+ * @param {Interval} interval - Other interval to merge with
* @returns {Interval}
*/
merge(other_interval) {
return new Interval(
- this.low === undefined ?
- other_interval.low : (this.low < other_interval.low ? this.low : other_interval.low),
- this.high === undefined ?
- other_interval.high : (this.high > other_interval.high ? this.high : other_interval.high)
+ this.low === undefined ? other_interval.low : Math.min(this.low, other_interval.low),
+ this.high === undefined ? other_interval.high : Math.max(this.high, other_interval.high)
);
}
@@ -3508,11 +3506,9 @@
this.item = {key: key, value: value}; // key is supposed to be instance of Interval
/* If not, this should by an array of two numbers */
- if (key && key instanceof Array && key.length === 2) {
+ if (key && key instanceof Array && key.length == 2) {
if (!Number.isNaN(key[0]) && !Number.isNaN(key[1])) {
- let [low, high] = key;
- if (low > high) [low, high] = [high, low];
- this.item.key = new Interval(low, high);
+ this.item.key = new Interval(Math.min(key[0], key[1]), Math.max(key[0], key[1]));
}
}
@@ -3544,7 +3540,7 @@
_value_equal(other_node) {
return this.item.value && other_node.item.value && this.item.value.equal_to ?
this.item.value.equal_to(other_node.item.value) :
- this.item.value === other_node.item.value;
+ this.item.value == other_node.item.value;
}
equal_to(other_node) {
// if tree stores only keys
@@ -3664,7 +3660,7 @@
* @returns {boolean}
*/
isEmpty() {
- return (this.root == null || this.root === this.nil_node);
+ return (this.root == null || this.root == this.nil_node);
}
/**
@@ -3696,7 +3692,7 @@
*/
exist(key, value = key) {
let search_node = new Node(key, value);
- return !!this.tree_search(this.root, search_node);
+ return this.tree_search(this.root, search_node) ? true : false;
}
/**
@@ -3735,7 +3731,8 @@
*/
intersect_any(interval) {
let search_node = new Node(interval);
- return this.tree_find_any_interval(this.root, search_node);
+ let found = this.tree_find_any_interval(this.root, search_node);
+ return found;
}
/**
@@ -3747,34 +3744,15 @@
this.tree_walk(this.root, (node) => visitor(node.item.key, node.item.value));
}
- /**
- * Value Mapper. Walk through every node and map node value to another value
- * @param callback(value,key) - function to be called for each tree item
- */
+ /** Value Mapper. Walk through every node and map node value to another value
+ * @param callback(value,key) - function to be called for each tree item
+ */
map(callback) {
const tree = new IntervalTree();
this.tree_walk(this.root, (node) => tree.insert(node.item.key, callback(node.item.value, node.item.key)));
return tree;
}
- /**
- * @param {Interval} interval - optional if the iterator is intended to start from the beginning
- * @param outputMapperFn(value,key) - optional function that maps (value, key) to custom output
- * @returns {Iterator}
- */
- *iterate(interval, outputMapperFn = (value, key) => value === key ? key.output() : value) {
- let node;
- if (interval) {
- node = this.tree_search_nearest_forward(this.root, new Node(interval));
- } else if (this.root) {
- node = this.local_minimum(this.root);
- }
- while (node) {
- yield outputMapperFn(node.item.value, node.item.key);
- node = this.tree_successor(node);
- }
- }
-
recalc_max(node) {
let node_current = node;
while (node_current.parent != null) {
@@ -3787,11 +3765,11 @@
let current_node = this.root;
let parent_node = null;
- if (this.root == null || this.root === this.nil_node) {
+ if (this.root == null || this.root == this.nil_node) {
this.root = insert_node;
}
else {
- while (current_node !== this.nil_node) {
+ while (current_node != this.nil_node) {
parent_node = current_node;
if (insert_node.less_than(current_node)) {
current_node = current_node.left;
@@ -3821,10 +3799,10 @@
let uncle_node;
current_node = insert_node;
- while (current_node !== this.root && current_node.parent.color === RB_TREE_COLOR_RED) {
- if (current_node.parent === current_node.parent.parent.left) { // parent is left child of grandfather
+ while (current_node != this.root && current_node.parent.color == RB_TREE_COLOR_RED) {
+ if (current_node.parent == current_node.parent.parent.left) { // parent is left child of grandfather
uncle_node = current_node.parent.parent.right; // right brother of parent
- if (uncle_node.color === RB_TREE_COLOR_RED) { // Case 1. Uncle is red
+ if (uncle_node.color == RB_TREE_COLOR_RED) { // Case 1. Uncle is red
// re-color father and uncle into black
current_node.parent.color = RB_TREE_COLOR_BLACK;
uncle_node.color = RB_TREE_COLOR_BLACK;
@@ -3832,7 +3810,7 @@
current_node = current_node.parent.parent;
}
else { // Case 2 & 3. Uncle is black
- if (current_node === current_node.parent.right) { // Case 2. Current if right child
+ if (current_node == current_node.parent.right) { // Case 2. Current if right child
// This case is transformed into Case 3.
current_node = current_node.parent;
this.rotate_left(current_node);
@@ -3845,7 +3823,7 @@
}
else { // parent is right child of grandfather
uncle_node = current_node.parent.parent.left; // left brother of parent
- if (uncle_node.color === RB_TREE_COLOR_RED) { // Case 4. Uncle is red
+ if (uncle_node.color == RB_TREE_COLOR_RED) { // Case 4. Uncle is red
// re-color father and uncle into black
current_node.parent.color = RB_TREE_COLOR_BLACK;
uncle_node.color = RB_TREE_COLOR_BLACK;
@@ -3853,7 +3831,7 @@
current_node = current_node.parent.parent;
}
else {
- if (current_node === current_node.parent.left) { // Case 5. Current is left child
+ if (current_node == current_node.parent.left) { // Case 5. Current is left child
// Transform into case 6
current_node = current_node.parent;
this.rotate_right(current_node);
@@ -3873,7 +3851,7 @@
let cut_node; // node to be cut - either delete_node or successor_node ("y" from 14.4)
let fix_node; // node to fix rb tree property ("x" from 14.4)
- if (delete_node.left === this.nil_node || delete_node.right === this.nil_node) { // delete_node has less then 2 children
+ if (delete_node.left == this.nil_node || delete_node.right == this.nil_node) { // delete_node has less then 2 children
cut_node = delete_node;
}
else { // delete_node has 2 children
@@ -3881,7 +3859,7 @@
}
// fix_node if single child of cut_node
- if (cut_node.left !== this.nil_node) {
+ if (cut_node.left != this.nil_node) {
fix_node = cut_node.left;
}
else {
@@ -3893,11 +3871,11 @@
fix_node.parent = cut_node.parent;
/*}*/
- if (cut_node === this.root) {
+ if (cut_node == this.root) {
this.root = fix_node;
}
else {
- if (cut_node === cut_node.parent.left) {
+ if (cut_node == cut_node.parent.left) {
cut_node.parent.left = fix_node;
}
else {
@@ -3911,13 +3889,13 @@
// COPY DATA !!!
// Delete_node becomes cut_node, it means that we cannot hold reference
// to node in outer structure and we will have to delete by key, additional search need
- if (cut_node !== delete_node) {
+ if (cut_node != delete_node) {
delete_node.copy_data(cut_node);
delete_node.update_max(); // update max property of the cut node at the new place
this.recalc_max(delete_node); // update max property upward from delete_node to root
}
- if (/*fix_node != this.nil_node && */cut_node.color === RB_TREE_COLOR_BLACK) {
+ if (/*fix_node != this.nil_node && */cut_node.color == RB_TREE_COLOR_BLACK) {
this.delete_fixup(fix_node);
}
}
@@ -3926,23 +3904,23 @@
let current_node = fix_node;
let brother_node;
- while (current_node !== this.root && current_node.parent != null && current_node.color === RB_TREE_COLOR_BLACK) {
- if (current_node === current_node.parent.left) { // fix node is left child
+ while (current_node != this.root && current_node.parent != null && current_node.color == RB_TREE_COLOR_BLACK) {
+ if (current_node == current_node.parent.left) { // fix node is left child
brother_node = current_node.parent.right;
- if (brother_node.color === RB_TREE_COLOR_RED) { // Case 1. Brother is red
+ if (brother_node.color == RB_TREE_COLOR_RED) { // Case 1. Brother is red
brother_node.color = RB_TREE_COLOR_BLACK; // re-color brother
current_node.parent.color = RB_TREE_COLOR_RED; // re-color father
this.rotate_left(current_node.parent);
brother_node = current_node.parent.right; // update brother
}
// Derive to cases 2..4: brother is black
- if (brother_node.left.color === RB_TREE_COLOR_BLACK &&
- brother_node.right.color === RB_TREE_COLOR_BLACK) { // case 2: both nephews black
+ if (brother_node.left.color == RB_TREE_COLOR_BLACK &&
+ brother_node.right.color == RB_TREE_COLOR_BLACK) { // case 2: both nephews black
brother_node.color = RB_TREE_COLOR_RED; // re-color brother
current_node = current_node.parent; // continue iteration
}
else {
- if (brother_node.right.color === RB_TREE_COLOR_BLACK) { // case 3: left nephew red, right nephew black
+ if (brother_node.right.color == RB_TREE_COLOR_BLACK) { // case 3: left nephew red, right nephew black
brother_node.color = RB_TREE_COLOR_RED; // re-color brother
brother_node.left.color = RB_TREE_COLOR_BLACK; // re-color nephew
this.rotate_right(brother_node);
@@ -3959,20 +3937,20 @@
}
else { // fix node is right child
brother_node = current_node.parent.left;
- if (brother_node.color === RB_TREE_COLOR_RED) { // Case 1. Brother is red
+ if (brother_node.color == RB_TREE_COLOR_RED) { // Case 1. Brother is red
brother_node.color = RB_TREE_COLOR_BLACK; // re-color brother
current_node.parent.color = RB_TREE_COLOR_RED; // re-color father
this.rotate_right(current_node.parent);
brother_node = current_node.parent.left; // update brother
}
// Go to cases 2..4
- if (brother_node.left.color === RB_TREE_COLOR_BLACK &&
- brother_node.right.color === RB_TREE_COLOR_BLACK) { // case 2
+ if (brother_node.left.color == RB_TREE_COLOR_BLACK &&
+ brother_node.right.color == RB_TREE_COLOR_BLACK) { // case 2
brother_node.color = RB_TREE_COLOR_RED; // re-color brother
current_node = current_node.parent; // continue iteration
}
else {
- if (brother_node.left.color === RB_TREE_COLOR_BLACK) { // case 3: right nephew red, left nephew black
+ if (brother_node.left.color == RB_TREE_COLOR_BLACK) { // case 3: right nephew red, left nephew black
brother_node.color = RB_TREE_COLOR_RED; // re-color brother
brother_node.right.color = RB_TREE_COLOR_BLACK; // re-color nephew
this.rotate_left(brother_node);
@@ -3993,7 +3971,7 @@
}
tree_search(node, search_node) {
- if (node == null || node === this.nil_node)
+ if (node == null || node == this.nil_node)
return undefined;
if (search_node.equal_to(node)) {
@@ -4007,31 +3985,12 @@
}
}
- tree_search_nearest_forward(node, search_node) {
- let best;
- let curr = node;
- while (curr && curr !== this.nil_node) {
- if (curr.less_than(search_node)) {
- if (curr.intersect(search_node)) {
- best = curr;
- curr = curr.left;
- } else {
- curr = curr.right;
- }
- } else {
- if (!best || curr.less_than(best)) best = curr;
- curr = curr.left;
- }
- }
- return best || null;
- }
-
// Original search_interval method; container res support push() insertion
// Search all intervals intersecting given one
tree_search_interval(node, search_node, res) {
- if (node != null && node !== this.nil_node) {
+ if (node != null && node != this.nil_node) {
// if (node->left != this.nil_node && node->left->max >= low) {
- if (node.left !== this.nil_node && !node.not_intersect_left_subtree(search_node)) {
+ if (node.left != this.nil_node && !node.not_intersect_left_subtree(search_node)) {
this.tree_search_interval(node.left, search_node, res);
}
// if (low <= node->high && node->low <= high) {
@@ -4039,7 +3998,7 @@
res.push(node);
}
// if (node->right != this.nil_node && node->low <= high) {
- if (node.right !== this.nil_node && !node.not_intersect_right_subtree(search_node)) {
+ if (node.right != this.nil_node && !node.not_intersect_right_subtree(search_node)) {
this.tree_search_interval(node.right, search_node, res);
}
}
@@ -4047,14 +4006,17 @@
tree_find_any_interval(node, search_node) {
let found = false;
- if (node != null && node !== this.nil_node) {
- if (node.left !== this.nil_node && !node.not_intersect_left_subtree(search_node)) {
+ if (node != null && node != this.nil_node) {
+ // if (node->left != this.nil_node && node->left->max >= low) {
+ if (node.left != this.nil_node && !node.not_intersect_left_subtree(search_node)) {
found = this.tree_find_any_interval(node.left, search_node);
}
+ // if (low <= node->high && node->low <= high) {
if (!found) {
found = node.intersect(search_node);
}
- if (!found && node.right !== this.nil_node && !node.not_intersect_right_subtree(search_node)) {
+ // if (node->right != this.nil_node && node->low <= high) {
+ if (!found && node.right != this.nil_node && !node.not_intersect_right_subtree(search_node)) {
found = this.tree_find_any_interval(node.right, search_node);
}
}
@@ -4063,7 +4025,7 @@
local_minimum(node) {
let node_min = node;
- while (node_min.left != null && node_min.left !== this.nil_node) {
+ while (node_min.left != null && node_min.left != this.nil_node) {
node_min = node_min.left;
}
return node_min;
@@ -4072,7 +4034,7 @@
// not in use
local_maximum(node) {
let node_max = node;
- while (node_max.right != null && node_max.right !== this.nil_node) {
+ while (node_max.right != null && node_max.right != this.nil_node) {
node_max = node_max.right;
}
return node_max;
@@ -4083,13 +4045,13 @@
let current_node;
let parent_node;
- if (node.right !== this.nil_node) {
+ if (node.right != this.nil_node) {
node_successor = this.local_minimum(node.right);
}
else {
current_node = node;
parent_node = node.parent;
- while (parent_node != null && parent_node.right === current_node) {
+ while (parent_node != null && parent_node.right == current_node) {
current_node = parent_node;
parent_node = parent_node.parent;
}
@@ -4110,16 +4072,16 @@
x.right = y.left; // b goes to x.right
- if (y.left !== this.nil_node) {
+ if (y.left != this.nil_node) {
y.left.parent = x; // x becomes parent of b
}
y.parent = x.parent; // move parent
- if (x === this.root) {
+ if (x == this.root) {
this.root = y; // y becomes root
}
else { // y becomes child of x.parent
- if (x === x.parent.left) {
+ if (x == x.parent.left) {
x.parent.left = y;
}
else {
@@ -4129,12 +4091,12 @@
y.left = x; // x becomes left child of y
x.parent = y; // and y becomes parent of x
- if (x != null && x !== this.nil_node) {
+ if (x != null && x != this.nil_node) {
x.update_max();
}
y = x.parent;
- if (y != null && y !== this.nil_node) {
+ if (y != null && y != this.nil_node) {
y.update_max();
}
}
@@ -4144,16 +4106,16 @@
y.left = x.right; // b goes to y.left
- if (x.right !== this.nil_node) {
+ if (x.right != this.nil_node) {
x.right.parent = y; // y becomes parent of b
}
x.parent = y.parent; // move parent
- if (y === this.root) { // x becomes root
+ if (y == this.root) { // x becomes root
this.root = x;
}
else { // y becomes child of x.parent
- if (y === y.parent.left) {
+ if (y == y.parent.left) {
y.parent.left = x;
}
else {
@@ -4163,18 +4125,18 @@
x.right = y; // y becomes right child of x
y.parent = x; // and x becomes parent of y
- if (y !== null && y !== this.nil_node) {
+ if (y != null && y != this.nil_node) {
y.update_max();
}
x = y.parent;
- if (x != null && x !== this.nil_node) {
+ if (x != null && x != this.nil_node) {
x.update_max();
}
}
tree_walk(node, action) {
- if (node != null && node !== this.nil_node) {
+ if (node != null && node != this.nil_node) {
this.tree_walk(node.left, action);
// arr.push(node.toArray());
action(node);
@@ -4186,8 +4148,8 @@
testRedBlackProperty() {
let res = true;
this.tree_walk(this.root, function (node) {
- if (node.color === RB_TREE_COLOR_RED) {
- if (!(node.left.color === RB_TREE_COLOR_BLACK && node.right.color === RB_TREE_COLOR_BLACK)) {
+ if (node.color == RB_TREE_COLOR_RED) {
+ if (!(node.left.color == RB_TREE_COLOR_BLACK && node.right.color == RB_TREE_COLOR_BLACK)) {
res = false;
}
}
@@ -4200,27 +4162,27 @@
let height = 0;
let heightLeft = 0;
let heightRight = 0;
- if (node.color === RB_TREE_COLOR_BLACK) {
+ if (node.color == RB_TREE_COLOR_BLACK) {
height++;
}
- if (node.left !== this.nil_node) {
+ if (node.left != this.nil_node) {
heightLeft = this.testBlackHeightProperty(node.left);
}
else {
heightLeft = 1;
}
- if (node.right !== this.nil_node) {
+ if (node.right != this.nil_node) {
heightRight = this.testBlackHeightProperty(node.right);
}
else {
heightRight = 1;
}
- if (heightLeft !== heightRight) {
+ if (heightLeft != heightRight) {
throw new Error('Red-black height property violated');
}
height += heightLeft;
return height;
- }
+ };
}
/**
diff --git a/package.json b/package.json
index fa21d55..4226e54 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@flatten-js/core",
- "version": "1.6.1",
+ "version": "1.6.2",
"description": "Javascript library for 2d geometry",
"main": "dist/main.cjs",
"umd:main": "dist/main.umd.js",