[Back to GRAPHICS SWAG index] [Back to Main SWAG index] [Original]

    {
    SEAN PALMER

    I was just toying around With a B-Spline curve routine I got out of an
    old issue of Byte, and thought it was pretty neat. I changed it to use
    fixed point fractions instead of Reals, and optimized it some...

    by Sean Palmer
    public domain
    }

    Var
      color : Byte;
    Procedure plot(x, y : Word);
    begin
      mem[$A000 : y * 320 + x] := color;
    end;

    Type
      coord = Record
        x, y : Word;
      end;

      CurveDataRec = Array [0..65521 div sizeof(coord)] of coord;

    Function fracMul(f, f2 : Word) : Word;
    Inline(
      $58/                   {pop ax}
      $5B/                   {pop bx}
      $F7/$E3/               {mul bx}
      $89/$D0);              {mov ax,dx}

    Function mul(f, f2 : Word) : LongInt;
    Inline(
      $58/                   {pop ax}
      $5B/                   {pop bx}
      $F7/$E3);              {mul bx}

    Const
      nSteps = 1 shl 8;  {about 8 For smoothness (dots), 4 For speed (lines)}

    Procedure drawBSpline(Var d0 : coord; nPoints : Word);
    Const
      nsa  = $10000 div 6;
      nsb  = $20000 div 3;
      step = $10000 div nSteps;
    Var
      i, xx, yy,
      t1, t2, t3,
      c1, c2, c3, c4 : Word;

      d : curveDataRec Absolute d0;

    begin
      t1 := 0;
      color := 32 + 2;

      For i := 0 to nPoints - 4 do
      begin

       {algorithm converted from Steve Enns' original Basic subroutine}

        Repeat
          t2 := fracMul(t1, t1);
          t3 := fracMul(t2, t1);
          c1 := (Integer(t2 - t1) div 2) + nsa - fracmul(nsa, t3);
          c2 := (t3 shr 1) + nsb - t2;
          c3 := ((t2 + t1 - t3) shr 1) + nsa;
          c4 := fracmul(nsa, t3);
          xx := (mul(c1, d[i].x) + mul(c2, d[i + 1].x) +
                 mul(c3, d[i + 2].x) + mul(c4, d[i + 3].x)) shr 16;
          yy := (mul(c1, d[i].y) + mul(c2, d[i + 1].y) +
                 mul(c3, d[i + 2].y) + mul(c4, d[i + 3].y)) shr 16;
          plot(xx, yy);
          inc(t1, step);
        Until t1 = 0;  {this is why nSteps must be even power of 2}
       inc(color);
       end;
    end;

    Const
      pts = 24; {number of points} {chose this because of colors}

    Var
      c : Array [-1..2 + pts] of coord;
      i : Integer;
    begin
      Asm
        mov ax, $13
        int $10
      end;  {init vga/mcga Graphics}
      randomize;
      For i := 1 to pts do
      With c[i] do
      begin
        {x:=i*(319 div pts);}    {for precision demo}
        x := random(320);               {for fun demo}
        y := random(200);
      end;
      {for i:=1 to pts div 2 do c[i*2+1].y:=c[i*2].y;}    {fit closer}
      For i := 1 to pts do
      With c[i] do
      begin
        color := i + 32;
        plot(x, y);
      end;
      {replicate end points so curves fit to input}
      c[-1] := c[1];
      c[0]  := c[1];
      c[pts + 1] := c[pts];
      c[pts + 2] := c[pts];
      drawBSpline(c[-1], pts + 4);
      readln;
      Asm
        mov ax, 3
        int $10
      end;  {Text mode again}
    end.

[Back to GRAPHICS SWAG index] [Back to Main SWAG index] [Original]