/* The routines in this file are copyright (c) 1987 by Helene (Lee) Taran.
 * Permission is granted for use and free distribution as long as the
 * original author's name is included with the code.
 */

#include "spline.h"

extern int DrawAFrame;
REAL_POINT *TickMark();
REAL_POINT *Midpoint();

/* Draw_Natural_Bspline : draws the bspline with natural ends that
 * is defined by the list of <control_points>. Assumes that there
 * are at least three control points.
 */
Draw_Natural_Bspline(w, control_points)
struct Window *w;
DLISTPTR control_points;
{
  REAL_POINT t1, t2, t3, t4, first, last;
  DLISTPTR a = FIRST(control_points);
  DLISTPTR b = NEXT(a);
  DLISTPTR c = NEXT(b);

  first = *POINT(a);
  TickMark(&t1,1,3,POINT(a),POINT(b));
  TickMark(&t2,2,3,POINT(a),POINT(b));
  if (DrawAFrame) DrawConstructionLine(w,POINT(a),POINT(b));
  while (1) {
      if (b == LAST(control_points)) { 
         DrawBezierArc(w,&first,&t1,&t2,POINT(b));
         return;
      }
      TickMark(&t3,1,3,POINT(b),POINT(c));
      TickMark(&t4,2,3,POINT(b),POINT(c));  
      TickMark(&last,1,2,&t2,&t3);
      if (DrawAFrame) {
          DrawConstructionLine(w,POINT(b),POINT(c));
          DrawConstructionLine(w,&t2,&t3);
      }
      DrawBezierArc(w,&last,&t2,&t1,&first);
      first = last; t1 = t3;  t2 = t4;  a = b;  b = c;  c = NEXT(c);
  } 
}

/* Draw_TripleKnot_Bspline : draws the bspline with triple knots at the ends
 * defined by the list of <control_points>. Assumes that there
 * are at least four control points.
 */
Draw_TripleKnot_Bspline(w, control_points)
struct Window *w;
DLISTPTR control_points;
{
  REAL_POINT t1, t2, t3, t4, first, last;
  DLISTPTR a = FIRST(control_points);
  DLISTPTR b = NEXT(a);
  DLISTPTR c = NEXT(b);
  DLISTPTR d = NEXT(c);
  
  if (DrawAFrame) DrawConstructionLine(w,POINT(a),POINT(b));

  first = *POINT(a);
  t1 = *POINT(b);
  if (LENGTH(control_points) == 4)  t2 = *POINT(c);
  else TickMark(&t2,1,2,POINT(b),POINT(c));

  while (1) {

    if (d == LAST(control_points)) {  /* draw the last arc */
       if (DrawAFrame) {
           DrawConstructionLine(w,POINT(b),POINT(c));
           DrawConstructionLine(w,POINT(c),POINT(d));
       }
       DrawBezierArc(w,&first,&t1,&t2,POINT(d));
       return;
    }

    if (d == PREVIOUS(LAST(control_points))) {
      TickMark(&t3,1,2,POINT(c),POINT(d));
      t4 = *POINT(d);
    } else {
      TickMark(&t3,1,3,POINT(c),POINT(d));  
      TickMark(&t4,2,3,POINT(c),POINT(d));  
    }

    TickMark(&last,1,2,&t2,&t3);
    if (DrawAFrame) {
        DrawConstructionLine(w,POINT(b),POINT(c));
        DrawConstructionLine(w,&t2,&t3);
    }
    DrawBezierArc(w,&last,&t2,&t1,&first);
    first = last; t1 = t3;  t2 = t4;  a = b;  b = c;  c = d; d = NEXT(d);
  } 
}
 


/* Draw_Closed_Bspline : draws the closed bspline that
 * is defined by the list of <control_points>. Assumes that there
 * are at least three control points. 
 */
Draw_Closed_Bspline(w, control_points)
struct Window *w;
DLISTPTR control_points;
{
  REAL_POINT t1, t2, t3, t4, first, last;
  DLISTPTR a = FIRST(control_points);
  DLISTPTR b = NEXT(a);
  DLISTPTR c = NEXT(b);

  TickMark(&t1,2,3,POINT(LAST(control_points)),POINT(a));
  TickMark(&t2,1,3,POINT(a),POINT(b));
  TickMark(&first,1,2,&t1,&t2);
  if (DrawAFrame) DrawConstructionLine(w,POINT(a),POINT(b));
  do {
      if (b == LAST(control_points)) c = FIRST(control_points);
      TickMark(&t3,2,3,POINT(a),POINT(b));
      TickMark(&t4,1,3,POINT(b),POINT(c));  
      TickMark(&last,1,2,&t3,&t4);
      if (DrawAFrame) {
          DrawConstructionLine(w,POINT(b),POINT(c));
          DrawConstructionLine(w,&t3,&t4);
      }
      DrawBezierArc(w,&first,&t2,&t3,&last);
      first = last; t1 = t3;  t2 = t4;  a = b;  b = c;  c = NEXT(c);
  } while (a != FIRST(control_points));
}
