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.