Path.mesa
Doug Wyatt, June 28, 1984 12:23:47 pm PDT
DIRECTORY
ImagerBasic USING [Pair];
Path: CEDAR DEFINITIONS
~ BEGIN
Pair: TYPE ~ ImagerBasic.Pair;
PATH: TYPE ~ REF PathRep;
SegType: TYPE ~ {move, line, curve, conic, arc};
PathRep: TYPE ~ RECORD[segs: Segs, reals: Reals, lp: Pair];
Seg: TYPE ~ RECORD[type: SegType, index: NAT];
Segs: TYPE ~ REF SegsRep;
SegsRep: TYPE ~ RECORD[length: NAT, array: SEQUENCE max: NAT OF Seg];
Reals: TYPE ~ REF RealsRep;
RealsRep: TYPE ~ RECORD[length: NAT, array: SEQUENCE max: NAT OF REAL];
New: PROC[nSegs: NAT, expectedType: SegType ← move] RETURNS[PATH];
ObtainScratch: PROC[nSegs: NAT, expectedType: SegType ← move] RETURNS[PATH];
ReleaseScratch: PROC[path: PATH];
LastPoint: PROC[path: PATH] RETURNS[x, y: REAL];
LastPointP: PROC[path: PATH] RETURNS[Pair];
Return path's lp.
MoveTo: PROC[path: PATH, x, y: REAL];
MoveToP: PROC[path: PATH, p: Pair];
Start a new trajectory at p.
LineTo: PROC[path: PATH, x, y: REAL];
LineToP: PROC[path: PATH, p: Pair];
Extend path with a straight line segment. The lp of the result is p.
LineToX: PROC[path: PATH, x: REAL];
LineToY: PROC[path: PATH, y: REAL];
LineToX is equivalent to path.LineTo[x, path.lp.y].
LineToY is equivalent to path.LineTo[path.lp.x, y].
CurveTo: PROC[path: PATH, x1, y1, x2, y2, x3, y3: REAL];
CurveToP: PROC[path: PATH, p1, p2, p3: Pair];
Extend path with a cubic curve segment. The lp of the result is p3.
Let p0=path.lp. The curve segment is defined by Bezier control points p0, p1, p2, p3. It starts at p0, tangent to the line joining p0 and p1, and ends at p3, tangent to the line joining p2 and p3. It is bounded by the quadrilateral with vertices p0, p1, p2, p3.
ConicTo: PROC[path: PATH, x1, y1, x2, y2: REAL, r: REAL];
ConicToP: PROC[path: PATH, p1, p2: Pair, r: REAL];
Extend path with a segment of a conic section. The lp of the result is p2.
Let p0=path.lp. Let m be the midpoint of the line joining p0 and p2. Let p be the point on the line joining m and p1 such that Length[m, p]/Length[m, p1] = r. The curve segment starts at p0, passes through p, and ends at p2. It is a line if r=0; an ellipse if 0<r<1/2; a parabola if r=1/2; a hyperbola if 1/2<r<1. It is bounded by the triangle with vertices p0, p1, p2.
ArcTo: PROC[path: PATH, x1, y1, x2, y2: REAL];
ArcToP: PROC[path: PATH, p1, p2: Pair];
Extend path with a circular arc. The lp of the result is p2.
Let p0=path.lp. The arc starts at p0, passes through p1, and ends at p2. It is recommended that p1 lie near the halfway point along the arc. If p0 and p2 are coincident, ArcTo produces a circle; p1 lies on the circle diametrically opposite p0. If p0, p1, and p2 are colinear, the effect is { path.LineToP[p1]; path.LineToP[p2] }.
MaskTriangle: PROC[context: Context, a, b, c: Pair] ~ {
path: PATH ~ Path.ObtainScratch[3];
path.MoveToP[a];
path.LineToP[b];
path.LineToP[c];
context.MaskFillPath[path];
Path.ReleaseScratch[path];
};
END.