diff --git a/src/api/geom/linestring.js b/src/api/geom/linestring.js new file mode 100644 index 0000000000..61c0ee28a6 --- /dev/null +++ b/src/api/geom/linestring.js @@ -0,0 +1,137 @@ +goog.provide('ol.geom.linestring'); + +goog.require('ol.geom.LineString'); +goog.require('ol.geom.point'); +goog.require('ol.projection'); + +/** + * @export + * @param {Array.} opt_arg Point. + * @return {ol.geom.LineString} LineString. + */ +ol.geom.linestring = function(opt_arg){ + + if (opt_arg instanceof ol.geom.LineString) { + return opt_arg; + } + + var vertices = []; + if (arguments.length == 1 && goog.isDef(opt_arg)) { + if (goog.isArray(opt_arg)) { + var allValid = goog.array.every(opt_arg, function(spec){ + var v = ol.geom.point(spec); + if (v instanceof ol.geom.Point) { + vertices.push(v); + return true; + } else { + return false; + } + }); + if (!allValid) { + var msg = 'ol.geom.linestring: at least one point ' + + 'definition was erroneous.'; + throw new Error(msg); + } + } else { + throw new Error('ol.geom.linestring'); + } + } + + var ls = new ol.geom.LineString(vertices); + return ls; +}; +goog.inherits(ol.geom.linestring, ol.geom.geometry); + +/** + * @export + * @param {Array.=} opt_arg An array of vertex specifications. + * @return {Array.|ol.geom.LineString|undefined} Result. + */ +ol.geom.LineString.prototype.vertices = function(opt_arg){ + if (arguments.length == 1 && goog.isDef(opt_arg)) { + var vertices = [], + allValid = false; + goog.array.every(opt_arg, function(spec){ + var v = ol.geom.point(spec); + if (v instanceof ol.geom.Point) { + vertices.push(v); + return true; + } else { + return false; + } + }); + if (!allValid) { + vertices = []; + } + this.setVertices(vertices); + return this; + } + else { + return this.getVertices(); + } +}; + +/** + * @export + * @param {ol.PointLike} vertex A point specification. + * @param {number=} opt_index An optional index to add the vertices at. If not + * provided, the vertex will be added to the end of the list of vertices. + * @return {ol.geom.LineString} The LineString instance. + */ +ol.geom.LineString.prototype.add = function(vertex, opt_index){ + var index = this.vertices_.length, + allValid = false, + v = ol.geom.point(vertex); + if (arguments.length == 2 && goog.isDef(opt_index)) { + index = opt_index; + } + this.addVertex(v, index); + return this; +}; + +/** + * @export + * @param {Array.} vertices Some vertex specifications. + * @param {number=} opt_index An optional index to add the vertices at. If not + * provided, the points will be added to the end of the list of vertices. + * @return {ol.geom.LineString} The LineString instance. + */ +ol.geom.LineString.prototype.addAll = function(vertices, opt_index){ + var index = this.vertices_.length, + v; + + if (arguments.length == 2 && goog.isDef(opt_index)) { + index = opt_index; + } + + goog.array.every(vertices, function(vertexSpec){ + v = ol.geom.point(vertexSpec); + this.addVertex(v, index); + index++; + return true; + }, this); + + return this; +}; + +/** + * @export + * @param {(ol.geom.Point|Array.)} vertices A point specification or + * an array of point specifications. + * @return {ol.geom.LineString} The MultiPoint instance. + */ +ol.geom.LineString.prototype.remove = function(vertices){ + var vertexArr = []; + if (!goog.isArray(vertices)) { + vertexArr.push(vertices); + } else { + vertexArr = vertices; + } + + goog.array.every(vertexArr, function(v){ + this.removeVertex(v); + return true; + }, this); + + return this; +}; diff --git a/src/ol/geom/LineString.js b/src/ol/geom/LineString.js new file mode 100644 index 0000000000..54b07295d5 --- /dev/null +++ b/src/ol/geom/LineString.js @@ -0,0 +1,63 @@ +goog.provide('ol.geom.LineString'); + +goog.require('goog.array'); +goog.require('ol.geom.Geometry'); +goog.require('ol.geom.Point'); +goog.require('ol.Projection'); + +/** + * Creates ol.geom.LineString objects. + * + * @extends {ol.geom.Geometry} + * @param {Array.} vertices An array of points building the + * linestrings vertices. + * + * @constructor + */ +ol.geom.LineString = function(vertices) { + /** + * @private + * @type {Array.} + */ + this.vertices_ = vertices; + +}; + +goog.inherits(ol.geom.LineString, ol.geom.Geometry); + +/** + * Sets the LineString's points. + * + * @return {Array.} An array of points. + */ +ol.geom.LineString.prototype.getVertices = function() { + return this.vertices_; +}; + +/** + * Gets the LineString's points. + * + * @param {Array.} vertices An array of points. + */ +ol.geom.LineString.prototype.setVertices = function(vertices) { + this.vertices_ = vertices; +}; + +/** + * Adds the given vertex to the list of vertices at the specified index. + * + * @param {ol.geom.Point} vertex A point to be added. + * @param {number} index The index where to add. + */ +ol.geom.LineString.prototype.addVertex = function(vertex, index) { + goog.array.insertAt(this.vertices_,vertex,index); +}; + +/** + * Removes the given vertex from the list of vertices. + * + * @param {ol.geom.Point} vertex A point to be removed. + */ +ol.geom.LineString.prototype.removeVertex = function(vertex) { + goog.array.remove(this.vertices_, vertex); +}; diff --git a/test/spec/api/geom/linestring.test.js b/test/spec/api/geom/linestring.test.js new file mode 100644 index 0000000000..356b5b1284 --- /dev/null +++ b/test/spec/api/geom/linestring.test.js @@ -0,0 +1,224 @@ +describe("ol.geom.linestring", function() { + var ls; + beforeEach(function() { + ls = ol.geom.linestring([ + {x:0, y:1}, + {x:2, y:3} + ]); + }); + + afterEach(function() { + ls = null; + }); + describe("can construct instances with some vertices", function() { + it("works for the object notation of vertices", function(){ + expect( ls ).toBeA( ol.geom.LineString ); + }); + + it("works for the array notation of vertices", function(){ + ls = ol.geom.linestring([ + [0, 1], + [2, 3] + ]); + + expect( ls ).toBeA( ol.geom.LineString ); + }); + + it("works for real vertices", function(){ + ls = ol.geom.linestring([ + ol.geom.point([0,1]), + ol.geom.point([2,3]) + ]); + + expect( ls ).toBeA( ol.geom.LineString ); + }); + }); + + describe("can construct instances without any vertices", function() { + + it("works with an empty array", function(){ + ls = ol.geom.linestring([]); + + expect( ls ).toBeA( ol.geom.LineString ); + }); + + it("works without arguments", function(){ + ls = ol.geom.linestring(); + + expect( ls ).toBeA( ol.geom.LineString ); + }); + }); + + describe("the method 'add'", function() { + it("exists", function(){ + expect( ls.add ).toBeA( Function ); + }); + + describe("can be used as setter", function(){ + it("works with a single vertex specification and an index", function(){ + var p = ol.geom.point([24,7]); + ls.add(p, 0); + + expect(ls.vertices().length).toBe(3); + + var firstPoint = ls.vertices()[0]; + + expect( firstPoint.x() + ',' + firstPoint.y() ).toBe( '24,7' ); + }); + + it("works with point instance", function(){ + ls = ol.geom.linestring(); + ls.add(ol.geom.point([24,7])); + expect(ls.vertices().length).toBe(1); + var firstPoint = ls.vertices()[0]; + expect( firstPoint.x() + ',' + firstPoint.y() ).toBe( '24,7' ); + }); + + it("works with array specifications", function(){ + ls = ol.geom.linestring(); + ls.add([24,7]); + expect(ls.vertices().length).toBe(1); + var firstPoint = ls.vertices()[0]; + expect( firstPoint.x() + ',' + firstPoint.y() ).toBe( '24,7' ); + }); + + it("works with object specifications", function(){ + ls = ol.geom.linestring(); + ls.add({x:24,y:7}); + expect(ls.vertices().length).toBe(1); + var firstPoint = ls.vertices()[0]; + expect( firstPoint.x() + ',' + firstPoint.y() ).toBe( '24,7' ); + }); + + it("the index is functional", function(){ + var p = ol.geom.point([24,7]); + ls.add(p, 1); + + expect(ls.vertices().length).toBe(3); + + var firstPoint = ls.vertices()[0], // untouched + secondPoint = ls.vertices()[1], // this should be ours + thirdPoint = ls.vertices()[2]; // shifted here + + expect( firstPoint.x() + ',' + firstPoint.y() ).toBe( '0,1' ); + expect( secondPoint.x() + ',' + secondPoint.y() ).toBe( '24,7' ); + expect( thirdPoint.x() + ',' + thirdPoint.y() ).toBe( '2,3' ); + }); + + it("the index is optional", function(){ + var p = ol.geom.point([24,7]); + ls.add(p); + + expect(ls.vertices().length).toBe(3); + + var thirdPoint = ls.vertices()[2]; + expect( thirdPoint.x() + ',' + thirdPoint.y() ).toBe( '24,7' ); + }); + + it("returns the linestring instance", function(){ + var p = ol.geom.point([24,7]); + var returned = ls.add(p); + + expect(returned).toBe(ls); + }); + }); + }); + + describe("the method 'addAll'", function(){ + it("exists", function(){ + expect( ls.addAll ).toBeA( Function ); + }); + + describe("can be used as setter", function(){ + + it("works with an array of point specifications and an index", function(){ + var ps = [ + ol.geom.point([24,7]), + ol.geom.point([7,11]) + ]; + ls.addAll(ps, 0); + + expect(ls.vertices().length).toBe(4); + + var firstPoint = ls.vertices()[0], + secondPoint = ls.vertices()[1]; + + expect( firstPoint.x() + ',' + firstPoint.y() ).toBe( '24,7' ); + expect( secondPoint.x() + ',' + secondPoint.y() ).toBe( '7,11' ); + }); + + it("the index is functional", function(){ + var ps = [ + [24,7], + {x:7, y:11} + ]; + ls.addAll(ps, 1); + + expect(ls.vertices().length).toBe(4); + + var firstPoint = ls.vertices()[0], // untouched + secondPoint = ls.vertices()[1], // this should be ours + thirdPoint = ls.vertices()[2], // this should be ours + fourthPoint = ls.vertices()[3]; // shifted here + + expect( firstPoint.x() + ',' + firstPoint.y() ).toBe( '0,1' ); + expect( secondPoint.x() + ',' + secondPoint.y() ).toBe( '24,7' ); + expect( thirdPoint.x() + ',' + thirdPoint.y() ).toBe( '7,11' ); + expect( fourthPoint.x() + ',' + fourthPoint.y() ).toBe( '2,3' ); + }); + + it("the index is optional", function(){ + var ps = [ + [24,7], + {x:7, y:11} + ]; + ls.addAll(ps); + + expect(ls.vertices().length).toBe(4); + + var thirdPoint = ls.vertices()[2], + fourthPoint = ls.vertices()[3]; + expect( thirdPoint.x() + ',' + thirdPoint.y() ).toBe( '24,7' ); + expect( fourthPoint.x() + ',' + fourthPoint.y() ).toBe( '7,11' ); + }); + + it("returns the linestring instance", function(){ + var ps = [ + [24,7], + {x:7, y:11} + ]; + var returned = ls.addAll(ps); + + expect(returned).toBe(ls); + }); + }); + }); + + + describe("the method 'remove'", function() { + it("exists", function(){ + expect( ls.add ).toBeA( Function ); + }); + + it("works with a single point", function(){ + var p = ls.vertices()[0]; + ls.remove(p); + expect(ls.vertices().length).toBe(1); + var firstPoint = ls.vertices()[0]; + expect( firstPoint.x() + ',' + firstPoint.y() ).toBe( '2,3' ); + }); + + it("works with an array of point specifications", function(){ + var ps = [ + ls.vertices()[1], + ls.vertices()[0] + ]; + ls.remove(ps); + expect(ls.vertices().length).toBe(0); + }); + }); +}); + + + + diff --git a/test/spec/ol/geom/LineString.test.js b/test/spec/ol/geom/LineString.test.js new file mode 100644 index 0000000000..bf6894706a --- /dev/null +++ b/test/spec/ol/geom/LineString.test.js @@ -0,0 +1,112 @@ +describe("ol.geom.LineString", function() { + var ls; + + beforeEach(function(){ + ls = new ol.geom.LineString([ + new ol.geom.Point(0,0), + new ol.geom.Point(10,10), + new ol.geom.Point(10,0), + new ol.geom.Point(20,20) + ]); + }); + + afterEach(function(){ + ls = null; + }); + + it("constructs instances", function() { + expect( ls ).toBeA( ol.geom.LineString ); + }); + + it("can construct instances without any points", function() { + // empty array + mp = new ol.geom.LineString([]); + expect( ls ).toBeA( ol.geom.LineString ); + + // no argument at all + mp = new ol.geom.LineString(); + expect( ls ).toBeA( ol.geom.LineString ); + }); + + it("inherits from ol.geom.Geometry", function() { + expect( ls ).toBeA( ol.geom.Geometry ); + }); + + it("has a working getter for vertices", function() { + + var vertices = ls.getVertices(); + + expect( vertices ).toBeA( Array ); + expect( vertices.length ).toBe( 4 ); + expect( vertices[0] ).toBeA( ol.geom.Point ); + + expect( vertices[0].getX() + ',' + vertices[0].getY()).toBe( '0,0' ); + + }); + + it("has a working setter for vertices", function() { + + ls.setVertices([ + new ol.geom.Point(30,40), + new ol.geom.Point(50,60) + ]); + + var vertices = ls.getVertices(); + + expect( vertices.length ).toBe( 2 ); + expect( vertices[0] ).toBeA( ol.geom.Point ); + expect( vertices[1] ).toBeA( ol.geom.Point ); + + expect( vertices[0].getX() + ',' + vertices[0].getY()).toBe( '30,40' ); + expect( vertices[1].getX() + ',' + vertices[1].getY()).toBe( '50,60' ); + + }); + + it("has a method to add vertices", function() { + + ls.addVertex( + new ol.geom.Point(30,40), + 1 + ); + ls.addVertex( + new ol.geom.Point(50,60), + 2 + ); + ls.addVertex( + new ol.geom.Point(-10,0), + 0 + ); + + var vertices = ls.getVertices(); + + expect( vertices.length ).toBe( 7 ); + expect( vertices[0].getX() + ',' + vertices[0].getY()).toBe( '-10,0' ); + expect( vertices[1].getX() + ',' + vertices[1].getY()).toBe( '0,0' ); + expect( vertices[2].getX() + ',' + vertices[2].getY()).toBe( '30,40' ); + expect( vertices[3].getX() + ',' + vertices[3].getY()).toBe( '50,60' ); + expect( vertices[4].getX() + ',' + vertices[4].getY()).toBe( '10,10' ); + expect( vertices[5].getX() + ',' + vertices[5].getY()).toBe( '10,0' ); + expect( vertices[6].getX() + ',' + vertices[6].getY()).toBe( '20,20' ); + + }); + + it("has a method to remove vertices", function() { + ls.setVertices([ + new ol.geom.Point(0,10), + new ol.geom.Point(10,20), + new ol.geom.Point(20,30), + new ol.geom.Point(30,40) + ]); + + var v = ls.getVertices()[2]; // 20,30; + + ls.removeVertex( v ); + + var vertices = ls.getVertices(); + + expect( vertices.length ).toBe( 3 ); + expect( vertices[0].getX() + ',' + vertices[0].getY()).toBe( '0,10' ); + expect( vertices[1].getX() + ',' + vertices[1].getY()).toBe( '10,20' ); + expect( vertices[2].getX() + ',' + vertices[2].getY()).toBe( '30,40' ); + }); +});