diff --git a/src/ol/parser/wkt.js b/src/ol/parser/wkt.js index 634944bb43..fedbe57f41 100644 --- a/src/ol/parser/wkt.js +++ b/src/ol/parser/wkt.js @@ -1,9 +1,9 @@ goog.provide('ol.parser.WKT'); +goog.require('goog.array'); goog.require('goog.string'); goog.require('ol.geom.Geometry'); goog.require('ol.geom.GeometryCollection'); -goog.require('ol.geom.GeometryType'); goog.require('ol.geom.LineString'); goog.require('ol.geom.MultiLineString'); goog.require('ol.geom.MultiPoint'); @@ -19,25 +19,32 @@ goog.require('ol.parser.Parser'); * @extends {ol.parser.Parser} */ ol.parser.WKT = function() { - this.regExes = { - typeStr: /^\s*(\w+)\s*\(\s*(.*)\s*\)\s*$/, - spaces: /\s+/, - parenComma: /\)\s*,\s*\(/, - doubleParenComma: /\)\s*\)\s*,\s*\(\s*\(/, - trimParens: /^\s*\(?(.*?)\)?\s*$/ - }; }; goog.inherits(ol.parser.WKT, ol.parser.Parser); +/** + * Constants for regExes. + * @enum {RegExp} + */ +ol.parser.WKT.regExes = { + typeStr: /^\s*(\w+)\s*\(\s*(.*)\s*\)\s*$/, + spaces: /\s+/, + parenComma: /\)\s*,\s*\(/, + doubleParenComma: /\)\s*\)\s*,\s*\(\s*\(/, + trimParens: /^\s*\(?(.*?)\)?\s*$/, + geomCollection: /,\s*([A-Za-z])/g +}; + + /** * @param {string} str WKT point. * @return {ol.geom.Point} Parsed point. * @private */ ol.parser.WKT.prototype.parsePoint_ = function(str) { - var coords = goog.string.trim(str).split(this.regExes.spaces); - return new ol.geom.Point(coords.map(parseFloat)); + var coords = goog.string.trim(str).split(ol.parser.WKT.regExes.spaces); + return new ol.geom.Point(goog.array.map(coords, parseFloat)); }; @@ -67,7 +74,7 @@ ol.parser.WKT.prototype.parseMultiPoint_ = function(str) { var points = goog.string.trim(str).split(','); var parts = []; for (var i = 0, ii = points.length; i < ii; ++i) { - point = points[i].replace(this.regExes.trimParens, '$1'); + point = points[i].replace(ol.parser.WKT.regExes.trimParens, '$1'); parts.push(this.parsePoint_.apply(this, [point])); } return ol.geom.MultiPoint.fromParts(parts); @@ -81,10 +88,10 @@ ol.parser.WKT.prototype.parseMultiPoint_ = function(str) { */ ol.parser.WKT.prototype.parseMultiLineString_ = function(str) { var line; - var lines = goog.string.trim(str).split(this.regExes.parenComma); + var lines = goog.string.trim(str).split(ol.parser.WKT.regExes.parenComma); var parts = []; for (var i = 0, ii = lines.length; i < ii; ++i) { - line = lines[i].replace(this.regExes.trimParens, '$1'); + line = lines[i].replace(ol.parser.WKT.regExes.trimParens, '$1'); parts.push(this.parseLineString_.apply(this, [line])); } return ol.geom.MultiLineString.fromParts(parts); @@ -98,10 +105,10 @@ ol.parser.WKT.prototype.parseMultiLineString_ = function(str) { */ ol.parser.WKT.prototype.parsePolygon_ = function(str) { var ring, linestring, linearring; - var rings = goog.string.trim(str).split(this.regExes.parenComma); + var rings = goog.string.trim(str).split(ol.parser.WKT.regExes.parenComma); var coordinates = []; for (var i = 0, ii = rings.length; i < ii; ++i) { - ring = rings[i].replace(this.regExes.trimParens, '$1'); + ring = rings[i].replace(ol.parser.WKT.regExes.trimParens, '$1'); linestring = this.parseLineString_.apply(this, [ring]).getCoordinates(); coordinates.push(linestring); } @@ -116,10 +123,11 @@ ol.parser.WKT.prototype.parsePolygon_ = function(str) { */ ol.parser.WKT.prototype.parseMultiPolygon_ = function(str) { var polygon; - var polygons = goog.string.trim(str).split(this.regExes.doubleParenComma); + var polygons = goog.string.trim(str).split( + ol.parser.WKT.regExes.doubleParenComma); var parts = []; for (var i = 0, ii = polygons.length; i < ii; ++i) { - polygon = polygons[i].replace(this.regExes.trimParens, '$1'); + polygon = polygons[i].replace(ol.parser.WKT.regExes.trimParens, '$1'); parts.push(this.parsePolygon_.apply(this, [polygon])); } return ol.geom.MultiPolygon.fromParts(parts); @@ -133,7 +141,7 @@ ol.parser.WKT.prototype.parseMultiPolygon_ = function(str) { */ ol.parser.WKT.prototype.parseGeometryCollection_ = function(str) { // separate components of the collection with | - str = str.replace(/,\s*([A-Za-z])/g, '|$1'); + str = str.replace(ol.parser.WKT.regExes.geomCollection, '|$1'); var wktArray = goog.string.trim(str).split('|'); var components = []; for (var i = 0, ii = wktArray.length; i < ii; ++i) { @@ -251,7 +259,7 @@ ol.parser.WKT.prototype.encodeMultiPolygon_ = function(geom) { */ ol.parser.WKT.prototype.parse_ = function(wkt) { wkt = wkt.replace(/[\n\r]/g, ' '); - var matches = this.regExes.typeStr.exec(wkt); + var matches = ol.parser.WKT.regExes.typeStr.exec(wkt); var geometry; if (matches) { var type = matches[1].toLowerCase(); @@ -295,36 +303,22 @@ ol.parser.WKT.prototype.parse_ = function(wkt) { ol.parser.WKT.prototype.encode_ = function(geom) { var type = geom.getType(); var result = type.toUpperCase() + '('; - switch (type) { - case ol.geom.GeometryType.POINT: - result += this.encodePoint_(/** @type {ol.geom.Point} */ (geom)); - break; - case ol.geom.GeometryType.MULTIPOINT: - result += this.encodeMultiPoint_( - /** @type {ol.geom.MultiPoint} */ (geom)); - break; - case ol.geom.GeometryType.LINESTRING: - result += this.encodeLineString_( - /** @type {ol.geom.LineString} */ (geom)); - break; - case ol.geom.GeometryType.MULTILINESTRING: - result += this.encodeMultiLineString_( - /** @type {ol.geom.MultiLineString} */ (geom)); - break; - case ol.geom.GeometryType.POLYGON: - result += this.encodePolygon_( - /** @type {ol.geom.Polygon} */ (geom)); - break; - case ol.geom.GeometryType.MULTIPOLYGON: - result += this.encodeMultiPolygon_( - /** @type {ol.geom.MultiPolygon} */ (geom)); - break; - case ol.geom.GeometryType.GEOMETRYCOLLECTION: - result += this.encodeGeometryCollection_( - /** @type {ol.geom.GeometryCollection} */ (geom)); - break; - default: - throw new Error('Bad geometry type: ' + type); + if (geom instanceof ol.geom.Point) { + result += this.encodePoint_(geom); + } else if (geom instanceof ol.geom.MultiPoint) { + result += this.encodeMultiPoint_(geom); + } else if (geom instanceof ol.geom.LineString) { + result += this.encodeLineString_(geom); + } else if (geom instanceof ol.geom.MultiLineString) { + result += this.encodeMultiLineString_(geom); + } else if (geom instanceof ol.geom.Polygon) { + result += this.encodePolygon_(geom); + } else if (geom instanceof ol.geom.MultiPolygon) { + result += this.encodeMultiPolygon_(geom); + } else if (geom instanceof ol.geom.GeometryCollection) { + result += this.encodeGeometryCollection_(geom); + } else { + throw new Error('Bad geometry type: ' + type); } return result + ')'; }; diff --git a/test/spec/ol/parser/wkt.test.js b/test/spec/ol/parser/wkt.test.js index 55e288223f..37751b4698 100644 --- a/test/spec/ol/parser/wkt.test.js +++ b/test/spec/ol/parser/wkt.test.js @@ -9,6 +9,10 @@ describe('ol.parser.WKT', function() { var geom = parser.read(wkt); expect(geom.getCoordinates()).to.eql([30, 10]); expect(parser.write(geom)).to.eql(wkt); + // test whitespace when reading + wkt = 'POINT (30 10)'; + geom = parser.read(wkt); + expect(geom.getCoordinates()).to.eql([30, 10]); }); it('MultiPoint read / written correctly', function() { @@ -21,6 +25,7 @@ describe('ol.parser.WKT', function() { expect(geom.components[2].getCoordinates()).to.eql([20, 20]); expect(geom.components[3].getCoordinates()).to.eql([30, 10]); expect(parser.write(geom)).to.eql(wkt); + // this has whitespace wkt = 'MULTIPOINT (10 40, 40 30, 20 20, 30 10)'; geom = parser.read(wkt); expect(geom.components.length).to.eql(4); @@ -36,6 +41,11 @@ describe('ol.parser.WKT', function() { expect(geom.getType()).to.eql(ol.geom.GeometryType.LINESTRING); expect(geom.getCoordinates()).to.eql([[30, 10], [10, 30], [40, 40]]); expect(parser.write(geom)).to.eql(wkt); + // test whitespace when reading + wkt = 'LINESTRING (30 10, 10 30, 40 40)'; + geom = parser.read(wkt); + expect(geom.getType()).to.eql(ol.geom.GeometryType.LINESTRING); + expect(geom.getCoordinates()).to.eql([[30, 10], [10, 30], [40, 40]]); }); it('MultiLineString read / written correctly', function() { @@ -49,6 +59,16 @@ describe('ol.parser.WKT', function() { expect(geom.components[0].getCoordinates()).to.eql( [[10, 10], [20, 20], [10, 40]]); expect(parser.write(geom)).to.eql(wkt); + // test whitespace when reading + wkt = 'MULTILINESTRING ( (10 10, 20 20, 10 40), ' + + '(40 40, 30 30, 40 20, 30 10) )'; + geom = parser.read(wkt); + expect(geom.getType()).to.eql(ol.geom.GeometryType.MULTILINESTRING); + expect(geom.components.length).to.eql(2); + expect(geom.components[0].getType()).to.eql( + ol.geom.GeometryType.LINESTRING); + expect(geom.components[0].getCoordinates()).to.eql( + [[10, 10], [20, 20], [10, 40]]); }); it('Polygon read / written correctly', function() { @@ -71,6 +91,14 @@ describe('ol.parser.WKT', function() { expect(geom.rings[1].getCoordinates()).to.eql( [[20, 30], [35, 35], [30, 20], [20, 30]]); expect(parser.write(geom)).to.eql(wkt); + // test whitespace when reading + wkt = 'POLYGON ( (30 10, 10 20, 20 40, 40 40, 30 10) )'; + geom = parser.read(wkt); + expect(geom.getType()).to.eql(ol.geom.GeometryType.POLYGON); + expect(geom.rings.length).to.eql(1); + expect(geom.rings[0].getType()).to.eql(ol.geom.GeometryType.LINEARRING); + expect(geom.rings[0].getCoordinates()).to.eql( + [[30, 10], [10, 20], [20, 40], [40, 40], [30, 10]]); }); it('MultiPolygon read / written correctly', function() { @@ -90,6 +118,23 @@ describe('ol.parser.WKT', function() { expect(geom.components[1].rings[1].getCoordinates()).to.eql( [[30, 20], [20, 25], [20, 15], [30, 20]]); expect(parser.write(geom)).to.eql(wkt); + // test whitespace when reading + wkt = 'MULTIPOLYGON( ( (40 40, 20 45, 45 30, 40 40) ), ' + + '( (20 35, 45 20, 30 5, 10 10, 10 30, 20 35 ), ( 30 20, 20 25, ' + + '20 15, 30 20 ) ) )'; + geom = parser.read(wkt); + expect(geom.getType()).to.eql(ol.geom.GeometryType.MULTIPOLYGON); + expect(geom.components.length).to.eql(2); + expect(geom.components[0].getType()).to.eql(ol.geom.GeometryType.POLYGON); + expect(geom.components[1].getType()).to.eql(ol.geom.GeometryType.POLYGON); + expect(geom.components[0].rings.length).to.eql(1); + expect(geom.components[1].rings.length).to.eql(2); + expect(geom.components[0].rings[0].getCoordinates()).to.eql( + [[40, 40], [20, 45], [45, 30], [40, 40]]); + expect(geom.components[1].rings[0].getCoordinates()).to.eql( + [[20, 35], [45, 20], [30, 5], [10, 10], [10, 30], [20, 35]]); + expect(geom.components[1].rings[1].getCoordinates()).to.eql( + [[30, 20], [20, 25], [20, 15], [30, 20]]); }); it('GeometryCollection read / written correctly', function() { @@ -103,6 +148,16 @@ describe('ol.parser.WKT', function() { expect(geom.components[0].getCoordinates()).to.eql([4, 6]); expect(geom.components[1].getCoordinates()).to.eql([[4, 6], [7, 10]]); expect(parser.write(geom)).to.eql(wkt); + // test whitespace when reading + wkt = 'GEOMETRYCOLLECTION ( POINT (4 6), LINESTRING (4 6, 7 10) )'; + geom = parser.read(wkt); + expect(geom.components.length).to.eql(2); + expect(geom.getType()).to.eql(ol.geom.GeometryType.GEOMETRYCOLLECTION); + expect(geom.components[0].getType()).to.eql(ol.geom.GeometryType.POINT); + expect(geom.components[1].getType()).to.eql( + ol.geom.GeometryType.LINESTRING); + expect(geom.components[0].getCoordinates()).to.eql([4, 6]); + expect(geom.components[1].getCoordinates()).to.eql([[4, 6], [7, 10]]); }); });