DIRECTORY Commander, Controls, Draw2d, G2dBasic, G2dMatrix, G2dTool, G2dVector, ImagerBackdoor, ImagerSample, RealFns, Rope, ViewerOps; G2dTransformCmdImpl: CEDAR PROGRAM IMPORTS Controls, Draw2d, G2dMatrix, G2dTool, G2dVector, ImagerBackdoor, ImagerSample, RealFns, ViewerOps ~ BEGIN Pair: TYPE ~ G2dBasic.Pair; PairSequence: TYPE ~ G2dBasic.PairSequence; Triple: TYPE ~ G2dBasic.Triple; TripleSequence: TYPE ~ G2dBasic.TripleSequence; Matrix: TYPE ~ G2dMatrix.Matrix; Data: TYPE ~ REF DataRep; DataRep: TYPE ~ RECORD [ s, sx, sy, r, tx, ty: Controls.Control ¬ NIL, vmin, vmax: Pair ¬ [0.0, 0.0], outerData: Controls.OuterData ¬ NIL, outer, graphics: Controls.Viewer ¬ NIL, buf: ImagerSample.SampleMap ¬ NIL, nPts: NAT ¬ 5, pts, nrms: PairSequence ¬ NIL, lines: TripleSequence ¬ NIL ]; TransformCmd: Commander.CommandProc ~ { d: Data ¬ NEW[DataRep]; d.tx ¬ Controls.NewControl[name: "TX", proc: T, clientData: d, min: -10., max: 10.0, init: 0]; d.ty ¬ Controls.NewControl[name: "TY", proc: T, clientData: d, min: -10., max: 10.0, init: 0]; d.sx ¬ Controls.NewControl[name: "SX", proc: T, clientData: d, min: -10., max: 10.0, init: 1]; d.s ¬ Controls.NewControl[name: "S", proc: S, clientData: d, min: -10., max: 10.0, init: 1]; d.sy ¬ Controls.NewControl[name: "SY", proc: T, clientData: d, min: -10., max: 10.0, init: 1]; d.r ¬ Controls.NewControl[name: "R", proc: T, clientData: d, max: 360.0, init: 0.0]; d.outerData ¬ Controls.OuterViewer[ name: "2d Transform", buttons: LIST[ Controls.ClickButton["IP Out", IPOut, d], Controls.ClickButton["NPts", NPts, d], Controls.ClickButton["Reset", Reset, d]], controls: LIST[d.tx, d.ty, d.sx, d.s, d.sy, d.r], typescriptHeight: 18, graphicsHeight: 300, drawProc: Draw, clientData: d ]; d.outer ¬ d.outerData.parent; d.graphics ¬ d.outerData.graphics; Init[d]; }; Init: PROC [d: Data] ~ { IF d.pts = NIL OR d.pts.maxLength < d.nPts THEN { d.pts ¬ NEW[G2dBasic.PairSequenceRep[d.nPts]]; d.nrms ¬ NEW[G2dBasic.PairSequenceRep[d.nPts]]; d.lines ¬ NEW[G2dBasic.TripleSequenceRep[d.nPts]]; }; FOR i: NAT IN [0..d.nPts) DO a: REAL ¬ (2.0*3.141592)*REAL[i]/REAL[d.nPts]; c: Pair ¬ d.nrms[i] ¬ d.pts[i] ¬ [RealFns.Cos[a], RealFns.Sin[a]]; d.lines[i] ¬ [c.x, c.y, -c.x*c.x-c.y*c.y]; ENDLOOP; }; T: Controls.ControlProc ~ {Repaint[NARROW[control.clientData, Data], $Slider]}; S: Controls.ControlProc ~ { d: Data ¬ NARROW[control.clientData]; Controls.SetSliderDialValue[d.sx, control.value]; Controls.SetSliderDialValue[d.sy, control.value]; Repaint[d, $Slider]; }; Rotate: PROC [m: Matrix, degrees: REAL] RETURNS [Matrix] ~ { cosDeg: REAL ¬ RealFns.CosDeg[degrees]; sinDeg: REAL ¬ RealFns.SinDeg[degrees]; RETURN[G2dMatrix.Mul[m, [[cosDeg, sinDeg, 0.0], [-sinDeg, cosDeg, 0.0], [0.0, 0.0, 1.0]]]]; }; Reset: Controls.ClickProc ~ { d: Data ¬ NARROW[clientData]; Controls.Reset[d.sx, d.sy, d.s, d.r, d.tx, d.ty]; Repaint[d, $Init]; }; Repaint: PROC [d: Data, r: REF ANY] ~ {ViewerOps.PaintViewer[d.graphics, client, FALSE, r]}; Draw: Controls.DrawProc ~ { Buffer: PROC [op: {save, restore}] ~ { Save: PROC [pm: Imager.PixelMap] ~ {d.buf ¬ ImagerSample.Copy[pm[0]]}; Restore: PROC [pm: Imager.PixelMap] ~ {ImagerSample.Transfer[pm[0], d.buf]}; r: Imager.Rectangle ¬ ImagerBackdoor.GetBounds[context]; ImagerBackdoor.AccessBufferRectangle[context, IF op = save THEN Save ELSE Restore, r]; }; InvViewPt: PROC [p: Pair] RETURNS [q: Pair] ~ {q ¬ [(p.x-200.0)/50.0, (p.y-200.0)/50.0]}; ViewPt: PROC [p: Pair] RETURNS [q: Pair] ~ {q ¬ [200.0+50.0*p.x, 150.0+50.0*p.y]}; Segment: PROC [p1, p2: Pair] ~ {Draw2d.Line[context, ViewPt[p1], ViewPt[p2], type]}; Arrow:PROC[p,v:Pair]~{Draw2d.Arrow[context,ViewPt[p],ViewPt[G2dVector.Add[p,v]],type]}; DrawLine: PROC [l: Triple] ~ { IF ABS[l.y] < 0.0001 THEN IF ABS[l.x] < 0.0001 THEN RETURN ELSE Segment[[-l.z/l.x, 2*d.vmin.y], [-l.z/l.x, d.vmax.y]] ELSE Segment[[d.vmin.x,(-l.z-l.x*(d.vmin.x))/l.y], [d.vmax.x,(-l.z-l.x*d.vmax.x)/l.y]]; }; PreMultiplyNormal: PROC [n: Pair, i: Matrix] RETURNS [Pair] ~ { RETURN[[i.row1.x*n.x+i.row1.y*n.y, i.row2.x*n.x+i.row2.y*n.y]]; }; PreMultiplyLine: PROC [l: Triple, i: Matrix] RETURNS [Triple] ~ { RETURN[[ i.row1.x*l.x+i.row1.y*l.y+i.row1.z*l.z, i.row2.x*l.x+i.row2.y*l.y+i.row2.z*l.z, i.row3.x*l.x+i.row3.y*l.y+i.row3.z*l.z]]; }; XformPt: PROC [p: Pair, i: Matrix] RETURNS [Pair] ~ { xHP: Triple ¬ G2dMatrix.Transform[[p.x, p.y, 1.0], i]; RETURN[[xHP.x/xHP.z, xHP.y/xHP.z]]; }; Action: PROC ~ { DrawTransformed: PROC ~ { x: Matrix ¬ G2dMatrix.Translate[ Rotate[ G2dMatrix.Scale[ G2dMatrix.Identity[], [d.sx.value, d.sy.value]], d.r.value], [d.tx.value, d.ty.value]]; adjoint: Matrix ¬ G2dMatrix.Adjoint[x]; xP0: Pair ¬ XformPt[d.pts[d.nPts-1], x]; FOR i: NAT IN [0..d.nPts) DO xP1: Pair ¬ XformPt[d.pts[i], x]; n: Pair ¬ d.nrms[i]; xHN: Triple ¬ G2dMatrix.Transform[[n.x, n.y, 0.0], x]; type ¬ dashed; Arrow[xP1, [xHN.x, xHN.y]]; type ¬ solid; Arrow[xP1, PreMultiplyNormal[d.nrms[i], adjoint]]; Segment[xP0, xP1]; xP0 ¬ xP1; ENDLOOP; }; DrawOriginal: PROC ~ { FOR i: NAT IN [0..d.nPts) DO p1: Pair ¬ d.pts[i]; Arrow[p1, d.nrms[i]]; Segment[p1, d.pts[(i+1) MOD d.nPts]]; ENDLOOP; }; SELECT whatChanged FROM $IPOut => DrawTransformed[]; $Slider => {Buffer[restore]; DrawTransformed[]}; ENDCASE => { d.vmin ¬ InvViewPt[[viewer.wx, viewer.wy]]; d.vmax ¬ InvViewPt[[viewer.wx+viewer.ww, viewer.wy+viewer.wh]]; DrawOriginal[]; Buffer[save]; IF whatChanged = $Init THEN DrawTransformed[]; }; }; d: Data ¬ NARROW[clientData]; type: Draw2d.DrawType ¬ solid; Draw2d.DoWithBuffer[context, Action]; }; NPts: Controls.ClickProc ~ { d: Data ¬ NARROW[clientData]; d.nPts ¬ Controls.GetNat[d.outerData.typescript, "# points: ", d.nPts]; Init[d]; Repaint[d, $Init]; }; IPOut: Controls.ClickProc ~ { d: Data ¬ NARROW[clientData]; fileName: Rope.ROPE ¬ Controls.TypescriptReadFileName[d.outerData.typescript]; IF fileName # NIL THEN Draw2d.IPOut[fileName, Draw, d]; }; G2dTool.Register["Transform", TransformCmd, "2d transformations test"]; END. Ψ G2dTransformCmdImpl.mesa Copyright Σ 1988, 1992 by Xerox Corporation. All rights reserved. Bloomenthal, July 20, 1992 1:09 pm PDT type _ dashed; DrawLine[PreMultiplyLine[d.lines[i], adjoint]]; type _ solid; ΚT•NewlineDelimiter –"cedarcode" style™™Jšœ Οeœ6™BJ™&—˜šΟk œ~˜‡J˜——šΠlnœžœž˜"šžœb˜iJ˜——šœž˜J˜Jšœ žœ˜ Jšœžœ˜-Jšœ žœ˜#Jšœžœ˜1šœ žœ˜$J˜—Jšœ žœžœ ˜šœ žœžœ˜Jšœ,žœ˜0J˜#Jšœ%žœ˜)Jšœ'žœ˜+Jšœ%žœ˜)Jšœ žœ˜Jšœžœ˜#Jšœž˜"Jšœ˜J˜—šΠbn œ˜'Jšœ žœ ˜JšœΟsœ‘œ"‘œ˜^Jšœ‘œ‘œ"‘œ˜^Jšœ‘œ‘œ"‘œ˜^Jšœ‘œ‘œ"‘œ˜\Jšœ‘œ‘œ"‘œ˜^Jšœ‘œN˜T˜#Jšœ˜šœ žœ˜Jšœ)˜)Jšœ&˜&Jšœ)˜)—Jšœ žœ#˜1J˜J˜J˜J˜ J˜—J˜J˜"J˜J˜J˜—šΟnœžœ˜šžœ žœžœžœ˜1Jšœžœ#˜.Jšœ žœ#˜/Jšœ žœ%˜2J˜—šžœžœžœ ž˜Jšœžœžœžœ ˜.J˜BJ˜*Jšžœ˜—J˜J˜—š œ"žœ&˜OJ˜—šΟbœ˜Jšœ žœ˜%Jšœ1˜1Jšœ1˜1J˜Jšœ˜J˜—š’œžœžœžœ ˜