[comp.sys.mac.programmer] Arrowhead routines

mkb@rover.ri.cmu.edu (Mike Blackwell) (03/07/91)

Here are two routines I whipped up which draw a line with an arrowhead at
the end. They both use the fixed point math routines for speed. The first
draws the arrowhead with an arc of a circle, the second makes the arrowhead
with all straight lines.

		Mike Blackwell		mkb@rover.ri.cmu.edu

/************************************************************************/
/*  Draw a line with an arrowhead at the end.                           */
/*                                                                      */
/*  Mike Blackwell                    mkb@rover.ri.cmu.edu              */
/*  The Robotics Institute            Carnegie Mellon University        */
/************************************************************************/

void OldArrow(Point start, Point end, short size)
// Draw a line from start to end, and put an arrowhead at the end.
// No error checking - start and end better not be the same...
{
    Fixed ang;
    long iang;
    Rect r;

    // Figure out the angle of the line
    ang = FixATan2(end.h - start.h, end.v - start.v);
    // Convert to degrees
    ang = FixMul(ang, X2Fix(57.2957795131));
    iang = 270 + Fix2Long(ang);	// Convert to Arc style angle

    // Draw the line
    MoveTo(start.h, start.v);
    LineTo(end.h, end.v);

    // Center a square over the end point
    SetRect(&r, -size, -size, size, size);
    OffsetRect(&r, end.h, end.v);

    // Draw the arrow head (arc section of a circle)
    PaintArc(&r, iang - 15, 30);
}


void Arrow(Point start, Point end, short size)
// Draw a line from start to end, and put an arrowhead at the end. Size is
// length of arrowhead, and also width of base. Line length must be non-zero
// for anything to be drawn.
{
    Fixed len;		// Length of line
    long dx, dy;	// Delta X and Y of line
    Fixed lx, ly;	// dx/len, dy/len
    Fixed xm, ym;	// The point where the arrow base crosses the line
    Fixed xa, ya;	// Arrow base point translated to start, rotated 90
    long p1x, p1y;	// One arrow base point
    long p2x, p2y;	// And the other
    PolyHandle arrowHead;

    dx = end.h - start.h;
    dy = end.v - start.v;

    len = X2Fix(sqrt((extended)((dx * dx) + (dy * dy))));
    if (len > 0) {
	lx = FixDiv(Long2Fix(dx), len);
	ly = FixDiv(Long2Fix(dy), len);
	xm = Long2Fix((long)start.h) + FixMul((len - Long2Fix((long)size)), lx);
	ym = Long2Fix((long)start.v) + FixMul((len - Long2Fix((long)size)), ly);
	xa = FixMul(Long2Fix((long)(size / 2)), lx);
	ya = FixMul(Long2Fix((long)(size / 2)), ly);
	// Rotate the point +/- 90, and translate up to mid point
	p1x = Fix2Long(xm - ya);
	p1y = Fix2Long(ym + xa);
	p2x = Fix2Long(xm + ya);
	p2y = Fix2Long(ym - xa);

	MoveTo(start.h, start.v);
	LineTo(end.h, end.v);

	arrowHead = OpenPoly();
	MoveTo(end.h, end.v);
	LineTo(p1x, p1y);
	LineTo(p2x, p2y);
	LineTo(end.h, end.v);
	ClosePoly();
	PaintPoly(arrowHead);
	KillPoly(arrowHead);
    }
}