From bf8c12d9f7c0209d7a8b3b35f689d16943055631 Mon Sep 17 00:00:00 2001 From: Bart van den Eijnden Date: Wed, 15 May 2013 14:01:25 +0200 Subject: [PATCH 1/4] Add WKT parser. Add a parser (read/write) for OGC Well-Known-Text (WKT). It deals with geometries only, not with features, mostly because WKT can only contain a single geometry (or geometry collection). This can later on be used to serialize and deserialize geometries in ol3. --- src/ol/parser/wkt.js | 350 ++++++++++++++++++++++++++++++++ test/spec/ol/parser/wkt.test.js | 111 ++++++++++ 2 files changed, 461 insertions(+) create mode 100644 src/ol/parser/wkt.js create mode 100644 test/spec/ol/parser/wkt.test.js diff --git a/src/ol/parser/wkt.js b/src/ol/parser/wkt.js new file mode 100644 index 0000000000..634944bb43 --- /dev/null +++ b/src/ol/parser/wkt.js @@ -0,0 +1,350 @@ +goog.provide('ol.parser.WKT'); + +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'); +goog.require('ol.geom.MultiPolygon'); +goog.require('ol.geom.Point'); +goog.require('ol.geom.Polygon'); +goog.require('ol.parser.Parser'); + + + +/** + * @constructor + * @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); + + +/** + * @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)); +}; + + +/** + * @param {string} str WKT linestring. + * @return {ol.geom.LineString} Parsed linestring. + * @private + */ +ol.parser.WKT.prototype.parseLineString_ = function(str) { + var points = goog.string.trim(str).split(','); + var coordinates = []; + for (var i = 0, ii = points.length; i < ii; ++i) { + coordinates.push(this.parsePoint_.apply(this, + [points[i]]).getCoordinates()); + } + return new ol.geom.LineString(coordinates); +}; + + +/** + * @param {string} str WKT multipoint. + * @return {ol.geom.MultiPoint} Parsed multipoint. + * @private + */ +ol.parser.WKT.prototype.parseMultiPoint_ = function(str) { + var point; + 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'); + parts.push(this.parsePoint_.apply(this, [point])); + } + return ol.geom.MultiPoint.fromParts(parts); +}; + + +/** + * @param {string} str WKT multilinestring. + * @return {ol.geom.MultiLineString} Parsed multilinestring. + * @private + */ +ol.parser.WKT.prototype.parseMultiLineString_ = function(str) { + var line; + var lines = goog.string.trim(str).split(this.regExes.parenComma); + var parts = []; + for (var i = 0, ii = lines.length; i < ii; ++i) { + line = lines[i].replace(this.regExes.trimParens, '$1'); + parts.push(this.parseLineString_.apply(this, [line])); + } + return ol.geom.MultiLineString.fromParts(parts); +}; + + +/** + * @param {string} str WKT polygon. + * @return {ol.geom.Polygon} Parsed polygon. + * @private + */ +ol.parser.WKT.prototype.parsePolygon_ = function(str) { + var ring, linestring, linearring; + var rings = goog.string.trim(str).split(this.regExes.parenComma); + var coordinates = []; + for (var i = 0, ii = rings.length; i < ii; ++i) { + ring = rings[i].replace(this.regExes.trimParens, '$1'); + linestring = this.parseLineString_.apply(this, [ring]).getCoordinates(); + coordinates.push(linestring); + } + return new ol.geom.Polygon(coordinates); +}; + + +/** + * @param {string} str WKT multipolygon. + * @return {ol.geom.MultiPolygon} Parsed multipolygon. + * @private + */ +ol.parser.WKT.prototype.parseMultiPolygon_ = function(str) { + var polygon; + var polygons = goog.string.trim(str).split(this.regExes.doubleParenComma); + var parts = []; + for (var i = 0, ii = polygons.length; i < ii; ++i) { + polygon = polygons[i].replace(this.regExes.trimParens, '$1'); + parts.push(this.parsePolygon_.apply(this, [polygon])); + } + return ol.geom.MultiPolygon.fromParts(parts); +}; + + +/** + * @param {string} str WKT geometrycollection. + * @return {ol.geom.GeometryCollection} Parsed geometrycollection. + * @private + */ +ol.parser.WKT.prototype.parseGeometryCollection_ = function(str) { + // separate components of the collection with | + str = str.replace(/,\s*([A-Za-z])/g, '|$1'); + var wktArray = goog.string.trim(str).split('|'); + var components = []; + for (var i = 0, ii = wktArray.length; i < ii; ++i) { + components.push(this.parse_.apply(this, [wktArray[i]])); + } + return new ol.geom.GeometryCollection(components); +}; + + +/** + * @param {ol.geom.Point} geom Point geometry. + * @return {string} Coordinates part of Point as WKT. + * @private + */ +ol.parser.WKT.prototype.encodePoint_ = function(geom) { + var coordinates = geom.getCoordinates(); + return coordinates[0] + ' ' + coordinates[1]; +}; + + +/** + * @param {ol.geom.MultiPoint} geom MultiPoint geometry. + * @return {string} Coordinates part of MultiPoint as WKT. + * @private + */ +ol.parser.WKT.prototype.encodeMultiPoint_ = function(geom) { + var array = []; + for (var i = 0, ii = geom.components.length; i < ii; ++i) { + array.push('(' + this.encodePoint_.apply(this, [geom.components[i]]) + ')'); + } + return array.join(','); +}; + + +/** + * @param {ol.geom.GeometryCollection} geom GeometryCollection geometry. + * @return {string} Coordinates part of GeometryCollection as WKT. + * @private + */ +ol.parser.WKT.prototype.encodeGeometryCollection_ = function(geom) { + var array = []; + for (var i = 0, ii = geom.components.length; i < ii; ++i) { + array.push(this.encode_.apply(this, [geom.components[i]])); + } + return array.join(','); +}; + + +/** + * @param {ol.geom.LineString} geom LineString geometry. + * @return {string} Coordinates part of LineString as WKT. + * @private + */ +ol.parser.WKT.prototype.encodeLineString_ = function(geom) { + var coordinates = geom.getCoordinates(); + var array = []; + for (var i = 0, ii = coordinates.length; i < ii; ++i) { + array.push(coordinates[i][0] + ' ' + coordinates[i][1]); + } + return array.join(','); +}; + + +/** + * @param {ol.geom.MultiLineString} geom MultiLineString geometry. + * @return {string} Coordinates part of MultiLineString as WKT. + * @private + */ +ol.parser.WKT.prototype.encodeMultiLineString_ = function(geom) { + var array = []; + for (var i = 0, ii = geom.components.length; i < ii; ++i) { + array.push('(' + this.encodeLineString_.apply(this, + [geom.components[i]]) + ')'); + } + return array.join(','); +}; + + +/** + * @param {ol.geom.Polygon} geom Polygon geometry. + * @return {string} Coordinates part of Polygon as WKT. + * @private + */ +ol.parser.WKT.prototype.encodePolygon_ = function(geom) { + var array = []; + for (var i = 0, ii = geom.rings.length; i < ii; ++i) { + array.push('(' + this.encodeLineString_.apply(this, + [geom.rings[i]]) + ')'); + } + return array.join(','); +}; + + +/** + * @param {ol.geom.MultiPolygon} geom MultiPolygon geometry. + * @return {string} Coordinates part of MultiPolygon as WKT. + * @private + */ +ol.parser.WKT.prototype.encodeMultiPolygon_ = function(geom) { + var array = []; + for (var i = 0, ii = geom.components.length; i < ii; ++i) { + array.push('(' + this.encodePolygon_.apply(this, + [geom.components[i]]) + ')'); + } + return array.join(','); +}; + + +/** + * Parse a WKT string. + * @param {string} wkt WKT string. + * @return {ol.geom.Geometry|ol.geom.GeometryCollection|undefined} + * The geometry created. + * @private + */ +ol.parser.WKT.prototype.parse_ = function(wkt) { + wkt = wkt.replace(/[\n\r]/g, ' '); + var matches = this.regExes.typeStr.exec(wkt); + var geometry; + if (matches) { + var type = matches[1].toLowerCase(); + var str = matches[2]; + switch (type) { + case 'point': + geometry = this.parsePoint_(str); + break; + case 'multipoint': + geometry = this.parseMultiPoint_(str); + break; + case 'linestring': + geometry = this.parseLineString_(str); + break; + case 'multilinestring': + geometry = this.parseMultiLineString_(str); + break; + case 'polygon': + geometry = this.parsePolygon_(str); + break; + case 'multipolygon': + geometry = this.parseMultiPolygon_(str); + break; + case 'geometrycollection': + geometry = this.parseGeometryCollection_(str); + break; + default: + throw new Error('Bad geometry type: ' + type); + } + } + return geometry; +}; + + +/** + * Encode a geometry as WKT. + * @param {ol.geom.Geometry} geom The geometry to encode. + * @return {string} WKT string for the geometry. + * @private + */ +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); + } + return result + ')'; +}; + + +/** + * Parse a WKT string. + * @param {string} str WKT string. + * @return {ol.geom.Geometry|undefined} Parsed geometry. + */ +ol.parser.WKT.prototype.read = function(str) { + return this.parse_(str); +}; + + +/** + * Write out a geometry as a WKT string. + * @param {ol.geom.Geometry} geom The geometry to encode. + * @return {string} WKT for the geometry. + */ +ol.parser.WKT.prototype.write = function(geom) { + return this.encode_(geom); +}; diff --git a/test/spec/ol/parser/wkt.test.js b/test/spec/ol/parser/wkt.test.js new file mode 100644 index 0000000000..55e288223f --- /dev/null +++ b/test/spec/ol/parser/wkt.test.js @@ -0,0 +1,111 @@ +goog.provide('ol.test.parser.WKT'); + +describe('ol.parser.WKT', function() { + + var parser = new ol.parser.WKT(); + + it('Point read / written correctly', function() { + var wkt = 'POINT(30 10)'; + var geom = parser.read(wkt); + expect(geom.getCoordinates()).to.eql([30, 10]); + expect(parser.write(geom)).to.eql(wkt); + }); + + it('MultiPoint read / written correctly', function() { + // there are two forms to test + var wkt = 'MULTIPOINT((10 40),(40 30),(20 20),(30 10))'; + var geom = parser.read(wkt); + expect(geom.components.length).to.eql(4); + expect(geom.components[0].getCoordinates()).to.eql([10, 40]); + expect(geom.components[1].getCoordinates()).to.eql([40, 30]); + 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); + wkt = 'MULTIPOINT (10 40, 40 30, 20 20, 30 10)'; + geom = parser.read(wkt); + expect(geom.components.length).to.eql(4); + expect(geom.components[0].getCoordinates()).to.eql([10, 40]); + expect(geom.components[1].getCoordinates()).to.eql([40, 30]); + expect(geom.components[2].getCoordinates()).to.eql([20, 20]); + expect(geom.components[3].getCoordinates()).to.eql([30, 10]); + }); + + it('LineString read / written correctly', function() { + var wkt = 'LINESTRING(30 10,10 30,40 40)'; + var geom = parser.read(wkt); + 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); + }); + + it('MultiLineString read / written correctly', function() { + var wkt = 'MULTILINESTRING((10 10,20 20,10 40),' + + '(40 40,30 30,40 20,30 10))'; + var 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]]); + expect(parser.write(geom)).to.eql(wkt); + }); + + it('Polygon read / written correctly', function() { + var wkt = 'POLYGON((30 10,10 20,20 40,40 40,30 10))'; + var 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]]); + expect(parser.write(geom)).to.eql(wkt); + wkt = 'POLYGON((35 10,10 20,15 40,45 45,35 10),(20 30,35 35,30 20,20 30))'; + geom = parser.read(wkt); + expect(geom.getType()).to.eql(ol.geom.GeometryType.POLYGON); + expect(geom.rings.length).to.eql(2); + expect(geom.rings[0].getType()).to.eql(ol.geom.GeometryType.LINEARRING); + expect(geom.rings[1].getType()).to.eql(ol.geom.GeometryType.LINEARRING); + expect(geom.rings[0].getCoordinates()).to.eql( + [[35, 10], [10, 20], [15, 40], [45, 45], [35, 10]]); + expect(geom.rings[1].getCoordinates()).to.eql( + [[20, 30], [35, 35], [30, 20], [20, 30]]); + expect(parser.write(geom)).to.eql(wkt); + }); + + it('MultiPolygon read / written correctly', function() { + var 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)))'; + var 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]]); + expect(parser.write(geom)).to.eql(wkt); + }); + + it('GeometryCollection read / written correctly', function() { + var wkt = 'GEOMETRYCOLLECTION(POINT(4 6),LINESTRING(4 6,7 10))'; + var 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]]); + expect(parser.write(geom)).to.eql(wkt); + }); + +}); + +goog.require('ol.geom.GeometryType'); +goog.require('ol.parser.WKT'); From bb16820ab0915e4aef5c684e5c7f7b916d3c5c47 Mon Sep 17 00:00:00 2001 From: Bart van den Eijnden Date: Thu, 16 May 2013 15:44:31 +0200 Subject: [PATCH 2/4] add exports for WKT --- src/ol/parser/wkt.exports | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 src/ol/parser/wkt.exports diff --git a/src/ol/parser/wkt.exports b/src/ol/parser/wkt.exports new file mode 100644 index 0000000000..27763ba19d --- /dev/null +++ b/src/ol/parser/wkt.exports @@ -0,0 +1,3 @@ +@exportSymbol ol.parser.WKT +@exportProperty ol.parser.WKT.prototype.read +@exportProperty ol.parser.WKT.prototype.write From 585887b04e79c86f2e72658990db81798aec6bc0 Mon Sep 17 00:00:00 2001 From: Bart van den Eijnden Date: Fri, 17 May 2013 10:09:40 +0200 Subject: [PATCH 3/4] address review comments by @twpayne --- src/ol/parser/wkt.js | 92 +++++++++++++++------------------ test/spec/ol/parser/wkt.test.js | 55 ++++++++++++++++++++ 2 files changed, 98 insertions(+), 49 deletions(-) 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]]); }); }); From 3e3b5ab02d082ebc7d25a8f3582b583a4baf083c Mon Sep 17 00:00:00 2001 From: Bart van den Eijnden Date: Fri, 17 May 2013 10:15:22 +0200 Subject: [PATCH 4/4] move last RegExp into constant --- src/ol/parser/wkt.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ol/parser/wkt.js b/src/ol/parser/wkt.js index fedbe57f41..5720bb819b 100644 --- a/src/ol/parser/wkt.js +++ b/src/ol/parser/wkt.js @@ -33,7 +33,8 @@ ol.parser.WKT.regExes = { parenComma: /\)\s*,\s*\(/, doubleParenComma: /\)\s*\)\s*,\s*\(\s*\(/, trimParens: /^\s*\(?(.*?)\)?\s*$/, - geomCollection: /,\s*([A-Za-z])/g + geomCollection: /,\s*([A-Za-z])/g, + removeNewLine: /[\n\r]/g }; @@ -258,7 +259,7 @@ ol.parser.WKT.prototype.encodeMultiPolygon_ = function(geom) { * @private */ ol.parser.WKT.prototype.parse_ = function(wkt) { - wkt = wkt.replace(/[\n\r]/g, ' '); + wkt = wkt.replace(ol.parser.WKT.regExes.removeNewLine, ' '); var matches = ol.parser.WKT.regExes.typeStr.exec(wkt); var geometry; if (matches) {