diff --git a/examples/wms-no-proj.js b/examples/wms-no-proj.js index d0692a6455..578dfdd7eb 100644 --- a/examples/wms-no-proj.js +++ b/examples/wms-no-proj.js @@ -4,6 +4,7 @@ import Projection from '../src/ol/proj/Projection.js'; import TileWMS from '../src/ol/source/TileWMS.js'; import View from '../src/ol/View.js'; import {Image as ImageLayer, Tile as TileLayer} from '../src/ol/layer.js'; +import {ScaleLine, defaults as defaultControls} from '../src/ol/control.js'; const layers = [ new TileLayer({ @@ -37,12 +38,18 @@ const layers = [ // projection object. Requesting tiles only needs the code together with a // tile grid of Cartesian coordinates; it does not matter how those // coordinates relate to latitude or longitude. +// +// With no transforms available projection units must be assumed to represent +// true distances. In the case of local projections this may be a sufficiently +// close approximation for a meaningful (if not 100% accurate) ScaleLine control. + const projection = new Projection({ code: 'EPSG:21781', units: 'm', }); const map = new Map({ + controls: defaultControls().extend([new ScaleLine()]), layers: layers, target: 'map', view: new View({ diff --git a/src/ol/proj.js b/src/ol/proj.js index 9d59af3dc0..c508ef754e 100644 --- a/src/ol/proj.js +++ b/src/ol/proj.js @@ -212,20 +212,25 @@ export function getPointResolution(projection, resolution, point, opt_units) { projection, get('EPSG:4326') ); - let 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); - const width = getDistance(vertices.slice(0, 2), vertices.slice(2, 4)); - const height = getDistance(vertices.slice(4, 6), vertices.slice(6, 8)); - pointResolution = (width + height) / 2; + if (toEPSG4326 === identityTransform && units !== Units.DEGREES) { + // no transform is available + pointResolution = resolution * projection.getMetersPerUnit(); + } else { + let 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); + const width = getDistance(vertices.slice(0, 2), vertices.slice(2, 4)); + const height = getDistance(vertices.slice(4, 6), vertices.slice(6, 8)); + pointResolution = (width + height) / 2; + } const metersPerUnit = opt_units ? METERS_PER_UNIT[opt_units] : projection.getMetersPerUnit(); diff --git a/test/spec/ol/proj.test.js b/test/spec/ol/proj.test.js index c98c90c036..eb0b9f7feb 100644 --- a/test/spec/ol/proj.test.js +++ b/test/spec/ol/proj.test.js @@ -410,6 +410,16 @@ describe('ol.proj', function () { ); expect(pointResolution).to.be(1); }); + it('returns the nominal resolution for projections without transforms', function () { + const projection = new Projection({ + code: 'foo', + units: 'ft', + }); + let pointResolution = getPointResolution(projection, 2, [0, 0]); + expect(pointResolution).to.be(2); + pointResolution = getPointResolution(projection, 2, [0, 0], 'm'); + expect(pointResolution).to.be(0.6096); + }); }); describe('Proj4js integration', function () {