Merge pull request #2867 from openlayers/module
Support for importing CommonJS style modules (like rbush).
This commit is contained in:
1
build.py
1
build.py
@@ -270,6 +270,7 @@ def examples_star_json(name, match):
|
|||||||
"exports": [],
|
"exports": [],
|
||||||
"src": [
|
"src": [
|
||||||
"src/**/*.js",
|
"src/**/*.js",
|
||||||
|
"build/ol.ext/*.js",
|
||||||
"examples/%(id)s.js" % match.groupdict()],
|
"examples/%(id)s.js" % match.groupdict()],
|
||||||
"compile": {
|
"compile": {
|
||||||
"js": [
|
"js": [
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
"exports": [],
|
"exports": [],
|
||||||
"src": [
|
"src": [
|
||||||
"src/**/*.js",
|
"src/**/*.js",
|
||||||
|
"build/ol.ext/*.js",
|
||||||
"build/examples/all.js"
|
"build/examples/all.js"
|
||||||
],
|
],
|
||||||
"compile": {
|
"compile": {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
],
|
],
|
||||||
"homepage": "http://openlayers.org/",
|
"homepage": "http://openlayers.org/",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"install": "node tasks/parse-examples.js",
|
"install": "node tasks/install.js",
|
||||||
"postinstall": "closure-util update",
|
"postinstall": "closure-util update",
|
||||||
"start": "node tasks/serve.js",
|
"start": "node tasks/serve.js",
|
||||||
"test": "node tasks/test.js"
|
"test": "node tasks/test.js"
|
||||||
@@ -30,6 +30,7 @@
|
|||||||
"htmlparser2": "3.7.3",
|
"htmlparser2": "3.7.3",
|
||||||
"jsdoc": "3.3.0-alpha9",
|
"jsdoc": "3.3.0-alpha9",
|
||||||
"nomnom": "1.8.0",
|
"nomnom": "1.8.0",
|
||||||
|
"rbush": "1.3.4",
|
||||||
"temp": "0.8.1",
|
"temp": "0.8.1",
|
||||||
"walk": "2.3.4"
|
"walk": "2.3.4"
|
||||||
},
|
},
|
||||||
@@ -43,5 +44,8 @@
|
|||||||
"phantomjs": "1.9.10",
|
"phantomjs": "1.9.10",
|
||||||
"proj4": "2.3.3",
|
"proj4": "2.3.3",
|
||||||
"sinon": "1.10.3"
|
"sinon": "1.10.3"
|
||||||
}
|
},
|
||||||
|
"ext": [
|
||||||
|
"rbush"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,199 +1,17 @@
|
|||||||
// Based on rbush https://github.com/mourner/rbush
|
|
||||||
// Copyright (c) 2013 Vladimir Agafonkin
|
|
||||||
//
|
|
||||||
// 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 without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, 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 NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
// THE SOFTWARE.
|
|
||||||
|
|
||||||
// FIXME bulk inserts
|
// FIXME bulk inserts
|
||||||
// FIXME is level argument needed to insert_?
|
|
||||||
|
|
||||||
goog.provide('ol.structs.RBush');
|
goog.provide('ol.structs.RBush');
|
||||||
|
|
||||||
goog.require('goog.array');
|
goog.require('goog.array');
|
||||||
goog.require('goog.asserts');
|
goog.require('goog.asserts');
|
||||||
goog.require('goog.object');
|
goog.require('goog.object');
|
||||||
goog.require('ol.extent');
|
goog.require('ol.ext.rbush');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @constructor
|
|
||||||
* @param {ol.Extent} extent Extent.
|
|
||||||
* @param {number} height Height.
|
|
||||||
* @param {Array.<ol.structs.RBushNode.<T>>} children Children.
|
|
||||||
* @param {?T} value Value.
|
|
||||||
* @struct
|
|
||||||
* @template T
|
|
||||||
*/
|
|
||||||
ol.structs.RBushNode = function(extent, height, children, value) {
|
|
||||||
|
|
||||||
if (height === 0) {
|
|
||||||
goog.asserts.assert(goog.isNull(children));
|
|
||||||
goog.asserts.assert(!goog.isNull(value));
|
|
||||||
} else {
|
|
||||||
goog.asserts.assert(!goog.isNull(children));
|
|
||||||
goog.asserts.assert(goog.isNull(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {ol.Extent}
|
|
||||||
*/
|
|
||||||
this.extent = extent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {number}
|
|
||||||
*/
|
|
||||||
this.height = height;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {Array.<ol.structs.RBushNode.<T>>}
|
|
||||||
*/
|
|
||||||
this.children = children;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {?T}
|
|
||||||
*/
|
|
||||||
this.value = value;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {ol.structs.RBushNode.<T>} node1 Node 1.
|
|
||||||
* @param {ol.structs.RBushNode.<T>} node2 Node 2.
|
|
||||||
* @return {number} Compare minimum X.
|
|
||||||
* @template T
|
|
||||||
*/
|
|
||||||
ol.structs.RBushNode.compareMinX = function(node1, node2) {
|
|
||||||
return node1.extent[0] - node2.extent[0];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {ol.structs.RBushNode.<T>} node1 Node 1.
|
|
||||||
* @param {ol.structs.RBushNode.<T>} node2 Node 2.
|
|
||||||
* @return {number} Compare minimum Y.
|
|
||||||
* @template T
|
|
||||||
*/
|
|
||||||
ol.structs.RBushNode.compareMinY = function(node1, node2) {
|
|
||||||
return node1.extent[1] - node2.extent[1];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {number} maxEntries Max entries.
|
|
||||||
*/
|
|
||||||
ol.structs.RBushNode.prototype.assertValid = function(maxEntries) {
|
|
||||||
if (this.height === 0) {
|
|
||||||
goog.asserts.assert(goog.isNull(this.children));
|
|
||||||
goog.asserts.assert(!goog.isNull(this.value));
|
|
||||||
} else {
|
|
||||||
goog.asserts.assert(!goog.isNull(this.children));
|
|
||||||
goog.asserts.assert(goog.isNull(this.value));
|
|
||||||
goog.asserts.assert(this.children.length <= maxEntries);
|
|
||||||
var i, ii;
|
|
||||||
for (i = 0, ii = this.children.length; i < ii; ++i) {
|
|
||||||
var child = this.children[i];
|
|
||||||
goog.asserts.assert(ol.extent.containsExtent(this.extent, child.extent));
|
|
||||||
child.assertValid(maxEntries);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {number} start Start.
|
|
||||||
* @param {number} stop Stop.
|
|
||||||
* @param {ol.Extent=} opt_extent Extent.
|
|
||||||
* @return {ol.Extent} Extent.
|
|
||||||
*/
|
|
||||||
ol.structs.RBushNode.prototype.getChildrenExtent =
|
|
||||||
function(start, stop, opt_extent) {
|
|
||||||
goog.asserts.assert(!this.isLeaf());
|
|
||||||
var children = this.children;
|
|
||||||
var extent = ol.extent.createOrUpdateEmpty(opt_extent);
|
|
||||||
var i;
|
|
||||||
for (i = start; i < stop; ++i) {
|
|
||||||
ol.extent.extend(extent, children[i].extent);
|
|
||||||
}
|
|
||||||
return extent;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {ol.Extent} extent Extent.
|
|
||||||
* @param {T} value Value.
|
|
||||||
* @param {Array.<ol.structs.RBushNode.<T>>} path Path.
|
|
||||||
* @return {boolean} Removed.
|
|
||||||
*/
|
|
||||||
ol.structs.RBushNode.prototype.remove = function(extent, value, path) {
|
|
||||||
var children = this.children;
|
|
||||||
var ii = children.length;
|
|
||||||
var child, i;
|
|
||||||
if (this.height == 1) {
|
|
||||||
for (i = 0; i < ii; ++i) {
|
|
||||||
child = children[i];
|
|
||||||
if (child.value === value) {
|
|
||||||
goog.array.removeAt(children, i);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
goog.asserts.assert(this.height > 1);
|
|
||||||
for (i = 0; i < ii; ++i) {
|
|
||||||
child = children[i];
|
|
||||||
if (ol.extent.containsExtent(child.extent, extent)) {
|
|
||||||
path.push(child);
|
|
||||||
if (child.remove(extent, value, path)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
path.pop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* FIXME empty description for jsdoc
|
|
||||||
*/
|
|
||||||
ol.structs.RBushNode.prototype.updateExtent = function() {
|
|
||||||
goog.asserts.assert(!this.isLeaf());
|
|
||||||
var extent = ol.extent.createOrUpdateEmpty(this.extent);
|
|
||||||
var children = this.children;
|
|
||||||
var i, ii;
|
|
||||||
for (i = 0, ii = children.length; i < ii; ++i) {
|
|
||||||
ol.extent.extend(extent, children[i].extent);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return {boolean} Is leaf.
|
|
||||||
*/
|
|
||||||
ol.structs.RBushNode.prototype.isLeaf = function() {
|
|
||||||
return goog.isNull(this.children);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Wrapper around the RBush by Vladimir Agafonkin.
|
||||||
|
*
|
||||||
* @constructor
|
* @constructor
|
||||||
* @param {number=} opt_maxEntries Max entries.
|
* @param {number=} opt_maxEntries Max entries.
|
||||||
* @see https://github.com/mourner/rbush
|
* @see https://github.com/mourner/rbush
|
||||||
@@ -204,28 +22,16 @@ ol.structs.RBush = function(opt_maxEntries) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @type {number}
|
|
||||||
*/
|
*/
|
||||||
this.maxEntries_ =
|
this.rbush_ = ol.ext.rbush(opt_maxEntries);
|
||||||
Math.max(4, goog.isDef(opt_maxEntries) ? opt_maxEntries : 9);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* A mapping between the objects added to this rbush wrapper
|
||||||
|
* and the objects that are actually added to the internal rbush.
|
||||||
* @private
|
* @private
|
||||||
* @type {number}
|
* @type {Object.<number, Object>}
|
||||||
*/
|
*/
|
||||||
this.minEntries_ = Math.max(2, Math.ceil(0.4 * this.maxEntries_));
|
this.items_ = {};
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @type {ol.structs.RBushNode.<T>}
|
|
||||||
*/
|
|
||||||
this.root_ = new ol.structs.RBushNode(ol.extent.createEmpty(), 1, [], null);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @type {Object.<string, ol.Extent>}
|
|
||||||
*/
|
|
||||||
this.valueExtent_ = {};
|
|
||||||
|
|
||||||
if (goog.DEBUG) {
|
if (goog.DEBUG) {
|
||||||
/**
|
/**
|
||||||
@@ -234,167 +40,89 @@ ol.structs.RBush = function(opt_maxEntries) {
|
|||||||
*/
|
*/
|
||||||
this.readers_ = 0;
|
this.readers_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {ol.structs.RBushNode.<T>} node Node.
|
|
||||||
* @param {function(ol.structs.RBushNode.<T>, ol.structs.RBushNode.<T>): number}
|
|
||||||
* compare Compare.
|
|
||||||
* @private
|
|
||||||
* @return {number} All distance margin.
|
|
||||||
*/
|
|
||||||
ol.structs.RBush.prototype.allDistMargin_ = function(node, compare) {
|
|
||||||
var children = node.children;
|
|
||||||
var m = this.minEntries_;
|
|
||||||
var M = children.length;
|
|
||||||
var i;
|
|
||||||
goog.array.sort(children, compare);
|
|
||||||
var leftExtent = node.getChildrenExtent(0, m);
|
|
||||||
var rightExtent = node.getChildrenExtent(M - m, M);
|
|
||||||
var margin =
|
|
||||||
ol.extent.getMargin(leftExtent) + ol.extent.getMargin(rightExtent);
|
|
||||||
for (i = m; i < M - m; ++i) {
|
|
||||||
ol.extent.extend(leftExtent, children[i].extent);
|
|
||||||
margin += ol.extent.getMargin(leftExtent);
|
|
||||||
}
|
|
||||||
for (i = M - m - 1; i >= m; --i) {
|
|
||||||
ol.extent.extend(rightExtent, children[i].extent);
|
|
||||||
margin += ol.extent.getMargin(rightExtent);
|
|
||||||
}
|
|
||||||
return margin;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* FIXME empty description for jsdoc
|
|
||||||
*/
|
|
||||||
ol.structs.RBush.prototype.assertValid = function() {
|
|
||||||
this.root_.assertValid(this.maxEntries_);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {ol.structs.RBushNode.<T>} node Node.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
ol.structs.RBush.prototype.chooseSplitAxis_ = function(node) {
|
|
||||||
var xMargin = this.allDistMargin_(node, ol.structs.RBushNode.compareMinX);
|
|
||||||
var yMargin = this.allDistMargin_(node, ol.structs.RBushNode.compareMinY);
|
|
||||||
if (xMargin < yMargin) {
|
|
||||||
goog.array.sort(node.children, ol.structs.RBushNode.compareMinX);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {ol.structs.RBushNode.<T>} node Node.
|
|
||||||
* @private
|
|
||||||
* @return {number} Split index.
|
|
||||||
*/
|
|
||||||
ol.structs.RBush.prototype.chooseSplitIndex_ = function(node) {
|
|
||||||
var children = node.children;
|
|
||||||
var m = this.minEntries_;
|
|
||||||
var M = children.length;
|
|
||||||
var minOverlap = Infinity;
|
|
||||||
var minArea = Infinity;
|
|
||||||
var extent1 = ol.extent.createEmpty();
|
|
||||||
var extent2 = ol.extent.createEmpty();
|
|
||||||
var index = 0;
|
|
||||||
var i;
|
|
||||||
for (i = m; i <= M - m; ++i) {
|
|
||||||
extent1 = node.getChildrenExtent(0, i, extent1);
|
|
||||||
extent2 = node.getChildrenExtent(i, M, extent2);
|
|
||||||
var overlap = ol.extent.getIntersectionArea(extent1, extent2);
|
|
||||||
var area = ol.extent.getArea(extent1) + ol.extent.getArea(extent2);
|
|
||||||
if (overlap < minOverlap) {
|
|
||||||
minOverlap = overlap;
|
|
||||||
minArea = Math.min(area, minArea);
|
|
||||||
index = i;
|
|
||||||
} else if (overlap == minOverlap && area < minArea) {
|
|
||||||
minArea = area;
|
|
||||||
index = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return index;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Insert a value into the RBush.
|
||||||
* @param {ol.Extent} extent Extent.
|
* @param {ol.Extent} extent Extent.
|
||||||
* @param {ol.structs.RBushNode.<T>} node Node.
|
* @param {T} value Value.
|
||||||
* @param {number} level Level.
|
|
||||||
* @param {Array.<ol.structs.RBushNode.<T>>} path Path.
|
|
||||||
* @private
|
|
||||||
* @return {ol.structs.RBushNode.<T>} Node.
|
|
||||||
*/
|
*/
|
||||||
ol.structs.RBush.prototype.chooseSubtree_ =
|
ol.structs.RBush.prototype.insert = function(extent, value) {
|
||||||
function(extent, node, level, path) {
|
if (goog.DEBUG && this.readers_) {
|
||||||
while (!node.isLeaf() && path.length - 1 != level) {
|
throw new Error('Can not insert value while reading');
|
||||||
var minArea = Infinity;
|
|
||||||
var minEnlargement = Infinity;
|
|
||||||
var children = node.children;
|
|
||||||
var bestChild = null;
|
|
||||||
var i, ii;
|
|
||||||
for (i = 0, ii = children.length; i < ii; ++i) {
|
|
||||||
var child = children[i];
|
|
||||||
var area = ol.extent.getArea(child.extent);
|
|
||||||
var enlargement = ol.extent.getEnlargedArea(child.extent, extent) - area;
|
|
||||||
if (enlargement < minEnlargement) {
|
|
||||||
minEnlargement = enlargement;
|
|
||||||
minArea = Math.min(area, minArea);
|
|
||||||
bestChild = child;
|
|
||||||
} else if (enlargement == minEnlargement && area < minArea) {
|
|
||||||
minArea = area;
|
|
||||||
bestChild = child;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
goog.asserts.assert(!goog.isNull(bestChild));
|
|
||||||
node = bestChild;
|
|
||||||
path.push(node);
|
|
||||||
}
|
}
|
||||||
return node;
|
var item = [
|
||||||
|
extent[0],
|
||||||
|
extent[1],
|
||||||
|
extent[2],
|
||||||
|
extent[3],
|
||||||
|
value
|
||||||
|
];
|
||||||
|
this.rbush_.insert(item);
|
||||||
|
// remember the object that was added to the internal rbush
|
||||||
|
goog.object.add(this.items_, goog.getUid(value).toString(), item);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FIXME empty description for jsdoc
|
* Remove a value from the RBush.
|
||||||
|
* @param {T} value Value.
|
||||||
|
* @return {boolean} Removed.
|
||||||
*/
|
*/
|
||||||
ol.structs.RBush.prototype.clear = function() {
|
ol.structs.RBush.prototype.remove = function(value) {
|
||||||
var node = this.root_;
|
if (goog.DEBUG && this.readers_) {
|
||||||
node.extent = ol.extent.createOrUpdateEmpty(this.root_.extent);
|
throw new Error('Can not remove value while reading');
|
||||||
node.height = 1;
|
|
||||||
node.children.length = 0;
|
|
||||||
node.value = null;
|
|
||||||
goog.object.clear(this.valueExtent_);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Array.<ol.structs.RBushNode.<T>>} path Path.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
ol.structs.RBush.prototype.condense_ = function(path) {
|
|
||||||
var i;
|
|
||||||
for (i = path.length - 1; i >= 0; --i) {
|
|
||||||
var node = path[i];
|
|
||||||
if (node.children.length === 0) {
|
|
||||||
if (i > 0) {
|
|
||||||
goog.array.remove(path[i - 1].children, node);
|
|
||||||
} else {
|
|
||||||
this.clear();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
node.updateExtent();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
var uid = goog.getUid(value).toString();
|
||||||
|
goog.asserts.assert(goog.object.containsKey(this.items_, uid));
|
||||||
|
|
||||||
|
// get the object in which the value was wrapped when adding to the
|
||||||
|
// internal rbush. then use that object to do the removal.
|
||||||
|
var item = goog.object.get(this.items_, uid);
|
||||||
|
goog.object.remove(this.items_, uid);
|
||||||
|
return this.rbush_.remove(item) !== null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calls a callback function with each node in the tree. Inside the callback,
|
* Update the extent of a value in the RBush.
|
||||||
* no tree modifications (insert, update, remove) can be made.
|
* @param {ol.Extent} extent Extent.
|
||||||
|
* @param {T} value Value.
|
||||||
|
*/
|
||||||
|
ol.structs.RBush.prototype.update = function(extent, value) {
|
||||||
|
this.remove(value);
|
||||||
|
this.insert(extent, value);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return all values in the RBush.
|
||||||
|
* @return {Array.<T>} All.
|
||||||
|
*/
|
||||||
|
ol.structs.RBush.prototype.getAll = function() {
|
||||||
|
var items = this.rbush_.all();
|
||||||
|
return goog.array.map(items, function(item) {
|
||||||
|
return item[4];
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return all values in the given extent.
|
||||||
|
* @param {ol.Extent} extent Extent.
|
||||||
|
* @return {Array.<T>} All in extent.
|
||||||
|
*/
|
||||||
|
ol.structs.RBush.prototype.getInExtent = function(extent) {
|
||||||
|
var items = this.rbush_.search(extent);
|
||||||
|
return goog.array.map(items, function(item) {
|
||||||
|
return item[4];
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls a callback function with each value in the tree.
|
||||||
* If the callback returns a truthy value, this value is returned without
|
* If the callback returns a truthy value, this value is returned without
|
||||||
* checking the rest of the tree.
|
* checking the rest of the tree.
|
||||||
* @param {function(this: S, T): *} callback Callback.
|
* @param {function(this: S, T): *} callback Callback.
|
||||||
@@ -406,49 +134,18 @@ ol.structs.RBush.prototype.forEach = function(callback, opt_this) {
|
|||||||
if (goog.DEBUG) {
|
if (goog.DEBUG) {
|
||||||
++this.readers_;
|
++this.readers_;
|
||||||
try {
|
try {
|
||||||
return this.forEach_(this.root_, callback, opt_this);
|
return this.forEach_(this.getAll(), callback, opt_this);
|
||||||
} finally {
|
} finally {
|
||||||
--this.readers_;
|
--this.readers_;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return this.forEach_(this.root_, callback, opt_this);
|
return this.forEach_(this.getAll(), callback, opt_this);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {ol.structs.RBushNode.<T>} node Node.
|
* Calls a callback function with each value in the provided extent.
|
||||||
* @param {function(this: S, T): *} callback Callback.
|
|
||||||
* @param {S=} opt_this The object to use as `this` in `callback`.
|
|
||||||
* @private
|
|
||||||
* @return {*} Callback return value.
|
|
||||||
* @template S
|
|
||||||
*/
|
|
||||||
ol.structs.RBush.prototype.forEach_ = function(node, callback, opt_this) {
|
|
||||||
goog.asserts.assert(!node.isLeaf());
|
|
||||||
/** @type {Array.<ol.structs.RBushNode.<T>>} */
|
|
||||||
var toVisit = [node];
|
|
||||||
var children, i, ii, result;
|
|
||||||
while (toVisit.length > 0) {
|
|
||||||
node = toVisit.pop();
|
|
||||||
children = node.children;
|
|
||||||
if (node.height == 1) {
|
|
||||||
for (i = 0, ii = children.length; i < ii; ++i) {
|
|
||||||
result = callback.call(opt_this, children[i].value);
|
|
||||||
if (result) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
toVisit.push.apply(toVisit, children);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calls a callback function with each node in the provided extent. Inside the
|
|
||||||
* callback, no tree modifications (insert, update, remove) can be made.
|
|
||||||
* @param {ol.Extent} extent Extent.
|
* @param {ol.Extent} extent Extent.
|
||||||
* @param {function(this: S, T): *} callback Callback.
|
* @param {function(this: S, T): *} callback Callback.
|
||||||
* @param {S=} opt_this The object to use as `this` in `callback`.
|
* @param {S=} opt_this The object to use as `this` in `callback`.
|
||||||
@@ -460,81 +157,50 @@ ol.structs.RBush.prototype.forEachInExtent =
|
|||||||
if (goog.DEBUG) {
|
if (goog.DEBUG) {
|
||||||
++this.readers_;
|
++this.readers_;
|
||||||
try {
|
try {
|
||||||
return this.forEachInExtent_(extent, callback, opt_this);
|
return this.forEach_(this.getInExtent(extent), callback, opt_this);
|
||||||
} finally {
|
} finally {
|
||||||
--this.readers_;
|
--this.readers_;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return this.forEachInExtent_(extent, callback, opt_this);
|
return this.forEach_(this.getInExtent(extent), callback, opt_this);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {ol.Extent} extent Extent.
|
* @param {Array.<T>} values Values.
|
||||||
* @param {function(this: S, T): *} callback Callback.
|
* @param {function(this: S, T): *} callback Callback.
|
||||||
* @param {S=} opt_this The object to use as `this` in `callback`.
|
* @param {S=} opt_this The object to use as `this` in `callback`.
|
||||||
* @private
|
* @private
|
||||||
* @return {*} Callback return value.
|
* @return {*} Callback return value.
|
||||||
* @template S
|
* @template S
|
||||||
*/
|
*/
|
||||||
ol.structs.RBush.prototype.forEachInExtent_ =
|
ol.structs.RBush.prototype.forEach_ = function(values, callback, opt_this) {
|
||||||
function(extent, callback, opt_this) {
|
|
||||||
/** @type {Array.<ol.structs.RBushNode.<T>>} */
|
|
||||||
var toVisit = [this.root_];
|
|
||||||
var result;
|
var result;
|
||||||
while (toVisit.length > 0) {
|
for (var i = 0, l = values.length; i < l; i++) {
|
||||||
var node = toVisit.pop();
|
result = callback.call(opt_this, values[i]);
|
||||||
if (ol.extent.intersects(extent, node.extent)) {
|
if (result) {
|
||||||
if (node.isLeaf()) {
|
return result;
|
||||||
result = callback.call(opt_this, node.value);
|
|
||||||
if (result) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
} else if (ol.extent.containsExtent(extent, node.extent)) {
|
|
||||||
result = this.forEach_(node, callback, opt_this);
|
|
||||||
if (result) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
toVisit.push.apply(toVisit, node.children);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return undefined;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return {Array.<T>} All.
|
* @return {boolean} Is empty.
|
||||||
*/
|
*/
|
||||||
ol.structs.RBush.prototype.getAll = function() {
|
ol.structs.RBush.prototype.isEmpty = function() {
|
||||||
var values = [];
|
return goog.object.isEmpty(this.items_);
|
||||||
this.forEach(
|
|
||||||
/**
|
|
||||||
* @param {T} value Value.
|
|
||||||
*/
|
|
||||||
function(value) {
|
|
||||||
values.push(value);
|
|
||||||
});
|
|
||||||
return values;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {ol.Extent} extent Extent.
|
* Remove all values from the RBush.
|
||||||
* @return {Array.<T>} All in extent.
|
|
||||||
*/
|
*/
|
||||||
ol.structs.RBush.prototype.getInExtent = function(extent) {
|
ol.structs.RBush.prototype.clear = function() {
|
||||||
var values = [];
|
this.rbush_.clear();
|
||||||
this.forEachInExtent(extent,
|
goog.object.clear(this.items_);
|
||||||
/**
|
|
||||||
* @param {T} value Value.
|
|
||||||
*/
|
|
||||||
function(value) {
|
|
||||||
values.push(value);
|
|
||||||
});
|
|
||||||
return values;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -543,160 +209,6 @@ ol.structs.RBush.prototype.getInExtent = function(extent) {
|
|||||||
* @return {ol.Extent} Extent.
|
* @return {ol.Extent} Extent.
|
||||||
*/
|
*/
|
||||||
ol.structs.RBush.prototype.getExtent = function(opt_extent) {
|
ol.structs.RBush.prototype.getExtent = function(opt_extent) {
|
||||||
return ol.extent.returnOrUpdate(this.root_.extent, opt_extent);
|
// FIXME add getExtent() to rbush
|
||||||
};
|
return this.rbush_.data.bbox;
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {T} value Value.
|
|
||||||
* @private
|
|
||||||
* @return {string} Key.
|
|
||||||
*/
|
|
||||||
ol.structs.RBush.prototype.getKey_ = function(value) {
|
|
||||||
goog.asserts.assert(goog.isObject(value));
|
|
||||||
return goog.getUid(value).toString();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {ol.Extent} extent Extent.
|
|
||||||
* @param {T} value Value.
|
|
||||||
*/
|
|
||||||
ol.structs.RBush.prototype.insert = function(extent, value) {
|
|
||||||
if (goog.DEBUG && this.readers_) {
|
|
||||||
throw new Error('cannot insert value while reading');
|
|
||||||
}
|
|
||||||
var key = this.getKey_(value);
|
|
||||||
goog.asserts.assert(!this.valueExtent_.hasOwnProperty(key));
|
|
||||||
this.insert_(extent, value, this.root_.height - 1);
|
|
||||||
this.valueExtent_[key] = ol.extent.clone(extent);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {ol.Extent} extent Extent.
|
|
||||||
* @param {T} value Value.
|
|
||||||
* @param {number} level Level.
|
|
||||||
* @private
|
|
||||||
* @return {ol.structs.RBushNode.<T>} Node.
|
|
||||||
*/
|
|
||||||
ol.structs.RBush.prototype.insert_ = function(extent, value, level) {
|
|
||||||
/** @type {Array.<ol.structs.RBushNode.<T>>} */
|
|
||||||
var path = [this.root_];
|
|
||||||
var node = this.chooseSubtree_(extent, this.root_, level, path);
|
|
||||||
node.children.push(new ol.structs.RBushNode(extent, 0, null, value));
|
|
||||||
ol.extent.extend(node.extent, extent);
|
|
||||||
var i;
|
|
||||||
for (i = path.length - 1; i >= 0; --i) {
|
|
||||||
if (path[i].children.length > this.maxEntries_) {
|
|
||||||
this.split_(path, i);
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (; i >= 0; --i) {
|
|
||||||
ol.extent.extend(path[i].extent, extent);
|
|
||||||
}
|
|
||||||
return node;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return {boolean} Is empty.
|
|
||||||
*/
|
|
||||||
ol.structs.RBush.prototype.isEmpty = function() {
|
|
||||||
return this.root_.children.length === 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {T} value Value.
|
|
||||||
* @return {boolean} Removed.
|
|
||||||
*/
|
|
||||||
ol.structs.RBush.prototype.remove = function(value) {
|
|
||||||
if (goog.DEBUG && this.readers_) {
|
|
||||||
throw new Error('cannot remove value while reading');
|
|
||||||
}
|
|
||||||
var key = this.getKey_(value);
|
|
||||||
goog.asserts.assert(this.valueExtent_.hasOwnProperty(key));
|
|
||||||
var extent = this.valueExtent_[key];
|
|
||||||
delete this.valueExtent_[key];
|
|
||||||
return this.remove_(extent, value);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {ol.Extent} extent Extent.
|
|
||||||
* @param {T} value Value.
|
|
||||||
* @private
|
|
||||||
* @return {boolean} Removed.
|
|
||||||
*/
|
|
||||||
ol.structs.RBush.prototype.remove_ = function(extent, value) {
|
|
||||||
var root = this.root_;
|
|
||||||
var path = [root];
|
|
||||||
var removed = root.remove(extent, value, path);
|
|
||||||
if (removed) {
|
|
||||||
this.condense_(path);
|
|
||||||
} else {
|
|
||||||
goog.asserts.assert(path.length == 1);
|
|
||||||
goog.asserts.assert(path[0] === root);
|
|
||||||
}
|
|
||||||
return removed;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Array.<ol.structs.RBushNode.<T>>} path Path.
|
|
||||||
* @param {number} level Level.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
ol.structs.RBush.prototype.split_ = function(path, level) {
|
|
||||||
var node = path[level];
|
|
||||||
this.chooseSplitAxis_(node);
|
|
||||||
var splitIndex = this.chooseSplitIndex_(node);
|
|
||||||
// FIXME too few arguments to splice here
|
|
||||||
var newChildren = node.children.splice(splitIndex);
|
|
||||||
var newNode = new ol.structs.RBushNode(
|
|
||||||
ol.extent.createEmpty(), node.height, newChildren, null);
|
|
||||||
node.updateExtent();
|
|
||||||
newNode.updateExtent();
|
|
||||||
if (level) {
|
|
||||||
path[level - 1].children.push(newNode);
|
|
||||||
} else {
|
|
||||||
this.splitRoot_(node, newNode);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {ol.structs.RBushNode.<T>} node1 Node 1.
|
|
||||||
* @param {ol.structs.RBushNode.<T>} node2 Node 2.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
ol.structs.RBush.prototype.splitRoot_ = function(node1, node2) {
|
|
||||||
goog.asserts.assert(node1 === this.root_);
|
|
||||||
var height = node1.height + 1;
|
|
||||||
var extent = ol.extent.extend(node1.extent.slice(), node2.extent);
|
|
||||||
var children = [node1, node2];
|
|
||||||
this.root_ = new ol.structs.RBushNode(extent, height, children, null);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {ol.Extent} extent Extent.
|
|
||||||
* @param {T} value Value.
|
|
||||||
*/
|
|
||||||
ol.structs.RBush.prototype.update = function(extent, value) {
|
|
||||||
var key = this.getKey_(value);
|
|
||||||
var currentExtent = this.valueExtent_[key];
|
|
||||||
goog.asserts.assert(goog.isDef(currentExtent));
|
|
||||||
if (!ol.extent.equals(currentExtent, extent)) {
|
|
||||||
if (goog.DEBUG && this.readers_) {
|
|
||||||
throw new Error('cannot update extent while reading');
|
|
||||||
}
|
|
||||||
var removed = this.remove_(currentExtent, value);
|
|
||||||
goog.asserts.assert(removed);
|
|
||||||
this.insert_(extent, value, this.root_.height - 1);
|
|
||||||
this.valueExtent_[key] = ol.extent.clone(extent, currentExtent);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|||||||
97
tasks/build-ext.js
Normal file
97
tasks/build-ext.js
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
var fs = require('fs');
|
||||||
|
var path = require('path');
|
||||||
|
|
||||||
|
var async = require('async');
|
||||||
|
var fse = require('fs-extra');
|
||||||
|
|
||||||
|
var pkg = require('../package.json');
|
||||||
|
|
||||||
|
var root = path.join(__dirname, '..');
|
||||||
|
var buildDir = path.join(root, 'build', 'ol.ext');
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get external module metadata.
|
||||||
|
* @return {Array.<Object>} Array of objects representing external modules.
|
||||||
|
*/
|
||||||
|
function getExternalModules() {
|
||||||
|
return pkg.ext.map(function(name) {
|
||||||
|
return {
|
||||||
|
name: name,
|
||||||
|
main: require.resolve(name)
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrap a CommonJS module in Closure Library accessible code.
|
||||||
|
* @param {Object} mod Module metadata.
|
||||||
|
* @param {function(Error, string)} callback Called with any error and the
|
||||||
|
* wrapped module.
|
||||||
|
*/
|
||||||
|
function wrapModule(mod, callback) {
|
||||||
|
fs.readFile(mod.main, function(err, data) {
|
||||||
|
if (err) {
|
||||||
|
callback(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var wrapped = 'goog.provide(\'ol.ext.' + mod.name + '\');\n' +
|
||||||
|
'/** @typedef {function(*)} */\n' +
|
||||||
|
'ol.ext.' + mod.name + ';\n' +
|
||||||
|
'(function() {\n' +
|
||||||
|
'var exports = {};\n' +
|
||||||
|
'var module = {exports: exports};\n' +
|
||||||
|
'/**\n' +
|
||||||
|
' * @fileoverview\n' +
|
||||||
|
' * @suppress {accessControls, ambiguousFunctionDecl, ' +
|
||||||
|
'checkDebuggerStatement, checkRegExp, checkTypes, checkVars, const, ' +
|
||||||
|
'constantProperty, deprecated, duplicate, es5Strict, ' +
|
||||||
|
'fileoverviewTags, missingProperties, nonStandardJsDocs, ' +
|
||||||
|
'strictModuleDepCheck, suspiciousCode, undefinedNames, ' +
|
||||||
|
'undefinedVars, unknownDefines, uselessCode, visibility}\n' +
|
||||||
|
' */\n' + data.toString() + '\n' +
|
||||||
|
'ol.ext.' + mod.name + ' = module.exports;\n' +
|
||||||
|
'})();\n';
|
||||||
|
callback(null, wrapped);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build external modules.
|
||||||
|
* @param {Array.<Object>} modules External modules.
|
||||||
|
* @param {function(Error)} callback Called with any error.
|
||||||
|
*/
|
||||||
|
function buildModules(modules, callback) {
|
||||||
|
async.each(modules, function(mod, done) {
|
||||||
|
var output = path.join(buildDir, mod.name) + '.js';
|
||||||
|
async.waterfall([
|
||||||
|
wrapModule.bind(null, mod),
|
||||||
|
fse.outputFile.bind(fse, output)
|
||||||
|
], done);
|
||||||
|
}, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build all external modules.
|
||||||
|
* @param {function(Error)} callback Called with any error.
|
||||||
|
*/
|
||||||
|
function main(callback) {
|
||||||
|
var modules = getExternalModules();
|
||||||
|
buildModules(modules, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (require.main === module) {
|
||||||
|
main(function(err) {
|
||||||
|
if (err) {
|
||||||
|
process.stderr.write(err.message + '\n');
|
||||||
|
process.exit(1);
|
||||||
|
} else {
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = main;
|
||||||
@@ -127,7 +127,7 @@ function getDependencies(config, exports, callback) {
|
|||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
options = {
|
options = {
|
||||||
lib: ['src/**/*.js'],
|
lib: ['src/**/*.js', 'build/ol.ext/*.js'],
|
||||||
cwd: root
|
cwd: root
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
17
tasks/install.js
Normal file
17
tasks/install.js
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
var async = require('async');
|
||||||
|
|
||||||
|
var buildExt = require('./build-ext');
|
||||||
|
var parseExamples = require('./parse-examples');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse examples and build external modules.
|
||||||
|
*/
|
||||||
|
async.waterfall([
|
||||||
|
parseExamples,
|
||||||
|
buildExt
|
||||||
|
], function(err) {
|
||||||
|
if (err) {
|
||||||
|
process.stderr.write(err + '\n');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -137,14 +137,25 @@ function writeExampleList(exampleInfos, callback) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* List examples, parse them, and write example list.
|
* List examples, parse them, and write example list.
|
||||||
|
* @param {function(Error)} callback Called with any error.
|
||||||
*/
|
*/
|
||||||
async.waterfall([
|
function main(callback) {
|
||||||
listExamples,
|
async.waterfall([
|
||||||
parseExamples,
|
listExamples,
|
||||||
writeExampleList
|
parseExamples,
|
||||||
], function(err) {
|
writeExampleList
|
||||||
if (err) {
|
], callback);
|
||||||
process.stderr.write(err + '\n');
|
}
|
||||||
process.exit(1);
|
|
||||||
}
|
if (require.main === module) {
|
||||||
});
|
main(function(err) {
|
||||||
|
if (err) {
|
||||||
|
process.stderr.write(err.message + '\n');
|
||||||
|
process.exit(1);
|
||||||
|
} else {
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = main;
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ var createServer = exports.createServer = function(callback) {
|
|||||||
var manager = new closure.Manager({
|
var manager = new closure.Manager({
|
||||||
lib: [
|
lib: [
|
||||||
'src/**/*.js',
|
'src/**/*.js',
|
||||||
|
'build/ol.ext/*.js',
|
||||||
'test/spec/**/*.test.js'
|
'test/spec/**/*.test.js'
|
||||||
],
|
],
|
||||||
main: 'examples/*.js'
|
main: 'examples/*.js'
|
||||||
|
|||||||
Reference in New Issue
Block a user