From ae6618a195500e9e74689ff594183158ec215bda Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Mon, 1 May 2023 13:18:50 -0700 Subject: [PATCH] update get point at distance --- lib/geo/point.go | 8 ++++++++ lib/geo/route.go | 15 ++++++++------- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/lib/geo/point.go b/lib/geo/point.go index dd8508b61..18a4ba8c7 100644 --- a/lib/geo/point.go +++ b/lib/geo/point.go @@ -287,3 +287,11 @@ func (p *Point) Transpose() { } p.X, p.Y = p.Y, p.X } + +// point t% of the way between a and b +func (a *Point) Interpolate(b *Point, t float64) *Point { + return NewPoint( + a.X*(1.0-t)+b.X*t, + a.Y*(1.0-t)+b.Y*t, + ) +} diff --git a/lib/geo/route.go b/lib/geo/route.go index eb1cd1fcb..b2aa8b48b 100644 --- a/lib/geo/route.go +++ b/lib/geo/route.go @@ -20,22 +20,23 @@ func (route Route) Length() float64 { // 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 + var curr, next *Point + var length float64 for i := 0; i < len(route)-1; i++ { - curr, next := route[i], route[i+1] - length := EuclideanDistance(curr.X, curr.Y, next.X, next.Y) + 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 - return NewPoint( - curr.X*(1.0-t)+next.X*t, - curr.Y*(1.0-t)+next.Y*t, - ), i + return curr.Interpolate(next, t), i } remaining -= length } - return nil, -1 + // 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) {