in reply to Re: How to smooth values of an x,y,z array using Math::Spline
in thread How to smooth values of an x,y,z array using Math::Spline

Yes, I think a Bezier curve would be fine. Mainly just trying to smooth-out some noise. I'd appreciate you sharing that code.
  • Comment on Re^2: How to smooth values of an x,y,z array using Math::Spline

Replies are listed 'Best First'.
Re^3: How to smooth values of an x,y,z array using Math::Spline
by pryrt (Abbot) on May 10, 2023 at 18:35 UTC
    Given what you said Re^2: How to smooth values of an x,y,z array using Math::Spline, I think my second answer Re^2: How to smooth values of an x,y,z array using Math::Spline is your best bet. That answer allows for any number of observations to be smoothed. My original thought for the Bezier would have been to only pay attention to four points, only hitting the outer two; and if I expanded that idea to multiple "fixed points", it would require that the number of observations be 3N+1, and it would "waste" (go toward but not hit) roughly 2/3 of the points.

    But, if you really want the Bezier, and thus not hitting most of the points you list:

    use FindBin; use local::lib "$FindBin::Bin/tmplib"; use warnings; use strict; use feature ':5.10'; my @accel = ([-0.7437,0.1118,-0.5367], [-0.5471,0.0062,-0.6338], [-0.6437,0.1216,-0.5255], [-0.4437,0.3216,-0.3255], # add three more observations, to show it works with more + than 4 points (with any 3N+1) [-0.2718,0.3142,-0.1618], [-0.4567,0.1234,+0.1618], [-0.9876,0.5432,+0.3162], ); # note: I changed from an array whose only element is an arrayref +of arrayrefs to an array who has n arrayrefs, to be a simple 2D array use Math::Spline; die "requires 3N+1 points, supplied ".scalar(@accel)." points" unless +1 == scalar(@accel) % 3; my $first = 0; my @interp_accel = (); my $NSTEPS = 100; my $dt = 1/$NSTEPS; my $grp = 0; while($first+3 < @accel) { my (@idx) = map {$first+$_} 0..3; my $t = @interp_accel ? $dt : 0; while($t < 1+$dt) { my @m = ( (1-$t)**3, (1-$t)**2 * ($t)**1 * 3, (1-$t)**1 * ($t)**2 * 3, ($t)**3 ); my $x = 0; $x += $m[$_] * $accel[$idx[$_]][0] for 0..3; my $y = 0; $y += $m[$_] * $accel[$idx[$_]][1] for 0..3; my $z = 0; $z += $m[$_] * $accel[$idx[$_]][2] for 0..3; printf "interpolate t=%.3f => [%+-7.4f,%+-7.4f,%+-7.4f]\n", $g +rp+$t, $x, $y, $z if $t<=2*$dt or $t>=$dt*($NSTEPS-2); # debug print print "...\n" if $t==3*$dt; push @interp_accel, [$x,$y,$z]; $t += $dt; } ++$grp; $first += 3; }

    output:

    interpolate t=0.000 => [-0.7437,+0.1118,-0.5367] interpolate t=0.010 => [-0.7379,+0.1087,-0.5396] interpolate t=0.020 => [-0.7323,+0.1057,-0.5423] ... interpolate t=0.980 => [-0.4553,+0.3097,-0.3374] interpolate t=0.990 => [-0.4496,+0.3156,-0.3315] interpolate t=1.000 => [-0.4437,+0.3216,-0.3255] interpolate t=1.010 => [-0.4387,+0.3213,-0.3205] interpolate t=1.020 => [-0.4338,+0.3209,-0.3155] ... interpolate t=1.980 => [-0.9562,+0.5187,+0.3067] interpolate t=1.990 => [-0.9718,+0.5308,+0.3115] interpolate t=2.000 => [-0.9876,+0.5432,+0.3162]

    Whether this or Re^2: How to smooth values of an x,y,z array using Math::Spline is better for "smoothing" the data that you have is really up to you.

    addenda: Please note that in all of my solutions, @interp_accel will contain the complete list of interpolated values, even if my manual editing or in-code logic doesn't print them all. I just skipped most of the printing to save space in the posts, so the reduced output was enough to show what was going on.