Skip to content

Instantly share code, notes, and snippets.

@funnylookinhat
Created January 28, 2013 17:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save funnylookinhat/4657409 to your computer and use it in GitHub Desktop.
Save funnylookinhat/4657409 to your computer and use it in GitHub Desktop.
Comparing two class definitions for NodeJS exports.
/**
* Static Quad Tree
* This is a one-way tree that only allows insertion for maximum efficiency.
* @author David Overcash <funnylookinhat@gmail.com>
* Credit to https://github.com/mikechambers/ExamplesByMesh for a great example.
*/
(function(exports) {
var Node = (function (constructParams) {
var _MAX_ITEMS = 4;
var _quad,
_center,
_items,
_children;
__construct = function () {
_quad = {
xMin: Math.floor(constructParams.quad.xMin),
xMax: Math.ceil(constructParams.quad.xMax),
yMin: Math.floor(constructParams.quad.yMin),
yMax: Math.ceil(constructParams.quad.yMax)
};
_center = {
x: Math.floor( _quad.xMin + ( ( _quad.xMax - _quad.xMin ) / 2 ) ),
y: Math.floor( _quad.yMin + ( ( _quad.yMax - _quad.yMin ) / 2 ) )
}
_items = [];
_children = null;
}()
// Determine the index for an item within the quad for this node.
// If you want to use Hilbert curves for a radius search or whatnot, you
// should change this to return values appropriate to the matrix
// [[0,3],
// [1,2]]
_itemIndex = function (item) {
if( item.x < _center.x ) {
if( item.y > _center.y ) {
return 0;
} else {
return 1;
}
} else {
if( item.y > _center.y ) {
return 3;
} else {
return 2;
}
}
return (
( item.x < _center.x ? 1 : 0 ) +
( 2 * ( item.y < _center.y ? 1 : 0 ) )
);
}
// Initialize _children and move all items.
_generateChildren = function() {
_children = [];
// Can we speed this up? Or at least make it look nicer?
var quads = [];
quads.push({xMin: _quad.xMin,xMax: _center.x,yMin: _center.y,yMax: _quad.yMax});
quads.push({xMin: _quad.xMin,xMax: _center.x,yMin: _quad.yMin,yMax: _center.y});
quads.push({xMin: _center.x,xMax: _quad.xMax,yMin: _quad.yMin,yMax: _center.y});
quads.push({xMin: _center.x,xMax: _quad.xMax,yMin: _center.y,yMax: _quad.yMax});
for( i in quads ) {
_children[i] = new Node({quad: quads[i]});
}
var item = null;
while( _items.length ) {
item = _items.pop();
_children[_itemIndex(item)].insertItem(item);
}
_items = null;
}
this.insertItem = function (item) {
if( _children != null ) {
if( _children[_itemIndex(item)] == undefined ) {
console.log("ERR?");
console.log(_children);
}
_children[_itemIndex(item)].insertItem(item);
} else {
_items.push(item);
if( _items.length > _MAX_ITEMS ) {
_generateChildren();
}
}
}
this.fetchItemsInQuad = function (quad) {
var items = [];
if( _pointInQuad(_center,quad) ) {
if( _items != null ) {
items.concat(_items);
} else {
for( i in _children ) {
items.concat(_children[i].fetchItemsInQuad(quad));
}
}
}
return items;
}
this.totalItems = function () {
var count = 0;
if( _items != null ) {
count += _items.length;
} else {
for ( i in _children ) {
count += _children[i].totalItems();
}
}
return count;
}
});
var StaticQuadTree = (function (constructParams) {
var _rootNode;
_pointInQuad = function(point,quad) {
return (
point.x >= quad.xMin &&
point.x <= quad.xMax &&
point.y >= quad.yMin &&
point.y <= quad.yMax
);
}
__construct = function () {
if( constructParams.quad == null ) {
throw new TypeError("Parameter object must contain object property quad");
}
if( constructParams.quad.xMin == null ||
typeof constructParams.quad.xMin != "number" ) {
throw new TypeError("Parameter object quad must contain numeric property xMin");
}
if( constructParams.quad.yMin == null ||
typeof constructParams.quad.yMin != "number" ) {
throw new TypeError("Parameter object quad must contain numeric property yMin");
}
if( constructParams.quad.xMax == null ||
typeof constructParams.quad.xMax != "number" ) {
throw new TypeError("Parameter object quad must contain numeric property xMax");
}
if( constructParams.quad.yMax == null ||
typeof constructParams.quad.yMax != "number" ) {
throw new TypeError("Parameter object quad must contain numeric property yMax");
}
_rootNode = new Node({quad: {
xMin: constructParams.quad.xMin,
xMax: constructParams.quad.xMax,
yMin: constructParams.quad.yMin,
yMax: constructParams.quad.yMax
}});
}()
this.insertItem = function (item) {
if( typeof item != "object" ) {
throw new TypeError("Parameter item must be an object");
}
if( item.x == null ||
typeof item.x != "number" ) {
throw new TypeError("Parameter item must contain numeric property x");
}
if( item.y == null ||
typeof item.y != "number" ) {
throw new TypeError("Parameter item must container numeric property y");
}
_rootNode.insertItem(item);
}
// TODO
this.fetchItemsInQuad = function (quad) {
return _rootNode.fetchItemsInQuad(quad);
}
this.totalItems = function (quad) {
return _rootNode.totalItems();
}
});
exports.StaticQuadTree = StaticQuadTree;
})(typeof global === "undefined" ? window : exports);
/**
* Static Quad Tree
* This is a one-way tree that only allows insertion for maximum efficiency.
* @author David Overcash <funnylookinhat@gmail.com>
* Credit to https://github.com/mikechambers/ExamplesByMesh for a great example.
*/
(function(exports) {
var Node = function (xMin,xMax,yMin,yMax,level) {
this._quad = {
xMin: xMin,
xMax: xMax,
yMin: yMin,
yMax: yMax
};
this._center = {
x: Math.floor( this._quad.xMin + ( ( this._quad.xMax - this._quad.xMin ) / 2 ) ),
y: Math.floor( this._quad.yMin + ( ( this._quad.yMax - this._quad.yMin ) / 2 ) )
}
this._items = [];
this._children = null;
if( level != null ) {
this._level = level;
} else {
this._level = 0;
}
}
Node.MAX_ITEMS = 4;
Node.MAX_LEVEL = 4;
Node._pointInQuad = function(point,quad) {
return (
point.x >= quad.xMin &&
point.x <= quad.xMax &&
point.y >= quad.yMin &&
point.y <= quad.yMax
);
}
Node.prototype._intersectsQuad = function (quad) {
return ( (
this._quad.xMin > quad.xMax ||
this._quad.xMax < quad.xMin ||
this._quad.yMin > quad.yMax ||
this._quad.yMax < quad.yMin
) ? false : true );
}
Node.prototype._containedInQuad = function (quad) {
return ( (
this._quad.xMin >= quad.xMin &&
this._quad.xMax <= quad.xMax &&
this._quad.yMin >= quad.yMin &&
this._quad.yMax <= quad.yMax
) ? true : false );
}
Node.prototype._itemIndex = function (item) {
if( item.y < this._center.y ) {
if( item.x < this._center.x ) {
return 1;
}
return 2;
} else {
if( item.x < this._center.x ) {
return 0;
}
return 3;
}
/*
return (
( item.y < this._center.y ? 1 : 0 ) +
( item.x < this._center.x ? 0 : 2 )
);
*/
}
Node.prototype._generateChildren = function() {
this._children = [];
// Can we speed this up? Or at least make it look nicer?
this._children[0] = new Node(this._quad.xMin, this._center.x, this._center.y, this._quad.yMax, (this._level + 1));
this._children[1] = new Node(this._quad.xMin, this._center.x, this._quad.yMin, this._center.y, (this._level + 1));
this._children[2] = new Node(this._center.x, this._quad.xMax, this._quad.yMin, this._center.y, (this._level + 1));
this._children[3] = new Node(this._center.x, this._quad.xMax, this._center.y, this._quad.yMax, (this._level + 1));
var item = null;
while( this._items.length ) {
item = this._items.pop();
this._children[this._itemIndex(item)].insertItem(item);
}
_items = null;
}
Node.prototype.insertItem = function (item) {
if( this._children != null ) {
this._children[this._itemIndex(item)].insertItem(item);
} else {
this._items.push(item);
if( (
! Node.MAX_LEVEL ||
this._level < Node.MAX_LEVEL
) &&
this._items.length > Node.MAX_ITEMS ) {
this._generateChildren();
}
}
}
Node.prototype.fetchAllItems = function () {
var items = [];
if( this._items != null ) {
items = items.concat(this._items);
}
if( this._children != null ) {
for( i in this._children ) {
items = items.concat(this._children[i].fetchAllItems());
}
}
return items;
}
Node.prototype.fetchItemsInQuad = function (quad) {
var items = [];
if( this._intersectsQuad(quad) ) {
if( this._items != null ) {
items = items.concat(this._items);
}
if( this._children != null ) {
if( this._containedInQuad(quad) ) {
for( i in this._children ) {
items = items.concat(this._children[i].fetchAllItems());
}
} else {
for( i in this._children ) {
items = items.concat(this._children[i].fetchItemsInQuad(quad));
}
}
}
}
return items;
}
Node.prototype.totalItems = function () {
var count = this._items.length;
if( this._children != null ) {
for ( i in this._children ) {
count += this._children[i].totalItems();
}
}
return count;
}
Node.prototype.dumpTree = function (level) {
console.log('NODE: x={'+this._quad.xMin+':'+this._quad.xMax+'} y={'+this._quad.yMin+':'+this._quad.yMax+'}'+' ITEMS: '+this._items.length);
if( this._children != null ) {
for( i in this._children ) {
console.log(level);
this._children[i].dumpTree((level+'-'));
}
}
}
var StaticQuadTree = function (xMin,xMax,yMin,yMax) {
if( xMin == null ||
typeof xMin != "number" ) {
throw new TypeError("xMin must be numeric.");
}
if( yMin == null ||
typeof yMin != "number" ) {
throw new TypeError("yMin must be numeric.");
}
if( xMax == null ||
typeof xMax != "number" ) {
throw new TypeError("xMax must be numeric.");
}
if( yMax == null ||
typeof yMax != "number" ) {
throw new TypeError("yMax must be numeric.");
}
this._rootNode = new Node(xMin, xMax, yMin, yMax);
}
StaticQuadTree.prototype.insertItem = function (item) {
if( typeof item != "object" ) {
throw new TypeError("Parameter item must be an object");
}
if( item.x == null ||
typeof item.x != "number" ) {
throw new TypeError("Parameter item must contain numeric property x");
}
if( item.y == null ||
typeof item.y != "number" ) {
throw new TypeError("Parameter item must container numeric property y");
}
this._rootNode.insertItem(item);
}
StaticQuadTree.prototype.fetchItemsInQuad = function (xMin,xMax,yMin,yMax) {
var quad = {
xMin: xMin,
xMax: xMax,
yMin: yMin,
yMax: yMax
}
return this._rootNode.fetchItemsInQuad(quad);
}
StaticQuadTree.prototype.totalItems = function() {
return this._rootNode.totalItems();
}
StaticQuadTree.prototype.dumpTree = function() {
this._rootNode.dumpTree('-');
}
exports.Node = Node;
exports.StaticQuadTree = StaticQuadTree;
})(typeof global === "undefined" ? window : exports);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment