/* 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.
 */

/*
 * Reformatted, and modified to compile without warnings and errors
 * under SAS/C -6.5x by gduncan@philips.oz.au (GMD). This included
 * proto generation, renaming of some literals to avoid name collisions,
 * and Amiga Version string (also displayed in Title bar).
 * No original version number, this version arbitrarily named 1.1. 
 * - otherwise no functional changes.
 * GMD - Sep 94
 */

#include "all.h"

/* Midpoint: returns the midpoint of the line through <p0> and <p1> */

void
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.
 */

void
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
 */

void
DrawBezierArc (w, p000, p001, p011, p111)
     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);
    }
}
/*--*/
