|
encodeGString.orx
|
|
/* ---------------------------------------------------------------- */
/* Encodes a Google PolyLine string from 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): */
/* */
/* A series of latitude/longitude pairs separated by at least */
/* 1 space, either via: */
/* stdin - if invoked as a command */
/* or: */
/* an Array if invoked as a function/subroutine. */
/* */
/* Result: */
/* */
/* If invoked as a command encoded string to stdout, */
/* if invoked as a function the encoded string is return value. */
/* */
/* ---------------------------------------------------------------- */
/* 2013/12/13 - Initial version */
/* ---------------------------------------------------------------- */
--::routine encodeGString
parse source os how me
if (how="COMMAND") then do
item = .input~supplier
end
else do
use strict arg thePath
if thePath~class~id<>"Array" then do
raise syntax 40.912 array("encodeGString",1,thePath~class~id)
end
item = thePath~supplier
end
numeric digits 20
prevLat = 0
prevLon = 0
encodedGString = ''
do while item~available
parse value(item~item) with lat lon .
-- no checking on valid range, maybe later if necessary
deltaLat = lat-prevLat
deltaLon = lon-prevLon
prevLat = lat
prevLon = lon
encodedGString = encodedGString || encodeDegrees(deltaLat)
encodedGString = encodedGString || encodeDegrees(deltaLon)
item~next
end
if how="COMMAND"
then say encodedGString
else return encodedGString
exit
encodeDegrees: Procedure
parse arg degrees
-- take the inital signed value, multiply by 1e5 and round the result
tmpString = (degrees*1e5)~format(,0)
-- convert to binary, left shift 1 position for sign bit
tmpString = (tmpString*2)~d2c(4)
-- if original was negative invert what we have
if degrees<0 then tmpString = tmpString~bitxor('ffffffff'x)
-- break this binary value out in 5 bit chunks from the right
-- and place them in reverse order
tmpString = tmpString~c2d
tmpWords = ''
do while tmpString>0
tmpWords = tmpWords (tmpString//32)~d2c(1)
tmpString = tmpString%32
end
-- OR each chunk with '20'x except the last, to indicate end of number
-- convert each chunk to decimal, add 63, concatenate into ascii string
encodedDegrees = ''
do i=1 to tmpWords~words-1
encodedDegrees = encodedDegrees || (tmpWords~word(i)~bitor('20'x)~c2d+63)~d2c
end
encodedDegrees = encodedDegrees || (tmpWords~word(i)~c2d+63)~d2c
return encodedDegrees
If you feel inclined to make corrections, suggestions etc.,
please mail me any.
| |
All content © Ruurd Idenburg, 2007–2023,
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 Fri, 07 May 2021 12:15:43 +0200 by Ruurd Idenburg.
|
|