2023-05-07 23:29:59 +00:00
|
|
|
// Package geoutils provides utility functions to handler geographic calculations such as distance between geometries.
|
2023-03-29 22:45:18 +00:00
|
|
|
package geoutils
|
|
|
|
|
|
|
|
import (
|
|
|
|
"math"
|
|
|
|
|
|
|
|
"github.com/paulmach/orb"
|
|
|
|
"github.com/paulmach/orb/geo"
|
|
|
|
)
|
|
|
|
|
2023-05-07 23:29:59 +00:00
|
|
|
// DistanceFromLineString provides the shorteds distance between a point and a linestring.
|
|
|
|
// It returns the distance in meters, and the index of the closest linestring segment to the point
|
2023-03-29 22:45:18 +00:00
|
|
|
func DistanceFromLineString(point orb.Point, lineString orb.LineString) (distance float64, closestIndex int) {
|
|
|
|
minDistance := math.Inf(1)
|
|
|
|
closest := -1
|
|
|
|
|
|
|
|
for i := 0; i < len(lineString)-1; i++ {
|
|
|
|
a := lineString[i]
|
|
|
|
b := lineString[i+1]
|
|
|
|
pointOnSegment := projectToSegment(point, a, b)
|
|
|
|
dist := geo.Distance(point, pointOnSegment)
|
|
|
|
if dist < minDistance {
|
|
|
|
minDistance = dist
|
|
|
|
closest = i
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-07 23:29:59 +00:00
|
|
|
// log.Debug().
|
|
|
|
// Float64("min distance", minDistance).
|
|
|
|
// Int("index", closest).
|
|
|
|
// Any("point", point).
|
|
|
|
// Msg("minimum distance to polyline")
|
|
|
|
|
2023-03-29 22:45:18 +00:00
|
|
|
return minDistance, closest
|
|
|
|
}
|
|
|
|
|
2023-05-07 23:29:59 +00:00
|
|
|
// projectToSegment projects the point to the segment. This function is used in DistanceFromLineString for point-to-segment distance calculation
|
2023-03-29 22:45:18 +00:00
|
|
|
func projectToSegment(point, a, b orb.Point) orb.Point {
|
|
|
|
x := a[0]
|
|
|
|
y := a[1]
|
|
|
|
dx := b[0] - x
|
|
|
|
dy := b[1] - y
|
|
|
|
|
|
|
|
if dx != 0 || dy != 0 {
|
|
|
|
t := ((point[0]-x)*dx + (point[1]-y)*dy) / (dx*dx + dy*dy)
|
|
|
|
|
|
|
|
if t > 1 {
|
|
|
|
x = b[0]
|
|
|
|
y = b[1]
|
|
|
|
} else if t > 0 {
|
|
|
|
x += dx * t
|
|
|
|
y += dy * t
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return orb.Point{x, y}
|
|
|
|
}
|