d2/lib/geo/route.go

64 lines
1.3 KiB
Go
Raw Permalink Normal View History

package geo
import (
"math"
)
type Route []*Point
func (route Route) Length() float64 {
l := 0.
for i := 0; i < len(route)-1; i++ {
l += EuclideanDistance(
route[i].X, route[i].Y,
route[i+1].X, route[i+1].Y,
)
}
return l
}
// return the point at _distance_ along the route, and the index of the segment it's on
func (route Route) GetPointAtDistance(distance float64) (*Point, int) {
remaining := distance
2023-05-01 20:18:50 +00:00
var curr, next *Point
var length float64
for i := 0; i < len(route)-1; i++ {
2023-05-01 20:18:50 +00:00
curr, next = route[i], route[i+1]
length = EuclideanDistance(curr.X, curr.Y, next.X, next.Y)
if remaining <= length {
t := remaining / length
// point t% of the way between curr and next
2023-05-01 20:18:50 +00:00
return curr.Interpolate(next, t), i
}
remaining -= length
}
2023-05-01 20:18:50 +00:00
// distance > length, so continue with last segment
// Note: distance < 0 handled above with first segment
return curr.Interpolate(next, 1+remaining/length), len(route) - 2
}
func (route Route) GetBoundingBox() (tl, br *Point) {
minX := math.Inf(1)
minY := math.Inf(1)
maxX := math.Inf(-1)
maxY := math.Inf(-1)
for _, p := range route {
if p.X < minX {
minX = p.X
}
if p.X > maxX {
maxX = p.X
}
if p.Y < minY {
minY = p.Y
}
if p.Y > maxY {
maxY = p.Y
}
}
return NewPoint(minX, minY), NewPoint(maxX, maxY)
}