ImplicitConvolveToolImpl.mesa
Copyright Ó 1990 by Xerox Corporation. All rights reserved.
Bloomenthal, November 30, 1992 2:59 pm PST
DIRECTORY CedarProcess, Commander, Controls, Convert, CtBasic, CtViewer, G3dBasic, G3dDraw, G3dMatrix, G3dShape, G3dTool, Imager, ImagerColor, ImplicitConvolve, ImplicitDefs, ImplicitDesign, ImplicitMinimal, IO, MessageWindow, ProcessProps, Real, Rope, SF, ViewerClasses, ViewerSpecs;
ImplicitConvolveToolImpl: CEDAR PROGRAM
IMPORTS CedarProcess, Controls, Convert, CtBasic, CtViewer, G3dDraw, G3dTool, ImplicitConvolve, ImplicitDesign, ImplicitMinimal, IO, MessageWindow, ProcessProps, Rope, SF, ViewerSpecs
EXPORTS ImplicitConvolve
~ BEGIN
Types and Constants
Box:     TYPE ~ CtBasic.Box;
SampleMap:   TYPE ~ CtBasic.SampleMap;
Triple:    TYPE ~ G3dBasic.Triple;
Context:    TYPE ~ Imager.Context;
IntegerPair:   TYPE ~ ImplicitConvolve.IntegerPair;
Primitive:    TYPE ~ ImplicitConvolve.Primitive;
PrimitiveList:  TYPE ~ ImplicitConvolve.PrimitiveList;
PrimitiveProc:  TYPE ~ ImplicitConvolve.PrimitiveProc;
Tool:     TYPE ~ ImplicitConvolve.Tool;
ToolRep:    TYPE ~ ImplicitConvolve.ToolRep;
ROPE:     TYPE ~ Rope.ROPE;
ClickProc:   TYPE ~ ViewerClasses.ClickProc;
Viewer:    TYPE ~ ViewerClasses.Viewer;
margin:    INTEGER ¬ 4;
Convolve Tool
MakeTool: PUBLIC PROC [
name:    Rope.ROPE ¬ NIL,
primitives:  PrimitiveList ¬ NIL,
convexSolids:  LIST OF PrimitiveList ¬ NIL,
res:    IntegerPair ¬ [50, 50],
client:    G3dTool.Client ¬ [],
ops:    G3dTool.Operations ¬ G3dTool.allOps,
extraControls:  LIST OF Controls.Control ¬ NIL,
extraButtons:  LIST OF Controls.Button ¬ NIL,
controlSizes:  Controls.ControlSizes ¬ [],
useArcBalls:  BOOL ¬ TRUE,
arcBallSize:  INT ¬ 136,
graphicsHeight: INT ¬ 475,
camera:   G3dTool.CameraRep ¬ [[0, 2, 0], [], 1, 60],
background:  Triple ¬ [0.3, 0.3, 1.0],
noOpen:   BOOL ¬ FALSE,
toolSettings:  ImplicitDesign.ToolRep ¬ [],
tool3dSettings: G3dTool.ToolRep ¬ []]
RETURNS [Tool]
~ {
CountActive: PrimitiveProc ~ {IF p.active THEN t.nPrimitives ¬ t.nPrimitives+1};
SetID: PrimitiveProc ~ {IF p.id = -1 THEN {p.id ¬ id; id ¬ id+1}};
id: INTEGER ¬ 0;
t: Tool ¬ NEW[ToolRep¬[client:client, res:res, primitives:primitives, convexSolids:convexSolids]];
DoWithAllPrimitives[t, CountActive];
DoWithAllPrimitives[t, SetID];
IF res = [0, 0] THEN t.res ¬ [50, 50] ELSE SetRes[t, res];
FOR b: LIST OF Controls.Button ¬ LIST[
Controls.ClickButton["Maps", Maps, t, 1],
Controls.ClickButton["DoAll", DoAll, t, 1]],
Controls.ClickButton["Interp: On", InterpButton, t, 1],
b.rest WHILE b # NIL DO
extraButtons ¬ CONS[b.first, extraButtons];
ENDLOOP;
t.cmd ¬ NARROW[ProcessProps.GetProp[$CommanderHandle], Commander.Handle];
t.tool ¬ ImplicitDesign.MakeTool[
name: name,
function: Function,
start: Start,
client: [draw: Draw, data: t],
ops: ops,
extraButtons: extraButtons,
extraControls: extraControls,
controlSizes: controlSizes,
useArcBalls: useArcBalls,
arcBallSize: arcBallSize,
graphicsHeight: graphicsHeight,
camera: camera,
background: background,
noOpen: noOpen,
toolSettings: toolSettings,
tool3dSettings: tool3dSettings
];
SetToolSettingsFromLog[t, name];
RETURN[t];
};
SetToolSettingsFromLog: PROC [t: Tool, name: ROPE] ~ {
GetArg: PROC [key: ROPE] RETURNS [rope: ROPE ¬ NIL] ~ {
i: INT ¬ Rope.Find[entry, key,, FALSE];
IF i # -1 THEN {
ii: INT ¬ Rope.SkipOver[entry, i+Rope.Length[key], ": \t"];
rope ¬ Rope.Substr[entry, ii, Rope.SkipTo[entry, ii, ",: \t\n"]-ii];
};
};
GetInt: PROC [key: ROPE, def: INT] RETURNS [r: INT] ~ {
r ¬ Convert.IntFromRope[GetArg[key] ! Convert.Error => {r ¬ def; CONTINUE}];
};
GetBool: PROC [key: ROPE, def: BOOL] RETURNS [r: BOOL] ~ {
Eq: PROC [r1, r2: ROPE] RETURNS [b: BOOL] ~ {b ¬ Rope.Equal[r1, r2, FALSE]};
a: ROPE ¬ GetArg[key];
r ¬ SELECT TRUE FROM Eq[a, "true"] => TRUE, Eq[a, "false"] => FALSE, ENDCASE => def;
};
entry: ROPE ¬ ImplicitDesign.GetLogEntry[t.tool, name];
IF entry = NIL THEN RETURN;
t.res ¬ [GetInt["resx", t.res.x], GetInt["resx", t.res.y]];
t.filter ¬ GetBool["filter", t.filter];
t.interp ¬ GetBool["interp", t.interp];
};
Document: ImplicitDefs.DocProc ~ {
t: Tool ¬ NARROW[clientData];
doc ¬ IO.PutFLR["resx: %g, resy: %g, filter: %g, interp: %g",
LIST[IO.int[t.res.x], IO.int[t.res.y], IO.bool[t.filter], IO.bool[t.interp]]];
};
DoWithAllPrimitives: PROC [t: Tool, action: PrimitiveProc] ~ {
FOR s: LIST OF PrimitiveList ¬ t.convexSolids, s.rest WHILE s # NIL DO
FOR l: PrimitiveList ¬ s.first, l.rest WHILE l # NIL DO
CedarProcess.CheckAbort[];
IF NOT action[l.first] THEN RETURN;
ENDLOOP;
ENDLOOP;
FOR l: PrimitiveList ¬ t.primitives, l.rest WHILE l # NIL DO
CedarProcess.CheckAbort[];
IF NOT action[l.first] THEN RETURN;
ENDLOOP;
};
Union: PROC[b1,b2:Box]RETURNS[u:Box]~{u¬[SF.Min[b1.min,b2.min],SF.Max[b1.max,b2.max]]};
ShowMaps: PROC [t: Tool, map: SampleMap] RETURNS [affectedRegion: Box] ~ {
FOR l: PrimitiveList ¬ t.primitives, l.rest WHILE l # NIL DO
affectedRegion ¬ Union[affectedRegion, ShowMap[l.first, map]];
ENDLOOP;
};
ShowMap: PROC [p: Primitive, map: SampleMap] RETURNS [affectedRegion: Box] ~ {
affectedRegion ¬ [[p.display.y, p.display.x], [p.display.y+p.res.y, p.display.x+p.res.x]];
ImplicitConvolve.DisplayPrimitive[p, map];
};
debug: BOOL ¬ FALSE;
Draw: G3dTool.DrawProc ~ {
t: Tool ¬ NARROW[clientData];
IF whatChanged = $Overlay THEN RETURN;
IF t.client.draw # NIL
THEN t.client.draw[context, viewer, whatChanged, view, vp, v, tool, t.client.data];
ImplicitConvolve.DrawPrimitives[t.primitives, context, view, vp, whatChanged, solid];
FOR s: LIST OF PrimitiveList ¬ t.convexSolids, s.rest WHILE s # NIL DO
ImplicitConvolve.DrawPrimitives[s.first, context, view, vp, whatChanged, solid];
ENDLOOP;
IF debug THEN FOR l: PrimitiveList ¬ t.primitives, l.rest WHILE l # NIL DO
p: Primitive ¬ l.first;
IF p.twist.tw0 # 0 THEN {
G3dDraw.Vector[context, p.origin, p.normal, view, vp, "n"];
G3dDraw.Vector[context, p.origin, p.xAxis, view, vp, "x"];
G3dDraw.Vector[context, p.origin, p.yAxis, view, vp, "y"];
G3dDraw.Mark[context, p.p0x, view, vp, "p0x", asterisk];
G3dDraw.Mark[context, p.twist.p0, view, vp, "p0", asterisk];
G3dDraw.Mark[context, p.twist.p1, view, vp, "p1", asterisk];
};
IF p.points.length = 2 THEN {
G3dDraw.Mark[context, p.points[0], view, vp];
G3dDraw.Mark[context, p.points[1], view, vp];
};
ENDLOOP;
};
Convolving
GetFilterViewer: PROC [t: Tool] RETURNS [v: Viewer] ~ {
NextDisplay: PROC [now, res: IntegerPair] RETURNS [next: IntegerPair] ~ {
IF INT[now.x+2*res.x+margin] > (width-2)
THEN {next ¬ [margin, now.y+hRow+margin]; hRow ¬ res.y}
ELSE {next ¬ [now.x+res.x+margin, now.y]; hRow ¬ MAX[hRow, res.y]};
};
Ht: PROC [primitives: PrimitiveList] RETURNS [h: INTEGER ¬ 0] ~ {
High: PrimitiveProc ~ {
IF NOT p.active THEN RETURN;
h ¬ MAX[h, INTEGER[display.y+p.res.y+margin]];
display ¬ NextDisplay[display, p.res];
};
DoWithAllPrimitives[t, High];
h ¬ MIN[h+14, ViewerSpecs.bwScreenHeight-200];
};
hRow: INTEGER ¬ 0;
display: IntegerPair ¬ [margin, margin];
width: INTEGER ¬ ViewerSpecs.openRightWidth;
name: ROPE ¬ Rope.Concat["ImpImages: ", t.tool.tool3d.name];
v ¬ CtViewer.GetViewer[name, right, Ht[t.primitives], TRUE, TRUE];
};
Clear: CtViewer.ViewerProc ~ {CtBasic.FillBWMap[maps[0].map, 255]};
Show: CtViewer.ViewerProc ~ {RETURN[ShowMap[NARROW[clientData], maps[0].map]]};
DoMakeMaps: PUBLIC PROC [t: Tool] ~ {
Process: PrimitiveProc ~ {
NextDisplay: PROC [now, res: IntegerPair] RETURNS [next: IntegerPair] ~ {
IF INT[now.x+2*res.x+margin] > v.cw
THEN {next ¬ [margin, now.y+hRow+margin]; hRow ¬ res.y}
ELSE {next ¬ [now.x+res.x+margin, now.y]; hRow ¬ MAX[hRow, res.y]};
IF INT[next.y+p.res.y] > v.ch THEN next.y ¬ margin;
};
IF p.active THEN {
msg: ROPE ¬ IO.PutFR["%g/%g maps made", IO.int[done¬done+1], IO.int[t.nPrimitives]];
ImplicitConvolve.ConvolvePrimitive[p, t.filter];
p.display ¬ display;
CtViewer.DoWithViewer[v, Show, p];
display ¬ NextDisplay[display, p.res];
MessageWindow.Append[msg, TRUE];
TerminalIO.PutF["primitive %g: min value = %g, max value = %g, ave value = %g\n", IO.int[p.id],IO.real[ImplicitConvolve.ValueOfPrimitive[p.bounds.min,p]],IO.real[ImplicitConvolve.ValueOfPrimitive[p.bounds.max,p]],IO.real[ImplicitConvolve.ValueOfPrimitive[G3dVector.Midpoint[p.bounds.max,p.bounds.min], p]]];
};
};
done: INTEGER ¬ 0;
hRow: INTEGER ¬ 0;
display: IntegerPair ¬ [margin, margin];
v: Viewer ¬ GetFilterViewer[t];
G3dTool.TSWrite[t.tool.tool3d, "Making maps . . . "];
CtViewer.DoWithViewer[v, Clear];
DoWithAllPrimitives[t, Process];
G3dTool.TSWrite[t.tool.tool3d, "done\n"];
};
SetRes: PROC [t: Tool, res: IntegerPair] ~ {
Set: PrimitiveProc ~ {p.res ¬ t.res; ImplicitConvolve.SetGeometry[p]};
t.res ¬ res;
DoWithAllPrimitives[t, Set];
};
Extent: Controls.ClickProc ~ {
Set: PrimitiveProc ~ {p.extent ¬ extent; ImplicitConvolve.SetGeometry[p]};
t: Tool ¬ NARROW[clientData];
extent: REAL ¬ Convert.RealFromRope[ViewerTools.GetContents[t.extent.textViewer]];
DoWithAllPrimitives[t, Set];
};
Buttons
DoAll: ClickProc ~ {[] ¬ ImplicitDesign.MaybeFork[NARROW[clientData, Tool].tool, ForkDoAll]};
ForkDoAll: CedarProcess.ForkableProc ~ {
tool: ImplicitDesign.Tool ¬ NARROW[data];
DoMakeMaps[NARROW[tool.client.data]];
ImplicitDesign.Triangulate[tool];
AddColor[tool];
G3dTool.Render[tool.tool3d];
};
Maps: ClickProc ~ {
t: Tool ¬ NARROW[clientData];
IF mouseButton = red
THEN [] ¬ ImplicitDesign.MaybeFork[t.tool, ForkMakeMaps]
ELSE {
SELECT Controls.PopUpRequest[["Map Operations"], LIST[
["Set resolution", IO.PutFR["now (%g, %g)", IO.int[t.res.x], IO.int[t.res.y]]],
["Toggle filter", IO.PutFR1["now %g", IO.rope[IF t.filter THEN "on" ELSE "off"]]]]]
FROM
1 => SetRes[t, Controls.GetIntegerPair[t.tool.tool3d.typescript, "res", t.res]];
2 => t.filter ¬ NOT t.filter;
ENDCASE;
};
};
ForkMakeMaps: CedarProcess.ForkableProc ~ {
tool: ImplicitDesign.Tool ¬ NARROW[data];
DoMakeMaps[NARROW[tool.client.data]];
};
InterpButton: Controls.ClickProc ~ {
Set: PrimitiveProc ~ {p.interp ¬ t.interp};
t: Tool ¬ NARROW[clientData];
Controls.ButtonToggle[t.tool.outerData, t.interp ¬ NOT t.interp, "Interp: On", "Interp: Off"];
DoWithAllPrimitives[t, Set];
};
Implicit Evaluation
Start: ImplicitDesign.StartProc ~ {
FindStart: PrimitiveProc ~ {
FOR i: INT IN [0..p.points.length) DO
point ¬ ImplicitMinimal.FindStart[p.points[i], Function, t.tool.size, t.tool.level, clientData
! ImplicitMinimal.Error => LOOP];
RETURN[FALSE];
ENDLOOP;
};
t: Tool ¬ NARROW[clientData];
IF t.anim # NIL AND nFrames > 1 THEN t.anim[REAL[frame]/REAL[nFrames-1], t, use];
DoWithAllPrimitives[t, FindStart];
};
AddColor: PROC [t: ImplicitDesign.Tool] ~ {
rt: G3dTool.Tool ¬ t.tool3d;
ct: Tool ¬ NARROW[t.client.data];
IF rt.shapes # NIL THEN
FOR i: INTEGER IN [0..rt.shapes.length) DO
FOR j: INTEGER IN [0..rt.shapes[i].vertices.length) DO
Process: PrimitiveProc ~ {
IF p.active AND (val ¬ ImplicitConvolve.ValueOfPrimitive[v.point, p]) > 0 THEN {
sum ¬ sum+val;
rgb ¬ [rgb.R+val*p.color.R, rgb.G+val*p.color.G, rgb.B+val*p.color.B];
};
};
val, sum: REAL ¬ 0.0;
rgb: ImagerColor.RGB ¬ [0.0, 0.0, 0.0]; -- probably should do this in hsv space
v: G3dShape.Vertex ¬ rt.shapes[i].vertices[j];
DoWithAllPrimitives[ct, Process];
IF sum > 0.0 THEN v.color ¬ [rgb.R/sum, rgb.G/sum, rgb.B/sum];
ENDLOOP;
ENDLOOP;
};
Function: ImplicitMinimal.Function ~ {
Set: PrimitiveProc ~ {value ¬ value+ImplicitConvolve.ValueOfPrimitive[point, p]};
t: Tool ¬ NARROW[clientData];
ImplicitConvolve.InvalidateDistance[t.primitives];
FOR s: LIST OF PrimitiveList ¬ t.convexSolids, s.rest WHILE s # NIL DO
ImplicitConvolve.InvalidateDistance[s.first];
IF ImplicitConvolve.InsideSolid[point, s.first] THEN RETURN[Real.LargestNumber];
ENDLOOP;
DoWithAllPrimitives[t, Set];
};
END...
Height: PROC [primitives: PrimitiveList] RETURNS [h: INTEGER ¬ 0] ~ {
display: IntegerPair ¬ [5, 5];
FOR l: PrimitiveList ¬ t.primitives, l.rest WHILE l # NIL DO-- see block in DoMakeMaps
h ¬ MAX[h, l.first.display.y+l.first.res.y+5];
IF l.first.thickness # NIL AND l.first.thickness.array # NIL
THEN h ¬ MAX[h, l.first.thickness.display.y+l.first.res.y+5];
ENDLOOP;
h ¬ h+14;
};
SetDisplays: PROC [primitives: PrimitiveList] ~ {
display: IntegerPair ¬ [5, 5];
FOR l: PrimitiveList ¬ primitives, l.rest WHILE l # NIL DO
IF l.first.display = [0, 0] THEN l.first.display ¬ display ELSE display ¬ l.first.display;
display ¬ NextDisplay[display, l.first.res];
IF l.first.thickness = NIL OR l.first.thickness.array = NIL THEN LOOP;
IF l.first.thickness.display = [0, 0]
THEN l.first.thickness.display ¬ display ELSE display ¬ l.first.thickness.display;
display ¬ NextDisplay[display, l.first.res];
ENDLOOP;
};
ImplicitConvolveDebug: Commander.CommandProc ~ {
argv: CommanderOps.ArgumentVector ¬ CommanderOps.Parse[cmd];
IF argv.argc = 2
THEN SELECT TRUE FROM
Rope.Equal[argv[1], "on", FALSE] => debug ¬ TRUE;
Rope.Equal[argv[1], "off", FALSE] => debug ¬ FALSE;
ENDCASE => IO.PutF[cmd.out, "Bad argument\n"]
ELSE IO.PutF[cmd.out, "debug mode is %g\n", IO.rope[IF debug THEN "on" ELSE "off"]];
};
Commander.Register["ImplicitConvolveDebug", ImplicitConvolveDebug, "<on | off>"];