routing-service/encoding/polylines/decoding.go

64 lines
1.4 KiB
Go
Raw Normal View History

2023-03-27 18:57:28 +00:00
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
}