[comp.sys.mac.programmer] You got it. Re: Spline code anyone?

hawley@adobe.COM (Steve Hawley) (02/20/91)

In article <1991Feb18.231756.13442@ecst.csuchico.edu> brad@ecst.csuchico.edu (Brad Lowe) writes:
>Does anyone have any code that draws splines (smooth curves around points)?  
>How about books/articles with code examples?  Any help would be most most appreciated.  

Here is a version of a spline routine that was written for the BLIT terminal
at Bell Laboratories by Theo Pavlidis.  Theo also has a fairly good graphics
book (can't remember the title) that tells how this works.

This is not Mac source code and will not drop into place --sorry.

To help you do the conversion:
In the BLIT world, a Point is:

typedef struct { short x, y; } Point;

add() is a macro to add the components of a point with a single instruction.
jmoveto() and jlineto() do just what you think they do.  f is a transfer
function.  In the BLIT world, the equivalent of PenMode was a C function
to perform a bit-level transfer between a source and destination.

p is an array of Points.  The first and last entries are should not be
used.  In jspline p[0] is set to p[1] and p[n] is set to p[n-1].  This is
to guarantee that the spline starts and ends at a specified pair of points.
Some bad news: if you translate this to Quickdraw calls and draw the spline in
patXor, the spline will have lots of little discontinuities, since the Mac's
LineTo will draw both end points.  Tanstaafl.

For the technically curious: if you have a pair of duplicate points in a
list of points to be splined through, the spline will intersect the duplicate
points.

cursinhibit() hides the cursor, cursallow() shows it.  These calls aren't
neccessary on the Mac (so why am I leaving them in?  To keep the code the
same as when I swiped it from the BLIT libraries).

Extra credit: how can you change the value of scale to make this code more
efficient?

jspline(offset,p, n, f) Point offset; register Point *p; int n, f;
{	register long w, t1, t2, t3, scale=1000; 
	register int i, j, steps=10; 
	Point q;
    	if (p != (Point *) NULL) {
		p[0] = p[1];
		p[n] = p[n-1];
		cursinhibit();
		jmoveto(add(offset,p[0]));
		for (i = 0; i < n-1; i++) {
			for (j = 0; j < steps; j++) {
				w = scale * j / steps;
				t1 = w * w / (2 * scale);
				w = w - scale/2;
				t2 = 3*scale/4 - w * w / scale;
				w = w - scale/2;
				t3 = w * w / (2*scale);
				q.x = (t1*p[i+2].x + t2*p[i+1].x + 
					t3*p[i].x + scale/2) / scale;
				q.y = (t1*p[i+2].y + t2*p[i+1].y + 
					t3*p[i].y + scale/2) / scale;
				jlineto(add(offset,q), f);
			}
		}
		cursallow();
	}
}

Share and enjoy.

Steve Hawley
hawley@adobe.com
-- 
"Did you know that a cow was *MURDERED* to make that jacket?"
"Yes.    I didn't think there were any witnesses, so I guess I'll have to kill
 you too." -Jake Johansen