From 8c8ddce290f016117e63fd77b18258caceee6d8a Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Mon, 4 Mar 2013 20:31:01 +0100 Subject: [PATCH] GeoJSON parser implements StringFeatureParser --- src/ol/parser/geojson.js | 155 +++++++++++++++++----------- test/spec/ol/parser/geojson.test.js | 19 +++- 2 files changed, 111 insertions(+), 63 deletions(-) diff --git a/src/ol/parser/geojson.js b/src/ol/parser/geojson.js index cb5863e243..94624e3d7a 100644 --- a/src/ol/parser/geojson.js +++ b/src/ol/parser/geojson.js @@ -2,6 +2,7 @@ goog.provide('ol.parser.GeoJSON'); goog.require('ol.Feature'); goog.require('ol.geom.Geometry'); +goog.require('ol.geom.GeometryType'); goog.require('ol.geom.LineString'); goog.require('ol.geom.MultiLineString'); goog.require('ol.geom.MultiPoint'); @@ -10,11 +11,14 @@ goog.require('ol.geom.Point'); goog.require('ol.geom.Polygon'); goog.require('ol.geom.SharedVertices'); goog.require('ol.parser.Parser'); +goog.require('ol.parser.ReadFeaturesOptions'); +goog.require('ol.parser.StringFeatureParser'); /** * @constructor + * @implements {ol.parser.StringFeatureParser} * @extends {ol.parser.Parser} */ ol.parser.GeoJSON = function() {}; @@ -24,63 +28,74 @@ goog.inherits(ol.parser.GeoJSON, ol.parser.Parser); /** * Parse a GeoJSON string. * @param {string} str GeoJSON string. - * @param {ol.parser.GeoJSON.ReadOptions=} opt_options Read options. * @return {ol.Feature|Array.| * ol.geom.Geometry|Array.} Parsed geometry or array * of geometries. */ -ol.parser.GeoJSON.prototype.read = function(str, opt_options) { +ol.parser.GeoJSON.prototype.read = function(str) { var json = /** @type {GeoJSONObject} */ (JSON.parse(str)); - return this.parse_(json, opt_options); + return this.parse_(json); +}; + + +/** + * Parse a GeoJSON feature collection. + * @param {string} str GeoJSON feature collection. + * @param {ol.parser.ReadFeaturesOptions=} opt_options Reader options. + * @return {Array.} Array of features. + */ +ol.parser.GeoJSON.prototype.readFeaturesFromString = + function(str, opt_options) { + var json = /** @type {GeoJSONFeatureCollection} */ (JSON.parse(str)); + return this.parseFeatureCollection_(json, opt_options); }; /** * @param {GeoJSONObject} json GeoJSON object. - * @param {ol.parser.GeoJSON.ReadOptions=} opt_options Read options. * @return {ol.Feature|Array.| * ol.geom.Geometry|Array.} Parsed geometry or array * of geometries. * @private */ -ol.parser.GeoJSON.prototype.parse_ = function(json, opt_options) { +ol.parser.GeoJSON.prototype.parse_ = function(json) { var result; switch (json.type) { case 'FeatureCollection': result = this.parseFeatureCollection_( - /** @type {GeoJSONFeatureCollection} */ (json), opt_options); + /** @type {GeoJSONFeatureCollection} */ (json)); break; case 'Feature': result = this.parseFeature_( - /** @type {GeoJSONFeature} */ (json), opt_options); + /** @type {GeoJSONFeature} */ (json)); break; case 'GeometryCollection': result = this.parseGeometryCollection_( - /** @type {GeoJSONGeometryCollection} */ (json), opt_options); + /** @type {GeoJSONGeometryCollection} */ (json)); break; case 'Point': result = this.parsePoint_( - /** @type {GeoJSONGeometry} */ (json), opt_options); + /** @type {GeoJSONGeometry} */ (json)); break; case 'LineString': result = this.parseLineString_( - /** @type {GeoJSONGeometry} */ (json), opt_options); + /** @type {GeoJSONGeometry} */ (json)); break; case 'Polygon': result = this.parsePolygon_( - /** @type {GeoJSONGeometry} */ (json), opt_options); + /** @type {GeoJSONGeometry} */ (json)); break; case 'MultiPoint': result = this.parseMultiPoint_( - /** @type {GeoJSONGeometry} */ (json), opt_options); + /** @type {GeoJSONGeometry} */ (json)); break; case 'MultiLineString': result = this.parseMultiLineString_( - /** @type {GeoJSONGeometry} */ (json), opt_options); + /** @type {GeoJSONGeometry} */ (json)); break; case 'MultiPolygon': result = this.parseMultiPolygon_( - /** @type {GeoJSONGeometry} */ (json), opt_options); + /** @type {GeoJSONGeometry} */ (json)); break; default: throw new Error('GeoJSON parsing not implemented for type: ' + json.type); @@ -91,27 +106,55 @@ ol.parser.GeoJSON.prototype.parse_ = function(json, opt_options) { /** * @param {GeoJSONFeature} json GeoJSON feature. - * @param {ol.parser.GeoJSON.ReadOptions=} opt_options Read options. + * @param {ol.parser.ReadFeaturesOptions=} opt_options Read options. * @return {ol.Feature} Parsed feature. * @private */ ol.parser.GeoJSON.prototype.parseFeature_ = function(json, opt_options) { var geomJson = json.geometry, - geometry = null; + geometry = null, + options = opt_options || {}; + var feature = new ol.Feature(json.properties); if (geomJson) { - geometry = /** @type {ol.geom.Geometry} */ (this.parse_( - /** @type {GeoJSONGeometry} */ (geomJson), opt_options)); + var type = geomJson.type; + var callback = options.callback; + var sharedVertices; + if (callback) { + goog.asserts.assert(type in ol.parser.GeoJSON.GeometryType, + 'Bad geometry type: ' + type); + sharedVertices = callback(feature, ol.parser.GeoJSON.GeometryType[type]); + } + switch (type) { + case 'Point': + geometry = this.parsePoint_(geomJson, sharedVertices); + break; + case 'LineString': + geometry = this.parseLineString_(geomJson, sharedVertices); + break; + case 'Polygon': + geometry = this.parsePolygon_(geomJson, sharedVertices); + break; + case 'MultiPoint': + geometry = this.parseMultiPoint_(geomJson, sharedVertices); + break; + case 'MultiLineString': + geometry = this.parseMultiLineString_(geomJson, sharedVertices); + break; + case 'MultiPolygon': + geometry = this.parseMultiPolygon_(geomJson, sharedVertices); + break; + default: + throw new Error('Bad geometry type: ' + type); + } + feature.setGeometry(geometry); } - var feature = new ol.Feature(); - feature.setGeometry(geometry); - feature.setValues(json.properties); return feature; }; /** * @param {GeoJSONFeatureCollection} json GeoJSON feature collection. - * @param {ol.parser.GeoJSON.ReadOptions=} opt_options Read options. + * @param {ol.parser.ReadFeaturesOptions=} opt_options Read options. * @return {Array.} Parsed array of features. * @private */ @@ -123,7 +166,7 @@ ol.parser.GeoJSON.prototype.parseFeatureCollection_ = function( i; for (i = 0; i < len; ++i) { - result[i] = this.parse_( + result[i] = this.parseFeature_( /** @type {GeoJSONFeature} */ (features[i]), opt_options); } return result; @@ -132,20 +175,17 @@ ol.parser.GeoJSON.prototype.parseFeatureCollection_ = function( /** * @param {GeoJSONGeometryCollection} json GeoJSON geometry collection. - * @param {ol.parser.GeoJSON.ReadOptions=} opt_options Read options. * @return {Array.} Parsed array of geometries. * @private */ -ol.parser.GeoJSON.prototype.parseGeometryCollection_ = function( - json, opt_options) { +ol.parser.GeoJSON.prototype.parseGeometryCollection_ = function(json) { var geometries = json.geometries, len = geometries.length, result = new Array(len), i; for (i = 0; i < len; ++i) { - result[i] = this.parse_( - /** @type {GeoJSONGeometry} */ (geometries[i]), opt_options); + result[i] = this.parse_(/** @type {GeoJSONGeometry} */ (geometries[i])); } return result; }; @@ -153,81 +193,80 @@ ol.parser.GeoJSON.prototype.parseGeometryCollection_ = function( /** * @param {GeoJSONGeometry} json GeoJSON linestring. - * @param {ol.parser.GeoJSON.ReadOptions=} opt_options Read options. + * @param {ol.geom.SharedVertices=} opt_vertices Shared vertices. * @return {ol.geom.LineString} Parsed linestring. * @private */ -ol.parser.GeoJSON.prototype.parseLineString_ = function(json, opt_options) { - var vertices = opt_options && opt_options.lineVertices; - return new ol.geom.LineString(json.coordinates, vertices); +ol.parser.GeoJSON.prototype.parseLineString_ = function(json, opt_vertices) { + return new ol.geom.LineString(json.coordinates, opt_vertices); }; /** * @param {GeoJSONGeometry} json GeoJSON multi-linestring. - * @param {ol.parser.GeoJSON.ReadOptions=} opt_options Read options. + * @param {ol.geom.SharedVertices=} opt_vertices Shared vertices. * @return {ol.geom.MultiLineString} Parsed multi-linestring. * @private */ ol.parser.GeoJSON.prototype.parseMultiLineString_ = function( - json, opt_options) { - var vertices = opt_options && opt_options.lineVertices; - return new ol.geom.MultiLineString(json.coordinates, vertices); + json, opt_vertices) { + return new ol.geom.MultiLineString(json.coordinates, opt_vertices); }; /** * @param {GeoJSONGeometry} json GeoJSON multi-point. - * @param {ol.parser.GeoJSON.ReadOptions=} opt_options Read options. + * @param {ol.geom.SharedVertices=} opt_vertices Shared vertices. * @return {ol.geom.MultiPoint} Parsed multi-point. * @private */ -ol.parser.GeoJSON.prototype.parseMultiPoint_ = function(json, opt_options) { - var vertices = opt_options && opt_options.pointVertices; - return new ol.geom.MultiPoint(json.coordinates, vertices); +ol.parser.GeoJSON.prototype.parseMultiPoint_ = function(json, opt_vertices) { + return new ol.geom.MultiPoint(json.coordinates, opt_vertices); }; /** * @param {GeoJSONGeometry} json GeoJSON multi-polygon. - * @param {ol.parser.GeoJSON.ReadOptions=} opt_options Read options. + * @param {ol.geom.SharedVertices=} opt_vertices Shared vertices. * @return {ol.geom.MultiPolygon} Parsed multi-polygon. * @private */ -ol.parser.GeoJSON.prototype.parseMultiPolygon_ = function(json, opt_options) { - var vertices = opt_options && opt_options.polygonVertices; - return new ol.geom.MultiPolygon(json.coordinates, vertices); +ol.parser.GeoJSON.prototype.parseMultiPolygon_ = function(json, opt_vertices) { + return new ol.geom.MultiPolygon(json.coordinates, opt_vertices); }; /** * @param {GeoJSONGeometry} json GeoJSON point. - * @param {ol.parser.GeoJSON.ReadOptions=} opt_options Read options. - * @return {ol.geom.Point} Parsed multi-point. + * @param {ol.geom.SharedVertices=} opt_vertices Shared vertices. + * @return {ol.geom.Point} Parsed point. * @private */ -ol.parser.GeoJSON.prototype.parsePoint_ = function(json, opt_options) { - var vertices = opt_options && opt_options.pointVertices; - return new ol.geom.Point(json.coordinates, vertices); +ol.parser.GeoJSON.prototype.parsePoint_ = function(json, opt_vertices) { + return new ol.geom.Point(json.coordinates, opt_vertices); }; /** * @param {GeoJSONGeometry} json GeoJSON polygon. - * @param {ol.parser.GeoJSON.ReadOptions=} opt_options Read options. + * @param {ol.geom.SharedVertices=} opt_vertices Shared vertices. * @return {ol.geom.Polygon} Parsed polygon. * @private */ -ol.parser.GeoJSON.prototype.parsePolygon_ = function(json, opt_options) { - var vertices = opt_options && opt_options.polygonVertices; - return new ol.geom.Polygon(json.coordinates, vertices); +ol.parser.GeoJSON.prototype.parsePolygon_ = function(json, opt_vertices) { + return new ol.geom.Polygon(json.coordinates, opt_vertices); }; /** - * @typedef {{pointVertices: (ol.geom.SharedVertices|undefined), - * lineVertices: (ol.geom.SharedVertices|undefined), - * polygonVertices: (ol.geom.SharedVertices|undefined)}} - * TODO: add support for toProjection + * @enum {ol.geom.GeometryType} */ -ol.parser.GeoJSON.ReadOptions; +ol.parser.GeoJSON.GeometryType = { + 'Point': ol.geom.GeometryType.POINT, + 'LineString': ol.geom.GeometryType.LINESTRING, + 'Polygon': ol.geom.GeometryType.POLYGON, + 'MultiPoint': ol.geom.GeometryType.MULTIPOINT, + 'MultiLineString': ol.geom.GeometryType.MULTILINESTRING, + 'MultiPolygon': ol.geom.GeometryType.MULTIPOLYGON, + 'GeometryCollection': ol.geom.GeometryType.GEOMETRYCOLLECTION +}; diff --git a/test/spec/ol/parser/geojson.test.js b/test/spec/ol/parser/geojson.test.js index 16a807125e..ceee0b5a6b 100644 --- a/test/spec/ol/parser/geojson.test.js +++ b/test/spec/ol/parser/geojson.test.js @@ -174,11 +174,20 @@ describe('ol.parser.GeoJSON', function() { var lineVertices = new ol.geom.SharedVertices(); var polygonVertices = new ol.geom.SharedVertices(); - var result = parser.read(text, { - pointVertices: pointVertices, - lineVertices: lineVertices, - polygonVertices: polygonVertices - }); + var lookup = { + 'point': pointVertices, + 'linestring': lineVertices, + 'polygon': polygonVertices, + 'multipoint': pointVertices, + 'multilinstring': lineVertices, + 'multipolygon': polygonVertices + }; + + var callback = function(feature, type) { + return lookup[type]; + } + + var result = parser.readFeaturesFromString(text, {callback: callback}); expect(result.length).toBe(179); expect(pointVertices.coordinates.length).toBe(0);