Turfjs / turf

A modular geospatial engine written in JavaScript and TypeScript
https://turfjs.org/
MIT License
9.2k stars 934 forks source link

Wrong distance calculated from pointToLineDistance #2270

Open mathildor opened 2 years ago

mathildor commented 2 years ago

Turf version:

6.5.0

Description of issue:

There seems to be a bug in the calculation of the minimum distance from a point to a line in turf. When calculating the length of a line showing the minimum distance between a point and a line I get a different value than when using the pointToLineDistance function.

image

Example illustrating the bug:

https://jsfiddle.net/h8c9pvfa/36/

rowanwins commented 2 years ago

Hi @mathildor

So I think this is a quirk of visualising data in EPSG:3857 (Web Mercator) and the data being in EPSG:4326 (WGS84).

Pulling your data into QGIS and visualising it in WGS84 shows their different trajectory. I also used QGIS to calculate the nearest point and then checked their respective lengths and they are pretty similar to what Turf is generating.

Screen Shot 2022-03-17 at 8 52 24 pm

Hopefully that helps, if so feel free to close this issue :)

mathildor commented 2 years ago

Hi again,

I looked into this a bit further and I'm still confused.

If I use turf. nearestPointOnLine this function also gives 3,4m while turf. pointToLineDistance says 4,3m. As far as I can see in the documentation, these functions should give me the same results?

I updated the jsfiddle to show the two calculations:

https://jsfiddle.net/n5tsq0uy/4/

mathildor commented 2 years ago

Also, won't looking at the data in QGIS in epsg:4326 be misleading when finding the nearest point, since the coordinate-system has different scaling in the x- and y-axis? I think the point you're showing as the nearest point in QGIS is only the point that looks like the closes point in that projection, due to the scaling.

mathildor commented 2 years ago

@rowanwins have you had time to look further into this?

zo0m commented 1 year ago

Faced with the same issue:

const distanceToLine = turf.pointToLineDistance(point, line, distanceOptions);
const distanceToLinePoint = turf.distance(point, turf.nearestPointOnLine(line, point), distanceOptions);

I expected that these distances should be the same. turf.pointToLineDistance - returns the wrong value

wchargin commented 2 weeks ago

This is still broken in v7.0.0. I tested by creating a line at a given heading, projecting a point a small distance away from one of the endpoints perpendicular to the line, and comparing "distance to endpoint" with "distance to line". The error is effectively zero sometimes, but approaches 2% in my testing, varying continuously with the heading of the line:

Plot of error as a function of heading

Script: https://gist.github.com/wchargin/d673b48b8accf3027d47e644c4f7dddf

Here is a simple single example, for which PostGIS 3.4.2 (GEOS 3.12.1) says that the distance from point to line is 1000.26m but Turf says that it is 1017.6m:

$ cat test.sql
SELECT ST_Distance(
    ST_GeomFromGeoJSON('{"type":"Point","coordinates":[11.991689565382663,34.00578044047174]}')::geography,
    ST_GeomFromGeoJSON('{"type":"LineString","coordinates":[[12,34],[11.993027757380355,33.99311060965808]]}')::geography
);
$ psql -tf test.sql
 1000.26221222

Data: https://gist.github.com/wchargin/94c4be94b525fdb6ea022fcca4d6894d

(This datum was generated by asking Turf to give me a point that's 1000m off the line, so PostGIS seems more likely correct here.)

I do also find that this patch reduces the max error in my tests from 1.7e−2 to 1.5e−9, an improvement of roughly ten million times:

-  const lineDistance = turf.pointToLineDistance(target, line);
+  const lineDistance = turf.nearestPointOnLine(line, target).properties.dist;

Could pointToLineDistance be made to just call nearestPointOnLine, since that seems more accurate?