ImplicitWingCmdImpl.mesa
Copyright Ó 1991 by Xerox Corporation. All rights reserved.
Bloomenthal, August 11, 1992 4:02 pm PDT
DIRECTORY Commander, CommanderOps, Controls, Draw2d, FileNames, G3dBasic, G3dDraw, G3dMatrix, G3dTube, G3dSpline, G3dTool, G3dVector, ImplicitConvolve, ImplicitDefs, ImplicitDesign, IO, Menus, Rope, TerminalIO;
ImplicitPetalCmdImpl: CEDAR PROGRAM
IMPORTS CommanderOps, Controls, FileNames, G3dBasic, G3dDraw, G3dTube, G3dSpline, G3dTool, G3dVector, ImplicitConvolve, ImplicitDesign, IO, Rope
~ BEGIN
Imported Types
RealSequence:   TYPE ~ G3dBasic.RealSequence;
Triple:     TYPE ~ G3dBasic.Triple;
TripleSequence:   TYPE ~ G3dBasic.TripleSequence;
TripleSequenceRep:  TYPE ~ G3dBasic.TripleSequenceRep;
Spline:     TYPE ~ G3dSpline.Spline;
SplineSequence:   TYPE ~ G3dSpline.SplineSequence;
Tube:      TYPE ~ G3dTube.Tube;
ClickProc:    TYPE ~ Menus.ClickProc;
ROPE:      TYPE ~ Rope.ROPE;
Primitive:     TYPE ~ ImplicitConvolve.Primitive;
PrimitiveList:   TYPE ~ ImplicitConvolve.PrimitiveList;
TripleList:    TYPE ~ ImplicitConvolve.TripleList;
The Long Awaited ~WING~
WingData:    TYPE ~ REF WingDataRep;
WingDataRep:   TYPE ~ RECORD [
tool:        ImplicitDesign.Tool ¬ NIL,
tube:        Tube ¬ NIL,
primitives:      PrimitiveList ¬ NIL,
c0, c1:       Spline ¬ NIL,
lofts:        SplineSequence ¬ NIL,
kHeight:       REAL ¬ 0.5,
kWidth:       REAL ¬ 0.25,
kSag:        REAL ¬ -0.2,
thickness:      REAL ¬ 0.01,
doWeb, doVeins:    BOOL ¬ TRUE,
showLofts, showSplines:  BOOL ¬ TRUE,
showLines:      BOOL ¬ FALSE
];
WingCmd: Commander.CommandProc ~ {
argv: CommanderOps.ArgumentVector ¬ CommanderOps.Parse[cmd];
FOR n: NAT IN [0..argv.argc-1) DO
IF Rope.Equal[argv[n], "-tube", FALSE] THEN {Wing[cmd, argv[n+1]]; RETURN};
ENDLOOP;
RETURN[$Failure, "must specify -tube <name>"];
};
Wing: PROC [cmd: Commander.Handle, tubeName: ROPE] ~ {
w: WingData ¬ NEW[WingDataRep];
w.tube ¬ G3dTube.TubeFromFile[FileNames.ResolveRelativePath[tubeName]];
IF w.tube = NIL OR G3dTube.NBranches[w.tube, TRUE] # 2
THEN IO.PutF[cmd.out, "bad tube\n"]
ELSE {
G3dTube.SelectAll[w.tube];
G3dTube.Make[w.tube];
MakeWing[w, 6];
w.tool ¬ ImplicitConvolve.MakeTool[
cmd: cmd,
name: "WINGing it!",
polys: w.primitives,
extraButtons: LIST[
Controls.ClickButton["Height", KHeight, w, 1],
Controls.ClickButton["Width", KWidth, w, 1],
Controls.ClickButton["Sag", KSag, w, 1],
Controls.ClickButton["NLofts", NLofts, w, 1],
Controls.ClickButton["Thick", Thickness, w, 1],
Controls.ClickButton["Veins-On", ToggleVeins, w, 1],
Controls.ClickButton["Web-On", ToggleWeb, w, 1]],
Controls.ClickButton["Lofts-On", ToggleLoft, w, 2],
Controls.ClickButton["Lines-Off", ToggleLine, w, 2],
Controls.ClickButton["Splines-On", ToggleSpline, w, 2],
draw: Draw,
data: w,
toolSettings: [trackSize: .015, threshold: 0.25]
]
};
};
Display
MakeWing: PROC [w: WingData, nLofts: NAT, repaint: BOOL ¬ FALSE] ~ {
MakeLofts[w, nLofts];
MakePrimitives[w];
IF repaint THEN ImplicitDesign.Repaint[w.tool];
};
Draw: Draw2d.DrawProc ~ {
Action: PROC ~ {
IF w.showLines THEN G3dTube.DrawLines[context, w.tube, view];
IF w.showSplines THEN G3dTube.DrawSplines[context, w.tube, view];
IF w.showLofts THEN G3dDraw.DrawCurves[context, w.lofts, view];
};
w: WingData ¬ NARROW[clientData];
view: G3dMatrix.Matrix ¬ G3dTool.GetViewTransform[viewer];
WrapInCG6[context, Action];
};
Geometry
MakePrimitives: PROC [w: WingData] ~ {
AddPrimitive: PROC [list: TripleList, intensity, extent: REAL, intensities: RealSequence ¬ NIL]
~ {
ScaleOffset: PROC [list: TripleList, scale, zOffset: REAL] RETURNS [p: TripleSequence] ~ {
p ¬ G3dBasic.TripleSequenceFromList[list];
FOR n: NAT IN [0..p.length) DO
p[n] ¬ G3dVector.Sub[G3dVector.Mul[p[n], scale], [0, 0, zOffset]];
ENDLOOP;
};
pts: TripleSequence ¬ ScaleOffset[list, 1.75, .5];
p: Primitive ¬ ImplicitConvolve.MakePrimitive[pts, extent,, intensity, intensities,, [55, 55]];
p.display ¬ display;
display ¬ IF (count ¬ count+1) MOD 6 = 0
THEN [5, display.y+p.res.y+5]
ELSE [display.x+p.res.x+5, display.y];
w.primitives ¬ CONS[p, w.primitives];
};
AddSegment: PROC [p1, p2: Triple, intensities: RealSequence ¬ NIL] ~ {
AddPrimitive[LIST[p1, p2], 1.0, .04, intensities];
};
AddRectangle: PROC [p1, p2, p3, p4: Triple] ~ {AddPrimitive[LIST[p1, p2, p3, p4], .75, .015]};
MakeRectangles: PROC [res: NAT] ~ {
pts1: TripleSequence ¬ NEW[TripleSequenceRep[res+1]];
pts2: TripleSequence ¬ NEW[TripleSequenceRep[res+1]];
FOR n: NAT IN [0..res] DO pts1[n] ¬ w.tube.p1; ENDLOOP;
FOR n: NAT IN [0..w.lofts.length) DO
FOR i: NAT IN [0..res] DO
pts2[i] ¬ G3dSpline.Position[w.lofts[n], REAL[i]/REAL[res]];
ENDLOOP;
FOR i: NAT IN [0..res) DO AddRectangle[pts1[i], pts1[i+1], pts2[i+1], pts2[i]]; ENDLOOP;
{temp: TripleSequence ¬ pts1; pts1 ¬ pts2; pts2 ¬ temp};
ENDLOOP;
};
MakeSegments: PROC [s: Spline, res: NAT] ~ {
p1: Triple ¬ w.tube.p1;
FOR i: NAT IN [1..res] DO
t: REAL ¬ REAL[i]/REAL[res];
p2: Triple ¬ G3dSpline.Position[s, REAL[i]/REAL[res]];
intensities: RealSequence ¬ NEW[G3dBasic.RealSequenceRep[2]];
intensities[0] ¬ 1.0-REAL[i]/REAL[res];
intensities[1] ¬ 1.0-REAL[i-1]/REAL[res];
AddSegment[p1, p2, intensities];
p1 ¬ p2;
ENDLOOP;
};
count: NAT ¬ 0;
display: ImplicitConvolve.NatPair ¬ [5, 5];
MakeSegments[w.c0, w.lofts.length];
MakeSegments[w.c1, w.lofts.length];
MakeRectangles[w.lofts.length];
};
MakeLofts: PROC [w: WingData, nLofts: NAT] ~ {
Loft: PROC [c0, c1: Spline, t, kWide, kHigh, kSag: REAL, out: Spline] RETURNS [Spline] ~ {
p0, p1, v0, v1, p0p1, pMid, vSum, beam, pp0, pp1, cross, sag: Triple;
[p0, v0] ¬ G3dSpline.PositionAndVelocity[c0, t];
[p1, v1] ¬ G3dSpline.PositionAndVelocity[c1, t];
p0p1 ¬ [p1.x-p0.x, p1.y-p0.y, p1.z-p0.z];
beam ¬ [p0p1.x*kWide, p0p1.y*kWide, p0p1.z*kWide];
pMid ¬ [0.5*(p0.x+p1.x), 0.5*(p0.y+p1.y), 0.5*(p0.z+p1.z)];
vSum ¬ [v0.x+v1.x, v0.y+v1.y, v0.z+v1.z];
pp0 ¬ [pMid.x-beam.x, pMid.y-beam.y, pMid.z-beam.z];
pp1 ¬ [pMid.x+beam.x, pMid.y+beam.y, pMid.z+beam.z];
cross ¬G3dVector.SetVectorLength[G3dVector.Cross[v0,v1],kHigh*G3dVector.Length[p0p1]];
sag ¬ G3dVector.SetVectorLength[vSum, -t*t*kSag];
pp0 ¬ [pp0.x+cross.x+sag.x, pp0.y+cross.y+sag.y, pp0.z+cross.z+sag.z];
pp1 ¬ [pp1.x+cross.x+sag.x, pp1.y+cross.y+sag.y, pp1.z+cross.z+sag.z];
RETURN[G3dSpline.SplineFromBezier[[p0, pp0, pp1, p1], out]];
};
w.c0 ¬ G3dTube.GetBranch[w.tube, 0].spline;
w.c1 ¬ G3dTube.GetBranch[w.tube, 1].spline;
IF w.lofts = NIL THEN w.lofts ¬ NEW[G3dSpline.SplineSequenceRep[nLofts]];
IF w.lofts.maxLength < nLofts THEN {
old: SplineSequence ¬ w.lofts;
w.lofts ¬ NEW [G3dSpline.SplineSequenceRep[nLofts]];
FOR n: NAT IN [0..old.length) DO w.lofts[n] ¬ old[n]; ENDLOOP;
};
w.lofts.length ¬ nLofts;
FOR n: NAT IN [1..nLofts] DO
t: REAL ¬ REAL[n]/REAL[nLofts];
w.lofts[n-1] ¬ Loft[w.c0, w.c1, t, w.kWidth, w.kHeight, w.kSag, w.lofts[n-1]];
ENDLOOP;
};
[Artwork node; type 'Artwork on' to command tool]
Diagram of lofts
Buttons
NLofts: ClickProc ~ {
w: WingData ¬ NARROW[clientData];
MakeWing[w, MAX[1, Controls.GetNat[w.tool.typescript, "NLofts", w.lofts.length]], TRUE];
};
Thickness: ClickProc ~ {
w: WingData ¬ NARROW[clientData];
w.thickness ¬ Controls.TypescriptReadValue[w.tool.typescript, "Thickness", w.thickness];
};
KHeight: ClickProc ~ {
w: WingData ¬ NARROW[clientData];
w.kHeight ¬ Controls.TypescriptReadValue[w.tool.typescript, "KHeight", w.kHeight];
MakeWing[w, w.lofts.length, TRUE];
};
KWidth: ClickProc ~ {
w: WingData ¬ NARROW[clientData];
w.kWidth ¬ Controls.TypescriptReadValue[w.tool.typescript, "KWidth", w.kWidth];
MakeWing[w, w.lofts.length, TRUE];
};
KSag: ClickProc ~ {
w: WingData ¬ NARROW[clientData];
w.kSag ¬ Controls.TypescriptReadValue[w.tool.typescript, "KSag", w.kSag];
MakeWing[w, w.lofts.length, TRUE];
};
Option: TYPE ~ {web, veins, lofts, lines, splines};
ToggleWeb:   ClickProc ~ {Toggle[clientData, mouseButton, web,  "Web"]};
ToggleVeins:  ClickProc ~ {Toggle[clientData, mouseButton, veins,  "Veins"]};
ToggleLoft:   ClickProc ~ {Toggle[clientData, mouseButton, lofts,  "Lofts"]};
ToggleLine:  ClickProc ~ {Toggle[clientData, mouseButton, lines,  "Lines"]};
ToggleSpline:  ClickProc ~ {Toggle[clientData, mouseButton, splines,  "Splines"]};
Toggle: PROC [ref: REF, button: Menus.MouseButton, option: Option, name: ROPE] ~ {
w: WingData ¬ NARROW[ref];
state: BOOL ¬ SELECT option FROM
web  => w.doWeb    ¬ NOT w.doWeb,
veins  => w.doVeins   ¬ NOT w.doVeins,
lofts  => w.showLofts   ¬ NOT w.showLofts,
lines  => w.showLines   ¬ NOT w.showLines,
splines => w.showSplines  ¬ NOT w.showSplines,
ENDCASE => TRUE;
Controls.ButtonToggle[
w.tool.renderTool.outerData, state, Rope.Cat[name, "-On"], Rope.Cat[name, "-Off"]];
IF button = blue THEN ImplicitDesign.Repaint[w.tool, NIL];
};
Start Code
ImplicitDesign.Register["Wing", WingCmd, "\ta wing?", "ImplicitConvolve"];
END.