Is there any way we can calculate the scale ratio using L.CRS.scale
?
Using L.CRS.scale
for that kind of calculation is cumbersome and most probably unreliable in the end. The result of L.CRS.scale()
has to be multiplied by a CRS-dependant constant (the world bounds according to that CRS) in order to make the numbers meaningful, which IMO leads to confusion. As explained elsewhere, the implementation of L.CRS
is geared towards quickly displaying things on a screen, and not towards an abstract GIS understanding of CRSs.
Instead, I suggest doing as L.Control.Scale
does: calculate the distance in meters between two points at known places in the screen, with a known distance in pixels between them.
The relevant code from L.Control.Scale
I'm referring to is
var y = map.getSize().y / 2;
var maxMeters = map.distance(
map.containerPointToLatLng([0, y]),
map.containerPointToLatLng([this.options.maxWidth, y]));
That calculates the distance in map meters between two points in a horizontal line in the middle of the map, measuring this.options.maxWidth
CSS pixels wide.
So if you're assuming 96 DPI, that means (after a tiny bit of math) a centimeter is 38 pixels. So if you replace this.options.maxWidth
with 38
in the aforementioned code, you'll end up with the amount of map meters that correspond to a screen centimeter. Deriving a scale factor from those numbers is trivial.
This approach has the advantage of not needing any constants from the CRS definition, since the distance()
function does the heavy lifting for you.
This approach has the disadvantage of a varying scale factor for the same zoom level (which might in fact be desireable if the projection distorts lengths). This can be worked around by replacing the implementation of L.CRS.distance
with a cartesian distance of projected coordinates implementation.