Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

commonJS module #4

Open
wants to merge 3 commits into from

4 participants

@booo

Perhaps this could be a fix for issue #3.

Regards

Philipp

@chrkaatz

Nice one, looks good.

@tmcw

@imbcmdth any chance of this making it in?

@calvinmetcalf

@inbcmdth hasn't made a commit to this project in 3 years and hasn't done anything on github since October. It may be safe to call this orphaned.

EDIT looks like @maxogden forked it, converted it to a commonjs package, and uploaded it to npm about 8 months ago.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jul 24, 2011
  1. @booo

    rtree.js: removed whitespaces...

    booo authored
  2. @booo
  3. @booo

    package.json added

    booo authored
This page is out of date. Refresh to see the latest.
Showing with 104 additions and 75 deletions.
  1. +25 −0 package.json
  2. +79 −75 src/rtree.js
View
25 package.json
@@ -0,0 +1,25 @@
+{
+ "name": "rtree",
+ "version": "0.0.1",
+ "description": "rtree library for javascript",
+ "keywords": ["rtree"],
+ "maintainers": [
+ {
+ "name": "Jon-Carlos Rivera",
+ "email": "imbcmdth@hotmail.com",
+ "web": "https://github.com/imbcmdth/RTree"
+ }
+ ],
+ "bugs": {
+ "web": "https://github.com/imbcmdth/RTree/issues"
+ },
+ "repositories": [
+ {
+ "type": "git",
+ "url": "https://github.com/imbcmdth/RTree.git"
+ }
+ ],
+ "dependencies": {},
+ "main": "./src/rtree.js"
+
+}
View
154 src/rtree.js
@@ -1,9 +1,9 @@
-/******************************************************************************
+/******************************************************************************
rtree.js - General-Purpose Non-Recursive Javascript R-Tree Library
Version 0.6.2, December 5st 2009
Copyright (c) 2009 Jon-Carlos Rivera
-
+
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
@@ -11,10 +11,10 @@
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
-
+
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
-
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -37,9 +37,9 @@ var RTree = function(width){
if(!isNaN(width)){ _Min_Width = Math.floor(width/2.0); _Max_Width = width;}
// Start with an empty root-tree
var _T = {x:0, y:0, w:0, h:0, id:"root", nodes:[] };
-
+
var isArray = function(o) {
- return Object.prototype.toString.call(o) === '[object Array]';
+ return Object.prototype.toString.call(o) === '[object Array]';
};
/* @function
@@ -70,13 +70,13 @@ var RTree = function(width){
// Area of new enlarged rectangle
var lperi = (l + w) / 2.0; // Average size of a side of the new rectangle
var larea = l * w; // Area of new rectangle
- // return the ratio of the perimeter to the area - the closer to 1 we are,
- // the more "square" a rectangle is. conversly, when approaching zero the
+ // return the ratio of the perimeter to the area - the closer to 1 we are,
+ // the more "square" a rectangle is. conversly, when approaching zero the
// more elongated a rectangle is
var lgeo = larea / (lperi*lperi);
- return(larea * fill / lgeo);
+ return(larea * fill / lgeo);
};
-
+
/* find the best specific node(s) for object to be deleted from
* [ leaf node parent ] = _remove_subtree(rectangle, object, root)
* @private
@@ -86,19 +86,19 @@ var RTree = function(width){
var count_stack = []; // Contains the elements that overlap
var ret_array = [];
var current_depth = 1;
-
+
if(!rect || !RTree.Rectangle.overlap_rectangle(rect, root))
return ret_array;
var ret_obj = {x:rect.x, y:rect.y, w:rect.w, h:rect.h, target:obj};
-
+
count_stack.push(root.nodes.length);
hit_stack.push(root);
do {
var tree = hit_stack.pop();
var i = count_stack.pop()-1;
-
+
if("target" in ret_obj) { // We are searching for a target
while(i >= 0) {
var ltree = tree.nodes[i];
@@ -109,9 +109,9 @@ var RTree = function(width){
// we can cancel search and start walking up the list
if("nodes" in ltree) {// If we are deleting a node not a leaf...
ret_array = _search_subtree(ltree, true, [], ltree);
- tree.nodes.splice(i, 1);
+ tree.nodes.splice(i, 1);
} else {
- ret_array = tree.nodes.splice(i, 1);
+ ret_array = tree.nodes.splice(i, 1);
}
// Resize MBR down...
RTree.Rectangle.make_MBR(tree.nodes, tree);
@@ -146,7 +146,7 @@ var RTree = function(width){
count_stack.push(1);
} else if(hit_stack.length > 0 && tree.nodes.length < _Min_Width) { // Underflow..AGAIN!
ret_obj.nodes = _search_subtree(tree, true, ret_obj.nodes, tree);
- tree.nodes.length = 0;
+ tree.nodes.length = 0;
}else {
delete ret_obj.nodes; // Just start resizing
}
@@ -155,7 +155,7 @@ var RTree = function(width){
}
current_depth -= 1;
}while(hit_stack.length > 0);
-
+
return(ret_array);
};
@@ -167,26 +167,26 @@ var RTree = function(width){
var best_choice_index = -1;
var best_choice_stack = [];
var best_choice_area;
-
+
var load_callback = function(local_tree, local_node){
- return(function(data) {
+ return(function(data) {
local_tree._attach_data(local_node, data);
});
};
-
+
best_choice_stack.push(root);
- var nodes = root.nodes;
+ var nodes = root.nodes;
- do {
+ do {
if(best_choice_index != -1) {
best_choice_stack.push(nodes[best_choice_index]);
nodes = nodes[best_choice_index].nodes;
best_choice_index = -1;
}
-
+
for(var i = nodes.length-1; i >= 0; i--) {
var ltree = nodes[i];
- if("leaf" in ltree) {
+ if("leaf" in ltree) {
// Bail out of everything and start inserting
best_choice_index = -1;
break;
@@ -201,10 +201,10 @@ var RTree = function(width){
// Enlarge rectangle to fit new rectangle
var nw = Math.max(ltree.x+ltree.w, rect.x+rect.w) - Math.min(ltree.x, rect.x);
var nh = Math.max(ltree.y+ltree.h, rect.y+rect.h) - Math.min(ltree.y, rect.y);
-
+
// Area of new enlarged rectangle
var lratio = RTree.Rectangle.squarified_ratio(nw, nh, ltree.nodes.length+2);
-
+
if(best_choice_index < 0 || Math.abs(lratio - old_lratio) < best_choice_area) {
best_choice_area = Math.abs(lratio - old_lratio); best_choice_index = i;
}
@@ -225,7 +225,7 @@ var RTree = function(width){
}
return(n);
};
-
+
/* insert the best source rectangle into the best fitting parent node: a or b
* [] = pick_next(array of source nodes, target node array a, target node array b)
* @private
@@ -237,14 +237,14 @@ var RTree = function(width){
var high_area_delta;
var high_area_node;
var lowest_growth_group;
-
+
for(var i = nodes.length-1; i>=0;i--) {
var l = nodes[i];
var new_area_a = {};
new_area_a.x = Math.min(a.x, l.x); new_area_a.y = Math.min(a.y, l.y);
new_area_a.w = Math.max(a.x+a.w, l.x+l.w) - new_area_a.x; new_area_a.h = Math.max(a.y+a.h, l.y+l.h) - new_area_a.y;
var change_new_area_a = Math.abs(RTree.Rectangle.squarified_ratio(new_area_a.w, new_area_a.h, a.nodes.length+2) - area_a);
-
+
var new_area_b = {};
new_area_b.x = Math.min(b.x, l.x); new_area_b.y = Math.min(b.y, l.y);
new_area_b.w = Math.max(b.x+b.w, l.x+l.w) - new_area_b.x; new_area_b.h = Math.max(b.y+b.h, l.y+l.h) - new_area_b.y;
@@ -280,7 +280,7 @@ var RTree = function(width){
var lowest_high_y = nodes.length-1;
var highest_low_y = 0;
var t1, t2;
-
+
for(var i = nodes.length-2; i>=0;i--) {
var l = nodes[i];
if(l.x > nodes[highest_low_x].x ) highest_low_x = i;
@@ -290,7 +290,7 @@ var RTree = function(width){
}
var dx = Math.abs((nodes[lowest_high_x].x+nodes[lowest_high_x].w) - nodes[highest_low_x].x);
var dy = Math.abs((nodes[lowest_high_y].y+nodes[lowest_high_y].h) - nodes[highest_low_y].y);
- if( dx > dy ) {
+ if( dx > dy ) {
if(lowest_high_x > highest_low_x) {
t1 = nodes.splice(lowest_high_x, 1)[0];
t2 = nodes.splice(highest_low_x, 1)[0];
@@ -310,7 +310,7 @@ var RTree = function(width){
return([{x:t1.x, y:t1.y, w:t1.w, h:t1.h, nodes:[t1]},
{x:t2.x, y:t2.y, w:t2.w, h:t2.h, nodes:[t2]} ]);
};
-
+
var _attach_data = function(node, more_tree){
node.nodes = more_tree.nodes;
node.x = more_tree.x; node.y = more_tree.y;
@@ -318,27 +318,27 @@ var RTree = function(width){
return(node);
};
- /* non-recursive internal search function
+ /* non-recursive internal search function
* [ nodes | objects ] = _search_subtree(rectangle, [return node data], [array to fill], root to begin search at)
* @private
*/
var _search_subtree = function(rect, return_node, return_array, root) {
var hit_stack = []; // Contains the elements that overlap
-
+
if(!RTree.Rectangle.overlap_rectangle(rect, root))
return(return_array);
-
+
var load_callback = function(local_tree, local_node){
- return(function(data) {
+ return(function(data) {
local_tree._attach_data(local_node, data);
});
};
-
+
hit_stack.push(root.nodes);
-
+
do {
var nodes = hit_stack.pop();
-
+
for(var i = nodes.length-1; i >= 0; i--) {
var ltree = nodes[i];
if(RTree.Rectangle.overlap_rectangle(rect, ltree)) {
@@ -357,10 +357,10 @@ var RTree = function(width){
}
}
}while(hit_stack.length > 0);
-
+
return(return_array);
};
-
+
/* non-recursive internal insert function
* [] = _insert_subtree(rectangle, object to insert, root to begin insertion at)
* @private
@@ -375,13 +375,13 @@ var RTree = function(width){
root.nodes.push(node);
return;
}
-
+
// Find the best fitting leaf node
// choose_leaf returns an array of all tree levels (including root)
// that were traversed while trying to find the leaf
var tree_stack = _choose_leaf_subtree(node, root);
var ret_obj = node;//{x:rect.x,y:rect.y,w:rect.w,h:rect.h, leaf:obj};
-
+
// Walk back up the tree resizing and inserting as needed
do {
//handle the case of an empty node (from a split)
@@ -396,20 +396,20 @@ var RTree = function(width){
} else {
bc = tree_stack.pop();
}
-
+
// If there is data attached to this ret_obj
- if("leaf" in ret_obj || "nodes" in ret_obj || isArray(ret_obj)) {
+ if("leaf" in ret_obj || "nodes" in ret_obj || isArray(ret_obj)) {
// Do Insert
if(isArray(ret_obj)) {
for(var ai = 0; ai < ret_obj.length; ai++) {
RTree.Rectangle.expand_rectangle(bc, ret_obj[ai]);
}
- bc.nodes = bc.nodes.concat(ret_obj);
+ bc.nodes = bc.nodes.concat(ret_obj);
} else {
RTree.Rectangle.expand_rectangle(bc, ret_obj);
bc.nodes.push(ret_obj); // Do Insert
}
-
+
if(bc.nodes.length <= _Max_Width) { // Start Resizeing Up the Tree
ret_obj = {x:bc.x,y:bc.y,w:bc.w,h:bc.h};
} else { // Otherwise Split this Node
@@ -417,7 +417,7 @@ var RTree = function(width){
// formed from the split of the previous node's overflow
var a = _linear_split(bc.nodes);
ret_obj = a;//[1];
-
+
if(tree_stack.length < 1) { // If are splitting the root..
bc.nodes.push(a[0]);
tree_stack.push(bc); // Reconsider the root element
@@ -442,7 +442,7 @@ var RTree = function(width){
this.get_tree = function() {
return _T;
};
-
+
/* quick 'n' dirty function for plugins or manually loading the tree
* [ tree ] = RTree.set_tree(sub-tree, where to attach): returns the raw tree data. useful for adding
* @public
@@ -453,8 +453,8 @@ var RTree = function(width){
where = _T;
return(_attach_data(where, new_tree));
};
-
- /* non-recursive search function
+
+ /* non-recursive search function
* [ nodes | objects ] = RTree.search(rectangle, [return node data], [array to fill])
* @public
*/
@@ -474,7 +474,7 @@ var RTree = function(width){
}
return(_search_subtree.apply(this, arguments));
};
-
+
/* partially-recursive toJSON function
* [ string ] = RTree.toJSON([rectangle], [tree])
* @public
@@ -486,10 +486,10 @@ var RTree = function(width){
var max_depth = 3; // This triggers recursion and tree-splitting
var current_depth = 1;
var return_string = "";
-
+
if(rect && !RTree.Rectangle.overlap_rectangle(rect, _T))
return "";
-
+
if(!tree) {
count_stack.push(_T.nodes.length);
hit_stack.push(_T.nodes);
@@ -500,14 +500,14 @@ var RTree = function(width){
hit_stack.push(tree.nodes);
return_string += "var main_tree = {x:"+tree.x.toFixed()+",y:"+tree.y.toFixed()+",w:"+tree.w.toFixed()+",h:"+tree.h.toFixed()+",nodes:[";
}
-
+
do {
var nodes = hit_stack.pop();
var i = count_stack.pop()-1;
-
+
if(i >= 0 && i < nodes.length-1)
return_string += ",";
-
+
while(i >= 0) {
var ltree = nodes[i];
if(!rect || RTree.Rectangle.overlap_rectangle(rect, ltree)) {
@@ -544,15 +544,15 @@ var RTree = function(width){
return_string += "]}"; current_depth -= 1;
}
}while(hit_stack.length > 0);
-
+
return_string+=";";
-
+
for(var my_key in return_stack) {
return_string += "\nvar " + my_key + " = function(){" + return_stack[my_key] + " return(main_tree);};";
}
return(return_string);
};
-
+
/* non-recursive function that deletes a specific
* [ number ] = RTree.remove(rectangle, obj)
*/
@@ -571,8 +571,8 @@ var RTree = function(width){
if(arguments[1] === false) { // Do area-wide delete
var numberdeleted = 0;
var ret_array = [];
- do {
- numberdeleted=ret_array.length;
+ do {
+ numberdeleted=ret_array.length;
ret_array = ret_array.concat(_remove_subtree.apply(this, arguments));
}while( numberdeleted != ret_array.length);
return ret_array;
@@ -581,17 +581,17 @@ var RTree = function(width){
return(_remove_subtree.apply(this, arguments));
}
};
-
+
/* non-recursive insert function
* [] = RTree.insert(rectangle, object to insert)
*/
this.insert = function(rect, obj) {
if(arguments.length < 2)
throw "Wrong number of arguments. RT.Insert requires at least a bounding rectangle and an object."
-
+
return(_insert_subtree({x:rect.x,y:rect.y,w:rect.w,h:rect.h,leaf:obj}, _T));
};
-
+
/* non-recursive delete function
* [deleted object] = RTree.remove(rectangle, [object to delete])
*/
@@ -605,7 +605,7 @@ RTree.Rectangle = function(ix, iy, iw, ih) { // new Rectangle(bounds) or new Rec
var x, x2, y, y2, w, h;
if(ix.x) {
- x = ix.x; y = ix.y;
+ x = ix.x; y = ix.y;
if(ix.w !== 0 && !ix.w && ix.x2){
w = ix.x2-ix.x; h = ix.y2-ix.y;
} else {
@@ -620,18 +620,18 @@ RTree.Rectangle = function(ix, iy, iw, ih) { // new Rectangle(bounds) or new Rec
this.x1 = this.x = function(){return x;};
this.y1 = this.y = function(){return y;};
this.x2 = function(){return x2;};
- this.y2 = function(){return y2;};
+ this.y2 = function(){return y2;};
this.w = function(){return w;};
this.h = function(){return h;};
-
+
this.toJSON = function() {
return('{"x":'+x.toString()+', "y":'+y.toString()+', "w":'+w.toString()+', "h":'+h.toString()+'}');
};
-
+
this.overlap = function(a) {
return(this.x() < a.x2() && this.x2() > a.x() && this.y() < a.y2() && this.y2() > a.y());
};
-
+
this.expand = function(a) {
var nx = Math.min(this.x(), a.x());
var ny = Math.min(this.y(), a.y());
@@ -640,11 +640,11 @@ RTree.Rectangle = function(ix, iy, iw, ih) { // new Rectangle(bounds) or new Rec
x = nx; y = ny;
return(this);
};
-
+
this.setRect = function(ix, iy, iw, ih) {
var x, x2, y, y2, w, h;
if(ix.x) {
- x = ix.x; y = ix.y;
+ x = ix.x; y = ix.y;
if(ix.w !== 0 && !ix.w && ix.x2) {
w = ix.x2-ix.x; h = ix.y2-ix.y;
} else {
@@ -703,9 +703,13 @@ RTree.Rectangle.make_MBR = function(nodes, rect) {
rect = {x:nodes[0].x, y:nodes[0].y, w:nodes[0].w, h:nodes[0].h};
else
rect.x = nodes[0].x; rect.y = nodes[0].y; rect.w = nodes[0].w; rect.h = nodes[0].h;
-
+
for(var i = nodes.length-1; i>0; i--)
RTree.Rectangle.expand_rectangle(rect, nodes[i]);
-
+
return(rect);
-};
+};
+
+if (typeof module === 'object' && typeof require === 'function') {
+ exports.RTree = RTree
+}
Something went wrong with that request. Please try again.