diff --git a/src/ol/geom/abstractcollection.js b/src/ol/geom/abstractcollection.js
new file mode 100644
index 0000000000..b5ce4ee588
--- /dev/null
+++ b/src/ol/geom/abstractcollection.js
@@ -0,0 +1,79 @@
+goog.provide('ol.geom.AbstractCollection');
+
+goog.require('ol.Extent');
+goog.require('ol.geom.Geometry');
+
+
+
+/**
+ * A collection of geometries. This constructor is not to be used directly.
+ *
+ * @constructor
+ * @extends {ol.geom.Geometry}
+ */
+ol.geom.AbstractCollection = function() {
+ goog.base(this);
+
+ /**
+ * @type {number}
+ */
+ this.dimension;
+
+ /**
+ * @type {Array.
}
+ */
+ this.components = null;
+
+ /**
+ * @type {ol.Extent}
+ * @protected
+ */
+ this.bounds = null;
+
+};
+goog.inherits(ol.geom.AbstractCollection, ol.geom.Geometry);
+
+
+/**
+ * @inheritDoc
+ */
+ol.geom.AbstractCollection.prototype.getBounds = function() {
+ if (goog.isNull(this.bounds)) {
+ var minX,
+ minY = minX = Number.POSITIVE_INFINITY,
+ maxX,
+ maxY = maxX = Number.NEGATIVE_INFINITY,
+ components = this.components,
+ len = components.length,
+ bounds, i;
+
+ for (i = 0; i < len; ++i) {
+ bounds = components[i].getBounds();
+ minX = Math.min(bounds.minX, minX);
+ minY = Math.min(bounds.minY, minY);
+ maxX = Math.max(bounds.maxX, maxX);
+ maxY = Math.max(bounds.maxY, maxY);
+ }
+ this.bounds = new ol.Extent(minX, minY, maxX, maxY);
+ }
+ return this.bounds;
+};
+
+
+/**
+ * @inheritDoc
+ */
+ol.geom.AbstractCollection.prototype.getCoordinates = function() {
+ var count = this.components.length;
+ var coordinates = new Array(count);
+ for (var i = 0; i < count; ++i) {
+ coordinates[i] = this.components[i].getCoordinates();
+ }
+ return coordinates;
+};
+
+
+/**
+ * @inheritDoc
+ */
+ol.geom.AbstractCollection.prototype.getType = goog.abstractMethod;
diff --git a/src/ol/geom/base.js b/src/ol/geom/base.js
new file mode 100644
index 0000000000..31ebb15f95
--- /dev/null
+++ b/src/ol/geom/base.js
@@ -0,0 +1,14 @@
+goog.provide('ol.geom.Vertex');
+goog.provide('ol.geom.VertexArray');
+
+
+/**
+ * @typedef {Array.}
+ */
+ol.geom.Vertex;
+
+
+/**
+ * @typedef {Array.}
+ */
+ol.geom.VertexArray;
diff --git a/src/ol/geom/geometry.js b/src/ol/geom/geometry.js
index b2ab428bf5..4e61d692f6 100644
--- a/src/ol/geom/geometry.js
+++ b/src/ol/geom/geometry.js
@@ -1,15 +1,23 @@
-goog.require('ol.Extent');
-goog.provide('ol.geom.Coordinate');
-goog.provide('ol.geom.CoordinateArray');
goog.provide('ol.geom.Geometry');
goog.provide('ol.geom.GeometryType');
+goog.require('ol.Extent');
+goog.require('ol.geom.SharedVertices');
+
/**
* @constructor
*/
-ol.geom.Geometry = function() {};
+ol.geom.Geometry = function() {
+
+ /**
+ * @type {ol.geom.SharedVertices}
+ * @protected
+ */
+ this.vertices = null;
+
+};
/**
@@ -26,6 +34,21 @@ ol.geom.Geometry.prototype.dimension;
ol.geom.Geometry.prototype.getBounds = goog.abstractMethod;
+/**
+ * @return {Array} The GeoJSON style coordinates array for the geometry.
+ */
+ol.geom.Geometry.prototype.getCoordinates = goog.abstractMethod;
+
+
+/**
+ * Get the shared vertices for this geometry.
+ * @return {ol.geom.SharedVertices} The shared vertices.
+ */
+ol.geom.Geometry.prototype.getSharedVertices = function() {
+ return this.vertices;
+};
+
+
/**
* Get the geometry type.
* @return {ol.geom.GeometryType} The geometry type.
@@ -33,18 +56,6 @@ ol.geom.Geometry.prototype.getBounds = goog.abstractMethod;
ol.geom.Geometry.prototype.getType = goog.abstractMethod;
-/**
- * @typedef {Array.}
- */
-ol.geom.Coordinate;
-
-
-/**
- * @typedef {Array.}
- */
-ol.geom.CoordinateArray;
-
-
/**
* @enum {string}
*/
diff --git a/src/ol/geom/geometrycollection.js b/src/ol/geom/geometrycollection.js
index 277eafa899..8585d95394 100644
--- a/src/ol/geom/geometrycollection.js
+++ b/src/ol/geom/geometrycollection.js
@@ -1,65 +1,43 @@
goog.provide('ol.geom.GeometryCollection');
-goog.require('ol.Extent');
+goog.require('ol.geom.AbstractCollection');
goog.require('ol.geom.Geometry');
goog.require('ol.geom.GeometryType');
/**
- * A collection of geometries. This constructor should not called. Instead
- * create one of the fixed type collections.
+ * A mixed collection of geometries. Used one of the fixed type multi-part
+ * constructors for collections of the same type.
+ *
* @constructor
- * @extends {ol.geom.Geometry}
+ * @extends {ol.geom.AbstractCollection}
+ * @param {Array.} geometries Array of geometries.
*/
-ol.geom.GeometryCollection = function() {
-
+ol.geom.GeometryCollection = function(geometries) {
goog.base(this);
/**
* @type {Array.}
*/
- this.components = null;
+ this.components = geometries;
+
+ var dimension = 0;
+ for (var i = 0, ii = geometries.length; i < ii; ++i) {
+ if (goog.isDef(dimension)) {
+ dimension = geometries[i].dimension;
+ } else {
+ goog.asserts.assert(dimension == geometries[i].dimension);
+ }
+ }
/**
* @type {number}
*/
- this.dimension;
-
- /**
- * @type {ol.Extent}
- * @protected
- */
- this.bounds = null;
+ this.dimension = dimension;
};
-goog.inherits(ol.geom.GeometryCollection, ol.geom.Geometry);
-
-
-/**
- * @inheritDoc
- */
-ol.geom.GeometryCollection.prototype.getBounds = function() {
- if (goog.isNull(this.bounds)) {
- var minX,
- minY = minX = Number.POSITIVE_INFINITY,
- maxX,
- maxY = maxX = Number.NEGATIVE_INFINITY,
- components = this.components,
- len = components.length,
- bounds, i;
-
- for (i = 0; i < len; ++i) {
- bounds = components[i].getBounds();
- minX = Math.min(bounds.minX, minX);
- minY = Math.min(bounds.minY, minY);
- maxX = Math.max(bounds.maxX, maxX);
- maxY = Math.max(bounds.maxY, maxY);
- }
- this.bounds = new ol.Extent(minX, minY, maxX, maxY);
- }
- return this.bounds;
-};
+goog.inherits(ol.geom.GeometryCollection, ol.geom.AbstractCollection);
/**
diff --git a/src/ol/geom/linearring.js b/src/ol/geom/linearring.js
index 92d181e6e0..0d2180be87 100644
--- a/src/ol/geom/linearring.js
+++ b/src/ol/geom/linearring.js
@@ -1,20 +1,21 @@
goog.provide('ol.geom.LinearRing');
-goog.require('ol.geom.CoordinateArray');
goog.require('ol.geom.GeometryType');
goog.require('ol.geom.LineString');
+goog.require('ol.geom.SharedVertices');
+goog.require('ol.geom.VertexArray');
/**
* @constructor
* @extends {ol.geom.LineString}
- * @param {ol.geom.CoordinateArray} coordinates Coordinates array (e.g.
- * [[x0, y0], [x1, y1], [x0, y0]]).
+ * @param {ol.geom.VertexArray} coordinates Vertex array (e.g.
+ * [[x0, y0], [x1, y1]]).
+ * @param {ol.geom.SharedVertices=} opt_shared Shared vertices.
*/
-ol.geom.LinearRing = function(coordinates) {
-
- goog.base(this, coordinates);
+ol.geom.LinearRing = function(coordinates, opt_shared) {
+ goog.base(this, coordinates, opt_shared);
/**
* We're intentionally not enforcing that rings be closed right now. This
@@ -30,5 +31,5 @@ goog.inherits(ol.geom.LinearRing, ol.geom.LineString);
* @inheritDoc
*/
ol.geom.LinearRing.prototype.getType = function() {
- return ol.geom.GeometryType.GEOMETRYCOLLECTION;
+ return ol.geom.GeometryType.LINEARRING;
};
diff --git a/src/ol/geom/linestring.js b/src/ol/geom/linestring.js
index 6d8be32f5c..561c973a33 100644
--- a/src/ol/geom/linestring.js
+++ b/src/ol/geom/linestring.js
@@ -2,44 +2,47 @@ goog.provide('ol.geom.LineString');
goog.require('goog.asserts');
goog.require('ol.Extent');
-goog.require('ol.geom.CoordinateArray');
goog.require('ol.geom.Geometry');
goog.require('ol.geom.GeometryType');
+goog.require('ol.geom.SharedVertices');
+goog.require('ol.geom.VertexArray');
/**
* @constructor
* @extends {ol.geom.Geometry}
- * @param {ol.geom.CoordinateArray} coordinates Coordinates array (e.g.
+ * @param {ol.geom.VertexArray} coordinates Vertex array (e.g.
* [[x0, y0], [x1, y1]]).
+ * @param {ol.geom.SharedVertices=} opt_shared Shared vertices.
*/
-ol.geom.LineString = function(coordinates) {
-
+ol.geom.LineString = function(coordinates, opt_shared) {
goog.base(this);
+ goog.asserts.assert(goog.isArray(coordinates[0]));
- // assume the same dimension for all coordinates
- var dimension = coordinates[0].length,
- count = coordinates.length,
- length = count * dimension;
+ var vertices = opt_shared,
+ dimension;
+
+ if (!goog.isDef(vertices)) {
+ dimension = coordinates[0].length;
+ vertices = new ol.geom.SharedVertices({dimension: dimension});
+ }
/**
- * @type {Array}
+ * @type {ol.geom.SharedVertices}
*/
- this.coordinates = new Array(length);
- var i, offset, j;
- for (i = 0; i < count; ++i) {
- goog.asserts.assert(coordinates[i].length === dimension);
- offset = i * dimension;
- for (j = 0; j < dimension; ++j) {
- this.coordinates[offset + j] = coordinates[i][j];
- }
- }
+ this.vertices = vertices;
+
+ /**
+ * @type {string}
+ * @private
+ */
+ this.sharedId_ = vertices.add(coordinates);
/**
* @type {number}
*/
- this.dimension = dimension;
+ this.dimension = vertices.getDimension();
goog.asserts.assert(this.dimension >= 2);
/**
@@ -52,6 +55,45 @@ ol.geom.LineString = function(coordinates) {
goog.inherits(ol.geom.LineString, ol.geom.Geometry);
+/**
+ * Get a vertex coordinate value for the given dimension.
+ * @param {number} index Vertex index.
+ * @param {number} dim Coordinate dimension.
+ * @return {number} The vertex coordinate value.
+ */
+ol.geom.LineString.prototype.get = function(index, dim) {
+ return this.vertices.get(this.sharedId_, index, dim);
+};
+
+
+/**
+ * @inheritDoc
+ * @return {ol.geom.VertexArray} Coordinates array.
+ */
+ol.geom.LineString.prototype.getCoordinates = function() {
+ var count = this.getCount();
+ var coordinates = new Array(count);
+ var vertex;
+ for (var i = 0; i < count; ++i) {
+ vertex = new Array(this.dimension);
+ for (var j = 0; j < this.dimension; ++j) {
+ vertex[j] = this.get(i, j);
+ }
+ coordinates[i] = vertex;
+ }
+ return coordinates;
+};
+
+
+/**
+ * Get the count of vertices in this linestring.
+ * @return {number} The vertex count.
+ */
+ol.geom.LineString.prototype.getCount = function() {
+ return this.vertices.getCount(this.sharedId_);
+};
+
+
/**
* @inheritDoc
*/
@@ -61,14 +103,15 @@ ol.geom.LineString.prototype.getBounds = function() {
minY = minX = Number.POSITIVE_INFINITY,
maxX,
maxY = maxX = Number.NEGATIVE_INFINITY,
- coordinates = this.coordinates,
- len = coordinates.length,
- dim = this.dimension,
+ vertices = this.vertices,
+ id = this.sharedId_,
+ count = vertices.getCount(id),
+ dimension = this.dimension,
x, y, i;
- for (i = 0; i < len; i += dim) {
- x = coordinates[i];
- y = coordinates[i + 1];
+ for (i = 0; i < count; ++i) {
+ x = vertices.get(id, i, 0);
+ y = vertices.get(id, i, 1);
minX = Math.min(minX, x);
minY = Math.min(minY, y);
maxX = Math.max(maxX, x);
@@ -86,3 +129,12 @@ ol.geom.LineString.prototype.getBounds = function() {
ol.geom.LineString.prototype.getType = function() {
return ol.geom.GeometryType.LINESTRING;
};
+
+
+/**
+ * Get the identifier used to mark this line in the shared vertices structure.
+ * @return {string} The identifier.
+ */
+ol.geom.LineString.prototype.getSharedId = function() {
+ return this.sharedId_;
+};
diff --git a/src/ol/geom/multilinestring.js b/src/ol/geom/multilinestring.js
index c9def94fbe..71f99afbe1 100644
--- a/src/ol/geom/multilinestring.js
+++ b/src/ol/geom/multilinestring.js
@@ -1,45 +1,50 @@
goog.provide('ol.geom.MultiLineString');
goog.require('goog.asserts');
-goog.require('ol.geom.CoordinateArray');
-goog.require('ol.geom.GeometryCollection');
+goog.require('ol.geom.AbstractCollection');
goog.require('ol.geom.GeometryType');
goog.require('ol.geom.LineString');
+goog.require('ol.geom.SharedVertices');
+goog.require('ol.geom.VertexArray');
/**
* @constructor
- * @extends {ol.geom.GeometryCollection}
- * @param {Array.} coordinates Coordinates array.
+ * @extends {ol.geom.AbstractCollection}
+ * @param {Array.} coordinates Coordinates array.
+ * @param {ol.geom.SharedVertices=} opt_shared Shared vertices.
*/
-ol.geom.MultiLineString = function(coordinates) {
+ol.geom.MultiLineString = function(coordinates, opt_shared) {
goog.base(this);
+ goog.asserts.assert(goog.isArray(coordinates[0][0]));
- var numParts = coordinates.length,
+ var vertices = opt_shared,
dimension;
+ if (!goog.isDef(vertices)) {
+ // try to get dimension from first vertex in first line
+ dimension = coordinates[0][0].length;
+ vertices = new ol.geom.SharedVertices({dimension: dimension});
+ }
+
+ var numParts = coordinates.length;
+
/**
* @type {Array.}
*/
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].dimension;
- } else {
- goog.asserts.assert(this.components[i].dimension === dimension);
- }
+ this.components[i] = new ol.geom.LineString(coordinates[i], vertices);
}
/**
* @type {number}
*/
- this.dimension = dimension;
- goog.asserts.assert(this.dimension >= 2);
+ this.dimension = vertices.getDimension();
};
-goog.inherits(ol.geom.MultiLineString, ol.geom.GeometryCollection);
+goog.inherits(ol.geom.MultiLineString, ol.geom.AbstractCollection);
/**
@@ -48,3 +53,20 @@ goog.inherits(ol.geom.MultiLineString, ol.geom.GeometryCollection);
ol.geom.MultiLineString.prototype.getType = function() {
return ol.geom.GeometryType.MULTILINESTRING;
};
+
+
+/**
+ * Create a multi-linestring geometry from an array of linestring geometries.
+ *
+ * @param {Array.} geometries Array of geometries.
+ * @param {ol.geom.SharedVertices=} opt_shared Shared vertices.
+ * @return {ol.geom.MultiLineString} A new geometry.
+ */
+ol.geom.MultiLineString.fromParts = function(geometries, opt_shared) {
+ var count = geometries.length;
+ var coordinates = new Array(count);
+ for (var i = 0; i < count; ++i) {
+ coordinates[i] = geometries[i].getCoordinates();
+ }
+ return new ol.geom.MultiLineString(coordinates, opt_shared);
+};
diff --git a/src/ol/geom/multipoint.js b/src/ol/geom/multipoint.js
index e4d632e26d..43c475bfeb 100644
--- a/src/ol/geom/multipoint.js
+++ b/src/ol/geom/multipoint.js
@@ -1,45 +1,55 @@
goog.provide('ol.geom.MultiPoint');
goog.require('goog.asserts');
-goog.require('ol.geom.CoordinateArray');
-goog.require('ol.geom.GeometryCollection');
+goog.require('ol.geom.AbstractCollection');
goog.require('ol.geom.GeometryType');
goog.require('ol.geom.Point');
+goog.require('ol.geom.SharedVertices');
+goog.require('ol.geom.VertexArray');
/**
* @constructor
- * @extends {ol.geom.GeometryCollection}
- * @param {ol.geom.CoordinateArray} coordinates Coordinates array.
+ * @extends {ol.geom.AbstractCollection}
+ * @param {ol.geom.VertexArray} coordinates Coordinates array.
+ * @param {ol.geom.SharedVertices=} opt_shared Shared vertices.
*/
-ol.geom.MultiPoint = function(coordinates) {
+ol.geom.MultiPoint = function(coordinates, opt_shared) {
goog.base(this);
+ goog.asserts.assert(goog.isArray(coordinates[0]));
- var numParts = coordinates.length,
+ var vertices = opt_shared,
dimension;
+ if (!goog.isDef(vertices)) {
+ // try to get dimension from first vertex
+ dimension = coordinates[0].length;
+ vertices = new ol.geom.SharedVertices({dimension: dimension});
+ }
+
+ /**
+ * @type {ol.geom.SharedVertices}
+ */
+ this.vertices = vertices;
+
+ var numParts = coordinates.length;
+
/**
* @type {Array.}
*/
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);
- }
+ this.components[i] = new ol.geom.Point(coordinates[i], vertices);
}
/**
* @type {number}
*/
- this.dimension = dimension;
- goog.asserts.assert(this.dimension >= 2);
+ this.dimension = vertices.getDimension();
};
-goog.inherits(ol.geom.MultiPoint, ol.geom.GeometryCollection);
+goog.inherits(ol.geom.MultiPoint, ol.geom.AbstractCollection);
/**
@@ -48,3 +58,20 @@ goog.inherits(ol.geom.MultiPoint, ol.geom.GeometryCollection);
ol.geom.MultiPoint.prototype.getType = function() {
return ol.geom.GeometryType.MULTIPOINT;
};
+
+
+/**
+ * Create a multi-point geometry from an array of point geometries.
+ *
+ * @param {Array.} geometries Array of geometries.
+ * @param {ol.geom.SharedVertices=} opt_shared Shared vertices.
+ * @return {ol.geom.MultiPoint} A new geometry.
+ */
+ol.geom.MultiPoint.fromParts = function(geometries, opt_shared) {
+ var count = geometries.length;
+ var coordinates = new Array(count);
+ for (var i = 0; i < count; ++i) {
+ coordinates[i] = geometries[i].getCoordinates();
+ }
+ return new ol.geom.MultiPoint(coordinates, opt_shared);
+};
diff --git a/src/ol/geom/multipolygon.js b/src/ol/geom/multipolygon.js
index dcc0ec89c3..b3c87c6175 100644
--- a/src/ol/geom/multipolygon.js
+++ b/src/ol/geom/multipolygon.js
@@ -1,46 +1,51 @@
goog.provide('ol.geom.MultiPolygon');
goog.require('goog.asserts');
-goog.require('ol.geom.CoordinateArray');
-goog.require('ol.geom.GeometryCollection');
+goog.require('ol.geom.AbstractCollection');
goog.require('ol.geom.GeometryType');
goog.require('ol.geom.Polygon');
+goog.require('ol.geom.SharedVertices');
+goog.require('ol.geom.VertexArray');
/**
* @constructor
- * @extends {ol.geom.GeometryCollection}
- * @param {Array.>} coordinates Coordinates
+ * @extends {ol.geom.AbstractCollection}
+ * @param {Array.>} coordinates Coordinates
* array.
+ * @param {ol.geom.SharedVertices=} opt_shared Shared vertices.
*/
-ol.geom.MultiPolygon = function(coordinates) {
+ol.geom.MultiPolygon = function(coordinates, opt_shared) {
goog.base(this);
+ goog.asserts.assert(goog.isArray(coordinates[0][0][0]));
- var numParts = coordinates.length,
+ var vertices = opt_shared,
dimension;
+ if (!goog.isDef(vertices)) {
+ // try to get dimension from first vertex in first ring of the first poly
+ dimension = coordinates[0][0][0].length;
+ vertices = new ol.geom.SharedVertices({dimension: dimension});
+ }
+
+ var numParts = coordinates.length;
+
/**
* @type {Array.}
*/
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].dimension;
- } else {
- goog.asserts.assert(this.components[i].dimension === dimension);
- }
+ this.components[i] = new ol.geom.Polygon(coordinates[i], vertices);
}
/**
* @type {number}
*/
- this.dimension = dimension;
- goog.asserts.assert(this.dimension >= 2);
+ this.dimension = vertices.getDimension();
};
-goog.inherits(ol.geom.MultiPolygon, ol.geom.GeometryCollection);
+goog.inherits(ol.geom.MultiPolygon, ol.geom.AbstractCollection);
/**
@@ -49,3 +54,20 @@ goog.inherits(ol.geom.MultiPolygon, ol.geom.GeometryCollection);
ol.geom.MultiPolygon.prototype.getType = function() {
return ol.geom.GeometryType.MULTIPOLYGON;
};
+
+
+/**
+ * Create a multi-polygon geometry from an array of polygon geometries.
+ *
+ * @param {Array.} geometries Array of geometries.
+ * @param {ol.geom.SharedVertices=} opt_shared Shared vertices.
+ * @return {ol.geom.MultiPolygon} A new geometry.
+ */
+ol.geom.MultiPolygon.fromParts = function(geometries, opt_shared) {
+ var count = geometries.length;
+ var coordinates = new Array(count);
+ for (var i = 0; i < count; ++i) {
+ coordinates[i] = geometries[i].getCoordinates();
+ }
+ return new ol.geom.MultiPolygon(coordinates, opt_shared);
+};
diff --git a/src/ol/geom/point.js b/src/ol/geom/point.js
index 59790ce6ec..621a6e4f13 100644
--- a/src/ol/geom/point.js
+++ b/src/ol/geom/point.js
@@ -2,30 +2,45 @@ goog.provide('ol.geom.Point');
goog.require('goog.asserts');
goog.require('ol.Extent');
-goog.require('ol.geom.Coordinate');
goog.require('ol.geom.Geometry');
goog.require('ol.geom.GeometryType');
+goog.require('ol.geom.SharedVertices');
+goog.require('ol.geom.Vertex');
/**
* @constructor
* @extends {ol.geom.Geometry}
- * @param {ol.geom.Coordinate} coordinates Coordinates array (e.g. [x, y]).
+ * @param {ol.geom.Vertex} coordinates Coordinates array (e.g. [x, y]).
+ * @param {ol.geom.SharedVertices=} opt_shared Shared vertices.
*/
-ol.geom.Point = function(coordinates) {
-
+ol.geom.Point = function(coordinates, opt_shared) {
goog.base(this);
+ var vertices = opt_shared,
+ dimension;
+
+ if (!goog.isDef(vertices)) {
+ dimension = coordinates.length;
+ vertices = new ol.geom.SharedVertices({dimension: dimension});
+ }
+
/**
- * @type {Array}
+ * @type {ol.geom.SharedVertices}
*/
- this.coordinates = coordinates;
+ this.vertices = vertices;
+
+ /**
+ * @type {string}
+ * @private
+ */
+ this.sharedId_ = vertices.add([coordinates]);
/**
* @type {number}
*/
- this.dimension = coordinates.length;
+ this.dimension = vertices.getDimension();
goog.asserts.assert(this.dimension >= 2);
/**
@@ -38,22 +53,53 @@ ol.geom.Point = function(coordinates) {
goog.inherits(ol.geom.Point, ol.geom.Geometry);
+/**
+ * @param {number} dim Coordinate dimension.
+ * @return {number} The coordinate value.
+ */
+ol.geom.Point.prototype.get = function(dim) {
+ return this.vertices.get(this.sharedId_, 0, dim);
+};
+
+
/**
* @inheritDoc
*/
ol.geom.Point.prototype.getBounds = function() {
if (goog.isNull(this.bounds_)) {
- var x = this.coordinates[0],
- y = this.coordinates[1];
+ var x = this.get(0),
+ y = this.get(1);
this.bounds_ = new ol.Extent(x, y, x, y);
}
return this.bounds_;
};
+/**
+ * @inheritDoc
+ * @return {ol.geom.Vertex} Coordinates array.
+ */
+ol.geom.Point.prototype.getCoordinates = function() {
+ var coordinates = new Array(this.dimension);
+ for (var i = 0; i < this.dimension; ++i) {
+ coordinates[i] = this.get(i);
+ }
+ return coordinates;
+};
+
+
/**
* @inheritDoc
*/
ol.geom.Point.prototype.getType = function() {
return ol.geom.GeometryType.POINT;
};
+
+
+/**
+ * Get the identifier used to mark this point in the shared vertices structure.
+ * @return {string} The identifier.
+ */
+ol.geom.Point.prototype.getSharedId = function() {
+ return this.sharedId_;
+};
diff --git a/src/ol/geom/polygon.js b/src/ol/geom/polygon.js
index c3c3e88a76..c38b4aa57a 100644
--- a/src/ol/geom/polygon.js
+++ b/src/ol/geom/polygon.js
@@ -2,43 +2,53 @@ goog.provide('ol.geom.Polygon');
goog.require('goog.asserts');
goog.require('ol.Extent');
-goog.require('ol.geom.CoordinateArray');
goog.require('ol.geom.Geometry');
goog.require('ol.geom.GeometryType');
goog.require('ol.geom.LinearRing');
+goog.require('ol.geom.SharedVertices');
+goog.require('ol.geom.VertexArray');
/**
* @constructor
* @extends {ol.geom.Geometry}
- * @param {Array.} coordinates Array of rings. First
+ * @param {Array.} coordinates Array of rings. First
* is outer, any remaining are inner.
+ * @param {ol.geom.SharedVertices=} opt_shared Shared vertices.
*/
-ol.geom.Polygon = function(coordinates) {
-
+ol.geom.Polygon = function(coordinates, opt_shared) {
goog.base(this);
+ goog.asserts.assert(goog.isArray(coordinates[0][0]));
- var numRings = coordinates.length,
+ var vertices = opt_shared,
dimension;
+ if (!goog.isDef(vertices)) {
+ // try to get dimension from first vertex in first ring
+ dimension = coordinates[0][0].length;
+ vertices = new ol.geom.SharedVertices({dimension: dimension});
+ }
+
+ /**
+ * @type {ol.geom.SharedVertices}
+ */
+ this.vertices = vertices;
+
+ var numRings = coordinates.length;
+
/**
* @type {Array.}
*/
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);
- }
+ this.rings[i] = new ol.geom.LinearRing(coordinates[i], vertices);
}
/**
* @type {number}
*/
- this.dimension = dimension;
+ this.dimension = vertices.getDimension();
goog.asserts.assert(this.dimension >= 2);
/**
@@ -59,6 +69,19 @@ ol.geom.Polygon.prototype.getBounds = function() {
};
+/**
+ * @return {Array.} Coordinates array.
+ */
+ol.geom.Polygon.prototype.getCoordinates = function() {
+ var count = this.rings.length;
+ var coordinates = new Array(count);
+ for (var i = 0; i < count; ++i) {
+ coordinates[i] = this.rings[i].getCoordinates();
+ }
+ return coordinates;
+};
+
+
/**
* @inheritDoc
*/
diff --git a/src/ol/geom/sharedvertices.js b/src/ol/geom/sharedvertices.js
new file mode 100644
index 0000000000..39ff922027
--- /dev/null
+++ b/src/ol/geom/sharedvertices.js
@@ -0,0 +1,195 @@
+goog.provide('ol.geom.SharedVertices');
+
+goog.require('goog.asserts');
+goog.require('ol.geom.Vertex');
+goog.require('ol.geom.VertexArray');
+
+
+/**
+ * @typedef {{dimension: (number),
+ * offset: (ol.geom.Vertex|undefined)}}
+ */
+ol.geom.SharedVerticesOptions;
+
+
+
+/**
+ * Provides methods for dealing with shared, flattened arrays of vertices.
+ *
+ * @constructor
+ * @param {ol.geom.SharedVerticesOptions=} opt_options Shared vertices options.
+ */
+ol.geom.SharedVertices = function(opt_options) {
+ var options = goog.isDef(opt_options) ? opt_options : {};
+
+ /**
+ * @type {number}
+ * @private
+ */
+ this.counter_ = 0;
+
+ /**
+ * @type {Array.}
+ */
+ this.coordinates = [];
+
+ /**
+ * Number of dimensions per vertex. Default is 2.
+ * @type {number}
+ * @private
+ */
+ this.dimension_ = options.dimension || 2;
+
+ /**
+ * Vertex offset.
+ * @type {Array.}
+ * @private
+ */
+ this.offset_ = options.offset || null;
+ goog.asserts.assert(goog.isNull(this.offset_) ||
+ this.offset_.length === this.dimension_);
+
+ /**
+ * @type {Object}
+ * @private
+ */
+ this.lookup_ = {};
+
+ /**
+ * @type {Array.}
+ * @private
+ */
+ this.ids_ = [];
+
+};
+
+
+/**
+ * Adds a vertex array to the shared coordinate array.
+ * @param {ol.geom.VertexArray} vertices Array of vertices.
+ * @return {string} Index used to reference the added vertex array.
+ */
+ol.geom.SharedVertices.prototype.add = function(vertices) {
+ var start = this.coordinates.length;
+ var offset = this.offset_;
+ var dimension = this.dimension_;
+ var count = vertices.length;
+ var vertex, index;
+ for (var i = 0; i < count; ++i) {
+ vertex = vertices[i];
+ goog.asserts.assert(vertex.length == dimension);
+ if (!offset) {
+ Array.prototype.push.apply(this.coordinates, vertex);
+ } else {
+ index = start + (i * dimension);
+ for (var j = 0; j < dimension; ++j) {
+ this.coordinates[index + j] = vertex[j] - offset[j];
+ }
+ }
+ }
+ var id = this.getId_();
+ var idIndex = this.ids_.push(id) - 1;
+ this.lookup_[id] = {
+ idIndex: idIndex,
+ start: start,
+ count: count
+ };
+ return id;
+};
+
+
+/**
+ * @param {string} id The vertex array identifier (returned by add).
+ * @param {number} index The vertex index.
+ * @param {number} dim The coordinate dimension.
+ * @return {number} The coordinate value.
+ */
+ol.geom.SharedVertices.prototype.get = function(id, index, dim) {
+ goog.asserts.assert(dim <= this.dimension_);
+ goog.asserts.assert(this.lookup_.hasOwnProperty(id));
+ goog.asserts.assert(index < this.lookup_[id].count);
+ var start = this.lookup_[id].start;
+ var value = this.coordinates[start + (index * this.dimension_) + dim];
+ if (this.offset_) {
+ value += this.offset_[dim];
+ }
+ return value;
+};
+
+
+/**
+ * @param {string} id The vertex array identifier (returned by add).
+ * @return {number} The number of vertices in the referenced array.
+ */
+ol.geom.SharedVertices.prototype.getCount = function(id) {
+ goog.asserts.assert(this.lookup_.hasOwnProperty(id));
+ return this.lookup_[id].count;
+};
+
+
+/**
+ * Gets an identifier that is unique for this instance.
+ * @return {string} Identifier.
+ * @private
+ */
+ol.geom.SharedVertices.prototype.getId_ = function() {
+ return String(++this.counter_);
+};
+
+
+/**
+ * @return {number} The dimension of each vertex in the array.
+ */
+ol.geom.SharedVertices.prototype.getDimension = function() {
+ return this.dimension_;
+};
+
+
+/**
+ * @return {Array.} The offset array for vertex coordinates (or null).
+ */
+ol.geom.SharedVertices.prototype.getOffset = function() {
+ return this.offset_;
+};
+
+
+/**
+ * @param {string} id The vertex array identifier (returned by add).
+ * @return {number} The start index in the shared vertices array.
+ */
+ol.geom.SharedVertices.prototype.getStart = function(id) {
+ goog.asserts.assert(this.lookup_.hasOwnProperty(id));
+ return this.lookup_[id].start;
+};
+
+
+/**
+ * @param {number} id The vertex array identifier (returned by add).
+ * @return {ol.geom.VertexArray} The removed vertex array.
+ */
+ol.geom.SharedVertices.prototype.remove = function(id) {
+ goog.asserts.assert(this.lookup_.hasOwnProperty(id));
+ var info = this.lookup_[id];
+ var dimension = this.dimension_;
+ var length = info.count * dimension;
+ var removed = this.coordinates.splice(info.start, length);
+ var offset = this.offset_;
+ var array = new Array(info.count);
+ var vertex;
+ for (var i = 0; i < info.count; ++i) {
+ vertex = new Array(dimension);
+ for (var j = 0; j < dimension; ++j) {
+ vertex[j] = removed[(i * dimension) + j] + (offset ? offset[j] : 0);
+ }
+ array[i] = vertex;
+ }
+ delete this.lookup_[id];
+ this.ids_.splice(info.idIndex, 1);
+ var afterInfo;
+ for (var k = info.idIndex, kk = this.ids_.length; k < kk; ++k) {
+ afterInfo = this.lookup_[this.ids_[k]];
+ afterInfo.idIndex -= 1;
+ afterInfo.start -= length;
+ }
+ return array;
+};
diff --git a/src/ol/renderer/canvas/canvasrenderer.js b/src/ol/renderer/canvas/canvasrenderer.js
index 7f3d17fd1d..4f0d0b7fb4 100644
--- a/src/ol/renderer/canvas/canvasrenderer.js
+++ b/src/ol/renderer/canvas/canvasrenderer.js
@@ -8,6 +8,9 @@ goog.require('ol.Pixel');
goog.require('ol.canvas');
goog.require('ol.geom.Geometry');
goog.require('ol.geom.GeometryType');
+goog.require('ol.geom.LineString');
+goog.require('ol.geom.Point');
+goog.require('ol.geom.Polygon');
goog.require('ol.style.LineLiteral');
goog.require('ol.style.PointLiteral');
goog.require('ol.style.PolygonLiteral');
@@ -108,20 +111,18 @@ ol.renderer.canvas.Renderer.prototype.renderLineStringFeatures_ =
function(features, symbolizer) {
var context = this.context_,
- i, ii, line, coords, dim, j, jj, x, y;
+ i, ii, line, dim, j, jj, x, y;
context.globalAlpha = symbolizer.opacity;
context.strokeStyle = symbolizer.strokeStyle;
context.lineWidth = symbolizer.strokeWidth * this.inverseScale_;
context.beginPath();
-
for (i = 0, ii = features.length; i < ii; ++i) {
- line = features[i].getGeometry();
+ line = /** @type {ol.geom.LineString} */ features[i].getGeometry();
dim = line.dimension;
- coords = line.coordinates;
- for (j = 0, jj = coords.length; j < jj; j += dim) {
- x = coords[j];
- y = coords[j + 1];
+ for (j = 0, jj = line.getCount(); j < jj; ++j) {
+ x = line.get(j, 0);
+ y = line.get(j, 1);
if (j === 0) {
context.moveTo(x, y);
} else {
@@ -143,7 +144,7 @@ ol.renderer.canvas.Renderer.prototype.renderPointFeatures_ =
function(features, symbolizer) {
var context = this.context_,
- canvas, i, ii, coords, vec;
+ canvas, i, ii, point, vec;
if (symbolizer instanceof ol.style.ShapeLiteral) {
canvas = ol.renderer.canvas.Renderer.renderShape(symbolizer);
@@ -156,9 +157,9 @@ ol.renderer.canvas.Renderer.prototype.renderPointFeatures_ =
context.setTransform(1, 0, 0, 1, -mid, -mid);
context.globalAlpha = 1;
for (i = 0, ii = features.length; i < ii; ++i) {
- coords = features[i].getGeometry().coordinates;
+ point = /** @type {ol.geom.Point} */ features[i].getGeometry();
vec = goog.vec.Mat4.multVec3(
- this.transform_, [coords[0], coords[1], 0], []);
+ this.transform_, [point.get(0), point.get(1), 0], []);
context.drawImage(canvas, vec[0], vec[1]);
}
context.restore();
@@ -176,7 +177,7 @@ ol.renderer.canvas.Renderer.prototype.renderPolygonFeatures_ =
var context = this.context_,
strokeStyle = symbolizer.strokeStyle,
fillStyle = symbolizer.fillStyle,
- i, ii, poly, rings, numRings, coords, dim, j, jj, x, y;
+ i, ii, poly, rings, numRings, ring, dim, j, jj, x, y;
context.globalAlpha = symbolizer.opacity;
if (strokeStyle) {
@@ -196,7 +197,7 @@ ol.renderer.canvas.Renderer.prototype.renderPolygonFeatures_ =
*/
context.beginPath();
for (i = 0, ii = features.length; i < ii; ++i) {
- poly = features[i].getGeometry();
+ poly = /** @type {ol.geom.Polygon} */ features[i].getGeometry();
dim = poly.dimension;
rings = poly.rings;
numRings = rings.length;
@@ -205,10 +206,10 @@ ol.renderer.canvas.Renderer.prototype.renderPolygonFeatures_ =
// TODO: use sketch canvas to render outer and punch holes for inner rings
throw new Error('Rendering holes not implemented');
} else {
- coords = rings[0].coordinates;
- for (j = 0, jj = coords.length; j < jj; j += dim) {
- x = coords[j];
- y = coords[j + 1];
+ ring = rings[0];
+ for (j = 0, jj = ring.getCount(); j < jj; ++j) {
+ x = ring.get(j, 0);
+ y = ring.get(j, 1);
if (j === 0) {
context.moveTo(x, y);
} else {
diff --git a/test/spec/ol/geom/geometrycollection.test.js b/test/spec/ol/geom/geometrycollection.test.js
new file mode 100644
index 0000000000..69246431de
--- /dev/null
+++ b/test/spec/ol/geom/geometrycollection.test.js
@@ -0,0 +1,79 @@
+goog.provide('ol.test.geom.GeometryCollection');
+
+describe('ol.geom.GeometryCollection', 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 geometry collection from an array of geometries', function() {
+ var point = new ol.geom.Point([10, 20]);
+ var line = new ol.geom.LineString([[10, 20], [30, 40]]);
+ var poly = new ol.geom.Polygon([outer, inner1, inner2]);
+ var multi = new ol.geom.GeometryCollection([point, line, poly]);
+ expect(multi).toBeA(ol.geom.GeometryCollection);
+ expect(multi).toBeA(ol.geom.Geometry);
+ });
+
+ });
+
+ describe('#components', function() {
+
+ it('is an array of geometries', function() {
+ var point = new ol.geom.Point([10, 20]);
+ var line = new ol.geom.LineString([[10, 20], [30, 40]]);
+ var poly = new ol.geom.Polygon([outer, inner1, inner2]);
+ var multi = new ol.geom.GeometryCollection([point, line, poly]);
+
+ expect(multi.components.length).toBe(3);
+ expect(multi.components[0]).toBeA(ol.geom.Point);
+ expect(multi.components[1]).toBeA(ol.geom.LineString);
+ expect(multi.components[2]).toBeA(ol.geom.Polygon);
+ });
+
+ });
+
+ describe('#dimension', function() {
+
+ it('can be 2', function() {
+ var point = new ol.geom.Point([10, 20]);
+ var line = new ol.geom.LineString([[10, 20], [30, 40]]);
+ var poly = new ol.geom.Polygon([outer, inner1, inner2]);
+ var multi = new ol.geom.GeometryCollection([point, line, poly]);
+ expect(multi.dimension).toBe(2);
+ });
+
+ it('can be 3', function() {
+ var multi = new ol.geom.GeometryCollection([
+ new ol.geom.Point([30, 40, 50])
+ ]);
+ expect(multi.dimension).toBe(3);
+ });
+
+ });
+
+ describe('#getBounds()', function() {
+
+ it('returns the bounding extent', function() {
+ var point = new ol.geom.Point([10, 2]);
+ var line = new ol.geom.LineString([[1, 20], [30, 40]]);
+ var multi = new ol.geom.GeometryCollection([point, line]);
+ var bounds = multi.getBounds();
+ expect(bounds.minX).toBe(1);
+ expect(bounds.minY).toBe(2);
+ expect(bounds.maxX).toBe(30);
+ expect(bounds.maxY).toBe(40);
+ });
+
+ });
+
+});
+
+goog.require('ol.geom.Geometry');
+goog.require('ol.geom.GeometryCollection');
+goog.require('ol.geom.LineString');
+goog.require('ol.geom.Point');
+goog.require('ol.geom.Polygon');
diff --git a/test/spec/ol/geom/linearring.test.js b/test/spec/ol/geom/linearring.test.js
index 117289b3fe..54b0ff0d37 100644
--- a/test/spec/ol/geom/linearring.test.js
+++ b/test/spec/ol/geom/linearring.test.js
@@ -17,20 +17,6 @@ describe('ol.geom.LinearRing', function() {
});
- describe('#coordinates', function() {
-
- it('is an array', function() {
- var ring = new ol.geom.LinearRing([[10, 20], [30, 40]]);
-
- 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() {
@@ -45,6 +31,14 @@ describe('ol.geom.LinearRing', function() {
});
+ describe('#getCoordinates()', function() {
+
+ it('is an array', function() {
+ var ring = new ol.geom.LinearRing([[10, 20], [30, 40]]);
+ expect(ring.getCoordinates()).toEqual([[10, 20], [30, 40]]);
+ });
+
+ });
});
diff --git a/test/spec/ol/geom/linestring.test.js b/test/spec/ol/geom/linestring.test.js
index 654ffcf208..25fe5ca0d1 100644
--- a/test/spec/ol/geom/linestring.test.js
+++ b/test/spec/ol/geom/linestring.test.js
@@ -16,18 +16,12 @@ describe('ol.geom.LineString', function() {
}).toThrow();
});
- });
-
- describe('#coordinates', function() {
-
- it('is an array', function() {
- var line = new ol.geom.LineString([[10, 20], [30, 40]]);
-
- 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);
+ it('accepts shared vertices', function() {
+ var vertices = new ol.geom.SharedVertices();
+ var l1 = new ol.geom.LineString([[10, 20], [30, 40]], vertices);
+ var l2 = new ol.geom.LineString([[50, 60], [70, 80]], vertices);
+ expect(l1.getCoordinates()).toEqual([[10, 20], [30, 40]]);
+ expect(l2.getCoordinates()).toEqual([[50, 60], [70, 80]]);
});
});
@@ -59,8 +53,51 @@ describe('ol.geom.LineString', function() {
});
+ describe('#getCoordinates', function() {
+
+ it('returns an array', function() {
+ var line = new ol.geom.LineString([[10, 20], [30, 40]]);
+ expect(line.getCoordinates()).toEqual([[10, 20], [30, 40]]);
+ });
+
+ });
+
+ describe('#getSharedId()', function() {
+
+ it('returns identifiers', function() {
+ var vertices = new ol.geom.SharedVertices();
+
+ var l1 = new ol.geom.LineString([[10, 20], [30, 40]], vertices);
+ var l2 = new ol.geom.LineString(
+ [[50, 60], [70, 80], [90, 100]], vertices);
+
+ var id1 = l1.getSharedId();
+ var id2 = l2.getSharedId();
+
+ expect(vertices.coordinates).toEqual(
+ [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]);
+
+ expect(vertices.getStart(id1)).toBe(0);
+ expect(vertices.getCount(id1)).toBe(2);
+ expect(vertices.get(id1, 0, 0)).toBe(10);
+ expect(vertices.get(id1, 0, 1)).toBe(20);
+ expect(vertices.get(id1, 1, 0)).toBe(30);
+ expect(vertices.get(id1, 1, 1)).toBe(40);
+
+ expect(vertices.getStart(id2)).toBe(4);
+ expect(vertices.getCount(id2)).toBe(3);
+ expect(vertices.get(id2, 0, 0)).toBe(50);
+ expect(vertices.get(id2, 0, 1)).toBe(60);
+ expect(vertices.get(id2, 1, 0)).toBe(70);
+ expect(vertices.get(id2, 1, 1)).toBe(80);
+ expect(vertices.get(id2, 2, 0)).toBe(90);
+ expect(vertices.get(id2, 2, 1)).toBe(100);
+ });
+
+ });
});
goog.require('ol.geom.Geometry');
goog.require('ol.geom.LineString');
+goog.require('ol.geom.SharedVertices');
diff --git a/test/spec/ol/geom/multilinestring.test.js b/test/spec/ol/geom/multilinestring.test.js
index 356a70fc92..8bca72fa5c 100644
--- a/test/spec/ol/geom/multilinestring.test.js
+++ b/test/spec/ol/geom/multilinestring.test.js
@@ -68,6 +68,19 @@ describe('ol.geom.MultiLineString', function() {
});
+ describe('#getCoordinates', function() {
+
+ it('returns an array', function() {
+ var coordinates = [
+ [[10, 20], [30, 40]],
+ [[20, 30], [40, 50]]
+ ];
+ var multi = new ol.geom.MultiLineString(coordinates);
+ expect(multi.getCoordinates()).toEqual(coordinates);
+ });
+
+ });
+
});
goog.require('ol.geom.Geometry');
diff --git a/test/spec/ol/geom/multipoint.test.js b/test/spec/ol/geom/multipoint.test.js
index 0e1c641ff2..d373e6031d 100644
--- a/test/spec/ol/geom/multipoint.test.js
+++ b/test/spec/ol/geom/multipoint.test.js
@@ -58,6 +58,15 @@ describe('ol.geom.MultiPoint', function() {
});
+ describe('#getCoordinates', function() {
+
+ it('returns an array', function() {
+ var multi = new ol.geom.MultiPoint([[10, 20], [30, 40]]);
+ expect(multi.getCoordinates()).toEqual([[10, 20], [30, 40]]);
+ });
+
+ });
+
});
goog.require('ol.geom.Geometry');
diff --git a/test/spec/ol/geom/multipolygon.test.js b/test/spec/ol/geom/multipolygon.test.js
index 0dd9dd9a80..cd2ad19793 100644
--- a/test/spec/ol/geom/multipolygon.test.js
+++ b/test/spec/ol/geom/multipolygon.test.js
@@ -71,6 +71,20 @@ describe('ol.geom.MultiPolygon', function() {
});
+ describe('#getCoordinates', function() {
+
+ it('returns an array', function() {
+ var coordinates = [
+ [outer1, inner1a, inner1b],
+ [outer2]
+ ];
+ var multi = new ol.geom.MultiPolygon(coordinates);
+ expect(multi.getCoordinates()).toEqual(coordinates);
+ });
+
+ });
+
+
});
goog.require('ol.geom.Geometry');
diff --git a/test/spec/ol/geom/point.test.js b/test/spec/ol/geom/point.test.js
index b4276cfa45..5f8784135a 100644
--- a/test/spec/ol/geom/point.test.js
+++ b/test/spec/ol/geom/point.test.js
@@ -10,6 +10,16 @@ describe('ol.geom.Point', function() {
expect(point).toBeA(ol.geom.Geometry);
});
+ it('accepts shared vertices', function() {
+ var vertices = new ol.geom.SharedVertices();
+ var p1 = new ol.geom.Point([10, 20], vertices);
+ var p2 = new ol.geom.Point([30, 40], vertices);
+ var p3 = new ol.geom.Point([50, 60], vertices);
+ expect(p1.getCoordinates()).toEqual([10, 20]);
+ expect(p2.getCoordinates()).toEqual([30, 40]);
+ expect(p3.getCoordinates()).toEqual([50, 60]);
+ });
+
it('throws when given with insufficient dimensions', function() {
expect(function() {
var point = new ol.geom.Point([1]);
@@ -18,19 +28,6 @@ describe('ol.geom.Point', function() {
});
- describe('#coordinates', function() {
-
- it('is an array', function() {
- var point = new ol.geom.Point([10, 20]);
-
- 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() {
@@ -58,7 +55,52 @@ describe('ol.geom.Point', function() {
});
+ describe('#getCoordinates()', function() {
+
+ it('returns an array', function() {
+ var point = new ol.geom.Point([10, 20]);
+ expect(point.getCoordinates()).toEqual([10, 20]);
+ });
+
+ });
+
+
+ describe('#getSharedId()', function() {
+
+ it('returns identifiers', function() {
+ var vertices = new ol.geom.SharedVertices();
+
+ var p1 = new ol.geom.Point([10, 20], vertices);
+ var p2 = new ol.geom.Point([30, 40], vertices);
+ var p3 = new ol.geom.Point([50, 60], vertices);
+
+ var id1 = p1.getSharedId();
+ var id2 = p2.getSharedId();
+ var id3 = p3.getSharedId();
+
+ expect(vertices.coordinates).toEqual(
+ [10, 20, 30, 40, 50, 60]);
+
+ expect(vertices.getStart(id1)).toBe(0);
+ expect(vertices.getCount(id1)).toBe(1);
+ expect(vertices.get(id1, 0, 0)).toBe(10);
+ expect(vertices.get(id1, 0, 1)).toBe(20);
+
+ expect(vertices.getStart(id2)).toBe(2);
+ expect(vertices.getCount(id2)).toBe(1);
+ expect(vertices.get(id2, 0, 0)).toBe(30);
+ expect(vertices.get(id2, 0, 1)).toBe(40);
+
+ expect(vertices.getStart(id3)).toBe(4);
+ expect(vertices.getCount(id3)).toBe(1);
+ expect(vertices.get(id3, 0, 0)).toBe(50);
+ expect(vertices.get(id3, 0, 1)).toBe(60);
+ });
+
+ });
+
});
goog.require('ol.geom.Geometry');
goog.require('ol.geom.Point');
+goog.require('ol.geom.SharedVertices');
diff --git a/test/spec/ol/geom/polygon.test.js b/test/spec/ol/geom/polygon.test.js
index 591b896643..199c0df9ec 100644
--- a/test/spec/ol/geom/polygon.test.js
+++ b/test/spec/ol/geom/polygon.test.js
@@ -1,4 +1,4 @@
-gooog.require('ol.test.geom.Polygon');
+goog.provide('ol.test.geom.Polygon');
describe('ol.geom.Polygon', function() {
@@ -20,6 +20,16 @@ describe('ol.geom.Polygon', function() {
}).toThrow();
});
+ it('accepts shared vertices', function() {
+ var vertices = new ol.geom.SharedVertices();
+ var p1 = new ol.geom.Polygon([outer], vertices);
+ var p2 = new ol.geom.Polygon([outer, inner1], vertices);
+ var p3 = new ol.geom.Polygon([outer, inner2], vertices);
+ expect(p1.getCoordinates()).toEqual([outer]);
+ expect(p2.getCoordinates()).toEqual([outer, inner1]);
+ expect(p3.getCoordinates()).toEqual([outer, inner2]);
+ });
+
});
describe('#rings', function() {
@@ -62,8 +72,17 @@ describe('ol.geom.Polygon', function() {
});
+ describe('#getCoordinates()', function() {
+
+ it('returns an array', function() {
+ var poly = new ol.geom.Polygon([outer, inner1, inner2]);
+ expect(poly.getCoordinates()).toEqual([outer, inner1, inner2]);
+ });
+
+ });
});
goog.require('ol.geom.Geometry');
goog.require('ol.geom.Polygon');
+goog.require('ol.geom.SharedVertices');
diff --git a/test/spec/ol/geom/sharedvertices.test.js b/test/spec/ol/geom/sharedvertices.test.js
new file mode 100644
index 0000000000..c007c39205
--- /dev/null
+++ b/test/spec/ol/geom/sharedvertices.test.js
@@ -0,0 +1,195 @@
+goog.provide('ol.test.geom.SharedVertices');
+
+describe('ol.geom.SharedVertices', function() {
+
+ describe('constructor', function() {
+ it('creates an instance', function() {
+ var vertices = new ol.geom.SharedVertices();
+ expect(vertices).toBeA(ol.geom.SharedVertices);
+ });
+
+ it('accepts options', function() {
+ var vertices = new ol.geom.SharedVertices({
+ dimension: 4,
+ offset: [1, 2, 3, 4]
+ });
+
+ expect(vertices.getDimension()).toBe(4);
+ expect(vertices.getOffset()).toEqual([1, 2, 3, 4]);
+ });
+ });
+
+ describe('offset option', function() {
+ it('offsets the internally stored vertex coordinates', function() {
+ var vertices = new ol.geom.SharedVertices({offset: [3, -1]});
+ vertices.add([[3, -1], [0, 0]]);
+ vertices.add([[10, 20]]);
+ expect(vertices.coordinates).toEqual([0, 0, -3, 1, 7, 21]);
+ });
+ });
+
+ describe('#add()', function() {
+ it('adds vertex arrays to the shared coordinates', function() {
+ var vertices = new ol.geom.SharedVertices();
+ expect(vertices.coordinates.length).toBe(0);
+
+ vertices.add([[1, 2], [3, 4]]);
+ expect(vertices.coordinates).toEqual([1, 2, 3, 4]);
+
+ vertices.add([[5, 6]]);
+ expect(vertices.coordinates).toEqual([1, 2, 3, 4, 5, 6]);
+ });
+
+ it('returns an identifier for coordinate access', function() {
+ var vertices = new ol.geom.SharedVertices();
+ var id = vertices.add([[1, 2], [3, 4]]);
+ expect(typeof id).toBe('string');
+ });
+ });
+
+ describe('#get()', function() {
+ it('provides access to vertex coordinates', function() {
+ var vertices = new ol.geom.SharedVertices();
+ var first = vertices.add([[1, 2], [3, 4]]);
+ var second = vertices.add([[5, 6]]);
+
+ expect(vertices.get(first, 0, 0)).toBe(1);
+ expect(vertices.get(first, 0, 1)).toBe(2);
+ expect(vertices.get(first, 1, 0)).toBe(3);
+ expect(vertices.get(first, 1, 1)).toBe(4);
+ expect(vertices.get(second, 0, 0)).toBe(5);
+ expect(vertices.get(second, 0, 1)).toBe(6);
+ });
+
+ it('works for non-2d vertices', function() {
+ var vertices = new ol.geom.SharedVertices({dimension: 3});
+ var id = vertices.add([[1, 2, 3], [4, 5, 6]]);
+
+ expect(vertices.get(id, 0, 0)).toBe(1);
+ expect(vertices.get(id, 0, 1)).toBe(2);
+ expect(vertices.get(id, 0, 2)).toBe(3);
+ expect(vertices.get(id, 1, 0)).toBe(4);
+ expect(vertices.get(id, 1, 1)).toBe(5);
+ expect(vertices.get(id, 1, 2)).toBe(6);
+ });
+
+ it('works when an offset is provided', function() {
+ var vertices = new ol.geom.SharedVertices({offset: [3, 3]});
+ var id = vertices.add([[1, 2], [3, 4], [5, 6]]);
+
+ expect(vertices.get(id, 0, 0)).toBe(1);
+ expect(vertices.get(id, 0, 1)).toBe(2);
+ expect(vertices.get(id, 1, 0)).toBe(3);
+ expect(vertices.get(id, 1, 1)).toBe(4);
+ expect(vertices.get(id, 2, 0)).toBe(5);
+ expect(vertices.get(id, 2, 1)).toBe(6);
+ });
+
+ });
+
+ describe('#getCount()', function() {
+ it('returns the length of an identified vertex array', function() {
+ var vertices = new ol.geom.SharedVertices();
+ var first = vertices.add([[2, 3], [3, 4], [4, 5]]);
+ var second = vertices.add([[5, 6], [6, 6]]);
+
+ expect(vertices.getCount(first)).toBe(3);
+ expect(vertices.getCount(second)).toBe(2);
+ });
+ });
+
+ describe('#getDimension()', function() {
+ it('returns 2 by default', function() {
+ var vertices = new ol.geom.SharedVertices();
+ expect(vertices.getDimension()).toBe(2);
+ });
+
+ it('returns the dimension provided to the constructor', function() {
+ var vertices = new ol.geom.SharedVertices({dimension: 10});
+ expect(vertices.getDimension()).toBe(10);
+ });
+ });
+
+ describe('#getOffset()', function() {
+ it('returns null by default', function() {
+ var vertices = new ol.geom.SharedVertices();
+ expect(vertices.getOffset()).toBeNull();
+ });
+
+ it('returns the offset provided to the constructor', function() {
+ var vertices = new ol.geom.SharedVertices({offset: [1, 2]});
+ expect(vertices.getOffset()).toEqual([1, 2]);
+ });
+ });
+
+ describe('#getStart()', function() {
+ it('returns the start of the identified vertex array', function() {
+ var vertices = new ol.geom.SharedVertices();
+ var first = vertices.add([[1, 2]]);
+ var second = vertices.add([[3, 4], [5, 6]]);
+ var third = vertices.add([[7, 8], [9, 10], [11, 12]]);
+
+ expect(vertices.coordinates).toEqual(
+ [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
+ expect(vertices.getStart(first)).toBe(0);
+ expect(vertices.getStart(second)).toBe(2);
+ expect(vertices.getStart(third)).toBe(6);
+ });
+ });
+
+ describe('#remove()', function() {
+ it('removes a vertex array', function() {
+ var vertices = new ol.geom.SharedVertices();
+ var first = vertices.add([[1, 2], [3, 4]]);
+ var second = vertices.add([[5, 6]]);
+ var third = vertices.add([[7, 8], [9, 10], [11, 12]]);
+
+ expect(vertices.remove(second)).toEqual([[5, 6]]);
+ expect(vertices.coordinates).toEqual([1, 2, 3, 4, 7, 8, 9, 10, 11, 12]);
+
+ expect(vertices.remove(first)).toEqual([[1, 2], [3, 4]]);
+ expect(vertices.coordinates).toEqual([7, 8, 9, 10, 11, 12]);
+
+ expect(vertices.remove(third)).toEqual([[7, 8], [9, 10], [11, 12]]);
+ expect(vertices.coordinates).toEqual([]);
+ });
+
+ it('adjusts returned vertices by offset', function() {
+
+ var vertices = new ol.geom.SharedVertices({offset: [10, 20]});
+ var first = vertices.add([[1, 2]]);
+ var second = vertices.add([[3, 4]]);
+ var third = vertices.add([[5, 6]]);
+
+ expect(vertices.remove(second)).toEqual([[3, 4]]);
+ expect(vertices.coordinates).toEqual([-9, -18, -5, -14]);
+
+ expect(vertices.remove(third)).toEqual([[5, 6]]);
+ expect(vertices.coordinates).toEqual([-9, -18]);
+
+ expect(vertices.remove(first)).toEqual([[1, 2]]);
+ expect(vertices.coordinates).toEqual([]);
+ });
+
+ });
+
+ describe('#coordinates', function() {
+ it('is not reassigned', function() {
+ var vertices = new ol.geom.SharedVertices();
+ var first = vertices.add([[1, 2], [3, 4]]);
+ var coordinates = vertices.coordinates;
+
+ var second = vertices.add([[5, 6]]);
+ expect(vertices.coordinates).toBe(coordinates);
+
+ vertices.remove(first);
+ expect(vertices.coordinates).toBe(coordinates);
+
+ vertices.remove(second);
+ expect(vertices.coordinates).toBe(coordinates);
+ });
+ });
+
+});
+
+goog.require('ol.geom.SharedVertices');
diff --git a/test/spec/ol/parser/geojson.test.js b/test/spec/ol/parser/geojson.test.js
index dfbd3ae70d..624b95b07b 100644
--- a/test/spec/ol/parser/geojson.test.js
+++ b/test/spec/ol/parser/geojson.test.js
@@ -76,8 +76,7 @@ describe('ol.parser.geojson', function() {
var obj = ol.parser.geojson.read(str);
expect(obj).toBeA(ol.geom.Point);
- expect(obj.coordinates[0]).toBe(10);
- expect(obj.coordinates[1]).toBe(20);
+ expect(obj.getCoordinates()).toEqual([10, 20]);
});
it('parses linestring', function() {
@@ -88,10 +87,7 @@ describe('ol.parser.geojson', function() {
var obj = ol.parser.geojson.read(str);
expect(obj).toBeA(ol.geom.LineString);
- expect(obj.coordinates[0]).toBe(10);
- expect(obj.coordinates[1]).toBe(20);
- expect(obj.coordinates[2]).toBe(30);
- expect(obj.coordinates[3]).toBe(40);
+ expect(obj.getCoordinates()).toEqual([[10, 20], [30, 40]]);
});
it('parses polygon', function() {