From bcf7707b015f37c60e97f893468ef4c00bfcb8e3 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Tue, 23 Apr 2013 18:29:23 +0200 Subject: [PATCH 01/25] Factor out ol.structs.Buffer#markDirty --- src/ol/structs/buffer.js | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/ol/structs/buffer.js b/src/ol/structs/buffer.js index add2494b9f..0450cf70c1 100644 --- a/src/ol/structs/buffer.js +++ b/src/ol/structs/buffer.js @@ -86,10 +86,7 @@ ol.structs.Buffer.prototype.add = function(values) { for (i = 0; i < size; ++i) { this.arr_[offset + i] = values[i]; } - var ii; - for (i = 0, ii = this.dirtySets_.length; i < ii; ++i) { - this.dirtySets_[i].addRange(offset, offset + size); - } + this.markDirty(size, offset); return offset; }; @@ -147,6 +144,18 @@ ol.structs.Buffer.prototype.getUsage = function() { }; +/** + * @param {number} size Size. + * @param {number} offset Offset. + */ +ol.structs.Buffer.prototype.markDirty = function(size, offset) { + var i, ii; + for (i = 0, ii = this.dirtySets_.length; i < ii; ++i) { + this.dirtySets_[i].addRange(offset, offset + size); + } +}; + + /** * @param {number} size Size. * @param {number} offset Offset. @@ -187,8 +196,5 @@ ol.structs.Buffer.prototype.set = function(values, offset) { for (i = 0; i < n; ++i) { arr[offset + i] = values[i]; } - var ii; - for (i = 0, ii = this.dirtySets_.length; i < ii; ++i) { - this.dirtySets_[i].addRange(offset, offset + n); - } + this.markDirty(n, offset); }; From 7fd2e1ffcad5cac4d41acf3572530d7d4eff16b3 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Tue, 23 Apr 2013 18:29:45 +0200 Subject: [PATCH 02/25] Factor out ol.structs.Buffer#allocate --- src/ol/structs/buffer.js | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/ol/structs/buffer.js b/src/ol/structs/buffer.js index 0450cf70c1..bc049f7a08 100644 --- a/src/ol/structs/buffer.js +++ b/src/ol/structs/buffer.js @@ -72,16 +72,26 @@ ol.structs.Buffer = function(opt_arr, opt_used, opt_usage) { }; +/** + * @param {number} size Size. + * @return {number} Offset. + */ +ol.structs.Buffer.prototype.allocate = function(size) { + goog.asserts.assert(size > 0); + var offset = this.freeSet_.findRange(size); + goog.asserts.assert(offset != -1); // FIXME + this.freeSet_.removeRange(offset, offset + size); + return offset; +}; + + /** * @param {Array.} values Values. * @return {number} Offset. */ ol.structs.Buffer.prototype.add = function(values) { var size = values.length; - goog.asserts.assert(size > 0); - var offset = this.freeSet_.findRange(size); - goog.asserts.assert(offset != -1); // FIXME - this.freeSet_.removeRange(offset, offset + size); + var offset = this.allocate(size); var i; for (i = 0; i < size; ++i) { this.arr_[offset + i] = values[i]; From d51cdc0e4806281101a1175643358d911fd3c2a6 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Tue, 23 Apr 2013 18:30:51 +0200 Subject: [PATCH 03/25] Add ol.geom2 utility functions --- src/ol/geom2/geom2.js | 71 ++++++++++++++++++++++++++++++++ test/spec/ol/geom2/geom2.test.js | 71 ++++++++++++++++++++++++++++++++ 2 files changed, 142 insertions(+) create mode 100644 src/ol/geom2/geom2.js create mode 100644 test/spec/ol/geom2/geom2.test.js diff --git a/src/ol/geom2/geom2.js b/src/ol/geom2/geom2.js new file mode 100644 index 0000000000..a2ce5de71d --- /dev/null +++ b/src/ol/geom2/geom2.js @@ -0,0 +1,71 @@ +goog.provide('ol.geom2'); + +goog.require('goog.asserts'); +goog.require('ol.Extent'); + + +/** + * @param {ol.structs.Buffer} buf Buffer. + * @param {number} dim Dimension. + * @return {ol.Extent} Extent. + */ +ol.geom2.getExtent = function(buf, dim) { + var extent = new Array(2 * dim); + var extentIndex = 0; + var i; + for (i = 0; i < dim; ++i) { + extent[extentIndex++] = Infinity; + extent[extentIndex++] = -Infinity; + } + var bufArr = buf.getArray(); + buf.forEachRange(function(start, stop) { + var extentIndex, i, j; + for (i = start; i < stop; i += dim) { + extentIndex = 0; + for (j = 0; j < dim; ++j) { + extent[extentIndex++] = Math.min(extent[2 * j], bufArr[i + j]); + extent[extentIndex++] = Math.max(extent[2 * j + 1], bufArr[i + j]); + } + } + }); + return extent; +}; + + +/** + * @param {Array.} arr Array. + * @param {number} offset Offset. + * @param {Array.>} unpackedPoints Unpacked points. + * @param {number} dim Dimension. + * @return {number} Offset. + */ +ol.geom2.packPoints = function(arr, offset, unpackedPoints, dim) { + var n = unpackedPoints.length; + var i, j, point; + for (i = 0; i < n; ++i) { + point = unpackedPoints[i]; + goog.asserts.assert(point.length == dim); + for (j = 0; j < dim; ++j) { + arr[offset++] = point[j]; + } + } + return offset; +}; + + +/** + * @param {Array.} arr Array. + * @param {number} offset Offset. + * @param {number} end End. + * @param {number} dim Dimension. + * @return {Array.>} Unpacked points. + */ +ol.geom2.unpackPoints = function(arr, offset, end, dim) { + var unpackedPoints = new Array((end - offset) / dim); + var i = 0; + var j; + for (j = offset; j < end; j += dim) { + unpackedPoints[i++] = arr.slice(j, j + dim); + } + return unpackedPoints; +}; diff --git a/test/spec/ol/geom2/geom2.test.js b/test/spec/ol/geom2/geom2.test.js new file mode 100644 index 0000000000..d894bc65af --- /dev/null +++ b/test/spec/ol/geom2/geom2.test.js @@ -0,0 +1,71 @@ +goog.provide('ol.test.geom2'); + + +describe('ol.geom2', function() { + + var buf, dim; + beforeEach(function() { + buf = new ol.structs.Buffer([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], 12); + dim = 2; + }); + + describe('ol.geom2.getExtent', function() { + + it('returns the expected extent', function() { + var extent = ol.geom2.getExtent(buf, dim); + expect(extent).to.eql([0, 10, 1, 11]); + }); + + it('returns the expect extent in three dimensions', function() { + var extent = ol.geom2.getExtent(buf, 3); + expect(extent).to.eql([0, 9, 1, 10, 2, 11]); + }); + + it('returns the expect extent in four dimensions', function() { + var extent = ol.geom2.getExtent(buf, 4); + expect(extent).to.eql([0, 8, 1, 9, 2, 10, 3, 11]); + }); + + it('returns the expect extent in six dimensions', function() { + var extent = ol.geom2.getExtent(buf, 6); + expect(extent).to.eql([0, 6, 1, 7, 2, 8, 3, 9, 4, 10, 5, 11]); + }); + + }); + + describe('ol.geom2.packPoints', function() { + + it('packs points as expected', function() { + var arr = []; + var offset = ol.geom2.packPoints(arr, 0, [[0, 1], [2, 3], [4, 5]], 2); + expect(offset).to.be(6); + expect(arr).to.eql([0, 1, 2, 3, 4, 5]); + }); + + it('raises an exception if dimensions do not match', function() { + expect(function() { + ol.geom2.packPoints([], 0, [[0, 1, 2]], 2); + }).to.throwException(); + }); + + }); + + describe('ol.geom2.unpackPoints', function() { + + it('unpacks points in two dimensions', function() { + var unpackedPoints = ol.geom2.unpackPoints([0, 1, 2, 3, 4, 5], 0, 6, 2); + expect(unpackedPoints).to.eql([[0, 1], [2, 3], [4, 5]]); + }); + + it('unpacks points in three dimensions', function() { + var unpackedPoints = ol.geom2.unpackPoints([0, 1, 2, 3, 4, 5], 0, 6, 3); + expect(unpackedPoints).to.eql([[0, 1, 2], [3, 4, 5]]); + }); + + }); + +}); + + +goog.require('ol.geom2'); +goog.require('ol.structs.Buffer'); From 93ba55d3575924eb94b89a1326666b071376a178 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Tue, 23 Apr 2013 18:31:20 +0200 Subject: [PATCH 04/25] Add ol.geom2.PointCollection --- src/ol/geom2/pointcollection.exports | 4 + src/ol/geom2/pointcollection.js | 142 ++++++++++ test/spec/ol/geom2/pointcollection.test.js | 293 +++++++++++++++++++++ 3 files changed, 439 insertions(+) create mode 100644 src/ol/geom2/pointcollection.exports create mode 100644 src/ol/geom2/pointcollection.js create mode 100644 test/spec/ol/geom2/pointcollection.test.js diff --git a/src/ol/geom2/pointcollection.exports b/src/ol/geom2/pointcollection.exports new file mode 100644 index 0000000000..7a7a485279 --- /dev/null +++ b/src/ol/geom2/pointcollection.exports @@ -0,0 +1,4 @@ +@exportSymbol ol.geom2.PointCollection +@exportSymbol ol.geom2.PointCollection.createEmpty +@exportSymbol ol.geom2.PointCollection.pack +@exportProperty ol.geom2.PointCollection.prototype.add diff --git a/src/ol/geom2/pointcollection.js b/src/ol/geom2/pointcollection.js new file mode 100644 index 0000000000..877071878d --- /dev/null +++ b/src/ol/geom2/pointcollection.js @@ -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.} + */ +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.} 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.} 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; +}; diff --git a/test/spec/ol/geom2/pointcollection.test.js b/test/spec/ol/geom2/pointcollection.test.js new file mode 100644 index 0000000000..52d7d33bd5 --- /dev/null +++ b/test/spec/ol/geom2/pointcollection.test.js @@ -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'); From ac48fae0af0752336003126b277598d072c969e1 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Tue, 23 Apr 2013 18:32:09 +0200 Subject: [PATCH 05/25] Add ol.source.VectorSource2 --- src/objectliterals.jsdoc | 9 +++++++ src/ol/source/vectorsource2.exports | 1 + src/ol/source/vectorsource2.js | 37 +++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+) create mode 100644 src/ol/source/vectorsource2.exports create mode 100644 src/ol/source/vectorsource2.js diff --git a/src/objectliterals.jsdoc b/src/objectliterals.jsdoc index 02269b07e0..e938eec2a9 100644 --- a/src/objectliterals.jsdoc +++ b/src/objectliterals.jsdoc @@ -461,6 +461,15 @@ * of `url` when the WMS supports multiple urls for GetMap requests. */ +/** + * @typedef {Object} ol.source.VectorSource2Options + * @property {Array.|undefined} attributions Attributions. + * @property {ol.Extent|undefined} extent Extent. + * @property {Array.|undefined} pointCollections + * Point collections. + * @property {ol.ProjectionLike} projection Projection. + */ + /** * @typedef {Object} ol.source.WMTSOptions * @property {Array.|undefined} attributions Attributions. diff --git a/src/ol/source/vectorsource2.exports b/src/ol/source/vectorsource2.exports new file mode 100644 index 0000000000..1d3cf6c8ed --- /dev/null +++ b/src/ol/source/vectorsource2.exports @@ -0,0 +1 @@ +@exportSymbol ol.source.VectorSource2 diff --git a/src/ol/source/vectorsource2.js b/src/ol/source/vectorsource2.js new file mode 100644 index 0000000000..612c11582b --- /dev/null +++ b/src/ol/source/vectorsource2.js @@ -0,0 +1,37 @@ +goog.provide('ol.source.VectorSource2'); + +goog.require('ol.geom2.PointCollection'); +goog.require('ol.source.Source'); + + + +/** + * @constructor + * @extends {ol.source.Source} + * @param {ol.source.VectorSource2Options} options Options. + */ +ol.source.VectorSource2 = function(options) { + + goog.base(this, { + attributions: options.attributions, + extent: options.extent, + projection: options.projection + }); + + /** + * @private + * @type {Array.} + */ + this.pointCollections_ = goog.isDef(options.pointCollections) ? + options.pointCollections : []; + +}; +goog.inherits(ol.source.VectorSource2, ol.source.Source); + + +/** + * @return {Array.} Point collections. + */ +ol.source.VectorSource2.prototype.getPointCollections = function() { + return this.pointCollections_; +}; From bed8c4485928d92baa22e4ba7a1dff434a7f25fd Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Tue, 23 Apr 2013 18:32:48 +0200 Subject: [PATCH 06/25] Add ol.layer.VectorLayer2 --- src/ol/layer/vectorlayer2.exports | 1 + src/ol/layer/vectorlayer2.js | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 src/ol/layer/vectorlayer2.exports create mode 100644 src/ol/layer/vectorlayer2.js diff --git a/src/ol/layer/vectorlayer2.exports b/src/ol/layer/vectorlayer2.exports new file mode 100644 index 0000000000..84c34826f8 --- /dev/null +++ b/src/ol/layer/vectorlayer2.exports @@ -0,0 +1 @@ +@exportSymbol ol.layer.VectorLayer2 diff --git a/src/ol/layer/vectorlayer2.js b/src/ol/layer/vectorlayer2.js new file mode 100644 index 0000000000..8ca94375b6 --- /dev/null +++ b/src/ol/layer/vectorlayer2.js @@ -0,0 +1,24 @@ +goog.provide('ol.layer.VectorLayer2'); + +goog.require('ol.layer.Layer'); +goog.require('ol.source.VectorSource2'); + + + +/** + * @constructor + * @extends {ol.layer.Layer} + * @param {ol.layer.LayerOptions} options Options. + */ +ol.layer.VectorLayer2 = function(options) { + goog.base(this, options); +}; +goog.inherits(ol.layer.VectorLayer2, ol.layer.Layer); + + +/** + * @return {ol.source.VectorSource2} Source. + */ +ol.layer.VectorLayer2.prototype.getVectorSource = function() { + return /** @type {ol.source.VectorSource2} */ (this.getSource()); +}; From e4b5ec8f0bd8c25882db2393fdd53d4b0bd22c10 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Tue, 23 Apr 2013 18:52:23 +0200 Subject: [PATCH 07/25] Add ol.renderer.webgl.VectorLayer2 --- .../webglvectorlayer2pointcollection.glsl | 21 +++ .../webglvectorlayer2pointcollectionshader.js | 82 +++++++++ .../webgl/webglvectorlayer2renderer.js | 156 ++++++++++++++++++ 3 files changed, 259 insertions(+) create mode 100644 src/ol/renderer/webgl/webglvectorlayer2pointcollection.glsl create mode 100644 src/ol/renderer/webgl/webglvectorlayer2pointcollectionshader.js create mode 100644 src/ol/renderer/webgl/webglvectorlayer2renderer.js diff --git a/src/ol/renderer/webgl/webglvectorlayer2pointcollection.glsl b/src/ol/renderer/webgl/webglvectorlayer2pointcollection.glsl new file mode 100644 index 0000000000..07f09ef42e --- /dev/null +++ b/src/ol/renderer/webgl/webglvectorlayer2pointcollection.glsl @@ -0,0 +1,21 @@ +//! NAMESPACE=ol.renderer.webgl.vectorlayer2.shader.PointCollection +//! CLASS=ol.renderer.webgl.vectorlayer2.shader.PointCollection + + +//! VERTEX +attribute vec2 a_position; +uniform float u_pointSize; +uniform mat4 u_modelViewMatrix; + +void main(void) { + gl_Position = u_modelViewMatrix * vec4(a_position, 0., 1.); + gl_PointSize = u_pointSize; +} + + +//! FRAGMENT +uniform vec4 u_color; + +void main(void) { + gl_FragColor = u_color; +} diff --git a/src/ol/renderer/webgl/webglvectorlayer2pointcollectionshader.js b/src/ol/renderer/webgl/webglvectorlayer2pointcollectionshader.js new file mode 100644 index 0000000000..825697a28f --- /dev/null +++ b/src/ol/renderer/webgl/webglvectorlayer2pointcollectionshader.js @@ -0,0 +1,82 @@ +// This file is automatically generated, do not edit +goog.provide('ol.renderer.webgl.vectorlayer2.shader.PointCollection'); +goog.require('ol.webgl.shader'); +/** + * @constructor + * @extends {ol.webgl.shader.Fragment} + */ +ol.renderer.webgl.vectorlayer2.shader.PointCollectionFragment = function() { + goog.base(this, ol.renderer.webgl.vectorlayer2.shader.PointCollectionFragment.SOURCE); +}; +goog.inherits(ol.renderer.webgl.vectorlayer2.shader.PointCollectionFragment, ol.webgl.shader.Fragment); +goog.addSingletonGetter(ol.renderer.webgl.vectorlayer2.shader.PointCollectionFragment); +/** + * @const + * @type {string} + */ +ol.renderer.webgl.vectorlayer2.shader.PointCollectionFragment.DEBUG_SOURCE = 'precision mediump float;\n//! NAMESPACE=ol.renderer.webgl.vectorlayer2.shader.PointCollection\n//! CLASS=ol.renderer.webgl.vectorlayer2.shader.PointCollection\n\n\n//! FRAGMENT\nuniform vec4 u_color;\n\nvoid main(void) {\n gl_FragColor = u_color;\n}\n\n'; +/** + * @const + * @type {string} + */ +ol.renderer.webgl.vectorlayer2.shader.PointCollectionFragment.OPTIMIZED_SOURCE = 'precision mediump float;uniform vec4 c;void main(){gl_FragColor=c;}'; +/** + * @const + * @type {string} + */ +ol.renderer.webgl.vectorlayer2.shader.PointCollectionFragment.SOURCE = goog.DEBUG ? + ol.renderer.webgl.vectorlayer2.shader.PointCollectionFragment.DEBUG_SOURCE : + ol.renderer.webgl.vectorlayer2.shader.PointCollectionFragment.OPTIMIZED_SOURCE; +/** + * @constructor + * @extends {ol.webgl.shader.Vertex} + */ +ol.renderer.webgl.vectorlayer2.shader.PointCollectionVertex = function() { + goog.base(this, ol.renderer.webgl.vectorlayer2.shader.PointCollectionVertex.SOURCE); +}; +goog.inherits(ol.renderer.webgl.vectorlayer2.shader.PointCollectionVertex, ol.webgl.shader.Vertex); +goog.addSingletonGetter(ol.renderer.webgl.vectorlayer2.shader.PointCollectionVertex); +/** + * @const + * @type {string} + */ +ol.renderer.webgl.vectorlayer2.shader.PointCollectionVertex.DEBUG_SOURCE = '//! NAMESPACE=ol.renderer.webgl.vectorlayer2.shader.PointCollection\n//! CLASS=ol.renderer.webgl.vectorlayer2.shader.PointCollection\n\n\n//! VERTEX\nattribute vec2 a_position;\nuniform float u_pointSize;\nuniform mat4 u_modelViewMatrix;\n\nvoid main(void) {\n gl_Position = u_modelViewMatrix * vec4(a_position, 0., 1.);\n gl_PointSize = u_pointSize;\n}\n\n\n'; +/** + * @const + * @type {string} + */ +ol.renderer.webgl.vectorlayer2.shader.PointCollectionVertex.OPTIMIZED_SOURCE = 'attribute vec2 c;uniform float a;uniform mat4 b;void main(){gl_Position=b*vec4(c,0,1);gl_PointSize=a;}'; +/** + * @const + * @type {string} + */ +ol.renderer.webgl.vectorlayer2.shader.PointCollectionVertex.SOURCE = goog.DEBUG ? + ol.renderer.webgl.vectorlayer2.shader.PointCollectionVertex.DEBUG_SOURCE : + ol.renderer.webgl.vectorlayer2.shader.PointCollectionVertex.OPTIMIZED_SOURCE; +/** + * @constructor + * @param {WebGLRenderingContext} gl GL. + * @param {WebGLProgram} program Program. + */ +ol.renderer.webgl.vectorlayer2.shader.PointCollection.Locations = function(gl, program) { + /** + * @type {WebGLUniformLocation} + */ + this.u_pointSize = gl.getUniformLocation( + program, goog.DEBUG ? 'u_pointSize' : 'a'); + /** + * @type {WebGLUniformLocation} + */ + this.u_modelViewMatrix = gl.getUniformLocation( + program, goog.DEBUG ? 'u_modelViewMatrix' : 'b'); + /** + * @type {WebGLUniformLocation} + */ + this.u_color = gl.getUniformLocation( + program, goog.DEBUG ? 'u_color' : 'c'); + /** + * @type {number} + */ + this.a_position = gl.getAttribLocation( + program, goog.DEBUG ? 'a_position' : 'c'); +}; diff --git a/src/ol/renderer/webgl/webglvectorlayer2renderer.js b/src/ol/renderer/webgl/webglvectorlayer2renderer.js new file mode 100644 index 0000000000..d16d4fa8ec --- /dev/null +++ b/src/ol/renderer/webgl/webglvectorlayer2renderer.js @@ -0,0 +1,156 @@ +goog.provide('ol.renderer.webgl.VectorLayer2'); + +goog.require('goog.vec.Mat4'); +goog.require('goog.webgl'); +goog.require('ol.math'); +goog.require('ol.renderer.webgl.Layer'); +goog.require('ol.renderer.webgl.vectorlayer2.shader.PointCollection'); + + + +/** + * @constructor + * @extends {ol.renderer.webgl.Layer} + * @param {ol.renderer.Map} mapRenderer Map renderer. + * @param {ol.layer.VectorLayer2} vectorLayer2 Vector layer. + */ +ol.renderer.webgl.VectorLayer2 = function(mapRenderer, vectorLayer2) { + + goog.base(this, mapRenderer, vectorLayer2); + + goog.vec.Mat4.makeIdentity(this.projectionMatrix); + + /** + * @private + * @type {!goog.vec.Mat4.Number} + */ + this.modelViewMatrix_ = goog.vec.Mat4.createNumberIdentity(); + + /** + * @private + * @type {ol.renderer.webgl.vectorlayer2.shader.PointCollection.Locations} + */ + this.pointCollectionLocations_ = null; + +}; +goog.inherits(ol.renderer.webgl.VectorLayer2, ol.renderer.webgl.Layer); + + +/** + * @return {ol.layer.VectorLayer2} Vector layer. + */ +ol.renderer.webgl.VectorLayer2.prototype.getVectorLayer = function() { + return /** @type {ol.layer.VectorLayer2} */ (this.getLayer()); +}; + + +/** + * @inheritDoc + */ +ol.renderer.webgl.VectorLayer2.prototype.handleWebGLContextLost = function() { + goog.base(this, 'handleWebGLContextLost'); + this.pointCollectionLocations_ = null; +}; + + +/** + * @inheritDoc + */ +ol.renderer.webgl.VectorLayer2.prototype.renderFrame = + function(frameState, layerState) { + + var mapRenderer = this.getWebGLMapRenderer(); + var gl = mapRenderer.getGL(); + + var view2DState = frameState.view2DState; + + var vectorLayer = this.getVectorLayer(); + var vectorSource = vectorLayer.getVectorSource(); + + var size = frameState.size; + var framebufferDimension = ol.math.roundUpToPowerOfTwo( + Math.max(size[0], size[1])); + + this.bindFramebuffer(frameState, framebufferDimension); + gl.viewport(0, 0, framebufferDimension, framebufferDimension); + + gl.clearColor(0, 0, 0, 0); + gl.clear(goog.webgl.COLOR_BUFFER_BIT); + gl.enable(goog.webgl.BLEND); + + goog.vec.Mat4.makeIdentity(this.modelViewMatrix_); + if (view2DState.rotation !== 0) { + goog.vec.Mat4.rotateZ(this.modelViewMatrix_, -view2DState.rotation); + } + goog.vec.Mat4.scale(this.modelViewMatrix_, + 2 / (framebufferDimension * view2DState.resolution), + 2 / (framebufferDimension * view2DState.resolution), + 1); + goog.vec.Mat4.translate(this.modelViewMatrix_, + -view2DState.center[0], + -view2DState.center[1], + 0); + + var pointCollections = vectorSource.getPointCollections(); + if (pointCollections.length > 0) { + this.renderPointCollections(pointCollections); + } + + goog.vec.Mat4.makeIdentity(this.texCoordMatrix); + goog.vec.Mat4.translate(this.texCoordMatrix, + 0.5, + 0.5, + 0); + goog.vec.Mat4.scale(this.texCoordMatrix, + size[0] / framebufferDimension, + size[1] / framebufferDimension, + 1); + goog.vec.Mat4.translate(this.texCoordMatrix, + -0.5, + -0.5, + 0); + +}; + + +/** + * @param {Array.} pointCollections Point collections. + */ +ol.renderer.webgl.VectorLayer2.prototype.renderPointCollections = + function(pointCollections) { + + var mapRenderer = this.getWebGLMapRenderer(); + var gl = mapRenderer.getGL(); + + var fragmentShader = ol.renderer.webgl.vectorlayer2.shader. + PointCollectionFragment.getInstance(); + var vertexShader = ol.renderer.webgl.vectorlayer2.shader. + PointCollectionVertex.getInstance(); + var program = mapRenderer.getProgram(fragmentShader, vertexShader); + gl.useProgram(program); + if (goog.isNull(this.pointCollectionLocations_)) { + this.pointCollectionLocations_ = + new ol.renderer.webgl.vectorlayer2.shader.PointCollection.Locations( + gl, program); + } + + gl.uniformMatrix4fv(this.pointCollectionLocations_.u_modelViewMatrix, false, + this.modelViewMatrix_); + + var buf, dim, i, pointCollection; + for (i = 0; i < pointCollections.length; ++i) { + pointCollection = pointCollections[i]; + buf = pointCollection.buf; + dim = pointCollection.dim; + mapRenderer.bindBuffer(goog.webgl.ARRAY_BUFFER, buf); + gl.enableVertexAttribArray(this.pointCollectionLocations_.a_position); + gl.vertexAttribPointer(this.pointCollectionLocations_.a_position, 2, + goog.webgl.FLOAT, false, 4 * dim, 0); + gl.uniform4fv(this.pointCollectionLocations_.u_color, [1, 0, 0, 0.75]); + gl.uniform1f(this.pointCollectionLocations_.u_pointSize, 3); + buf.forEachRange(function(start, stop) { + gl.drawArrays(goog.webgl.POINTS, start / dim, (stop - start) / dim); + }); + } + +}; From 4cc54415793dc2e1f1fe18cf4d33ca41314cf2d0 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Tue, 23 Apr 2013 18:53:20 +0200 Subject: [PATCH 08/25] Activate ol.renderer.webgl.VectorLayer2 --- src/ol/renderer/webgl/webglmaprenderer.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ol/renderer/webgl/webglmaprenderer.js b/src/ol/renderer/webgl/webglmaprenderer.js index 68126fe41c..d250365299 100644 --- a/src/ol/renderer/webgl/webglmaprenderer.js +++ b/src/ol/renderer/webgl/webglmaprenderer.js @@ -18,9 +18,11 @@ goog.require('ol.Tile'); goog.require('ol.css'); goog.require('ol.layer.ImageLayer'); goog.require('ol.layer.TileLayer'); +goog.require('ol.layer.VectorLayer2'); goog.require('ol.renderer.Map'); goog.require('ol.renderer.webgl.ImageLayer'); goog.require('ol.renderer.webgl.TileLayer'); +goog.require('ol.renderer.webgl.VectorLayer2'); goog.require('ol.renderer.webgl.map.shader.Color'); goog.require('ol.renderer.webgl.map.shader.Default'); goog.require('ol.size'); @@ -300,6 +302,8 @@ ol.renderer.webgl.Map.prototype.createLayerRenderer = function(layer) { return new ol.renderer.webgl.TileLayer(this, layer); } else if (layer instanceof ol.layer.ImageLayer) { return new ol.renderer.webgl.ImageLayer(this, layer); + } else if (layer instanceof ol.layer.VectorLayer2) { + return new ol.renderer.webgl.VectorLayer2(this, layer); } else { goog.asserts.fail(); return null; From 1690cb9cae243a5c093a95843a8cded0f4c4d8e4 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Wed, 1 May 2013 16:17:18 +0200 Subject: [PATCH 09/25] Add ol.geom2.LineStringCollection --- src/ol/geom2/linestringcollection.exports | 2 + src/ol/geom2/linestringcollection.js | 183 +++++++++++++ test/spec/ol/geom2/linecollection.test.js | 303 ++++++++++++++++++++++ 3 files changed, 488 insertions(+) create mode 100644 src/ol/geom2/linestringcollection.exports create mode 100644 src/ol/geom2/linestringcollection.js create mode 100644 test/spec/ol/geom2/linecollection.test.js diff --git a/src/ol/geom2/linestringcollection.exports b/src/ol/geom2/linestringcollection.exports new file mode 100644 index 0000000000..6f7b393e71 --- /dev/null +++ b/src/ol/geom2/linestringcollection.exports @@ -0,0 +1,2 @@ +@exportSymbol ol.geom2.LineStringCollection +@exportSymbol ol.geom2.LineStringCollection.pack diff --git a/src/ol/geom2/linestringcollection.js b/src/ol/geom2/linestringcollection.js new file mode 100644 index 0000000000..9981ec7100 --- /dev/null +++ b/src/ol/geom2/linestringcollection.js @@ -0,0 +1,183 @@ +goog.provide('ol.geom2.LineString'); +goog.provide('ol.geom2.LineStringCollection'); + +goog.require('goog.asserts'); +goog.require('goog.object'); +goog.require('ol.geom2'); +goog.require('ol.structs.Buffer'); + + +/** + * @typedef {Array.>} + */ +ol.geom2.LineString; + + + +/** + * @constructor + * @param {ol.structs.Buffer} buf Buffer. + * @param {Object.>=} opt_ranges Ranges. + * @param {number=} opt_dim Dimension. + */ +ol.geom2.LineStringCollection = function(buf, opt_ranges, opt_dim) { + + /** + * @type {ol.structs.Buffer} + */ + this.buf = buf; + + /** + * @type {Object.>} + */ + this.ranges = goog.isDef(opt_ranges) ? opt_ranges : {}; + + /** + * @type {number} + */ + this.dim = goog.isDef(opt_dim) ? opt_dim : 2; + +}; + + +/** + * @param {number} capacity Capacity. + * @param {number=} opt_dim Dimension. + * @return {ol.geom2.LineStringCollection} Line string collection. + */ +ol.geom2.LineStringCollection.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.LineStringCollection(buf, undefined, dim); +}; + + +/** + * @param {Array.} unpackedLineStrings Unpacked line + * strings. + * @param {number=} opt_capacity Capacity. + * @param {number=} opt_dim Dimension. + * @return {ol.geom2.LineStringCollection} Line string collection. + */ +ol.geom2.LineStringCollection.pack = + function(unpackedLineStrings, opt_capacity, opt_dim) { + var i; + var n = unpackedLineStrings.length; + var dim = goog.isDef(opt_dim) ? opt_dim : + n > 0 ? unpackedLineStrings[0][0].length : 2; + var capacity; + if (goog.isDef(opt_capacity)) { + capacity = opt_capacity; + } else { + capacity = 0; + for (i = 0; i < n; ++i) { + capacity += unpackedLineStrings[i].length; + } + } + capacity *= dim; + var arr = new Array(capacity); + /** @type {Object.>} */ + var ranges = {}; + var offset = 0; + var start; + for (i = 0; i < n; ++i) { + goog.asserts.assert(unpackedLineStrings[i].length > 1); + start = offset; + offset = ol.geom2.packPoints(arr, offset, unpackedLineStrings[i], dim); + ranges[start] = [start, offset]; + } + goog.asserts.assert(offset <= capacity); + var buf = new ol.structs.Buffer(arr, offset); + return new ol.geom2.LineStringCollection(buf, ranges, dim); +}; + + +/** + * @param {ol.geom2.LineString} lineString Line string. + * @return {number} Offset. + */ +ol.geom2.LineStringCollection.prototype.add = function(lineString) { + var n = lineString.length * this.dim; + var offset = this.buf.allocate(n); + goog.asserts.assert(offset != -1); + this.ranges[offset] = [offset, offset + n]; + ol.geom2.packPoints(this.buf.getArray(), offset, lineString, this.dim); + return offset; +}; + + +/** + * @param {number} offset Offset. + * @return {ol.geom2.LineString} Line string. + */ +ol.geom2.LineStringCollection.prototype.get = function(offset) { + goog.asserts.assert(offset in this.ranges); + var range = this.ranges[offset]; + return ol.geom2.unpackPoints( + this.buf.getArray(), range[0], range[1], this.dim); +}; + + +/** + * @return {number} Count. + */ +ol.geom2.LineStringCollection.prototype.getCount = function() { + return goog.object.getCount(this.ranges); +}; + + +/** + * @return {ol.Extent} Extent. + */ +ol.geom2.LineStringCollection.prototype.getExtent = function() { + return ol.geom2.getExtent(this.buf, this.dim); +}; + + +/** + * @param {number} offset Offset. + */ +ol.geom2.LineStringCollection.prototype.remove = function(offset) { + goog.asserts.assert(offset in this.ranges); + var range = this.ranges[offset]; + this.buf.remove(range[1] - range[0], range[0]); + delete this.ranges[offset]; +}; + + +/** + * @param {number} offset Offset. + * @param {ol.geom2.LineString} lineString Line string. + * @return {number} Offset. + */ +ol.geom2.LineStringCollection.prototype.set = function(offset, lineString) { + var dim = this.dim; + goog.asserts.assert(offset in this.ranges); + var range = this.ranges[offset]; + if (lineString.length * dim == range[1] - range[0]) { + ol.geom2.packPoints(this.buf.getArray(), range[0], lineString, dim); + this.buf.markDirty(range[1] - range[0], range[0]); + return offset; + } else { + this.remove(offset); + return this.add(lineString); + } +}; + + +/** + * @return {Array.} Line strings. + */ +ol.geom2.LineStringCollection.prototype.unpack = function() { + var dim = this.dim; + var n = this.getCount(); + var lineStrings = new Array(n); + var i = 0; + var offset, range; + for (offset in this.ranges) { + range = this.ranges[Number(offset)]; + lineStrings[i++] = ol.geom2.unpackPoints( + this.buf.getArray(), range[0], range[1], dim); + } + return lineStrings; +}; diff --git a/test/spec/ol/geom2/linecollection.test.js b/test/spec/ol/geom2/linecollection.test.js new file mode 100644 index 0000000000..a90b51a110 --- /dev/null +++ b/test/spec/ol/geom2/linecollection.test.js @@ -0,0 +1,303 @@ +goog.provide('ol.test.geom2.LineStringCollection'); + + +describe('ol.geom2.LineStringCollection', function() { + + describe('createEmpty', function() { + + it('creates an empty instance with the specified capacity', function() { + var lsc = ol.geom2.LineStringCollection.createEmpty(16); + expect(lsc.getCount()).to.be(0); + expect(lsc.buf.getArray()).to.have.length(32); + }); + + it('can create empty collections for higher dimensions', function() { + var lsc = ol.geom2.LineStringCollection.createEmpty(16, 3); + expect(lsc.getCount()).to.be(0); + expect(lsc.buf.getArray()).to.have.length(48); + }); + + }); + + describe('pack', function() { + + it('packs an empty array', function() { + var lsc = ol.geom2.LineStringCollection.pack([]); + expect(lsc.buf.getArray()).to.be.empty(); + expect(lsc.ranges).to.be.empty(); + expect(lsc.dim).to.be(2); + }); + + it('packs an empty array with a capacity', function() { + var lsc = ol.geom2.LineStringCollection.pack([], 4); + expect(lsc.buf.getArray()).to.eql( + [NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN]); + expect(lsc.ranges).to.be.empty(); + expect(lsc.dim).to.be(2); + }); + + it('packs an array of line strings', function() { + var lsc = ol.geom2.LineStringCollection.pack( + [[[0, 1], [2, 3], [4, 5]], [[6, 7], [8, 9]]]); + expect(lsc.buf.getArray()).to.eql([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + expect(lsc.getCount()).to.be(2); + expect(lsc.ranges[0]).to.eql([0, 6]); + expect(lsc.ranges[6]).to.eql([6, 10]); + expect(lsc.dim).to.be(2); + }); + + it('packs an array of line strings with a different dimension', function() { + var lsc = ol.geom2.LineStringCollection.pack( + [[[0, 1, 2], [3, 4, 5]], [[6, 7, 8], [9, 10, 11]]]); + expect(lsc.buf.getArray()).to.eql([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]); + expect(lsc.getCount()).to.be(2); + expect(lsc.ranges[0]).to.eql([0, 6]); + expect(lsc.ranges[6]).to.eql([6, 12]); + expect(lsc.dim).to.be(3); + }); + + it('packs an array of line strings with extra capacity', function() { + var lsc = ol.geom2.LineStringCollection.pack( + [[[0, 1], [2, 3], [4, 5]], [[6, 7], [8, 9]]], 16); + expect(lsc.buf.getArray().slice(0, 10)).to.eql( + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + expect(lsc.buf.getArray()).to.have.length(32); + expect(lsc.getCount()).to.be(2); + expect(lsc.ranges[0]).to.eql([0, 6]); + expect(lsc.ranges[6]).to.eql([6, 10]); + expect(lsc.dim).to.be(2); + }); + + it('throws an error when dimensions are inconsistent', function() { + expect(function() { + var lsc = ol.geom2.LineStringCollection.pack([[0, 1], [2, 3, 4]]); + lsc = lsc; // suppress gjslint warning about unused variable + }).to.throwException(); + }); + + it('throws an error when a line string is too short', function() { + expect(function() { + var lsc = ol.geom2.LineStringCollection.pack([[0, 1]]); + lsc = lsc; // suppress gjslint warning about unused variable + }).to.throwException(); + }); + + it('throws an error when the capacity is too small', function() { + expect(function() { + var lsc = ol.geom2.LineStringCollection.pack( + [[[0, 1], [2, 3], [4, 5]], [[6, 7], [8, 9]]], 4); + lsc = lsc; // suppress gjslint warning about unused variable + }).to.throwException(); + }); + + }); + + describe('with an empty instance with spare capacity', function() { + + var lsc; + beforeEach(function() { + var buf = new ol.structs.Buffer(new Array(8), 0); + lsc = new ol.geom2.LineStringCollection(buf); + }); + + describe('add', function() { + + it('adds a line string', function() { + var offset = lsc.add([[0, 1], [2, 3]]); + expect(offset).to.be(0); + expect(lsc.getCount()).to.be(1); + expect(lsc.ranges[0]).to.eql([0, 4]); + expect(lsc.dim).to.be(2); + }); + + }); + + describe('getCount', function() { + + it('returns zero', function() { + expect(lsc.getCount()).to.be(0); + }); + + }); + + describe('getExtent', function() { + + it('returns an empty extent', function() { + expect(ol.extent.isEmpty(lsc.getExtent())).to.be(true); + }); + + }); + + describe('remove', function() { + + it('throws an exception', function() { + expect(function() { + lsc.remove(0); + }).to.throwException(); + }); + + }); + + }); + + describe('with an initial line string', function() { + + var lsc, offset; + beforeEach(function() { + var buf = new ol.structs.Buffer(new Array(8), 0); + lsc = new ol.geom2.LineStringCollection(buf); + offset = lsc.add([[0, 1], [2, 3]]); + }); + + describe('add', function() { + + it('can add a second line string', function() { + var offset2 = lsc.add([[4, 5], [6, 7]]); + expect(offset2).to.be(4); + expect(lsc.getCount()).to.be(2); + expect(lsc.ranges[0]).to.eql([0, 4]); + expect(lsc.ranges[4]).to.eql([4, 8]); + expect(lsc.dim).to.be(2); + }); + + }); + + describe('get', function() { + + it('returns the expected line string', function() { + expect(lsc.get(0)).to.eql([[0, 1], [2, 3]]); + }); + + }); + + describe('getCount', function() { + + it('returns the expected value', function() { + expect(lsc.getCount()).to.be(1); + }); + + }); + + describe('getExtent', function() { + + it('returns the expected extent', function() { + expect(lsc.getExtent()).to.eql([0, 2, 1, 3]); + }); + + }); + + describe('remove', function() { + + it('removes the line string', function() { + lsc.remove(0); + expect(lsc.getCount()).to.be(0); + }); + + }); + + describe('set', function() { + + it('can update the line string in place', function() { + expect(lsc.set(0, [[4, 5], [6, 7]])).to.be(0); + expect(lsc.buf.getArray()).to.eql([4, 5, 6, 7, NaN, NaN, NaN, NaN]); + }); + + it('can replace the line string with a shorter one', function() { + expect(lsc.set(0, [[4, 5]])).to.be(0); + expect(lsc.buf.getArray()).to.eql([4, 5, NaN, NaN, NaN, NaN, NaN, NaN]); + }); + + it('can replace the line string with a longer one', function() { + expect(lsc.set(0, [[4, 5], [6, 7], [8, 9], [10, 11]])).to.be(0); + expect(lsc.buf.getArray()).to.eql([4, 5, 6, 7, 8, 9, 10, 11]); + }); + + }); + + describe('unpack', function() { + + it('returns the expected value', function() { + expect(lsc.unpack()).to.eql([[[0, 1], [2, 3]]]); + }); + + }); + + }); + + describe('with multiple initial line strings', function() { + + var lsc; + beforeEach(function() { + lsc = ol.geom2.LineStringCollection.pack( + [[[0, 1], [2, 3]], [[4, 5], [6, 7], [8, 9]]], 16); + }); + + describe('get', function() { + + it('returns the expected values', function() { + expect(lsc.get(0)).to.eql([[0, 1], [2, 3]]); + expect(lsc.get(4)).to.eql([[4, 5], [6, 7], [8, 9]]); + }); + + }); + + describe('getCount', function() { + + it('returns the expected value', function() { + expect(lsc.getCount()).to.be(2); + }); + + }); + + describe('getExtent', function() { + + it('returns the expected value', function() { + expect(lsc.getExtent()).to.eql([0, 8, 1, 9]); + }); + + }); + + describe('remove', function() { + + it('can remove the first line string', function() { + lsc.remove(0); + expect(lsc.getCount()).to.be(1); + expect(lsc.get(4)).to.eql([[4, 5], [6, 7], [8, 9]]); + }); + + it('can remove the second line string', function() { + lsc.remove(4); + expect(lsc.getCount()).to.be(1); + expect(lsc.get(0)).to.eql([[0, 1], [2, 3]]); + }); + + }); + + describe('usage examples', function() { + + it('allows the first line string to be replaced', function() { + lsc.remove(0); + expect(lsc.getCount()).to.be(1); + expect(lsc.add([[10, 11], [12, 13]])).to.be(0); + expect(lsc.getCount()).to.be(2); + expect(lsc.get(0)).to.eql([[10, 11], [12, 13]]); + }); + + it('will allocate at the end of the array', function() { + lsc.remove(0); + expect(lsc.getCount()).to.be(1); + expect(lsc.add([[10, 11], [12, 13], [14, 15]])).to.be(10); + expect(lsc.getCount()).to.be(2); + expect(lsc.get(10)).to.eql([[10, 11], [12, 13], [14, 15]]); + }); + + }); + + }); + +}); + + +goog.require('ol.geom2.LineStringCollection'); +goog.require('ol.extent'); +goog.require('ol.structs.Buffer'); From 8f86288614a0c9d164ae24d905cb762e7802ecde Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Wed, 1 May 2013 16:22:14 +0200 Subject: [PATCH 10/25] Add line string collections to ol.source.VectorSource2 --- src/objectliterals.jsdoc | 2 ++ src/ol/source/vectorsource2.js | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/objectliterals.jsdoc b/src/objectliterals.jsdoc index e938eec2a9..c7e37d17fa 100644 --- a/src/objectliterals.jsdoc +++ b/src/objectliterals.jsdoc @@ -465,6 +465,8 @@ * @typedef {Object} ol.source.VectorSource2Options * @property {Array.|undefined} attributions Attributions. * @property {ol.Extent|undefined} extent Extent. + * @property {Array.|undefined} + * lineStringCollections Line string collections. * @property {Array.|undefined} pointCollections * Point collections. * @property {ol.ProjectionLike} projection Projection. diff --git a/src/ol/source/vectorsource2.js b/src/ol/source/vectorsource2.js index 612c11582b..095859b431 100644 --- a/src/ol/source/vectorsource2.js +++ b/src/ol/source/vectorsource2.js @@ -1,5 +1,6 @@ goog.provide('ol.source.VectorSource2'); +goog.require('ol.geom2.LineStringCollection'); goog.require('ol.geom2.PointCollection'); goog.require('ol.source.Source'); @@ -25,10 +26,25 @@ ol.source.VectorSource2 = function(options) { this.pointCollections_ = goog.isDef(options.pointCollections) ? options.pointCollections : []; + /** + * @private + * @type {Array.} + */ + this.lineStringCollections_ = goog.isDef(options.lineStringCollections) ? + options.lineStringCollections : []; + }; goog.inherits(ol.source.VectorSource2, ol.source.Source); +/** + * @return {Array.} Line string collections. + */ +ol.source.VectorSource2.prototype.getLineStringCollections = function() { + return this.lineStringCollections_; +}; + + /** * @return {Array.} Point collections. */ From 2484cf2c558ca08339c2dd4eeea931e725639039 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Wed, 29 May 2013 08:49:15 +0200 Subject: [PATCH 11/25] Add line string rendering --- ...webglvectorlayer2linestringcollection.glsl | 19 +++++ ...lvectorlayer2linestringcollectionshader.js | 77 +++++++++++++++++++ .../webgl/webglvectorlayer2renderer.js | 55 +++++++++++++ 3 files changed, 151 insertions(+) create mode 100644 src/ol/renderer/webgl/webglvectorlayer2linestringcollection.glsl create mode 100644 src/ol/renderer/webgl/webglvectorlayer2linestringcollectionshader.js diff --git a/src/ol/renderer/webgl/webglvectorlayer2linestringcollection.glsl b/src/ol/renderer/webgl/webglvectorlayer2linestringcollection.glsl new file mode 100644 index 0000000000..0877de55b1 --- /dev/null +++ b/src/ol/renderer/webgl/webglvectorlayer2linestringcollection.glsl @@ -0,0 +1,19 @@ +//! NAMESPACE=ol.renderer.webgl.vectorlayer2.shader.LineStringCollection +//! CLASS=ol.renderer.webgl.vectorlayer2.shader.LineStringCollection + + +//! VERTEX +attribute vec2 a_position; +uniform mat4 u_modelViewMatrix; + +void main(void) { + gl_Position = u_modelViewMatrix * vec4(a_position, 0., 1.); +} + + +//! FRAGMENT +uniform vec4 u_color; + +void main(void) { + gl_FragColor = u_color; +} diff --git a/src/ol/renderer/webgl/webglvectorlayer2linestringcollectionshader.js b/src/ol/renderer/webgl/webglvectorlayer2linestringcollectionshader.js new file mode 100644 index 0000000000..209412877e --- /dev/null +++ b/src/ol/renderer/webgl/webglvectorlayer2linestringcollectionshader.js @@ -0,0 +1,77 @@ +// This file is automatically generated, do not edit +goog.provide('ol.renderer.webgl.vectorlayer2.shader.LineStringCollection'); +goog.require('ol.webgl.shader'); +/** + * @constructor + * @extends {ol.webgl.shader.Fragment} + */ +ol.renderer.webgl.vectorlayer2.shader.LineStringCollectionFragment = function() { + goog.base(this, ol.renderer.webgl.vectorlayer2.shader.LineStringCollectionFragment.SOURCE); +}; +goog.inherits(ol.renderer.webgl.vectorlayer2.shader.LineStringCollectionFragment, ol.webgl.shader.Fragment); +goog.addSingletonGetter(ol.renderer.webgl.vectorlayer2.shader.LineStringCollectionFragment); +/** + * @const + * @type {string} + */ +ol.renderer.webgl.vectorlayer2.shader.LineStringCollectionFragment.DEBUG_SOURCE = 'precision mediump float;\n//! NAMESPACE=ol.renderer.webgl.vectorlayer2.shader.LineStringCollection\n//! CLASS=ol.renderer.webgl.vectorlayer2.shader.LineStringCollection\n\n\n//! FRAGMENT\nuniform vec4 u_color;\n\nvoid main(void) {\n gl_FragColor = u_color;\n}\n\n'; +/** + * @const + * @type {string} + */ +ol.renderer.webgl.vectorlayer2.shader.LineStringCollectionFragment.OPTIMIZED_SOURCE = 'precision mediump float;uniform vec4 b;void main(){gl_FragColor=b;}'; +/** + * @const + * @type {string} + */ +ol.renderer.webgl.vectorlayer2.shader.LineStringCollectionFragment.SOURCE = goog.DEBUG ? + ol.renderer.webgl.vectorlayer2.shader.LineStringCollectionFragment.DEBUG_SOURCE : + ol.renderer.webgl.vectorlayer2.shader.LineStringCollectionFragment.OPTIMIZED_SOURCE; +/** + * @constructor + * @extends {ol.webgl.shader.Vertex} + */ +ol.renderer.webgl.vectorlayer2.shader.LineStringCollectionVertex = function() { + goog.base(this, ol.renderer.webgl.vectorlayer2.shader.LineStringCollectionVertex.SOURCE); +}; +goog.inherits(ol.renderer.webgl.vectorlayer2.shader.LineStringCollectionVertex, ol.webgl.shader.Vertex); +goog.addSingletonGetter(ol.renderer.webgl.vectorlayer2.shader.LineStringCollectionVertex); +/** + * @const + * @type {string} + */ +ol.renderer.webgl.vectorlayer2.shader.LineStringCollectionVertex.DEBUG_SOURCE = '//! NAMESPACE=ol.renderer.webgl.vectorlayer2.shader.LineStringCollection\n//! CLASS=ol.renderer.webgl.vectorlayer2.shader.LineStringCollection\n\n\n//! VERTEX\nattribute vec2 a_position;\nuniform mat4 u_modelViewMatrix;\n\nvoid main(void) {\n gl_Position = u_modelViewMatrix * vec4(a_position, 0., 1.);\n}\n\n\n'; +/** + * @const + * @type {string} + */ +ol.renderer.webgl.vectorlayer2.shader.LineStringCollectionVertex.OPTIMIZED_SOURCE = 'attribute vec2 b;uniform mat4 a;void main(){gl_Position=a*vec4(b,0,1);}'; +/** + * @const + * @type {string} + */ +ol.renderer.webgl.vectorlayer2.shader.LineStringCollectionVertex.SOURCE = goog.DEBUG ? + ol.renderer.webgl.vectorlayer2.shader.LineStringCollectionVertex.DEBUG_SOURCE : + ol.renderer.webgl.vectorlayer2.shader.LineStringCollectionVertex.OPTIMIZED_SOURCE; +/** + * @constructor + * @param {WebGLRenderingContext} gl GL. + * @param {WebGLProgram} program Program. + */ +ol.renderer.webgl.vectorlayer2.shader.LineStringCollection.Locations = function(gl, program) { + /** + * @type {WebGLUniformLocation} + */ + this.u_modelViewMatrix = gl.getUniformLocation( + program, goog.DEBUG ? 'u_modelViewMatrix' : 'a'); + /** + * @type {WebGLUniformLocation} + */ + this.u_color = gl.getUniformLocation( + program, goog.DEBUG ? 'u_color' : 'b'); + /** + * @type {number} + */ + this.a_position = gl.getAttribLocation( + program, goog.DEBUG ? 'a_position' : 'b'); +}; diff --git a/src/ol/renderer/webgl/webglvectorlayer2renderer.js b/src/ol/renderer/webgl/webglvectorlayer2renderer.js index d16d4fa8ec..3322d743c9 100644 --- a/src/ol/renderer/webgl/webglvectorlayer2renderer.js +++ b/src/ol/renderer/webgl/webglvectorlayer2renderer.js @@ -4,6 +4,7 @@ goog.require('goog.vec.Mat4'); goog.require('goog.webgl'); goog.require('ol.math'); goog.require('ol.renderer.webgl.Layer'); +goog.require('ol.renderer.webgl.vectorlayer2.shader.LineStringCollection'); goog.require('ol.renderer.webgl.vectorlayer2.shader.PointCollection'); @@ -26,6 +27,13 @@ ol.renderer.webgl.VectorLayer2 = function(mapRenderer, vectorLayer2) { */ this.modelViewMatrix_ = goog.vec.Mat4.createNumberIdentity(); + /** + * @private + * @type + * {ol.renderer.webgl.vectorlayer2.shader.LineStringCollection.Locations} + */ + this.lineStringCollectionLocations_ = null; + /** * @private * @type {ol.renderer.webgl.vectorlayer2.shader.PointCollection.Locations} @@ -95,6 +103,10 @@ ol.renderer.webgl.VectorLayer2.prototype.renderFrame = if (pointCollections.length > 0) { this.renderPointCollections(pointCollections); } + var lineStringCollections = vectorSource.getLineStringCollections(); + if (lineStringCollections.length > 0) { + this.renderLineStringCollections(lineStringCollections); + } goog.vec.Mat4.makeIdentity(this.texCoordMatrix); goog.vec.Mat4.translate(this.texCoordMatrix, @@ -113,6 +125,49 @@ ol.renderer.webgl.VectorLayer2.prototype.renderFrame = }; +/** + * @param {Array.} lineStringCollections Line + * string collections. + */ +ol.renderer.webgl.VectorLayer2.prototype.renderLineStringCollections = + function(lineStringCollections) { + + var mapRenderer = this.getWebGLMapRenderer(); + var gl = mapRenderer.getGL(); + + var fragmentShader = ol.renderer.webgl.vectorlayer2.shader. + LineStringCollectionFragment.getInstance(); + var vertexShader = ol.renderer.webgl.vectorlayer2.shader. + LineStringCollectionVertex.getInstance(); + var program = mapRenderer.getProgram(fragmentShader, vertexShader); + gl.useProgram(program); + if (goog.isNull(this.lineStringCollectionLocations_)) { + this.lineStringCollectionLocations_ = + new ol.renderer.webgl.vectorlayer2.shader.LineStringCollection. + Locations(gl, program); + } + + gl.uniformMatrix4fv(this.lineStringCollectionLocations_.u_modelViewMatrix, + false, this.modelViewMatrix_); + + var buf, dim, i, lineStringCollection; + for (i = 0; i < lineStringCollections.length; ++i) { + lineStringCollection = lineStringCollections[i]; + buf = lineStringCollection.buf; + dim = lineStringCollection.dim; + mapRenderer.bindBuffer(goog.webgl.ARRAY_BUFFER, buf); + gl.enableVertexAttribArray(this.lineStringCollectionLocations_.a_position); + gl.vertexAttribPointer(this.lineStringCollectionLocations_.a_position, 2, + goog.webgl.FLOAT, false, 4 * dim, 0); + gl.uniform4fv(this.lineStringCollectionLocations_.u_color, [1, 1, 0, 0.75]); + buf.forEachRange(function(start, stop) { + gl.drawArrays(goog.webgl.LINES, start / dim, (stop - start) / dim); + }); + } + +}; + + /** * @param {Array.} pointCollections Point collections. */ From f55fed9bc3679d6589eecb56c8b22733b55962e0 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Tue, 23 Apr 2013 18:53:45 +0200 Subject: [PATCH 12/25] Add ten thousand points example --- examples/ten-thousand-points.html | 55 ++++++++++++++++++++++++++++ examples/ten-thousand-points.js | 61 +++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+) create mode 100644 examples/ten-thousand-points.html create mode 100644 examples/ten-thousand-points.js diff --git a/examples/ten-thousand-points.html b/examples/ten-thousand-points.html new file mode 100644 index 0000000000..b7953bcb89 --- /dev/null +++ b/examples/ten-thousand-points.html @@ -0,0 +1,55 @@ + + + + + + + + + + Ten thousand points example + + + + + +
+ +
+
+
+
+
+ +
+ +
+

Ten thousand points example

+

Example of a map with ten thousand points.

+
+

See the ten-thousand-points.js source to see how this is done.

+
+
points, vector, openstreetmap
+
+ +
+ +
+ + + + + + diff --git a/examples/ten-thousand-points.js b/examples/ten-thousand-points.js new file mode 100644 index 0000000000..7fa1412f0d --- /dev/null +++ b/examples/ten-thousand-points.js @@ -0,0 +1,61 @@ +goog.require('ol.Map'); +goog.require('ol.RendererHints'); +goog.require('ol.View2D'); +goog.require('ol.control.MousePosition'); +goog.require('ol.control.defaults'); +goog.require('ol.geom2.LineStringCollection'); +goog.require('ol.geom2.PointCollection'); +goog.require('ol.layer.TileLayer'); +goog.require('ol.layer.VectorLayer2'); +goog.require('ol.source.OSM'); +goog.require('ol.source.VectorSource2'); + + +var pointCollection = ol.geom2.PointCollection.createEmpty(101 * 101); +var i, j, x, y; +for (i = 0; i < 101; ++i) { + for (j = 0; j < 101; ++j) { + x = 20000000 * (i - 50) / 50; + y = 20000000 * (j - 50) / 50; + pointCollection.add([x, y]); + } +} + +var k = 1000000; +var lineStringCollection = ol.geom2.LineStringCollection.pack([ + [[-20 * k, -20 * k], [20 * k, 20 * k]], + [[-20 * k, 20 * k], [20 * k, -20 * k]], + [[0 * k, 15 * k], [10 * k, 5 * k]], + [[10 * k, 5 * k], [5 * k, 5 * k]], + [[5 * k, 5 * k], [5 * k, -15 * k]], + [[5 * k, -15 * k], [-5 * k, -15 * k]], + [[-5 * k, -15 * k], [-5 * k, 5 * k]], + [[-5 * k, 5 * k], [-10 * k, 5 * k]], + [[-10 * k, 5 * k], [0 * k, 15 * k]] +]); + +var map = new ol.Map({ + controls: ol.control.defaults({}, [ + new ol.control.MousePosition({ + undefinedHTML: ' ' + }) + ]), + layers: [ + new ol.layer.TileLayer({ + source: new ol.source.OSM() + }), + new ol.layer.VectorLayer2({ + source: new ol.source.VectorSource2({ + lineStringCollections: [lineStringCollection], + projection: 'EPSG:3857', + pointCollections: [pointCollection] + }) + }) + ], + renderers: ol.RendererHints.createFromQueryData(), + target: 'map', + view: new ol.View2D({ + center: [0, 0], + zoom: 0 + }) +}); From 674468268e27ef2dc5d12d544ea9a0f4c70d21b9 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Thu, 30 May 2013 18:04:26 +0200 Subject: [PATCH 13/25] Add ol.renderer.canvas.VectorLayer2 bare skeleton --- .../canvas/canvasvectorlayer2renderer.js | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 src/ol/renderer/canvas/canvasvectorlayer2renderer.js diff --git a/src/ol/renderer/canvas/canvasvectorlayer2renderer.js b/src/ol/renderer/canvas/canvasvectorlayer2renderer.js new file mode 100644 index 0000000000..6167e2ca07 --- /dev/null +++ b/src/ol/renderer/canvas/canvasvectorlayer2renderer.js @@ -0,0 +1,43 @@ +goog.provide('ol.renderer.canvas.VectorLayer2'); + +goog.require('ol.renderer.canvas.Layer'); + + + +/** + * @constructor + * @extends {ol.renderer.canvas.Layer} + * @param {ol.renderer.Map} mapRenderer Map renderer. + * @param {ol.layer.VectorLayer2} vectorLayer2 Vector layer. + */ +ol.renderer.canvas.VectorLayer2 = function(mapRenderer, vectorLayer2) { + + goog.base(this, mapRenderer, vectorLayer2); + +}; +goog.inherits(ol.renderer.canvas.VectorLayer2, ol.renderer.canvas.Layer); + + +/** + * @inheritDoc + */ +ol.renderer.canvas.VectorLayer2.prototype.getImage = function() { + return null; // FIXME +}; + + +/** + * @return {ol.layer.VectorLayer2} Vector layer. + */ +ol.renderer.canvas.VectorLayer2.prototype.getVectorLayer = function() { + return /** @type {ol.layer.VectorLayer2} */ (this.getLayer()); +}; + + +/** + * @inheritDoc + */ +ol.renderer.canvas.VectorLayer2.prototype.renderFrame = + function(frameState, layerState) { + // FIXME +}; From f61edacb5c017fd68551ddd1e9411c816c388959 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Thu, 30 May 2013 18:09:10 +0200 Subject: [PATCH 14/25] Activate ol.renderer.canvas.VectorLayer2 bare skeleton --- src/ol/renderer/canvas/canvasmaprenderer.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ol/renderer/canvas/canvasmaprenderer.js b/src/ol/renderer/canvas/canvasmaprenderer.js index 3849cff227..f155483e99 100644 --- a/src/ol/renderer/canvas/canvasmaprenderer.js +++ b/src/ol/renderer/canvas/canvasmaprenderer.js @@ -12,10 +12,12 @@ goog.require('ol.css'); goog.require('ol.layer.ImageLayer'); goog.require('ol.layer.TileLayer'); goog.require('ol.layer.Vector'); +goog.require('ol.layer.VectorLayer2'); goog.require('ol.renderer.Map'); goog.require('ol.renderer.canvas.ImageLayer'); goog.require('ol.renderer.canvas.TileLayer'); goog.require('ol.renderer.canvas.VectorLayer'); +goog.require('ol.renderer.canvas.VectorLayer2'); goog.require('ol.size'); @@ -72,6 +74,8 @@ ol.renderer.canvas.Map.prototype.createLayerRenderer = function(layer) { return new ol.renderer.canvas.TileLayer(this, layer); } else if (layer instanceof ol.layer.Vector) { return new ol.renderer.canvas.VectorLayer(this, layer); + } else if (layer instanceof ol.layer.VectorLayer2) { + return new ol.renderer.canvas.VectorLayer2(this, layer); } else { goog.asserts.fail(); return null; From 42f15f000be95b06240b155de5a8d2afb0791288 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Thu, 30 May 2013 19:55:09 +0200 Subject: [PATCH 15/25] Add ol.structs.Buffer#getSplit32 --- src/ol/structs/buffer.js | 57 +++++++++++++++++++++++++++++ test/spec/ol/structs/buffer.test.js | 39 ++++++++++++++++++++ 2 files changed, 96 insertions(+) diff --git a/src/ol/structs/buffer.js b/src/ol/structs/buffer.js index bc049f7a08..65178cfb0c 100644 --- a/src/ol/structs/buffer.js +++ b/src/ol/structs/buffer.js @@ -22,6 +22,12 @@ ol.structs.BufferUsage = { ol.BUFFER_REPLACE_UNUSED_ENTRIES_WITH_NANS = goog.DEBUG; +/** + * @typedef {{high: Float32Array, low: Float32Array}} + */ +ol.structs.BufferSplit32; + + /** * @constructor @@ -62,6 +68,18 @@ ol.structs.Buffer = function(opt_arr, opt_used, opt_usage) { } } + /** + * @private + * @type {?ol.structs.BufferSplit32} + */ + this.split32_ = null; + + /** + * @private + * @type {ol.structs.IntegerSet} + */ + this.split32DirtySet_ = null; + /** * @private * @type {number} @@ -146,6 +164,45 @@ ol.structs.Buffer.prototype.getFreeSet = function() { }; +/** + * Splits this buffer into two Float32Arrays. + * @see http://blogs.agi.com/insight3d/index.php/2008/09/03/precisions-precisions/ + * @return {ol.structs.BufferSplit32} Split. + */ +ol.structs.Buffer.prototype.getSplit32 = function() { + var arr = this.arr_; + var n = arr.length; + if (goog.isNull(this.split32DirtySet_)) { + this.split32DirtySet_ = new ol.structs.IntegerSet([0, n]); + this.addDirtySet(this.split32DirtySet_); + } + if (goog.isNull(this.split32_)) { + this.split32_ = { + high: new Float32Array(n), + low: new Float32Array(n) + }; + } + var split32 = this.split32_; + this.split32DirtySet_.forEachRange(function(start, stop) { + var doubleHigh, i, value; + for (i = start; i < stop; ++i) { + value = arr[i]; + if (value < 0) { + doubleHigh = 65536 * Math.floor(-value / 65536); + split32.high[i] = -doubleHigh; + split32.low[i] = value + doubleHigh; + } else { + doubleHigh = 65536 * Math.floor(value / 65536); + split32.high[i] = doubleHigh; + split32.low[i] = value - doubleHigh; + } + } + }); + this.split32DirtySet_.clear(); + return this.split32_; +}; + + /** * @return {number} Usage. */ diff --git a/test/spec/ol/structs/buffer.test.js b/test/spec/ol/structs/buffer.test.js index 2e3710cfa3..956364c706 100644 --- a/test/spec/ol/structs/buffer.test.js +++ b/test/spec/ol/structs/buffer.test.js @@ -220,6 +220,45 @@ describe('ol.structs.Buffer', function() { }); + describe('with a populated instance', function() { + + var b; + beforeEach(function() { + b = new ol.structs.Buffer([1234567.1234567, -7654321.7654321]); + }); + + describe('getSplit32', function() { + + it('returns the expected value', function() { + var split32 = b.getSplit32(); + expect(split32.high).to.be.a(Float32Array); + expect(split32.low).to.be.a(Float32Array); + expect(split32.high).to.have.length(2); + expect(split32.low).to.have.length(2); + expect(split32.high[0]).to.roughlyEqual(1179648.0, 1e1); + expect(split32.low[0]).to.roughlyEqual(54919.12345670001, 1e-2); + expect(split32.high[1]).to.roughlyEqual(-7602176.0, 1e1); + expect(split32.low[1]).to.roughlyEqual(-52145.76543209981, 1e-2); + }); + + it('tracks updates', function() { + b.getSplit32(); + b.getArray()[0] = 0; + b.markDirty(1, 0); + var split32 = b.getSplit32(); + expect(split32.high).to.be.a(Float32Array); + expect(split32.low).to.be.a(Float32Array); + expect(split32.high).to.have.length(2); + expect(split32.low).to.have.length(2); + expect(split32.high[0]).to.be(0); + expect(split32.low[0]).to.be(0); + expect(split32.high[1]).to.roughlyEqual(-7602176.0, 1e1); + expect(split32.low[1]).to.roughlyEqual(-52145.76543209981, 1e-2); + }); + + }); + }); + describe('usage tests', function() { it('allows multiple adds and removes', function() { From db2f805ed902822c300f1a0abb355bbc49e284a7 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Thu, 30 May 2013 20:05:02 +0200 Subject: [PATCH 16/25] Return split values in a single interleaved Float32Array --- src/ol/structs/buffer.js | 32 ++++++++++++----------------- test/spec/ol/structs/buffer.test.js | 28 +++++++++++-------------- 2 files changed, 25 insertions(+), 35 deletions(-) diff --git a/src/ol/structs/buffer.js b/src/ol/structs/buffer.js index 65178cfb0c..91848768c2 100644 --- a/src/ol/structs/buffer.js +++ b/src/ol/structs/buffer.js @@ -22,12 +22,6 @@ ol.structs.BufferUsage = { ol.BUFFER_REPLACE_UNUSED_ENTRIES_WITH_NANS = goog.DEBUG; -/** - * @typedef {{high: Float32Array, low: Float32Array}} - */ -ol.structs.BufferSplit32; - - /** * @constructor @@ -70,7 +64,7 @@ ol.structs.Buffer = function(opt_arr, opt_used, opt_usage) { /** * @private - * @type {?ol.structs.BufferSplit32} + * @type {?Float32Array} */ this.split32_ = null; @@ -165,9 +159,12 @@ ol.structs.Buffer.prototype.getFreeSet = function() { /** - * Splits this buffer into two Float32Arrays. + * Returns a Float32Array twice the length of the buffer containing each value + * split into two 32-bit floating point values that, when added together, + * approximate the original value. Even indicies contain the high bits, odd + * indicies contain the low bits. * @see http://blogs.agi.com/insight3d/index.php/2008/09/03/precisions-precisions/ - * @return {ol.structs.BufferSplit32} Split. + * @return {Float32Array} Split. */ ol.structs.Buffer.prototype.getSplit32 = function() { var arr = this.arr_; @@ -177,24 +174,21 @@ ol.structs.Buffer.prototype.getSplit32 = function() { this.addDirtySet(this.split32DirtySet_); } if (goog.isNull(this.split32_)) { - this.split32_ = { - high: new Float32Array(n), - low: new Float32Array(n) - }; + this.split32_ = new Float32Array(2 * n); } var split32 = this.split32_; this.split32DirtySet_.forEachRange(function(start, stop) { - var doubleHigh, i, value; - for (i = start; i < stop; ++i) { + var doubleHigh, i, j, value; + for (i = start, j = 2 * start; i < stop; ++i, j += 2) { value = arr[i]; if (value < 0) { doubleHigh = 65536 * Math.floor(-value / 65536); - split32.high[i] = -doubleHigh; - split32.low[i] = value + doubleHigh; + split32[j] = -doubleHigh; + split32[j + 1] = value + doubleHigh; } else { doubleHigh = 65536 * Math.floor(value / 65536); - split32.high[i] = doubleHigh; - split32.low[i] = value - doubleHigh; + split32[j] = doubleHigh; + split32[j + 1] = value - doubleHigh; } } }); diff --git a/test/spec/ol/structs/buffer.test.js b/test/spec/ol/structs/buffer.test.js index 956364c706..d91e37a4d7 100644 --- a/test/spec/ol/structs/buffer.test.js +++ b/test/spec/ol/structs/buffer.test.js @@ -231,14 +231,12 @@ describe('ol.structs.Buffer', function() { it('returns the expected value', function() { var split32 = b.getSplit32(); - expect(split32.high).to.be.a(Float32Array); - expect(split32.low).to.be.a(Float32Array); - expect(split32.high).to.have.length(2); - expect(split32.low).to.have.length(2); - expect(split32.high[0]).to.roughlyEqual(1179648.0, 1e1); - expect(split32.low[0]).to.roughlyEqual(54919.12345670001, 1e-2); - expect(split32.high[1]).to.roughlyEqual(-7602176.0, 1e1); - expect(split32.low[1]).to.roughlyEqual(-52145.76543209981, 1e-2); + expect(split32).to.be.a(Float32Array); + expect(split32).to.have.length(4); + expect(split32[0]).to.roughlyEqual(1179648.0, 1e1); + expect(split32[1]).to.roughlyEqual(54919.12345670001, 1e-2); + expect(split32[2]).to.roughlyEqual(-7602176.0, 1e1); + expect(split32[3]).to.roughlyEqual(-52145.76543209981, 1e-2); }); it('tracks updates', function() { @@ -246,14 +244,12 @@ describe('ol.structs.Buffer', function() { b.getArray()[0] = 0; b.markDirty(1, 0); var split32 = b.getSplit32(); - expect(split32.high).to.be.a(Float32Array); - expect(split32.low).to.be.a(Float32Array); - expect(split32.high).to.have.length(2); - expect(split32.low).to.have.length(2); - expect(split32.high[0]).to.be(0); - expect(split32.low[0]).to.be(0); - expect(split32.high[1]).to.roughlyEqual(-7602176.0, 1e1); - expect(split32.low[1]).to.roughlyEqual(-52145.76543209981, 1e-2); + expect(split32).to.be.a(Float32Array); + expect(split32).to.have.length(4); + expect(split32[0]).to.be(0); + expect(split32[1]).to.be(0); + expect(split32[2]).to.roughlyEqual(-7602176.0, 1e1); + expect(split32[3]).to.roughlyEqual(-52145.76543209981, 1e-2); }); }); From 3225a07f6f4a6bbe894efc942cd3696a76071ad8 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Fri, 31 May 2013 12:58:02 +0200 Subject: [PATCH 17/25] Add ol.geom2.LineStringCollection#getIndices --- src/ol/geom2/linestringcollection.js | 24 ++++++++++++++++++++ test/spec/ol/geom2/linecollection.test.js | 27 +++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/src/ol/geom2/linestringcollection.js b/src/ol/geom2/linestringcollection.js index 9981ec7100..2b3427cf77 100644 --- a/src/ol/geom2/linestringcollection.js +++ b/src/ol/geom2/linestringcollection.js @@ -1,6 +1,7 @@ goog.provide('ol.geom2.LineString'); goog.provide('ol.geom2.LineStringCollection'); +goog.require('goog.array'); goog.require('goog.asserts'); goog.require('goog.object'); goog.require('ol.geom2'); @@ -134,6 +135,29 @@ ol.geom2.LineStringCollection.prototype.getExtent = function() { }; +/** + * @return {Array} Indices. + */ +ol.geom2.LineStringCollection.prototype.getIndices = function() { + // FIXME cache and track dirty / track output length + // FIXME return UInt16Array? + var dim = this.dim; + var offsets = goog.array.map(goog.object.getKeys(this.ranges), Number); + goog.array.sort(offsets); + var n = offsets.length; + var indices = []; + var i, j, range, stop; + for (i = 0; i < n; ++i) { + range = this.ranges[offsets[i]]; + stop = range[1] / dim - 1; + for (j = range[0] / dim; j < stop; ++j) { + indices.push(j, j + 1); + } + } + return indices; +}; + + /** * @param {number} offset Offset. */ diff --git a/test/spec/ol/geom2/linecollection.test.js b/test/spec/ol/geom2/linecollection.test.js index a90b51a110..001ef675cc 100644 --- a/test/spec/ol/geom2/linecollection.test.js +++ b/test/spec/ol/geom2/linecollection.test.js @@ -128,6 +128,14 @@ describe('ol.geom2.LineStringCollection', function() { }); + describe('getIndices', function() { + + it('returns the expected value', function() { + expect(lsc.getIndices()).to.be.empty(); + }); + + }); + describe('remove', function() { it('throws an exception', function() { @@ -186,6 +194,14 @@ describe('ol.geom2.LineStringCollection', function() { }); + describe('getIndices', function() { + + it('returns the expected value', function() { + expect(lsc.getIndices()).to.eql([0, 1]); + }); + + }); + describe('remove', function() { it('removes the line string', function() { @@ -257,18 +273,28 @@ describe('ol.geom2.LineStringCollection', function() { }); + describe('getIndices', function() { + + it('returns the expected value', function() { + expect(lsc.getIndices()).to.eql([0, 1, 2, 3, 3, 4]); + }); + + }); + describe('remove', function() { it('can remove the first line string', function() { lsc.remove(0); expect(lsc.getCount()).to.be(1); expect(lsc.get(4)).to.eql([[4, 5], [6, 7], [8, 9]]); + expect(lsc.getIndices()).to.eql([2, 3, 3, 4]); }); it('can remove the second line string', function() { lsc.remove(4); expect(lsc.getCount()).to.be(1); expect(lsc.get(0)).to.eql([[0, 1], [2, 3]]); + expect(lsc.getIndices()).to.eql([0, 1]); }); }); @@ -289,6 +315,7 @@ describe('ol.geom2.LineStringCollection', function() { expect(lsc.add([[10, 11], [12, 13], [14, 15]])).to.be(10); expect(lsc.getCount()).to.be(2); expect(lsc.get(10)).to.eql([[10, 11], [12, 13], [14, 15]]); + expect(lsc.getIndices()).to.eql([2, 3, 3, 4, 5, 6, 6, 7]); }); }); From 38c0e24bcd5dc2d1918440435ddb72e65a95be16 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Fri, 31 May 2013 16:52:09 +0200 Subject: [PATCH 18/25] Add Assertion#arreql Needed because expect.js's eql does not support typed arrays. --- test/expect-0.2.0-ol3/expect.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/expect-0.2.0-ol3/expect.js b/test/expect-0.2.0-ol3/expect.js index 052f9a1df2..d8be00a0f1 100644 --- a/test/expect-0.2.0-ol3/expect.js +++ b/test/expect-0.2.0-ol3/expect.js @@ -371,6 +371,20 @@ return this; }; + /** + * Checks if the array sort of equals another array. + * + * @api public + */ + + Assertion.prototype.arreql = function (obj) { + this.assert( + goog.array.equals(this.obj, obj) + , function(){ return 'expected ' + i(this.obj) + ' to sort of equal ' + i(obj) } + , function(){ return 'expected ' + i(this.obj) + ' to sort of not equal ' + i(obj) }); + return this; + }; + /** * Checks if the obj sortof equals another. * From e260255ce8c76e2e4693371cd869ba74e6659803 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Fri, 31 May 2013 17:47:25 +0200 Subject: [PATCH 19/25] Return Uint16Array from ol.geom2.LineStringCollection#getIndices --- src/ol/geom2/linestringcollection.js | 5 ++--- test/spec/ol/geom2/linecollection.test.js | 10 +++++----- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/ol/geom2/linestringcollection.js b/src/ol/geom2/linestringcollection.js index 2b3427cf77..56a83369e5 100644 --- a/src/ol/geom2/linestringcollection.js +++ b/src/ol/geom2/linestringcollection.js @@ -136,11 +136,10 @@ ol.geom2.LineStringCollection.prototype.getExtent = function() { /** - * @return {Array} Indices. + * @return {Uint16Array} Indices. */ ol.geom2.LineStringCollection.prototype.getIndices = function() { // FIXME cache and track dirty / track output length - // FIXME return UInt16Array? var dim = this.dim; var offsets = goog.array.map(goog.object.getKeys(this.ranges), Number); goog.array.sort(offsets); @@ -154,7 +153,7 @@ ol.geom2.LineStringCollection.prototype.getIndices = function() { indices.push(j, j + 1); } } - return indices; + return new Uint16Array(indices); }; diff --git a/test/spec/ol/geom2/linecollection.test.js b/test/spec/ol/geom2/linecollection.test.js index 001ef675cc..1968e679f1 100644 --- a/test/spec/ol/geom2/linecollection.test.js +++ b/test/spec/ol/geom2/linecollection.test.js @@ -197,7 +197,7 @@ describe('ol.geom2.LineStringCollection', function() { describe('getIndices', function() { it('returns the expected value', function() { - expect(lsc.getIndices()).to.eql([0, 1]); + expect(lsc.getIndices()).to.arreql([0, 1]); }); }); @@ -276,7 +276,7 @@ describe('ol.geom2.LineStringCollection', function() { describe('getIndices', function() { it('returns the expected value', function() { - expect(lsc.getIndices()).to.eql([0, 1, 2, 3, 3, 4]); + expect(lsc.getIndices()).to.arreql([0, 1, 2, 3, 3, 4]); }); }); @@ -287,14 +287,14 @@ describe('ol.geom2.LineStringCollection', function() { lsc.remove(0); expect(lsc.getCount()).to.be(1); expect(lsc.get(4)).to.eql([[4, 5], [6, 7], [8, 9]]); - expect(lsc.getIndices()).to.eql([2, 3, 3, 4]); + expect(lsc.getIndices()).to.arreql([2, 3, 3, 4]); }); it('can remove the second line string', function() { lsc.remove(4); expect(lsc.getCount()).to.be(1); expect(lsc.get(0)).to.eql([[0, 1], [2, 3]]); - expect(lsc.getIndices()).to.eql([0, 1]); + expect(lsc.getIndices()).to.arreql([0, 1]); }); }); @@ -315,7 +315,7 @@ describe('ol.geom2.LineStringCollection', function() { expect(lsc.add([[10, 11], [12, 13], [14, 15]])).to.be(10); expect(lsc.getCount()).to.be(2); expect(lsc.get(10)).to.eql([[10, 11], [12, 13], [14, 15]]); - expect(lsc.getIndices()).to.eql([2, 3, 3, 4, 5, 6, 6, 7]); + expect(lsc.getIndices()).to.arreql([2, 3, 3, 4, 5, 6, 6, 7]); }); }); From 45572931a194358179c99b43bfb74fb804f476c9 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Fri, 31 May 2013 18:26:19 +0200 Subject: [PATCH 20/25] Draw LineStrings using drawElements This enables drawing of LineStrings with more than two coordinates. --- .../renderer/webgl/webglvectorlayer2renderer.js | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/ol/renderer/webgl/webglvectorlayer2renderer.js b/src/ol/renderer/webgl/webglvectorlayer2renderer.js index 3322d743c9..436732107c 100644 --- a/src/ol/renderer/webgl/webglvectorlayer2renderer.js +++ b/src/ol/renderer/webgl/webglvectorlayer2renderer.js @@ -150,19 +150,27 @@ ol.renderer.webgl.VectorLayer2.prototype.renderLineStringCollections = gl.uniformMatrix4fv(this.lineStringCollectionLocations_.u_modelViewMatrix, false, this.modelViewMatrix_); - var buf, dim, i, lineStringCollection; + var buf, dim, i, indexBuffer, indices, lineStringCollection; for (i = 0; i < lineStringCollections.length; ++i) { lineStringCollection = lineStringCollections[i]; buf = lineStringCollection.buf; dim = lineStringCollection.dim; mapRenderer.bindBuffer(goog.webgl.ARRAY_BUFFER, buf); + // FIXME re-use index buffer + // FIXME use mapRenderer.bindBuffer + indices = lineStringCollection.getIndices(); + indexBuffer = gl.createBuffer(); + gl.bindBuffer(goog.webgl.ELEMENT_ARRAY_BUFFER, indexBuffer); + gl.bufferData( + goog.webgl.ELEMENT_ARRAY_BUFFER, indices, goog.webgl.DYNAMIC_DRAW); gl.enableVertexAttribArray(this.lineStringCollectionLocations_.a_position); gl.vertexAttribPointer(this.lineStringCollectionLocations_.a_position, 2, goog.webgl.FLOAT, false, 4 * dim, 0); gl.uniform4fv(this.lineStringCollectionLocations_.u_color, [1, 1, 0, 0.75]); - buf.forEachRange(function(start, stop) { - gl.drawArrays(goog.webgl.LINES, start / dim, (stop - start) / dim); - }); + gl.drawElements( + goog.webgl.LINES, indices.length, goog.webgl.UNSIGNED_SHORT, 0); + gl.bindBuffer(goog.webgl.ELEMENT_ARRAY_BUFFER, null); + gl.deleteBuffer(indexBuffer); } }; From 5850dff2549a25312a62becf5cdb7bc14004576c Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Fri, 31 May 2013 18:27:16 +0200 Subject: [PATCH 21/25] Use long LineString in ten-thousand-points example --- examples/ten-thousand-points.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/examples/ten-thousand-points.js b/examples/ten-thousand-points.js index 7fa1412f0d..28e75e0ed0 100644 --- a/examples/ten-thousand-points.js +++ b/examples/ten-thousand-points.js @@ -25,13 +25,14 @@ var k = 1000000; var lineStringCollection = ol.geom2.LineStringCollection.pack([ [[-20 * k, -20 * k], [20 * k, 20 * k]], [[-20 * k, 20 * k], [20 * k, -20 * k]], - [[0 * k, 15 * k], [10 * k, 5 * k]], - [[10 * k, 5 * k], [5 * k, 5 * k]], - [[5 * k, 5 * k], [5 * k, -15 * k]], - [[5 * k, -15 * k], [-5 * k, -15 * k]], - [[-5 * k, -15 * k], [-5 * k, 5 * k]], - [[-5 * k, 5 * k], [-10 * k, 5 * k]], - [[-10 * k, 5 * k], [0 * k, 15 * k]] + [[0 * k, 15 * k], + [10 * k, 5 * k], + [5 * k, 5 * k], + [5 * k, -15 * k], + [-5 * k, -15 * k], + [-5 * k, 5 * k], + [-10 * k, 5 * k], + [0 * k, 15 * k]] ]); var map = new ol.Map({ From a8586640350a3c8eaa3227c1861b98f0945b1bc6 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Thu, 6 Jun 2013 18:36:00 +0200 Subject: [PATCH 22/25] Add warning about internal API to example --- examples/ten-thousand-points.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/examples/ten-thousand-points.js b/examples/ten-thousand-points.js index 28e75e0ed0..dcb33d75e1 100644 --- a/examples/ten-thousand-points.js +++ b/examples/ten-thousand-points.js @@ -11,6 +11,12 @@ goog.require('ol.source.OSM'); goog.require('ol.source.VectorSource2'); +// WARNING +// This example is an experimental testbed for WebGL vector work. The function +// calls used here are internal and low-level and are not representative of the +// final API. + + var pointCollection = ol.geom2.PointCollection.createEmpty(101 * 101); var i, j, x, y; for (i = 0; i < 101; ++i) { From 85ca39cf0c15fe5504122036aa0ca960b136bf35 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Thu, 6 Jun 2013 18:36:40 +0200 Subject: [PATCH 23/25] Add warnings about internal classes and functions --- src/ol/geom2/linestringcollection.js | 2 ++ src/ol/geom2/pointcollection.js | 3 +++ src/ol/layer/vectorlayer2.js | 1 + src/ol/source/vectorsource2.js | 1 + 4 files changed, 7 insertions(+) diff --git a/src/ol/geom2/linestringcollection.js b/src/ol/geom2/linestringcollection.js index 56a83369e5..06a49b13a9 100644 --- a/src/ol/geom2/linestringcollection.js +++ b/src/ol/geom2/linestringcollection.js @@ -16,6 +16,7 @@ ol.geom2.LineString; /** + * This is an internal class that will be removed from the API. * @constructor * @param {ol.structs.Buffer} buf Buffer. * @param {Object.>=} opt_ranges Ranges. @@ -54,6 +55,7 @@ ol.geom2.LineStringCollection.createEmpty = function(capacity, opt_dim) { /** + * This is an internal function that will be removed from the API. * @param {Array.} unpackedLineStrings Unpacked line * strings. * @param {number=} opt_capacity Capacity. diff --git a/src/ol/geom2/pointcollection.js b/src/ol/geom2/pointcollection.js index 877071878d..c9ba6e8336 100644 --- a/src/ol/geom2/pointcollection.js +++ b/src/ol/geom2/pointcollection.js @@ -15,6 +15,7 @@ ol.geom2.Point; /** + * This is an internal class that will be removed from the API. * @constructor * @param {ol.structs.Buffer} buf Buffer. * @param {number=} opt_dim Dimension. @@ -35,6 +36,7 @@ ol.geom2.PointCollection = function(buf, opt_dim) { /** + * This is an internal function that will be removed from the API. * @param {number} capacity Capacity. * @param {number=} opt_dim Dimension. * @return {ol.geom2.PointCollection} Point collection. @@ -47,6 +49,7 @@ ol.geom2.PointCollection.createEmpty = function(capacity, opt_dim) { /** + * This is an internal function that will be removed from the API. * @param {Array.} unpackedPoints Unpacked points. * @param {number=} opt_capacity Capacity. * @param {number=} opt_dim Dimension. diff --git a/src/ol/layer/vectorlayer2.js b/src/ol/layer/vectorlayer2.js index 8ca94375b6..471fdb8b75 100644 --- a/src/ol/layer/vectorlayer2.js +++ b/src/ol/layer/vectorlayer2.js @@ -6,6 +6,7 @@ goog.require('ol.source.VectorSource2'); /** + * This is an internal class that will be removed from the API. * @constructor * @extends {ol.layer.Layer} * @param {ol.layer.LayerOptions} options Options. diff --git a/src/ol/source/vectorsource2.js b/src/ol/source/vectorsource2.js index 095859b431..e5e72f37bd 100644 --- a/src/ol/source/vectorsource2.js +++ b/src/ol/source/vectorsource2.js @@ -7,6 +7,7 @@ goog.require('ol.source.Source'); /** + * This is an internal class that will be removed from the API. * @constructor * @extends {ol.source.Source} * @param {ol.source.VectorSource2Options} options Options. From e8ab4f9f0c2ecfe4219d906c784713cc7829ee6e Mon Sep 17 00:00:00 2001 From: ahocevar Date: Mon, 10 Jun 2013 11:22:32 +0200 Subject: [PATCH 24/25] Removing canvas renderer stub for VectorLayer2 Setting the renderer of the ten-thousand-points example to WebGL should remove the need for this stub. This is basically the same approach we took for all vector examples in master, where we set the renderer to Canvas. --- examples/ten-thousand-points.js | 4 +- src/ol/renderer/canvas/canvasmaprenderer.js | 4 -- .../canvas/canvasvectorlayer2renderer.js | 43 ------------------- 3 files changed, 2 insertions(+), 49 deletions(-) delete mode 100644 src/ol/renderer/canvas/canvasvectorlayer2renderer.js diff --git a/examples/ten-thousand-points.js b/examples/ten-thousand-points.js index dcb33d75e1..87552e26e0 100644 --- a/examples/ten-thousand-points.js +++ b/examples/ten-thousand-points.js @@ -1,5 +1,5 @@ goog.require('ol.Map'); -goog.require('ol.RendererHints'); +goog.require('ol.RendererHint'); goog.require('ol.View2D'); goog.require('ol.control.MousePosition'); goog.require('ol.control.defaults'); @@ -59,7 +59,7 @@ var map = new ol.Map({ }) }) ], - renderers: ol.RendererHints.createFromQueryData(), + renderer: ol.RendererHint.WEBGL, target: 'map', view: new ol.View2D({ center: [0, 0], diff --git a/src/ol/renderer/canvas/canvasmaprenderer.js b/src/ol/renderer/canvas/canvasmaprenderer.js index f155483e99..3849cff227 100644 --- a/src/ol/renderer/canvas/canvasmaprenderer.js +++ b/src/ol/renderer/canvas/canvasmaprenderer.js @@ -12,12 +12,10 @@ goog.require('ol.css'); goog.require('ol.layer.ImageLayer'); goog.require('ol.layer.TileLayer'); goog.require('ol.layer.Vector'); -goog.require('ol.layer.VectorLayer2'); goog.require('ol.renderer.Map'); goog.require('ol.renderer.canvas.ImageLayer'); goog.require('ol.renderer.canvas.TileLayer'); goog.require('ol.renderer.canvas.VectorLayer'); -goog.require('ol.renderer.canvas.VectorLayer2'); goog.require('ol.size'); @@ -74,8 +72,6 @@ ol.renderer.canvas.Map.prototype.createLayerRenderer = function(layer) { return new ol.renderer.canvas.TileLayer(this, layer); } else if (layer instanceof ol.layer.Vector) { return new ol.renderer.canvas.VectorLayer(this, layer); - } else if (layer instanceof ol.layer.VectorLayer2) { - return new ol.renderer.canvas.VectorLayer2(this, layer); } else { goog.asserts.fail(); return null; diff --git a/src/ol/renderer/canvas/canvasvectorlayer2renderer.js b/src/ol/renderer/canvas/canvasvectorlayer2renderer.js deleted file mode 100644 index 6167e2ca07..0000000000 --- a/src/ol/renderer/canvas/canvasvectorlayer2renderer.js +++ /dev/null @@ -1,43 +0,0 @@ -goog.provide('ol.renderer.canvas.VectorLayer2'); - -goog.require('ol.renderer.canvas.Layer'); - - - -/** - * @constructor - * @extends {ol.renderer.canvas.Layer} - * @param {ol.renderer.Map} mapRenderer Map renderer. - * @param {ol.layer.VectorLayer2} vectorLayer2 Vector layer. - */ -ol.renderer.canvas.VectorLayer2 = function(mapRenderer, vectorLayer2) { - - goog.base(this, mapRenderer, vectorLayer2); - -}; -goog.inherits(ol.renderer.canvas.VectorLayer2, ol.renderer.canvas.Layer); - - -/** - * @inheritDoc - */ -ol.renderer.canvas.VectorLayer2.prototype.getImage = function() { - return null; // FIXME -}; - - -/** - * @return {ol.layer.VectorLayer2} Vector layer. - */ -ol.renderer.canvas.VectorLayer2.prototype.getVectorLayer = function() { - return /** @type {ol.layer.VectorLayer2} */ (this.getLayer()); -}; - - -/** - * @inheritDoc - */ -ol.renderer.canvas.VectorLayer2.prototype.renderFrame = - function(frameState, layerState) { - // FIXME -}; From bbb95e15fa2939441ad4f3e1cda8772cf1fdd5cf Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Mon, 10 Jun 2013 14:43:01 +0200 Subject: [PATCH 25/25] Fix line collection arguments in tests, thanks @ahocevar --- test/spec/ol/geom2/linecollection.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/spec/ol/geom2/linecollection.test.js b/test/spec/ol/geom2/linecollection.test.js index 1968e679f1..8fe7c4eddb 100644 --- a/test/spec/ol/geom2/linecollection.test.js +++ b/test/spec/ol/geom2/linecollection.test.js @@ -70,14 +70,14 @@ describe('ol.geom2.LineStringCollection', function() { it('throws an error when dimensions are inconsistent', function() { expect(function() { - var lsc = ol.geom2.LineStringCollection.pack([[0, 1], [2, 3, 4]]); + var lsc = ol.geom2.LineStringCollection.pack([[[0, 1], [2, 3, 4]]]); lsc = lsc; // suppress gjslint warning about unused variable }).to.throwException(); }); it('throws an error when a line string is too short', function() { expect(function() { - var lsc = ol.geom2.LineStringCollection.pack([[0, 1]]); + var lsc = ol.geom2.LineStringCollection.pack([[[0, 1]]]); lsc = lsc; // suppress gjslint warning about unused variable }).to.throwException(); });