IPGeometryImpl.mesa
Last changed by:
Doug Wyatt, July 7, 1983 11:52 am
DIRECTORY
IPErrors USING [Bug, MasterError],
IPGeometry USING [],
IPImagerBasic USING [Outline, OutlineRep, Pair, Segment, SegmentRep, Trajectory, Transformation],
IPTransform USING [Tp];
IPGeometryImpl: CEDAR PROGRAM
IMPORTS IPErrors, IPTransform
EXPORTS IPGeometry
= BEGIN OPEN IPImagerBasic;
MoveTo: PUBLIC PROC[p: Pair] RETURNS[Trajectory] = {
RETURN[NEW[SegmentRep[moveto] ← [
prev: NIL, lp: p, simple: TRUE, variant: moveto[]]]];
};
LineTo: PUBLIC PROC[t: Trajectory, p: Pair] RETURNS[Trajectory] = {
RETURN[NEW[SegmentRep[lineto] ← [
prev: t, lp: p, simple: t.simple AND (p.x=t.lp.x OR p.y=t.lp.y), variant: lineto[]]]];
};
LineToX: PUBLIC PROC[t: Trajectory, x: REAL] RETURNS[Trajectory] = {
RETURN[NEW[SegmentRep[lineto] ← [
prev: t, lp: [x, t.lp.y], simple: t.simple, variant: lineto[]]]];
};
LineToY: PUBLIC PROC[t: Trajectory, y: REAL] RETURNS[Trajectory] = {
RETURN[NEW[SegmentRep[lineto] ← [
prev: t, lp: [t.lp.x, y], simple: t.simple, variant: lineto[]]]];
};
CurveTo: PUBLIC PROC[t: Trajectory, p1, p2, p3: Pair] RETURNS[Trajectory] = {
RETURN[NEW[SegmentRep[curveto] ← [
prev: t, lp: p3, simple: FALSE, variant: curveto[p1, p2]]]];
};
MakeOutline: PUBLIC PROC[n: INT, p: PROC RETURNS[Trajectory]] RETURNS[Outline] = {
IF n<0 THEN ERROR IPErrors.MasterError[InvalidArgs]
ELSE IF n>LAST[NAT] THEN ERROR IPErrors.MasterError[LimitExceeded]
ELSE {
size: NAT = n;
outline: Outline = NEW[OutlineRep[size]];
FOR i: NAT IN[0..size) DO outline[i] ← p[] ENDLOOP;
RETURN[outline];
};
};
MSegment: TYPE = REF SegmentRep[moveto];
LSegment: TYPE = REF SegmentRep[lineto];
CSegment: TYPE = REF SegmentRep[curveto];
MapTrajectory: PUBLIC PROC[t: Trajectory, m: Transformation ← NIL,
move: PROC[Pair], line: PROC[Pair], curve: PROC[Pair, Pair, Pair]] = {
Map: PROC[p: Pair] RETURNS[Pair] = INLINE {
RETURN[IF m=NIL THEN p ELSE IPTransform.Tp[m, p]] };
Eq: PROC[a, b: Pair] RETURNS[BOOL] = INLINE { RETURN[a.x=b.x AND a.y=b.y] };
fp, lp: Pair;
move[lp ← fp ← Map[t.lp]];
FOR s: Segment ← t, s.prev UNTIL s=NIL DO
WITH s SELECT FROM
s: MSegment => EXIT;
s: LSegment => {
p: Pair = Map[s.prev.lp];
IF NOT Eq[p, lp] THEN line[lp ← p];
};
s: CSegment => {
p1: Pair = Map[s.p2];
p2: Pair = Map[s.p1];
p3: Pair = Map[s.prev.lp];
matches: NAT ← 0;
IF Eq[lp, p1] THEN matches ← matches+1;
IF Eq[p1, p2] THEN matches ← matches+1;
IF Eq[p2, p3] THEN matches ← matches+1;
IF matches<2 THEN curve[p1, p2, lp ← p3]
ELSE IF matches<3 THEN line[lp ← p3];
};
ENDCASE => ERROR IPErrors.Bug; -- invalid segment type
REPEAT FINISHED => ERROR IPErrors.Bug; -- should have seen MSegment
ENDLOOP;
};
MapOutline: PUBLIC PROC[o: Outline, m: Transformation ← NIL,
move: PROC[Pair], line: PROC[Pair], curve: PROC[Pair, Pair, Pair]] = {
FOR i: NAT IN[0..o.length) DO
MapTrajectory[o[i], m, move, line, curve];
ENDLOOP;
};
END.