/* 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 and */ 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 and . 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 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); } }