From fd0a5f3622ddb07768cc8722894c119fc0f115f6 Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Fri, 18 Jan 2013 15:57:48 -0700 Subject: [PATCH] Point, linestring, and linearring coordinates as Float32Array --- src/ol/geom/geometry.js | 15 ++++++++ src/ol/geom/linearring.js | 27 +++++++++++++++ src/ol/geom/linestring.js | 25 ++++++++++++-- src/ol/geom/multilinestring.js | 26 ++++++++++++-- src/ol/geom/multipoint.js | 26 ++++++++++++-- src/ol/geom/multipolygon.js | 27 +++++++++++++-- src/ol/geom/point.js | 15 ++++++-- src/ol/geom/polygon.js | 28 +++++++++++++-- test/ol.html | 4 +++ test/spec/ol/geom/linearring.test.js | 49 ++++++++++++++++++++++++++ test/spec/ol/geom/linestring.test.js | 49 ++++++++++++++++++++++++++ test/spec/ol/geom/point.test.js | 48 ++++++++++++++++++++++++++ test/spec/ol/geom/polygon.test.js | 51 ++++++++++++++++++++++++++++ 13 files changed, 372 insertions(+), 18 deletions(-) create mode 100644 src/ol/geom/linearring.js create mode 100644 test/spec/ol/geom/linearring.test.js create mode 100644 test/spec/ol/geom/linestring.test.js create mode 100644 test/spec/ol/geom/point.test.js create mode 100644 test/spec/ol/geom/polygon.test.js diff --git a/src/ol/geom/geometry.js b/src/ol/geom/geometry.js index 57f8ec0545..2ddbbe0987 100644 --- a/src/ol/geom/geometry.js +++ b/src/ol/geom/geometry.js @@ -1,7 +1,22 @@ +goog.provide('ol.geom.Coordinate'); +goog.provide('ol.geom.CoordinateArray'); goog.provide('ol.geom.Geometry'); + /** * @interface */ ol.geom.Geometry = function() {}; + + +/** + * @typedef {Array.} + */ +ol.geom.Coordinate; + + +/** + * @typedef {Array.} + */ +ol.geom.CoordinateArray; diff --git a/src/ol/geom/linearring.js b/src/ol/geom/linearring.js new file mode 100644 index 0000000000..0af7ef18dc --- /dev/null +++ b/src/ol/geom/linearring.js @@ -0,0 +1,27 @@ +goog.provide('ol.geom.LinearRing'); + +goog.require('goog.asserts'); +goog.require('goog.vec.Float32Array'); +goog.require('ol.geom.CoordinateArray'); +goog.require('ol.geom.LineString'); + + + +/** + * @constructor + * @extends {ol.geom.LineString} + * @param {ol.geom.CoordinateArray} coordinates Coordinates array (e.g. + * [[x0, y0], [x1, y1], [x0, y0]]). + */ +ol.geom.LinearRing = function(coordinates) { + + goog.base(this, coordinates); + + /** + * We're intentionally not enforcing that rings be closed right now. This + * will allow proper rendering of data from tiled vector sources that leave + * open rings. + */ + +}; +goog.inherits(ol.geom.LinearRing, ol.geom.LineString); diff --git a/src/ol/geom/linestring.js b/src/ol/geom/linestring.js index 241aff7dfd..d820674615 100644 --- a/src/ol/geom/linestring.js +++ b/src/ol/geom/linestring.js @@ -1,5 +1,8 @@ goog.provide('ol.geom.LineString'); +goog.require('goog.asserts'); +goog.require('goog.vec.Float32Array'); +goog.require('ol.geom.CoordinateArray'); goog.require('ol.geom.Geometry'); @@ -7,13 +10,29 @@ goog.require('ol.geom.Geometry'); /** * @constructor * @implements {ol.geom.Geometry} - * @param {Array} coordinates Coordinates array. + * @param {ol.geom.CoordinateArray} coordinates Coordinates array (e.g. + * [[x0, y0], [x1, y1]]). */ ol.geom.LineString = function(coordinates) { + // assume the same dimension for all coordinates + var dimension = coordinates[0].length, + count = coordinates.length, + length = count * dimension; + /** - * @type {Array} + * @type {Float32Array} */ - this.coordinates = coordinates; + this.coordinates = new Float32Array(length); + for (var i = 0; i < count; ++i) { + goog.asserts.assert(coordinates[i].length === dimension); + this.coordinates.set(coordinates[i], i * dimension); + } + + /** + * @type {number} + */ + this.dimension = dimension; + goog.asserts.assert(this.dimension >= 2); }; diff --git a/src/ol/geom/multilinestring.js b/src/ol/geom/multilinestring.js index 0665f9d630..f73f24d8e6 100644 --- a/src/ol/geom/multilinestring.js +++ b/src/ol/geom/multilinestring.js @@ -1,19 +1,39 @@ goog.provide('ol.geom.MultiLineString'); +goog.require('goog.asserts'); +goog.require('ol.geom.CoordinateArray'); goog.require('ol.geom.Geometry'); +goog.require('ol.geom.LineString'); /** * @constructor * @implements {ol.geom.Geometry} - * @param {Array} coordinates Coordinates array. + * @param {Array.} coordinates Coordinates array. */ ol.geom.MultiLineString = function(coordinates) { + var numParts = coordinates.length, + dimension; + /** - * @type {Array} + * @type {Array.} */ - this.coordinates = coordinates; + this.components = new Array(numParts); + for (var i = 0; i < numParts; ++i) { + this.components[i] = new ol.geom.LineString(coordinates[i]); + if (!goog.isDef(dimension)) { + dimension = this.components[i]; + } else { + goog.asserts.assert(this.components[i].dimension === dimension); + } + } + + /** + * @type {number} + */ + this.dimension = dimension; + goog.asserts.assert(this.dimension >= 2); }; diff --git a/src/ol/geom/multipoint.js b/src/ol/geom/multipoint.js index 586730f6b6..8669a7c0cc 100644 --- a/src/ol/geom/multipoint.js +++ b/src/ol/geom/multipoint.js @@ -1,19 +1,39 @@ goog.provide('ol.geom.MultiPoint'); +goog.require('goog.asserts'); +goog.require('ol.geom.CoordinateArray'); goog.require('ol.geom.Geometry'); +goog.require('ol.geom.Point'); /** * @constructor * @implements {ol.geom.Geometry} - * @param {Array} coordinates Coordinates array. + * @param {ol.geom.CoordinateArray} coordinates Coordinates array. */ ol.geom.MultiPoint = function(coordinates) { + var numParts = coordinates.length, + dimension; + /** - * @type {Array} + * @type {Array.} */ - this.coordinates = coordinates; + this.components = new Array(numParts); + for (var i = 0; i < numParts; ++i) { + this.components[i] = new ol.geom.Point(coordinates[i]); + if (!goog.isDef(dimension)) { + dimension = this.components[i].dimension; + } else { + goog.asserts.assert(this.components[i].dimension === dimension); + } + } + + /** + * @type {number} + */ + this.dimension = dimension; + goog.asserts.assert(this.dimension >= 2); }; diff --git a/src/ol/geom/multipolygon.js b/src/ol/geom/multipolygon.js index 4f22f0d003..958ddf9d5d 100644 --- a/src/ol/geom/multipolygon.js +++ b/src/ol/geom/multipolygon.js @@ -1,19 +1,40 @@ goog.provide('ol.geom.MultiPolygon'); +goog.require('goog.asserts'); +goog.require('ol.geom.CoordinateArray'); goog.require('ol.geom.Geometry'); +goog.require('ol.geom.Polygon'); /** * @constructor * @implements {ol.geom.Geometry} - * @param {Array} coordinates Coordinates array. + * @param {Array.>} coordinates Coordinates + * array. */ ol.geom.MultiPolygon = function(coordinates) { + var numParts = coordinates.length, + dimension; + /** - * @type {Array} + * @type {Array.} */ - this.coordinates = coordinates; + this.components = new Array(numParts); + for (var i = 0; i < numParts; ++i) { + this.components[i] = new ol.geom.Polygon(coordinates[i]); + if (!goog.isDef(dimension)) { + dimension = this.components[i]; + } else { + goog.asserts.assert(this.components[i].dimension === dimension); + } + } + + /** + * @type {number} + */ + this.dimension = dimension; + goog.asserts.assert(this.dimension >= 2); }; diff --git a/src/ol/geom/point.js b/src/ol/geom/point.js index 2f4e2b6d64..db4bda24fb 100644 --- a/src/ol/geom/point.js +++ b/src/ol/geom/point.js @@ -1,5 +1,8 @@ goog.provide('ol.geom.Point'); +goog.require('goog.asserts'); +goog.require('goog.vec.Float32Array'); +goog.require('ol.geom.Coordinate'); goog.require('ol.geom.Geometry'); @@ -7,13 +10,19 @@ goog.require('ol.geom.Geometry'); /** * @constructor * @implements {ol.geom.Geometry} - * @param {Array} coordinates Coordinates array. + * @param {ol.geom.Coordinate} coordinates Coordinates array (e.g. [x, y]). */ ol.geom.Point = function(coordinates) { /** - * @type {Array} + * @type {Float32Array} */ - this.coordinates = coordinates; + this.coordinates = new Float32Array(coordinates); + + /** + * @type {number} + */ + this.dimension = coordinates.length; + goog.asserts.assert(this.dimension >= 2); }; diff --git a/src/ol/geom/polygon.js b/src/ol/geom/polygon.js index bd0f698c7d..489cd9255e 100644 --- a/src/ol/geom/polygon.js +++ b/src/ol/geom/polygon.js @@ -1,19 +1,41 @@ goog.provide('ol.geom.Polygon'); +goog.require('goog.asserts'); +goog.require('goog.vec.Float32Array'); +goog.require('ol.geom.CoordinateArray'); goog.require('ol.geom.Geometry'); +goog.require('ol.geom.LinearRing'); /** * @constructor * @implements {ol.geom.Geometry} - * @param {Array} coordinates Coordinates array. + * @param {Array.} coordinates Array of rings. First + * is outer, any remaining are inner. */ ol.geom.Polygon = function(coordinates) { + var numRings = coordinates.length, + dimension; + /** - * @type {Array} + * @type {Array.} */ - this.coordinates = coordinates; + this.rings = new Array(numRings); + for (var i = 0; i < numRings; ++i) { + this.rings[i] = new ol.geom.LinearRing(coordinates[i]); + if (!goog.isDef(dimension)) { + dimension = this.rings[i].dimension; + } else { + goog.asserts.assert(this.rings[i].dimension === dimension); + } + } + + /** + * @type {number} + */ + this.dimension = dimension; + goog.asserts.assert(this.dimension >= 2); }; diff --git a/test/ol.html b/test/ol.html index b0e05e2f6d..c71623217a 100644 --- a/test/ol.html +++ b/test/ol.html @@ -80,6 +80,10 @@ + + + + diff --git a/test/spec/ol/geom/linearring.test.js b/test/spec/ol/geom/linearring.test.js new file mode 100644 index 0000000000..c32d43651b --- /dev/null +++ b/test/spec/ol/geom/linearring.test.js @@ -0,0 +1,49 @@ +describe('ol.geom.LinearRing', function() { + + describe('constructor', function() { + + it('creates a ring from an array', function() { + var ring = new ol.geom.LinearRing([[10, 20], [30, 40]]); + expect(ring).toBeA(ol.geom.LinearRing); + }); + + it('throws when given mismatched dimension', function() { + expect(function() { + var ring = new ol.geom.LinearRing([[10, 20], [30, 40, 50]]); + }).toThrow(); + }); + + }); + + describe('coordinates', function() { + + it('is a Float32Array', function() { + var ring = new ol.geom.LinearRing([[10, 20], [30, 40]]); + expect(ring.coordinates).toBeA(Float32Array); + + expect(ring.coordinates.length).toBe(4); + expect(ring.coordinates[0]).toBe(10); + expect(ring.coordinates[1]).toBe(20); + expect(ring.coordinates[2]).toBe(30); + expect(ring.coordinates[3]).toBe(40); + }); + + }); + + describe('dimension', function() { + + it('can be 2', function() { + var ring = new ol.geom.LinearRing([[10, 20], [30, 40]]); + expect(ring.dimension).toBe(2); + }); + + it('can be 3', function() { + var ring = new ol.geom.LinearRing([[10, 20, 30], [40, 50, 60]]); + expect(ring.dimension).toBe(3); + }); + + }); + + +}); + diff --git a/test/spec/ol/geom/linestring.test.js b/test/spec/ol/geom/linestring.test.js new file mode 100644 index 0000000000..582c6fdf2a --- /dev/null +++ b/test/spec/ol/geom/linestring.test.js @@ -0,0 +1,49 @@ +describe('ol.geom.LineString', function() { + + describe('constructor', function() { + + it('creates a linestring from an array', function() { + var line = new ol.geom.LineString([[10, 20], [30, 40]]); + expect(line).toBeA(ol.geom.LineString); + }); + + it('throws when given mismatched dimension', function() { + expect(function() { + var line = new ol.geom.LineString([[10, 20], [30, 40, 50]]); + }).toThrow(); + }); + + }); + + describe('coordinates', function() { + + it('is a Float32Array', function() { + var line = new ol.geom.LineString([[10, 20], [30, 40]]); + expect(line.coordinates).toBeA(Float32Array); + + expect(line.coordinates.length).toBe(4); + expect(line.coordinates[0]).toBe(10); + expect(line.coordinates[1]).toBe(20); + expect(line.coordinates[2]).toBe(30); + expect(line.coordinates[3]).toBe(40); + }); + + }); + + describe('dimension', function() { + + it('can be 2', function() { + var line = new ol.geom.LineString([[10, 20], [30, 40]]); + expect(line.dimension).toBe(2); + }); + + it('can be 3', function() { + var line = new ol.geom.LineString([[10, 20, 30], [40, 50, 60]]); + expect(line.dimension).toBe(3); + }); + + }); + + +}); + diff --git a/test/spec/ol/geom/point.test.js b/test/spec/ol/geom/point.test.js new file mode 100644 index 0000000000..237b07394b --- /dev/null +++ b/test/spec/ol/geom/point.test.js @@ -0,0 +1,48 @@ +describe('ol.geom.Point', function() { + + describe('constructor', function() { + + it('creates a point from an array', function() { + var point = new ol.geom.Point([10, 20]); + expect(point).toBeA(ol.geom.Point); + }); + + it('throws when given with insufficient dimensions', function() { + expect(function() { + var point = new ol.geom.Point([1]); + }).toThrow(); + }); + + }); + + describe('coordinates', function() { + + it('is a Float32Array', function() { + var point = new ol.geom.Point([10, 20]); + expect(point.coordinates).toBeA(Float32Array); + + expect(point.coordinates.length).toBe(2); + expect(point.coordinates[0]).toBe(10); + expect(point.coordinates[1]).toBe(20); + + }); + + }); + + describe('dimension', function() { + + it('can be 2', function() { + var point = new ol.geom.Point([10, 20]); + expect(point.dimension).toBe(2); + }); + + it('can be 3', function() { + var point = new ol.geom.Point([10, 20, 30]); + expect(point.dimension).toBe(3); + }); + + }); + + +}); + diff --git a/test/spec/ol/geom/polygon.test.js b/test/spec/ol/geom/polygon.test.js new file mode 100644 index 0000000000..44b797a993 --- /dev/null +++ b/test/spec/ol/geom/polygon.test.js @@ -0,0 +1,51 @@ +describe('ol.geom.Polygon', function() { + + var outer = [[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]], + inner1 = [[1, 1], [2, 1], [2, 2], [1, 2], [1, 1]], + inner2 = [[8, 8], [9, 8], [9, 9], [8, 9], [8, 8]]; + + describe('constructor', function() { + + it('creates a polygon from an array', function() { + var poly = new ol.geom.Polygon([outer, inner1, inner2]); + expect(poly).toBeA(ol.geom.Polygon); + }); + + it('throws when given mismatched dimension', function() { + expect(function() { + var poly = new ol.geom.Polygon([[[10, 20], [30, 40, 50]]]); + }).toThrow(); + }); + + }); + + describe('rings', function() { + + it('is an array of LinearRing', function() { + var poly = new ol.geom.Polygon([outer, inner1, inner2]); + + expect(poly.rings.length).toBe(3); + expect(poly.rings[0]).toBeA(ol.geom.LinearRing); + expect(poly.rings[1]).toBeA(ol.geom.LinearRing); + expect(poly.rings[2]).toBeA(ol.geom.LinearRing); + }); + + }); + + describe('dimension', function() { + + it('can be 2', function() { + var poly = new ol.geom.Polygon([outer, inner1, inner2]); + expect(poly.dimension).toBe(2); + }); + + it('can be 3', function() { + var poly = new ol.geom.Polygon([[[10, 20, 30], [40, 50, 60]]]); + expect(poly.dimension).toBe(3); + }); + + }); + + +}); +