2023-03-27 18:57:28 +00:00
|
|
|
package polylines
|
|
|
|
|
|
|
|
import (
|
|
|
|
"github.com/paulmach/orb"
|
|
|
|
"github.com/twpayne/go-polyline"
|
|
|
|
)
|
|
|
|
|
2023-03-29 22:45:55 +00:00
|
|
|
// // Encode encodes coordinates to the "Encoded Polyline Algorithm Format"
|
|
|
|
// // More info: https://developers.google.com/maps/documentation/utilities/polylinealgorithm
|
|
|
|
// // points: points of the polyline
|
|
|
|
// // precision: usually 5 or 6; Google's original algorithm uses 5 digits of decimal precision,
|
|
|
|
// // which is accurate to about a meter. A precision of 6 gives you an accuracy of about 10cm
|
|
|
|
// // more info: https://mapzen.com/blog/polyline-precision/
|
|
|
|
// func Encode(linestring orb.LineString, precision uint32) string {
|
|
|
|
|
|
|
|
// encoded := ""
|
|
|
|
|
|
|
|
// latitude := 0.0
|
|
|
|
// longitude := 0.0
|
|
|
|
|
|
|
|
// for _, point := range linestring {
|
|
|
|
// polyLatitude := encodeElement(point.Lat()-latitude, precision)
|
|
|
|
// encoded += polyLatitude
|
|
|
|
|
|
|
|
// polyLongitude := encodeElement(point.Lon()-longitude, precision)
|
|
|
|
// encoded += polyLongitude
|
|
|
|
|
|
|
|
// // to conserve space, points only include the offset from the previous point
|
|
|
|
// latitude = point.Lat()
|
|
|
|
// longitude = point.Lon()
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// return encoded
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// // Encode5 is a short call for Encode with precision set to 5
|
|
|
|
// // Accuracy is about one meter
|
|
|
|
// func Encode5(linestring orb.LineString) string {
|
|
|
|
// return Encode(linestring, 5)
|
|
|
|
// }
|
|
|
|
|
|
|
|
// // Encode6 is a short call for Encode with precision set to 6
|
|
|
|
// // Accuracy is about ten centimeters
|
|
|
|
// func Encode6(linestring orb.LineString) string {
|
|
|
|
// return Encode(linestring, 6)
|
|
|
|
// }
|
|
|
|
|
|
|
|
// // encodeElement encodes an coordinate element (i.e. latitude or longitude)
|
|
|
|
// // to the "Encoded Polyline Algorithm Format"
|
|
|
|
// func encodeElement(element float64, precision uint32) string {
|
|
|
|
|
|
|
|
// elementInt := int32(math.Round(element * math.Pow10(int(precision))))
|
|
|
|
// elementInt = elementInt << 1
|
|
|
|
// if element < 0 {
|
|
|
|
// elementInt = ^elementInt
|
|
|
|
// }
|
|
|
|
|
|
|
|
// var c chunks
|
|
|
|
// c.Parse(elementInt)
|
|
|
|
|
|
|
|
// return c.String()
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// // round n to precision digits
|
|
|
|
// func round(n float64, precision uint32) float64 {
|
|
|
|
|
|
|
|
// factor := math.Pow10(int(precision))
|
|
|
|
// return math.Round(n*factor) / factor
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
func Encode(line orb.LineString, precision uint32) string {
|
2023-03-27 18:57:28 +00:00
|
|
|
|
|
|
|
preparedLine := [][]float64{}
|
|
|
|
|
|
|
|
for _, point := range line {
|
2023-03-29 22:45:55 +00:00
|
|
|
preparedLine = append(preparedLine, []float64{point.Lat(), point.Lon()})
|
2023-03-27 18:57:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return string(polyline.EncodeCoords(preparedLine))
|
|
|
|
}
|