JunoImageImpl.mesa
Pieces from JunoTop.mesa created May 1981 by Greg Nelson, Donna Auguste
Last Edited by: Gnelson, January 17, 1984 11:32 am
Last Edited by: Maureen Stone January 19, 1984 12:08 pm
Last Hacked by: Jorge Stolfi June 7, 1984 4:40:10 pm PDT
Procedures to manipulate and paint the current Juno image.
DIRECTORY
JunoStorage,
JunoImage,
JunoOldSolver USING [Solve, Outcome],
RealFns USING [SqRt];
- - - - ELEMENT ENUMERATION
EnumPoints:
PUBLIC
PROC [Proc: PointVisitProc] =
BEGIN
FOR p: Point ← points.first, p.link WHILE p # NIL DO Proc[p] ENDLOOP
END;
ReplacePoints:
PUBLIC
PROC [Proc: PointReplaceProc] =
BEGIN
pAnt, pNew, pNext: Point ← NIL;
FOR p: Point ← points.first, pNext WHILE p # NIL DO
pNext ← p.link;
pNew ← Proc[p];
IF pNew # p THEN
{points ← DeletePoint[p, pAnt, points]; GcPoints [p, p.link];
IF pNew # NIL THEN
{points ← InsertPoint[pNew, pAnt, points];
pAnt ← pNew}}
ELSE
{pAnt ← p}
ENDLOOP
END;
EnumConstrs:
PUBLIC
PROC [Proc: ConstrVisitProc] =
BEGIN
FOR c: Constr ← constrs.first, c.link WHILE c # NIL DO Proc[c] ENDLOOP
END;
EnumConstrPoints:
PUBLIC
PROC [c: Constr, Proc: PointVisitProc] =
BEGIN
WITH c SELECT FROM
cc: HorConstr =>
{Proc[cc.i]; Proc[cc.j]};
cc: VerConstr =>
{Proc[cc.i]; Proc[cc.j]};
cc: CongConstr =>
{Proc[cc.i]; Proc[cc.j]; Proc[cc.k]; Proc[cc.l]};
cc: ParaConstr =>
{Proc[cc.i]; Proc[cc.j]; Proc[cc.k]; Proc[cc.l]};
cc: PerpConstr =>
{Proc[cc.i]; Proc[cc.j]; Proc[cc.k]; Proc[cc.l]};
cc: AtConstr =>
{Proc[cc.p]};
cc: CcwConstr =>
{Proc[cc.i]; Proc[cc.j]; Proc[cc.k]};
ENDCASE => ERROR;
IF c.frame.org # NIL THEN Proc[c.frame.org];
IF c.frame.hor # NIL THEN Proc[c.frame.hor];
IF c.frame.ver # NIL THEN Proc[c.frame.ver]
END;
ReplaceConstrPoints:
PUBLIC
PROC [c: Constr, Proc: PointReplaceProc] =
BEGIN
WITH c SELECT FROM
cc: HorConstr =>
{cc.i ← Proc[cc.i]; cc.j ← Proc[cc.j]};
cc: VerConstr =>
{cc.i ← Proc[cc.i]; cc.j ← Proc[cc.j]};
cc: CongConstr =>
{cc.i ← Proc[cc.i]; cc.j ← Proc[cc.j]; cc.k ← Proc[cc.k]; cc.l ← Proc[cc.l]};
cc: ParaConstr =>
{cc.i ← Proc[cc.i]; cc.j ← Proc[cc.j]; cc.k ← Proc[cc.k]; cc.l ← Proc[cc.l]};
cc: PerpConstr =>
{cc.i ← Proc[cc.i]; cc.j ← Proc[cc.j]; cc.k ← Proc[cc.k]; cc.l ← Proc[cc.l]};
cc: AtConstr =>
{cc.p ← Proc[cc.p]};
cc: CcwConstr =>
{cc.i ← Proc[cc.i]; cc.j ← Proc[cc.j]; cc.k ← Proc[cc.k]};
ENDCASE => ERROR;
IF c.frame.org # NIL THEN c.frame.org ← Proc[c.frame.org];
IF c.frame.hor # NIL THEN c.frame.hor ← Proc[c.frame.hor];
IF c.frame.ver # NIL THEN c.frame.ver ← Proc[c.frame.ver]
END;
EnumActions:
PUBLIC
PROC [Proc: ActionVisitProc] =
BEGIN
FOR a: Action ← actions.first, a.link WHILE a # NIL DO Proc[a] ENDLOOP
END;
EnumActionPoints:
PUBLIC
PROC [a: Action, Proc: PointVisitProc] =
BEGIN
FOR args: ActionArgs ← a.args, args.rest WHILE args # NIL DO
WITH args.first SELECT FROM
p: Point => Proc[p];
ENDCASE;
ENDLOOP
END;
ReplaceActionPoints:
PUBLIC
PROC [a: Action, Proc: PointReplaceProc] =
BEGIN
FOR args: ActionArgs ← a.args, args.rest WHILE args # NIL DO
WITH args.first SELECT FROM
p: Point => args.first ← Proc[p];
ENDCASE;
ENDLOOP
END;
- - - - JUNKYARD
Basis: TYPE = REF BasisRec;
BasisRec: TYPE = RECORD[head:TangentVector ← NIL, tail:Basis];
TangentVector: TYPE = REF TvRec;
TvRec: TYPE = RECORD[head:PointPtr ← NIL, x, y: REAL ← 0, tail:TangentVector];
PushState: PUBLIC PROCEDURE;
PopState: PUBLIC PROCEDURE;
InitJunoStorage: PROC;
ResetJunoStorage: PROC; -- reclaims all records.
pointLpad, pointRpad: PointPtr; -- The lists of points, edges, arcs
edgeLpad, edgeRpad: EdgePtr; -- line constraints, and cong. constraints
arcLpad, arcRpad: ArcPtr; -- are padded on both sides.
lineLpad, lineRpad: LinPtr;
congLpad, congRpad: CongPtr;
stringLpad, stringRpad: StringPtr;
horLpad, horRpad: HorPtr;
verLpad, verRpad: VerPtr;
ccLpad, ccRpad: CCPtr;
SortPoints:
PROC =
BEGIN
p ← NIL; q ← image.points; image.points ← NIL;
UNTIL q = NIL DO
t ← q; q ← t.link; t.link ← NIL;
r ← p; rant ← NIL;
WHILE r # NIL AND
(t.x < r.x OR (t.x = r.x AND t.y < r.y)) DO
rant ← r; r ← r.link;
ENDLOOP;
p ← InsertPoint [t, rant, p];
ENDLOOP;
-- Now reverse the list by moving backwards through it:
UNTIL p = NIL DO
t ← p.link; p.link ← image.points; image.points ← p; p ← t
ENDLOOP}
END;
NewPoint:
PROC[x,y:
INTEGER, visible:
BOOL ←
TRUE]
RETURNS [PointPtr] =
{p: PointPtr ← AddPoint[x,y];
p.visible ← visible;
IF visible THEN JG.DrawPoint[x,y];
SortPoints[];
RETURN [p]};
AddLambda:
PROC [f:
REF
ANY, args:
LIST
OF PointPtr] =
{JG.SetPaintMode[opaque];
JA.Apply[f, args, NIL]; -- f is an atom
JG.SetPaintMode[invert];
JG.viewerChanged ← TRUE;
AddX[f, args];
SortPoints[] };
CopyToViewer:
PROC =
{ DO -- IF JunoA.newVersion = TRUE AND gotNewJunoA = FALSE
-- THEN { RefreshCursors[];
-- numCursor ← 11; notice that this is one-macro dependent!!
-- JunoA.newVersion ← FALSE;
-- gotNewJunoA ← TRUE;
-- RefreshCursors[]};
IF viewerDead THEN EXIT;
{t: Terminal.Virtual = Terminal.Current[];
Terminal.WaitForBWVerticalRetrace [t]; --! Should there be one instead of two calls?
Terminal.WaitForBWVerticalRetrace [t]};
IF JG.viewerChanged
THEN {ViewerOps.PaintViewer [viewer: self, hint: client, clearClient: FALSE];
JG.viewerChanged ← FALSE;}
ENDLOOP};
MoveStep:
PROC[copying:
BOOLEAN, solving:
BOOLEAN] =
-- this proc is used by both MoveCmd and CopyCmd. It (a) identifies t with s,
-- for each source-target pair (s,t) that satisfies s is selected and t is not
-- selected; (b) computes a transform that takes the sources to the targets,
-- and (c) applies the transform to all selected points (if copying = FALSE) or
-- to all copied points (if copying = TRUE). It also actually copies the selected
-- list if copying = TRUE. It is only within this procedure that copy fields are
-- ever non-NIL.
BEGIN
n: INTEGER = MIN[atop,satop];
i: INTEGER;
savedFixBit: ARRAY[0..10] OF BOOLEAN;
savedSourcePoint: ARRAY[0..10] OF PointPtr;
singular ← FALSE;
IF n > 2 THEN ComputeTransform[a[atop].p, a[atop-1].p, a[atop-2].p, sa[satop].p, sa[satop-1].p, sa[satop-2].p];
IF n = 2 OR singular THEN ComputeTransform[a[atop].p, a[atop-1].p, NIL, sa[satop].p, sa[satop-1].p, NIL];
IF n = 1 OR singular THEN ComputeTransform[a[atop].p, NIL, NIL, sa[satop].p, NIL, NIL];
IF n = 0 OR singular THEN
{JG.Blink["No such affine transformation"];
RETURN};
IF copying THEN {Copy[]; PerformTransform[copiedPoints]}
ELSE PerformTransform[pointLpad.slink];
FOR i IN [0.. n-1] DO
IF UnSelected[a[atop-i].p] AND NOT(UnSelected[sa[satop-i].p])
THEN {IF copying THEN a[atop-i].p.copy ← sa[satop-i].p.copy
ELSE a[atop-i].p.copy ← sa[satop-i].p}
ENDLOOP;
FOR i IN [0..n-1] DO
IF copying THEN savedSourcePoint[i] ← sa[satop-i].p.copy
ELSE savedSourcePoint[i] ← sa[satop-i].p;
savedFixBit[i] ← savedSourcePoint[i].fixed;
savedSourcePoint[i].fixed ← TRUE;
ENDLOOP;
IF copying
THEN {p: PointPtr ← pointLpad.slink;
UNTIL p = pointRpad DO p.copy ← NIL; p ← p.slink ENDLOOP};
Identify[]; -- identify p with p.copy for all p such that p.copy # NIL
IF solving THEN {JunoClass.cursor ← hourGlass;
WindowManager.RestoreCursor;
[] ← JunoSolver.Solve[.5];
JunoClass.cursor ← cursor[currentCursor].cursorName;
WindowManager.RestoreCursor};
SortPoints[];
FOR i IN [0..n-1] DO savedSourcePoint[i].fixed ← savedFixBit[i] ENDLOOP;
Refresh[];
END;
AlgebraStep:
PROC =
{body: REF ← MakeDefBody[sa[satop-1].p, sa[satop].p]; -- MakeDefBody is from JunoBody
colon: ATOM ← Atom.MakeAtom[":"];
leftpren: ATOM ← Atom.MakeAtom["("];
comma: ATOM ← Atom.MakeAtom[","];
AddDef[name: $X, locals: LIST[comma, $a, $b], body: body];
PW.AddTree[JunoParserEtc.junoA,
LIST[colon, LIST[leftpren, $X, LIST[comma, $a, $b]], body]]};
OtherAlgebraStep:
PROC =
{body: REF ← MakeDefBody[sa[satop].p, NIL]; -- MakeDefBody is from JunoBody
colon: ATOM ← Atom.MakeAtom[":"];
leftpren: ATOM ← Atom.MakeAtom["("];
comma: ATOM ← Atom.MakeAtom[","];
AddDef[name: $X, locals: $a, body: body];
PW.AddTree[JunoParserEtc.junoA,
LIST[colon, LIST[leftpren, $X, $a], body]]};
RefreshPoints:
PROCEDURE =
BEGIN
p: PointPtr ← pointLpad.link;
WHILE p # pointRpad
DO IF p.visible THEN JG.DrawPoint[Real.FixI[p.x], Real.FixI[p.y]];
p ← p.link ENDLOOP;
END;
RefreshEdges:
PROCEDURE =
BEGIN
p: EdgePtr ← edgeLpad.link;
WHILE p # edgeRpad
DO JG.DrawEdge[p.b1.x, p.b1.y, p.b2.x, p.b2.y];
p ← p.link ENDLOOP;
END;
RefreshArcs:
PROCEDURE =
BEGIN
p: ArcPtr ← arcLpad.link;
WHILE p # arcRpad
DO JG.DrawArc[p.b1.x, p.b1.y, p.b2.x, p.b2.y, p.b3.x, p.b3.y, p.b4.x, p.b4.y];
p ← p.link ENDLOOP;
END;
RefreshStrings:
PROCEDURE =
BEGIN
p : StringPtr ← stringLpad.link;
WHILE p # stringRpad
DO
JG.DrawString[p.b3.x, p.b3.y, p.stringText, p.stringFont,
p.fontName, p.fontSize, p.bold, p.italic];
p ← p.link ENDLOOP;
END;
RefreshX: PROC = {RefreshXR[constructionList]};
RefreshXR:
PROC[l:
LIST
OF ApplyRecord] =
{
IF l # NIL THEN {RefreshXR[l.rest]; JA.Apply[l.first.f, l.first.args, NIL]}};
SaveStateRec:
TYPE =
RECORD[
savePointLpad: PointPtr ← NIL,
saveEdgeLpad: EdgePtr ← NIL,
saveArcLpad: ArcPtr ← NIL,
saveLineLpad: LinPtr ← NIL,
saveCongLpad: CongPtr ← NIL,
saveHorLpad: HorPtr ← NIL,
saveVerLpad: VerPtr ← NIL,
saveStringLpad: StringPtr ← NIL,
saveCCLpad: CCPtr ← NIL];
UnSelected:
PROC[q:PointPtr]
RETURNS [
BOOLEAN] =
{p:PointPtr ← pointLpad.slink;
UNTIL p = pointRpad DO IF p = q THEN RETURN [FALSE] ELSE p ← p.slink ENDLOOP;
RETURN [TRUE]};