From 08569d4eb38b7a5b20342b132b2b44c8edbd3a06 Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Sun, 4 Dec 2016 12:41:04 -0800 Subject: [PATCH] Dedicated module for ol.proj.Projection --- changelog/upgrade-notes.md | 16 ++ src/ol/control/scaleline.js | 3 +- src/ol/proj/epsg3857.js | 13 +- src/ol/proj/epsg4326.js | 8 - src/ol/proj/index.js | 369 ++++------------------------- src/ol/proj/projection.js | 277 ++++++++++++++++++++++ src/ol/proj/units.js | 16 ++ src/ol/reproj/index.js | 4 +- test/spec/ol/proj/epsg3857.test.js | 6 +- test/spec/ol/proj/index.test.js | 10 +- 10 files changed, 368 insertions(+), 354 deletions(-) create mode 100644 src/ol/proj/projection.js diff --git a/changelog/upgrade-notes.md b/changelog/upgrade-notes.md index 17e80b9a10..22f5e10096 100644 --- a/changelog/upgrade-notes.md +++ b/changelog/upgrade-notes.md @@ -35,6 +35,22 @@ view.animate({ }); ``` +#### Use `ol.proj.getPointResolution()` instead of `projection.getPointResolution()` + +The experimental `getPointResolution` method has been removed from `ol.Projection` instances. Since the implementation of this method required an inverse transform (function for transforming projected coordinates to geographic coordinates) and `ol.Projection` instances are not constructed with forward or inverse transforms, it does not make sense that a projection instance can always calculate the point resolution. + +As a substitute for the `projection.getPointResolution()` function, a `ol.proj.getPointResolution()` function has been added. To upgrade, you will need to change things like this: +```js +projection.getPointResolution(resolution, point); +``` + +into this: +```js +ol.proj.getPointResolution(projection, resolution, point); +``` + +Note that if you were previously creating a projection with a `getPointResolution` function in the constructor (or calling `projection.setGetPointResolution()` after construction), this function will be used by `ol.proj.getPointResolution()`. + ### v3.19.1 #### `ol.style.Fill` with `CanvasGradient` or `CanvasPattern` diff --git a/src/ol/control/scaleline.js b/src/ol/control/scaleline.js index 9d3171eb3e..68aea08fdf 100644 --- a/src/ol/control/scaleline.js +++ b/src/ol/control/scaleline.js @@ -6,6 +6,7 @@ goog.require('ol.asserts'); goog.require('ol.control.Control'); goog.require('ol.css'); goog.require('ol.events'); +goog.require('ol.proj'); goog.require('ol.proj.METERS_PER_UNIT'); goog.require('ol.proj.Units'); @@ -169,7 +170,7 @@ ol.control.ScaleLine.prototype.updateElement_ = function() { var projection = viewState.projection; var metersPerUnit = projection.getMetersPerUnit(); var pointResolution = - projection.getPointResolution(viewState.resolution, center) * + ol.proj.getPointResolution(projection, viewState.resolution, center) * metersPerUnit; var nominalCount = this.minWidth_ * pointResolution; diff --git a/src/ol/proj/epsg3857.js b/src/ol/proj/epsg3857.js index 09864be283..105cf64a66 100644 --- a/src/ol/proj/epsg3857.js +++ b/src/ol/proj/epsg3857.js @@ -22,20 +22,15 @@ ol.proj.EPSG3857_ = function(code) { units: ol.proj.Units.METERS, extent: ol.proj.EPSG3857.EXTENT, global: true, - worldExtent: ol.proj.EPSG3857.WORLD_EXTENT + worldExtent: ol.proj.EPSG3857.WORLD_EXTENT, + getPointResolution: function(resolution, point) { + return resolution / ol.math.cosh(point[1] / ol.proj.EPSG3857.RADIUS); + } }); }; ol.inherits(ol.proj.EPSG3857_, ol.proj.Projection); -/** - * @inheritDoc - */ -ol.proj.EPSG3857_.prototype.getPointResolution = function(resolution, point) { - return resolution / ol.math.cosh(point[1] / ol.proj.EPSG3857.RADIUS); -}; - - /** * @const * @type {number} diff --git a/src/ol/proj/epsg4326.js b/src/ol/proj/epsg4326.js index d1fff14687..1ec287e13b 100644 --- a/src/ol/proj/epsg4326.js +++ b/src/ol/proj/epsg4326.js @@ -35,14 +35,6 @@ ol.proj.EPSG4326_ = function(code, opt_axisOrientation) { ol.inherits(ol.proj.EPSG4326_, ol.proj.Projection); -/** - * @inheritDoc - */ -ol.proj.EPSG4326_.prototype.getPointResolution = function(resolution, point) { - return resolution; -}; - - /** * Extent of the EPSG:4326 projection which is the whole world. * diff --git a/src/ol/proj/index.js b/src/ol/proj/index.js index 307e358b42..6a0cca6800 100644 --- a/src/ol/proj/index.js +++ b/src/ol/proj/index.js @@ -1,9 +1,9 @@ goog.provide('ol.proj'); goog.provide('ol.proj.METERS_PER_UNIT'); -goog.provide('ol.proj.Projection'); goog.require('ol'); goog.require('ol.extent'); +goog.require('ol.proj.Projection'); goog.require('ol.proj.Units'); goog.require('ol.proj.proj4'); goog.require('ol.proj.projections'); @@ -17,12 +17,7 @@ goog.require('ol.sphere.NORMAL'); * @type {Object.} * @api stable */ -ol.proj.METERS_PER_UNIT = {}; -ol.proj.METERS_PER_UNIT[ol.proj.Units.DEGREES] = - 2 * Math.PI * ol.sphere.NORMAL.radius / 360; -ol.proj.METERS_PER_UNIT[ol.proj.Units.FEET] = 0.3048; -ol.proj.METERS_PER_UNIT[ol.proj.Units.METERS] = 1; -ol.proj.METERS_PER_UNIT[ol.proj.Units.USFEET] = 1200 / 3937; +ol.proj.METERS_PER_UNIT = ol.proj.Units.METERS_PER_UNIT; if (ol.ENABLE_PROJ4JS) { @@ -47,329 +42,51 @@ if (ol.ENABLE_PROJ4JS) { /** - * @classdesc - * Projection definition class. One of these is created for each projection - * supported in the application and stored in the {@link ol.proj} namespace. - * You can use these in applications, but this is not required, as API params - * and options use {@link ol.ProjectionLike} which means the simple string - * code will suffice. - * - * You can use {@link ol.proj.get} to retrieve the object for a particular - * projection. - * - * The library includes definitions for `EPSG:4326` and `EPSG:3857`, together - * with the following aliases: - * * `EPSG:4326`: CRS:84, urn:ogc:def:crs:EPSG:6.6:4326, - * urn:ogc:def:crs:OGC:1.3:CRS84, urn:ogc:def:crs:OGC:2:84, - * http://www.opengis.net/gml/srs/epsg.xml#4326, - * urn:x-ogc:def:crs:EPSG:4326 - * * `EPSG:3857`: EPSG:102100, EPSG:102113, EPSG:900913, - * urn:ogc:def:crs:EPSG:6.18:3:3857, - * http://www.opengis.net/gml/srs/epsg.xml#3857 - * - * If you use proj4js, aliases can be added using `proj4.defs()`; see - * [documentation](https://github.com/proj4js/proj4js). To set an alternative - * namespace for proj4, use {@link ol.proj.setProj4}. - * - * @constructor - * @param {olx.ProjectionOptions} options Projection options. - * @struct - * @api stable + * Get the resolution of the point in degrees or distance units. + * For projections with degrees as the unit this will simply return the + * provided resolution. For other projections the point resolution is + * estimated by transforming the 'point' pixel to EPSG:4326, + * measuring its width and height on the normal sphere, + * and taking the average of the width and height. + * @param {ol.proj.Projection} projection The projection. + * @param {number} resolution Nominal resolution in projection units. + * @param {ol.Coordinate} point Point to find adjusted resolution at. + * @return {number} Point resolution at point in projection units. + * @api */ -ol.proj.Projection = function(options) { - - /** - * @private - * @type {string} - */ - this.code_ = options.code; - - /** - * @private - * @type {ol.proj.Units} - */ - this.units_ = /** @type {ol.proj.Units} */ (options.units); - - /** - * @private - * @type {ol.Extent} - */ - this.extent_ = options.extent !== undefined ? options.extent : null; - - /** - * @private - * @type {ol.Extent} - */ - this.worldExtent_ = options.worldExtent !== undefined ? - options.worldExtent : null; - - /** - * @private - * @type {string} - */ - this.axisOrientation_ = options.axisOrientation !== undefined ? - options.axisOrientation : 'enu'; - - /** - * @private - * @type {boolean} - */ - this.global_ = options.global !== undefined ? options.global : false; - - /** - * @private - * @type {boolean} - */ - this.canWrapX_ = !!(this.global_ && this.extent_); - - /** - * @private - * @type {function(number, ol.Coordinate):number} - */ - this.getPointResolutionFunc_ = options.getPointResolution !== undefined ? - options.getPointResolution : this.getPointResolution_; - - /** - * @private - * @type {ol.tilegrid.TileGrid} - */ - this.defaultTileGrid_ = null; - - /** - * @private - * @type {number|undefined} - */ - this.metersPerUnit_ = options.metersPerUnit; - - var code = options.code; - ol.DEBUG && console.assert(code !== undefined, - 'Option "code" is required for constructing instance'); - if (ol.ENABLE_PROJ4JS) { - var proj4js = ol.proj.proj4.get(); - if (typeof proj4js == 'function' && !ol.proj.projections.get(code)) { - var def = proj4js.defs(code); - if (def !== undefined) { - if (def.axis !== undefined && options.axisOrientation === undefined) { - this.axisOrientation_ = def.axis; - } - if (options.metersPerUnit === undefined) { - this.metersPerUnit_ = def.to_meter; - } - if (options.units === undefined) { - this.units_ = def.units; - } +ol.proj.getPointResolution = function(projection, resolution, point) { + var pointResolution; + var getter = projection.getPointResolutionFunc(); + if (getter) { + pointResolution = getter(resolution, point); + } else { + var units = projection.getUnits(); + if (units == ol.proj.Units.DEGREES) { + pointResolution = resolution; + } else { + // Estimate point resolution by transforming the center pixel to EPSG:4326, + // measuring its width and height on the normal sphere, and taking the + // average of the width and height. + var toEPSG4326 = ol.proj.getTransformFromProjections(projection, ol.proj.get('EPSG:4326')); + var vertices = [ + point[0] - resolution / 2, point[1], + point[0] + resolution / 2, point[1], + point[0], point[1] - resolution / 2, + point[0], point[1] + resolution / 2 + ]; + vertices = toEPSG4326(vertices, vertices, 2); + var width = ol.sphere.NORMAL.haversineDistance( + vertices.slice(0, 2), vertices.slice(2, 4)); + var height = ol.sphere.NORMAL.haversineDistance( + vertices.slice(4, 6), vertices.slice(6, 8)); + pointResolution = (width + height) / 2; + var metersPerUnit = projection.getMetersPerUnit(); + if (metersPerUnit !== undefined) { + pointResolution /= metersPerUnit; } } } - -}; - - -/** - * @return {boolean} The projection is suitable for wrapping the x-axis - */ -ol.proj.Projection.prototype.canWrapX = function() { - return this.canWrapX_; -}; - - -/** - * Get the code for this projection, e.g. 'EPSG:4326'. - * @return {string} Code. - * @api stable - */ -ol.proj.Projection.prototype.getCode = function() { - return this.code_; -}; - - -/** - * Get the validity extent for this projection. - * @return {ol.Extent} Extent. - * @api stable - */ -ol.proj.Projection.prototype.getExtent = function() { - return this.extent_; -}; - - -/** - * Get the units of this projection. - * @return {ol.proj.Units} Units. - * @api stable - */ -ol.proj.Projection.prototype.getUnits = function() { - return this.units_; -}; - - -/** - * Get the amount of meters per unit of this projection. If the projection is - * not configured with `metersPerUnit` or a units identifier, the return is - * `undefined`. - * @return {number|undefined} Meters. - * @api stable - */ -ol.proj.Projection.prototype.getMetersPerUnit = function() { - return this.metersPerUnit_ || ol.proj.METERS_PER_UNIT[this.units_]; -}; - - -/** - * Get the world extent for this projection. - * @return {ol.Extent} Extent. - * @api - */ -ol.proj.Projection.prototype.getWorldExtent = function() { - return this.worldExtent_; -}; - - -/** - * Get the axis orientation of this projection. - * Example values are: - * enu - the default easting, northing, elevation. - * neu - northing, easting, up - useful for "lat/long" geographic coordinates, - * or south orientated transverse mercator. - * wnu - westing, northing, up - some planetary coordinate systems have - * "west positive" coordinate systems - * @return {string} Axis orientation. - */ -ol.proj.Projection.prototype.getAxisOrientation = function() { - return this.axisOrientation_; -}; - - -/** - * Is this projection a global projection which spans the whole world? - * @return {boolean} Whether the projection is global. - * @api stable - */ -ol.proj.Projection.prototype.isGlobal = function() { - return this.global_; -}; - - -/** -* Set if the projection is a global projection which spans the whole world -* @param {boolean} global Whether the projection is global. -* @api stable -*/ -ol.proj.Projection.prototype.setGlobal = function(global) { - this.global_ = global; - this.canWrapX_ = !!(global && this.extent_); -}; - - -/** - * @return {ol.tilegrid.TileGrid} The default tile grid. - */ -ol.proj.Projection.prototype.getDefaultTileGrid = function() { - return this.defaultTileGrid_; -}; - - -/** - * @param {ol.tilegrid.TileGrid} tileGrid The default tile grid. - */ -ol.proj.Projection.prototype.setDefaultTileGrid = function(tileGrid) { - this.defaultTileGrid_ = tileGrid; -}; - - -/** - * Set the validity extent for this projection. - * @param {ol.Extent} extent Extent. - * @api stable - */ -ol.proj.Projection.prototype.setExtent = function(extent) { - this.extent_ = extent; - this.canWrapX_ = !!(this.global_ && extent); -}; - - -/** - * Set the world extent for this projection. - * @param {ol.Extent} worldExtent World extent - * [minlon, minlat, maxlon, maxlat]. - * @api - */ -ol.proj.Projection.prototype.setWorldExtent = function(worldExtent) { - this.worldExtent_ = worldExtent; -}; - - -/** -* Set the getPointResolution function for this projection. -* @param {function(number, ol.Coordinate):number} func Function -* @api -*/ -ol.proj.Projection.prototype.setGetPointResolution = function(func) { - this.getPointResolutionFunc_ = func; -}; - - -/** -* Default version. -* Get the resolution of the point in degrees or distance units. -* For projections with degrees as the unit this will simply return the -* provided resolution. For other projections the point resolution is -* estimated by transforming the 'point' pixel to EPSG:4326, -* measuring its width and height on the normal sphere, -* and taking the average of the width and height. -* @param {number} resolution Nominal resolution in projection units. -* @param {ol.Coordinate} point Point to find adjusted resolution at. -* @return {number} Point resolution at point in projection units. -* @private -*/ -ol.proj.Projection.prototype.getPointResolution_ = function(resolution, point) { - var units = this.getUnits(); - if (units == ol.proj.Units.DEGREES) { - return resolution; - } else { - // Estimate point resolution by transforming the center pixel to EPSG:4326, - // measuring its width and height on the normal sphere, and taking the - // average of the width and height. - var toEPSG4326 = ol.proj.getTransformFromProjections( - this, ol.proj.get('EPSG:4326')); - var vertices = [ - point[0] - resolution / 2, point[1], - point[0] + resolution / 2, point[1], - point[0], point[1] - resolution / 2, - point[0], point[1] + resolution / 2 - ]; - vertices = toEPSG4326(vertices, vertices, 2); - var width = ol.sphere.NORMAL.haversineDistance( - vertices.slice(0, 2), vertices.slice(2, 4)); - var height = ol.sphere.NORMAL.haversineDistance( - vertices.slice(4, 6), vertices.slice(6, 8)); - var pointResolution = (width + height) / 2; - var metersPerUnit = this.getMetersPerUnit(); - if (metersPerUnit !== undefined) { - pointResolution /= metersPerUnit; - } - return pointResolution; - } -}; - - -/** - * Get the resolution of the point in degrees or distance units. - * For projections with degrees as the unit this will simply return the - * provided resolution. The default for other projections is to estimate - * the point resolution by transforming the 'point' pixel to EPSG:4326, - * measuring its width and height on the normal sphere, - * and taking the average of the width and height. - * An alternative implementation may be given when constructing a - * projection. For many local projections, - * such a custom function will return the resolution unchanged. - * @param {number} resolution Resolution in projection units. - * @param {ol.Coordinate} point Point. - * @return {number} Point resolution in projection units. - * @api - */ -ol.proj.Projection.prototype.getPointResolution = function(resolution, point) { - return this.getPointResolutionFunc_(resolution, point); + return pointResolution; }; diff --git a/src/ol/proj/projection.js b/src/ol/proj/projection.js new file mode 100644 index 0000000000..82aa693b6e --- /dev/null +++ b/src/ol/proj/projection.js @@ -0,0 +1,277 @@ +goog.provide('ol.proj.Projection'); + +goog.require('ol'); +goog.require('ol.proj.Units'); +goog.require('ol.proj.proj4'); + + +/** + * @classdesc + * Projection definition class. One of these is created for each projection + * supported in the application and stored in the {@link ol.proj} namespace. + * You can use these in applications, but this is not required, as API params + * and options use {@link ol.ProjectionLike} which means the simple string + * code will suffice. + * + * You can use {@link ol.proj.get} to retrieve the object for a particular + * projection. + * + * The library includes definitions for `EPSG:4326` and `EPSG:3857`, together + * with the following aliases: + * * `EPSG:4326`: CRS:84, urn:ogc:def:crs:EPSG:6.6:4326, + * urn:ogc:def:crs:OGC:1.3:CRS84, urn:ogc:def:crs:OGC:2:84, + * http://www.opengis.net/gml/srs/epsg.xml#4326, + * urn:x-ogc:def:crs:EPSG:4326 + * * `EPSG:3857`: EPSG:102100, EPSG:102113, EPSG:900913, + * urn:ogc:def:crs:EPSG:6.18:3:3857, + * http://www.opengis.net/gml/srs/epsg.xml#3857 + * + * If you use proj4js, aliases can be added using `proj4.defs()`; see + * [documentation](https://github.com/proj4js/proj4js). To set an alternative + * namespace for proj4, use {@link ol.proj.setProj4}. + * + * @constructor + * @param {olx.ProjectionOptions} options Projection options. + * @struct + * @api stable + */ +ol.proj.Projection = function(options) { + + /** + * @private + * @type {string} + */ + this.code_ = options.code; + + /** + * @private + * @type {ol.proj.Units} + */ + this.units_ = /** @type {ol.proj.Units} */ (options.units); + + /** + * @private + * @type {ol.Extent} + */ + this.extent_ = options.extent !== undefined ? options.extent : null; + + /** + * @private + * @type {ol.Extent} + */ + this.worldExtent_ = options.worldExtent !== undefined ? + options.worldExtent : null; + + /** + * @private + * @type {string} + */ + this.axisOrientation_ = options.axisOrientation !== undefined ? + options.axisOrientation : 'enu'; + + /** + * @private + * @type {boolean} + */ + this.global_ = options.global !== undefined ? options.global : false; + + /** + * @private + * @type {boolean} + */ + this.canWrapX_ = !!(this.global_ && this.extent_); + + /** + * @private + * @type {function(number, ol.Coordinate):number|undefined} + */ + this.getPointResolutionFunc_ = options.getPointResolution; + + /** + * @private + * @type {ol.tilegrid.TileGrid} + */ + this.defaultTileGrid_ = null; + + /** + * @private + * @type {number|undefined} + */ + this.metersPerUnit_ = options.metersPerUnit; + + var code = options.code; + ol.DEBUG && console.assert(code !== undefined, + 'Option "code" is required for constructing instance'); + if (ol.ENABLE_PROJ4JS) { + var proj4js = ol.proj.proj4.get(); + if (typeof proj4js == 'function') { + var def = proj4js.defs(code); + if (def !== undefined) { + if (def.axis !== undefined && options.axisOrientation === undefined) { + this.axisOrientation_ = def.axis; + } + if (options.metersPerUnit === undefined) { + this.metersPerUnit_ = def.to_meter; + } + if (options.units === undefined) { + this.units_ = def.units; + } + } + } + } + +}; + + +/** + * @return {boolean} The projection is suitable for wrapping the x-axis + */ +ol.proj.Projection.prototype.canWrapX = function() { + return this.canWrapX_; +}; + + +/** + * Get the code for this projection, e.g. 'EPSG:4326'. + * @return {string} Code. + * @api stable + */ +ol.proj.Projection.prototype.getCode = function() { + return this.code_; +}; + + +/** + * Get the validity extent for this projection. + * @return {ol.Extent} Extent. + * @api stable + */ +ol.proj.Projection.prototype.getExtent = function() { + return this.extent_; +}; + + +/** + * Get the units of this projection. + * @return {ol.proj.Units} Units. + * @api stable + */ +ol.proj.Projection.prototype.getUnits = function() { + return this.units_; +}; + + +/** + * Get the amount of meters per unit of this projection. If the projection is + * not configured with `metersPerUnit` or a units identifier, the return is + * `undefined`. + * @return {number|undefined} Meters. + * @api stable + */ +ol.proj.Projection.prototype.getMetersPerUnit = function() { + return this.metersPerUnit_ || ol.proj.Units.METERS_PER_UNIT[this.units_]; +}; + + +/** + * Get the world extent for this projection. + * @return {ol.Extent} Extent. + * @api + */ +ol.proj.Projection.prototype.getWorldExtent = function() { + return this.worldExtent_; +}; + + +/** + * Get the axis orientation of this projection. + * Example values are: + * enu - the default easting, northing, elevation. + * neu - northing, easting, up - useful for "lat/long" geographic coordinates, + * or south orientated transverse mercator. + * wnu - westing, northing, up - some planetary coordinate systems have + * "west positive" coordinate systems + * @return {string} Axis orientation. + */ +ol.proj.Projection.prototype.getAxisOrientation = function() { + return this.axisOrientation_; +}; + + +/** + * Is this projection a global projection which spans the whole world? + * @return {boolean} Whether the projection is global. + * @api stable + */ +ol.proj.Projection.prototype.isGlobal = function() { + return this.global_; +}; + + +/** +* Set if the projection is a global projection which spans the whole world +* @param {boolean} global Whether the projection is global. +* @api stable +*/ +ol.proj.Projection.prototype.setGlobal = function(global) { + this.global_ = global; + this.canWrapX_ = !!(global && this.extent_); +}; + + +/** + * @return {ol.tilegrid.TileGrid} The default tile grid. + */ +ol.proj.Projection.prototype.getDefaultTileGrid = function() { + return this.defaultTileGrid_; +}; + + +/** + * @param {ol.tilegrid.TileGrid} tileGrid The default tile grid. + */ +ol.proj.Projection.prototype.setDefaultTileGrid = function(tileGrid) { + this.defaultTileGrid_ = tileGrid; +}; + + +/** + * Set the validity extent for this projection. + * @param {ol.Extent} extent Extent. + * @api stable + */ +ol.proj.Projection.prototype.setExtent = function(extent) { + this.extent_ = extent; + this.canWrapX_ = !!(this.global_ && extent); +}; + + +/** + * Set the world extent for this projection. + * @param {ol.Extent} worldExtent World extent + * [minlon, minlat, maxlon, maxlat]. + * @api + */ +ol.proj.Projection.prototype.setWorldExtent = function(worldExtent) { + this.worldExtent_ = worldExtent; +}; + + +/** + * Set the getPointResolution function for this projection. + * @param {function(number, ol.Coordinate):number} func Function + * @api + */ +ol.proj.Projection.prototype.setGetPointResolution = function(func) { + this.getPointResolutionFunc_ = func; +}; + + +/** + * Get the custom point resolution function for this projection (if set). + * @return {function(number, ol.Coordinate):number|undefined} The custom point + * resolution function (if set). + */ +ol.proj.Projection.prototype.getPointResolutionFunc = function() { + return this.getPointResolutionFunc_; +}; diff --git a/src/ol/proj/units.js b/src/ol/proj/units.js index e83994a1c8..3529a06ad5 100644 --- a/src/ol/proj/units.js +++ b/src/ol/proj/units.js @@ -1,5 +1,7 @@ goog.provide('ol.proj.Units'); +goog.require('ol.sphere.NORMAL'); + /** * Projection units: `'degrees'`, `'ft'`, `'m'`, `'pixels'`, `'tile-pixels'` or @@ -14,3 +16,17 @@ ol.proj.Units = { TILE_PIXELS: 'tile-pixels', USFEET: 'us-ft' }; + + +/** + * Meters per unit lookup table. + * @const + * @type {Object.} + * @api stable + */ +ol.proj.Units.METERS_PER_UNIT = {}; +ol.proj.Units.METERS_PER_UNIT[ol.proj.Units.DEGREES] = + 2 * Math.PI * ol.sphere.NORMAL.radius / 360; +ol.proj.Units.METERS_PER_UNIT[ol.proj.Units.FEET] = 0.3048; +ol.proj.Units.METERS_PER_UNIT[ol.proj.Units.METERS] = 1; +ol.proj.Units.METERS_PER_UNIT[ol.proj.Units.USFEET] = 1200 / 3937; diff --git a/src/ol/reproj/index.js b/src/ol/reproj/index.js index a804c4eec2..482b7d4d78 100644 --- a/src/ol/reproj/index.js +++ b/src/ol/reproj/index.js @@ -50,7 +50,7 @@ ol.reproj.calculateSourceResolution = function(sourceProj, targetProj, // calculate the ideal resolution of the source data var sourceResolution = - targetProj.getPointResolution(targetResolution, targetCenter); + ol.proj.getPointResolution(targetProj, targetResolution, targetCenter); var targetMetersPerUnit = targetProj.getMetersPerUnit(); if (targetMetersPerUnit !== undefined) { @@ -66,7 +66,7 @@ ol.reproj.calculateSourceResolution = function(sourceProj, targetProj, // in order to achieve optimal results. var compensationFactor = - sourceProj.getPointResolution(sourceResolution, sourceCenter) / + ol.proj.getPointResolution(sourceProj, sourceResolution, sourceCenter) / sourceResolution; if (isFinite(compensationFactor) && compensationFactor > 0) { diff --git a/test/spec/ol/proj/epsg3857.test.js b/test/spec/ol/proj/epsg3857.test.js index 2402b2854e..7dc47dcf9b 100644 --- a/test/spec/ol/proj/epsg3857.test.js +++ b/test/spec/ol/proj/epsg3857.test.js @@ -49,7 +49,7 @@ describe('ol.proj.EPSG3857', function() { var epsg3857 = ol.proj.get('EPSG:3857'); var resolution = 19.11; var point = [0, 0]; - expect(epsg3857.getPointResolution(resolution, point)). + expect(ol.proj.getPointResolution(epsg3857, resolution, point)). to.roughlyEqual(19.11, 1e-1); }); @@ -60,7 +60,7 @@ describe('ol.proj.EPSG3857', function() { var epsg4326 = ol.proj.get('EPSG:4326'); var resolution = 19.11; var point = ol.proj.transform([0, 43.65], epsg4326, epsg3857); - expect(epsg3857.getPointResolution(resolution, point)). + expect(ol.proj.getPointResolution(epsg3857, resolution, point)). to.roughlyEqual(19.11 * Math.cos(Math.PI * 43.65 / 180), 1e-9); }); @@ -72,7 +72,7 @@ describe('ol.proj.EPSG3857', function() { var latitude; for (latitude = 0; latitude <= 85; ++latitude) { var point = ol.proj.transform([0, latitude], epsg4326, epsg3857); - expect(epsg3857.getPointResolution(resolution, point)). + expect(ol.proj.getPointResolution(epsg3857, resolution, point)). to.roughlyEqual(19.11 * Math.cos(Math.PI * latitude / 180), 1e-9); } }); diff --git a/test/spec/ol/proj/index.test.js b/test/spec/ol/proj/index.test.js index 6839299884..6f2cb44de7 100644 --- a/test/spec/ol/proj/index.test.js +++ b/test/spec/ol/proj/index.test.js @@ -310,7 +310,7 @@ describe('ol.proj', function() { it('numerically estimates point scale at the equator', function() { var googleProjection = ol.proj.get('GOOGLE'); - expect(googleProjection.getPointResolution(1, [0, 0])). + expect(ol.proj.getPointResolution(googleProjection, 1, [0, 0])). to.roughlyEqual(1, 1e-1); }); @@ -320,8 +320,8 @@ describe('ol.proj', function() { var point, y; for (y = -20; y <= 20; ++y) { point = [0, 1000000 * y]; - expect(googleProjection.getPointResolution(1, point)).to.roughlyEqual( - epsg3857Projection.getPointResolution(1, point), 1e-1); + expect(ol.proj.getPointResolution(googleProjection, 1, point)).to.roughlyEqual( + ol.proj.getPointResolution(epsg3857Projection, 1, point), 1e-1); } }); @@ -332,8 +332,8 @@ describe('ol.proj', function() { for (x = -20; x <= 20; x += 2) { for (y = -20; y <= 20; y += 2) { point = [1000000 * x, 1000000 * y]; - expect(googleProjection.getPointResolution(1, point)).to.roughlyEqual( - epsg3857Projection.getPointResolution(1, point), 1e-1); + expect(ol.proj.getPointResolution(googleProjection, 1, point)).to.roughlyEqual( + ol.proj.getPointResolution(epsg3857Projection, 1, point), 1e-1); } } });