64 lines
1.4 KiB
Go
64 lines
1.4 KiB
Go
package polylines
|
|
|
|
import (
|
|
"math"
|
|
|
|
"github.com/paulmach/orb"
|
|
)
|
|
|
|
func Decode(encoded *string, precisionOptional ...int) orb.LineString {
|
|
// default to 6 digits of precision
|
|
precision := 6
|
|
if len(precisionOptional) > 0 {
|
|
precision = precisionOptional[0]
|
|
}
|
|
factor := math.Pow10(precision)
|
|
|
|
// Coordinates have variable length when encoded, so just keep
|
|
// track of whether we've hit the end of the string. In each
|
|
// loop iteration, a single coordinate is decoded.
|
|
lat, lng := 0, 0
|
|
var coordinates orb.LineString
|
|
index := 0
|
|
for index < len(*encoded) {
|
|
// Consume varint bits for lat until we run out
|
|
var byte int = 0x20
|
|
shift, result := 0, 0
|
|
for byte >= 0x20 {
|
|
byte = int((*encoded)[index]) - 63
|
|
result |= (byte & 0x1f) << shift
|
|
shift += 5
|
|
index++
|
|
}
|
|
|
|
// check if we need to go negative or not
|
|
if (result & 1) > 0 {
|
|
lat += ^(result >> 1)
|
|
} else {
|
|
lat += result >> 1
|
|
}
|
|
|
|
// Consume varint bits for lng until we run out
|
|
byte = 0x20
|
|
shift, result = 0, 0
|
|
for byte >= 0x20 {
|
|
byte = int((*encoded)[index]) - 63
|
|
result |= (byte & 0x1f) << shift
|
|
shift += 5
|
|
index++
|
|
}
|
|
|
|
// check if we need to go negative or not
|
|
if (result & 1) > 0 {
|
|
lng += ^(result >> 1)
|
|
} else {
|
|
lng += result >> 1
|
|
}
|
|
|
|
// scale the int back to floating point and storeLineString it
|
|
coordinates = append(coordinates, orb.Point{float64(lat) / factor, float64(lng) / factor})
|
|
}
|
|
|
|
return coordinates
|
|
}
|