fixed end-slope splines

This commit is contained in:
Josh Deprez 2021-10-04 13:33:35 +11:00
parent 22cb55de15
commit d28762468f
3 changed files with 28 additions and 31 deletions

View file

@ -22,21 +22,18 @@ func main() {
{X: 3, Y: -2}, {X: 3, Y: -2},
{X: 4, Y: 4}, {X: 4, Y: 4},
} }
linear := &geom.LinearSpline{Points: points} cubic := &geom.CubicSpline{
if err := linear.Prepare(); err != nil { Points: points,
log.Fatalf("linear.Prepare() = %v, want nil", err)
}
cubic := &geom.CubicSpline{Points: points,
FixedPreslope: true, FixedPreslope: true,
FixedPostslope: false, FixedPostslope: true,
Preslope: -5, Preslope: -5,
//Postslope: -4, Postslope: -4,
} }
if err := cubic.Prepare(); err != nil { if err := cubic.Prepare(); err != nil {
log.Fatalf("cubic.Prepare() = %v, want nil", err) log.Fatalf("cubic.Prepare() = %v, want nil", err)
} }
// Produce interpolated points in CSV-like form. // Produce interpolated points in CSV-like form.
for x := -8.0; x < 8.0; x += 0.0625 { for x := -8.0; x < 8.0; x += 0.0625 {
fmt.Printf("%f,%f,%f\n", x, linear.Interpolate(x), cubic.Interpolate(x)) fmt.Printf("%f,%f\n", x, cubic.Interpolate(x))
} }
} }

View file

@ -208,7 +208,7 @@ func (s *CubicSpline) Prepare() error {
s.m[i] = (B[i] - s.h[i]*s.m[i+1]) / diag[i] s.m[i] = (B[i] - s.h[i]*s.m[i+1]) / diag[i]
} }
if s.FixedPreslope { if s.FixedPreslope {
s.m[0] = (B[0] - s.h[0]*s.m[1]) / diag[1] s.m[0] = (B[0] - s.h[0]*s.m[1]) / diag[0]
} }
// Derive pre- and post-slope, if not fixed: // Derive pre- and post-slope, if not fixed:
if !s.FixedPreslope { if !s.FixedPreslope {

View file

@ -162,8 +162,8 @@ func TestFixedEndSlopesCubicSpline(t *testing.T) {
Points: []Float2{{-7, -2}, {-5, 1}, {-3, 0}, {-2, -3}, {0, 2}, {1, -5}, {3, -2}, {4, 4}}, Points: []Float2{{-7, -2}, {-5, 1}, {-3, 0}, {-2, -3}, {0, 2}, {1, -5}, {3, -2}, {4, 4}},
FixedPreslope: true, FixedPreslope: true,
FixedPostslope: true, FixedPostslope: true,
Preslope: -1, Preslope: -5,
Postslope: 1, Postslope: 4,
} }
if err := s.Prepare(); err != nil { if err := s.Prepare(); err != nil {
t.Errorf("s.Prepare() = %v, want nil", err) t.Errorf("s.Prepare() = %v, want nil", err)
@ -171,34 +171,34 @@ func TestFixedEndSlopesCubicSpline(t *testing.T) {
tests := []struct { tests := []struct {
x, want float64 x, want float64
}{ }{
{x: -8, want: -3.648342225609756}, {x: -8, want: 3},
{x: -7.5, want: -2.824171112804878}, {x: -7.5, want: 0.5},
{x: -7, want: -2}, {x: -7, want: -2},
{x: -6.5, want: -1.180464581745427}, {x: -6.5, want: -3.213753455247408},
{x: -6, want: -0.3887433307926829}, {x: -6, want: -2.4866758806597526},
{x: -5.5, want: 0.3473495855564025}, {x: -5.5, want: -0.7662603657422216},
{x: -5, want: 1}, {x: -5, want: 1},
{x: -4.5, want: 1.5067079125381098}, {x: -4.5, want: 2.02752418673185},
{x: -4, want: 1.6662299923780488}, {x: -4, want: 2.183379403298762},
{x: -3.5, want: 1.2426370760289636}, {x: -3.5, want: 1.4975449182162928},
{x: -3, want: 0}, {x: -3, want: 0},
{x: -2.5, want: -1.9368449885670733}, {x: -2.5, want: -1.9904880751130807},
{x: -2, want: -3}, {x: -2, want: -3},
{x: -1.5, want: -1.855450886051829}, {x: -1.5, want: -1.8287325238726178},
{x: -1, want: 0.45221989329268286}, {x: -1, want: 0.4715013478320472},
{x: -0.5, want: 2.2837807259908534}, {x: -0.5, want: 2.2859845456206873},
{x: 0, want: 2}, {x: 0, want: 2},
{x: 0.5, want: -1.229539824695122}, {x: 0.5, want: -1.2096392835930003},
{x: 1, want: -5}, {x: 1, want: -5},
{x: 1.5, want: -6.734946646341463}, {x: 1.5, want: -6.8416283067574355},
{x: 2, want: -6.406821646341463}, {x: 2, want: -6.6251085119020425},
{x: 2.5, want: -4.6252858231707314}, {x: 2.5, want: -4.846034461095628},
{x: 3, want: -2}, {x: 3, want: -2},
{x: 3.5, want: 0.941477705792683}, {x: 3.5, want: 1.3035791794215745},
{x: 4, want: 4}, {x: 4, want: 4},
{x: 4.5, want: 7.078029725609756}, {x: 4.5, want: 6},
{x: 5, want: 10.156059451219512}, {x: 5, want: 8},
{x: 5.5, want: 13.234089176829269}, {x: 5.5, want: 10},
} }
for _, test := range tests { for _, test := range tests {
if got := s.Interpolate(test.x); math.Abs(got-test.want) > 0.0000001 { if got := s.Interpolate(test.x); math.Abs(got-test.want) > 0.0000001 {