From 534a178a49bfcb7fe09eb3ec0a35e623148b921c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Tue, 8 Jul 2014 16:42:25 +0200 Subject: [PATCH 01/33] Add target/sourceProjection to ol.format.Feature#read* --- src/ol/format/featureformat.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/ol/format/featureformat.js b/src/ol/format/featureformat.js index 2cf35fb1f6..41026bfa02 100644 --- a/src/ol/format/featureformat.js +++ b/src/ol/format/featureformat.js @@ -35,6 +35,8 @@ ol.format.Feature.prototype.getType = goog.abstractMethod; * Read a single feature from a source. * * @param {ArrayBuffer|Document|Node|Object|string} source Source. + * @param {ol.proj.ProjectionLike=} opt_targetProjection Target projection. + * @param {ol.proj.ProjectionLike=} opt_sourceProjection Source projection. * @return {ol.Feature} Feature. */ ol.format.Feature.prototype.readFeature = goog.abstractMethod; @@ -44,6 +46,8 @@ ol.format.Feature.prototype.readFeature = goog.abstractMethod; * Read all features from a source. * * @param {ArrayBuffer|Document|Node|Object|string} source Source. + * @param {ol.proj.ProjectionLike=} opt_targetProjection Target projection. + * @param {ol.proj.ProjectionLike=} opt_sourceProjection Source projection. * @return {Array.} Features. */ ol.format.Feature.prototype.readFeatures = goog.abstractMethod; @@ -53,6 +57,8 @@ ol.format.Feature.prototype.readFeatures = goog.abstractMethod; * Read a single geometry from a source. * * @param {ArrayBuffer|Document|Node|Object|string} source Source. + * @param {ol.proj.ProjectionLike=} opt_targetProjection Target projection. + * @param {ol.proj.ProjectionLike=} opt_sourceProjection Source projection. * @return {ol.geom.Geometry} Geometry. */ ol.format.Feature.prototype.readGeometry = goog.abstractMethod; From d13261a21a7288536fc0a654697c1970e9c661d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Tue, 8 Jul 2014 16:43:00 +0200 Subject: [PATCH 02/33] Add target/sourceProjection to ol.format.JSONFeature#read* --- src/ol/format/jsonfeatureformat.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/ol/format/jsonfeatureformat.js b/src/ol/format/jsonfeatureformat.js index 912c6f01c5..ae3a04be53 100644 --- a/src/ol/format/jsonfeatureformat.js +++ b/src/ol/format/jsonfeatureformat.js @@ -72,6 +72,8 @@ ol.format.JSONFeature.prototype.readFeatures = function(source) { /** * @param {Object} object Object. + * @param {ol.proj.ProjectionLike=} opt_targetProjection Target projection. + * @param {ol.proj.ProjectionLike=} opt_sourceProjection Source projection. * @protected * @return {ol.Feature} Feature. */ @@ -80,6 +82,8 @@ ol.format.JSONFeature.prototype.readFeatureFromObject = goog.abstractMethod; /** * @param {Object} object Object. + * @param {ol.proj.ProjectionLike=} opt_targetProjection Target projection. + * @param {ol.proj.ProjectionLike=} opt_sourceProjection Source projection. * @protected * @return {Array.} Features. */ @@ -96,6 +100,8 @@ ol.format.JSONFeature.prototype.readGeometry = function(source) { /** * @param {Object} object Object. + * @param {ol.proj.ProjectionLike=} opt_targetProjection Target projection. + * @param {ol.proj.ProjectionLike=} opt_sourceProjection Source projection. * @protected * @return {ol.geom.Geometry} Geometry. */ From 225791c969dcf86dc3e0de057cec1245c123e3a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Tue, 8 Jul 2014 16:43:16 +0200 Subject: [PATCH 03/33] Add target/sourceProjection to ol.format.GeoJSON#read* --- src/ol/format/geojsonformat.js | 62 ++++++++++++++++++++++++++++------ 1 file changed, 51 insertions(+), 11 deletions(-) diff --git a/src/ol/format/geojsonformat.js b/src/ol/format/geojsonformat.js index 8f7d03007c..18847ff2db 100644 --- a/src/ol/format/geojsonformat.js +++ b/src/ol/format/geojsonformat.js @@ -64,28 +64,46 @@ ol.format.GeoJSON.EXTENSIONS_ = ['.geojson']; /** * @param {GeoJSONObject} object Object. + * @param {ol.proj.Projection} targetProjection Target projection. + * @param {ol.proj.Projection} sourceProjection Source projection. * @private * @return {ol.geom.Geometry} Geometry. */ -ol.format.GeoJSON.readGeometry_ = function(object) { +ol.format.GeoJSON.readGeometry_ = function( + object, targetProjection, sourceProjection) { if (goog.isNull(object)) { return null; } var geometryReader = ol.format.GeoJSON.GEOMETRY_READERS_[object.type]; goog.asserts.assert(goog.isDef(geometryReader)); - return geometryReader(object); + var geometry = geometryReader(object); + if (!goog.isNull(targetProjection) && !goog.isNull(sourceProjection) && + !ol.proj.equivalent(targetProjection, sourceProjection)) { + geometry.transform(sourceProjection, targetProjection); + } + return geometry; }; /** * @param {GeoJSONGeometryCollection} object Object. + * @param {ol.proj.Projection} targetProjection Target projection. + * @param {ol.proj.Projection} sourceProjection Source projection. * @private * @return {ol.geom.GeometryCollection} Geometry collection. */ -ol.format.GeoJSON.readGeometryCollectionGeometry_ = function(object) { +ol.format.GeoJSON.readGeometryCollectionGeometry_ = function( + object, targetProjection, sourceProjection) { goog.asserts.assert(object.type == 'GeometryCollection'); - var geometries = goog.array.map( - object.geometries, ol.format.GeoJSON.readGeometry_); + var geometries = goog.array.map(object.geometries, + /** + * @param {GeoJSONObject} geometry Geometry. + * @return {ol.geom.Geometry} geometry Geometry. + */ + function(geometry) { + return ol.format.GeoJSON.readGeometry_( + geometry, targetProjection, sourceProjection); + }); return new ol.geom.GeometryCollection(geometries); }; @@ -330,6 +348,8 @@ ol.format.GeoJSON.prototype.getExtensions = function() { * * @function * @param {ArrayBuffer|Document|Node|Object|string} source Source. + * @param {ol.proj.ProjectionLike=} opt_targetProjection Target projection. + * @param {ol.proj.ProjectionLike=} opt_sourceProjection Source projection. * @return {ol.Feature} Feature. * @api */ @@ -342,6 +362,8 @@ ol.format.GeoJSON.prototype.readFeature; * * @function * @param {ArrayBuffer|Document|Node|Object|string} source Source. + * @param {ol.proj.ProjectionLike=} opt_targetProjection Target projection. + * @param {ol.proj.ProjectionLike=} opt_sourceProjection Source projection. * @return {Array.} Features. * @api */ @@ -351,10 +373,17 @@ ol.format.GeoJSON.prototype.readFeatures; /** * @inheritDoc */ -ol.format.GeoJSON.prototype.readFeatureFromObject = function(object) { +ol.format.GeoJSON.prototype.readFeatureFromObject = function( + object, opt_targetProjection, opt_sourceProjection) { var geoJSONFeature = /** @type {GeoJSONFeature} */ (object); goog.asserts.assert(geoJSONFeature.type == 'Feature'); - var geometry = ol.format.GeoJSON.readGeometry_(geoJSONFeature.geometry); + var targetProjection = goog.isDef(opt_targetProjection) ? + ol.proj.get(opt_targetProjection) : null; + var sourceProjection = goog.isDef(opt_sourceProjection) ? + ol.proj.get(opt_sourceProjection) : + this.readProjectionFromObject(object); + var geometry = ol.format.GeoJSON.readGeometry_(geoJSONFeature.geometry, + targetProjection, sourceProjection); var feature = new ol.Feature(); if (goog.isDef(this.geometryName_)) { feature.setGeometryName(this.geometryName_); @@ -373,7 +402,8 @@ ol.format.GeoJSON.prototype.readFeatureFromObject = function(object) { /** * @inheritDoc */ -ol.format.GeoJSON.prototype.readFeaturesFromObject = function(object) { +ol.format.GeoJSON.prototype.readFeaturesFromObject = function( + object, opt_targetProjection, opt_sourceProjection) { var geoJSONObject = /** @type {GeoJSONObject} */ (object); if (geoJSONObject.type == 'Feature') { return [this.readFeatureFromObject(object)]; @@ -385,7 +415,8 @@ ol.format.GeoJSON.prototype.readFeaturesFromObject = function(object) { var geoJSONFeatures = geoJSONFeatureCollection.features; var i, ii; for (i = 0, ii = geoJSONFeatures.length; i < ii; ++i) { - features.push(this.readFeatureFromObject(geoJSONFeatures[i])); + features.push(this.readFeatureFromObject(geoJSONFeatures[i], + opt_targetProjection, opt_sourceProjection)); } return features; } else { @@ -400,6 +431,8 @@ ol.format.GeoJSON.prototype.readFeaturesFromObject = function(object) { * * @function * @param {ArrayBuffer|Document|Node|Object|string} source Source. + * @param {ol.proj.ProjectionLike=} opt_targetProjection Target projection. + * @param {ol.proj.ProjectionLike=} opt_sourceProjection Source projection. * @return {ol.geom.Geometry} Geometry. * @api */ @@ -409,9 +442,16 @@ ol.format.GeoJSON.prototype.readGeometry; /** * @inheritDoc */ -ol.format.GeoJSON.prototype.readGeometryFromObject = function(object) { +ol.format.GeoJSON.prototype.readGeometryFromObject = function( + object, opt_targetProjection, opt_sourceProjection) { + var targetProjection = goog.isDef(opt_targetProjection) ? + ol.proj.get(opt_targetProjection) : null; + var sourceProjection = goog.isDef(opt_sourceProjection) ? + ol.proj.get(opt_sourceProjection) : + this.readProjectionFromObject(object); return ol.format.GeoJSON.readGeometry_( - /** @type {GeoJSONGeometry} */ (object)); + /** @type {GeoJSONGeometry} */ (object), + targetProjection, sourceProjection); }; From 0ea55b7f27053943a28f09e4df82c9224bc2b7c3 Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Fri, 18 Jul 2014 20:47:36 +0200 Subject: [PATCH 04/33] Use a ReadFeatures object instead of sourceProjection/targetProjection --- externs/olx.js | 23 ++++++++++++ src/ol/format/featureformat.js | 9 ++--- src/ol/format/geojsonformat.js | 58 ++++++++++++------------------ src/ol/format/jsonfeatureformat.js | 9 ++--- 4 files changed, 52 insertions(+), 47 deletions(-) diff --git a/externs/olx.js b/externs/olx.js index 8ada72db1a..b0fd30c027 100644 --- a/externs/olx.js +++ b/externs/olx.js @@ -1144,6 +1144,29 @@ olx.control.ZoomToExtentOptions.prototype.tipLabel; olx.control.ZoomToExtentOptions.prototype.extent; +/** + * @typedef {{dataProjection: (ol.proj.ProjectionLike|undefined), + * featureProjection: (ol.proj.ProjectionLike|undefined)}} + */ +olx.format.ReadOptions; + + +/** + * Projection of the data we are reading. Default is the projection derived from + * the data. + * @type {ol.proj.ProjectionLike|undefined} + */ +olx.format.ReadOptions.prototype.dataProjection; + + +/** + * Projection of the feature geometries created by the format reader. Default + * is the `dataProjection`. + * @type {ol.proj.ProjectionLike|undefined} + */ +olx.format.ReadOptions.prototype.featureProjection; + + /** * @typedef {{defaultProjection: ol.proj.ProjectionLike, * geometryName: (string|undefined)}} diff --git a/src/ol/format/featureformat.js b/src/ol/format/featureformat.js index 41026bfa02..c466747771 100644 --- a/src/ol/format/featureformat.js +++ b/src/ol/format/featureformat.js @@ -35,8 +35,7 @@ ol.format.Feature.prototype.getType = goog.abstractMethod; * Read a single feature from a source. * * @param {ArrayBuffer|Document|Node|Object|string} source Source. - * @param {ol.proj.ProjectionLike=} opt_targetProjection Target projection. - * @param {ol.proj.ProjectionLike=} opt_sourceProjection Source projection. + * @param {olx.format.ReadOptions=} opt_options Read options. * @return {ol.Feature} Feature. */ ol.format.Feature.prototype.readFeature = goog.abstractMethod; @@ -46,8 +45,7 @@ ol.format.Feature.prototype.readFeature = goog.abstractMethod; * Read all features from a source. * * @param {ArrayBuffer|Document|Node|Object|string} source Source. - * @param {ol.proj.ProjectionLike=} opt_targetProjection Target projection. - * @param {ol.proj.ProjectionLike=} opt_sourceProjection Source projection. + * @param {olx.format.ReadOptions=} opt_options Read options. * @return {Array.} Features. */ ol.format.Feature.prototype.readFeatures = goog.abstractMethod; @@ -57,8 +55,7 @@ ol.format.Feature.prototype.readFeatures = goog.abstractMethod; * Read a single geometry from a source. * * @param {ArrayBuffer|Document|Node|Object|string} source Source. - * @param {ol.proj.ProjectionLike=} opt_targetProjection Target projection. - * @param {ol.proj.ProjectionLike=} opt_sourceProjection Source projection. + * @param {olx.format.ReadOptions=} opt_options Read options. * @return {ol.geom.Geometry} Geometry. */ ol.format.Feature.prototype.readGeometry = goog.abstractMethod; diff --git a/src/ol/format/geojsonformat.js b/src/ol/format/geojsonformat.js index 18847ff2db..1bfceb9742 100644 --- a/src/ol/format/geojsonformat.js +++ b/src/ol/format/geojsonformat.js @@ -64,22 +64,26 @@ ol.format.GeoJSON.EXTENSIONS_ = ['.geojson']; /** * @param {GeoJSONObject} object Object. - * @param {ol.proj.Projection} targetProjection Target projection. - * @param {ol.proj.Projection} sourceProjection Source projection. + * @param {olx.format.ReadOptions=} opt_options Read options. * @private * @return {ol.geom.Geometry} Geometry. */ -ol.format.GeoJSON.readGeometry_ = function( - object, targetProjection, sourceProjection) { +ol.format.GeoJSON.readGeometry_ = function(object, opt_options) { if (goog.isNull(object)) { return null; } + var featureProjection = goog.isDef(opt_options) && + goog.isDef(opt_options.featureProjection) ? + ol.proj.get(opt_options.featureProjection) : null; + var dataProjection = goog.isDef(opt_options) && + goog.isDef(opt_options.dataProjection) ? + ol.proj.get(opt_options.dataProjection) : null; var geometryReader = ol.format.GeoJSON.GEOMETRY_READERS_[object.type]; goog.asserts.assert(goog.isDef(geometryReader)); var geometry = geometryReader(object); - if (!goog.isNull(targetProjection) && !goog.isNull(sourceProjection) && - !ol.proj.equivalent(targetProjection, sourceProjection)) { - geometry.transform(sourceProjection, targetProjection); + if (!goog.isNull(featureProjection) && !goog.isNull(dataProjection) && + !ol.proj.equivalent(featureProjection, dataProjection)) { + geometry.transform(dataProjection, featureProjection); } return geometry; }; @@ -87,13 +91,12 @@ ol.format.GeoJSON.readGeometry_ = function( /** * @param {GeoJSONGeometryCollection} object Object. - * @param {ol.proj.Projection} targetProjection Target projection. - * @param {ol.proj.Projection} sourceProjection Source projection. + * @param {olx.format.ReadOptions=} opt_options Read options. * @private * @return {ol.geom.GeometryCollection} Geometry collection. */ ol.format.GeoJSON.readGeometryCollectionGeometry_ = function( - object, targetProjection, sourceProjection) { + object, opt_options) { goog.asserts.assert(object.type == 'GeometryCollection'); var geometries = goog.array.map(object.geometries, /** @@ -101,8 +104,7 @@ ol.format.GeoJSON.readGeometryCollectionGeometry_ = function( * @return {ol.geom.Geometry} geometry Geometry. */ function(geometry) { - return ol.format.GeoJSON.readGeometry_( - geometry, targetProjection, sourceProjection); + return ol.format.GeoJSON.readGeometry_(geometry, opt_options); }); return new ol.geom.GeometryCollection(geometries); }; @@ -348,8 +350,7 @@ ol.format.GeoJSON.prototype.getExtensions = function() { * * @function * @param {ArrayBuffer|Document|Node|Object|string} source Source. - * @param {ol.proj.ProjectionLike=} opt_targetProjection Target projection. - * @param {ol.proj.ProjectionLike=} opt_sourceProjection Source projection. + * @param {olx.format.ReadOptions=} opt_options Read options. * @return {ol.Feature} Feature. * @api */ @@ -362,8 +363,7 @@ ol.format.GeoJSON.prototype.readFeature; * * @function * @param {ArrayBuffer|Document|Node|Object|string} source Source. - * @param {ol.proj.ProjectionLike=} opt_targetProjection Target projection. - * @param {ol.proj.ProjectionLike=} opt_sourceProjection Source projection. + * @param {olx.format.ReadOptions=} opt_options Read options. * @return {Array.} Features. * @api */ @@ -374,16 +374,11 @@ ol.format.GeoJSON.prototype.readFeatures; * @inheritDoc */ ol.format.GeoJSON.prototype.readFeatureFromObject = function( - object, opt_targetProjection, opt_sourceProjection) { + object, opt_options) { var geoJSONFeature = /** @type {GeoJSONFeature} */ (object); goog.asserts.assert(geoJSONFeature.type == 'Feature'); - var targetProjection = goog.isDef(opt_targetProjection) ? - ol.proj.get(opt_targetProjection) : null; - var sourceProjection = goog.isDef(opt_sourceProjection) ? - ol.proj.get(opt_sourceProjection) : - this.readProjectionFromObject(object); var geometry = ol.format.GeoJSON.readGeometry_(geoJSONFeature.geometry, - targetProjection, sourceProjection); + opt_options); var feature = new ol.Feature(); if (goog.isDef(this.geometryName_)) { feature.setGeometryName(this.geometryName_); @@ -403,7 +398,7 @@ ol.format.GeoJSON.prototype.readFeatureFromObject = function( * @inheritDoc */ ol.format.GeoJSON.prototype.readFeaturesFromObject = function( - object, opt_targetProjection, opt_sourceProjection) { + object, opt_options) { var geoJSONObject = /** @type {GeoJSONObject} */ (object); if (geoJSONObject.type == 'Feature') { return [this.readFeatureFromObject(object)]; @@ -416,7 +411,7 @@ ol.format.GeoJSON.prototype.readFeaturesFromObject = function( var i, ii; for (i = 0, ii = geoJSONFeatures.length; i < ii; ++i) { features.push(this.readFeatureFromObject(geoJSONFeatures[i], - opt_targetProjection, opt_sourceProjection)); + opt_options)); } return features; } else { @@ -431,8 +426,7 @@ ol.format.GeoJSON.prototype.readFeaturesFromObject = function( * * @function * @param {ArrayBuffer|Document|Node|Object|string} source Source. - * @param {ol.proj.ProjectionLike=} opt_targetProjection Target projection. - * @param {ol.proj.ProjectionLike=} opt_sourceProjection Source projection. + * @param {olx.format.ReadOptions=} opt_options Read options. * @return {ol.geom.Geometry} Geometry. * @api */ @@ -443,15 +437,9 @@ ol.format.GeoJSON.prototype.readGeometry; * @inheritDoc */ ol.format.GeoJSON.prototype.readGeometryFromObject = function( - object, opt_targetProjection, opt_sourceProjection) { - var targetProjection = goog.isDef(opt_targetProjection) ? - ol.proj.get(opt_targetProjection) : null; - var sourceProjection = goog.isDef(opt_sourceProjection) ? - ol.proj.get(opt_sourceProjection) : - this.readProjectionFromObject(object); + object, opt_options) { return ol.format.GeoJSON.readGeometry_( - /** @type {GeoJSONGeometry} */ (object), - targetProjection, sourceProjection); + /** @type {GeoJSONGeometry} */ (object), opt_options); }; diff --git a/src/ol/format/jsonfeatureformat.js b/src/ol/format/jsonfeatureformat.js index ae3a04be53..edecc8497c 100644 --- a/src/ol/format/jsonfeatureformat.js +++ b/src/ol/format/jsonfeatureformat.js @@ -72,8 +72,7 @@ ol.format.JSONFeature.prototype.readFeatures = function(source) { /** * @param {Object} object Object. - * @param {ol.proj.ProjectionLike=} opt_targetProjection Target projection. - * @param {ol.proj.ProjectionLike=} opt_sourceProjection Source projection. + * @param {olx.format.ReadOptions=} opt_options Read options. * @protected * @return {ol.Feature} Feature. */ @@ -82,8 +81,7 @@ ol.format.JSONFeature.prototype.readFeatureFromObject = goog.abstractMethod; /** * @param {Object} object Object. - * @param {ol.proj.ProjectionLike=} opt_targetProjection Target projection. - * @param {ol.proj.ProjectionLike=} opt_sourceProjection Source projection. + * @param {olx.format.ReadOptions=} opt_options Read options. * @protected * @return {Array.} Features. */ @@ -100,8 +98,7 @@ ol.format.JSONFeature.prototype.readGeometry = function(source) { /** * @param {Object} object Object. - * @param {ol.proj.ProjectionLike=} opt_targetProjection Target projection. - * @param {ol.proj.ProjectionLike=} opt_sourceProjection Source projection. + * @param {olx.format.ReadOptions=} opt_options Read options. * @protected * @return {ol.geom.Geometry} Geometry. */ From 3245b8c6af14909a51e454be8d59232c945a0fc0 Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Fri, 18 Jul 2014 20:48:36 +0200 Subject: [PATCH 05/33] Update read* signatures in ol.format.JSONFeature to use options --- src/ol/format/jsonfeatureformat.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ol/format/jsonfeatureformat.js b/src/ol/format/jsonfeatureformat.js index edecc8497c..1d222eb732 100644 --- a/src/ol/format/jsonfeatureformat.js +++ b/src/ol/format/jsonfeatureformat.js @@ -57,16 +57,16 @@ ol.format.JSONFeature.prototype.getType = function() { /** * @inheritDoc */ -ol.format.JSONFeature.prototype.readFeature = function(source) { - return this.readFeatureFromObject(this.getObject_(source)); +ol.format.JSONFeature.prototype.readFeature = function(source, opt_options) { + return this.readFeatureFromObject(this.getObject_(source), opt_options); }; /** * @inheritDoc */ -ol.format.JSONFeature.prototype.readFeatures = function(source) { - return this.readFeaturesFromObject(this.getObject_(source)); +ol.format.JSONFeature.prototype.readFeatures = function(source, opt_options) { + return this.readFeaturesFromObject(this.getObject_(source), opt_options); }; @@ -91,8 +91,8 @@ ol.format.JSONFeature.prototype.readFeaturesFromObject = goog.abstractMethod; /** * @inheritDoc */ -ol.format.JSONFeature.prototype.readGeometry = function(source) { - return this.readGeometryFromObject(this.getObject_(source)); +ol.format.JSONFeature.prototype.readGeometry = function(source, opt_options) { + return this.readGeometryFromObject(this.getObject_(source), opt_options); }; From b0d95b326a6962d197e8e8f9a061c805db0b01e5 Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Fri, 18 Jul 2014 20:49:12 +0200 Subject: [PATCH 06/33] Introduce WriteOptions for feature formats --- externs/olx.js | 22 +++++++++++++++++++++- src/ol/format/featureformat.js | 3 +++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/externs/olx.js b/externs/olx.js index b0fd30c027..16af4ed0c2 100644 --- a/externs/olx.js +++ b/externs/olx.js @@ -1167,6 +1167,27 @@ olx.format.ReadOptions.prototype.dataProjection; olx.format.ReadOptions.prototype.featureProjection; +/** + * @typedef {{dataProjection: (ol.proj.ProjectionLike|undefined), + * featureProjection: ol.proj.ProjectionLike}} + */ +olx.format.WriteOptions; + + +/** + * Projection of the data we are writing. Default is the `featureProjection`. + * @type {ol.proj.ProjectionLike|undefined} + */ +olx.format.WriteOptions.prototype.dataProjection; + + +/** + * Projection of the feature geometries serialized by the format writer. + * @type {ol.proj.ProjectionLike} + */ +olx.format.WriteOptions.prototype.featureProjection; + + /** * @typedef {{defaultProjection: ol.proj.ProjectionLike, * geometryName: (string|undefined)}} @@ -1203,7 +1224,6 @@ olx.format.PolylineOptions; olx.format.PolylineOptions.prototype.factor; - /** * @typedef {{defaultProjection: ol.proj.ProjectionLike}} * @api diff --git a/src/ol/format/featureformat.js b/src/ol/format/featureformat.js index c466747771..83ae7e6c18 100644 --- a/src/ol/format/featureformat.js +++ b/src/ol/format/featureformat.js @@ -74,6 +74,7 @@ ol.format.Feature.prototype.readProjection = goog.abstractMethod; * Encode a feature in this format. * * @param {ol.Feature} feature Feature. + * @param {olx.format.WriteOptions=} opt_options Write options. * @return {ArrayBuffer|Node|Object|string} Result. */ ol.format.Feature.prototype.writeFeature = goog.abstractMethod; @@ -83,6 +84,7 @@ ol.format.Feature.prototype.writeFeature = goog.abstractMethod; * Encode an array of features in this format. * * @param {Array.} features Features. + * @param {olx.format.WriteOptions=} opt_options Write options. * @return {ArrayBuffer|Node|Object|string} Result. */ ol.format.Feature.prototype.writeFeatures = goog.abstractMethod; @@ -92,6 +94,7 @@ ol.format.Feature.prototype.writeFeatures = goog.abstractMethod; * Write a single geometry in this format. * * @param {ol.geom.Geometry} geometry Geometry. + * @param {olx.format.WriteOptions=} opt_options Write options. * @return {ArrayBuffer|Node|Object|string} Node. */ ol.format.Feature.prototype.writeGeometry = goog.abstractMethod; From 8aa799850dfed59fd7734592eeec9783c8006571 Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Fri, 18 Jul 2014 20:50:04 +0200 Subject: [PATCH 07/33] Add write transform capability to ol.format.JSONFeature --- src/ol/format/jsonfeatureformat.js | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/ol/format/jsonfeatureformat.js b/src/ol/format/jsonfeatureformat.js index 1d222eb732..17fadac0d7 100644 --- a/src/ol/format/jsonfeatureformat.js +++ b/src/ol/format/jsonfeatureformat.js @@ -124,13 +124,14 @@ ol.format.JSONFeature.prototype.readProjectionFromObject = goog.abstractMethod; /** * @inheritDoc */ -ol.format.JSONFeature.prototype.writeFeature = function(feature) { - return this.writeFeatureObject(feature); +ol.format.JSONFeature.prototype.writeFeature = function(feature, opt_options) { + return this.writeFeatureObject(feature, opt_options); }; /** * @param {ol.Feature} feature Feature. + * @param {olx.format.WriteOptions=} opt_options Write options. * @protected * @return {Object} Object. */ @@ -140,13 +141,15 @@ ol.format.JSONFeature.prototype.writeFeatureObject = goog.abstractMethod; /** * @inheritDoc */ -ol.format.JSONFeature.prototype.writeFeatures = function(features) { - return this.writeFeaturesObject(features); +ol.format.JSONFeature.prototype.writeFeatures = function( + features, opt_options) { + return this.writeFeaturesObject(features, opt_options); }; /** * @param {Array.} features Features. + * @param {olx.format.WriteOptions=} opt_options Write options. * @protected * @return {Object} Object. */ @@ -156,13 +159,15 @@ ol.format.JSONFeature.prototype.writeFeaturesObject = goog.abstractMethod; /** * @inheritDoc */ -ol.format.JSONFeature.prototype.writeGeometry = function(geometry) { - return this.writeGeometryObject(geometry); +ol.format.JSONFeature.prototype.writeGeometry = function( + geometry, opt_options) { + return this.writeGeometryObject(geometry, opt_options); }; /** * @param {ol.geom.Geometry} geometry Geometry. + * @param {olx.format.WriteOptions=} opt_options Write options. * @protected * @return {Object} Object. */ From 4c4a335448046544c004013d2808a8bb1254e3e7 Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Fri, 18 Jul 2014 20:50:26 +0200 Subject: [PATCH 08/33] Implement write transforms for ol.format.GeoJSON --- src/ol/format/geojsonformat.js | 38 +++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/src/ol/format/geojsonformat.js b/src/ol/format/geojsonformat.js index 1bfceb9742..4f03accc5b 100644 --- a/src/ol/format/geojsonformat.js +++ b/src/ol/format/geojsonformat.js @@ -178,13 +178,25 @@ ol.format.GeoJSON.readPolygonGeometry_ = function(object) { /** * @param {ol.geom.Geometry} geometry Geometry. + * @param {olx.format.WriteOptions=} opt_options Write options. * @private * @return {GeoJSONGeometry|GeoJSONGeometryCollection} GeoJSON geometry. */ -ol.format.GeoJSON.writeGeometry_ = function(geometry) { +ol.format.GeoJSON.writeGeometry_ = function(geometry, opt_options) { var geometryWriter = ol.format.GeoJSON.GEOMETRY_WRITERS_[geometry.getType()]; goog.asserts.assert(goog.isDef(geometryWriter)); - return geometryWriter(geometry); + var featureProjection = goog.isDef(opt_options) ? + ol.proj.get(opt_options.featureProjection) : null; + var dataProjection = goog.isDef(opt_options) && + goog.isDef(opt_options.dataProjection) ? + ol.proj.get(opt_options.dataProjection) : featureProjection; + if (!goog.isNull(featureProjection) && !goog.isNull(dataProjection) && + !ol.proj.equivalent(featureProjection, dataProjection)) { + return geometryWriter( + geometry.clone().transform(featureProjection, dataProjection)); + } else { + return geometryWriter(geometry); + } }; @@ -203,13 +215,17 @@ ol.format.GeoJSON.writeEmptyGeometryCollectionGeometry_ = function(geometry) { /** * @param {ol.geom.Geometry} geometry Geometry. + * @param {olx.format.WriteOptions=} opt_options Write options. * @private * @return {GeoJSONGeometryCollection} GeoJSON geometry collection. */ -ol.format.GeoJSON.writeGeometryCollectionGeometry_ = function(geometry) { +ol.format.GeoJSON.writeGeometryCollectionGeometry_ = function( + geometry, opt_options) { goog.asserts.assertInstanceof(geometry, ol.geom.GeometryCollection); var geometries = goog.array.map( - geometry.getGeometriesArray(), ol.format.GeoJSON.writeGeometry_); + geometry.getGeometriesArray(), function(geometry) { + return ol.format.GeoJSON.writeGeometry_(geometry, opt_options); + }); return /** @type {GeoJSONGeometryCollection} */ ({ 'type': 'GeometryCollection', 'geometries': geometries @@ -484,6 +500,7 @@ ol.format.GeoJSON.prototype.readProjectionFromObject = function(object) { * * @function * @param {ol.Feature} feature Feature. + * @param {olx.format.WriteOptions} options Write options. * @return {GeoJSONFeature} GeoJSON. * @api */ @@ -493,7 +510,8 @@ ol.format.GeoJSON.prototype.writeFeature; /** * @inheritDoc */ -ol.format.GeoJSON.prototype.writeFeatureObject = function(feature) { +ol.format.GeoJSON.prototype.writeFeatureObject = function( + feature, opt_options) { var object = { 'type': 'Feature' }; @@ -504,7 +522,8 @@ ol.format.GeoJSON.prototype.writeFeatureObject = function(feature) { var geometry = feature.getGeometry(); if (goog.isDefAndNotNull(geometry)) { goog.object.set( - object, 'geometry', ol.format.GeoJSON.writeGeometry_(geometry)); + object, 'geometry', + ol.format.GeoJSON.writeGeometry_(geometry, opt_options)); } var properties = feature.getProperties(); goog.object.remove(properties, 'geometry'); @@ -520,6 +539,7 @@ ol.format.GeoJSON.prototype.writeFeatureObject = function(feature) { * * @function * @param {Array.} features Features. + * @param {olx.format.WriteOptions} options Write options. * @return {GeoJSONObject} GeoJSON. * @api */ @@ -529,11 +549,12 @@ ol.format.GeoJSON.prototype.writeFeatures; /** * @inheritDoc */ -ol.format.GeoJSON.prototype.writeFeaturesObject = function(features) { +ol.format.GeoJSON.prototype.writeFeaturesObject = + function(features, opt_options) { var objects = []; var i, ii; for (i = 0, ii = features.length; i < ii; ++i) { - objects.push(this.writeFeatureObject(features[i])); + objects.push(this.writeFeatureObject(features[i], opt_options)); } return /** @type {GeoJSONFeatureCollection} */ ({ 'type': 'FeatureCollection', @@ -547,6 +568,7 @@ ol.format.GeoJSON.prototype.writeFeaturesObject = function(features) { * * @function * @param {ol.geom.Geometry} geometry Geometry. + * @param {olx.format.WriteOptions} options Write options. * @return {GeoJSONGeometry|GeoJSONGeometryCollection} GeoJSON. * @api */ From 464eb3ccf53f958e4c002e7c232ddc03e59bdd7d Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Mon, 28 Jul 2014 20:01:35 +0200 Subject: [PATCH 09/33] Make projection retrieval consistent --- src/ol/format/geojsonformat.js | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/ol/format/geojsonformat.js b/src/ol/format/geojsonformat.js index 4f03accc5b..7e2803ef0b 100644 --- a/src/ol/format/geojsonformat.js +++ b/src/ol/format/geojsonformat.js @@ -72,12 +72,10 @@ ol.format.GeoJSON.readGeometry_ = function(object, opt_options) { if (goog.isNull(object)) { return null; } - var featureProjection = goog.isDef(opt_options) && - goog.isDef(opt_options.featureProjection) ? - ol.proj.get(opt_options.featureProjection) : null; - var dataProjection = goog.isDef(opt_options) && - goog.isDef(opt_options.dataProjection) ? - ol.proj.get(opt_options.dataProjection) : null; + var featureProjection = goog.isDef(opt_options) ? + ol.proj.get(opt_options.featureProjection) : null; + var dataProjection = goog.isDef(opt_options) ? + ol.proj.get(opt_options.dataProjection) : null; var geometryReader = ol.format.GeoJSON.GEOMETRY_READERS_[object.type]; goog.asserts.assert(goog.isDef(geometryReader)); var geometry = geometryReader(object); @@ -187,9 +185,8 @@ ol.format.GeoJSON.writeGeometry_ = function(geometry, opt_options) { goog.asserts.assert(goog.isDef(geometryWriter)); var featureProjection = goog.isDef(opt_options) ? ol.proj.get(opt_options.featureProjection) : null; - var dataProjection = goog.isDef(opt_options) && - goog.isDef(opt_options.dataProjection) ? - ol.proj.get(opt_options.dataProjection) : featureProjection; + var dataProjection = goog.isDef(opt_options) ? + ol.proj.get(opt_options.dataProjection) : featureProjection; if (!goog.isNull(featureProjection) && !goog.isNull(dataProjection) && !ol.proj.equivalent(featureProjection, dataProjection)) { return geometryWriter( From 68d572e062eabdc1565121398036b442984febd8 Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Mon, 28 Jul 2014 20:01:54 +0200 Subject: [PATCH 10/33] Better descriptions of options --- externs/olx.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/externs/olx.js b/externs/olx.js index 16af4ed0c2..8b073ba63a 100644 --- a/externs/olx.js +++ b/externs/olx.js @@ -1152,16 +1152,16 @@ olx.format.ReadOptions; /** - * Projection of the data we are reading. Default is the projection derived from - * the data. + * Projection of the data we are reading. If not provided, the projection will + * be derived from the data (where possible). * @type {ol.proj.ProjectionLike|undefined} */ olx.format.ReadOptions.prototype.dataProjection; /** - * Projection of the feature geometries created by the format reader. Default - * is the `dataProjection`. + * Projection of the feature geometries created by the format reader. if not + * provided, features will be returned in the `dataProjection`. * @type {ol.proj.ProjectionLike|undefined} */ olx.format.ReadOptions.prototype.featureProjection; @@ -1175,7 +1175,8 @@ olx.format.WriteOptions; /** - * Projection of the data we are writing. Default is the `featureProjection`. + * Projection of the data we are writing. If not provided, features will be + * written in the `featureProjection`. * @type {ol.proj.ProjectionLike|undefined} */ olx.format.WriteOptions.prototype.dataProjection; From ee5f85df9f796f32af033d0a447f66066b0f0ef3 Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Wed, 30 Jul 2014 14:07:55 +0200 Subject: [PATCH 11/33] Add transformGeometry function to avoid repeated code --- src/ol/format/featureformat.js | 26 ++++++++++++++++++++++++++ src/ol/format/geojsonformat.js | 26 +++++--------------------- 2 files changed, 31 insertions(+), 21 deletions(-) diff --git a/src/ol/format/featureformat.js b/src/ol/format/featureformat.js index 83ae7e6c18..99f5c0a870 100644 --- a/src/ol/format/featureformat.js +++ b/src/ol/format/featureformat.js @@ -1,6 +1,7 @@ goog.provide('ol.format.Feature'); goog.require('goog.functions'); +goog.require('ol.proj'); @@ -98,3 +99,28 @@ ol.format.Feature.prototype.writeFeatures = goog.abstractMethod; * @return {ArrayBuffer|Node|Object|string} Node. */ ol.format.Feature.prototype.writeGeometry = goog.abstractMethod; + + +/** + * @param {ol.geom.Geometry} geometry Geometry. + * @param {boolean} write Set to true for writing, false for reading. + * @param {(olx.format.WriteOptions|olx.format.ReadOptions)=} opt_options + * Options. + * @return {ol.geom.Geometry} Transformed geometry. + * @protected + */ +ol.format.Feature.transformGeometry = function( + geometry, write, opt_options) { + var featureProjection = goog.isDef(opt_options) ? + ol.proj.get(opt_options.featureProjection) : null; + var dataProjection = goog.isDef(opt_options) ? + ol.proj.get(opt_options.dataProjection) : null; + if (!goog.isNull(featureProjection) && !goog.isNull(dataProjection) && + !ol.proj.equivalent(featureProjection, dataProjection)) { + return (write ? geometry.clone() : geometry).transform( + write ? featureProjection : dataProjection, + write ? dataProjection : featureProjection); + } else { + return geometry; + } +}; diff --git a/src/ol/format/geojsonformat.js b/src/ol/format/geojsonformat.js index 7e2803ef0b..cf6c1acd90 100644 --- a/src/ol/format/geojsonformat.js +++ b/src/ol/format/geojsonformat.js @@ -7,6 +7,7 @@ goog.require('goog.array'); goog.require('goog.asserts'); goog.require('goog.object'); goog.require('ol.Feature'); +goog.require('ol.format.Feature'); goog.require('ol.format.JSONFeature'); goog.require('ol.geom.GeometryCollection'); goog.require('ol.geom.GeometryType'); @@ -72,18 +73,10 @@ ol.format.GeoJSON.readGeometry_ = function(object, opt_options) { if (goog.isNull(object)) { return null; } - var featureProjection = goog.isDef(opt_options) ? - ol.proj.get(opt_options.featureProjection) : null; - var dataProjection = goog.isDef(opt_options) ? - ol.proj.get(opt_options.dataProjection) : null; var geometryReader = ol.format.GeoJSON.GEOMETRY_READERS_[object.type]; goog.asserts.assert(goog.isDef(geometryReader)); - var geometry = geometryReader(object); - if (!goog.isNull(featureProjection) && !goog.isNull(dataProjection) && - !ol.proj.equivalent(featureProjection, dataProjection)) { - geometry.transform(dataProjection, featureProjection); - } - return geometry; + return ol.format.Feature.transformGeometry( + geometryReader(object), false, opt_options); }; @@ -183,17 +176,8 @@ ol.format.GeoJSON.readPolygonGeometry_ = function(object) { ol.format.GeoJSON.writeGeometry_ = function(geometry, opt_options) { var geometryWriter = ol.format.GeoJSON.GEOMETRY_WRITERS_[geometry.getType()]; goog.asserts.assert(goog.isDef(geometryWriter)); - var featureProjection = goog.isDef(opt_options) ? - ol.proj.get(opt_options.featureProjection) : null; - var dataProjection = goog.isDef(opt_options) ? - ol.proj.get(opt_options.dataProjection) : featureProjection; - if (!goog.isNull(featureProjection) && !goog.isNull(dataProjection) && - !ol.proj.equivalent(featureProjection, dataProjection)) { - return geometryWriter( - geometry.clone().transform(featureProjection, dataProjection)); - } else { - return geometryWriter(geometry); - } + return geometryWriter( + ol.format.Feature.transformGeometry(geometry, true, opt_options)); }; From 46bba1fa3c24bef0b944d06f006d1cc09d49bf5f Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Wed, 30 Jul 2014 14:10:05 +0200 Subject: [PATCH 12/33] Get projection from data if dataProjection is not specified --- src/ol/format/jsonfeatureformat.js | 32 +++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/src/ol/format/jsonfeatureformat.js b/src/ol/format/jsonfeatureformat.js index 17fadac0d7..7b594bb69b 100644 --- a/src/ol/format/jsonfeatureformat.js +++ b/src/ol/format/jsonfeatureformat.js @@ -46,6 +46,26 @@ ol.format.JSONFeature.prototype.getObject_ = function(source) { }; +/** + * Adds the data projection to the read options. + * @param {Object} obj Data object. + * @param {olx.format.ReadOptions=} opt_options Options. + * @return {olx.format.ReadOptions|undefined} Options. + * @private + */ +ol.format.JSONFeature.prototype.getReadOptions_ = function(obj, opt_options) { + var options; + if (goog.isDef(opt_options)) { + options = { + dataProjection: goog.isDef(opt_options.dataProjection) ? + opt_options.dataProjection : this.readProjectionFromObject(obj), + featureProjection: opt_options.featureProjection + }; + } + return options; +}; + + /** * @inheritDoc */ @@ -58,7 +78,9 @@ ol.format.JSONFeature.prototype.getType = function() { * @inheritDoc */ ol.format.JSONFeature.prototype.readFeature = function(source, opt_options) { - return this.readFeatureFromObject(this.getObject_(source), opt_options); + var obj = this.getObject_(source); + return this.readFeatureFromObject( + obj, this.getReadOptions_(obj, opt_options)); }; @@ -66,7 +88,9 @@ ol.format.JSONFeature.prototype.readFeature = function(source, opt_options) { * @inheritDoc */ ol.format.JSONFeature.prototype.readFeatures = function(source, opt_options) { - return this.readFeaturesFromObject(this.getObject_(source), opt_options); + var obj = this.getObject_(source); + return this.readFeaturesFromObject( + obj, this.getReadOptions_(obj, opt_options)); }; @@ -92,7 +116,9 @@ ol.format.JSONFeature.prototype.readFeaturesFromObject = goog.abstractMethod; * @inheritDoc */ ol.format.JSONFeature.prototype.readGeometry = function(source, opt_options) { - return this.readGeometryFromObject(this.getObject_(source), opt_options); + var obj = this.getObject_(source); + return this.readGeometryFromObject( + obj, this.getReadOptions_(obj, opt_options)); }; From b8a834b4378a1c4a0260d67d866b42f7bd82007d Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Wed, 30 Jul 2014 14:10:11 +0200 Subject: [PATCH 13/33] Add transform tests for GeoJSON readFeatures --- test/spec/ol/format/geojsonformat.test.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/test/spec/ol/format/geojsonformat.test.js b/test/spec/ol/format/geojsonformat.test.js index 60e11ea4de..aee62d9838 100644 --- a/test/spec/ol/format/geojsonformat.test.js +++ b/test/spec/ol/format/geojsonformat.test.js @@ -174,6 +174,27 @@ describe('ol.format.GeoJSON', function() { expect(features[2].getGeometry()).to.be.an(ol.geom.Polygon); }); + it('can read and transform a feature collection', function() { + var features = format.readFeatures(featureCollectionGeoJSON, { + featureProjection: 'EPSG:3857' + }); + expect(features[0].getGeometry()).to.be.an(ol.geom.Point); + expect(features[0].getGeometry().getCoordinates()).to.eql( + ol.proj.transform([102.0, 0.5], 'EPSG:4326', 'EPSG:3857')); + expect(features[1].getGeometry().getCoordinates()).to.eql([ + ol.proj.transform([102.0, 0.0], 'EPSG:4326', 'EPSG:3857'), + ol.proj.transform([103.0, 1.0], 'EPSG:4326', 'EPSG:3857'), + ol.proj.transform([104.0, 0.0], 'EPSG:4326', 'EPSG:3857'), + ol.proj.transform([105.0, 1.0], 'EPSG:4326', 'EPSG:3857') + ]); + expect(features[2].getGeometry().getCoordinates()).to.eql([[ + ol.proj.transform([100.0, 0.0], 'EPSG:4326', 'EPSG:3857'), + ol.proj.transform([100.0, 1.0], 'EPSG:4326', 'EPSG:3857'), + ol.proj.transform([101.0, 1.0], 'EPSG:4326', 'EPSG:3857'), + ol.proj.transform([101.0, 0.0], 'EPSG:4326', 'EPSG:3857') + ]]); + }); + it('can create a feature with a specific geometryName', function() { var feature = new ol.format.GeoJSON({geometryName: 'the_geom'}). readFeature(pointGeoJSON); From da0988f5f4c21e936b17ae833d43faf84c0c5cc1 Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Wed, 30 Jul 2014 14:22:51 +0200 Subject: [PATCH 14/33] Add ReadOptions and WriteOptions for XML formats --- src/ol/format/xmlfeatureformat.js | 58 +++++++++++++++++++------------ 1 file changed, 36 insertions(+), 22 deletions(-) diff --git a/src/ol/format/xmlfeatureformat.js b/src/ol/format/xmlfeatureformat.js index bea0f39a79..f1d2eae3be 100644 --- a/src/ol/format/xmlfeatureformat.js +++ b/src/ol/format/xmlfeatureformat.js @@ -35,14 +35,15 @@ ol.format.XMLFeature.prototype.getType = function() { /** * @inheritDoc */ -ol.format.XMLFeature.prototype.readFeature = function(source) { +ol.format.XMLFeature.prototype.readFeature = function(source, opt_options) { if (ol.xml.isDocument(source)) { - return this.readFeatureFromDocument(/** @type {Document} */ (source)); + return this.readFeatureFromDocument( + /** @type {Document} */ (source), opt_options); } else if (ol.xml.isNode(source)) { - return this.readFeatureFromNode(/** @type {Node} */ (source)); + return this.readFeatureFromNode(/** @type {Node} */ (source), opt_options); } else if (goog.isString(source)) { var doc = ol.xml.load(source); - return this.readFeatureFromDocument(doc); + return this.readFeatureFromDocument(doc, opt_options); } else { goog.asserts.fail(); return null; @@ -52,10 +53,12 @@ ol.format.XMLFeature.prototype.readFeature = function(source) { /** * @param {Document} doc Document. + * @param {olx.format.ReadOptions=} opt_options Options. * @return {ol.Feature} Feature. */ -ol.format.XMLFeature.prototype.readFeatureFromDocument = function(doc) { - var features = this.readFeaturesFromDocument(doc); +ol.format.XMLFeature.prototype.readFeatureFromDocument = function( + doc, opt_options) { + var features = this.readFeaturesFromDocument(doc, opt_options); if (features.length > 0) { return features[0]; } else { @@ -66,6 +69,7 @@ ol.format.XMLFeature.prototype.readFeatureFromDocument = function(doc) { /** * @param {Node} node Node. + * @param {olx.format.ReadOptions=} opt_options Options. * @return {ol.Feature} Feature. */ ol.format.XMLFeature.prototype.readFeatureFromNode = goog.abstractMethod; @@ -74,14 +78,15 @@ ol.format.XMLFeature.prototype.readFeatureFromNode = goog.abstractMethod; /** * @inheritDoc */ -ol.format.XMLFeature.prototype.readFeatures = function(source) { +ol.format.XMLFeature.prototype.readFeatures = function(source, opt_options) { if (ol.xml.isDocument(source)) { - return this.readFeaturesFromDocument(/** @type {Document} */ (source)); + return this.readFeaturesFromDocument( + /** @type {Document} */ (source), opt_options); } else if (ol.xml.isNode(source)) { - return this.readFeaturesFromNode(/** @type {Node} */ (source)); + return this.readFeaturesFromNode(/** @type {Node} */ (source), opt_options); } else if (goog.isString(source)) { var doc = ol.xml.load(source); - return this.readFeaturesFromDocument(doc); + return this.readFeaturesFromDocument(doc, opt_options); } else { goog.asserts.fail(); return []; @@ -91,16 +96,18 @@ ol.format.XMLFeature.prototype.readFeatures = function(source) { /** * @param {Document} doc Document. + * @param {olx.format.ReadOptions=} opt_options Options. * @protected * @return {Array.} Features. */ -ol.format.XMLFeature.prototype.readFeaturesFromDocument = function(doc) { +ol.format.XMLFeature.prototype.readFeaturesFromDocument = function( + doc, opt_options) { /** @type {Array.} */ var features = []; var n; for (n = doc.firstChild; !goog.isNull(n); n = n.nextSibling) { if (n.nodeType == goog.dom.NodeType.ELEMENT) { - goog.array.extend(features, this.readFeaturesFromNode(n)); + goog.array.extend(features, this.readFeaturesFromNode(n, opt_options)); } } return features; @@ -109,6 +116,7 @@ ol.format.XMLFeature.prototype.readFeaturesFromDocument = function(doc) { /** * @param {Node} node Node. + * @param {olx.format.ReadOptions=} opt_options Options. * @protected * @return {Array.} Features. */ @@ -118,14 +126,15 @@ ol.format.XMLFeature.prototype.readFeaturesFromNode = goog.abstractMethod; /** * @inheritDoc */ -ol.format.XMLFeature.prototype.readGeometry = function(source) { +ol.format.XMLFeature.prototype.readGeometry = function(source, opt_options) { if (ol.xml.isDocument(source)) { - return this.readGeometryFromDocument(/** @type {Document} */ (source)); + return this.readGeometryFromDocument( + /** @type {Document} */ (source), opt_options); } else if (ol.xml.isNode(source)) { - return this.readGeometryFromNode(/** @type {Node} */ (source)); + return this.readGeometryFromNode(/** @type {Node} */ (source), opt_options); } else if (goog.isString(source)) { var doc = ol.xml.load(source); - return this.readGeometryFromDocument(doc); + return this.readGeometryFromDocument(doc, opt_options); } else { goog.asserts.fail(); return null; @@ -135,6 +144,7 @@ ol.format.XMLFeature.prototype.readGeometry = function(source) { /** * @param {Document} doc Document. + * @param {olx.format.ReadOptions=} opt_options Options. * @protected * @return {ol.geom.Geometry} Geometry. */ @@ -143,6 +153,7 @@ ol.format.XMLFeature.prototype.readGeometryFromDocument = goog.abstractMethod; /** * @param {Node} node Node. + * @param {olx.format.ReadOptions=} opt_options Options. * @protected * @return {ol.geom.Geometry} Geometry. */ @@ -186,13 +197,14 @@ ol.format.XMLFeature.prototype.readProjectionFromNode = goog.abstractMethod; /** * @inheritDoc */ -ol.format.XMLFeature.prototype.writeFeature = function(feature) { - return this.writeFeatureNode(feature); +ol.format.XMLFeature.prototype.writeFeature = function(feature, opt_options) { + return this.writeFeatureNode(feature, opt_options); }; /** * @param {ol.Feature} feature Feature. + * @param {olx.format.WriteOptions=} opt_options Options. * @protected * @return {Node} Node. */ @@ -202,13 +214,14 @@ ol.format.XMLFeature.prototype.writeFeatureNode = goog.abstractMethod; /** * @inheritDoc */ -ol.format.XMLFeature.prototype.writeFeatures = function(features) { - return this.writeFeaturesNode(features); +ol.format.XMLFeature.prototype.writeFeatures = function(features, opt_options) { + return this.writeFeaturesNode(features, opt_options); }; /** * @param {Array.} features Features. + * @param {olx.format.WriteOptions=} opt_options Options. * @protected * @return {Node} Node. */ @@ -218,13 +231,14 @@ ol.format.XMLFeature.prototype.writeFeaturesNode = goog.abstractMethod; /** * @inheritDoc */ -ol.format.XMLFeature.prototype.writeGeometry = function(geometry) { - return this.writeGeometryNode(geometry); +ol.format.XMLFeature.prototype.writeGeometry = function(geometry, opt_options) { + return this.writeGeometryNode(geometry, opt_options); }; /** * @param {ol.geom.Geometry} geometry Geometry. + * @param {olx.format.WriteOptions=} opt_options Options. * @protected * @return {Node} Node. */ From 4825cba48aac59dffafb249c1aed0068ea9c660f Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Wed, 30 Jul 2014 16:13:53 +0200 Subject: [PATCH 15/33] Implement ReadOptions and WriteOptions for ol.format.GML --- src/ol/format/gmlformat.js | 48 +++++++++++++++------- test/spec/ol/format/gmlformat.test.js | 57 +++++++++++++++++++++++++-- 2 files changed, 87 insertions(+), 18 deletions(-) diff --git a/src/ol/format/gmlformat.js b/src/ol/format/gmlformat.js index 1dd843cb23..e757d6547a 100644 --- a/src/ol/format/gmlformat.js +++ b/src/ol/format/gmlformat.js @@ -1,3 +1,5 @@ +//FIXME Implement readProjectionFrom* + goog.provide('ol.format.GML'); goog.require('goog.asserts'); @@ -8,6 +10,7 @@ goog.require('goog.string'); goog.require('ol.Feature'); goog.require('ol.array'); goog.require('ol.extent'); +goog.require('ol.format.Feature'); goog.require('ol.format.XMLFeature'); goog.require('ol.format.XSD'); goog.require('ol.geom.Geometry'); @@ -161,7 +164,7 @@ ol.format.GML.readGeometry = function(node, objectStack) { var geometry = ol.xml.pushParseAndPop(/** @type {ol.geom.Geometry} */(null), ol.format.GML.GEOMETRY_PARSERS_, node, objectStack); if (goog.isDefAndNotNull(geometry)) { - return geometry; + return ol.format.Feature.transformGeometry(geometry, false, context); } else { return undefined; } @@ -1036,9 +1039,14 @@ ol.format.GML.RING_PARSERS_ = { /** * @inheritDoc */ -ol.format.GML.prototype.readGeometryFromNode = function(node) { - var geometry = ol.format.GML.readGeometry(node, [{}]); - return (goog.isDef(geometry)) ? geometry : null; +ol.format.GML.prototype.readGeometryFromNode = function(node, opt_options) { + var obj = {}; + if (goog.isDef(opt_options)) { + goog.object.extend(obj, opt_options); + //FIXME Get dataProjection from data + } + var geometry = ol.format.GML.readGeometry(node, [obj]); + return (goog.isDef(geometry) ? geometry : null); }; @@ -1047,6 +1055,7 @@ ol.format.GML.prototype.readGeometryFromNode = function(node) { * * @function * @param {ArrayBuffer|Document|Node|Object|string} source Source. + * @param {olx.format.ReadOptions=} opt_options Options. * @return {Array.} Features. * @api */ @@ -1056,12 +1065,16 @@ ol.format.GML.prototype.readFeatures; /** * @inheritDoc */ -ol.format.GML.prototype.readFeaturesFromNode = function(node) { - var objectStack = [{ +ol.format.GML.prototype.readFeaturesFromNode = function(node, opt_options) { + var options = { 'featureType': this.featureType_, 'featureNS': this.featureNS_ - }]; - return ol.format.GML.readFeatures_(node, objectStack); + }; + if (goog.isDef(opt_options)) { + goog.object.extend(options, opt_options); + //FIXME Get dataProjection from data + } + return ol.format.GML.readFeatures_(node, [options]); }; @@ -1444,7 +1457,9 @@ ol.format.GML.writeGeometry = function(node, geometry, objectStack) { item.node = node; ol.xml.pushSerializeAndPop(/** @type {ol.xml.NodeStackItem} */ (item), ol.format.GML.GEOMETRY_SERIALIZERS_, - ol.format.GML.GEOMETRY_NODE_FACTORY_, [geometry], objectStack); + ol.format.GML.GEOMETRY_NODE_FACTORY_, + [ol.format.Feature.transformGeometry(geometry, true, context)], + objectStack); }; @@ -1672,14 +1687,15 @@ ol.format.GML.GEOMETRY_NODE_FACTORY_ = function(value, objectStack, /** * @inheritDoc */ -ol.format.GML.prototype.writeGeometryNode = function(geometry) { +ol.format.GML.prototype.writeGeometryNode = function(geometry, opt_options) { var geom = ol.xml.createElementNS('http://www.opengis.net/gml', 'geom'); var context = {node: geom, srsName: this.srsName_, curve: this.curve_, surface: this.surface_, multiSurface: this.multiSurface_, multiCurve: this.multiCurve_}; - ol.xml.pushSerializeAndPop(/** @type {ol.xml.NodeStackItem} */ - (context), ol.format.GML.GEOMETRY_SERIALIZERS_, - ol.format.GML.GEOMETRY_NODE_FACTORY_, [geometry], []); + if (goog.isDef(opt_options)) { + goog.object.extend(context, opt_options); + } + ol.format.GML.writeGeometry(geom, geometry, [context]); return geom; }; @@ -1689,6 +1705,7 @@ ol.format.GML.prototype.writeGeometryNode = function(geometry) { * * @function * @param {Array.} features Features. + * @param {olx.format.WriteOptions=} opt_options Options. * @return {Node} Result. * @api */ @@ -1698,7 +1715,7 @@ ol.format.GML.prototype.writeFeatures; /** * @inheritDoc */ -ol.format.GML.prototype.writeFeaturesNode = function(features) { +ol.format.GML.prototype.writeFeaturesNode = function(features, opt_options) { var node = ol.xml.createElementNS('http://www.opengis.net/gml', 'featureMembers'); ol.xml.setAttributeNS(node, 'http://www.w3.org/2001/XMLSchema-instance', @@ -1712,6 +1729,9 @@ ol.format.GML.prototype.writeFeaturesNode = function(features) { featureNS: this.featureNS_, featureType: this.featureType_ }; + if (goog.isDef(opt_options)) { + goog.object.extend(context, opt_options); + } ol.format.GML.writeFeatureMembers_(node, features, [context]); return node; }; diff --git a/test/spec/ol/format/gmlformat.test.js b/test/spec/ol/format/gmlformat.test.js index 0040f3ade2..9b10a7fe00 100644 --- a/test/spec/ol/format/gmlformat.test.js +++ b/test/spec/ol/format/gmlformat.test.js @@ -1,11 +1,11 @@ goog.provide('ol.test.format.GML'); -var readGeometry = function(format, text) { +var readGeometry = function(format, text, opt_options) { var doc = ol.xml.load(text); // we need an intermediate node for testing purposes var node = goog.dom.createElement(goog.dom.TagName.PRE); node.appendChild(doc.documentElement); - return format.readGeometryFromNode(node); + return format.readGeometryFromNode(node, opt_options); }; describe('ol.format.GML', function() { @@ -33,6 +33,28 @@ describe('ol.format.GML', function() { expect(serialized.firstElementChild).to.xmleql(ol.xml.load(text)); }); + it('can read, transform and write a point geometry', function() { + var config = { + dataProjection: 'CRS:84', + featureProjection: 'EPSG:3857' + }; + var text = + '' + + ' 1 2' + + ''; + var g = readGeometry(format, text, config); + expect(g).to.be.an(ol.geom.Point); + var coordinates = g.getCoordinates(); + expect(coordinates.splice(0, 2)).to.eql( + ol.proj.transform([1, 2], 'CRS:84', 'EPSG:3857')); + var serialized = format.writeGeometry(g, config); + var pos = serialized.firstElementChild.firstElementChild.textContent; + var coordinate = pos.split(' '); + expect(coordinate[0]).to.roughlyEqual(1, 1e-9); + expect(coordinate[1]).to.roughlyEqual(2, 1e-9); + }); + it('can read and write a point geometry in EPSG:4326', function() { var text = '' + + ' 1 2 3 4' + + ''; + var g = readGeometry(format, text, config); + expect(g).to.be.an(ol.geom.LineString); + var coordinates = g.getCoordinates(); + expect(coordinates[0].slice(0, 2)).to.eql( + ol.proj.transform([1, 2], 'CRS:84', 'EPSG:3857')); + expect(coordinates[1].slice(0, 2)).to.eql( + ol.proj.transform([3, 4], 'CRS:84', 'EPSG:3857')); + var serialized = format.writeGeometry(g, config); + var poss = serialized.firstElementChild.firstElementChild.textContent; + var coordinate = poss.split(' '); + expect(coordinate[0]).to.roughlyEqual(1, 1e-9); + expect(coordinate[1]).to.roughlyEqual(2, 1e-9); + expect(coordinate[2]).to.roughlyEqual(3, 1e-9); + expect(coordinate[3]).to.roughlyEqual(4, 1e-9); + }); + it('can read and write a linestring geometry in EPSG:4326', function() { var text = ' Date: Wed, 30 Jul 2014 22:19:23 +0200 Subject: [PATCH 16/33] Make options complete in ol.format.Feature already --- src/ol/format/featureformat.js | 26 ++++++++++++++++-- src/ol/format/geojsonformat.js | 4 +-- src/ol/format/gmlformat.js | 38 ++++++++++++++++++--------- src/ol/format/jsonfeatureformat.js | 29 +++----------------- test/spec/ol/format/gmlformat.test.js | 2 +- 5 files changed, 56 insertions(+), 43 deletions(-) diff --git a/src/ol/format/featureformat.js b/src/ol/format/featureformat.js index 99f5c0a870..aad4e4a91e 100644 --- a/src/ol/format/featureformat.js +++ b/src/ol/format/featureformat.js @@ -26,6 +26,27 @@ ol.format.Feature = function() { ol.format.Feature.prototype.getExtensions = goog.abstractMethod; +/** + * Adds the data projection to the read options. + * @param {Document|Node|Object|string} source Source. + * @param {olx.format.ReadOptions=} opt_options Options. + * @return {olx.format.ReadOptions|undefined} Options. + * @protected + */ +ol.format.Feature.prototype.getReadOptions = function( + source, opt_options) { + var options; + if (goog.isDef(opt_options)) { + options = { + dataProjection: goog.isDef(opt_options.dataProjection) ? + opt_options.dataProjection : this.readProjection(source), + featureProjection: opt_options.featureProjection + }; + } + return options; +}; + + /** * @return {ol.format.FormatType} Format. */ @@ -103,13 +124,14 @@ ol.format.Feature.prototype.writeGeometry = goog.abstractMethod; /** * @param {ol.geom.Geometry} geometry Geometry. - * @param {boolean} write Set to true for writing, false for reading. + * @param {boolean} write Set to true for writing, false for reading. For + * writing, the geometry will be cloned before transforming. * @param {(olx.format.WriteOptions|olx.format.ReadOptions)=} opt_options * Options. * @return {ol.geom.Geometry} Transformed geometry. * @protected */ -ol.format.Feature.transformGeometry = function( +ol.format.Feature.transformWithOptions = function( geometry, write, opt_options) { var featureProjection = goog.isDef(opt_options) ? ol.proj.get(opt_options.featureProjection) : null; diff --git a/src/ol/format/geojsonformat.js b/src/ol/format/geojsonformat.js index cf6c1acd90..f4c3e1fe67 100644 --- a/src/ol/format/geojsonformat.js +++ b/src/ol/format/geojsonformat.js @@ -75,7 +75,7 @@ ol.format.GeoJSON.readGeometry_ = function(object, opt_options) { } var geometryReader = ol.format.GeoJSON.GEOMETRY_READERS_[object.type]; goog.asserts.assert(goog.isDef(geometryReader)); - return ol.format.Feature.transformGeometry( + return ol.format.Feature.transformWithOptions( geometryReader(object), false, opt_options); }; @@ -177,7 +177,7 @@ ol.format.GeoJSON.writeGeometry_ = function(geometry, opt_options) { var geometryWriter = ol.format.GeoJSON.GEOMETRY_WRITERS_[geometry.getType()]; goog.asserts.assert(goog.isDef(geometryWriter)); return geometryWriter( - ol.format.Feature.transformGeometry(geometry, true, opt_options)); + ol.format.Feature.transformWithOptions(geometry, true, opt_options)); }; diff --git a/src/ol/format/gmlformat.js b/src/ol/format/gmlformat.js index e757d6547a..6ee8620a1e 100644 --- a/src/ol/format/gmlformat.js +++ b/src/ol/format/gmlformat.js @@ -164,7 +164,7 @@ ol.format.GML.readGeometry = function(node, objectStack) { var geometry = ol.xml.pushParseAndPop(/** @type {ol.geom.Geometry} */(null), ol.format.GML.GEOMETRY_PARSERS_, node, objectStack); if (goog.isDefAndNotNull(geometry)) { - return ol.format.Feature.transformGeometry(geometry, false, context); + return ol.format.Feature.transformWithOptions(geometry, false, context); } else { return undefined; } @@ -1040,12 +1040,8 @@ ol.format.GML.RING_PARSERS_ = { * @inheritDoc */ ol.format.GML.prototype.readGeometryFromNode = function(node, opt_options) { - var obj = {}; - if (goog.isDef(opt_options)) { - goog.object.extend(obj, opt_options); - //FIXME Get dataProjection from data - } - var geometry = ol.format.GML.readGeometry(node, [obj]); + var geometry = ol.format.GML.readGeometry(node, + [this.getReadOptions(node, goog.isDef(opt_options) ? opt_options : {})]); return (goog.isDef(geometry) ? geometry : null); }; @@ -1071,13 +1067,21 @@ ol.format.GML.prototype.readFeaturesFromNode = function(node, opt_options) { 'featureNS': this.featureNS_ }; if (goog.isDef(opt_options)) { - goog.object.extend(options, opt_options); - //FIXME Get dataProjection from data + goog.object.extend(options, this.getReadOptions(node, opt_options)); } return ol.format.GML.readFeatures_(node, [options]); }; +/** + * @inheritDoc + */ +ol.format.GML.prototype.readProjectionFromNode = function(node) { + //TODO read this from data + return ol.proj.get(this.srsName_); +}; + + /** * @param {Node} node Node. * @param {ol.geom.Point} value Point geometry. @@ -1455,11 +1459,21 @@ ol.format.GML.writeGeometry = function(node, geometry, objectStack) { goog.asserts.assert(goog.isObject(context)); var item = goog.object.clone(context); item.node = node; + var value; + if (goog.isArray(geometry)) { + if (goog.isDef(context.dataProjection)) { + value = ol.proj.transformExtent( + geometry, context.featureProjection, context.dataProjection); + } else { + value = geometry; + } + } else { + goog.asserts.assertInstanceof(geometry, ol.geom.Geometry); + value = ol.format.Feature.transformWithOptions(geometry, true, context); + } ol.xml.pushSerializeAndPop(/** @type {ol.xml.NodeStackItem} */ (item), ol.format.GML.GEOMETRY_SERIALIZERS_, - ol.format.GML.GEOMETRY_NODE_FACTORY_, - [ol.format.Feature.transformGeometry(geometry, true, context)], - objectStack); + ol.format.GML.GEOMETRY_NODE_FACTORY_, [value], objectStack); }; diff --git a/src/ol/format/jsonfeatureformat.js b/src/ol/format/jsonfeatureformat.js index 7b594bb69b..3fe530b574 100644 --- a/src/ol/format/jsonfeatureformat.js +++ b/src/ol/format/jsonfeatureformat.js @@ -46,26 +46,6 @@ ol.format.JSONFeature.prototype.getObject_ = function(source) { }; -/** - * Adds the data projection to the read options. - * @param {Object} obj Data object. - * @param {olx.format.ReadOptions=} opt_options Options. - * @return {olx.format.ReadOptions|undefined} Options. - * @private - */ -ol.format.JSONFeature.prototype.getReadOptions_ = function(obj, opt_options) { - var options; - if (goog.isDef(opt_options)) { - options = { - dataProjection: goog.isDef(opt_options.dataProjection) ? - opt_options.dataProjection : this.readProjectionFromObject(obj), - featureProjection: opt_options.featureProjection - }; - } - return options; -}; - - /** * @inheritDoc */ @@ -78,9 +58,8 @@ ol.format.JSONFeature.prototype.getType = function() { * @inheritDoc */ ol.format.JSONFeature.prototype.readFeature = function(source, opt_options) { - var obj = this.getObject_(source); return this.readFeatureFromObject( - obj, this.getReadOptions_(obj, opt_options)); + this.getObject_(source), this.getReadOptions(source, opt_options)); }; @@ -88,9 +67,8 @@ ol.format.JSONFeature.prototype.readFeature = function(source, opt_options) { * @inheritDoc */ ol.format.JSONFeature.prototype.readFeatures = function(source, opt_options) { - var obj = this.getObject_(source); return this.readFeaturesFromObject( - obj, this.getReadOptions_(obj, opt_options)); + this.getObject_(source), this.getReadOptions(source, opt_options)); }; @@ -116,9 +94,8 @@ ol.format.JSONFeature.prototype.readFeaturesFromObject = goog.abstractMethod; * @inheritDoc */ ol.format.JSONFeature.prototype.readGeometry = function(source, opt_options) { - var obj = this.getObject_(source); return this.readGeometryFromObject( - obj, this.getReadOptions_(obj, opt_options)); + this.getObject_(source), this.getReadOptions(source, opt_options)); }; diff --git a/test/spec/ol/format/gmlformat.test.js b/test/spec/ol/format/gmlformat.test.js index 9b10a7fe00..fc2e5ffcbe 100644 --- a/test/spec/ol/format/gmlformat.test.js +++ b/test/spec/ol/format/gmlformat.test.js @@ -35,7 +35,6 @@ describe('ol.format.GML', function() { it('can read, transform and write a point geometry', function() { var config = { - dataProjection: 'CRS:84', featureProjection: 'EPSG:3857' }; var text = @@ -48,6 +47,7 @@ describe('ol.format.GML', function() { var coordinates = g.getCoordinates(); expect(coordinates.splice(0, 2)).to.eql( ol.proj.transform([1, 2], 'CRS:84', 'EPSG:3857')); + config.dataProjection = 'CRS:84'; var serialized = format.writeGeometry(g, config); var pos = serialized.firstElementChild.firstElementChild.textContent; var coordinate = pos.split(' '); From 65346d716decab2a4b659be8d82724dc88a0569c Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Wed, 30 Jul 2014 22:19:44 +0200 Subject: [PATCH 17/33] Add GeoJSON tests for write transforms --- test/spec/ol/format/geojsonformat.test.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/spec/ol/format/geojsonformat.test.js b/test/spec/ol/format/geojsonformat.test.js index aee62d9838..0ab714bd47 100644 --- a/test/spec/ol/format/geojsonformat.test.js +++ b/test/spec/ol/format/geojsonformat.test.js @@ -473,6 +473,23 @@ describe('ol.format.GeoJSON', function() { } }); + it('transforms and encodes feature collection', function() { + var str = JSON.stringify(data), + array = format.readFeatures(str); + var geojson = format.writeFeatures(array, { + dataProjection: 'EPSG:4326', + featureProjection: 'EPSG:3857' + }); + var result = format.readFeatures(geojson); + var got, exp; + for (var i = 0, ii = array.length; i < ii; ++i) { + got = array[i]; + exp = result[i]; + expect(got.getGeometry().transform('EPSG:3857', 'EPSG:4326') + .getCoordinates()).to.eql(exp.getGeometry().getCoordinates()); + } + }); + }); describe('#writeGeometry', function() { From 281fd3c6a9bf21a6892c9dc5aa5f8aca1f38afeb Mon Sep 17 00:00:00 2001 From: tsauerwein Date: Fri, 8 Aug 2014 10:54:40 +0200 Subject: [PATCH 18/33] Implement GML.readProjectionFromNode() --- src/ol/format/gmlformat.js | 6 ++---- test/spec/ol/format/gmlformat.test.js | 19 ++++++++++++++++++- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/ol/format/gmlformat.js b/src/ol/format/gmlformat.js index 6ee8620a1e..a4b7cfbaea 100644 --- a/src/ol/format/gmlformat.js +++ b/src/ol/format/gmlformat.js @@ -1,5 +1,3 @@ -//FIXME Implement readProjectionFrom* - goog.provide('ol.format.GML'); goog.require('goog.asserts'); @@ -1077,8 +1075,8 @@ ol.format.GML.prototype.readFeaturesFromNode = function(node, opt_options) { * @inheritDoc */ ol.format.GML.prototype.readProjectionFromNode = function(node) { - //TODO read this from data - return ol.proj.get(this.srsName_); + return goog.isDef(this.srsName_) ? this.srsName_ : + node.firstElementChild.getAttribute('srsName'); }; diff --git a/test/spec/ol/format/gmlformat.test.js b/test/spec/ol/format/gmlformat.test.js index fc2e5ffcbe..e96d571ae7 100644 --- a/test/spec/ol/format/gmlformat.test.js +++ b/test/spec/ol/format/gmlformat.test.js @@ -10,10 +10,11 @@ var readGeometry = function(format, text, opt_options) { describe('ol.format.GML', function() { - var format, formatWGS84; + var format, formatWGS84, formatNoSrs; beforeEach(function() { format = new ol.format.GML({srsName: 'CRS:84'}); formatWGS84 = new ol.format.GML({srsName: 'urn:x-ogc:def:crs:EPSG:4326'}); + formatNoSrs = new ol.format.GML(); }); describe('#readGeometry', function() { @@ -55,6 +56,22 @@ describe('ol.format.GML', function() { expect(coordinate[1]).to.roughlyEqual(2, 1e-9); }); + it('can detect SRS, read and transform a point geometry', function() { + var config = { + featureProjection: 'EPSG:3857' + }; + var text = + '' + + ' 1 2' + + ''; + var g = readGeometry(formatNoSrs, text, config); + expect(g).to.be.an(ol.geom.Point); + var coordinates = g.getCoordinates(); + expect(coordinates.splice(0, 2)).to.eql( + ol.proj.transform([1, 2], 'CRS:84', 'EPSG:3857')); + }); + it('can read and write a point geometry in EPSG:4326', function() { var text = ' Date: Fri, 8 Aug 2014 11:14:03 +0200 Subject: [PATCH 19/33] Fix GeoJSON.readFeaturesFromObject Only feature collections worked properly. --- src/ol/format/geojsonformat.js | 2 +- test/spec/ol/format/geojsonformat.test.js | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/ol/format/geojsonformat.js b/src/ol/format/geojsonformat.js index f4c3e1fe67..9b12d76095 100644 --- a/src/ol/format/geojsonformat.js +++ b/src/ol/format/geojsonformat.js @@ -398,7 +398,7 @@ ol.format.GeoJSON.prototype.readFeaturesFromObject = function( object, opt_options) { var geoJSONObject = /** @type {GeoJSONObject} */ (object); if (geoJSONObject.type == 'Feature') { - return [this.readFeatureFromObject(object)]; + return [this.readFeatureFromObject(object, opt_options)]; } else if (geoJSONObject.type == 'FeatureCollection') { var geoJSONFeatureCollection = /** @type {GeoJSONFeatureCollection} */ (object); diff --git a/test/spec/ol/format/geojsonformat.test.js b/test/spec/ol/format/geojsonformat.test.js index 0ab714bd47..2c6b220ff5 100644 --- a/test/spec/ol/format/geojsonformat.test.js +++ b/test/spec/ol/format/geojsonformat.test.js @@ -174,6 +174,15 @@ describe('ol.format.GeoJSON', function() { expect(features[2].getGeometry()).to.be.an(ol.geom.Polygon); }); + it('can read and transform a point', function() { + var feature = format.readFeatures(pointGeoJSON, { + featureProjection: 'EPSG:3857' + }); + expect(feature[0].getGeometry()).to.be.an(ol.geom.Point); + expect(feature[0].getGeometry().getCoordinates()).to.eql( + ol.proj.transform([102.0, 0.5], 'EPSG:4326', 'EPSG:3857')); + }); + it('can read and transform a feature collection', function() { var features = format.readFeatures(featureCollectionGeoJSON, { featureProjection: 'EPSG:3857' From e44673849108d5a178ff5028049f850ff8066437 Mon Sep 17 00:00:00 2001 From: tsauerwein Date: Fri, 8 Aug 2014 11:43:53 +0200 Subject: [PATCH 20/33] Implement read transforms for ol.format.TopoJSON --- src/ol/format/topojsonformat.js | 19 ++++++++------ test/spec/ol/format/topojson.test.js | 37 ++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 7 deletions(-) diff --git a/src/ol/format/topojsonformat.js b/src/ol/format/topojsonformat.js index e7397886f2..314b9b2c3e 100644 --- a/src/ol/format/topojsonformat.js +++ b/src/ol/format/topojsonformat.js @@ -3,6 +3,7 @@ goog.provide('ol.format.TopoJSON'); goog.require('goog.asserts'); goog.require('goog.object'); goog.require('ol.Feature'); +goog.require('ol.format.Feature'); goog.require('ol.format.JSONFeature'); goog.require('ol.geom.LineString'); goog.require('ol.geom.MultiLineString'); @@ -218,17 +219,18 @@ ol.format.TopoJSON.prototype.getExtensions = function() { * @param {Array.>} arcs Array of arcs. * @param {Array.} scale Scale for each dimension. * @param {Array.} translate Translation for each dimension. + * @param {olx.format.ReadOptions=} opt_options Read options. * @return {Array.} Array of features. * @private */ ol.format.TopoJSON.readFeaturesFromGeometryCollection_ = function( - collection, arcs, scale, translate) { + collection, arcs, scale, translate, opt_options) { var geometries = collection.geometries; var features = []; var i, ii; for (i = 0, ii = geometries.length; i < ii; ++i) { features[i] = ol.format.TopoJSON.readFeatureFromGeometry_( - geometries[i], arcs, scale, translate); + geometries[i], arcs, scale, translate, opt_options); } return features; }; @@ -241,11 +243,12 @@ ol.format.TopoJSON.readFeaturesFromGeometryCollection_ = function( * @param {Array.>} arcs Array of arcs. * @param {Array.} scale Scale for each dimension. * @param {Array.} translate Translation for each dimension. + * @param {olx.format.ReadOptions=} opt_options Read options. * @return {ol.Feature} Feature. * @private */ ol.format.TopoJSON.readFeatureFromGeometry_ = function(object, arcs, - scale, translate) { + scale, translate, opt_options) { var geometry; var type = object.type; var geometryReader = ol.format.TopoJSON.GEOMETRY_READERS_[type]; @@ -256,7 +259,8 @@ ol.format.TopoJSON.readFeatureFromGeometry_ = function(object, arcs, geometry = geometryReader(object, arcs); } var feature = new ol.Feature(); - feature.setGeometry(geometry); + feature.setGeometry(ol.format.Feature.transformWithOptions( + geometry, false, opt_options)); if (goog.isDef(object.id)) { feature.setId(object.id); } @@ -281,7 +285,8 @@ ol.format.TopoJSON.prototype.readFeatures; /** * @inheritDoc */ -ol.format.TopoJSON.prototype.readFeaturesFromObject = function(object) { +ol.format.TopoJSON.prototype.readFeaturesFromObject = function( + object, opt_options) { if (object.type == 'Topology') { var topoJSONTopology = /** @type {TopoJSONTopology} */ (object); var transform, scale = null, translate = null; @@ -306,12 +311,12 @@ ol.format.TopoJSON.prototype.readFeaturesFromObject = function(object) { (topoJSONFeatures[i]); features.push.apply(features, ol.format.TopoJSON.readFeaturesFromGeometryCollection_( - feature, arcs, scale, translate)); + feature, arcs, scale, translate, opt_options)); } else { feature = /** @type {TopoJSONGeometry} */ (topoJSONFeatures[i]); features.push(ol.format.TopoJSON.readFeatureFromGeometry_( - feature, arcs, scale, translate)); + feature, arcs, scale, translate, opt_options)); } } return features; diff --git a/test/spec/ol/format/topojson.test.js b/test/spec/ol/format/topojson.test.js index 5f1753103e..8ef332cdb8 100644 --- a/test/spec/ol/format/topojson.test.js +++ b/test/spec/ol/format/topojson.test.js @@ -1,5 +1,7 @@ goog.provide('ol.test.format.TopoJSON'); +goog.require('ol.proj'); + var aruba = { type: 'Topology', transform: { @@ -89,6 +91,41 @@ describe('ol.format.TopoJSON', function() { }); }); + it('parses simple.json and transforms', function(done) { + afterLoadText('spec/ol/format/topojson/simple.json', function(text) { + var features = format.readFeatures(text, { + featureProjection: 'EPSG:3857' + }); + expect(features.length).to.be(3); + + var point = features[0].getGeometry(); + expect(point.getType()).to.be('Point'); + expect(features[0].getGeometry().getCoordinates()).to.eql( + ol.proj.transform([102.0, 0.5], 'EPSG:4326', 'EPSG:3857')); + + var line = features[1].getGeometry(); + expect(line.getType()).to.be('LineString'); + expect(line.getCoordinates()).to.eql([ + ol.proj.transform([102.0, 0.0], 'EPSG:4326', 'EPSG:3857'), + ol.proj.transform([103.0, 1.0], 'EPSG:4326', 'EPSG:3857'), + ol.proj.transform([104.0, 0.0], 'EPSG:4326', 'EPSG:3857'), + ol.proj.transform([105.0, 1.0], 'EPSG:4326', 'EPSG:3857') + ]); + + var polygon = features[2].getGeometry(); + expect(polygon.getType()).to.be('Polygon'); + expect(polygon.getCoordinates()).to.eql([[ + ol.proj.transform([100.0, 0.0], 'EPSG:4326', 'EPSG:3857'), + ol.proj.transform([100.0, 1.0], 'EPSG:4326', 'EPSG:3857'), + ol.proj.transform([101.0, 1.0], 'EPSG:4326', 'EPSG:3857'), + ol.proj.transform([101.0, 0.0], 'EPSG:4326', 'EPSG:3857'), + ol.proj.transform([100.0, 0.0], 'EPSG:4326', 'EPSG:3857') + ]]); + + done(); + }); + }); + it('parses world-110m.json', function(done) { afterLoadText('spec/ol/format/topojson/world-110m.json', function(text) { From 31dbbc6a8c9832e0360ebdf36eca71d4cc37474e Mon Sep 17 00:00:00 2001 From: tsauerwein Date: Fri, 8 Aug 2014 15:05:35 +0200 Subject: [PATCH 21/33] Implement read/write transforms for ol.format.GPX --- src/ol/format/featureformat.js | 6 +- src/ol/format/geojsonformat.js | 5 +- src/ol/format/gmlformat.js | 6 +- src/ol/format/gpxformat.js | 24 +++++++- src/ol/format/topojsonformat.js | 2 +- src/ol/format/xmlfeatureformat.js | 34 +++++++++++ test/spec/ol/format/gpxformat.test.js | 88 +++++++++++++++++++++++++++ 7 files changed, 154 insertions(+), 11 deletions(-) diff --git a/src/ol/format/featureformat.js b/src/ol/format/featureformat.js index aad4e4a91e..d7176bcde0 100644 --- a/src/ol/format/featureformat.js +++ b/src/ol/format/featureformat.js @@ -124,15 +124,15 @@ ol.format.Feature.prototype.writeGeometry = goog.abstractMethod; /** * @param {ol.geom.Geometry} geometry Geometry. - * @param {boolean} write Set to true for writing, false for reading. For - * writing, the geometry will be cloned before transforming. + * @param {boolean} write Set to true for writing, false for reading. + * @param {boolean} clone The geometry will be cloned before transforming. * @param {(olx.format.WriteOptions|olx.format.ReadOptions)=} opt_options * Options. * @return {ol.geom.Geometry} Transformed geometry. * @protected */ ol.format.Feature.transformWithOptions = function( - geometry, write, opt_options) { + geometry, write, clone, opt_options) { var featureProjection = goog.isDef(opt_options) ? ol.proj.get(opt_options.featureProjection) : null; var dataProjection = goog.isDef(opt_options) ? diff --git a/src/ol/format/geojsonformat.js b/src/ol/format/geojsonformat.js index 9b12d76095..f6cfc07a70 100644 --- a/src/ol/format/geojsonformat.js +++ b/src/ol/format/geojsonformat.js @@ -76,7 +76,7 @@ ol.format.GeoJSON.readGeometry_ = function(object, opt_options) { var geometryReader = ol.format.GeoJSON.GEOMETRY_READERS_[object.type]; goog.asserts.assert(goog.isDef(geometryReader)); return ol.format.Feature.transformWithOptions( - geometryReader(object), false, opt_options); + geometryReader(object), false, false, opt_options); }; @@ -177,7 +177,8 @@ ol.format.GeoJSON.writeGeometry_ = function(geometry, opt_options) { var geometryWriter = ol.format.GeoJSON.GEOMETRY_WRITERS_[geometry.getType()]; goog.asserts.assert(goog.isDef(geometryWriter)); return geometryWriter( - ol.format.Feature.transformWithOptions(geometry, true, opt_options)); + ol.format.Feature.transformWithOptions( + geometry, true, true, opt_options)); }; diff --git a/src/ol/format/gmlformat.js b/src/ol/format/gmlformat.js index a4b7cfbaea..ed840a66d8 100644 --- a/src/ol/format/gmlformat.js +++ b/src/ol/format/gmlformat.js @@ -162,7 +162,8 @@ ol.format.GML.readGeometry = function(node, objectStack) { var geometry = ol.xml.pushParseAndPop(/** @type {ol.geom.Geometry} */(null), ol.format.GML.GEOMETRY_PARSERS_, node, objectStack); if (goog.isDefAndNotNull(geometry)) { - return ol.format.Feature.transformWithOptions(geometry, false, context); + return ol.format.Feature.transformWithOptions( + geometry, false, false, context); } else { return undefined; } @@ -1467,7 +1468,8 @@ ol.format.GML.writeGeometry = function(node, geometry, objectStack) { } } else { goog.asserts.assertInstanceof(geometry, ol.geom.Geometry); - value = ol.format.Feature.transformWithOptions(geometry, true, context); + value = + ol.format.Feature.transformWithOptions(geometry, true, true, context); } ol.xml.pushSerializeAndPop(/** @type {ol.xml.NodeStackItem} */ (item), ol.format.GML.GEOMETRY_SERIALIZERS_, diff --git a/src/ol/format/gpxformat.js b/src/ol/format/gpxformat.js index af48c40316..d3a7dc9413 100644 --- a/src/ol/format/gpxformat.js +++ b/src/ol/format/gpxformat.js @@ -415,6 +415,7 @@ ol.format.GPX.prototype.handleReadExtensions_ = function(features) { * * @function * @param {ArrayBuffer|Document|Node|Object|string} source Source. + * @param {olx.format.ReadOptions=} opt_options Read options. * @return {ol.Feature} Feature. * @api */ @@ -424,7 +425,7 @@ ol.format.GPX.prototype.readFeature; /** * @inheritDoc */ -ol.format.GPX.prototype.readFeatureFromNode = function(node) { +ol.format.GPX.prototype.readFeatureFromNode = function(node, opt_options) { goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT); if (!goog.array.contains(ol.format.GPX.NAMESPACE_URIS_, node.namespaceURI)) { return null; @@ -438,6 +439,8 @@ ol.format.GPX.prototype.readFeatureFromNode = function(node) { return null; } this.handleReadExtensions_([feature]); + ol.format.XMLFeature.transformFeaturesWithOptions( + [feature], false, this.getReadOptions(node, opt_options)); return feature; }; @@ -447,6 +450,7 @@ ol.format.GPX.prototype.readFeatureFromNode = function(node) { * * @function * @param {ArrayBuffer|Document|Node|Object|string} source Source. + * @param {olx.format.ReadOptions=} opt_options Read options. * @return {Array.} Features. * @api */ @@ -456,7 +460,7 @@ ol.format.GPX.prototype.readFeatures; /** * @inheritDoc */ -ol.format.GPX.prototype.readFeaturesFromNode = function(node) { +ol.format.GPX.prototype.readFeaturesFromNode = function(node, opt_options) { goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT); if (!goog.array.contains(ol.format.GPX.NAMESPACE_URIS_, node.namespaceURI)) { return []; @@ -467,6 +471,8 @@ ol.format.GPX.prototype.readFeaturesFromNode = function(node) { node, []); if (goog.isDef(features)) { this.handleReadExtensions_(features); + ol.format.XMLFeature.transformFeaturesWithOptions( + features, false, this.getReadOptions(node, opt_options)); return features; } else { return []; @@ -845,6 +851,7 @@ ol.format.GPX.GPX_SERIALIZERS_ = ol.xml.makeStructureNS( * * @function * @param {Array.} features Features. + * @param {olx.format.WriteOptions=} opt_options Write options. * @return {Node} Result. * @api */ @@ -854,9 +861,20 @@ ol.format.GPX.prototype.writeFeatures; /** * @inheritDoc */ -ol.format.GPX.prototype.writeFeaturesNode = function(features) { +ol.format.GPX.prototype.writeFeaturesNode = function(features, opt_options) { //FIXME Serialize metadata var gpx = ol.xml.createElementNS('http://www.topografix.com/GPX/1/1', 'gpx'); + if (goog.isDef(opt_options)) { + if (!goog.isDef(opt_options.dataProjection)) { + // for convenience set a default dataProjection + opt_options = { + featureProjection: opt_options.featureProjection, + dataProjection: this.readProjectionFromDocument(null) + }; + } + } + features = ol.format.XMLFeature.transformFeaturesWithOptions( + features, true, opt_options); ol.xml.pushSerializeAndPop(/** @type {ol.xml.NodeStackItem} */ ({node: gpx}), ol.format.GPX.GPX_SERIALIZERS_, ol.format.GPX.GPX_NODE_FACTORY_, features, []); diff --git a/src/ol/format/topojsonformat.js b/src/ol/format/topojsonformat.js index 314b9b2c3e..5e272850d1 100644 --- a/src/ol/format/topojsonformat.js +++ b/src/ol/format/topojsonformat.js @@ -260,7 +260,7 @@ ol.format.TopoJSON.readFeatureFromGeometry_ = function(object, arcs, } var feature = new ol.Feature(); feature.setGeometry(ol.format.Feature.transformWithOptions( - geometry, false, opt_options)); + geometry, false, false, opt_options)); if (goog.isDef(object.id)) { feature.setId(object.id); } diff --git a/src/ol/format/xmlfeatureformat.js b/src/ol/format/xmlfeatureformat.js index f1d2eae3be..dc185b74df 100644 --- a/src/ol/format/xmlfeatureformat.js +++ b/src/ol/format/xmlfeatureformat.js @@ -5,6 +5,7 @@ goog.require('goog.asserts'); goog.require('goog.dom.NodeType'); goog.require('ol.format.Feature'); goog.require('ol.format.FormatType'); +goog.require('ol.proj'); goog.require('ol.xml'); @@ -243,3 +244,36 @@ ol.format.XMLFeature.prototype.writeGeometry = function(geometry, opt_options) { * @return {Node} Node. */ ol.format.XMLFeature.prototype.writeGeometryNode = goog.abstractMethod; + + +/** + * @param {Array.} features Features. + * @param {boolean} write Set to true for writing, false for reading. For + * writing, the features will be cloned before transforming. + * @param {(olx.format.WriteOptions|olx.format.ReadOptions)=} opt_options + * Options. + * @protected + * @return {Array.} Features. + */ +ol.format.XMLFeature.transformFeaturesWithOptions = function( + features, write, opt_options) { + var featureProjection = goog.isDef(opt_options) ? + ol.proj.get(opt_options.featureProjection) : null; + var dataProjection = goog.isDef(opt_options) ? + ol.proj.get(opt_options.dataProjection) : null; + + if (!goog.isNull(featureProjection) && !goog.isNull(dataProjection) && + !ol.proj.equivalent(featureProjection, dataProjection)) { + if (write) { + features = goog.array.map(features, function(feature) { + return feature.clone(); + }); + } + + goog.array.forEach(features, function(feature) { + feature.setGeometry(ol.format.Feature.transformWithOptions( + feature.getGeometry(), write, false, opt_options)); + }); + } + return features; +}; diff --git a/test/spec/ol/format/gpxformat.test.js b/test/spec/ol/format/gpxformat.test.js index 1a0f9c7180..0897b38c1d 100644 --- a/test/spec/ol/format/gpxformat.test.js +++ b/test/spec/ol/format/gpxformat.test.js @@ -1,5 +1,6 @@ goog.provide('ol.test.format.GPX'); +goog.require('ol.proj'); describe('ol.format.GPX', function() { @@ -80,6 +81,34 @@ describe('ol.format.GPX', function() { expect(serialized).to.xmleql(ol.xml.load(text)); }); + it('can transform, read and write a rte', function() { + var text = + '' + + ' ' + + ' ' + + ' ' + + ' ' + + ''; + var fs = format.readFeatures(text, { + featureProjection: 'EPSG:3857' + }); + expect(fs).to.have.length(1); + var f = fs[0]; + expect(f).to.be.an(ol.Feature); + var g = f.getGeometry(); + expect(g).to.be.an(ol.geom.LineString); + var p1 = ol.proj.transform([2, 1], 'EPSG:4326', 'EPSG:3857'); + p1.push(0, 0); + var p2 = ol.proj.transform([6, 5], 'EPSG:4326', 'EPSG:3857'); + p2.push(0, 0); + expect(g.getCoordinates()).to.eql([p1, p2]); + expect(g.getLayout()).to.be(ol.geom.GeometryLayout.XYZM); + var serialized = format.writeFeatures(fs, { + featureProjection: 'EPSG:3857' + }); + expect(serialized).to.xmleql(ol.xml.load(text)); + }); + }); describe('trk', function() { @@ -181,6 +210,42 @@ describe('ol.format.GPX', function() { expect(serialized).to.xmleql(ol.xml.load(text)); }); + it('can tranform, read and write a trk with a trkseg', function() { + var text = + '' + + ' ' + + ' ' + + ' ' + + ' 3' + + ' ' + + ' ' + + ' ' + + ' 7' + + ' ' + + ' ' + + ' ' + + ' ' + + ''; + var fs = format.readFeatures(text, { + featureProjection: 'EPSG:3857' + }); + expect(fs).to.have.length(1); + var f = fs[0]; + expect(f).to.be.an(ol.Feature); + var g = f.getGeometry(); + expect(g).to.be.an(ol.geom.MultiLineString); + var p1 = ol.proj.transform([2, 1], 'EPSG:4326', 'EPSG:3857'); + p1.push(3, 1263115752); + var p2 = ol.proj.transform([6, 5], 'EPSG:4326', 'EPSG:3857'); + p2.push(7, 1263115812); + expect(g.getCoordinates()).to.eql([[p1, p2]]); + expect(g.getLayout()).to.be(ol.geom.GeometryLayout.XYZM); + var serialized = format.writeFeatures(fs, { + featureProjection: 'EPSG:3857' + }); + expect(serialized).to.xmleql(ol.xml.load(text)); + }); + it('can read and write a trk with multiple trksegs', function() { var text = '' + @@ -243,6 +308,29 @@ describe('ol.format.GPX', function() { expect(serialized).to.xmleql(ol.xml.load(text)); }); + it('can transform, read and write a wpt', function() { + var text = + '' + + ' ' + + ''; + var fs = format.readFeatures(text, { + featureProjection: 'EPSG:3857' + }); + expect(fs).to.have.length(1); + var f = fs[0]; + expect(f).to.be.an(ol.Feature); + var g = f.getGeometry(); + expect(g).to.be.an(ol.geom.Point); + var expectedPoint = ol.proj.transform([2, 1], 'EPSG:4326', 'EPSG:3857'); + expectedPoint.push(0, 0); + expect(g.getCoordinates()).to.eql(expectedPoint); + expect(g.getLayout()).to.be(ol.geom.GeometryLayout.XYZM); + var serialized = format.writeFeatures(fs, { + featureProjection: 'EPSG:3857' + }); + expect(serialized).to.xmleql(ol.xml.load(text)); + }); + it('can read and write a wpt with ele', function() { var text = '' + From b05f880f7cc9b59c44f98f0e9e3f41eb312ff654 Mon Sep 17 00:00:00 2001 From: tsauerwein Date: Fri, 8 Aug 2014 16:40:46 +0200 Subject: [PATCH 22/33] Implement read/write transforms for ol.format.KML --- src/ol/format/gpxformat.js | 14 ++-- src/ol/format/kmlformat.js | 23 ++++- src/ol/format/xmlfeatureformat.js | 21 +++++ test/spec/ol/format/gpxformat.test.js | 3 +- test/spec/ol/format/kmlformat.test.js | 116 ++++++++++++++++++++++++++ test/spec/ol/format/topojson.test.js | 3 +- 6 files changed, 163 insertions(+), 17 deletions(-) diff --git a/src/ol/format/gpxformat.js b/src/ol/format/gpxformat.js index d3a7dc9413..2c4d6d80c1 100644 --- a/src/ol/format/gpxformat.js +++ b/src/ol/format/gpxformat.js @@ -864,17 +864,13 @@ ol.format.GPX.prototype.writeFeatures; ol.format.GPX.prototype.writeFeaturesNode = function(features, opt_options) { //FIXME Serialize metadata var gpx = ol.xml.createElementNS('http://www.topografix.com/GPX/1/1', 'gpx'); - if (goog.isDef(opt_options)) { - if (!goog.isDef(opt_options.dataProjection)) { - // for convenience set a default dataProjection - opt_options = { - featureProjection: opt_options.featureProjection, - dataProjection: this.readProjectionFromDocument(null) - }; - } - } + + // for convenience set a default dataProjection + opt_options = ol.format.XMLFeature.setDefaultDataProjection( + opt_options, this.readProjectionFromDocument(null)); features = ol.format.XMLFeature.transformFeaturesWithOptions( features, true, opt_options); + ol.xml.pushSerializeAndPop(/** @type {ol.xml.NodeStackItem} */ ({node: gpx}), ol.format.GPX.GPX_SERIALIZERS_, ol.format.GPX.GPX_NODE_FACTORY_, features, []); diff --git a/src/ol/format/kmlformat.js b/src/ol/format/kmlformat.js index 20f0fef1c6..83333f9e31 100644 --- a/src/ol/format/kmlformat.js +++ b/src/ol/format/kmlformat.js @@ -1487,6 +1487,7 @@ ol.format.KML.prototype.readSharedStyleMap_ = function(node, objectStack) { * * @function * @param {ArrayBuffer|Document|Node|Object|string} source Source. + * @param {olx.format.ReadOptions=} opt_options Read options. * @return {ol.Feature} Feature. * @api */ @@ -1496,7 +1497,7 @@ ol.format.KML.prototype.readFeature; /** * @inheritDoc */ -ol.format.KML.prototype.readFeatureFromNode = function(node) { +ol.format.KML.prototype.readFeatureFromNode = function(node, opt_options) { goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT); if (!goog.array.contains(ol.format.KML.NAMESPACE_URIS_, node.namespaceURI)) { return null; @@ -1504,6 +1505,8 @@ ol.format.KML.prototype.readFeatureFromNode = function(node) { goog.asserts.assert(node.localName == 'Placemark'); var feature = this.readPlacemark_(node, []); if (goog.isDef(feature)) { + ol.format.XMLFeature.transformFeaturesWithOptions( + [feature], false, this.getReadOptions(node, opt_options)); return feature; } else { return null; @@ -1516,6 +1519,7 @@ ol.format.KML.prototype.readFeatureFromNode = function(node) { * * @function * @param {ArrayBuffer|Document|Node|Object|string} source Source. + * @param {olx.format.ReadOptions=} opt_options Read options. * @return {Array.} Features. * @api */ @@ -1525,7 +1529,7 @@ ol.format.KML.prototype.readFeatures; /** * @inheritDoc */ -ol.format.KML.prototype.readFeaturesFromNode = function(node) { +ol.format.KML.prototype.readFeaturesFromNode = function(node, opt_options) { goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT); if (!goog.array.contains(ol.format.KML.NAMESPACE_URIS_, node.namespaceURI)) { return []; @@ -1535,6 +1539,8 @@ ol.format.KML.prototype.readFeaturesFromNode = function(node) { if (localName == 'Document' || localName == 'Folder') { features = this.readDocumentOrFolder_(node, []); if (goog.isDef(features)) { + ol.format.XMLFeature.transformFeaturesWithOptions( + features, false, this.getReadOptions(node, opt_options)); return features; } else { return []; @@ -1542,6 +1548,8 @@ ol.format.KML.prototype.readFeaturesFromNode = function(node) { } else if (localName == 'Placemark') { var feature = this.readPlacemark_(node, []); if (goog.isDef(feature)) { + ol.format.XMLFeature.transformFeaturesWithOptions( + [feature], false, this.getReadOptions(node, opt_options)); return [feature]; } else { return []; @@ -1551,7 +1559,7 @@ ol.format.KML.prototype.readFeaturesFromNode = function(node) { var n; for (n = node.firstElementChild; !goog.isNull(n); n = n.nextElementSibling) { - var fs = this.readFeaturesFromNode(n); + var fs = this.readFeaturesFromNode(n, opt_options); if (goog.isDef(fs)) { goog.array.extend(features, fs); } @@ -2494,6 +2502,7 @@ ol.format.KML.OUTER_BOUNDARY_NODE_FACTORY_ = * * @function * @param {Array.} features Features. + * @param {olx.format.WriteOptions=} opt_options Options. * @return {Node} Result. * @api */ @@ -2503,7 +2512,7 @@ ol.format.KML.prototype.writeFeatures; /** * @inheritDoc */ -ol.format.KML.prototype.writeFeaturesNode = function(features) { +ol.format.KML.prototype.writeFeaturesNode = function(features, opt_options) { var kml = ol.xml.createElementNS(ol.format.KML.NAMESPACE_URIS_[4], 'kml'); var xmlnsUri = 'http://www.w3.org/2000/xmlns/'; var xmlSchemaInstanceUri = 'http://www.w3.org/2001/XMLSchema-instance'; @@ -2513,6 +2522,12 @@ ol.format.KML.prototype.writeFeaturesNode = function(features) { ol.xml.setAttributeNS(kml, xmlSchemaInstanceUri, 'xsi:schemaLocation', ol.format.KML.SCHEMA_LOCATION_); + // for convenience set a default dataProjection + opt_options = ol.format.XMLFeature.setDefaultDataProjection( + opt_options, this.readProjectionFromDocument(null)); + features = ol.format.XMLFeature.transformFeaturesWithOptions( + features, true, opt_options); + var /** @type {ol.xml.NodeStackItem} */ context = {node: kml}; var properties = {}; if (features.length > 1) { diff --git a/src/ol/format/xmlfeatureformat.js b/src/ol/format/xmlfeatureformat.js index dc185b74df..79ba70b62d 100644 --- a/src/ol/format/xmlfeatureformat.js +++ b/src/ol/format/xmlfeatureformat.js @@ -277,3 +277,24 @@ ol.format.XMLFeature.transformFeaturesWithOptions = function( } return features; }; + + +/** + * @param {(olx.format.WriteOptions|olx.format.ReadOptions)=} opt_options + * Options. + * @param {ol.proj.ProjectionLike} defaultDataProjection Default projection. + * @protected + * @return {(olx.format.WriteOptions|olx.format.ReadOptions)=} Updated options. + */ +ol.format.XMLFeature.setDefaultDataProjection = function( + opt_options, defaultDataProjection) { + if (goog.isDef(opt_options)) { + if (!goog.isDef(opt_options.dataProjection)) { + opt_options = { + featureProjection: opt_options.featureProjection, + dataProjection: defaultDataProjection + }; + } + } + return opt_options; +}; diff --git a/test/spec/ol/format/gpxformat.test.js b/test/spec/ol/format/gpxformat.test.js index 0897b38c1d..d26b101553 100644 --- a/test/spec/ol/format/gpxformat.test.js +++ b/test/spec/ol/format/gpxformat.test.js @@ -1,7 +1,5 @@ goog.provide('ol.test.format.GPX'); -goog.require('ol.proj'); - describe('ol.format.GPX', function() { var format; @@ -559,4 +557,5 @@ goog.require('ol.format.GPX'); goog.require('ol.geom.LineString'); goog.require('ol.geom.MultiLineString'); goog.require('ol.geom.Point'); +goog.require('ol.proj'); goog.require('ol.xml'); diff --git a/test/spec/ol/format/kmlformat.test.js b/test/spec/ol/format/kmlformat.test.js index b3add3f507..6f49b449a4 100644 --- a/test/spec/ol/format/kmlformat.test.js +++ b/test/spec/ol/format/kmlformat.test.js @@ -119,6 +119,76 @@ describe('ol.format.KML', function() { expect(g.getCoordinates()).to.eql([1, 2, 3]); }); + it('can transform and read Point geometries', function() { + var text = + '' + + ' ' + + ' ' + + ' 1,2,3' + + ' ' + + ' ' + + ''; + var fs = format.readFeatures(text, { + featureProjection: 'EPSG:3857' + }); + expect(fs).to.have.length(1); + var f = fs[0]; + expect(f).to.be.an(ol.Feature); + var g = f.getGeometry(); + expect(g).to.be.an(ol.geom.Point); + var expectedPoint = ol.proj.transform([1, 2], 'EPSG:4326', 'EPSG:3857'); + expectedPoint.push(3); + expect(g.getCoordinates()).to.eql(expectedPoint); + }); + + it('can read a single Point geometry', function() { + var text = + '' + + ' ' + + ' ' + + ' 1,2,3' + + ' ' + + ' ' + + ''; + var f = format.readFeature(text); + expect(f).to.be.an(ol.Feature); + var g = f.getGeometry(); + expect(g).to.be.an(ol.geom.Point); + expect(g.getCoordinates()).to.eql([1, 2, 3]); + }); + + it('can transform and read a single Point geometry', function() { + var text = + '' + + ' ' + + ' ' + + ' 1,2,3' + + ' ' + + ' ' + + ''; + var f = format.readFeature(text, { + featureProjection: 'EPSG:3857' + }); + expect(f).to.be.an(ol.Feature); + var g = f.getGeometry(); + expect(g).to.be.an(ol.geom.Point); + var expectedPoint = ol.proj.transform([1, 2], 'EPSG:4326', 'EPSG:3857'); + expectedPoint.push(3); + expect(g.getCoordinates()).to.eql(expectedPoint); + }); + it('can write XY Point geometries', function() { var layout = ol.geom.GeometryLayout.XY; var point = new ol.geom.Point([1, 2], layout); @@ -159,6 +229,29 @@ describe('ol.format.KML', function() { expect(node).to.xmleql(ol.xml.load(text)); }); + it('can transform and write XYZ Point geometries', function() { + var layout = ol.geom.GeometryLayout.XYZ; + var point = new ol.geom.Point([1, 2, 3], layout).transform( + 'EPSG:4326', 'EPSG:3857'); + var features = [new ol.Feature(point)]; + var node = format.writeFeatures(features, { + featureProjection: 'EPSG:3857' + }); + var text = + '' + + ' ' + + ' ' + + ' 1,2,3' + + ' ' + + ' ' + + ''; + expect(node).to.xmleql(ol.xml.load(text)); + }); + it('can write XYM Point geometries', function() { var layout = ol.geom.GeometryLayout.XYM; var point = new ol.geom.Point([1, 2, 100], layout); @@ -1890,6 +1983,28 @@ describe('ol.format.KML', function() { expect(fs[0]).to.be.an(ol.Feature); }); + it('can transform and read a single feature from a Document', function() { + var text = + '' + + ' ' + + ' ' + + ' 1,2,3' + + ' ' + + ' ' + + ''; + var fs = format.readFeatures(text, { + featureProjection: 'EPSG:3857' + }); + expect(fs).to.have.length(1); + var f = fs[0]; + expect(f).to.be.an(ol.Feature); + var g = f.getGeometry(); + expect(g).to.be.an(ol.geom.Point); + var expectedPoint = ol.proj.transform([1, 2], 'EPSG:4326', 'EPSG:3857'); + expectedPoint.push(3); + expect(g.getCoordinates()).to.eql(expectedPoint); + }); + it('can read a multiple features from a Document', function() { var text = '' + @@ -2317,6 +2432,7 @@ goog.require('ol.geom.Polygon'); goog.require('ol.style.Fill'); goog.require('ol.style.Icon'); goog.require('ol.style.IconOrigin'); +goog.require('ol.proj'); goog.require('ol.style.Stroke'); goog.require('ol.style.Style'); goog.require('ol.style.Text'); diff --git a/test/spec/ol/format/topojson.test.js b/test/spec/ol/format/topojson.test.js index 8ef332cdb8..47f0ac7acd 100644 --- a/test/spec/ol/format/topojson.test.js +++ b/test/spec/ol/format/topojson.test.js @@ -1,7 +1,5 @@ goog.provide('ol.test.format.TopoJSON'); -goog.require('ol.proj'); - var aruba = { type: 'Topology', transform: { @@ -160,4 +158,5 @@ goog.require('ol.Feature'); goog.require('ol.geom.MultiPolygon'); goog.require('ol.geom.Polygon'); goog.require('ol.format.Feature'); +goog.require('ol.proj'); goog.require('ol.format.TopoJSON'); From bfb6c2e3b82587fbd43461972b1e23b6a157db87 Mon Sep 17 00:00:00 2001 From: tsauerwein Date: Fri, 8 Aug 2014 17:25:05 +0200 Subject: [PATCH 23/33] Implement read transforms for ol.format.OSMXML --- src/ol/format/osmxmlformat.js | 5 +- test/spec/ol/format/osmxmlformat.test.js | 105 +++++++++++++++++++++++ 2 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 test/spec/ol/format/osmxmlformat.test.js diff --git a/src/ol/format/osmxmlformat.js b/src/ol/format/osmxmlformat.js index 456247d47d..7627b428df 100644 --- a/src/ol/format/osmxmlformat.js +++ b/src/ol/format/osmxmlformat.js @@ -189,6 +189,7 @@ ol.format.OSMXML.NODE_PARSERS_ = ol.xml.makeParsersNS( * * @function * @param {ArrayBuffer|Document|Node|Object|string} source Source. + * @param {olx.format.ReadOptions=} opt_options Read options. * @return {Array.} Features. * @api */ @@ -198,7 +199,7 @@ ol.format.OSMXML.prototype.readFeatures; /** * @inheritDoc */ -ol.format.OSMXML.prototype.readFeaturesFromNode = function(node) { +ol.format.OSMXML.prototype.readFeaturesFromNode = function(node, opt_options) { goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT); if (node.localName == 'osm') { var state = ol.xml.pushParseAndPop({ @@ -206,6 +207,8 @@ ol.format.OSMXML.prototype.readFeaturesFromNode = function(node) { features: [] }, ol.format.OSMXML.PARSERS_, node, []); if (goog.isDef(state.features)) { + ol.format.XMLFeature.transformFeaturesWithOptions( + state.features, false, this.getReadOptions(node, opt_options)); return state.features; } } diff --git a/test/spec/ol/format/osmxmlformat.test.js b/test/spec/ol/format/osmxmlformat.test.js new file mode 100644 index 0000000000..9053083aa1 --- /dev/null +++ b/test/spec/ol/format/osmxmlformat.test.js @@ -0,0 +1,105 @@ +goog.provide('ol.test.format.OSMXML'); + + +describe('ol.format.OSMXML', function() { + + var format; + beforeEach(function() { + format = new ol.format.OSMXML(); + }); + + describe('#readFeatures', function() { + + it('can read an empty document', function() { + var text = + '' + + '' + + ''; + var fs = format.readFeatures(text); + expect(fs).to.have.length(0); + }); + + it('can read nodes', function() { + var text = + '' + + '' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ''; + var fs = format.readFeatures(text); + expect(fs).to.have.length(2); + var f = fs[0]; + expect(f).to.be.an(ol.Feature); + var g = f.getGeometry(); + expect(g).to.be.an(ol.geom.Point); + expect(g.getCoordinates()).to.eql([2, 1]); + }); + + it('can read nodes and ways', function() { + var text = + '' + + '' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ''; + var fs = format.readFeatures(text); + expect(fs).to.have.length(3); + var point = fs[0]; + expect(point).to.be.an(ol.Feature); + var g = point.getGeometry(); + expect(g).to.be.an(ol.geom.Point); + expect(g.getCoordinates()).to.eql([2, 1]); + var line = fs[2]; + expect(line).to.be.an(ol.Feature); + g = line.getGeometry(); + expect(g).to.be.an(ol.geom.LineString); + expect(g.getCoordinates()).to.eql([[2, 1], [4, 3]]); + }); + + it('can transform and read nodes', function() { + var text = + '' + + '' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ''; + var fs = format.readFeatures(text, { + featureProjection: 'EPSG:3857' + }); + expect(fs).to.have.length(2); + var f = fs[0]; + expect(f).to.be.an(ol.Feature); + var g = f.getGeometry(); + expect(g).to.be.an(ol.geom.Point); + expect(g.getCoordinates()).to.eql( + ol.proj.transform([2, 1], 'EPSG:4326', 'EPSG:3857')); + }); + + }); + +}); + + +goog.require('goog.dom.xml'); +goog.require('ol.Feature'); +goog.require('ol.format.OSMXML'); +goog.require('ol.geom.Point'); +goog.require('ol.geom.LineString'); +goog.require('ol.proj'); From 9bc70f34590f456d4ecff01dab9c2465f6b594e3 Mon Sep 17 00:00:00 2001 From: tsauerwein Date: Mon, 11 Aug 2014 10:17:31 +0200 Subject: [PATCH 24/33] Implement read/write transforms for ol.format.WKT --- src/ol/format/textfeatureformat.js | 32 +++++++----- src/ol/format/wktformat.js | 39 +++++++++----- test/spec/ol/format/wktformat.test.js | 75 +++++++++++++++++++++++++++ 3 files changed, 121 insertions(+), 25 deletions(-) diff --git a/src/ol/format/textfeatureformat.js b/src/ol/format/textfeatureformat.js index bdfa98cbbf..0b30b5dc4a 100644 --- a/src/ol/format/textfeatureformat.js +++ b/src/ol/format/textfeatureformat.js @@ -47,13 +47,14 @@ ol.format.TextFeature.prototype.getType = function() { /** * @inheritDoc */ -ol.format.TextFeature.prototype.readFeature = function(source) { - return this.readFeatureFromText(this.getText_(source)); +ol.format.TextFeature.prototype.readFeature = function(source, opt_options) { + return this.readFeatureFromText(this.getText_(source), opt_options); }; /** * @param {string} text Text. + * @param {olx.format.ReadOptions=} opt_options Read options. * @protected * @return {ol.Feature} Feature. */ @@ -63,13 +64,14 @@ ol.format.TextFeature.prototype.readFeatureFromText = goog.abstractMethod; /** * @inheritDoc */ -ol.format.TextFeature.prototype.readFeatures = function(source) { - return this.readFeaturesFromText(this.getText_(source)); +ol.format.TextFeature.prototype.readFeatures = function(source, opt_options) { + return this.readFeaturesFromText(this.getText_(source), opt_options); }; /** * @param {string} text Text. + * @param {olx.format.ReadOptions=} opt_options Read options. * @protected * @return {Array.} Features. */ @@ -79,13 +81,14 @@ ol.format.TextFeature.prototype.readFeaturesFromText = goog.abstractMethod; /** * @inheritDoc */ -ol.format.TextFeature.prototype.readGeometry = function(source) { - return this.readGeometryFromText(this.getText_(source)); +ol.format.TextFeature.prototype.readGeometry = function(source, opt_options) { + return this.readGeometryFromText(this.getText_(source), opt_options); }; /** * @param {string} text Text. + * @param {olx.format.ReadOptions=} opt_options Read options. * @protected * @return {ol.geom.Geometry} Geometry. */ @@ -111,13 +114,14 @@ ol.format.TextFeature.prototype.readProjectionFromText = goog.abstractMethod; /** * @inheritDoc */ -ol.format.TextFeature.prototype.writeFeature = function(feature) { - return this.writeFeatureText(feature); +ol.format.TextFeature.prototype.writeFeature = function(feature, opt_options) { + return this.writeFeatureText(feature, opt_options); }; /** * @param {ol.Feature} feature Features. + * @param {olx.format.WriteOptions=} opt_options Write options. * @protected * @return {string} Text. */ @@ -127,13 +131,15 @@ ol.format.TextFeature.prototype.writeFeatureText = goog.abstractMethod; /** * @inheritDoc */ -ol.format.TextFeature.prototype.writeFeatures = function(features) { - return this.writeFeaturesText(features); +ol.format.TextFeature.prototype.writeFeatures = function( + features, opt_options) { + return this.writeFeaturesText(features, opt_options); }; /** * @param {Array.} features Features. + * @param {olx.format.WriteOptions=} opt_options Write options. * @protected * @return {string} Text. */ @@ -143,13 +149,15 @@ ol.format.TextFeature.prototype.writeFeaturesText = goog.abstractMethod; /** * @inheritDoc */ -ol.format.TextFeature.prototype.writeGeometry = function(geometry) { - return this.writeGeometryText(geometry); +ol.format.TextFeature.prototype.writeGeometry = function( + geometry, opt_options) { + return this.writeGeometryText(geometry, opt_options); }; /** * @param {ol.geom.Geometry} geometry Geometry. + * @param {olx.format.WriteOptions=} opt_options Write options. * @protected * @return {string} Text. */ diff --git a/src/ol/format/wktformat.js b/src/ol/format/wktformat.js index e0ba9b918a..d0c1f0a930 100644 --- a/src/ol/format/wktformat.js +++ b/src/ol/format/wktformat.js @@ -3,6 +3,7 @@ goog.provide('ol.format.WKT'); goog.require('goog.array'); goog.require('goog.asserts'); goog.require('ol.Feature'); +goog.require('ol.format.Feature'); goog.require('ol.format.TextFeature'); goog.require('ol.geom.Geometry'); goog.require('ol.geom.GeometryCollection'); @@ -208,6 +209,7 @@ ol.format.WKT.prototype.parse_ = function(wkt) { * * @function * @param {ArrayBuffer|Document|Node|Object|string} source Source. + * @param {olx.format.ReadOptions=} opt_options Read options. * @return {ol.Feature} Feature. * @api */ @@ -217,8 +219,8 @@ ol.format.WKT.prototype.readFeature; /** * @inheritDoc */ -ol.format.WKT.prototype.readFeatureFromText = function(text) { - var geom = this.readGeometryFromText(text); +ol.format.WKT.prototype.readFeatureFromText = function(text, opt_options) { + var geom = this.readGeometryFromText(text, opt_options); if (goog.isDef(geom)) { var feature = new ol.Feature(); feature.setGeometry(geom); @@ -233,6 +235,7 @@ ol.format.WKT.prototype.readFeatureFromText = function(text) { * * @function * @param {ArrayBuffer|Document|Node|Object|string} source Source. + * @param {olx.format.ReadOptions=} opt_options Read options. * @return {Array.} Features. * @api */ @@ -242,9 +245,9 @@ ol.format.WKT.prototype.readFeatures; /** * @inheritDoc */ -ol.format.WKT.prototype.readFeaturesFromText = function(text) { +ol.format.WKT.prototype.readFeaturesFromText = function(text, opt_options) { var geometries = []; - var geometry = this.readGeometryFromText(text); + var geometry = this.readGeometryFromText(text, opt_options); if (this.splitCollection_ && geometry.getType() == ol.geom.GeometryType.GEOMETRY_COLLECTION) { geometries = (/** @type {ol.geom.GeometryCollection} */ (geometry)) @@ -267,6 +270,7 @@ ol.format.WKT.prototype.readFeaturesFromText = function(text) { * * @function * @param {ArrayBuffer|Document|Node|Object|string} source Source. + * @param {olx.format.ReadOptions=} opt_options Read options. * @return {ol.geom.Geometry} Geometry. * @api */ @@ -276,8 +280,14 @@ ol.format.WKT.prototype.readGeometry; /** * @inheritDoc */ -ol.format.WKT.prototype.readGeometryFromText = function(text) { - return this.parse_(text) || null; +ol.format.WKT.prototype.readGeometryFromText = function(text, opt_options) { + var geometry = this.parse_(text); + if (goog.isDef(geometry)) { + return ol.format.Feature.transformWithOptions( + geometry, false, false, opt_options); + } else { + return null; + } }; @@ -294,6 +304,7 @@ ol.format.WKT.prototype.readProjectionFromText = function(text) { * * @function * @param {ol.Feature} feature Feature. + * @param {olx.format.WriteOptions=} opt_options Write options. * @return {string} WKT string. * @api */ @@ -303,10 +314,10 @@ ol.format.WKT.prototype.writeFeature; /** * @inheritDoc */ -ol.format.WKT.prototype.writeFeatureText = function(feature) { +ol.format.WKT.prototype.writeFeatureText = function(feature, opt_options) { var geometry = feature.getGeometry(); if (goog.isDef(geometry)) { - return this.writeGeometryText(geometry); + return this.writeGeometryText(geometry, opt_options); } return ''; }; @@ -317,6 +328,7 @@ ol.format.WKT.prototype.writeFeatureText = function(feature) { * * @function * @param {Array.} features Features. + * @param {olx.format.WriteOptions=} opt_options Write options. * @return {string} WKT string. * @api */ @@ -326,16 +338,16 @@ ol.format.WKT.prototype.writeFeatures; /** * @inheritDoc */ -ol.format.WKT.prototype.writeFeaturesText = function(features) { +ol.format.WKT.prototype.writeFeaturesText = function(features, opt_options) { if (features.length == 1) { - return this.writeFeatureText(features[0]); + return this.writeFeatureText(features[0], opt_options); } var geometries = []; for (var i = 0, ii = features.length; i < ii; ++i) { geometries.push(features[i].getGeometry()); } var collection = new ol.geom.GeometryCollection(geometries); - return this.writeGeometryText(collection); + return this.writeGeometryText(collection, opt_options); }; @@ -353,8 +365,9 @@ ol.format.WKT.prototype.writeGeometry; /** * @inheritDoc */ -ol.format.WKT.prototype.writeGeometryText = function(geometry) { - return ol.format.WKT.encode_(geometry); +ol.format.WKT.prototype.writeGeometryText = function(geometry, opt_options) { + return ol.format.WKT.encode_(ol.format.Feature.transformWithOptions( + geometry, true, true, opt_options)); }; diff --git a/test/spec/ol/format/wktformat.test.js b/test/spec/ol/format/wktformat.test.js index f14e6ccfd6..66f9e84088 100644 --- a/test/spec/ol/format/wktformat.test.js +++ b/test/spec/ol/format/wktformat.test.js @@ -15,6 +15,21 @@ describe('ol.format.WKT', function() { expect(geom.getCoordinates()).to.eql([30, 10]); }); + it('Point transformed / read / written correctly', function() { + var wkt = 'POINT(1 2)'; + var geom = format.readGeometry(wkt, { + dataProjection: 'EPSG:4326', + featureProjection: 'EPSG:3857' + }); + expect(geom.getCoordinates()).to.eql( + ol.proj.transform([1, 2], 'EPSG:4326', 'EPSG:3857')); + var newWkt = format.writeGeometry(geom, { + dataProjection: 'EPSG:4326', + featureProjection: 'EPSG:3857' + }); + expect(newWkt).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))'; @@ -231,7 +246,67 @@ describe('ol.format.WKT', function() { expect(format.writeFeatures(features)).to.eql(wkt); }); + it('Point feature read / written correctly', function() { + var wkt = 'POINT(30 10)'; + var feature = format.readFeature(wkt); + var geom = feature.getGeometry(); + expect(geom.getCoordinates()).to.eql([30, 10]); + expect(format.writeFeature(feature)).to.eql(wkt); + }); + + it('Point feature transformed / read / written correctly', function() { + var wkt = 'POINT(1 2)'; + var feature = format.readFeature(wkt, { + dataProjection: 'EPSG:4326', + featureProjection: 'EPSG:3857' + }); + var geom = feature.getGeometry(); + expect(geom.getCoordinates()).to.eql( + ol.proj.transform([1, 2], 'EPSG:4326', 'EPSG:3857')); + var newWkt = format.writeFeature(feature, { + dataProjection: 'EPSG:4326', + featureProjection: 'EPSG:3857' + }); + expect(newWkt).to.eql(wkt); + }); + + it('Features read / written correctly', function() { + var wkt = 'GEOMETRYCOLLECTION(POINT(1 2),POINT(3 4))'; + var features = format.readFeatures(wkt); + expect(features.length).to.eql(2); + var point1 = features[0].getGeometry(); + var point2 = features[1].getGeometry(); + expect(point1.getType()).to.eql(ol.geom.GeometryType.POINT); + expect(point2.getType()).to.eql(ol.geom.GeometryType.POINT); + expect(point1.getCoordinates()).to.eql([1, 2]); + expect(point2.getCoordinates()).to.eql([3, 4]); + expect(format.writeFeatures(features)).to.eql(wkt); + }); + + it('Features transformed / read / written correctly', function() { + var wkt = 'GEOMETRYCOLLECTION(POINT(1 2),POINT(4 5))'; + var features = format.readFeatures(wkt, { + dataProjection: 'EPSG:4326', + featureProjection: 'EPSG:3857' + }); + expect(features.length).to.eql(2); + var point1 = features[0].getGeometry(); + var point2 = features[1].getGeometry(); + expect(point1.getType()).to.eql(ol.geom.GeometryType.POINT); + expect(point2.getType()).to.eql(ol.geom.GeometryType.POINT); + expect(point1.getCoordinates()).to.eql( + ol.proj.transform([1, 2], 'EPSG:4326', 'EPSG:3857')); + expect(point2.getCoordinates()).to.eql( + ol.proj.transform([4, 5], 'EPSG:4326', 'EPSG:3857')); + var newWkt = format.writeFeatures(features, { + dataProjection: 'EPSG:4326', + featureProjection: 'EPSG:3857' + }); + expect(newWkt).to.eql(wkt); + }); + }); goog.require('ol.geom.GeometryType'); goog.require('ol.format.WKT'); +goog.require('ol.proj'); From f8560df793029068a20e891b77ab12a4fde75cfe Mon Sep 17 00:00:00 2001 From: tsauerwein Date: Mon, 11 Aug 2014 10:51:34 +0200 Subject: [PATCH 25/33] Implement read transforms for ol.format.IGC --- src/ol/format/igcformat.js | 12 ++- test/spec/ol/format/igcformat.test.js | 123 ++++++++++++++++++++++++++ test/spec/ol/format/igcformattest.js | 29 ------ 3 files changed, 131 insertions(+), 33 deletions(-) create mode 100644 test/spec/ol/format/igcformat.test.js delete mode 100644 test/spec/ol/format/igcformattest.js diff --git a/src/ol/format/igcformat.js b/src/ol/format/igcformat.js index c96cbe3d53..664cd35a10 100644 --- a/src/ol/format/igcformat.js +++ b/src/ol/format/igcformat.js @@ -5,6 +5,7 @@ goog.require('goog.asserts'); goog.require('goog.string'); goog.require('goog.string.newlines'); goog.require('ol.Feature'); +goog.require('ol.format.Feature'); goog.require('ol.format.TextFeature'); goog.require('ol.geom.LineString'); goog.require('ol.proj'); @@ -93,6 +94,7 @@ ol.format.IGC.prototype.getExtensions = function() { * * @function * @param {ArrayBuffer|Document|Node|Object|string} source Source. + * @param {olx.format.ReadOptions=} opt_options Read options. * @return {ol.Feature} Feature. * @api */ @@ -102,7 +104,7 @@ ol.format.IGC.prototype.readFeature; /** * @inheritDoc */ -ol.format.IGC.prototype.readFeatureFromText = function(text) { +ol.format.IGC.prototype.readFeatureFromText = function(text, opt_options) { var altitudeMode = this.altitudeMode_; var lines = goog.string.newlines.splitLines(text); /** @type {Object.} */ @@ -167,7 +169,8 @@ ol.format.IGC.prototype.readFeatureFromText = function(text) { var layout = altitudeMode == ol.format.IGCZ.NONE ? ol.geom.GeometryLayout.XYM : ol.geom.GeometryLayout.XYZM; lineString.setFlatCoordinates(layout, flatCoordinates); - var feature = new ol.Feature(lineString); + var feature = new ol.Feature(ol.format.Feature.transformWithOptions( + lineString, false, false, opt_options)); feature.setProperties(properties); return feature; }; @@ -179,6 +182,7 @@ ol.format.IGC.prototype.readFeatureFromText = function(text) { * * @function * @param {ArrayBuffer|Document|Node|Object|string} source Source. + * @param {olx.format.ReadOptions=} opt_options Read options. * @return {Array.} Features. * @api */ @@ -188,8 +192,8 @@ ol.format.IGC.prototype.readFeatures; /** * @inheritDoc */ -ol.format.IGC.prototype.readFeaturesFromText = function(text) { - var feature = this.readFeatureFromText(text); +ol.format.IGC.prototype.readFeaturesFromText = function(text, opt_options) { + var feature = this.readFeatureFromText(text, opt_options); if (!goog.isNull(feature)) { return [feature]; } else { diff --git a/test/spec/ol/format/igcformat.test.js b/test/spec/ol/format/igcformat.test.js new file mode 100644 index 0000000000..24921941b0 --- /dev/null +++ b/test/spec/ol/format/igcformat.test.js @@ -0,0 +1,123 @@ +goog.provide('ol.test.format.IGC'); + + +describe('ol.format.IGC', function() { + + var format; + var igc = + 'AFLY05094\n' + + 'HFDTE190411\n' + + 'HFFXA100\n' + + 'HFPLTPILOT:Tom Payne\n' + + 'HFGTYGLIDERTYPE:Axis Mercury\n' + + 'HFGIDGLIDERID:\n' + + 'HFDTM100GPSDATUM:WGS84\n' + + 'HFGPSGPS:FURUNO GH-80\n' + + 'HFRFWFIRMWAREVERSION:1.22\n' + + 'HFRHWHARDWAREVERSION:1.00\n' + + 'HFFTYFRTYPE:FLYTEC,5020\n' + + 'I013638TAS\n' + + 'B0848484556256N00651095EA0205102039000\n' + + 'B0855534556037N00651011EA0259302513000\n' + + 'B0903354554964N00648049EA0272402758000\n' + + 'GAB890A77AFE5CE63979AF6B1BED7F07D\n' + + 'G62BB282E44D63A1149EF2F5E8AF6F2F1\n' + + 'GEC14381987B15F81003EDE1E01A47843\n' + + 'G60189641B00B00800019000000000000'; + + beforeEach(function() { + format = new ol.format.IGC(); + }); + + describe('#readFeature', function() { + it('does not read invalid features', function() { + expect(format.readFeature('invalid')).to.be(null); + }); + + it('does read a feature', function() { + var feature = format.readFeature(igc); + expect(feature).to.be.an(ol.Feature); + var geom = feature.getGeometry(); + expect(geom.getType()).to.eql(ol.geom.GeometryType.LINE_STRING); + expect(geom.getCoordinates()).to.eql([ + [6.851583333333333, 45.9376, 1303202928], + [6.850183333333334, 45.93395, 1303203353], + [6.800816666666667, 45.916066666666666, 1303203815]]); + }); + + it('does transform and read a feature', function() { + var feature = format.readFeature(igc, { + dataProjection: 'EPSG:4326', + featureProjection: 'EPSG:3857' + }); + expect(feature).to.be.an(ol.Feature); + var geom = feature.getGeometry(); + expect(geom.getType()).to.eql(ol.geom.GeometryType.LINE_STRING); + + var expectedPoint1 = ol.proj.transform( + [6.851583333333333, 45.9376], 'EPSG:4326', 'EPSG:3857'); + expectedPoint1.push(1303202928); + var expectedPoint2 = ol.proj.transform( + [6.850183333333334, 45.93395], 'EPSG:4326', 'EPSG:3857'); + expectedPoint2.push(1303203353); + var expectedPoint3 = ol.proj.transform( + [6.800816666666667, 45.916066666666666], 'EPSG:4326', 'EPSG:3857'); + expectedPoint3.push(1303203815); + + expect(geom.getCoordinates()).to.eql( + [expectedPoint1, expectedPoint2, expectedPoint3]); + }); + + }); + + describe('#readFeatures', function() { + + it('does not read invalid features', function() { + expect(format.readFeatures('invalid')).to.be.empty(); + }); + + it('does read features', function() { + var features = format.readFeatures(igc); + expect(features.length).to.eql(1); + var feature = features[0]; + expect(feature).to.be.an(ol.Feature); + var geom = feature.getGeometry(); + expect(geom.getType()).to.eql(ol.geom.GeometryType.LINE_STRING); + expect(geom.getCoordinates()).to.eql([ + [6.851583333333333, 45.9376, 1303202928], + [6.850183333333334, 45.93395, 1303203353], + [6.800816666666667, 45.916066666666666, 1303203815]]); + }); + + it('does transform and read features', function() { + var features = format.readFeatures(igc, { + dataProjection: 'EPSG:4326', + featureProjection: 'EPSG:3857' + }); + expect(features.length).to.eql(1); + var feature = features[0]; + expect(feature).to.be.an(ol.Feature); + var geom = feature.getGeometry(); + expect(geom.getType()).to.eql(ol.geom.GeometryType.LINE_STRING); + + var expectedPoint1 = ol.proj.transform( + [6.851583333333333, 45.9376], 'EPSG:4326', 'EPSG:3857'); + expectedPoint1.push(1303202928); + var expectedPoint2 = ol.proj.transform( + [6.850183333333334, 45.93395], 'EPSG:4326', 'EPSG:3857'); + expectedPoint2.push(1303203353); + var expectedPoint3 = ol.proj.transform( + [6.800816666666667, 45.916066666666666], 'EPSG:4326', 'EPSG:3857'); + expectedPoint3.push(1303203815); + + expect(geom.getCoordinates()).to.eql( + [expectedPoint1, expectedPoint2, expectedPoint3]); + }); + }); + +}); + +goog.require('ol.format.IGC'); +goog.require('ol.Feature'); +goog.require('ol.geom.GeometryType'); +goog.require('ol.proj'); diff --git a/test/spec/ol/format/igcformattest.js b/test/spec/ol/format/igcformattest.js deleted file mode 100644 index d77e1fc08e..0000000000 --- a/test/spec/ol/format/igcformattest.js +++ /dev/null @@ -1,29 +0,0 @@ -goog.provide('ol.test.format.IGC'); - - -describe('ol.format.IGC', function() { - - var format; - beforeEach(function() { - format = new ol.format.IGC(); - }); - - describe('#readFeature', function() { - - it('does not read invalid features', function() { - expect(format.readFeature('invalid')).to.be(null); - }); - - }); - - describe('#readFeatures', function() { - - it('does not read invalid features', function() { - expect(format.readFeatures('invalid')).to.be.empty(); - }); - - }); - -}); - -goog.require('ol.format.IGC'); From 48ed2e861e4dd3ce40b7524671681c1274b9dfc2 Mon Sep 17 00:00:00 2001 From: tsauerwein Date: Mon, 11 Aug 2014 11:59:27 +0200 Subject: [PATCH 26/33] Implement read/write transforms for ol.format.Polyline --- src/ol/format/featureformat.js | 21 +++++++ src/ol/format/gpxformat.js | 3 +- src/ol/format/kmlformat.js | 3 +- src/ol/format/polylineformat.js | 42 +++++++++---- src/ol/format/xmlfeatureformat.js | 21 ------- test/spec/ol/format/polylineformat.test.js | 70 +++++++++++++++++++--- 6 files changed, 119 insertions(+), 41 deletions(-) diff --git a/src/ol/format/featureformat.js b/src/ol/format/featureformat.js index d7176bcde0..ff674c19c7 100644 --- a/src/ol/format/featureformat.js +++ b/src/ol/format/featureformat.js @@ -146,3 +146,24 @@ ol.format.Feature.transformWithOptions = function( return geometry; } }; + + +/** + * @param {(olx.format.WriteOptions|olx.format.ReadOptions)=} opt_options + * Options. + * @param {ol.proj.ProjectionLike} defaultDataProjection Default projection. + * @protected + * @return {(olx.format.WriteOptions|olx.format.ReadOptions)=} Updated options. + */ +ol.format.Feature.setDefaultDataProjection = function( + opt_options, defaultDataProjection) { + if (goog.isDef(opt_options)) { + if (!goog.isDef(opt_options.dataProjection)) { + opt_options = { + featureProjection: opt_options.featureProjection, + dataProjection: defaultDataProjection + }; + } + } + return opt_options; +}; diff --git a/src/ol/format/gpxformat.js b/src/ol/format/gpxformat.js index 2c4d6d80c1..bcec5da2fb 100644 --- a/src/ol/format/gpxformat.js +++ b/src/ol/format/gpxformat.js @@ -5,6 +5,7 @@ goog.require('goog.asserts'); goog.require('goog.dom.NodeType'); goog.require('goog.object'); goog.require('ol.Feature'); +goog.require('ol.format.Feature'); goog.require('ol.format.XMLFeature'); goog.require('ol.format.XSD'); goog.require('ol.geom.LineString'); @@ -866,7 +867,7 @@ ol.format.GPX.prototype.writeFeaturesNode = function(features, opt_options) { var gpx = ol.xml.createElementNS('http://www.topografix.com/GPX/1/1', 'gpx'); // for convenience set a default dataProjection - opt_options = ol.format.XMLFeature.setDefaultDataProjection( + opt_options = ol.format.Feature.setDefaultDataProjection( opt_options, this.readProjectionFromDocument(null)); features = ol.format.XMLFeature.transformFeaturesWithOptions( features, true, opt_options); diff --git a/src/ol/format/kmlformat.js b/src/ol/format/kmlformat.js index 83333f9e31..8dc1aaf0c8 100644 --- a/src/ol/format/kmlformat.js +++ b/src/ol/format/kmlformat.js @@ -16,6 +16,7 @@ goog.require('ol.Feature'); goog.require('ol.array'); goog.require('ol.color'); goog.require('ol.feature'); +goog.require('ol.format.Feature'); goog.require('ol.format.XMLFeature'); goog.require('ol.format.XSD'); goog.require('ol.geom.Geometry'); @@ -2523,7 +2524,7 @@ ol.format.KML.prototype.writeFeaturesNode = function(features, opt_options) { ol.format.KML.SCHEMA_LOCATION_); // for convenience set a default dataProjection - opt_options = ol.format.XMLFeature.setDefaultDataProjection( + opt_options = ol.format.Feature.setDefaultDataProjection( opt_options, this.readProjectionFromDocument(null)); features = ol.format.XMLFeature.transformFeaturesWithOptions( features, true, opt_options); diff --git a/src/ol/format/polylineformat.js b/src/ol/format/polylineformat.js index 0f08dc1950..750f1aa078 100644 --- a/src/ol/format/polylineformat.js +++ b/src/ol/format/polylineformat.js @@ -2,6 +2,7 @@ goog.provide('ol.format.Polyline'); goog.require('goog.asserts'); goog.require('ol.Feature'); +goog.require('ol.format.Feature'); goog.require('ol.format.TextFeature'); goog.require('ol.geom.LineString'); goog.require('ol.geom.flat.inflate'); @@ -248,6 +249,7 @@ ol.format.Polyline.encodeUnsignedInteger = function(num) { * * @function * @param {ArrayBuffer|Document|Node|Object|string} source Source. + * @param {olx.format.ReadOptions=} opt_options Read options. * @return {ol.Feature} Feature. * @api */ @@ -257,8 +259,8 @@ ol.format.Polyline.prototype.readFeature; /** * @inheritDoc */ -ol.format.Polyline.prototype.readFeatureFromText = function(text) { - var geometry = this.readGeometryFromText(text); +ol.format.Polyline.prototype.readFeatureFromText = function(text, opt_options) { + var geometry = this.readGeometryFromText(text, opt_options); return new ol.Feature(geometry); }; @@ -269,6 +271,7 @@ ol.format.Polyline.prototype.readFeatureFromText = function(text) { * * @function * @param {ArrayBuffer|Document|Node|Object|string} source Source. + * @param {olx.format.ReadOptions=} opt_options Read options. * @return {Array.} Features. * @api */ @@ -278,8 +281,9 @@ ol.format.Polyline.prototype.readFeatures; /** * @inheritDoc */ -ol.format.Polyline.prototype.readFeaturesFromText = function(text) { - var feature = this.readFeatureFromText(text); +ol.format.Polyline.prototype.readFeaturesFromText = + function(text, opt_options) { + var feature = this.readFeatureFromText(text, opt_options); return [feature]; }; @@ -289,6 +293,7 @@ ol.format.Polyline.prototype.readFeaturesFromText = function(text) { * * @function * @param {ArrayBuffer|Document|Node|Object|string} source Source. + * @param {olx.format.ReadOptions=} opt_options Read options. * @return {ol.geom.Geometry} Geometry. * @api */ @@ -298,11 +303,18 @@ ol.format.Polyline.prototype.readGeometry; /** * @inheritDoc */ -ol.format.Polyline.prototype.readGeometryFromText = function(text) { +ol.format.Polyline.prototype.readGeometryFromText = + function(text, opt_options) { var flatCoordinates = ol.format.Polyline.decodeDeltas(text, 2, this.factor_); var coordinates = ol.geom.flat.inflate.coordinates( flatCoordinates, 0, flatCoordinates.length, 2); - return new ol.geom.LineString(coordinates); + + // for convenience set a default dataProjection + opt_options = ol.format.Feature.setDefaultDataProjection( + opt_options, this.readProjectionFromText(null)); + + return ol.format.Feature.transformWithOptions( + new ol.geom.LineString(coordinates), false, false, opt_options); }; @@ -328,10 +340,10 @@ ol.format.Polyline.prototype.readProjectionFromText = function(text) { /** * @inheritDoc */ -ol.format.Polyline.prototype.writeFeatureText = function(feature) { +ol.format.Polyline.prototype.writeFeatureText = function(feature, opt_options) { var geometry = feature.getGeometry(); if (goog.isDefAndNotNull(geometry)) { - return this.writeGeometryText(geometry); + return this.writeGeometryText(geometry, opt_options); } else { goog.asserts.fail(); return ''; @@ -342,9 +354,10 @@ ol.format.Polyline.prototype.writeFeatureText = function(feature) { /** * @inheritDoc */ -ol.format.Polyline.prototype.writeFeaturesText = function(features) { +ol.format.Polyline.prototype.writeFeaturesText = + function(features, opt_options) { goog.asserts.assert(features.length == 1); - return this.writeFeatureText(features[0]); + return this.writeFeatureText(features[0], opt_options); }; @@ -353,6 +366,7 @@ ol.format.Polyline.prototype.writeFeaturesText = function(features) { * * @function * @param {ol.geom.Geometry} geometry Geometry. + * @param {olx.format.WriteOptions=} opt_options Write options. * @return {string} Geometry. * @api */ @@ -362,8 +376,14 @@ ol.format.Polyline.prototype.writeGeometry; /** * @inheritDoc */ -ol.format.Polyline.prototype.writeGeometryText = function(geometry) { +ol.format.Polyline.prototype.writeGeometryText = + function(geometry, opt_options) { goog.asserts.assertInstanceof(geometry, ol.geom.LineString); + // for convenience set a default dataProjection + opt_options = ol.format.Feature.setDefaultDataProjection( + opt_options, this.readProjectionFromText(null)); + geometry = ol.format.Feature.transformWithOptions( + geometry, true, true, opt_options); var flatCoordinates = geometry.getFlatCoordinates(); var stride = geometry.getStride(); return ol.format.Polyline.encodeDeltas(flatCoordinates, stride, this.factor_); diff --git a/src/ol/format/xmlfeatureformat.js b/src/ol/format/xmlfeatureformat.js index 79ba70b62d..dc185b74df 100644 --- a/src/ol/format/xmlfeatureformat.js +++ b/src/ol/format/xmlfeatureformat.js @@ -277,24 +277,3 @@ ol.format.XMLFeature.transformFeaturesWithOptions = function( } return features; }; - - -/** - * @param {(olx.format.WriteOptions|olx.format.ReadOptions)=} opt_options - * Options. - * @param {ol.proj.ProjectionLike} defaultDataProjection Default projection. - * @protected - * @return {(olx.format.WriteOptions|olx.format.ReadOptions)=} Updated options. - */ -ol.format.XMLFeature.setDefaultDataProjection = function( - opt_options, defaultDataProjection) { - if (goog.isDef(opt_options)) { - if (!goog.isDef(opt_options.dataProjection)) { - opt_options = { - featureProjection: opt_options.featureProjection, - dataProjection: defaultDataProjection - }; - } - } - return opt_options; -}; diff --git a/test/spec/ol/format/polylineformat.test.js b/test/spec/ol/format/polylineformat.test.js index ff38fb6a79..2c09ff8dfc 100644 --- a/test/spec/ol/format/polylineformat.test.js +++ b/test/spec/ol/format/polylineformat.test.js @@ -11,13 +11,17 @@ describe('ol.format.Polyline', function() { function resetTestingData() { format = new ol.format.Polyline(); - points = [[38.50000, -120.20000], - [40.70000, -120.95000], - [43.25200, -126.45300]]; - flatPoints = [38.50000, -120.20000, - 40.70000, -120.95000, - 43.25200, -126.45300]; - encodedFlatPoints = '_p~iF~ps|U_ulLnnqC_mqNvxq`@'; + points = [[-120.20000, 38.50000], + [-120.95000, 40.70000], + [-126.45300, 43.25200]]; + flatPoints = [-120.20000, 38.50000, + -120.95000, 40.70000, + -126.45300, 43.25200]; + encodedFlatPoints = '~ps|U_p~iFnnqC_ulLvxq`@_mqN'; + points3857 = [ + ol.proj.transform([-120.20000, 38.50000], 'EPSG:4326', 'EPSG:3857'), + ol.proj.transform([-120.95000, 40.70000], 'EPSG:4326', 'EPSG:3857'), + ol.proj.transform([-126.45300, 43.25200], 'EPSG:4326', 'EPSG:3857')]; floats = [0.00, 0.15, -0.01, -0.16, 0.16, 0.01]; smallFloats = [0.00000, 0.00015, -0.00001, -0.00016, 0.00016, 0.00001]; @@ -253,6 +257,16 @@ describe('ol.format.Polyline', function() { expect(geometry.getFlatCoordinates()).to.eql(flatPoints); }); + it('transforms and returns the expected feature', function() { + var feature = format.readFeature(encodedFlatPoints, { + featureProjection: 'EPSG:3857' + }); + expect(feature).to.be.an(ol.Feature); + var geometry = feature.getGeometry(); + expect(geometry).to.be.an(ol.geom.LineString); + expect(geometry.getCoordinates()).to.eql(points3857); + }); + }); describe('#readFeatures', function() { @@ -268,6 +282,19 @@ describe('ol.format.Polyline', function() { expect(geometry.getFlatCoordinates()).to.eql(flatPoints); }); + it('transforms and returns the expected features', function() { + var features = format.readFeatures(encodedFlatPoints, { + featureProjection: 'EPSG:3857' + }); + expect(features).to.be.an(Array); + expect(features).to.have.length(1); + var feature = features[0]; + expect(feature).to.be.an(ol.Feature); + var geometry = feature.getGeometry(); + expect(geometry).to.be.an(ol.geom.LineString); + expect(geometry.getCoordinates()).to.eql(points3857); + }); + }); describe('#readGeometry', function() { @@ -278,6 +305,14 @@ describe('ol.format.Polyline', function() { expect(geometry.getFlatCoordinates()).to.eql(flatPoints); }); + it('transforms and returns the expected geometry', function() { + var geometry = format.readGeometry(encodedFlatPoints, { + featureProjection: 'EPSG:3857' + }); + expect(geometry).to.be.an(ol.geom.LineString); + expect(geometry.getCoordinates()).to.eql(points3857); + }); + }); describe('#readProjection', function() { @@ -296,6 +331,13 @@ describe('ol.format.Polyline', function() { expect(format.writeFeature(feature)).to.be(encodedFlatPoints); }); + it('transforms and returns the expected text', function() { + var feature = new ol.Feature(new ol.geom.LineString(points3857)); + expect(format.writeFeature(feature, { + featureProjection: 'EPSG:3857' + })).to.be(encodedFlatPoints); + }); + }); describe('#writeFeature', function() { @@ -305,6 +347,13 @@ describe('ol.format.Polyline', function() { expect(format.writeFeatures(features)).to.be(encodedFlatPoints); }); + it('transforms and returns the expected text', function() { + var features = [new ol.Feature(new ol.geom.LineString(points3857))]; + expect(format.writeFeatures(features, { + featureProjection: 'EPSG:3857' + })).to.be(encodedFlatPoints); + }); + }); describe('#writeGeometry', function() { @@ -314,6 +363,13 @@ describe('ol.format.Polyline', function() { expect(format.writeGeometry(geometry)).to.be(encodedFlatPoints); }); + it('transforms and returns the expected text', function() { + var geometry = new ol.geom.LineString(points3857); + expect(format.writeGeometry(geometry, { + featureProjection: 'EPSG:3857' + })).to.be(encodedFlatPoints); + }); + }); }); From 3ff180b22423d3dafdb6f4e34711dd183975711c Mon Sep 17 00:00:00 2001 From: tsauerwein Date: Mon, 11 Aug 2014 12:22:29 +0200 Subject: [PATCH 27/33] Implement read transforms for ol.format.WFS --- src/ol/format/wfsformat.js | 5 ++++- test/spec/ol/format/wfsformat.test.js | 29 +++++++++++++++++++++------ 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/ol/format/wfsformat.js b/src/ol/format/wfsformat.js index 2f64506664..ca7eea37d1 100644 --- a/src/ol/format/wfsformat.js +++ b/src/ol/format/wfsformat.js @@ -94,6 +94,7 @@ ol.format.WFS.schemaLocation_ = 'http://www.opengis.net/wfs ' + * * @function * @param {ArrayBuffer|Document|Node|Object|string} source Source. + * @param {olx.format.ReadOptions=} opt_options Read options. * @return {Array.} Features. * @api */ @@ -103,7 +104,7 @@ ol.format.WFS.prototype.readFeatures; /** * @inheritDoc */ -ol.format.WFS.prototype.readFeaturesFromNode = function(node) { +ol.format.WFS.prototype.readFeaturesFromNode = function(node, opt_options) { var objectStack = [{ 'featureType': this.featureType_, 'featureNS': this.featureNS_ @@ -113,6 +114,8 @@ ol.format.WFS.prototype.readFeaturesFromNode = function(node) { if (!goog.isDef(features)) { features = []; } + ol.format.XMLFeature.transformFeaturesWithOptions( + features, false, this.getReadOptions(node, opt_options)); return features; }; diff --git a/test/spec/ol/format/wfsformat.test.js b/test/spec/ol/format/wfsformat.test.js index 411842bf2f..a68e3b1e55 100644 --- a/test/spec/ol/format/wfsformat.test.js +++ b/test/spec/ol/format/wfsformat.test.js @@ -4,15 +4,17 @@ describe('ol.format.WFS', function() { describe('when parsing TOPP states GML from WFS', function() { - var features, feature; + var features, feature, xml; + var config = { + 'featureNS': 'http://www.openplans.org/topp', + 'featureType': 'states' + }; + before(function(done) { proj4.defs('urn:x-ogc:def:crs:EPSG:4326', proj4.defs('EPSG:4326')); - afterLoadText('spec/ol/format/wfs/topp-states-wfs.xml', function(xml) { + afterLoadText('spec/ol/format/wfs/topp-states-wfs.xml', function(data) { try { - var config = { - 'featureNS': 'http://www.openplans.org/topp', - 'featureType': 'states' - }; + xml = data; features = new ol.format.WFS(config).readFeatures(xml); } catch (e) { done(e); @@ -32,6 +34,20 @@ describe('ol.format.WFS', function() { expect(feature.getGeometry()).to.be.an(ol.geom.MultiPolygon); }); + it('transforms and creates a polygon for Illinois', function() { + features = new ol.format.WFS(config).readFeatures(xml, { + featureProjection: 'EPSG:3857' + }); + feature = features[0]; + expect(feature.getId()).to.equal('states.1'); + expect(feature.get('STATE_NAME')).to.equal('Illinois'); + var geom = feature.getGeometry(); + expect(geom).to.be.an(ol.geom.MultiPolygon); + var p = ol.proj.transform([-88.071, 37.511], 'EPSG:4326', 'EPSG:3857'); + p.push(0); + expect(geom.getFirstCoordinate()).to.eql(p); + }); + }); describe('when parsing FeatureCollection', function() { @@ -388,3 +404,4 @@ goog.require('ol.geom.MultiPoint'); goog.require('ol.geom.MultiPolygon'); goog.require('ol.geom.Polygon'); goog.require('ol.format.WFS'); +goog.require('ol.proj'); From 294afe16fe168f38c39c2a30970d0be57fa0fa4c Mon Sep 17 00:00:00 2001 From: tsauerwein Date: Mon, 11 Aug 2014 14:04:31 +0200 Subject: [PATCH 28/33] Fix compiler type errors --- externs/olx.js | 2 +- src/ol/format/featureformat.js | 17 +++++++++-------- src/ol/format/polylineformat.js | 9 +++++---- src/ol/format/xmlfeatureformat.js | 7 +++++-- 4 files changed, 20 insertions(+), 15 deletions(-) diff --git a/externs/olx.js b/externs/olx.js index 8b073ba63a..d8ba2cbfbd 100644 --- a/externs/olx.js +++ b/externs/olx.js @@ -1160,7 +1160,7 @@ olx.format.ReadOptions.prototype.dataProjection; /** - * Projection of the feature geometries created by the format reader. if not + * Projection of the feature geometries created by the format reader. If not * provided, features will be returned in the `dataProjection`. * @type {ol.proj.ProjectionLike|undefined} */ diff --git a/src/ol/format/featureformat.js b/src/ol/format/featureformat.js index ff674c19c7..0627c4b90c 100644 --- a/src/ol/format/featureformat.js +++ b/src/ol/format/featureformat.js @@ -149,21 +149,22 @@ ol.format.Feature.transformWithOptions = function( /** - * @param {(olx.format.WriteOptions|olx.format.ReadOptions)=} opt_options + * @param {olx.format.WriteOptions|olx.format.ReadOptions|undefined} options * Options. * @param {ol.proj.ProjectionLike} defaultDataProjection Default projection. * @protected - * @return {(olx.format.WriteOptions|olx.format.ReadOptions)=} Updated options. + * @return {olx.format.WriteOptions|olx.format.ReadOptions|undefined} + * Updated options. */ ol.format.Feature.setDefaultDataProjection = function( - opt_options, defaultDataProjection) { - if (goog.isDef(opt_options)) { - if (!goog.isDef(opt_options.dataProjection)) { - opt_options = { - featureProjection: opt_options.featureProjection, + options, defaultDataProjection) { + if (goog.isDef(options)) { + if (!goog.isDef(options.dataProjection)) { + options = { + featureProjection: options.featureProjection, dataProjection: defaultDataProjection }; } } - return opt_options; + return options; }; diff --git a/src/ol/format/polylineformat.js b/src/ol/format/polylineformat.js index 750f1aa078..85b357c094 100644 --- a/src/ol/format/polylineformat.js +++ b/src/ol/format/polylineformat.js @@ -311,7 +311,7 @@ ol.format.Polyline.prototype.readGeometryFromText = // for convenience set a default dataProjection opt_options = ol.format.Feature.setDefaultDataProjection( - opt_options, this.readProjectionFromText(null)); + opt_options, this.readProjectionFromText('')); return ol.format.Feature.transformWithOptions( new ol.geom.LineString(coordinates), false, false, opt_options); @@ -381,9 +381,10 @@ ol.format.Polyline.prototype.writeGeometryText = goog.asserts.assertInstanceof(geometry, ol.geom.LineString); // for convenience set a default dataProjection opt_options = ol.format.Feature.setDefaultDataProjection( - opt_options, this.readProjectionFromText(null)); - geometry = ol.format.Feature.transformWithOptions( - geometry, true, true, opt_options); + opt_options, this.readProjectionFromText('')); + geometry = /** @type {ol.geom.LineString} */ + (ol.format.Feature.transformWithOptions( + geometry, true, true, opt_options)); var flatCoordinates = geometry.getFlatCoordinates(); var stride = geometry.getStride(); return ol.format.Polyline.encodeDeltas(flatCoordinates, stride, this.factor_); diff --git a/src/ol/format/xmlfeatureformat.js b/src/ol/format/xmlfeatureformat.js index dc185b74df..d6c23aaeb0 100644 --- a/src/ol/format/xmlfeatureformat.js +++ b/src/ol/format/xmlfeatureformat.js @@ -271,8 +271,11 @@ ol.format.XMLFeature.transformFeaturesWithOptions = function( } goog.array.forEach(features, function(feature) { - feature.setGeometry(ol.format.Feature.transformWithOptions( - feature.getGeometry(), write, false, opt_options)); + var geom = feature.getGeometry(); + if (goog.isDef(geom)) { + feature.setGeometry(ol.format.Feature.transformWithOptions( + geom, write, false, opt_options)); + } }); } return features; From 1205d0fe1eb3883b1a74cc36a9db0b7f4b52bf17 Mon Sep 17 00:00:00 2001 From: tsauerwein Date: Wed, 13 Aug 2014 10:32:26 +0200 Subject: [PATCH 29/33] Fix ol.format.GML.readProjectionFromNode --- src/ol/format/gmlformat.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ol/format/gmlformat.js b/src/ol/format/gmlformat.js index ed840a66d8..c771cb7d6c 100644 --- a/src/ol/format/gmlformat.js +++ b/src/ol/format/gmlformat.js @@ -1076,8 +1076,8 @@ ol.format.GML.prototype.readFeaturesFromNode = function(node, opt_options) { * @inheritDoc */ ol.format.GML.prototype.readProjectionFromNode = function(node) { - return goog.isDef(this.srsName_) ? this.srsName_ : - node.firstElementChild.getAttribute('srsName'); + return ol.proj.get(goog.isDef(this.srsName_) ? this.srsName_ : + node.firstElementChild.getAttribute('srsName')); }; From 539e4a23b9fd2d689aa3a66061bf5cc7b782b5b8 Mon Sep 17 00:00:00 2001 From: tsauerwein Date: Mon, 18 Aug 2014 14:28:43 +0200 Subject: [PATCH 30/33] Introduce `defaultDataProjection` for formats --- examples/tile-vector.js | 8 +--- externs/olx.js | 26 +++++++----- src/ol/format/featureformat.js | 51 +++++++++++++---------- src/ol/format/geojsonformat.js | 10 ++--- src/ol/format/gpxformat.js | 13 +++--- src/ol/format/igcformat.js | 7 +++- src/ol/format/jsonfeatureformat.js | 12 ++++-- src/ol/format/kmlformat.js | 13 +++--- src/ol/format/osmxmlformat.js | 9 +++- src/ol/format/polylineformat.js | 20 ++++----- src/ol/format/textfeatureformat.js | 24 ++++++++--- src/ol/format/topojsonformat.js | 10 ++--- src/ol/format/xmlfeatureformat.js | 12 ++++-- src/ol/source/geojsonsource.js | 2 +- src/ol/source/topojsonsource.js | 2 +- test/spec/ol/format/geojsonformat.test.js | 15 ++++++- test/spec/ol/format/igcformat.test.js | 2 - 17 files changed, 145 insertions(+), 91 deletions(-) diff --git a/examples/tile-vector.js b/examples/tile-vector.js index eb73c81f75..e25042023a 100644 --- a/examples/tile-vector.js +++ b/examples/tile-vector.js @@ -11,9 +11,7 @@ goog.require('ol.tilegrid.XYZ'); var waterLayer = new ol.layer.Vector({ source: new ol.source.TileVector({ - format: new ol.format.TopoJSON({ - defaultProjection: 'EPSG:4326' - }), + format: new ol.format.TopoJSON(), projection: 'EPSG:3857', tileGrid: new ol.tilegrid.XYZ({ maxZoom: 19 @@ -31,9 +29,7 @@ var waterLayer = new ol.layer.Vector({ var roadStyleCache = {}; var roadLayer = new ol.layer.Vector({ source: new ol.source.TileVector({ - format: new ol.format.TopoJSON({ - defaultProjection: 'EPSG:4326' - }), + format: new ol.format.TopoJSON(), projection: 'EPSG:3857', tileGrid: new ol.tilegrid.XYZ({ maxZoom: 19 diff --git a/externs/olx.js b/externs/olx.js index d8ba2cbfbd..6e2d5add74 100644 --- a/externs/olx.js +++ b/externs/olx.js @@ -1153,7 +1153,10 @@ olx.format.ReadOptions; /** * Projection of the data we are reading. If not provided, the projection will - * be derived from the data (where possible). + * be derived from the data (where possible) or the `defaultDataProjection` of + * the format is assigned (where set). If the projection can not be derived from + * the data and if no `defaultDataProjection` is set for a format, the features + * will not be reprojected. * @type {ol.proj.ProjectionLike|undefined} */ olx.format.ReadOptions.prototype.dataProjection; @@ -1175,22 +1178,25 @@ olx.format.WriteOptions; /** - * Projection of the data we are writing. If not provided, features will be - * written in the `featureProjection`. + * Projection of the data we are writing. If not provided, the + * `defaultDataProjection` of the format is assigned (where set). If no + * `defaultDataProjection` is set for a format, the features will be returned + * in the `featureProjection`. * @type {ol.proj.ProjectionLike|undefined} */ olx.format.WriteOptions.prototype.dataProjection; /** - * Projection of the feature geometries serialized by the format writer. + * Projection of the feature geometries that will be serialized by the format + * writer. * @type {ol.proj.ProjectionLike} */ olx.format.WriteOptions.prototype.featureProjection; /** - * @typedef {{defaultProjection: ol.proj.ProjectionLike, + * @typedef {{defaultDataProjection: ol.proj.ProjectionLike, * geometryName: (string|undefined)}} * @api */ @@ -1198,10 +1204,10 @@ olx.format.GeoJSONOptions; /** - * Default projection. + * Default data projection. * @type {ol.proj.ProjectionLike} */ -olx.format.GeoJSONOptions.prototype.defaultProjection; +olx.format.GeoJSONOptions.prototype.defaultDataProjection; /** @@ -1226,17 +1232,17 @@ olx.format.PolylineOptions.prototype.factor; /** - * @typedef {{defaultProjection: ol.proj.ProjectionLike}} + * @typedef {{defaultDataProjection: ol.proj.ProjectionLike}} * @api */ olx.format.TopoJSONOptions; /** - * Default projection. + * Default data projection. * @type {ol.proj.ProjectionLike} */ -olx.format.TopoJSONOptions.prototype.defaultProjection; +olx.format.TopoJSONOptions.prototype.defaultDataProjection; /** diff --git a/src/ol/format/featureformat.js b/src/ol/format/featureformat.js index 0627c4b90c..229f7bb83d 100644 --- a/src/ol/format/featureformat.js +++ b/src/ol/format/featureformat.js @@ -17,6 +17,12 @@ goog.require('ol.proj'); * @constructor */ ol.format.Feature = function() { + + /** + * @protected + * @type {ol.proj.Projection} + */ + this.defaultDataProjection = null; }; @@ -43,7 +49,28 @@ ol.format.Feature.prototype.getReadOptions = function( featureProjection: opt_options.featureProjection }; } - return options; + return this.adaptOptionsWithDefaultDataProjection(options); +}; + + +/** + * @param {olx.format.WriteOptions|olx.format.ReadOptions|undefined} options + * Options. + * @protected + * @return {olx.format.WriteOptions|olx.format.ReadOptions|undefined} + * Updated options. + */ +ol.format.Feature.prototype.adaptOptionsWithDefaultDataProjection = function( + options) { + var updatedOptions; + if (goog.isDef(options)) { + updatedOptions = { + featureProjection: options.featureProjection, + dataProjection: goog.isDefAndNotNull(options.dataProjection) ? + options.dataProjection : this.defaultDataProjection + }; + } + return updatedOptions; }; @@ -146,25 +173,3 @@ ol.format.Feature.transformWithOptions = function( return geometry; } }; - - -/** - * @param {olx.format.WriteOptions|olx.format.ReadOptions|undefined} options - * Options. - * @param {ol.proj.ProjectionLike} defaultDataProjection Default projection. - * @protected - * @return {olx.format.WriteOptions|olx.format.ReadOptions|undefined} - * Updated options. - */ -ol.format.Feature.setDefaultDataProjection = function( - options, defaultDataProjection) { - if (goog.isDef(options)) { - if (!goog.isDef(options.dataProjection)) { - options = { - featureProjection: options.featureProjection, - dataProjection: defaultDataProjection - }; - } - } - return options; -}; diff --git a/src/ol/format/geojsonformat.js b/src/ol/format/geojsonformat.js index f6cfc07a70..3c34782ee9 100644 --- a/src/ol/format/geojsonformat.js +++ b/src/ol/format/geojsonformat.js @@ -37,11 +37,11 @@ ol.format.GeoJSON = function(opt_options) { goog.base(this); /** - * @private - * @type {ol.proj.Projection} + * @inheritDoc */ - this.defaultProjection_ = ol.proj.get(options.defaultProjection ? - options.defaultProjection : 'EPSG:4326'); + this.defaultDataProjection = ol.proj.get( + goog.isDefAndNotNull(options.defaultDataProjection) ? + options.defaultDataProjection : 'EPSG:4326'); /** @@ -472,7 +472,7 @@ ol.format.GeoJSON.prototype.readProjectionFromObject = function(object) { return null; } } else { - return this.defaultProjection_; + return this.defaultDataProjection; } }; diff --git a/src/ol/format/gpxformat.js b/src/ol/format/gpxformat.js index bcec5da2fb..707c11778f 100644 --- a/src/ol/format/gpxformat.js +++ b/src/ol/format/gpxformat.js @@ -5,7 +5,6 @@ goog.require('goog.asserts'); goog.require('goog.dom.NodeType'); goog.require('goog.object'); goog.require('ol.Feature'); -goog.require('ol.format.Feature'); goog.require('ol.format.XMLFeature'); goog.require('ol.format.XSD'); goog.require('ol.geom.LineString'); @@ -31,6 +30,11 @@ ol.format.GPX = function(opt_options) { goog.base(this); + /** + * @inheritDoc + */ + this.defaultDataProjection = ol.proj.get('EPSG:4326'); + /** * @type {function(ol.Feature, Node)|undefined} * @private @@ -498,7 +502,7 @@ ol.format.GPX.prototype.readProjection; * @inheritDoc */ ol.format.GPX.prototype.readProjectionFromDocument = function(doc) { - return ol.proj.get('EPSG:4326'); + return this.defaultDataProjection; }; @@ -506,7 +510,7 @@ ol.format.GPX.prototype.readProjectionFromDocument = function(doc) { * @inheritDoc */ ol.format.GPX.prototype.readProjectionFromNode = function(node) { - return ol.proj.get('EPSG:4326'); + return this.defaultDataProjection; }; @@ -866,9 +870,6 @@ ol.format.GPX.prototype.writeFeaturesNode = function(features, opt_options) { //FIXME Serialize metadata var gpx = ol.xml.createElementNS('http://www.topografix.com/GPX/1/1', 'gpx'); - // for convenience set a default dataProjection - opt_options = ol.format.Feature.setDefaultDataProjection( - opt_options, this.readProjectionFromDocument(null)); features = ol.format.XMLFeature.transformFeaturesWithOptions( features, true, opt_options); diff --git a/src/ol/format/igcformat.js b/src/ol/format/igcformat.js index 664cd35a10..d1347e9e39 100644 --- a/src/ol/format/igcformat.js +++ b/src/ol/format/igcformat.js @@ -37,6 +37,11 @@ ol.format.IGC = function(opt_options) { goog.base(this); + /** + * @inheritDoc + */ + this.defaultDataProjection = ol.proj.get('EPSG:4326'); + /** * @private * @type {ol.format.IGCZ} @@ -217,5 +222,5 @@ ol.format.IGC.prototype.readProjection; * @inheritDoc */ ol.format.IGC.prototype.readProjectionFromText = function(text) { - return ol.proj.get('EPSG:4326'); + return this.defaultDataProjection; }; diff --git a/src/ol/format/jsonfeatureformat.js b/src/ol/format/jsonfeatureformat.js index 3fe530b574..109613a1ce 100644 --- a/src/ol/format/jsonfeatureformat.js +++ b/src/ol/format/jsonfeatureformat.js @@ -128,7 +128,9 @@ ol.format.JSONFeature.prototype.readProjectionFromObject = goog.abstractMethod; * @inheritDoc */ ol.format.JSONFeature.prototype.writeFeature = function(feature, opt_options) { - return this.writeFeatureObject(feature, opt_options); + return this.writeFeatureObject( + feature, + this.adaptOptionsWithDefaultDataProjection(opt_options)); }; @@ -146,7 +148,9 @@ ol.format.JSONFeature.prototype.writeFeatureObject = goog.abstractMethod; */ ol.format.JSONFeature.prototype.writeFeatures = function( features, opt_options) { - return this.writeFeaturesObject(features, opt_options); + return this.writeFeaturesObject( + features, + this.adaptOptionsWithDefaultDataProjection(opt_options)); }; @@ -164,7 +168,9 @@ ol.format.JSONFeature.prototype.writeFeaturesObject = goog.abstractMethod; */ ol.format.JSONFeature.prototype.writeGeometry = function( geometry, opt_options) { - return this.writeGeometryObject(geometry, opt_options); + return this.writeGeometryObject( + geometry, + this.adaptOptionsWithDefaultDataProjection(opt_options)); }; diff --git a/src/ol/format/kmlformat.js b/src/ol/format/kmlformat.js index 8dc1aaf0c8..fa4d28948a 100644 --- a/src/ol/format/kmlformat.js +++ b/src/ol/format/kmlformat.js @@ -16,7 +16,6 @@ goog.require('ol.Feature'); goog.require('ol.array'); goog.require('ol.color'); goog.require('ol.feature'); -goog.require('ol.format.Feature'); goog.require('ol.format.XMLFeature'); goog.require('ol.format.XSD'); goog.require('ol.geom.Geometry'); @@ -71,6 +70,11 @@ ol.format.KML = function(opt_options) { goog.base(this); + /** + * @inheritDoc + */ + this.defaultDataProjection = ol.proj.get('EPSG:4326'); + var defaultStyle = goog.isDef(options.defaultStyle) ? options.defaultStyle : ol.format.KML.DEFAULT_STYLE_ARRAY_; @@ -1654,7 +1658,7 @@ ol.format.KML.prototype.readProjection; * @inheritDoc */ ol.format.KML.prototype.readProjectionFromDocument = function(doc) { - return ol.proj.get('EPSG:4326'); + return this.defaultDataProjection; }; @@ -1662,7 +1666,7 @@ ol.format.KML.prototype.readProjectionFromDocument = function(doc) { * @inheritDoc */ ol.format.KML.prototype.readProjectionFromNode = function(node) { - return ol.proj.get('EPSG:4326'); + return this.defaultDataProjection; }; @@ -2523,9 +2527,6 @@ ol.format.KML.prototype.writeFeaturesNode = function(features, opt_options) { ol.xml.setAttributeNS(kml, xmlSchemaInstanceUri, 'xsi:schemaLocation', ol.format.KML.SCHEMA_LOCATION_); - // for convenience set a default dataProjection - opt_options = ol.format.Feature.setDefaultDataProjection( - opt_options, this.readProjectionFromDocument(null)); features = ol.format.XMLFeature.transformFeaturesWithOptions( features, true, opt_options); diff --git a/src/ol/format/osmxmlformat.js b/src/ol/format/osmxmlformat.js index 7627b428df..7831e7f32f 100644 --- a/src/ol/format/osmxmlformat.js +++ b/src/ol/format/osmxmlformat.js @@ -26,6 +26,11 @@ goog.require('ol.xml'); */ ol.format.OSMXML = function() { goog.base(this); + + /** + * @inheritDoc + */ + this.defaultDataProjection = ol.proj.get('EPSG:4326'); }; goog.inherits(ol.format.OSMXML, ol.format.XMLFeature); @@ -231,7 +236,7 @@ ol.format.OSMXML.prototype.readProjection; * @inheritDoc */ ol.format.OSMXML.prototype.readProjectionFromDocument = function(doc) { - return ol.proj.get('EPSG:4326'); + return this.defaultDataProjection; }; @@ -239,5 +244,5 @@ ol.format.OSMXML.prototype.readProjectionFromDocument = function(doc) { * @inheritDoc */ ol.format.OSMXML.prototype.readProjectionFromNode = function(node) { - return ol.proj.get('EPSG:4326'); + return this.defaultDataProjection; }; diff --git a/src/ol/format/polylineformat.js b/src/ol/format/polylineformat.js index 85b357c094..0cb41b57bb 100644 --- a/src/ol/format/polylineformat.js +++ b/src/ol/format/polylineformat.js @@ -23,6 +23,11 @@ ol.format.Polyline = function(opt_options) { goog.base(this); + /** + * @inheritDoc + */ + this.defaultDataProjection = ol.proj.get('EPSG:4326'); + /** * @private * @type {number} @@ -309,12 +314,9 @@ ol.format.Polyline.prototype.readGeometryFromText = var coordinates = ol.geom.flat.inflate.coordinates( flatCoordinates, 0, flatCoordinates.length, 2); - // for convenience set a default dataProjection - opt_options = ol.format.Feature.setDefaultDataProjection( - opt_options, this.readProjectionFromText('')); - return ol.format.Feature.transformWithOptions( - new ol.geom.LineString(coordinates), false, false, opt_options); + new ol.geom.LineString(coordinates), false, false, + this.adaptOptionsWithDefaultDataProjection(opt_options)); }; @@ -333,7 +335,7 @@ ol.format.Polyline.prototype.readProjection; * @inheritDoc */ ol.format.Polyline.prototype.readProjectionFromText = function(text) { - return ol.proj.get('EPSG:4326'); + return this.defaultDataProjection; }; @@ -379,12 +381,10 @@ ol.format.Polyline.prototype.writeGeometry; ol.format.Polyline.prototype.writeGeometryText = function(geometry, opt_options) { goog.asserts.assertInstanceof(geometry, ol.geom.LineString); - // for convenience set a default dataProjection - opt_options = ol.format.Feature.setDefaultDataProjection( - opt_options, this.readProjectionFromText('')); geometry = /** @type {ol.geom.LineString} */ (ol.format.Feature.transformWithOptions( - geometry, true, true, opt_options)); + geometry, true, true, + this.adaptOptionsWithDefaultDataProjection(opt_options))); var flatCoordinates = geometry.getFlatCoordinates(); var stride = geometry.getStride(); return ol.format.Polyline.encodeDeltas(flatCoordinates, stride, this.factor_); diff --git a/src/ol/format/textfeatureformat.js b/src/ol/format/textfeatureformat.js index 0b30b5dc4a..583d0a3062 100644 --- a/src/ol/format/textfeatureformat.js +++ b/src/ol/format/textfeatureformat.js @@ -48,7 +48,9 @@ ol.format.TextFeature.prototype.getType = function() { * @inheritDoc */ ol.format.TextFeature.prototype.readFeature = function(source, opt_options) { - return this.readFeatureFromText(this.getText_(source), opt_options); + return this.readFeatureFromText( + this.getText_(source), + this.adaptOptionsWithDefaultDataProjection(opt_options)); }; @@ -65,7 +67,9 @@ ol.format.TextFeature.prototype.readFeatureFromText = goog.abstractMethod; * @inheritDoc */ ol.format.TextFeature.prototype.readFeatures = function(source, opt_options) { - return this.readFeaturesFromText(this.getText_(source), opt_options); + return this.readFeaturesFromText( + this.getText_(source), + this.adaptOptionsWithDefaultDataProjection(opt_options)); }; @@ -82,7 +86,9 @@ ol.format.TextFeature.prototype.readFeaturesFromText = goog.abstractMethod; * @inheritDoc */ ol.format.TextFeature.prototype.readGeometry = function(source, opt_options) { - return this.readGeometryFromText(this.getText_(source), opt_options); + return this.readGeometryFromText( + this.getText_(source), + this.adaptOptionsWithDefaultDataProjection(opt_options)); }; @@ -115,7 +121,9 @@ ol.format.TextFeature.prototype.readProjectionFromText = goog.abstractMethod; * @inheritDoc */ ol.format.TextFeature.prototype.writeFeature = function(feature, opt_options) { - return this.writeFeatureText(feature, opt_options); + return this.writeFeatureText( + feature, + this.adaptOptionsWithDefaultDataProjection(opt_options)); }; @@ -133,7 +141,9 @@ ol.format.TextFeature.prototype.writeFeatureText = goog.abstractMethod; */ ol.format.TextFeature.prototype.writeFeatures = function( features, opt_options) { - return this.writeFeaturesText(features, opt_options); + return this.writeFeaturesText( + features, + this.adaptOptionsWithDefaultDataProjection(opt_options)); }; @@ -151,7 +161,9 @@ ol.format.TextFeature.prototype.writeFeaturesText = goog.abstractMethod; */ ol.format.TextFeature.prototype.writeGeometry = function( geometry, opt_options) { - return this.writeGeometryText(geometry, opt_options); + return this.writeGeometryText( + geometry, + this.adaptOptionsWithDefaultDataProjection(opt_options)); }; diff --git a/src/ol/format/topojsonformat.js b/src/ol/format/topojsonformat.js index 5e272850d1..ab7bd47794 100644 --- a/src/ol/format/topojsonformat.js +++ b/src/ol/format/topojsonformat.js @@ -31,11 +31,11 @@ ol.format.TopoJSON = function(opt_options) { goog.base(this); /** - * @private - * @type {ol.proj.Projection} + * @inheritDoc */ - this.defaultProjection_ = - ol.proj.get(options.defaultProjection || 'EPSG:4326'); + this.defaultDataProjection = ol.proj.get( + goog.isDefAndNotNull(options.defaultDataProjection) ? + options.defaultDataProjection : 'EPSG:4326'); }; goog.inherits(ol.format.TopoJSON, ol.format.JSONFeature); @@ -391,7 +391,7 @@ ol.format.TopoJSON.transformVertex_ = function(vertex, scale, translate) { * @api */ ol.format.TopoJSON.prototype.readProjection = function(object) { - return this.defaultProjection_; + return this.defaultDataProjection; }; diff --git a/src/ol/format/xmlfeatureformat.js b/src/ol/format/xmlfeatureformat.js index d6c23aaeb0..90ecddc10f 100644 --- a/src/ol/format/xmlfeatureformat.js +++ b/src/ol/format/xmlfeatureformat.js @@ -199,7 +199,9 @@ ol.format.XMLFeature.prototype.readProjectionFromNode = goog.abstractMethod; * @inheritDoc */ ol.format.XMLFeature.prototype.writeFeature = function(feature, opt_options) { - return this.writeFeatureNode(feature, opt_options); + return this.writeFeatureNode( + feature, + this.adaptOptionsWithDefaultDataProjection(opt_options)); }; @@ -216,7 +218,9 @@ ol.format.XMLFeature.prototype.writeFeatureNode = goog.abstractMethod; * @inheritDoc */ ol.format.XMLFeature.prototype.writeFeatures = function(features, opt_options) { - return this.writeFeaturesNode(features, opt_options); + return this.writeFeaturesNode( + features, + this.adaptOptionsWithDefaultDataProjection(opt_options)); }; @@ -233,7 +237,9 @@ ol.format.XMLFeature.prototype.writeFeaturesNode = goog.abstractMethod; * @inheritDoc */ ol.format.XMLFeature.prototype.writeGeometry = function(geometry, opt_options) { - return this.writeGeometryNode(geometry, opt_options); + return this.writeGeometryNode( + geometry, + this.adaptOptionsWithDefaultDataProjection(opt_options)); }; diff --git a/src/ol/source/geojsonsource.js b/src/ol/source/geojsonsource.js index ab4ab5803a..b1f11c89c7 100644 --- a/src/ol/source/geojsonsource.js +++ b/src/ol/source/geojsonsource.js @@ -23,7 +23,7 @@ ol.source.GeoJSON = function(opt_options) { attributions: options.attributions, extent: options.extent, format: new ol.format.GeoJSON({ - defaultProjection: options.defaultProjection + defaultDataProjection: options.defaultProjection }), logo: options.logo, object: options.object, diff --git a/src/ol/source/topojsonsource.js b/src/ol/source/topojsonsource.js index 2befa91465..8eec88abd1 100644 --- a/src/ol/source/topojsonsource.js +++ b/src/ol/source/topojsonsource.js @@ -23,7 +23,7 @@ ol.source.TopoJSON = function(opt_options) { attributions: options.attributions, extent: options.extent, format: new ol.format.TopoJSON({ - defaultProjection: options.defaultProjection + defaultDataProjection: options.defaultProjection }), logo: options.logo, object: options.object, diff --git a/test/spec/ol/format/geojsonformat.test.js b/test/spec/ol/format/geojsonformat.test.js index 2c6b220ff5..a3da003c8f 100644 --- a/test/spec/ol/format/geojsonformat.test.js +++ b/test/spec/ol/format/geojsonformat.test.js @@ -486,7 +486,6 @@ describe('ol.format.GeoJSON', function() { var str = JSON.stringify(data), array = format.readFeatures(str); var geojson = format.writeFeatures(array, { - dataProjection: 'EPSG:4326', featureProjection: 'EPSG:3857' }); var result = format.readFeatures(geojson); @@ -554,6 +553,20 @@ describe('ol.format.GeoJSON', function() { }); }); + it('transforms and encodes a point', function() { + var point = new ol.geom.Point([2, 3]); + var geojson = format.writeGeometry(point, { + featureProjection: 'EPSG:3857' + }); + var newPoint = format.readGeometry(geojson, { + featureProjection: 'EPSG:3857' + }); + expect(point.getCoordinates()[0]).to.eql(newPoint.getCoordinates()[0]); + expect( + Math.abs(point.getCoordinates()[1] - newPoint.getCoordinates()[1])) + .to.be.lessThan(0.0000001); + }); + }); }); diff --git a/test/spec/ol/format/igcformat.test.js b/test/spec/ol/format/igcformat.test.js index 24921941b0..c3b9c88440 100644 --- a/test/spec/ol/format/igcformat.test.js +++ b/test/spec/ol/format/igcformat.test.js @@ -47,7 +47,6 @@ describe('ol.format.IGC', function() { it('does transform and read a feature', function() { var feature = format.readFeature(igc, { - dataProjection: 'EPSG:4326', featureProjection: 'EPSG:3857' }); expect(feature).to.be.an(ol.Feature); @@ -91,7 +90,6 @@ describe('ol.format.IGC', function() { it('does transform and read features', function() { var features = format.readFeatures(igc, { - dataProjection: 'EPSG:4326', featureProjection: 'EPSG:3857' }); expect(features.length).to.eql(1); From e7864be2be99ebf11ec93ea200d84cd057419678 Mon Sep 17 00:00:00 2001 From: tsauerwein Date: Mon, 18 Aug 2014 15:48:29 +0200 Subject: [PATCH 31/33] Fix ol.format.transformWithOptions --- src/ol/format/featureformat.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ol/format/featureformat.js b/src/ol/format/featureformat.js index 229f7bb83d..0243780755 100644 --- a/src/ol/format/featureformat.js +++ b/src/ol/format/featureformat.js @@ -166,7 +166,7 @@ ol.format.Feature.transformWithOptions = function( ol.proj.get(opt_options.dataProjection) : null; if (!goog.isNull(featureProjection) && !goog.isNull(dataProjection) && !ol.proj.equivalent(featureProjection, dataProjection)) { - return (write ? geometry.clone() : geometry).transform( + return (clone ? geometry.clone() : geometry).transform( write ? featureProjection : dataProjection, write ? dataProjection : featureProjection); } else { From b30ed6b9343ad2a4e80ca7a873ffa8a7dcaa0022 Mon Sep 17 00:00:00 2001 From: tsauerwein Date: Tue, 19 Aug 2014 09:42:44 +0200 Subject: [PATCH 32/33] Put options on objectStack for xml formats --- src/ol/format/featureformat.js | 25 ++++++++++++++------- src/ol/format/geojsonformat.js | 10 ++++----- src/ol/format/gmlformat.js | 9 +++++--- src/ol/format/gpxformat.js | 29 ++++++++++++++++--------- src/ol/format/igcformat.js | 2 +- src/ol/format/kmlformat.js | 34 ++++++++++++++++------------- src/ol/format/osmxmlformat.js | 10 ++++++--- src/ol/format/polylineformat.js | 9 ++++---- src/ol/format/topojsonformat.js | 4 ++-- src/ol/format/wfsformat.js | 9 ++++---- src/ol/format/wktformat.js | 8 +++---- src/ol/format/xmlfeatureformat.js | 36 ------------------------------- 12 files changed, 90 insertions(+), 95 deletions(-) diff --git a/src/ol/format/featureformat.js b/src/ol/format/featureformat.js index 0243780755..364ba16a86 100644 --- a/src/ol/format/featureformat.js +++ b/src/ol/format/featureformat.js @@ -1,6 +1,7 @@ goog.provide('ol.format.Feature'); -goog.require('goog.functions'); +goog.require('goog.array'); +goog.require('ol.geom.Geometry'); goog.require('ol.proj'); @@ -150,25 +151,33 @@ ol.format.Feature.prototype.writeGeometry = goog.abstractMethod; /** - * @param {ol.geom.Geometry} geometry Geometry. + * @param {ol.geom.Geometry|ol.Extent} geometry Geometry. * @param {boolean} write Set to true for writing, false for reading. - * @param {boolean} clone The geometry will be cloned before transforming. * @param {(olx.format.WriteOptions|olx.format.ReadOptions)=} opt_options * Options. - * @return {ol.geom.Geometry} Transformed geometry. + * @return {ol.geom.Geometry|ol.Extent} Transformed geometry. * @protected */ ol.format.Feature.transformWithOptions = function( - geometry, write, clone, opt_options) { + geometry, write, opt_options) { var featureProjection = goog.isDef(opt_options) ? ol.proj.get(opt_options.featureProjection) : null; var dataProjection = goog.isDef(opt_options) ? ol.proj.get(opt_options.dataProjection) : null; if (!goog.isNull(featureProjection) && !goog.isNull(dataProjection) && !ol.proj.equivalent(featureProjection, dataProjection)) { - return (clone ? geometry.clone() : geometry).transform( - write ? featureProjection : dataProjection, - write ? dataProjection : featureProjection); + if (geometry instanceof ol.geom.Geometry) { + return (write ? geometry.clone() : geometry).transform( + write ? featureProjection : dataProjection, + write ? dataProjection : featureProjection); + } else { + // FIXME this is necessary because ol.format.GML treats extents + // as geometries + return ol.proj.transformExtent( + write ? goog.array.clone(geometry) : geometry, + write ? featureProjection : dataProjection, + write ? dataProjection : featureProjection); + } } else { return geometry; } diff --git a/src/ol/format/geojsonformat.js b/src/ol/format/geojsonformat.js index 3c34782ee9..17c4f4a9c6 100644 --- a/src/ol/format/geojsonformat.js +++ b/src/ol/format/geojsonformat.js @@ -75,8 +75,9 @@ ol.format.GeoJSON.readGeometry_ = function(object, opt_options) { } var geometryReader = ol.format.GeoJSON.GEOMETRY_READERS_[object.type]; goog.asserts.assert(goog.isDef(geometryReader)); - return ol.format.Feature.transformWithOptions( - geometryReader(object), false, false, opt_options); + return /** @type {ol.geom.Geometry} */ ( + ol.format.Feature.transformWithOptions( + geometryReader(object), false, opt_options)); }; @@ -176,9 +177,8 @@ ol.format.GeoJSON.readPolygonGeometry_ = function(object) { ol.format.GeoJSON.writeGeometry_ = function(geometry, opt_options) { var geometryWriter = ol.format.GeoJSON.GEOMETRY_WRITERS_[geometry.getType()]; goog.asserts.assert(goog.isDef(geometryWriter)); - return geometryWriter( - ol.format.Feature.transformWithOptions( - geometry, true, true, opt_options)); + return geometryWriter(/** @type {ol.geom.Geometry} */ ( + ol.format.Feature.transformWithOptions(geometry, true, opt_options))); }; diff --git a/src/ol/format/gmlformat.js b/src/ol/format/gmlformat.js index c771cb7d6c..3e2cdada0b 100644 --- a/src/ol/format/gmlformat.js +++ b/src/ol/format/gmlformat.js @@ -1,3 +1,6 @@ +// FIXME Envelopes should not be treated as geometries! readEnvelope_ is part +// of GEOMETRY_PARSERS_ and methods using GEOMETRY_PARSERS_ do not expect +// envelopes/extents, only geometries! goog.provide('ol.format.GML'); goog.require('goog.asserts'); @@ -162,8 +165,8 @@ ol.format.GML.readGeometry = function(node, objectStack) { var geometry = ol.xml.pushParseAndPop(/** @type {ol.geom.Geometry} */(null), ol.format.GML.GEOMETRY_PARSERS_, node, objectStack); if (goog.isDefAndNotNull(geometry)) { - return ol.format.Feature.transformWithOptions( - geometry, false, false, context); + return /** @type {ol.geom.Geometry} */ ( + ol.format.Feature.transformWithOptions(geometry, false, context)); } else { return undefined; } @@ -1469,7 +1472,7 @@ ol.format.GML.writeGeometry = function(node, geometry, objectStack) { } else { goog.asserts.assertInstanceof(geometry, ol.geom.Geometry); value = - ol.format.Feature.transformWithOptions(geometry, true, true, context); + ol.format.Feature.transformWithOptions(geometry, true, context); } ol.xml.pushSerializeAndPop(/** @type {ol.xml.NodeStackItem} */ (item), ol.format.GML.GEOMETRY_SERIALIZERS_, diff --git a/src/ol/format/gpxformat.js b/src/ol/format/gpxformat.js index 707c11778f..3fcae43c0a 100644 --- a/src/ol/format/gpxformat.js +++ b/src/ol/format/gpxformat.js @@ -5,6 +5,7 @@ goog.require('goog.asserts'); goog.require('goog.dom.NodeType'); goog.require('goog.object'); goog.require('ol.Feature'); +goog.require('ol.format.Feature'); goog.require('ol.format.XMLFeature'); goog.require('ol.format.XSD'); goog.require('ol.geom.LineString'); @@ -180,6 +181,7 @@ ol.format.GPX.parseTrkSeg_ = function(node, objectStack) { ol.format.GPX.readRte_ = function(node, objectStack) { goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT); goog.asserts.assert(node.localName == 'rte'); + var options = /** @type {olx.format.ReadOptions} */ (objectStack[0]); var values = ol.xml.pushParseAndPop({ 'flatCoordinates': [] }, ol.format.GPX.RTE_PARSERS_, node, objectStack); @@ -191,6 +193,7 @@ ol.format.GPX.readRte_ = function(node, objectStack) { goog.object.remove(values, 'flatCoordinates'); var geometry = new ol.geom.LineString(null); geometry.setFlatCoordinates(ol.geom.GeometryLayout.XYZM, flatCoordinates); + ol.format.Feature.transformWithOptions(geometry, false, options); var feature = new ol.Feature(geometry); feature.setProperties(values); return feature; @@ -206,6 +209,7 @@ ol.format.GPX.readRte_ = function(node, objectStack) { ol.format.GPX.readTrk_ = function(node, objectStack) { goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT); goog.asserts.assert(node.localName == 'trk'); + var options = /** @type {olx.format.ReadOptions} */ (objectStack[0]); var values = ol.xml.pushParseAndPop({ 'flatCoordinates': [], 'ends': [] @@ -221,6 +225,7 @@ ol.format.GPX.readTrk_ = function(node, objectStack) { var geometry = new ol.geom.MultiLineString(null); geometry.setFlatCoordinates( ol.geom.GeometryLayout.XYZM, flatCoordinates, ends); + ol.format.Feature.transformWithOptions(geometry, false, options); var feature = new ol.Feature(geometry); feature.setProperties(values); return feature; @@ -236,6 +241,7 @@ ol.format.GPX.readTrk_ = function(node, objectStack) { ol.format.GPX.readWpt_ = function(node, objectStack) { goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT); goog.asserts.assert(node.localName == 'wpt'); + var options = /** @type {olx.format.ReadOptions} */ (objectStack[0]); var values = ol.xml.pushParseAndPop( {}, ol.format.GPX.WPT_PARSERS_, node, objectStack); if (!goog.isDef(values)) { @@ -244,6 +250,7 @@ ol.format.GPX.readWpt_ = function(node, objectStack) { var coordinates = ol.format.GPX.appendCoordinate_([], node, values); var geometry = new ol.geom.Point( coordinates, ol.geom.GeometryLayout.XYZM); + ol.format.Feature.transformWithOptions(geometry, false, options); var feature = new ol.Feature(geometry); feature.setProperties(values); return feature; @@ -439,13 +446,11 @@ ol.format.GPX.prototype.readFeatureFromNode = function(node, opt_options) { if (!goog.isDef(featureReader)) { return null; } - var feature = featureReader(node, []); + var feature = featureReader(node, [this.getReadOptions(node, opt_options)]); if (!goog.isDef(feature)) { return null; } this.handleReadExtensions_([feature]); - ol.format.XMLFeature.transformFeaturesWithOptions( - [feature], false, this.getReadOptions(node, opt_options)); return feature; }; @@ -473,11 +478,9 @@ ol.format.GPX.prototype.readFeaturesFromNode = function(node, opt_options) { if (node.localName == 'gpx') { var features = ol.xml.pushParseAndPop( /** @type {Array.} */ ([]), ol.format.GPX.GPX_PARSERS_, - node, []); + node, [this.getReadOptions(node, opt_options)]); if (goog.isDef(features)) { this.handleReadExtensions_(features); - ol.format.XMLFeature.transformFeaturesWithOptions( - features, false, this.getReadOptions(node, opt_options)); return features; } else { return []; @@ -585,11 +588,14 @@ ol.format.GPX.writeWptType_ = function(node, coordinate, objectStack) { * @private */ ol.format.GPX.writeRte_ = function(node, feature, objectStack) { + var options = /** @type {olx.format.WriteOptions} */ (objectStack[0]); var properties = feature.getProperties(); var context = {node: node, 'properties': properties}; var geometry = feature.getGeometry(); if (goog.isDef(geometry)) { goog.asserts.assertInstanceof(geometry, ol.geom.LineString); + geometry = /** @type {ol.geom.LineString} */ + (ol.format.Feature.transformWithOptions(geometry, true, options)); goog.object.set(context, 'geometryLayout', geometry.getLayout()); goog.object.set(properties, 'rtept', geometry.getCoordinates()); } @@ -609,11 +615,14 @@ ol.format.GPX.writeRte_ = function(node, feature, objectStack) { * @private */ ol.format.GPX.writeTrk_ = function(node, feature, objectStack) { + var options = /** @type {olx.format.WriteOptions} */ (objectStack[0]); var properties = feature.getProperties(); var context = {node: node, 'properties': properties}; var geometry = feature.getGeometry(); if (goog.isDef(geometry)) { goog.asserts.assertInstanceof(geometry, ol.geom.MultiLineString); + geometry = /** @type {ol.geom.MultiLineString} */ + (ol.format.Feature.transformWithOptions(geometry, true, options)); goog.object.set(properties, 'trkseg', geometry.getLineStrings()); } var parentNode = objectStack[objectStack.length - 1].node; @@ -647,12 +656,15 @@ ol.format.GPX.writeTrkSeg_ = function(node, lineString, objectStack) { * @private */ ol.format.GPX.writeWpt_ = function(node, feature, objectStack) { + var options = /** @type {olx.format.WriteOptions} */ (objectStack[0]); var context = objectStack[objectStack.length - 1]; goog.asserts.assert(goog.isObject(context)); goog.object.set(context, 'properties', feature.getProperties()); var geometry = feature.getGeometry(); if (goog.isDef(geometry)) { goog.asserts.assertInstanceof(geometry, ol.geom.Point); + geometry = /** @type {ol.geom.Point} */ + (ol.format.Feature.transformWithOptions(geometry, true, options)); goog.object.set(context, 'geometryLayout', geometry.getLayout()); ol.format.GPX.writeWptType_(node, geometry.getCoordinates(), objectStack); } @@ -870,11 +882,8 @@ ol.format.GPX.prototype.writeFeaturesNode = function(features, opt_options) { //FIXME Serialize metadata var gpx = ol.xml.createElementNS('http://www.topografix.com/GPX/1/1', 'gpx'); - features = ol.format.XMLFeature.transformFeaturesWithOptions( - features, true, opt_options); - ol.xml.pushSerializeAndPop(/** @type {ol.xml.NodeStackItem} */ ({node: gpx}), ol.format.GPX.GPX_SERIALIZERS_, - ol.format.GPX.GPX_NODE_FACTORY_, features, []); + ol.format.GPX.GPX_NODE_FACTORY_, features, [opt_options]); return gpx; }; diff --git a/src/ol/format/igcformat.js b/src/ol/format/igcformat.js index d1347e9e39..841e608fa0 100644 --- a/src/ol/format/igcformat.js +++ b/src/ol/format/igcformat.js @@ -175,7 +175,7 @@ ol.format.IGC.prototype.readFeatureFromText = function(text, opt_options) { ol.geom.GeometryLayout.XYM : ol.geom.GeometryLayout.XYZM; lineString.setFlatCoordinates(layout, flatCoordinates); var feature = new ol.Feature(ol.format.Feature.transformWithOptions( - lineString, false, false, opt_options)); + lineString, false, opt_options)); feature.setProperties(properties); return feature; }; diff --git a/src/ol/format/kmlformat.js b/src/ol/format/kmlformat.js index fa4d28948a..85e369f011 100644 --- a/src/ol/format/kmlformat.js +++ b/src/ol/format/kmlformat.js @@ -16,6 +16,7 @@ goog.require('ol.Feature'); goog.require('ol.array'); goog.require('ol.color'); goog.require('ol.feature'); +goog.require('ol.format.Feature'); goog.require('ol.format.XMLFeature'); goog.require('ol.format.XSD'); goog.require('ol.geom.Geometry'); @@ -1431,6 +1432,10 @@ ol.format.KML.prototype.readPlacemark_ = function(node, objectStack) { if (!goog.isNull(id)) { feature.setId(id); } + var options = /** @type {olx.format.ReadOptions} */ (objectStack[0]); + if (goog.isDefAndNotNull(object.geometry)) { + ol.format.Feature.transformWithOptions(object.geometry, false, options); + } feature.setProperties(object); feature.setStyle(this.featureStyleFunction_); return feature; @@ -1508,10 +1513,9 @@ ol.format.KML.prototype.readFeatureFromNode = function(node, opt_options) { return null; } goog.asserts.assert(node.localName == 'Placemark'); - var feature = this.readPlacemark_(node, []); + var feature = this.readPlacemark_( + node, [this.getReadOptions(node, opt_options)]); if (goog.isDef(feature)) { - ol.format.XMLFeature.transformFeaturesWithOptions( - [feature], false, this.getReadOptions(node, opt_options)); return feature; } else { return null; @@ -1542,19 +1546,17 @@ ol.format.KML.prototype.readFeaturesFromNode = function(node, opt_options) { var features; var localName = ol.xml.getLocalName(node); if (localName == 'Document' || localName == 'Folder') { - features = this.readDocumentOrFolder_(node, []); + features = this.readDocumentOrFolder_( + node, [this.getReadOptions(node, opt_options)]); if (goog.isDef(features)) { - ol.format.XMLFeature.transformFeaturesWithOptions( - features, false, this.getReadOptions(node, opt_options)); return features; } else { return []; } } else if (localName == 'Placemark') { - var feature = this.readPlacemark_(node, []); + var feature = this.readPlacemark_( + node, [this.getReadOptions(node, opt_options)]); if (goog.isDef(feature)) { - ol.format.XMLFeature.transformFeaturesWithOptions( - [feature], false, this.getReadOptions(node, opt_options)); return [feature]; } else { return []; @@ -1966,9 +1968,14 @@ ol.format.KML.writePlacemark_ = function(node, feature, objectStack) { ol.xml.OBJECT_PROPERTY_NODE_FACTORY, values, objectStack, orderedKeys); // serialize geometry + var options = /** @type {olx.format.WriteOptions} */ (objectStack[0]); + var geometry = feature.getGeometry(); + if (goog.isDefAndNotNull(geometry)) { + geometry = + ol.format.Feature.transformWithOptions(geometry, true, options); + } ol.xml.pushSerializeAndPop(context, ol.format.KML.PLACEMARK_SERIALIZERS_, - ol.format.KML.GEOMETRY_NODE_FACTORY_, - [feature.getGeometry()], objectStack); + ol.format.KML.GEOMETRY_NODE_FACTORY_, [geometry], objectStack); }; @@ -2527,9 +2534,6 @@ ol.format.KML.prototype.writeFeaturesNode = function(features, opt_options) { ol.xml.setAttributeNS(kml, xmlSchemaInstanceUri, 'xsi:schemaLocation', ol.format.KML.SCHEMA_LOCATION_); - features = ol.format.XMLFeature.transformFeaturesWithOptions( - features, true, opt_options); - var /** @type {ol.xml.NodeStackItem} */ context = {node: kml}; var properties = {}; if (features.length > 1) { @@ -2540,6 +2544,6 @@ ol.format.KML.prototype.writeFeaturesNode = function(features, opt_options) { var orderedKeys = ol.format.KML.KML_SEQUENCE_[kml.namespaceURI]; var values = ol.xml.makeSequence(properties, orderedKeys); ol.xml.pushSerializeAndPop(context, ol.format.KML.KML_SERIALIZERS_, - ol.xml.OBJECT_PROPERTY_NODE_FACTORY, values, [], orderedKeys); + ol.xml.OBJECT_PROPERTY_NODE_FACTORY, values, [opt_options], orderedKeys); return kml; }; diff --git a/src/ol/format/osmxmlformat.js b/src/ol/format/osmxmlformat.js index 7831e7f32f..fb23b224a2 100644 --- a/src/ol/format/osmxmlformat.js +++ b/src/ol/format/osmxmlformat.js @@ -6,6 +6,7 @@ goog.require('goog.asserts'); goog.require('goog.dom.NodeType'); goog.require('goog.object'); goog.require('ol.Feature'); +goog.require('ol.format.Feature'); goog.require('ol.format.XMLFeature'); goog.require('ol.geom.LineString'); goog.require('ol.geom.Point'); @@ -59,6 +60,7 @@ ol.format.OSMXML.prototype.getExtensions = function() { ol.format.OSMXML.readNode_ = function(node, objectStack) { goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT); goog.asserts.assert(node.localName == 'node'); + var options = /** @type {olx.format.ReadOptions} */ (objectStack[0]); var state = /** @type {Object} */ (objectStack[objectStack.length - 1]); var id = node.getAttribute('id'); var coordinates = /** @type {Array.} */ ([ @@ -72,6 +74,7 @@ ol.format.OSMXML.readNode_ = function(node, objectStack) { }, ol.format.OSMXML.NODE_PARSERS_, node, objectStack); if (!goog.object.isEmpty(values.tags)) { var geometry = new ol.geom.Point(coordinates); + ol.format.Feature.transformWithOptions(geometry, false, options); var feature = new ol.Feature(geometry); feature.setId(id); feature.setProperties(values.tags); @@ -88,6 +91,7 @@ ol.format.OSMXML.readNode_ = function(node, objectStack) { ol.format.OSMXML.readWay_ = function(node, objectStack) { goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT); goog.asserts.assert(node.localName == 'way'); + var options = /** @type {olx.format.ReadOptions} */ (objectStack[0]); var id = node.getAttribute('id'); var values = ol.xml.pushParseAndPop({ ndrefs: [], @@ -109,6 +113,7 @@ ol.format.OSMXML.readWay_ = function(node, objectStack) { geometry = new ol.geom.LineString(null); geometry.setFlatCoordinates(ol.geom.GeometryLayout.XY, flatCoordinates); } + ol.format.Feature.transformWithOptions(geometry, false, options); var feature = new ol.Feature(geometry); feature.setId(id); feature.setProperties(values.tags); @@ -206,14 +211,13 @@ ol.format.OSMXML.prototype.readFeatures; */ ol.format.OSMXML.prototype.readFeaturesFromNode = function(node, opt_options) { goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT); + var options = this.getReadOptions(node, opt_options); if (node.localName == 'osm') { var state = ol.xml.pushParseAndPop({ nodes: {}, features: [] - }, ol.format.OSMXML.PARSERS_, node, []); + }, ol.format.OSMXML.PARSERS_, node, [options]); if (goog.isDef(state.features)) { - ol.format.XMLFeature.transformFeaturesWithOptions( - state.features, false, this.getReadOptions(node, opt_options)); return state.features; } } diff --git a/src/ol/format/polylineformat.js b/src/ol/format/polylineformat.js index 0cb41b57bb..c80e423565 100644 --- a/src/ol/format/polylineformat.js +++ b/src/ol/format/polylineformat.js @@ -314,9 +314,10 @@ ol.format.Polyline.prototype.readGeometryFromText = var coordinates = ol.geom.flat.inflate.coordinates( flatCoordinates, 0, flatCoordinates.length, 2); - return ol.format.Feature.transformWithOptions( - new ol.geom.LineString(coordinates), false, false, - this.adaptOptionsWithDefaultDataProjection(opt_options)); + return /** @type {ol.geom.Geometry} */ ( + ol.format.Feature.transformWithOptions( + new ol.geom.LineString(coordinates), false, + this.adaptOptionsWithDefaultDataProjection(opt_options))); }; @@ -383,7 +384,7 @@ ol.format.Polyline.prototype.writeGeometryText = goog.asserts.assertInstanceof(geometry, ol.geom.LineString); geometry = /** @type {ol.geom.LineString} */ (ol.format.Feature.transformWithOptions( - geometry, true, true, + geometry, true, this.adaptOptionsWithDefaultDataProjection(opt_options))); var flatCoordinates = geometry.getFlatCoordinates(); var stride = geometry.getStride(); diff --git a/src/ol/format/topojsonformat.js b/src/ol/format/topojsonformat.js index ab7bd47794..7c9e74d2a7 100644 --- a/src/ol/format/topojsonformat.js +++ b/src/ol/format/topojsonformat.js @@ -259,8 +259,8 @@ ol.format.TopoJSON.readFeatureFromGeometry_ = function(object, arcs, geometry = geometryReader(object, arcs); } var feature = new ol.Feature(); - feature.setGeometry(ol.format.Feature.transformWithOptions( - geometry, false, false, opt_options)); + feature.setGeometry(/** @type {ol.geom.Geometry} */ ( + ol.format.Feature.transformWithOptions(geometry, false, opt_options))); if (goog.isDef(object.id)) { feature.setId(object.id); } diff --git a/src/ol/format/wfsformat.js b/src/ol/format/wfsformat.js index ca7eea37d1..d4098c2ee5 100644 --- a/src/ol/format/wfsformat.js +++ b/src/ol/format/wfsformat.js @@ -105,17 +105,18 @@ ol.format.WFS.prototype.readFeatures; * @inheritDoc */ ol.format.WFS.prototype.readFeaturesFromNode = function(node, opt_options) { - var objectStack = [{ + var context = { 'featureType': this.featureType_, 'featureNS': this.featureNS_ - }]; + }; + goog.object.extend(context, this.getReadOptions(node, + goog.isDef(opt_options) ? opt_options : {})); + var objectStack = [context]; var features = ol.xml.pushParseAndPop([], ol.format.GML.FEATURE_COLLECTION_PARSERS, node, objectStack); if (!goog.isDef(features)) { features = []; } - ol.format.XMLFeature.transformFeaturesWithOptions( - features, false, this.getReadOptions(node, opt_options)); return features; }; diff --git a/src/ol/format/wktformat.js b/src/ol/format/wktformat.js index d0c1f0a930..328e95537a 100644 --- a/src/ol/format/wktformat.js +++ b/src/ol/format/wktformat.js @@ -283,8 +283,8 @@ ol.format.WKT.prototype.readGeometry; ol.format.WKT.prototype.readGeometryFromText = function(text, opt_options) { var geometry = this.parse_(text); if (goog.isDef(geometry)) { - return ol.format.Feature.transformWithOptions( - geometry, false, false, opt_options); + return /** @type {ol.geom.Geometry} */ ( + ol.format.Feature.transformWithOptions(geometry, false, opt_options)); } else { return null; } @@ -366,8 +366,8 @@ ol.format.WKT.prototype.writeGeometry; * @inheritDoc */ ol.format.WKT.prototype.writeGeometryText = function(geometry, opt_options) { - return ol.format.WKT.encode_(ol.format.Feature.transformWithOptions( - geometry, true, true, opt_options)); + return ol.format.WKT.encode_(/** @type {ol.geom.Geometry} */ ( + ol.format.Feature.transformWithOptions(geometry, true, opt_options))); }; diff --git a/src/ol/format/xmlfeatureformat.js b/src/ol/format/xmlfeatureformat.js index 90ecddc10f..319de0c18d 100644 --- a/src/ol/format/xmlfeatureformat.js +++ b/src/ol/format/xmlfeatureformat.js @@ -250,39 +250,3 @@ ol.format.XMLFeature.prototype.writeGeometry = function(geometry, opt_options) { * @return {Node} Node. */ ol.format.XMLFeature.prototype.writeGeometryNode = goog.abstractMethod; - - -/** - * @param {Array.} features Features. - * @param {boolean} write Set to true for writing, false for reading. For - * writing, the features will be cloned before transforming. - * @param {(olx.format.WriteOptions|olx.format.ReadOptions)=} opt_options - * Options. - * @protected - * @return {Array.} Features. - */ -ol.format.XMLFeature.transformFeaturesWithOptions = function( - features, write, opt_options) { - var featureProjection = goog.isDef(opt_options) ? - ol.proj.get(opt_options.featureProjection) : null; - var dataProjection = goog.isDef(opt_options) ? - ol.proj.get(opt_options.dataProjection) : null; - - if (!goog.isNull(featureProjection) && !goog.isNull(dataProjection) && - !ol.proj.equivalent(featureProjection, dataProjection)) { - if (write) { - features = goog.array.map(features, function(feature) { - return feature.clone(); - }); - } - - goog.array.forEach(features, function(feature) { - var geom = feature.getGeometry(); - if (goog.isDef(geom)) { - feature.setGeometry(ol.format.Feature.transformWithOptions( - geom, write, false, opt_options)); - } - }); - } - return features; -}; From 939e167c0b8fc525e7dc1bd2fb7291aeb8555dfd Mon Sep 17 00:00:00 2001 From: tsauerwein Date: Thu, 21 Aug 2014 11:39:01 +0200 Subject: [PATCH 33/33] Rename "adaptOptionsWithDefaultDataProjection" --- src/ol/format/featureformat.js | 6 ++++-- src/ol/format/jsonfeatureformat.js | 12 +++--------- src/ol/format/polylineformat.js | 5 ++--- src/ol/format/textfeatureformat.js | 21 ++++++--------------- src/ol/format/xmlfeatureformat.js | 12 +++--------- 5 files changed, 18 insertions(+), 38 deletions(-) diff --git a/src/ol/format/featureformat.js b/src/ol/format/featureformat.js index 364ba16a86..b5b5f20144 100644 --- a/src/ol/format/featureformat.js +++ b/src/ol/format/featureformat.js @@ -50,18 +50,20 @@ ol.format.Feature.prototype.getReadOptions = function( featureProjection: opt_options.featureProjection }; } - return this.adaptOptionsWithDefaultDataProjection(options); + return this.adaptOptions(options); }; /** + * Sets the `defaultDataProjection` on the options, if no `dataProjection` + * is set. * @param {olx.format.WriteOptions|olx.format.ReadOptions|undefined} options * Options. * @protected * @return {olx.format.WriteOptions|olx.format.ReadOptions|undefined} * Updated options. */ -ol.format.Feature.prototype.adaptOptionsWithDefaultDataProjection = function( +ol.format.Feature.prototype.adaptOptions = function( options) { var updatedOptions; if (goog.isDef(options)) { diff --git a/src/ol/format/jsonfeatureformat.js b/src/ol/format/jsonfeatureformat.js index 109613a1ce..97c4fa4ebb 100644 --- a/src/ol/format/jsonfeatureformat.js +++ b/src/ol/format/jsonfeatureformat.js @@ -128,9 +128,7 @@ ol.format.JSONFeature.prototype.readProjectionFromObject = goog.abstractMethod; * @inheritDoc */ ol.format.JSONFeature.prototype.writeFeature = function(feature, opt_options) { - return this.writeFeatureObject( - feature, - this.adaptOptionsWithDefaultDataProjection(opt_options)); + return this.writeFeatureObject(feature, this.adaptOptions(opt_options)); }; @@ -148,9 +146,7 @@ ol.format.JSONFeature.prototype.writeFeatureObject = goog.abstractMethod; */ ol.format.JSONFeature.prototype.writeFeatures = function( features, opt_options) { - return this.writeFeaturesObject( - features, - this.adaptOptionsWithDefaultDataProjection(opt_options)); + return this.writeFeaturesObject(features, this.adaptOptions(opt_options)); }; @@ -168,9 +164,7 @@ ol.format.JSONFeature.prototype.writeFeaturesObject = goog.abstractMethod; */ ol.format.JSONFeature.prototype.writeGeometry = function( geometry, opt_options) { - return this.writeGeometryObject( - geometry, - this.adaptOptionsWithDefaultDataProjection(opt_options)); + return this.writeGeometryObject(geometry, this.adaptOptions(opt_options)); }; diff --git a/src/ol/format/polylineformat.js b/src/ol/format/polylineformat.js index c80e423565..56fbe5e2b9 100644 --- a/src/ol/format/polylineformat.js +++ b/src/ol/format/polylineformat.js @@ -317,7 +317,7 @@ ol.format.Polyline.prototype.readGeometryFromText = return /** @type {ol.geom.Geometry} */ ( ol.format.Feature.transformWithOptions( new ol.geom.LineString(coordinates), false, - this.adaptOptionsWithDefaultDataProjection(opt_options))); + this.adaptOptions(opt_options))); }; @@ -384,8 +384,7 @@ ol.format.Polyline.prototype.writeGeometryText = goog.asserts.assertInstanceof(geometry, ol.geom.LineString); geometry = /** @type {ol.geom.LineString} */ (ol.format.Feature.transformWithOptions( - geometry, true, - this.adaptOptionsWithDefaultDataProjection(opt_options))); + geometry, true, this.adaptOptions(opt_options))); var flatCoordinates = geometry.getFlatCoordinates(); var stride = geometry.getStride(); return ol.format.Polyline.encodeDeltas(flatCoordinates, stride, this.factor_); diff --git a/src/ol/format/textfeatureformat.js b/src/ol/format/textfeatureformat.js index 583d0a3062..c838c1a729 100644 --- a/src/ol/format/textfeatureformat.js +++ b/src/ol/format/textfeatureformat.js @@ -49,8 +49,7 @@ ol.format.TextFeature.prototype.getType = function() { */ ol.format.TextFeature.prototype.readFeature = function(source, opt_options) { return this.readFeatureFromText( - this.getText_(source), - this.adaptOptionsWithDefaultDataProjection(opt_options)); + this.getText_(source), this.adaptOptions(opt_options)); }; @@ -68,8 +67,7 @@ ol.format.TextFeature.prototype.readFeatureFromText = goog.abstractMethod; */ ol.format.TextFeature.prototype.readFeatures = function(source, opt_options) { return this.readFeaturesFromText( - this.getText_(source), - this.adaptOptionsWithDefaultDataProjection(opt_options)); + this.getText_(source), this.adaptOptions(opt_options)); }; @@ -87,8 +85,7 @@ ol.format.TextFeature.prototype.readFeaturesFromText = goog.abstractMethod; */ ol.format.TextFeature.prototype.readGeometry = function(source, opt_options) { return this.readGeometryFromText( - this.getText_(source), - this.adaptOptionsWithDefaultDataProjection(opt_options)); + this.getText_(source), this.adaptOptions(opt_options)); }; @@ -121,9 +118,7 @@ ol.format.TextFeature.prototype.readProjectionFromText = goog.abstractMethod; * @inheritDoc */ ol.format.TextFeature.prototype.writeFeature = function(feature, opt_options) { - return this.writeFeatureText( - feature, - this.adaptOptionsWithDefaultDataProjection(opt_options)); + return this.writeFeatureText(feature, this.adaptOptions(opt_options)); }; @@ -141,9 +136,7 @@ ol.format.TextFeature.prototype.writeFeatureText = goog.abstractMethod; */ ol.format.TextFeature.prototype.writeFeatures = function( features, opt_options) { - return this.writeFeaturesText( - features, - this.adaptOptionsWithDefaultDataProjection(opt_options)); + return this.writeFeaturesText(features, this.adaptOptions(opt_options)); }; @@ -161,9 +154,7 @@ ol.format.TextFeature.prototype.writeFeaturesText = goog.abstractMethod; */ ol.format.TextFeature.prototype.writeGeometry = function( geometry, opt_options) { - return this.writeGeometryText( - geometry, - this.adaptOptionsWithDefaultDataProjection(opt_options)); + return this.writeGeometryText(geometry, this.adaptOptions(opt_options)); }; diff --git a/src/ol/format/xmlfeatureformat.js b/src/ol/format/xmlfeatureformat.js index 319de0c18d..3c61ee6574 100644 --- a/src/ol/format/xmlfeatureformat.js +++ b/src/ol/format/xmlfeatureformat.js @@ -199,9 +199,7 @@ ol.format.XMLFeature.prototype.readProjectionFromNode = goog.abstractMethod; * @inheritDoc */ ol.format.XMLFeature.prototype.writeFeature = function(feature, opt_options) { - return this.writeFeatureNode( - feature, - this.adaptOptionsWithDefaultDataProjection(opt_options)); + return this.writeFeatureNode(feature, this.adaptOptions(opt_options)); }; @@ -218,9 +216,7 @@ ol.format.XMLFeature.prototype.writeFeatureNode = goog.abstractMethod; * @inheritDoc */ ol.format.XMLFeature.prototype.writeFeatures = function(features, opt_options) { - return this.writeFeaturesNode( - features, - this.adaptOptionsWithDefaultDataProjection(opt_options)); + return this.writeFeaturesNode(features, this.adaptOptions(opt_options)); }; @@ -237,9 +233,7 @@ ol.format.XMLFeature.prototype.writeFeaturesNode = goog.abstractMethod; * @inheritDoc */ ol.format.XMLFeature.prototype.writeGeometry = function(geometry, opt_options) { - return this.writeGeometryNode( - geometry, - this.adaptOptionsWithDefaultDataProjection(opt_options)); + return this.writeGeometryNode(geometry, this.adaptOptions(opt_options)); };