heremaps / flexible-polyline

Flexible Polyline encoding: a lossy compressed representation of a list of coordinate pairs or triples
MIT License
89 stars 76 forks source link

dart: Flutter web gives completely wrong results when decoding polyline #26

Open cedrichansen opened 3 years ago

cedrichansen commented 3 years ago

Decoding polylines on flutter web is completely wrong.

Using the provided example from https://pub.dev/packages/flexible_polyline, running on android works just fine and prints out the expected results

List<LatLngZ> decoded = FlexiblePolyline.decode("BFoz5xJ67i1B1B7PzIhaxL7Y");

results in the following on android/ios


 LatLngZ [lat=50.10228, lng=8.69821, z=0.0]
 LatLngZ [lat=50.10201, lng=8.69567, z=0.0]
 LatLngZ [lat=50.10063, lng=8.6915, z=0.0]
 LatLngZ [lat=50.09878, lng=8.68752, z=0.0]

But running the exact same code with flutter web gives the following:

LatLngZ [lat=50.10228, lng=8.69821, z=0]
LatLngZ [lat=21524.93849, lng=21483.53215, z=0]
LatLngZ [lat=42999.77359, lng=42958.36446, z=0]
LatLngZ [lat=64474.60822, lng=64433.19696, z=0]

The first address is correct, but subsequent addresses 2-4 are very large If there are any additional params/options available that fix the decoding scheme based on web vs mobile, that would be an acceptable workaround until a better solution can be found

ichsan210 commented 2 years ago

i have same issue, is the problem have fix?

cedrichansen commented 2 years ago

I have not found a fix using this package. I have switched to a completely different method, specifically, calling a server of mine which is responsible for getting directions/polyline, using google maps, and communicating that result via http. Not my favourite work around, but it works well for my use case

VeaaC commented 2 years ago

Sounds a bit like https://github.com/heremaps/flexible-polyline/issues/52

moo24 commented 3 months ago

In Java:

long: The long data type is a 64-bit two's complement integer. The signed long has a minimum value of -2^63 and a maximum value of 2^63-1. In Java SE 8 and later, you can use the long data type to represent an unsigned 64-bit long, which has a minimum value of 0 and a maximum value of 2^64-1. Use this data type when you need a range of values wider than those provided by int. The Long class also contains methods like compareUnsigned, divideUnsigned etc to support arithmetic operations for unsigned long.

In Dart:

int Integer values no larger than 64 bits, depending on the platform. On the Dart VM, values can be from -2^63 to 2^63 - 1. **Dart that’s compiled to JavaScript uses JavaScript numbers, allowing values from -2^53 to 2^53 - 1.**

The Dart Lib uses int in Dart for the equivalent of long in Java in https://github.com/heremaps/flexible-polyline/blob/master/dart/lib/converter.dart#L84 The issue is caused by Dart itself - as when code is compiled to JavaScript it loses Precision. You need to use precision 5 or need to use the JavaScript lib (Gist with BigInt lib) for decoding instead as recommended here: https://github.com/heremaps/flexible-polyline/issues/52#issuecomment-984941759

VeaaC commented 3 months ago

Theoretically a base-10 big-int would be relatively easy to implement, since the only operations needed are:

At precision 15 we need log2(360 * 10^15) + 1 = 60 bits. That means that if you were to use Dart's 53 bit type only 2 variables are enough. You could e.g. work with 10^9 per variable (31 bits if signed). Addition would only need to take care of the carry (there's enough space to avoid overflow), and division by a power of ten shifts down the remainder (the equivalent of a bit-shift in base-2).

This approach could work for JS as well, and might be noticeably faster than base-2 BigInteger generic size BigInt library.

What do you think @moo24 / @haifeng2013 ?