|
echo $fn ?>
|
|
#!/usr/bin/env rexx
/* ---------------------------------------------------------------- */
/* Decodes a Google encoded PolyLine string into latitude/longitude */
/* pairs */
/* ---------------------------------------------------------------- */
/* */
/* Originally by Ruurd J. Idenburg */
/* */
/* No copyright, no licence, no guarantees or warrantees, be it */
/* explicit, implicit or whatever. Usage is totally and completely */
/* at the users own risk, the author shall not be liable for any */
/* damages whatsoever, for any reason whatsoever. */
/* */
/* Please keep this comment block intact when modifying this code */
/* and add a note with date and a description. */
/* */
/* ---------------------------------------------------------------- */
/* Parameter(s): */
/* */
/* encodedPolyline - a polyline encoded in Google format. */
/* e.g. "_p~iF~ps|U_ulLnnqC_mqNvxq`@" */
/* */
/* Result: */
/* */
/* If invoked as a command latitude/longitude pairs to stdout, */
/* if invoked as a function latitude/longitude pairs into array. */
/* */
/* ---------------------------------------------------------------- */
/* 2013/12/13 - Initial version */
/* 2014/10/15 - Improved deltalatitude/deltalongitude to prevent */
/* noticeable deviations in long encoded polylines */
/* 2021/05/20 - Added hashbang #!/usr/bin/env rexx */
/* ---------------------------------------------------------------- */
--::routine decodeGString public
parse source os how me
if how=="FUNCTION" then myResult = .array~new()
numeric digits 20
parse arg encPoly
-- get rid of surrounding spaces
encPoly = encPoly~space(0)
-- get rid of surrounding quotes
if (encPoly~pos('"')=1 & encPoly~lastpos('"')=encPoly~length) then encPoly = encPoly~strip('B','"')
if (encPoly~pos("'")=1 & encPoly~lastpos("'")=encPoly~length) then encPoly = encPoly~strip('B',"'")
-- get rid of possibly escaped backslashes, may be needed in some cases
-- where the backslash is used as an escape character, e.g. javascript(?) strings
-- setup latitude and longitude
latitude = 0
longitude = 0
-- first position in encoded string
i = 1
do until i>=encPoly~length
-- first the latitude
result = '00000000'x
byte = 32
do j=1 by 1 while (byte>=32)
-- Convert each character to it's decimal value minus 63
byte = encPoly~subchar(i)~c2d-63
-- bitwise AND byte with '1F'x then shift left 5*(j-1) (i.e. multiply by 32**(j-1)
-- and OR into 4 byte result. That is: 5 bit chunks concatenated in reverse order.
-- The opposite of the encoding steps.
result = ((byte//32)*(32**(j-1)))~d2c(4)~bitor(result)
-- increment position in encoded string
i += 1
end
-- encoding used 2's complement for negative values
-- if sign bit is not 0 then result should be negative
if result~bitand('00000001'x)~c2d\=0
then deltalatitude = -(result~c2d/2)~format(,0)/1e5
else deltalatitude = (result~c2d/2)~format(,0)/1e5
/*
if result~bitand('00000001'x)~c2d\=0
then testlatitude = latitude - ((result~c2d/2)~format(,0)/1e5)
else testlatitude = latitude + ((result~c2d/2)~format(,0)/1e5)
*/
latitude += deltalatitude
-- now the longitude
result = '00000000'x
byte = 32
do j=1 by 1 while (byte>=32)
-- Convert each character to it's decimal value minus 63
byte = (encPoly~subchar(i)~c2d-63)
-- bitwise AND byte with '1F'x then shift left 5*(j-1) (i.e. multiply by 32**(j-1)
-- and OR into 4 byte result
result = ((byte//32)*(32**(j-1)))~d2c(4)~bitor(result)
-- increment position in encoded string
i += 1
end
-- if sign bit is not 0 then result should be negative
if result~bitand('00000001'x)~c2d\=0
then deltalongitude = -(result~c2d/2)~format(,0)/1e5
else deltalongitude = (result~c2d/2)~format(,0)/1e5
/*
if result~bitand('00000001'x)~c2d\=0
then testlongitude = longitude - (result~c2d/2)~format(,0)/1e5
else testlongitude = longitude + (result~c2d/2)~format(,0)/1e5
*/
longitude += deltalongitude
if how=="COMMAND"
then say latitude longitude
else myResult~append(latitude longitude)
end
if how=="FUNCTION" then return myResult
If you feel inclined to make corrections, suggestions etc.,
please mail me any.
| |
All content © Ruurd Idenburg, 2007– echo date('Y');?>,
except where marked otherwise. All rights reserved. This page is primarily for non-commercial use only.
The Idenburg website records no personal information and sets no ‘cookies’.
This site is hosted on a VPS(Virtual Private System) rented from Transip.nl, a Dutch company, falling under Dutch (privacy) laws (I think).
This page updated on echo date("r", filemtime("./index.php"));?> by Ruurd Idenburg.
|
|