G2dTransformCmdImpl.mesa
Copyright Ó 1988, 1992 by Xerox Corporation. All rights reserved.
Bloomenthal, July 20, 1992 1:09 pm PDT
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; DrawLine[PreMultiplyLine[d.lines[i], adjoint]]; type ← solid;
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.