diff --git a/Gruntfile.js b/Gruntfile.js index ec1d629..5ad4c42 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -9,18 +9,9 @@ module.exports = function(grunt) { https://github.com/leaflet-extras/RTree.\n\ ******************************************************************************/\n\ (function(){\n\ - /*global module,window,self */\n\ + /*global module,window,self,RTree */\n\ \'use strict\';\n', - footer:'if (typeof module !== \'undefined\' && module.exports) {\n\ - module.exports = rTree;\n\ -}else if(typeof document === \'undefined\'){\n\ - self.rTree = rTree;\n\ - self.RTree = RTree;\n\ -}else{\n\ - window.rTree = rTree;\n\ - window.RTree = RTree;\n\ -}\n\ -})(this);\n', + uglify: { all: { src: 'dist/rtree.js', @@ -30,10 +21,9 @@ module.exports = function(grunt) { concat: { all: { options:{ - banner: '<%= banner %>', - footer:'<%= footer %>' + banner: '<%= banner %>' }, - src: ['src/rtree.js','src/rtree.json.js','src/rtree.geojson.js','src/rtree.end.js','src/rtree.rectangle.js'], + src: ['src/rtree.js','src/rtree.json.js','src/rtree.end.js','src/rtree.rectangle.js','src/rtree.geojson.js'], dest: 'dist/rtree.js' } }, diff --git a/dist/rtree.js b/dist/rtree.js index 7a98ef6..05592d9 100644 --- a/dist/rtree.js +++ b/dist/rtree.js @@ -5,16 +5,16 @@ https://github.com/leaflet-extras/RTree. ******************************************************************************/ (function(){ - /*global module,window,self */ + /*global module,window,self,RTree */ 'use strict'; -var RTree = function(width){ +function RTree(width){ // Variables to control tree-dimensions var minWidth = 3; // Minimum width of any node before a merge var maxWidth = 6; // Maximum width of any node before a split if(!isNaN(width)){ minWidth = Math.floor(width/2.0); maxWidth = width;} // Start with an empty root-tree var rootTree = {x:0, y:0, w:0, h:0, id:'root', nodes:[] }; - + this.root = rootTree; var isArray = function(o) { return Array.isArray?Array.isArray(o):Object.prototype.toString.call(o) === '[object Array]'; }; @@ -397,6 +397,7 @@ var RTree = function(width){ } }; + this.insertSubtree = insertSubtree; /* quick 'n' dirty function for plugins or manually drawing the tree * [ tree ] = RTree.getTree(): returns the raw tree data. useful for adding * @public @@ -490,7 +491,7 @@ var RTree = function(width){ */ this.toJSON = function(rect, callback) { callback = callback||function(err,data){return data;}; - return callback(null,JSON.stringify(rootTree)); + return callback(null,JSON.stringify(this.root)); }; RTree.fromJSON = function(json, callback) { @@ -499,199 +500,10 @@ var RTree = function(width){ rt.setTree(JSON.parse(json)); return callback(null, rt); }; -var bbox = function (ar,obj) { - if(obj && obj.bbox){ - return {leaf:obj,x:obj.bbox[0],y:obj.bbox[1],w:obj.bbox[2]-obj.bbox[0],h:obj.bbox[3]-obj.bbox[1]}; - } - var len = ar.length; - var i = 0; - var a = new Array(len); - while(i temp.max[0]) { - temp.max[0] = a[i][0]; - } - if(a[i][1] < temp.min[1]) { - temp.min[1] = a[i][1]; - }else if(a[i][1] > temp.max[1]) { - temp.max[1] = a[i][1]; - } - i++; - } - var out = {x:temp.min[0],y:temp.min[1],w:(temp.max[0]-temp.min[0]),h:(temp.max[1]-temp.min[1])}; - if(obj){ - out.leaf=obj; - } - return out; - }; - var geoJSON = {}; - geoJSON.point = function(obj) { - return(insertSubtree({x:obj.geometry.coordinates[0],y:obj.geometry.coordinates[1],w:0,h:0,leaf:obj}, rootTree)); - }; - geoJSON.multiPointLineString = function(obj) { - return(insertSubtree(bbox(obj.geometry.coordinates,obj), rootTree)); - }; - geoJSON.multiLineStringPolygon = function(obj) { - return(insertSubtree(bbox(Array.prototype.concat.apply([],obj.geometry.coordinates),obj), rootTree)); - }; - geoJSON.multiPolygon = function(obj) { - return(insertSubtree(bbox(Array.prototype.concat.apply([],Array.prototype.concat.apply([],obj.geometry.coordinates)),obj), rootTree)); - }; - geoJSON.makeRec = function(obj){ - return new RTree.Rectangle(obj.x,obj.y,obj.w,obj.h); - }; - geoJSON.geometryCollection = function(obj){ - if(obj.bbox){ - return(insertSubtree({leaf:obj,x:obj.bbox[0],y:obj.bbox[1],w:obj.bbox[2]-obj.bbox[0],h:obj.bbox[3]-obj.bbox[1]}, rootTree)); - } - var geos = obj.geometry.geometries; - var i = 0; - var len = geos.length; - var temp=[]; - var g; - while(i= b.x && a.y <= (b.y+b.h) && (a.y+a.h) >= b.y; @@ -805,6 +630,7 @@ RTree.Rectangle.overlapRectangle = function(a, b) { * @static function */ RTree.Rectangle.containsRectangle = function(a, b) { + 'use strict'; return (a.x+a.w) <= (b.x+b.w) && a.x >= b.x && (a.y+a.h) <= (b.y+b.h) && a.y >= b.y; }; @@ -812,7 +638,8 @@ RTree.Rectangle.containsRectangle = function(a, b) { * [ rectangle a ] = expandRectangle(rectangle a, rectangle b) * @static function */ -RTree.Rectangle.expandRectangle = function(a, b) { +RTree.Rectangle.expandRectangle = function(a, b) { + 'use strict'; var nx,ny; var axw = a.x+a.w; var bxw = b.x+b.w; @@ -850,6 +677,7 @@ RTree.Rectangle.expandRectangle = function(a, b) { * @static function */ RTree.Rectangle.makeMBR = function(nodes, rect) { + 'use strict'; if(!nodes.length){ return { x : 0, @@ -869,13 +697,256 @@ RTree.Rectangle.makeMBR = function(nodes, rect) { } return rect; -};if (typeof module !== 'undefined' && module.exports) { - module.exports = rTree; -}else if(typeof document === 'undefined'){ - self.rTree = rTree; - self.RTree = RTree; -}else{ - window.rTree = rTree; - window.RTree = RTree; -} -})(this); +}; +(function(self) { + 'use strict'; + var bbox = function(ar, obj) { + if (obj && obj.bbox) { + return { + leaf: obj, + x: obj.bbox[0], + y: obj.bbox[1], + w: obj.bbox[2] - obj.bbox[0], + h: obj.bbox[3] - obj.bbox[1] + }; + } + var len = ar.length; + var i = 0; + var a = new Array(len); + while (i < len) { + a[i] = [ar[i][0], ar[i][1]]; + i++; + } + var first = a[0]; + len = a.length; + i = 1; + var temp = { + min: [].concat(first), + max: [].concat(first) + }; + while (i < len) { + if (a[i][0] < temp.min[0]) { + temp.min[0] = a[i][0]; + } + else if (a[i][0] > temp.max[0]) { + temp.max[0] = a[i][0]; + } + if (a[i][1] < temp.min[1]) { + temp.min[1] = a[i][1]; + } + else if (a[i][1] > temp.max[1]) { + temp.max[1] = a[i][1]; + } + i++; + } + var out = { + x: temp.min[0], + y: temp.min[1], + w: (temp.max[0] - temp.min[0]), + h: (temp.max[1] - temp.min[1]) + }; + if (obj) { + out.leaf = obj; + } + return out; + }; + var geoJSON = {}; + geoJSON.point = function(obj,self) { + return (self.insertSubtree({ + x: obj.geometry.coordinates[0], + y: obj.geometry.coordinates[1], + w: 0, + h: 0, + leaf: obj + }, self.root)); + }; + geoJSON.multiPointLineString = function(obj,self) { + return (self.insertSubtree(bbox(obj.geometry.coordinates, obj), self.root)); + }; + geoJSON.multiLineStringPolygon = function(obj,self) { + return (self.insertSubtree(bbox(Array.prototype.concat.apply([], obj.geometry.coordinates), obj), self.root)); + }; + geoJSON.multiPolygon = function(obj,self) { + return (self.insertSubtree(bbox(Array.prototype.concat.apply([], Array.prototype.concat.apply([], obj.geometry.coordinates)), obj), self.root)); + }; + geoJSON.makeRec = function(obj) { + return new RTree.Rectangle(obj.x, obj.y, obj.w, obj.h); + }; + geoJSON.geometryCollection = function(obj,self) { + if (obj.bbox) { + return (self.insertSubtree({ + leaf: obj, + x: obj.bbox[0], + y: obj.bbox[1], + w: obj.bbox[2] - obj.bbox[0], + h: obj.bbox[3] - obj.bbox[1] + }, self.root)); + } + var geos = obj.geometry.geometries; + var i = 0; + var len = geos.length; + var temp = []; + var g; + while (i < len) { + g = geos[i]; + switch (g.type) { + case 'Point': + temp.push(geoJSON.makeRec({ + x: g.coordinates[0], + y: g.coordinates[1], + w: 0, + h: 0 + })); + break; + case 'MultiPoint': + temp.push(geoJSON.makeRec(bbox(g.coordinates))); + break; + case 'LineString': + temp.push(geoJSON.makeRec(bbox(g.coordinates))); + break; + case 'MultiLineString': + temp.push(geoJSON.makeRec(bbox(Array.prototype.concat.apply([], g.coordinates)))); + break; + case 'Polygon': + temp.push(geoJSON.makeRec(bbox(Array.prototype.concat.apply([], g.coordinates)))); + break; + case 'MultiPolygon': + temp.push(geoJSON.makeRec(bbox(Array.prototype.concat.apply([], Array.prototype.concat.apply([], g.coordinates))))); + break; + case 'GeometryCollection': + geos = geos.concat(g.geometries); + len = geos.length; + break; + } + i++; + } + var first = temp[0]; + i = 1; + len = temp.length; + while (i < len) { + first.expand(temp[i]); + i++; + } + return self.insertSubtree({ + leaf: obj, + x: first.x(), + y: first.y(), + h: first.h(), + w: first.w() + }, self.root); + }; + self.geoJSON = function(prelim, callback) { + var that = this; + callback = callback || function() { + return true; + }; + var features, feature; + if (RTree.isArray(prelim)) { + features = prelim.slice(); + } + else if (prelim.features && RTree.isArray(prelim.features)) { + features = prelim.features.slice(); + } + else { + throw ('this isn\'t what we\'re looking for'); + } + var len = features.length; + var i = 0; + while (i < len) { + feature = features[i]; + if (feature.type === 'Feature') { + switch (feature.geometry.type) { + case 'Point': + geoJSON.point(feature,that); + break; + case 'MultiPoint': + geoJSON.multiPointLineString(feature,that); + break; + case 'LineString': + geoJSON.multiPointLineString(feature,that); + break; + case 'MultiLineString': + geoJSON.multiLineStringPolygon(feature,that); + break; + case 'Polygon': + geoJSON.multiLineStringPolygon(feature,that); + break; + case 'MultiPolygon': + geoJSON.multiPolygon(feature, that); + break; + case 'GeometryCollection': + geoJSON.geometryCollection(feature, that); + break; + } + } + i++; + } + return callback(null, true); + }; + self.bbox = function() { + var x1, y1, x2, y2, callback; + switch (arguments.length) { + case 0: + throw ('not enough arguments'); + case 1: + x1 = arguments[0][0][0]; + y1 = arguments[0][0][1]; + x2 = arguments[0][1][0]; + y2 = arguments[0][1][1]; + break; + case 2: + if (typeof arguments[1] === 'function') { + x1 = arguments[0][0][0]; + y1 = arguments[0][0][1]; + x2 = arguments[0][1][0]; + y2 = arguments[0][1][1]; + callback = arguments[1]; + break; + } + else { + x1 = arguments[0][0]; + y1 = arguments[0][1]; + x2 = arguments[1][0]; + y2 = arguments[1][1]; + break; + } + break; + case 3: + x1 = arguments[0][0]; + y1 = arguments[0][1]; + x2 = arguments[1][0]; + y2 = arguments[1][1]; + callback = arguments[2]; + break; + case 4: + x1 = arguments[0]; + y1 = arguments[1]; + x2 = arguments[2]; + y2 = arguments[3]; + break; + case 5: + x1 = arguments[0]; + y1 = arguments[1]; + x2 = arguments[2]; + y2 = arguments[3]; + callback = arguments[4]; + break; + } + if (!callback) { + return this.search({ + x: x1, + y: y1, + w: x2 - x1, + h: y2 - y1 + }); + } + else { + this.search({ + x: x1, + y: y1, + w: x2 - x1, + h: y2 - y1 + }, callback); + } + }; +})(RTree.prototype); \ No newline at end of file diff --git a/dist/rtree.min.js b/dist/rtree.min.js index 35430b8..d3ddd0f 100644 --- a/dist/rtree.min.js +++ b/dist/rtree.min.js @@ -1 +1 @@ -!function(){"use strict";var a=function(b){var c=3,d=6;isNaN(b)||(c=Math.floor(b/2),d=b);var e={x:0,y:0,w:0,h:0,id:"root",nodes:[]},f=function(a){return Array.isArray?Array.isArray(a):"[object Array]"===Object.prototype.toString.call(a)};a.Rectangle.squarifiedRatio=function(a,b,c){var d=(a+b)/2,e=a*b,f=e/(d*d);return e*c/f};var g=function(a){for(var b,c=a.slice(),d=[];c.length;)b=c.pop(),b.nodes?c=c.concat(b.nodes):b.leaf&&d.push(b);return d},h=function(b,d,e){var f,h,i,j=[],k=[],l=[],m=1;if(!b||!a.Rectangle.overlapRectangle(b,e))return l;var p={x:b.x,y:b.y,w:b.w,h:b.h,target:d};for(k.push(e.nodes.length),j.push(e);j.length>0;){if(f=j.pop(),h=k.pop()-1,"target"in p)for(;h>=0;){if(i=f.nodes[h],a.Rectangle.overlapRectangle(p,i)){if(p.target&&"leaf"in i&&i.leaf===p.target||!p.target&&("leaf"in i||a.Rectangle.containsRectangle(i,p))){l="nodes"in i?g(f.nodes.splice(h,1)):f.nodes.splice(h,1),a.Rectangle.makeMBR(f.nodes,f),delete p.target;break}"nodes"in i&&(m++,k.push(h),j.push(f),f=i,h=i.nodes.length)}h--}else if("nodes"in p){f.nodes.splice(h+1,1),f.nodes.length>0&&a.Rectangle.makeMBR(f.nodes,f);for(var q=0;q0&&f.nodes.length=0;i--){var j=h[i];if("leaf"in j){e=-1;break}var k=a.Rectangle.squarifiedRatio(j.w,j.h,j.nodes.length+1),l=Math.max(j.x+j.w,b.x+b.w)-Math.min(j.x,b.x),m=Math.max(j.y+j.h,b.y+b.h)-Math.min(j.y,b.y),n=a.Rectangle.squarifiedRatio(l,m,j.nodes.length+2);(0>e||Math.abs(n-k)0;)k(a,b[0],b[1]);return b},k=function(b,d,e){for(var f,g,h,i=a.Rectangle.squarifiedRatio(d.w,d.h,d.nodes.length+1),j=a.Rectangle.squarifiedRatio(e.w,e.h,e.nodes.length+1),k=b.length-1;k>=0;k--){var l=b[k],m={};m.x=Math.min(d.x,l.x),m.y=Math.min(d.y,l.y),m.w=Math.max(d.x+d.w,l.x+l.w)-m.x,m.h=Math.max(d.y+d.h,l.y+l.h)-m.y;var n=Math.abs(a.Rectangle.squarifiedRatio(m.w,m.h,d.nodes.length+2)-i),o={};o.x=Math.min(e.x,l.x),o.y=Math.min(e.y,l.y),o.w=Math.max(e.x+e.w,l.x+l.w)-o.x,o.h=Math.max(e.y+e.h,l.y+l.h)-o.y;var p=Math.abs(a.Rectangle.squarifiedRatio(o.w,o.h,e.nodes.length+2)-j);(!g||!f||Math.abs(p-n)p?e:d)}var q=b.splice(g,1)[0];d.nodes.length+b.length+1<=c?(d.nodes.push(q),a.Rectangle.expandRectangle(d,q)):e.nodes.length+b.length+1<=c?(e.nodes.push(q),a.Rectangle.expandRectangle(e,q)):(h.nodes.push(q),a.Rectangle.expandRectangle(h,q))},l=function(a){for(var b,c,d=a.length-1,e=0,f=a.length-1,g=0,h=a.length-2;h>=0;h--){var i=a[h];i.x>a[e].x?e=h:i.x+i.wa[g].y?g=h:i.y+i.hk?d>e?(b=a.splice(d,1)[0],c=a.splice(e,1)[0]):(c=a.splice(e,1)[0],b=a.splice(d,1)[0]):f>g?(b=a.splice(f,1)[0],c=a.splice(g,1)[0]):(c=a.splice(g,1)[0],b=a.splice(f,1)[0]),[{x:b.x,y:b.y,w:b.w,h:b.h,nodes:[b]},{x:c.x,y:c.y,w:c.w,h:c.h,nodes:[c]}]},m=function(a,b){return a.nodes=b.nodes,a.x=b.x,a.y=b.y,a.w=b.w,a.h=b.h,a},n=function(b,c,d,e){var f=[];if(!a.Rectangle.overlapRectangle(b,e))return d;for(f.push(e.nodes);f.length>0;)for(var g=f.pop(),h=g.length-1;h>=0;h--){var i=g[h];a.Rectangle.overlapRectangle(b,i)&&("nodes"in i?f.push(i.nodes):"leaf"in i&&(c?d.push(i):d.push(i.leaf)))}return d},o=function(b,c){var e;if(0===c.nodes.length)return c.x=b.x,c.y=b.y,c.w=b.w,c.h=b.h,c.nodes.push(b),void 0;for(var g,h=i(b,c),k=b;h.length>0;){if(e&&"nodes"in e&&0===e.nodes.length){g=e,e=h.pop();for(var l=0;l0;)c=h(a,!1,e),d=c.length,f=f.concat(c);return b?b(null,f):f},q=function(a,b,c){var d=h(a,b,e);return c?c(null,d):d};this.remove=function(a,b,c){return b&&"function"!=typeof b?q(a,b,c):p(a,b)},this.insert=function(a,b,c){var d=o({x:a.x,y:a.y,w:a.w,h:a.h,leaf:b},e);return c?c(null,d):d},this.toJSON=function(a,b){return b=b||function(a,b){return b},b(null,JSON.stringify(e))},a.fromJSON=function(b,c){c=c||function(a,b){return b};var d=new a;return d.setTree(JSON.parse(b)),c(null,d)};var r=function(a,b){if(b&&b.bbox)return{leaf:b,x:b.bbox[0],y:b.bbox[1],w:b.bbox[2]-b.bbox[0],h:b.bbox[3]-b.bbox[1]};for(var c=a.length,d=0,e=new Array(c);c>d;)e[d]=[a[d][0],a[d][1]],d++;var f=e[0];c=e.length,d=1;for(var g={min:[].concat(f),max:[].concat(f)};c>d;)e[d][0]g.max[0]&&(g.max[0]=e[d][0]),e[d][1]g.max[1]&&(g.max[1]=e[d][1]),d++;var h={x:g.min[0],y:g.min[1],w:g.max[0]-g.min[0],h:g.max[1]-g.min[1]};return b&&(h.leaf=b),h},s={};s.point=function(a){return o({x:a.geometry.coordinates[0],y:a.geometry.coordinates[1],w:0,h:0,leaf:a},e)},s.multiPointLineString=function(a){return o(r(a.geometry.coordinates,a),e)},s.multiLineStringPolygon=function(a){return o(r(Array.prototype.concat.apply([],a.geometry.coordinates),a),e)},s.multiPolygon=function(a){return o(r(Array.prototype.concat.apply([],Array.prototype.concat.apply([],a.geometry.coordinates)),a),e)},s.makeRec=function(b){return new a.Rectangle(b.x,b.y,b.w,b.h)},s.geometryCollection=function(a){if(a.bbox)return o({leaf:a,x:a.bbox[0],y:a.bbox[1],w:a.bbox[2]-a.bbox[0],h:a.bbox[3]-a.bbox[1]},e);for(var b,c=a.geometry.geometries,d=0,f=c.length,g=[];f>d;){switch(b=c[d],b.type){case"Point":g.push(s.makeRec({x:b.coordinates[0],y:b.coordinates[1],w:0,h:0}));break;case"MultiPoint":g.push(s.makeRec(r(b.coordinates)));break;case"LineString":g.push(s.makeRec(r(b.coordinates)));break;case"MultiLineString":g.push(s.makeRec(r(Array.prototype.concat.apply([],b.coordinates))));break;case"Polygon":g.push(s.makeRec(r(Array.prototype.concat.apply([],b.coordinates))));break;case"MultiPolygon":g.push(s.makeRec(r(Array.prototype.concat.apply([],Array.prototype.concat.apply([],b.coordinates)))));break;case"GeometryCollection":c=c.concat(b.geometries),f=c.length}d++}var h=g[0];for(d=1,f=g.length;f>d;)h.expand(g[d]),d++;return o({leaf:a,x:h.x(),y:h.y(),h:h.h(),w:h.w()},e)},this.geoJSON=function(a,b){b=b||function(){return!0};var c,d;if(f(a))c=a.slice();else{if(!a.features||!f(a.features))throw"this isn't what we're looking for";c=a.features.slice()}for(var e=c.length,g=0;e>g;){if(d=c[g],"Feature"===d.type)switch(d.geometry.type){case"Point":s.point(d);break;case"MultiPoint":s.multiPointLineString(d);break;case"LineString":s.multiPointLineString(d);break;case"MultiLineString":s.multiLineStringPolygon(d);break;case"Polygon":s.multiLineStringPolygon(d);break;case"MultiPolygon":s.multiPolygon(d);break;case"GeometryCollection":s.geometryCollection(d)}g++}return b(null,!0)},this.bbox=function(){var a,b,c,d,e;switch(arguments.length){case 0:throw"not enough arguments";case 1:a=arguments[0][0][0],b=arguments[0][0][1],c=arguments[0][1][0],d=arguments[0][1][1];break;case 2:if("function"==typeof arguments[1]){a=arguments[0][0][0],b=arguments[0][0][1],c=arguments[0][1][0],d=arguments[0][1][1],e=arguments[1];break}a=arguments[0][0],b=arguments[0][1],c=arguments[1][0],d=arguments[1][1];break;case 3:a=arguments[0][0],b=arguments[0][1],c=arguments[1][0],d=arguments[1][1],e=arguments[2];break;case 4:a=arguments[0],b=arguments[1],c=arguments[2],d=arguments[3];break;case 5:a=arguments[0],b=arguments[1],c=arguments[2],d=arguments[3],e=arguments[4]}return e?(this.search({x:a,y:b,w:c-a,h:d-b},e),void 0):this.search({x:a,y:b,w:c-a,h:d-b})}},b=function(b,c){var d,e;if("function"==typeof b&&(c=b,b=void 0),!c)return new a(b);try{d=new a(b)}catch(f){e=f}finally{c(e,d)}};a.Rectangle=function(a,b,c,d){var e,f,g;a.x?(c=a.w,d=a.h,b=a.y,0!==a.w&&!a.w&&a.x2?(c=a.x2-a.x,d=a.y2-a.y):(c=a.w,d=a.h),a=a.x,e=a+c,f=b+d,g=d+c?!1:!0):(e=a+c,f=b+d,g=d+c?!1:!0),this.x1=this.x=function(){return a},this.y1=this.y=function(){return b},this.x2=function(){return e},this.y2=function(){return f},this.w=function(){return c},this.h=function(){return d},this.p=function(){return g},this.overlap=function(c){return g||c.p()?a<=c.x2()&&e>=c.x()&&b<=c.y2()&&f>=c.y():ac.x()&&bc.y()},this.expand=function(g){var h,i,j=g.x(),k=g.y(),l=g.x2(),m=g.y2();return h=a>j?j:a,i=b>k?k:b,c=e>l?e-h:l-h,d=f>m?f-i:m-i,a=h,b=i,this}},a.Rectangle.overlapRectangle=function(a,b){return 0===a.h&&0===a.w||0===b.h&&0===b.w?a.x<=b.x+b.w&&a.x+a.w>=b.x&&a.y<=b.y+b.h&&a.y+a.h>=b.y:a.xb.x&&a.yb.y},a.Rectangle.containsRectangle=function(a,b){return a.x+a.w<=b.x+b.w&&a.x>=b.x&&a.y+a.h<=b.y+b.h&&a.y>=b.y},a.Rectangle.expandRectangle=function(a,b){var c,d,e=a.x+a.w,f=b.x+b.w,g=a.y+a.h,h=b.y+b.h;return c=a.x>b.x?b.x:a.x,d=a.y>b.y?b.y:a.y,a.w=e>f?e-c:f-c,a.h=g>h?g-d:h-d,a.x=c,a.y=d,a},a.Rectangle.makeMBR=function(b,c){if(!b.length)return{x:0,y:0,w:0,h:0};c=c||{},c.x=b[0].x,c.y=b[0].y,c.w=b[0].w,c.h=b[0].h;for(var d=1,e=b.length;e>d;d++)a.Rectangle.expandRectangle(c,b[d]);return c},"undefined"!=typeof module&&module.exports?module.exports=b:"undefined"==typeof document?(self.rTree=b,self.RTree=a):(window.rTree=b,window.RTree=a)}(this); \ No newline at end of file +!function(){"use strict";function a(b){var c=3,d=6;isNaN(b)||(c=Math.floor(b/2),d=b);var e={x:0,y:0,w:0,h:0,id:"root",nodes:[]};this.root=e;var f=function(a){return Array.isArray?Array.isArray(a):"[object Array]"===Object.prototype.toString.call(a)};a.Rectangle.squarifiedRatio=function(a,b,c){var d=(a+b)/2,e=a*b,f=e/(d*d);return e*c/f};var g=function(a){for(var b,c=a.slice(),d=[];c.length;)b=c.pop(),b.nodes?c=c.concat(b.nodes):b.leaf&&d.push(b);return d},h=function(b,d,e){var f,h,i,j=[],k=[],l=[],m=1;if(!b||!a.Rectangle.overlapRectangle(b,e))return l;var p={x:b.x,y:b.y,w:b.w,h:b.h,target:d};for(k.push(e.nodes.length),j.push(e);j.length>0;){if(f=j.pop(),h=k.pop()-1,"target"in p)for(;h>=0;){if(i=f.nodes[h],a.Rectangle.overlapRectangle(p,i)){if(p.target&&"leaf"in i&&i.leaf===p.target||!p.target&&("leaf"in i||a.Rectangle.containsRectangle(i,p))){l="nodes"in i?g(f.nodes.splice(h,1)):f.nodes.splice(h,1),a.Rectangle.makeMBR(f.nodes,f),delete p.target;break}"nodes"in i&&(m++,k.push(h),j.push(f),f=i,h=i.nodes.length)}h--}else if("nodes"in p){f.nodes.splice(h+1,1),f.nodes.length>0&&a.Rectangle.makeMBR(f.nodes,f);for(var q=0;q0&&f.nodes.length=0;i--){var j=h[i];if("leaf"in j){e=-1;break}var k=a.Rectangle.squarifiedRatio(j.w,j.h,j.nodes.length+1),l=Math.max(j.x+j.w,b.x+b.w)-Math.min(j.x,b.x),m=Math.max(j.y+j.h,b.y+b.h)-Math.min(j.y,b.y),n=a.Rectangle.squarifiedRatio(l,m,j.nodes.length+2);(0>e||Math.abs(n-k)0;)k(a,b[0],b[1]);return b},k=function(b,d,e){for(var f,g,h,i=a.Rectangle.squarifiedRatio(d.w,d.h,d.nodes.length+1),j=a.Rectangle.squarifiedRatio(e.w,e.h,e.nodes.length+1),k=b.length-1;k>=0;k--){var l=b[k],m={};m.x=Math.min(d.x,l.x),m.y=Math.min(d.y,l.y),m.w=Math.max(d.x+d.w,l.x+l.w)-m.x,m.h=Math.max(d.y+d.h,l.y+l.h)-m.y;var n=Math.abs(a.Rectangle.squarifiedRatio(m.w,m.h,d.nodes.length+2)-i),o={};o.x=Math.min(e.x,l.x),o.y=Math.min(e.y,l.y),o.w=Math.max(e.x+e.w,l.x+l.w)-o.x,o.h=Math.max(e.y+e.h,l.y+l.h)-o.y;var p=Math.abs(a.Rectangle.squarifiedRatio(o.w,o.h,e.nodes.length+2)-j);(!g||!f||Math.abs(p-n)p?e:d)}var q=b.splice(g,1)[0];d.nodes.length+b.length+1<=c?(d.nodes.push(q),a.Rectangle.expandRectangle(d,q)):e.nodes.length+b.length+1<=c?(e.nodes.push(q),a.Rectangle.expandRectangle(e,q)):(h.nodes.push(q),a.Rectangle.expandRectangle(h,q))},l=function(a){for(var b,c,d=a.length-1,e=0,f=a.length-1,g=0,h=a.length-2;h>=0;h--){var i=a[h];i.x>a[e].x?e=h:i.x+i.wa[g].y?g=h:i.y+i.hk?d>e?(b=a.splice(d,1)[0],c=a.splice(e,1)[0]):(c=a.splice(e,1)[0],b=a.splice(d,1)[0]):f>g?(b=a.splice(f,1)[0],c=a.splice(g,1)[0]):(c=a.splice(g,1)[0],b=a.splice(f,1)[0]),[{x:b.x,y:b.y,w:b.w,h:b.h,nodes:[b]},{x:c.x,y:c.y,w:c.w,h:c.h,nodes:[c]}]},m=function(a,b){return a.nodes=b.nodes,a.x=b.x,a.y=b.y,a.w=b.w,a.h=b.h,a},n=function(b,c,d,e){var f=[];if(!a.Rectangle.overlapRectangle(b,e))return d;for(f.push(e.nodes);f.length>0;)for(var g=f.pop(),h=g.length-1;h>=0;h--){var i=g[h];a.Rectangle.overlapRectangle(b,i)&&("nodes"in i?f.push(i.nodes):"leaf"in i&&(c?d.push(i):d.push(i.leaf)))}return d},o=function(b,c){var e;if(0===c.nodes.length)return c.x=b.x,c.y=b.y,c.w=b.w,c.h=b.h,c.nodes.push(b),void 0;for(var g,h=i(b,c),k=b;h.length>0;){if(e&&"nodes"in e&&0===e.nodes.length){g=e,e=h.pop();for(var l=0;l0;)c=h(a,!1,e),d=c.length,f=f.concat(c);return b?b(null,f):f},q=function(a,b,c){var d=h(a,b,e);return c?c(null,d):d};this.remove=function(a,b,c){return b&&"function"!=typeof b?q(a,b,c):p(a,b)},this.insert=function(a,b,c){var d=o({x:a.x,y:a.y,w:a.w,h:a.h,leaf:b},e);return c?c(null,d):d},this.toJSON=function(a,b){return b=b||function(a,b){return b},b(null,JSON.stringify(this.root))},a.fromJSON=function(b,c){c=c||function(a,b){return b};var d=new a;return d.setTree(JSON.parse(b)),c(null,d)}}a.isArray=function(a){return Array.isArray?Array.isArray(a):"[object Array]"===Object.prototype.toString.call(a)};var b=function(b,c){var d,e;if("function"==typeof b&&(c=b,b=void 0),!c)return new a(b);try{d=new a(b)}catch(f){e=f}finally{c(e,d)}};b.isArray=a.isArray,"undefined"!=typeof module&&module.exports?module.exports=b:"undefined"==typeof document?(self.rTree=b,self.RTree=a):(window.rTree=b,window.RTree=a)}(this),RTree.Rectangle=function(a,b,c,d){"use strict";var e,f,g;a.x?(c=a.w,d=a.h,b=a.y,0!==a.w&&!a.w&&a.x2?(c=a.x2-a.x,d=a.y2-a.y):(c=a.w,d=a.h),a=a.x,e=a+c,f=b+d,g=d+c?!1:!0):(e=a+c,f=b+d,g=d+c?!1:!0),this.x1=this.x=function(){return a},this.y1=this.y=function(){return b},this.x2=function(){return e},this.y2=function(){return f},this.w=function(){return c},this.h=function(){return d},this.p=function(){return g},this.overlap=function(c){return g||c.p()?a<=c.x2()&&e>=c.x()&&b<=c.y2()&&f>=c.y():ac.x()&&bc.y()},this.expand=function(g){var h,i,j=g.x(),k=g.y(),l=g.x2(),m=g.y2();return h=a>j?j:a,i=b>k?k:b,c=e>l?e-h:l-h,d=f>m?f-i:m-i,a=h,b=i,this}},RTree.Rectangle.overlapRectangle=function(a,b){"use strict";return 0===a.h&&0===a.w||0===b.h&&0===b.w?a.x<=b.x+b.w&&a.x+a.w>=b.x&&a.y<=b.y+b.h&&a.y+a.h>=b.y:a.xb.x&&a.yb.y},RTree.Rectangle.containsRectangle=function(a,b){"use strict";return a.x+a.w<=b.x+b.w&&a.x>=b.x&&a.y+a.h<=b.y+b.h&&a.y>=b.y},RTree.Rectangle.expandRectangle=function(a,b){"use strict";var c,d,e=a.x+a.w,f=b.x+b.w,g=a.y+a.h,h=b.y+b.h;return c=a.x>b.x?b.x:a.x,d=a.y>b.y?b.y:a.y,a.w=e>f?e-c:f-c,a.h=g>h?g-d:h-d,a.x=c,a.y=d,a},RTree.Rectangle.makeMBR=function(a,b){"use strict";if(!a.length)return{x:0,y:0,w:0,h:0};b=b||{},b.x=a[0].x,b.y=a[0].y,b.w=a[0].w,b.h=a[0].h;for(var c=1,d=a.length;d>c;c++)RTree.Rectangle.expandRectangle(b,a[c]);return b},function(a){"use strict";var b=function(a,b){if(b&&b.bbox)return{leaf:b,x:b.bbox[0],y:b.bbox[1],w:b.bbox[2]-b.bbox[0],h:b.bbox[3]-b.bbox[1]};for(var c=a.length,d=0,e=new Array(c);c>d;)e[d]=[a[d][0],a[d][1]],d++;var f=e[0];c=e.length,d=1;for(var g={min:[].concat(f),max:[].concat(f)};c>d;)e[d][0]g.max[0]&&(g.max[0]=e[d][0]),e[d][1]g.max[1]&&(g.max[1]=e[d][1]),d++;var h={x:g.min[0],y:g.min[1],w:g.max[0]-g.min[0],h:g.max[1]-g.min[1]};return b&&(h.leaf=b),h},c={};c.point=function(a,b){return b.insertSubtree({x:a.geometry.coordinates[0],y:a.geometry.coordinates[1],w:0,h:0,leaf:a},b.root)},c.multiPointLineString=function(a,c){return c.insertSubtree(b(a.geometry.coordinates,a),c.root)},c.multiLineStringPolygon=function(a,c){return c.insertSubtree(b(Array.prototype.concat.apply([],a.geometry.coordinates),a),c.root)},c.multiPolygon=function(a,c){return c.insertSubtree(b(Array.prototype.concat.apply([],Array.prototype.concat.apply([],a.geometry.coordinates)),a),c.root)},c.makeRec=function(a){return new RTree.Rectangle(a.x,a.y,a.w,a.h)},c.geometryCollection=function(a,d){if(a.bbox)return d.insertSubtree({leaf:a,x:a.bbox[0],y:a.bbox[1],w:a.bbox[2]-a.bbox[0],h:a.bbox[3]-a.bbox[1]},d.root);for(var e,f=a.geometry.geometries,g=0,h=f.length,i=[];h>g;){switch(e=f[g],e.type){case"Point":i.push(c.makeRec({x:e.coordinates[0],y:e.coordinates[1],w:0,h:0}));break;case"MultiPoint":i.push(c.makeRec(b(e.coordinates)));break;case"LineString":i.push(c.makeRec(b(e.coordinates)));break;case"MultiLineString":i.push(c.makeRec(b(Array.prototype.concat.apply([],e.coordinates))));break;case"Polygon":i.push(c.makeRec(b(Array.prototype.concat.apply([],e.coordinates))));break;case"MultiPolygon":i.push(c.makeRec(b(Array.prototype.concat.apply([],Array.prototype.concat.apply([],e.coordinates)))));break;case"GeometryCollection":f=f.concat(e.geometries),h=f.length}g++}var j=i[0];for(g=1,h=i.length;h>g;)j.expand(i[g]),g++;return d.insertSubtree({leaf:a,x:j.x(),y:j.y(),h:j.h(),w:j.w()},d.root)},a.geoJSON=function(a,b){var d=this;b=b||function(){return!0};var e,f;if(RTree.isArray(a))e=a.slice();else{if(!a.features||!RTree.isArray(a.features))throw"this isn't what we're looking for";e=a.features.slice()}for(var g=e.length,h=0;g>h;){if(f=e[h],"Feature"===f.type)switch(f.geometry.type){case"Point":c.point(f,d);break;case"MultiPoint":c.multiPointLineString(f,d);break;case"LineString":c.multiPointLineString(f,d);break;case"MultiLineString":c.multiLineStringPolygon(f,d);break;case"Polygon":c.multiLineStringPolygon(f,d);break;case"MultiPolygon":c.multiPolygon(f,d);break;case"GeometryCollection":c.geometryCollection(f,d)}h++}return b(null,!0)},a.bbox=function(){var a,b,c,d,e;switch(arguments.length){case 0:throw"not enough arguments";case 1:a=arguments[0][0][0],b=arguments[0][0][1],c=arguments[0][1][0],d=arguments[0][1][1];break;case 2:if("function"==typeof arguments[1]){a=arguments[0][0][0],b=arguments[0][0][1],c=arguments[0][1][0],d=arguments[0][1][1],e=arguments[1];break}a=arguments[0][0],b=arguments[0][1],c=arguments[1][0],d=arguments[1][1];break;case 3:a=arguments[0][0],b=arguments[0][1],c=arguments[1][0],d=arguments[1][1],e=arguments[2];break;case 4:a=arguments[0],b=arguments[1],c=arguments[2],d=arguments[3];break;case 5:a=arguments[0],b=arguments[1],c=arguments[2],d=arguments[3],e=arguments[4]}return e?(this.search({x:a,y:b,w:c-a,h:d-b},e),void 0):this.search({x:a,y:b,w:c-a,h:d-b})}}(RTree.prototype); \ No newline at end of file diff --git a/package.json b/package.json index 5de75b5..536ab5a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rtree", - "version": "1.1.0", + "version": "1.1.1", "description": "rtree library for javascript", "keywords": [ "rtree" diff --git a/src/rtree.end.js b/src/rtree.end.js index 653ac03..695595b 100644 --- a/src/rtree.end.js +++ b/src/rtree.end.js @@ -1,3 +1,6 @@ +} +RTree.isArray = function(o) { + return Array.isArray?Array.isArray(o):Object.prototype.toString.call(o) === '[object Array]'; }; var rTree = function(width, callback){ var temp,err; @@ -16,4 +19,15 @@ var rTree = function(width, callback){ callback(err,temp); } } -}; \ No newline at end of file +}; +rTree.isArray = RTree.isArray; +if (typeof module !== 'undefined' && module.exports) { + module.exports = rTree; +}else if(typeof document === 'undefined'){ + self.rTree = rTree; + self.RTree = RTree; +}else{ + window.rTree = rTree; + window.RTree = RTree; +} +})(this); \ No newline at end of file diff --git a/src/rtree.geojson.js b/src/rtree.geojson.js index 7cc284e..5d68186 100644 --- a/src/rtree.geojson.js +++ b/src/rtree.geojson.js @@ -1,193 +1,252 @@ -var bbox = function (ar,obj) { - if(obj && obj.bbox){ - return {leaf:obj,x:obj.bbox[0],y:obj.bbox[1],w:obj.bbox[2]-obj.bbox[0],h:obj.bbox[3]-obj.bbox[1]}; +(function(self) { + 'use strict'; + var bbox = function(ar, obj) { + if (obj && obj.bbox) { + return { + leaf: obj, + x: obj.bbox[0], + y: obj.bbox[1], + w: obj.bbox[2] - obj.bbox[0], + h: obj.bbox[3] - obj.bbox[1] + }; } var len = ar.length; var i = 0; var a = new Array(len); - while(i temp.max[0]) { + } + else if (a[i][0] > temp.max[0]) { temp.max[0] = a[i][0]; } - if(a[i][1] < temp.min[1]) { + if (a[i][1] < temp.min[1]) { temp.min[1] = a[i][1]; - }else if(a[i][1] > temp.max[1]) { + } + else if (a[i][1] > temp.max[1]) { temp.max[1] = a[i][1]; } i++; } - var out = {x:temp.min[0],y:temp.min[1],w:(temp.max[0]-temp.min[0]),h:(temp.max[1]-temp.min[1])}; - if(obj){ - out.leaf=obj; + var out = { + x: temp.min[0], + y: temp.min[1], + w: (temp.max[0] - temp.min[0]), + h: (temp.max[1] - temp.min[1]) + }; + if (obj) { + out.leaf = obj; } return out; }; var geoJSON = {}; - geoJSON.point = function(obj) { - return(insertSubtree({x:obj.geometry.coordinates[0],y:obj.geometry.coordinates[1],w:0,h:0,leaf:obj}, rootTree)); + geoJSON.point = function(obj,self) { + return (self.insertSubtree({ + x: obj.geometry.coordinates[0], + y: obj.geometry.coordinates[1], + w: 0, + h: 0, + leaf: obj + }, self.root)); }; - geoJSON.multiPointLineString = function(obj) { - return(insertSubtree(bbox(obj.geometry.coordinates,obj), rootTree)); + geoJSON.multiPointLineString = function(obj,self) { + return (self.insertSubtree(bbox(obj.geometry.coordinates, obj), self.root)); }; - geoJSON.multiLineStringPolygon = function(obj) { - return(insertSubtree(bbox(Array.prototype.concat.apply([],obj.geometry.coordinates),obj), rootTree)); + geoJSON.multiLineStringPolygon = function(obj,self) { + return (self.insertSubtree(bbox(Array.prototype.concat.apply([], obj.geometry.coordinates), obj), self.root)); }; - geoJSON.multiPolygon = function(obj) { - return(insertSubtree(bbox(Array.prototype.concat.apply([],Array.prototype.concat.apply([],obj.geometry.coordinates)),obj), rootTree)); + geoJSON.multiPolygon = function(obj,self) { + return (self.insertSubtree(bbox(Array.prototype.concat.apply([], Array.prototype.concat.apply([], obj.geometry.coordinates)), obj), self.root)); }; - geoJSON.makeRec = function(obj){ - return new RTree.Rectangle(obj.x,obj.y,obj.w,obj.h); + geoJSON.makeRec = function(obj) { + return new RTree.Rectangle(obj.x, obj.y, obj.w, obj.h); }; - geoJSON.geometryCollection = function(obj){ - if(obj.bbox){ - return(insertSubtree({leaf:obj,x:obj.bbox[0],y:obj.bbox[1],w:obj.bbox[2]-obj.bbox[0],h:obj.bbox[3]-obj.bbox[1]}, rootTree)); + geoJSON.geometryCollection = function(obj,self) { + if (obj.bbox) { + return (self.insertSubtree({ + leaf: obj, + x: obj.bbox[0], + y: obj.bbox[1], + w: obj.bbox[2] - obj.bbox[0], + h: obj.bbox[3] - obj.bbox[1] + }, self.root)); } var geos = obj.geometry.geometries; var i = 0; var len = geos.length; - var temp=[]; + var temp = []; var g; - while(i= b.x && a.y <= (b.y+b.h) && (a.y+a.h) >= b.y; @@ -92,6 +94,7 @@ RTree.Rectangle.overlapRectangle = function(a, b) { * @static function */ RTree.Rectangle.containsRectangle = function(a, b) { + 'use strict'; return (a.x+a.w) <= (b.x+b.w) && a.x >= b.x && (a.y+a.h) <= (b.y+b.h) && a.y >= b.y; }; @@ -99,7 +102,8 @@ RTree.Rectangle.containsRectangle = function(a, b) { * [ rectangle a ] = expandRectangle(rectangle a, rectangle b) * @static function */ -RTree.Rectangle.expandRectangle = function(a, b) { +RTree.Rectangle.expandRectangle = function(a, b) { + 'use strict'; var nx,ny; var axw = a.x+a.w; var bxw = b.x+b.w; @@ -137,6 +141,7 @@ RTree.Rectangle.expandRectangle = function(a, b) { * @static function */ RTree.Rectangle.makeMBR = function(nodes, rect) { + 'use strict'; if(!nodes.length){ return { x : 0,