Search code examples
leafletmeasure

How to measure distance in crs.simple?


I have a non-geographic map aka flat image using CRS.Simple extended by a custom transformation. Everything works fine so far, but now I want to add a distance measurement button. I'm confident I could implement a distance measurement between two markers myself, but the dynamic line drawing and measuring is still a bit above my skills, so I hoped I could use a plugin. None of the ones I found, did offer this though. After looking at the plugins page of leaflet, I tried this fork https://github.com/aprilandjan/leaflet.measure of leaflet.measure originally by https://github.com/jtreml/leaflet.measure as it seemed to offer the ability to add custom units - in my case pixels.

I added this:

L.control.measure({
    //  distance formatter, output mile instead of km
    formatDistance: function (val) {
      return Math.round(1000 * val / scaleFactor) / 1000 + 'mapUnits';
    }
  }).addTo(map)

Unfortunately, the result is a number far too big compared to the pixelsize of the map (4096x4096). distance() returns the expected 1414.213562373095 between a point 1000,1000 and one at 2000,2000. Calculating distanctTo returns 8009572.105082839 instead though. I use this at the beginning of my file

var yx = L.latLng;
var xy = function(x, y) {
  if (L.Util.isArray(x)) { // When doing xy([x, y]);
    return yx(x[1], x[0]);
  }
  return yx(y, x); // When doing xy(x, y);
};

If I log val to the console, I get things like this:

20411385.176805027
7118674.47741132
20409736.502863288
7117025.8034695815
20409186.004645467
20409736.502863288

That's likely some problem of the function trying to calculate latlng without a proper reference system. Anyone got an idea how to solve this? I feel like it can't be overly difficult, but I don't know exactly where to start.


Solution

  • I found a way to do it, even though it feels a bit 'hacky': I replaced the line

    var distance = e.latlng.distanceTo(this._lastPoint)
    

    in the _mouseMove and the _mouseClick events of leaflet.measure with

      var currentPoint = e.latlng;                                                      
      var lastPoint = this._lastPoint;
      var distance = map.distance(currentPoint, lastPoint); 
    

    as the distance() method of the map returns meters, or in the case of a flat image, pixel values. And those we can translate in whatever unit we want in our flat image.

    If anyone has a more elegant way, I'm all ears!