diff --git a/src/ol/control/scaleline.js b/src/ol/control/scaleline.js index e5ed098b8a..19bcbe2b99 100644 --- a/src/ol/control/scaleline.js +++ b/src/ol/control/scaleline.js @@ -168,17 +168,22 @@ ol.control.ScaleLine.prototype.updateElement_ = function() { var center = viewState.center; var projection = viewState.projection; - var metersPerUnit = projection.getMetersPerUnit(); + var units = this.getUnits(); + var pointResolutionUnits = units == ol.control.ScaleLineUnits.DEGREES ? + ol.proj.Units.DEGREES : + ol.proj.Units.METERS; var pointResolution = - ol.proj.getPointResolution(projection, viewState.resolution, center) * - metersPerUnit; + ol.proj.getPointResolution(projection, viewState.resolution, center, pointResolutionUnits); var nominalCount = this.minWidth_ * pointResolution; var suffix = ''; - var units = this.getUnits(); if (units == ol.control.ScaleLineUnits.DEGREES) { var metersPerDegree = ol.proj.METERS_PER_UNIT[ol.proj.Units.DEGREES]; - pointResolution /= metersPerDegree; + if (projection.getUnits() == ol.proj.Units.DEGREES) { + nominalCount *= metersPerDegree; + } else { + pointResolution /= metersPerDegree; + } if (nominalCount < metersPerDegree / 60) { suffix = '\u2033'; // seconds pointResolution *= 3600; diff --git a/src/ol/proj.js b/src/ol/proj.js index 66b8fb21bd..b92974ead9 100644 --- a/src/ol/proj.js +++ b/src/ol/proj.js @@ -63,10 +63,12 @@ if (ol.ENABLE_PROJ4JS) { * @param {ol.ProjectionLike} 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. + * @param {ol.proj.Units=} opt_units Units to get the point resolution in. + * Default is the projection's units. + * @return {number} Point resolution. * @api */ -ol.proj.getPointResolution = function(projection, resolution, point) { +ol.proj.getPointResolution = function(projection, resolution, point, opt_units) { projection = ol.proj.get(projection); var pointResolution; var getter = projection.getPointResolutionFunc(); @@ -74,7 +76,7 @@ ol.proj.getPointResolution = function(projection, resolution, point) { pointResolution = getter(resolution, point); } else { var units = projection.getUnits(); - if (units == ol.proj.Units.DEGREES) { + if (units == ol.proj.Units.DEGREES && !opt_units || opt_units == ol.proj.Units.DEGREES) { pointResolution = resolution; } else { // Estimate point resolution by transforming the center pixel to EPSG:4326, @@ -93,7 +95,9 @@ ol.proj.getPointResolution = function(projection, resolution, point) { var height = ol.proj.AUTHALIC_SPHERE_.haversineDistance( vertices.slice(4, 6), vertices.slice(6, 8)); pointResolution = (width + height) / 2; - var metersPerUnit = projection.getMetersPerUnit(); + var metersPerUnit = opt_units ? + ol.proj.Units.METERS_PER_UNIT[opt_units] : + projection.getMetersPerUnit(); if (metersPerUnit !== undefined) { pointResolution /= metersPerUnit; } diff --git a/test/spec/ol/control/scaleline.test.js b/test/spec/ol/control/scaleline.test.js index df655d77c7..709a20a428 100644 --- a/test/spec/ol/control/scaleline.test.js +++ b/test/spec/ol/control/scaleline.test.js @@ -262,6 +262,44 @@ describe('ol.control.ScaleLine', function() { }); }); + describe('latitude may affect scale line in EPSG:4326', function() { + + it('is rendered differently at different latitudes for metric', function() { + var ctrl = new ol.control.ScaleLine(); + ctrl.setMap(map); + map.setView(new ol.View({ + center: ol.proj.fromLonLat([7, 0]), + zoom: 2, + projection: 'EPSG:4326' + })); + map.renderSync(); + var innerHtml0 = ctrl.element_.innerHTML; + map.getView().setCenter([7, 52]); + map.renderSync(); + var innerHtml52 = ctrl.element_.innerHTML; + expect(innerHtml0).to.not.be(innerHtml52); + }); + + it('is rendered the same at different latitudes for degrees', function() { + var ctrl = new ol.control.ScaleLine({ + units: 'degrees' + }); + ctrl.setMap(map); + map.setView(new ol.View({ + center: ol.proj.fromLonLat([7, 0]), + zoom: 2, + projection: 'EPSG:4326' + })); + map.renderSync(); + var innerHtml0 = ctrl.element_.innerHTML; + map.getView().setCenter([7, 52]); + map.renderSync(); + var innerHtml52 = ctrl.element_.innerHTML; + expect(innerHtml0).to.be(innerHtml52); + }); + + }); + describe('zoom affects the scaleline', function() { var currentZoom; var ctrl; diff --git a/test/spec/ol/proj/index.test.js b/test/spec/ol/proj/index.test.js index 200cfddbc0..094795d502 100644 --- a/test/spec/ol/proj/index.test.js +++ b/test/spec/ol/proj/index.test.js @@ -212,6 +212,33 @@ describe('ol.proj', function() { }); + describe('getPointResolution()', function() { + it('returns the correct point resolution for EPSG:4326', function() { + var pointResolution = ol.proj.getPointResolution('EPSG:4326', 1, [0, 0]); + expect (pointResolution).to.be(1); + pointResolution = ol.proj.getPointResolution('EPSG:4326', 1, [0, 52]); + expect (pointResolution).to.be(1); + }); + it('returns the correct point resolution for EPSG:4326 with custom units', function() { + var pointResolution = ol.proj.getPointResolution('EPSG:4326', 1, [0, 0], 'm'); + expect (pointResolution).to.roughlyEqual(111194.874284, 1e-5); + pointResolution = ol.proj.getPointResolution('EPSG:4326', 1, [0, 52], 'm'); + expect (pointResolution).to.roughlyEqual(89826.367538, 1e-5); + }); + it('returns the correct point resolution for EPSG:3857', function() { + var pointResolution = ol.proj.getPointResolution('EPSG:3857', 1, [0, 0]); + expect (pointResolution).to.be(1); + pointResolution = ol.proj.getPointResolution('EPSG:3857', 1, ol.proj.fromLonLat([0, 52])); + expect (pointResolution).to.roughlyEqual(0.615661, 1e-5); + }); + it('returns the correct point resolution for EPSG:3857 with custom units', function() { + var pointResolution = ol.proj.getPointResolution('EPSG:3857', 1, [0, 0], 'degrees'); + expect (pointResolution).to.be(1); + pointResolution = ol.proj.getPointResolution('EPSG:4326', 1, ol.proj.fromLonLat([0, 52]), 'degrees'); + expect (pointResolution).to.be(1); + }); + }); + describe('Proj4js integration', function() { var proj4 = window.proj4;