_Algorithm Alley_
by Robert F. Kauffmann

Listing One
{--------------------------TYPES------------------------------------}
type POINT = record                          { define a 2-D point}
        X, Y : integer;
     end;

     PT4 = array[1..5] of POINT; {Array of points controlling 1 seg }

     A4_4 = array[1..4,1..4] of real;     {Basis matrices for cubics}
     A1000_4 = array[1..1000,1..4] of real;  {Lookup table for basis
                                              curve points; up to 1000 points
                                              are pre-calculated in advance
                                              and stored for each of the
                                              four basis equations }
     Curve_Type = ( Cat_Rom,    {Cubic spline which passes through every
                                control point continuity in first derivative}
                    B_Spline,   {Cubic spline which does not pass through
                                control points; continuity in 2nd derivative}
                    Ext_Tspline,  {Triginometric spline which does not pass
                                  through control points; continuity in 
                                  all derivatives}
                    Int_Tspline ); {Cubic spline which passes through all 
                               control points; continuity in all derivatives}

{--------------------------VARIABLES--------------------------------}
var
   Max_Points    : real;    {Max number of points to interpolate per segment}
   Curve         : A1000_4; {Current interpolating curve}
   Curr_Basis    : Curve_Type; {Type of basis function being used}

{-------------------CUBIC CURVE BASIS MATRICES----------------------}
const
    Bspline : A4_4 =
          ( ( -0.166667,  0.5,       -0.5,        0.166667   ),
            (  0.5,      -1.0,        0.0,        0.666667   ),
            ( -0.5,       0.5,        0.5,        0.166667   ),
            (  0.166667,  0.0,        0.0,        0.0        ) );
    Catrom  : A4_4 =
          ( ( -0.5,  1.0,  -0.5,   0.0   ),
            (  1.5, -2.5,   0.0,   1.0   ),
            ( -1.5,  2.0,   0.5,   0.0   ),
            (  0.5, -0.5,   0.0,   0.0   ) );
{--------------------------------------------------------------------}
   function CubicSpline( t : real;
                         n : integer;
                         M : A4_4 ) : real;
  { Calculates value of nth cubic basis function specified by M for parameter
    t; calculates basis curve one point at a time; called by SetBasis }
   var T1, T2, T3 : real;
   begin
      T1 := t; T2 := t*t;T3 := t*t*t;
      CubicSpline := T3*M[n,1] + T2*M[n,2] + T1*M[n,3] + M[n,4];
   end; {CubicSpline}

 {-------------------------------------------------------------------}
   function ExTSpline( t : real;
                      n : integer ) : real;
   { Calculates the value of the n-th basis function for the
     exterpolating triginometric spline for parameter t; used to
     calculate the basis curve one point at a time; Called by
     SetBasis }
   var Sn, Cs : real;
   begin
       Sn := sin( 0.5*Pi*t ); Cs := cos( 0.5*Pi*t );
     case n of
       1 : ExTSpline := 0.25*( 1 - Cs);
       2 : ExTspline := 0.25*( 1 + Sn);
       3 : ExTspline := 0.25*( 1 + Cs);
       4 : ExTspline := 0.25*( 1 - Sn);
     end;
   end; {ExTspline}
 {-------------------------------------------------------------------}
   function InTspline( t : real;
                      n : integer ) : real;
   { Calculates the value of the n-th basis function for the
     interpolating triginometric spline for parameter t; used to
     calculate the basis curve one point at a time; Called by
     SetBasis }
   var Sn, Cs : real;
   begin
       Sn := sin( 0.5*Pi*t ); Cs := cos( 0.5*Pi*t );
     case n of
       1 : InTspline := 0.5*Cs*(Cs - 1 );
       2 : InTspline := 0.5*Sn*(Sn + 1 );
       3 : InTspline := 0.5*Cs*(Cs + 1 );
       4 : InTspline := 0.5*Sn*(Sn - 1 );
     end;
  end; {InTspline}
 {-------------------------------------------------------------------}
   procedure SetBasis( Basis : Curve_Type;
                       Max   : integer);
   {Pre-calculate basis function at specified granularity}
   var t : real;
       i, j : integer;
   begin
      Curr_Basis := Basis;
      if Max > 1000 then Max_Points := 1000  {set granularity <= 1000}
                    else Max_Points := Max;
      for i:= 1 to Max do begin
         t:= i/Max;
         case Basis of       {calculate basis curves on point a time}
            Ext_Tspline :   {exterpolating trig spline}
               for j:= 1 to 4 do Curve[i,j] := ExTspline( t, j );
            Int_Tspline :   {interpolating trig spline}
               for j:= 1 to 4 do Curve[i,j] := InTspline( t, j )
            Cat_Rom :       {Catmull-Rom cubic spline}
               for j:= 1 to 4 do Curve[i,j] := CubicSpline( t, j, CatRom );
            B_Spline :      {BSpline cubic spline}
               for j:= 1 to 4 do Curve[i,j] := CubicSpline( t, j, BSpline );
         end;
      end;
   end; {SetBasis}
 {-------------------------------------------------------------------}
  procedure PlotCurve ( P1,P2,P3,P4 : POINT;
                         C           : integer );
   {Plots a segment of the defined curve in the specified color;
    called by Render_Curve }
   var Xo, X1, X2, X3, X4, t, T1, T2, T3,
       Yo, Y1, Y2, Y3, Y4, X, Y   : real;
       i, j, Max           : integer;
   begin
      Max := round( Max_Points );
      X1 := P1.X; X2 := P2.X; X3 := P3.X; X4 := P4.X;
      Y1 := P1.Y; Y2 := P2.Y; Y3 := P3.Y; Y4 := P4.Y;
      for i:= 1 to Max do begin { vary thru [0,1] & plot basis functn}
          t:= i/Max;
          X := X1*Curve[i,1] + X2*Curve[i,2] +
               X3*Curve[i,3] + X4*Curve[i,4] ;
          Y := Y1*Curve[i,1] + Y2*Curve[i,2] +
               Y3*Curve[i,3] + Y4*Curve[i,4] ;
          put_pixel( X, Y, C );
      end;
   end; {PlotCurve}


3



