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);
}
}
});