Add ol.geom2.PointCollection
This commit is contained in:
4
src/ol/geom2/pointcollection.exports
Normal file
4
src/ol/geom2/pointcollection.exports
Normal file
@@ -0,0 +1,4 @@
|
||||
@exportSymbol ol.geom2.PointCollection
|
||||
@exportSymbol ol.geom2.PointCollection.createEmpty
|
||||
@exportSymbol ol.geom2.PointCollection.pack
|
||||
@exportProperty ol.geom2.PointCollection.prototype.add
|
||||
142
src/ol/geom2/pointcollection.js
Normal file
142
src/ol/geom2/pointcollection.js
Normal file
@@ -0,0 +1,142 @@
|
||||
goog.provide('ol.geom2.Point');
|
||||
goog.provide('ol.geom2.PointCollection');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('ol.Extent');
|
||||
goog.require('ol.geom2');
|
||||
goog.require('ol.structs.Buffer');
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {Array.<number>}
|
||||
*/
|
||||
ol.geom2.Point;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {ol.structs.Buffer} buf Buffer.
|
||||
* @param {number=} opt_dim Dimension.
|
||||
*/
|
||||
ol.geom2.PointCollection = function(buf, opt_dim) {
|
||||
|
||||
/**
|
||||
* @type {ol.structs.Buffer}
|
||||
*/
|
||||
this.buf = buf;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.dim = goog.isDef(opt_dim) ? opt_dim : 2;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} capacity Capacity.
|
||||
* @param {number=} opt_dim Dimension.
|
||||
* @return {ol.geom2.PointCollection} Point collection.
|
||||
*/
|
||||
ol.geom2.PointCollection.createEmpty = function(capacity, opt_dim) {
|
||||
var dim = goog.isDef(opt_dim) ? opt_dim : 2;
|
||||
var buf = new ol.structs.Buffer(new Array(capacity * dim), 0);
|
||||
return new ol.geom2.PointCollection(buf, dim);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<ol.geom2.Point>} unpackedPoints Unpacked points.
|
||||
* @param {number=} opt_capacity Capacity.
|
||||
* @param {number=} opt_dim Dimension.
|
||||
* @return {ol.geom2.PointCollection} Point collection.
|
||||
*/
|
||||
ol.geom2.PointCollection.pack =
|
||||
function(unpackedPoints, opt_capacity, opt_dim) {
|
||||
var n = unpackedPoints.length;
|
||||
var dim = goog.isDef(opt_dim) ? opt_dim :
|
||||
n > 0 ? unpackedPoints[0].length : 2;
|
||||
var capacity = goog.isDef(opt_capacity) ? opt_capacity : n * dim;
|
||||
goog.asserts.assert(capacity >= n * dim);
|
||||
var arr = new Array(capacity);
|
||||
ol.geom2.packPoints(arr, 0, unpackedPoints, dim);
|
||||
var buf = new ol.structs.Buffer(arr, n * dim);
|
||||
return new ol.geom2.PointCollection(buf, dim);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.geom2.Point} point Point.
|
||||
* @return {number} Offset.
|
||||
*/
|
||||
ol.geom2.PointCollection.prototype.add = function(point) {
|
||||
goog.asserts.assert(point.length == this.dim);
|
||||
return this.buf.add(point);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} offset Offset.
|
||||
* @return {ol.geom2.Point} Point.
|
||||
*/
|
||||
ol.geom2.PointCollection.prototype.get = function(offset) {
|
||||
var arr = this.buf.getArray();
|
||||
var dim = this.dim;
|
||||
goog.asserts.assert(0 <= offset && offset + dim < arr.length);
|
||||
goog.asserts.assert(offset % dim === 0);
|
||||
return arr.slice(offset, offset + dim);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} Count.
|
||||
*/
|
||||
ol.geom2.PointCollection.prototype.getCount = function() {
|
||||
return this.buf.getCount() / this.dim;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Extent} Extent.
|
||||
*/
|
||||
ol.geom2.PointCollection.prototype.getExtent = function() {
|
||||
return ol.geom2.getExtent(this.buf, this.dim);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} offset Offset.
|
||||
*/
|
||||
ol.geom2.PointCollection.prototype.remove = function(offset) {
|
||||
this.buf.remove(this.dim, offset);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} offset Offset.
|
||||
* @param {ol.geom2.Point} point Point.
|
||||
*/
|
||||
ol.geom2.PointCollection.prototype.set = function(offset, point) {
|
||||
this.buf.set(point, offset);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Array.<ol.geom2.Point>} Points.
|
||||
*/
|
||||
ol.geom2.PointCollection.prototype.unpack = function() {
|
||||
var dim = this.dim;
|
||||
var n = this.getCount();
|
||||
var points = new Array(n);
|
||||
var i = 0;
|
||||
var bufArr = this.buf.getArray();
|
||||
this.buf.forEachRange(function(start, stop) {
|
||||
var j;
|
||||
for (j = start; j < stop; j += dim) {
|
||||
points[i++] = bufArr.slice(j, j + dim);
|
||||
}
|
||||
});
|
||||
goog.asserts.assert(i == n);
|
||||
return points;
|
||||
};
|
||||
293
test/spec/ol/geom2/pointcollection.test.js
Normal file
293
test/spec/ol/geom2/pointcollection.test.js
Normal file
@@ -0,0 +1,293 @@
|
||||
goog.provide('ol.test.geom2.PointCollection');
|
||||
|
||||
|
||||
describe('ol.geom2.PointCollection', function() {
|
||||
|
||||
describe('createEmpty', function() {
|
||||
|
||||
it('creates an empty instance with the specified capacity', function() {
|
||||
var pc = ol.geom2.PointCollection.createEmpty(16);
|
||||
expect(pc.getCount()).to.be(0);
|
||||
expect(pc.buf.getArray()).to.have.length(32);
|
||||
});
|
||||
|
||||
it('can create empty collections for higher dimensions', function() {
|
||||
var pc = ol.geom2.PointCollection.createEmpty(16, 3);
|
||||
expect(pc.getCount()).to.be(0);
|
||||
expect(pc.buf.getArray()).to.have.length(48);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('pack', function() {
|
||||
|
||||
it('packs an empty array', function() {
|
||||
var pc = ol.geom2.PointCollection.pack([]);
|
||||
expect(pc.buf.getArray()).to.be.empty();
|
||||
expect(pc.dim).to.be(2);
|
||||
});
|
||||
|
||||
it('packs an empty array with a capacity', function() {
|
||||
var pc = ol.geom2.PointCollection.pack([], 4);
|
||||
expect(pc.buf.getArray()).to.eql([NaN, NaN, NaN, NaN]);
|
||||
expect(pc.dim).to.be(2);
|
||||
});
|
||||
|
||||
it('packs an empty array with a capacity and a dimension', function() {
|
||||
var pc = ol.geom2.PointCollection.pack([], 8, 2);
|
||||
expect(pc.buf.getArray()).to.eql(
|
||||
[NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN]);
|
||||
expect(pc.dim).to.be(2);
|
||||
});
|
||||
|
||||
it('packs a single point', function() {
|
||||
var pc = ol.geom2.PointCollection.pack([[0, 1]]);
|
||||
expect(pc.buf.getArray()).to.eql([0, 1]);
|
||||
expect(pc.dim).to.be(2);
|
||||
});
|
||||
|
||||
it('can pack multiple points', function() {
|
||||
var pc = ol.geom2.PointCollection.pack([[0, 1], [2, 3], [4, 5]]);
|
||||
expect(pc.buf.getArray()).to.eql([0, 1, 2, 3, 4, 5]);
|
||||
expect(pc.dim).to.be(2);
|
||||
});
|
||||
|
||||
it('can pack multiple points with a capacity', function() {
|
||||
var pc = ol.geom2.PointCollection.pack([[0, 1], [2, 3], [4, 5]], 8);
|
||||
expect(pc.buf.getArray()).to.eql([0, 1, 2, 3, 4, 5, NaN, NaN]);
|
||||
expect(pc.dim).to.be(2);
|
||||
});
|
||||
|
||||
it('can pack a single 3-dimensional point', function() {
|
||||
var pc = ol.geom2.PointCollection.pack([[0, 1, 2]]);
|
||||
expect(pc.buf.getArray()).to.eql([0, 1, 2]);
|
||||
expect(pc.dim).to.be(3);
|
||||
});
|
||||
|
||||
it('can pack a multiple 3-dimensional points', function() {
|
||||
var pc = ol.geom2.PointCollection.pack([[0, 1, 2], [4, 5, 6]]);
|
||||
expect(pc.buf.getArray()).to.eql([0, 1, 2, 4, 5, 6]);
|
||||
expect(pc.dim).to.be(3);
|
||||
});
|
||||
|
||||
it('raises an error when not all points have the same dimension',
|
||||
function() {
|
||||
expect(function() {
|
||||
var pc = ol.geom2.PointCollection.pack([[0, 1], [2]]);
|
||||
pc = pc; // suppress gjslint warning about unused variable
|
||||
}).to.throwException();
|
||||
});
|
||||
|
||||
it('raises an error when the capacity is too small', function() {
|
||||
expect(function() {
|
||||
var pc = ol.geom2.PointCollection.pack([[0, 1], [2, 3], [4, 5]], 2);
|
||||
pc = pc; // suppress gjslint warning about unused variable
|
||||
}).to.throwException();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('with an empty buffer, with capacity for two points', function() {
|
||||
|
||||
var pc;
|
||||
beforeEach(function() {
|
||||
var buf = new ol.structs.Buffer(new Array(4), 0);
|
||||
pc = new ol.geom2.PointCollection(buf);
|
||||
});
|
||||
|
||||
describe('add', function() {
|
||||
|
||||
it('can add a first point', function() {
|
||||
expect(pc.add([0, 1])).to.be(0);
|
||||
expect(pc.buf.getArray()).to.eql([0, 1, NaN, NaN]);
|
||||
});
|
||||
|
||||
it('can add a second point', function() {
|
||||
expect(pc.add([0, 1])).to.be(0);
|
||||
expect(pc.buf.getArray()).to.eql([0, 1, NaN, NaN]);
|
||||
expect(pc.add([2, 3])).to.be(2);
|
||||
expect(pc.buf.getArray()).to.eql([0, 1, 2, 3]);
|
||||
});
|
||||
|
||||
it('raises an error when the third point is added', function() {
|
||||
expect(pc.add([0, 1])).to.be(0);
|
||||
expect(pc.buf.getArray()).to.eql([0, 1, NaN, NaN]);
|
||||
expect(pc.add([2, 3])).to.be(2);
|
||||
expect(pc.buf.getArray()).to.eql([0, 1, 2, 3]);
|
||||
expect(function() {
|
||||
pc.add([4, 5]);
|
||||
}).to.throwException();
|
||||
});
|
||||
|
||||
it('raises an error if a point of the wrong dimension is added',
|
||||
function() {
|
||||
expect(function() {
|
||||
pc.add([0, 1, 2]);
|
||||
}).to.throwException();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('getCount', function() {
|
||||
|
||||
it('returns 0', function() {
|
||||
expect(pc.getCount()).to.be(0);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('getExtent', function() {
|
||||
|
||||
it('returns an empty extent', function() {
|
||||
expect(ol.extent.isEmpty(pc.getExtent())).to.be(true);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('unpack', function() {
|
||||
|
||||
it('returns an empty array', function() {
|
||||
expect(pc.unpack()).to.be.empty();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('with a partially populated instance', function() {
|
||||
|
||||
var dirtySet, pc;
|
||||
beforeEach(function() {
|
||||
dirtySet = new ol.structs.IntegerSet();
|
||||
pc = ol.geom2.PointCollection.pack([[0, 1], [2, 3]], 8);
|
||||
pc.buf.addDirtySet(dirtySet);
|
||||
});
|
||||
|
||||
describe('add', function() {
|
||||
|
||||
it('can add more points', function() {
|
||||
expect(pc.add([4, 5])).to.be(4);
|
||||
expect(pc.buf.getArray()).to.eql([0, 1, 2, 3, 4, 5, NaN, NaN]);
|
||||
expect(pc.add([6, 7])).to.be(6);
|
||||
expect(pc.buf.getArray()).to.eql([0, 1, 2, 3, 4, 5, 6, 7]);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('get', function() {
|
||||
|
||||
it('returns the expected value for the first point', function() {
|
||||
expect(pc.get(0)).to.eql([0, 1]);
|
||||
});
|
||||
|
||||
it('returns the expected value for the second point', function() {
|
||||
expect(pc.get(2)).to.eql([2, 3]);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('getCount', function() {
|
||||
|
||||
it('returns the expected value', function() {
|
||||
expect(pc.getCount()).to.be(2);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('getExtent', function() {
|
||||
|
||||
it('returns the expected value', function() {
|
||||
var extent = pc.getExtent();
|
||||
expect(extent).to.eql([0, 2, 1, 3]);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('remove', function() {
|
||||
|
||||
it('can remove the first point', function() {
|
||||
pc.remove(0);
|
||||
expect(pc.buf.getArray()).to.eql([NaN, NaN, 2, 3, NaN, NaN, NaN, NaN]);
|
||||
});
|
||||
|
||||
it('can remove the second point', function() {
|
||||
pc.remove(2);
|
||||
expect(pc.buf.getArray()).to.eql([0, 1, NaN, NaN, NaN, NaN, NaN, NaN]);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('set', function() {
|
||||
|
||||
it('marks the updated elements as dirty', function() {
|
||||
pc.set(2, [4, 5]);
|
||||
expect(pc.buf.getArray()).to.eql([0, 1, 4, 5, NaN, NaN, NaN, NaN]);
|
||||
expect(dirtySet.getArray()).to.eql([2, 4]);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('unpack', function() {
|
||||
|
||||
it('returns the expect value', function() {
|
||||
expect(pc.unpack()).to.eql([[0, 1], [2, 3]]);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('after removing the first point', function() {
|
||||
|
||||
beforeEach(function() {
|
||||
pc.remove(0);
|
||||
});
|
||||
|
||||
describe('getCount', function() {
|
||||
|
||||
it('returns the expected value', function() {
|
||||
expect(pc.getCount()).to.be(1);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('unpack', function() {
|
||||
|
||||
it('returns the expected value', function() {
|
||||
expect(pc.unpack()).to.eql([[2, 3]]);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('usage example', function() {
|
||||
|
||||
it('works as expected', function() {
|
||||
var pc = ol.geom2.PointCollection.pack([[0, 1], [2, 3], [4, 5]], 8);
|
||||
var dirtySet = new ol.structs.IntegerSet();
|
||||
pc.buf.addDirtySet(dirtySet);
|
||||
expect(pc.buf.getArray()).to.eql([0, 1, 2, 3, 4, 5, NaN, NaN]);
|
||||
expect(pc.unpack()).to.have.length(3);
|
||||
expect(pc.getCount()).to.be(3);
|
||||
expect(pc.get(2)).to.eql([2, 3]);
|
||||
pc.remove(2);
|
||||
expect(pc.buf.getArray()).to.eql([0, 1, NaN, NaN, 4, 5, NaN, NaN]);
|
||||
expect(pc.unpack()).to.have.length(2);
|
||||
expect(pc.getCount()).to.be(2);
|
||||
expect(pc.add([6, 7])).to.be(2);
|
||||
expect(pc.buf.getArray()).to.eql([0, 1, 6, 7, 4, 5, NaN, NaN]);
|
||||
expect(pc.unpack()).to.have.length(3);
|
||||
expect(pc.getCount()).to.be(3);
|
||||
expect(dirtySet.getArray()).to.eql([2, 4]);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
goog.require('ol.geom2.PointCollection');
|
||||
goog.require('ol.extent');
|
||||
goog.require('ol.structs.Buffer');
|
||||
goog.require('ol.structs.IntegerSet');
|
||||
Reference in New Issue
Block a user