urschrei / pypolyline

Fast Google Polyline encoding and decoding using a Rust binary
https://pypi.python.org/pypi/pypolyline
Other
40 stars 2 forks source link

Support for lon,lat in addition to lat,lon? #2

Open si-the-pie opened 5 years ago

si-the-pie commented 5 years ago

How about also supporting co-ordinate lists that are represented as longitude, latitude?

These are handled by the other polyline package:

>>> import polyline
>>> # Lat,Lon
... polyline.encode([(50, 100)])
'_sdpH_gjaR'

>>> # Lon,Lat
... polyline.encode([(100, 50)])
'_gjaR_sdpH'

>>> from pypolyline.util import encode_coordinates
>>> # Lat,Lon
... encode_coordinates([[50, 100]], 5)
b'_sdpH_gjaR'

>>> # Lon,Lat
... encode_coordinates([[100, 50]], 5)
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "/home/simon/.local/lib/python3.6/site-packages/pypolyline/util.py", line 133, in _void_array_to_string
    "%s. Latitudes must be between -90.0 and 90.0" % polyline)
pypolyline.util.EncodingError: b'Latitude error at position 0: 100'. Latitudes must be between -90.0 and 90.0
urschrei commented 5 years ago

It would have to be an API addition with explicit lat, lon and lon, lat methods, while retaining the original, as I don't want to have to try / guess the input order if coordinates are out of bounds. Happy to accept a PR.

captchanjack commented 2 years ago

I'm seeing some weirdness with the lon, lat API.

Encodes and decodes fine with pypolyline, however I have a requirement where decoding happens in the browser and testing with input lon, lat to pypolyline yields an encoded string that decodes as lat,lon in nodejs.

For example if we use the example from google's docs

test = [[-120.2, 38.5], [-120.95, 40.7], [-126.453, 43.252]]

and encode with pypolyline

from pypolyline.cutil import encode_coordinates, decode_polyline
encode_coordinates(test, 5).decode()  # '_p~iF~ps|U_ulLnnqC_mqNvxq`@'

decoding with any other python/nodejs package e.g. polyline (python) or mapbox's polyline npm package yields the reverse (i.e. lat, lon)

var polyline = require('@mapbox/polyline');
polyline.decode('_p~iF~ps|U_ulLnnqC_mqNvxq`@');  // [[38.5, -120.2], [40.7, -120.95], [43.252, -126.453]]

I know it's fairly easy to switch the decoded coordinates around, but I would expect the API to yield an encoded string that decodes as the exact input (with some precision) using any other polyline package, given they are all following google's algorithm.

Appreciate the work you put into this though! It's really fast compared other packages in python that's for sure.

I don't know any rust so I won't be able to put in a PR for the rust binary. Wondering if you or anyone else in the community can help!

Cheers!

urschrei commented 2 years ago

testing with input lon, lat to pypolyline yields an encoded string that decodes as lat,lon in nodejs.

The Google Polyline spec requires lat, lon input order and output order (and in fact the EPSG 4326 projection does too), so if you give it input in reversed coordinates you'll get either an incorrect (but valid) string as output, or an error (if either of the input coordinates are out of bounds)

For example if we use the example from google's docs

But that isn't the example from Google's docs. The coordinates have been reversed – they're no longer valid EPGSG 4326 coordinates OR Polyline input coordinates as per its spec.

As I said in the previous comment, there's no way to reliably detect the order of input coordinates; e.g. (80.0, 10.0) is valid input in both cases. I'm happy to accept a PR that adds new methods with specified input order – that's all Python anyway, no Rust knowledge required.