/* 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 "bezier.h"

/* Midpoint: returns the midpoint of the line through <p0> and <p1> */
Midpoint (m, p0 , p1)
REAL_POINT *m, *p0, *p1;
{  
   m->x = (p0->x + p1->x)/2 ;
   m->y = (p0->y + p1->y)/2 ;
}


/* TickMark : returns the point that is n/d of the way 
 * between <p0> and <p1>. If you just want to divide the line in
 * half use Midpoint.
 */
TickMark (t, n, d, p0, p1)
REAL_POINT *t;
int n, d; REAL_POINT *p0, *p1;
{  
   t->x = p0->x +  (p1->x - p0->x) * n/d ;
   t->y = p0->y +  (p1->y - p0->y) * n/d ;
}


/* DrawBezierArc: draws a bezier arc between the 4 given points by
 * recursively subdividing the curve until each segment is close
 * enough to be rendered as a line.
 * Assumes that your window <w> has been initialized and opened and that
 * in addition to the intuition library, the graphics library is open
 */
DrawBezierArc(w, p000, p001, p011, p111)
struct Window *w;                          /* draw the arc in this window */
REAL_POINT *p000, *p001, *p011, *p111;   /* bezier control points */
{ 
   REAL_POINT p00t,p0t1,pt11,p0tt,ptt1,pttt;
   float delta1 = (p001->x * p011->y - p001->y * p011->x) -
                  (p000->x * p011->y - p000->y * p011->x) +
     	          (p000->x * p001->y - p000->y * p001->x);

   float delta2 = (p111->x * p011->y - p111->y * p011->x) -
                  (p000->x * p011->y - p000->y * p011->x) +
		  (p000->x * p111->y - p000->y * p111->x);

   if (ABS(delta1) + ABS(delta2) <= CLOSENESS) { /* so close, just draw a line */
      Move(w->RPort,(long)p000->x,(long)p000->y);
      Draw(w->RPort,(long)p111->x,(long)p111->y);
     }
   else { /* divide the arc into two smaller bezier arcs */
       Midpoint(&p00t, p000, p001);
       Midpoint(&p0t1, p001, p011);
       Midpoint(&pt11, p011, p111);
       Midpoint(&p0tt, &p00t, &p0t1);
       Midpoint(&ptt1, &p0t1, &pt11);      
       Midpoint(&pttt, &p0tt, &ptt1);
       DrawBezierArc(w,p000,&p00t,&p0tt,&pttt);
       DrawBezierArc(w,&pttt,&ptt1,&pt11,p111);
   }
}   
      
