James Jarvis
James Jarvis

Reputation: 21

how to get an accurate length of a features that may be a LineString or MultiLineString of LatLng coordinates?

Using leafletjs map.distance() function, I consistently get a value that is ~40% over what it should be. Is this because I am a latitude of 56˚N?

Using Overpass Turbo, I get an OpenStreetMap export of hiking routes near a point, saving as GEOjson and reading.

('(rel(around:8000,56.56492, -3.58553)['route'='hiking'];);out geom;')

For some routes, the geometry is a LineString, for others it is a MultiLineString. Within a L.GEOjson onEachFeature function I have:

var length = 0
if ( feature.geometry.type == "MultiLineString" ) { 
  for ( var i = 0; i < (feature.geometry.coordinates.length); i++ ) {
    var thisLineString=feature.geometry.coordinates[i];
    for ( var j = 0; j < (thisLineString.length - 1); j++ ) {
    length = length + map.distance(thisLineString[j],thisLineString[j+1]) ;
  }
} else {
  if ( feature.geometry.type == "LineString" ) {
    for ( var i = 0; i < (feature.geometry.coordinates.length-1); i++ ) {
      length = length + map.distance(feature.geometry.coordinates[i],feature.geometry.coordinates[i+1]) ;
    }
  }
}

The leaflet function map.distance() returns values in metres.

Most of the results are too great by ~ 40% when compared with other map systems or the time it takes to walk/run the routes!

Upvotes: 2

Views: 58

Answers (1)

ghybs
ghybs

Reputation: 53290

Leaflet methods take LatLng coordinates, i.e. with order [latitude, longitude].

Whereas GeoJSON coordinates have order [longitude, latitude].

See also https://macwright.org/lonlat/

Therefore you have to swap their coordinates before passing them to map.distance(), e.g.:

function lngLat2latLng(lngLatCoordinates) {
  const latLng = [
    lngLatCoordinates[1], // latitude
    lngLatCoordinates[0], // longitude
  ];
  // Just in case there is also optional altitude
  if (lngLatCoordinates.length > 2) {
    latLng.push(lngLatCoordinates[2];
  }
  return latLng;
}

// usage
length += map.distance(
  // Swap coordinates from GeoJSON lngLat
  // to Leaflet latLng order
  lngLat2latLng(thisLineString[j]),
  lngLat2latLng(thisLineString[j+1]),
) ;

Upvotes: 1

Related Questions