Skip to content

Commit 3a7c82c

Browse files
committed
curve lerp to estimate point at percentage
1 parent 0c0e6ae commit 3a7c82c

File tree

2 files changed

+63
-0
lines changed

2 files changed

+63
-0
lines changed

geometry.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package sketchy
22

33
import (
44
"fmt"
5+
"log"
56
"math"
67
)
78

@@ -158,9 +159,53 @@ func (c *Curve) Last() Point {
158159
case 1:
159160
return c.Points[0]
160161
}
162+
if c.Closed {
163+
return c.Points[0]
164+
}
161165
return c.Points[n-1]
162166
}
163167

168+
// Lerp calculates a point a given percentage along a curve
169+
func (c *Curve) Lerp(perc float64) Point {
170+
var point Point
171+
if perc < 0 || perc > 1 {
172+
log.Fatalf("percentage in Lerp not between 0 and 1: %v\n", perc)
173+
}
174+
if NoTinyVals(perc) == 0 {
175+
return c.Points[0]
176+
}
177+
if math.Abs(perc-1) < Smol {
178+
return c.Last()
179+
}
180+
totalDist := c.Length()
181+
targetDist := perc * totalDist
182+
partialDist := 0.0
183+
var foundPoint bool
184+
n := len(c.Points)
185+
for i := 0; i < n-1; i++ {
186+
dist := Distance(c.Points[i], c.Points[i+1])
187+
if partialDist+dist >= targetDist {
188+
remainderDist := targetDist - partialDist
189+
pct := remainderDist / dist
190+
point = c.Points[i].Lerp(c.Points[i+1], pct)
191+
foundPoint = true
192+
break
193+
}
194+
partialDist += dist
195+
}
196+
if !foundPoint {
197+
if c.Closed {
198+
dist := Distance(c.Points[n-1], c.Points[0])
199+
remainderDist := targetDist - partialDist
200+
pct := remainderDist / dist
201+
point = c.Points[n-1].Lerp(c.Points[0], pct)
202+
} else {
203+
panic("couldn't find curve lerp point")
204+
}
205+
}
206+
return point
207+
}
208+
164209
// ContainsPoint determines if a point lies within a rectangle
165210
func (r *Rect) ContainsPoint(p Point) bool {
166211
return p.X >= r.X && p.X <= r.X+r.W && p.Y >= r.Y && p.Y <= r.Y+r.H

geometry_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,3 +75,21 @@ func TestPerpendicularBisector(t *testing.T) {
7575
pb,
7676
)
7777
}
78+
79+
func TestCurveLerp(t *testing.T) {
80+
assert := assert.New(t)
81+
var curve Curve
82+
points := []Point{
83+
{X: 0, Y: 0},
84+
{X: 1, Y: 0},
85+
{X: 2, Y: 0},
86+
{X: 10, Y: 0},
87+
}
88+
curve.Points = points
89+
lerp := curve.Lerp(0.0)
90+
assert.Equal(Point{X: 0, Y: 0}, lerp)
91+
lerp = curve.Lerp(1.0)
92+
assert.Equal(Point{X: 10, Y: 0}, lerp)
93+
lerp = curve.Lerp(0.25)
94+
assert.Equal(Point{X: 2.5, Y: 0}, lerp)
95+
}

0 commit comments

Comments
 (0)