geolib icon indicating copy to clipboard operation
geolib copied to clipboard

getDistanceSimple() returns NaN with specific parameters

Open emcsween opened this issue 7 years ago • 12 comments

Not sure if it's the near equal longitudes, but this call returns NaN:

geolib.getDistanceSimple({latitude: 43.647862 , longitude: -79.39290290000002}, {latitude: 43.647862, longitude: -79.392903})

emcsween avatar Apr 06 '17 13:04 emcsween

Same here. @manuelbieh the docs say its always a number I have more than 1.000 samples that validate that it returns NAN.

jimmykane avatar Jun 27 '17 19:06 jimmykane

Oh, that's weird. I'll investigate on this.

manuelbieh avatar Jun 27 '17 19:06 manuelbieh

@manuelbieh thanks a lot for your time 👍 ! Nice library and project.

jimmykane avatar Jun 27 '17 20:06 jimmykane

This issue still exists and I have no clue why. I'll buy ice cream for whoever solves this.

manuelbieh avatar May 13 '19 00:05 manuelbieh

I see it works normally. Tell me what wrong?

quocbaovu15101996 avatar May 27 '19 02:05 quocbaovu15101996

This issue still exists and I have no clue why. I'll buy ice cream for whoever solves this.

I just ran into this myself and I think I figured it out. It's an issue with floating point arithmetic when attempting to call getDistance() on two points that are the same or very close to the same point.

I have an app that records the user's path travelled over time, and sometimes the location is fixed for a short period leading to getDistance() being called on two copies of the same coordinate pair. The expected behavior is that getDistance() should return 0, which it does in most situations. But for certain coordinate pairs, e.g. { latitude: 38.95826, longitude: -77.44167 }, the getDistance() formula

const distance =
        Math.acos(
            Math.sin(toRad(toLat)) * Math.sin(toRad(fromLat)) +
                Math.cos(toRad(toLat)) *
                    Math.cos(toRad(fromLat)) *
                    Math.cos(toRad(fromLon) - toRad(toLon))
        ) * earthRadius;

will evaluate to Math.acos(1.0000000000000002) instead of Math.acos(1) due to floating point arithmetic and will return NaN as a result.

This leads to getPathLength() also returning NaN if the array of points contains these coordinate pairs in sequence.

I think adding a Math.min(1,x) check to the distance formula should fix it:

const distance =
        Math.acos(Math.min(1,
            Math.sin(toRad(toLat)) * Math.sin(toRad(fromLat)) +
                Math.cos(toRad(toLat)) *
                    Math.cos(toRad(fromLat)) *
                    Math.cos(toRad(fromLon) - toRad(toLon))
        )) * earthRadius;

projectpublius avatar May 31 '19 17:05 projectpublius

Oh! That is a great catch !

On Fri, May 31, 2019 at 7:27 PM Jeff [email protected] wrote:

This issue still exists and I have no clue why. I'll buy ice cream for whoever solves this.

I just ran into this myself and I think I figured it out. It's an issue with floating point arithmetic when attempting to call getDistance() on two points that are the same or very close to the same point.

I have an app that records the user's path travelled over time, and sometimes the location is fixed for a short period leading to getDistance() being called on two copies of the same coordinate pair. The expected behavior is that getDistance() should return 0, which it does in most situations. But for certain coordinate pairs, e.g. { latitude: 38.95826, longitude: -77.44167 }, the getDistance() formula

const distance = Math.acos( Math.sin(toRad(toLat)) * Math.sin(toRad(fromLat)) + Math.cos(toRad(toLat)) * Math.cos(toRad(fromLat)) * Math.cos(toRad(fromLon) - toRad(toLon)) ) * earthRadius;

will evaluate to Math.acos(1.0000000000000002) instead of Math.acos(1) due to floating point arithmetic and will return NaN as a result.

This leads to getPathLength() also returning NaN if the array of points contains these coordinate pairs in sequence.

A simple fix would be to add a Math.min(1,x) check to the distance formula:

const distance = Math.acos(Math.min(1, Math.sin(toRad(toLat)) * Math.sin(toRad(fromLat)) + Math.cos(toRad(toLat)) * Math.cos(toRad(fromLat)) * Math.cos(toRad(fromLon) - toRad(toLon)) )) * earthRadius;

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/manuelbieh/geolib/issues/129?email_source=notifications&email_token=AAJVX4ZWY7V4VYXVJSWXNGLPYFNX7A5CNFSM4DGWROQKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODWV3X2I#issuecomment-497794025, or mute the thread https://github.com/notifications/unsubscribe-auth/AAJVX44JXK35JHBYK6M7BFDPYFNX7ANCNFSM4DGWROQA .

jimmykane avatar May 31 '19 18:05 jimmykane

Has anyone resolved the "getDistanceFromLine is returning NaN" issue? Are these two issues related?

MajcenT avatar Mar 06 '20 13:03 MajcenT

I don't encounter this anymore

On Fri, 6 Mar 2020, 14:15 MajcenT, [email protected] wrote:

Has anyone resolved the "getDistanceFromLine is returning NaN" issue? Are these two issues related?

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/manuelbieh/geolib/issues/129?email_source=notifications&email_token=AAJVX44J7SJI7JZGDP2XSYTRGDZOHA5CNFSM4DGWROQKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEOBJZ4I#issuecomment-595762417, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAJVX46LLKB2NPZK3H4RB2DRGDZOHANCNFSM4DGWROQA .

jimmykane avatar Mar 06 '20 15:03 jimmykane

This should have been solved by adding a normalizeCosArg helper. Re-open if the error still occurs.

manuelbieh avatar May 24 '20 10:05 manuelbieh

I still encounter NaN values for these coordinates on [email protected]. Note that the supplied point is almost identical as the supplied lineStart.

Edit: Ah, I see you fixed this in 3.3.2. Geolib@latest on npm is still 3.3.1 though.

geolib.getDistanceFromLine({
  latitude: 53.0281161107639,
  longitude: 5.64420448614743,
}, {
  latitude: 53.028118,
  longitude: 5.644203,
}, {
  latitude: 53.029021,
  longitude: 5.646562,
})

geolib.getDistanceFromLine({
  latitude: 53.0515182362456,
  longitude: 5.67842625473533,
}, {
  latitude: 53.051521,
  longitude: 5.678421,
}, {
  latitude: 53.051652,
  longitude: 5.67852,
})

geolib.getDistanceFromLine({
  latitude: 53.0933224175307,
  longitude: 5.61011575344944,
}, {
  latitude: 53.093321,
  longitude: 5.610115,
}, {
  latitude: 53.093236,
  longitude: 5.610037,
})

geolib.getDistanceFromLine({
  latitude: 53.0867058030163,
  longitude: 5.59876618900706,
}, {
  latitude: 53.086705,
  longitude: 5.598759,
}, {
  latitude: 53.085538,
  longitude: 5.597901,
})

geolib.getDistanceFromLine({
  latitude: 53.0657207151762,
  longitude: 5.60056383087291,
}, {
  latitude: 53.065721,
  longitude: 5.600568,
}, {
  latitude: 53.062609,
  longitude: 5.600793,
})

casperkloppenburg avatar Jun 06 '20 10:06 casperkloppenburg

Encountered this issue with 3.3.4 as well. See https://github.com/manuelbieh/geolib/pull/304 for faulty scenarios and fix. Fix found by @redcic75

timvahlbrock avatar Dec 10 '23 12:12 timvahlbrock