From a8760108d4e519190d344f83537342d5c1f00f30 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Sun, 3 Mar 2013 17:19:18 +0100 Subject: [PATCH] Estimate point resolution for Proj4js projections --- src/ol/projection.js | 40 +++++++++++++++++++++++++++++++++ test/spec/ol/projection.test.js | 30 +++++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/src/ol/projection.js b/src/ol/projection.js index f55f4ba45e..0969b45882 100644 --- a/src/ol/projection.js +++ b/src/ol/projection.js @@ -8,6 +8,7 @@ goog.require('goog.object'); goog.require('ol.Coordinate'); goog.require('ol.Extent'); goog.require('ol.TransformFunction'); +goog.require('ol.sphere.NORMAL'); /** @@ -129,10 +130,49 @@ ol.Proj4jsProjection_ = function(code, proj4jsProj) { */ this.proj4jsProj_ = proj4jsProj; + /** + * @private + * @type {?ol.TransformFunction} + */ + this.toEPSG4326_ = null; + }; goog.inherits(ol.Proj4jsProjection_, ol.Projection); +/** + * @inheritDoc + */ +ol.Proj4jsProjection_.prototype.getPointResolution = + function(resolution, point) { + if (this.getUnits() == ol.ProjectionUnits.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. + if (goog.isNull(this.toEPSG4326_)) { + this.toEPSG4326_ = ol.projection.getTransform( + this, ol.projection.getProj4jsProjectionFromCode_('EPSG:4326')); + } + var vertices = [ + point.x - resolution / 2, point.y, + point.x + resolution / 2, point.y, + point.x, point.y - resolution / 2, + point.x, point.y + resolution / 2 + ]; + vertices = this.toEPSG4326_(vertices, vertices, 2); + var width = ol.sphere.NORMAL.haversineDistance( + new ol.Coordinate(vertices[0], vertices[1]), + new ol.Coordinate(vertices[2], vertices[3])); + var height = ol.sphere.NORMAL.haversineDistance( + new ol.Coordinate(vertices[4], vertices[5]), + new ol.Coordinate(vertices[6], vertices[7])); + return (width + height) / 2; + } +}; + + /** * @return {Proj4js.Proj} Proj4js projection. */ diff --git a/test/spec/ol/projection.test.js b/test/spec/ol/projection.test.js index 5a217e0f40..c961d41819 100644 --- a/test/spec/ol/projection.test.js +++ b/test/spec/ol/projection.test.js @@ -144,6 +144,36 @@ describe('ol.projection', function() { expect(point.y).toRoughlyEqual(200146.976, 1); }); + it('numerically estimates point scale at the equator', function() { + var googleProjection = ol.projection.getFromCode('GOOGLE'); + expect(googleProjection.getPointResolution(1, new ol.Coordinate(0, 0))). + toRoughlyEqual(1, 1e-1); + }); + + it('numerically estimates point scale at various latitudes', function() { + var epsg3857Projection = ol.projection.getFromCode('EPSG:3857'); + var googleProjection = ol.projection.getFromCode('GOOGLE'); + var point, y; + for (y = -20; y <= 20; ++y) { + point = new ol.Coordinate(0, 1000000 * y); + expect(googleProjection.getPointResolution(1, point)).toRoughlyEqual( + epsg3857Projection.getPointResolution(1, point), 1e-1); + } + }); + + it('numerically estimates point scale at various points', function() { + var epsg3857Projection = ol.projection.getFromCode('EPSG:3857'); + var googleProjection = ol.projection.getFromCode('GOOGLE'); + var point, x, y; + for (x = -20; x <= 20; ++x) { + for (y = -20; y <= 20; ++y) { + point = new ol.Coordinate(1000000 * x, 1000000 * y); + expect(googleProjection.getPointResolution(1, point)).toRoughlyEqual( + epsg3857Projection.getPointResolution(1, point), 1e-1); + } + } + }); + }); describe('ol.projection.getTransform()', function() {