SimpleCombinerTester.mesa
Last Edited by: Arnon, June 20, 1985 4:46:23 pm PDT
DIRECTORY
ClientStateInfo USING [defaultState, State, StateEqual],
Convert USING [RopeFromCard],
Imager USING [Context, DoSaveAll, MaskFillTrajectory, MaskStrokeTrajectory, MaskVector, ScaleT, SetColor, SetFont, SetStrokeEnd, SetStrokeJoint, SetStrokeWidth, SetXY, ShowRope, TranslateT, VEC],
ImagerColor USING [ColorFromAtom],
ImagerFont USING [Find, Font, Scale],
ImagerPath USING [MoveTo, Trajectory],
FS USING [GetDefaultWDir],
IO USING [PutF, PutFR],
Menus USING [AppendMenuEntry, CreateEntry, CreateMenu, Menu, MenuProc],
MessageWindow USING [Append, Blink],
Random USING [ChooseInt, Create],
RatNums USING [RatNum, RatNumFromREAL],
RCombiner USING [in, out],
Real USING [Float],
Rope USING [ROPE, Cat],
RVHandleUtils USING [AddVertexToPolygon, AdjacencyHandle, AdjacencyHandleList, ClearVisitedFields, ConvexHull, ConvexPolygon, DumpVertexHandle, FindAdjacency, ImagerPolygonAndStateList, ImagerVecFromPoint, InitVertexHandle, PointList, PolygonExtractor, PreviousOutlineVertex, ReadIOVHLFromFile, ThreeOrMoreVertices, VertexHandle, vertexIndex, VertexVerifyIOVHLFromFile, VHandleFromIOVHL],
SimpleCombiner USING [Combiner, Outline, OutlinesFromCombinerStructure],
TIPUser USING [InstantiateNewTIPTable, TIPScreenCoords],
ViewerClasses USING [InitProc, NotifyProc, PaintProc, Viewer, ViewerClass, ViewerClassRec, ViewerRec],
ViewerIO USING [CreateViewerStreams],
ViewerOps USING [CreateViewer, PaintViewer, RegisterViewerClass];
SimpleCombinerTester: CEDAR PROGRAM
IMPORTS RatNums, RVHandleUtils, ClientStateInfo, RCombiner, SimpleCombiner, ViewerOps, Menus, MessageWindow, Imager, ImagerColor, ImagerFont, ImagerPath, TIPUser, Convert,
IO, ViewerIO, Real, Random, Rope,
FS
SHARES Imager =
BEGIN OPEN RN: RatNums, CSI: ClientStateInfo, RVHU: RVHandleUtils, RCB: RCombiner, SCB: SimpleCombiner;
PlaneStructure: TYPE = RVHU.VertexHandle;
CombinerStructure: TYPE = RVHU.VertexHandle;
DOTWIDTH : INT = 10; -- diameter of vertices in edge drawing
SEGMENTWIDTH: INT = 2; -- width of segment portion in edge drawing
timesRomanBI: ImagerFont.Font ~ ImagerFont.Scale[ImagerFont.Find["xerox/pressfonts/timesroman-brr"], 10.]; --- why does scale of 10. work?
CombinerViewer: TYPE = ViewerClasses.Viewer;
CombinerViewerData: TYPE = REF CombinerViewerDataRec;
CombinerViewerDataRec:
TYPE =
RECORD [
lowerStructure: PlaneStructure, -- for PlaneStructure = RVHU.VertexHandle, assumed to be a vertex on the (convex) outline of the structure. We try to follow the rule that only known valid structures are ever attached to a CombinerViewer, since the Paint proc will look here when the viewer is to be repainted.
upperStructure: PlaneStructure, -- for PlaneStructure = RVHU.VertexHandle, assumed to be a vertex on the (convex) outline of the structure. We try to follow the rule that only known valid structures are ever attached to a CombinerViewer.
x, y: REAL, -- specify starting location in viewer window for drawing a figure
scale: REAL ← 1.0 -- current scale for Imager
];
PrivateState: TYPE = REF InclusionRelation;
InclusionRelation: TYPE = { inside };
RenderPolygonList:
PROC [context: Imager.Context, polygonList:
RVHU.ImagerPolygonAndStateList, insideColor:
ATOM] ~ {
WHILE polygonList #
NIL
DO
state: REF InclusionRelation ← NARROW[polygonList.first.state];
polygon: ImagerPath.Trajectory ← polygonList.first.trajectory;
IF state =
NIL
THEN context.SetColor[ImagerColor.ColorFromAtom[$White]]
ELSE
IF state^ = inside THEN context.SetColor[ImagerColor.ColorFromAtom[insideColor]] ELSE context.SetColor[ImagerColor.ColorFromAtom[$White]];
context.MaskFillTrajectory[ polygon ];
polygonList ← polygonList.rest;
ENDLOOP;
};
DrawPlaneStructure:
PUBLIC
PROC[context: Imager.Context, v: PlaneStructure, showState:
BOOL ←
TRUE, showVerticesOnly:
BOOL ←
FALSE, labelVertices:
BOOL ←
TRUE ] = {
This algorithm assumes that a PlaneStructure is an RVHU.VertexHandleList. Does Depth First Search. Assumes context color already set.
visitedValue: BOOL;
IF v =
NIL
THEN
RETURN;
-- no vertices
Imager.SetStrokeEnd[context, round];
Imager.SetFont[context, timesRomanBI];
IF v.adjacentVertices =
NIL
THEN {
-- one vertex
p1: Imager.VEC ← RVHU.ImagerVecFromPoint[v.coordinates];
Imager.SetStrokeWidth[context, DOTWIDTH];
Imager.MaskStrokeTrajectory[context, ImagerPath.MoveTo[ p1 ] ];
IF labelVertices
THEN {
context.SetXY[[p1.x, p1.y + 7.]];
context.ShowRope[Convert.RopeFromCard[v.index]];
};
}
ELSE {
-- two or more vertices
visitedValue ← v.visited;
DrawPlaneStructureSubr[context, v, showState, showVerticesOnly, labelVertices, NOT visitedValue]; -- toggle visitedValue
};
};
DrawPlaneStructureSubr:
PROC[context: Imager.Context, v: PlaneStructure, showState:
BOOL, showVerticesOnly:
BOOL, labelVertices:
BOOL, visitedValue:
BOOL] = {
Assumes two or more vertices
vAdjList: RVHU.AdjacencyHandleList ← v.adjacentVertices;
lastVertex, nextVertex: PlaneStructure;
done: BOOL;
vToNext, NextTov: RVHU.AdjacencyHandle;
Record that we've visited v
v.visited ← visitedValue; -- record that we've visited this vertex
Recursive calls for adjacencies of v
lastVertex ← vAdjList.first.vertex;
vAdjList ← vAdjList.rest; -- shift past marker vertex (i.e. first iteration of loop begins after it)
done ← FALSE;
WHILE
NOT done
DO
nextVertex ← vAdjList.first.vertex;
IF nextVertex = lastVertex THEN done ← TRUE; -- test for last vertex to be processed
IF (nextVertex.visited # visitedValue)
THEN
DrawPlaneStructureSubr[ context, nextVertex, showState, showVerticesOnly, labelVertices, visitedValue ]
ELSE {
[ vToNext, NextTov ] ← RVHU.FindAdjacency[ v, nextVertex ];
IF
NOT showState
OR
NOT
CSI.StateEqual[vToNext.leftState, NextTov.leftState]
THEN {
p1: Imager.VEC ← RVHU.ImagerVecFromPoint[v.coordinates];
p2: Imager.VEC ← RVHU.ImagerVecFromPoint[nextVertex.coordinates];
trajectory: ImagerPath.Trajectory ← ImagerPath.MoveTo[p1];
Imager.SetStrokeWidth[context, DOTWIDTH];
Imager.MaskStrokeTrajectory[context, trajectory];
IF labelVertices
THEN {
context.SetXY[[p1.x, p1.y + 7.]];
context.ShowRope[Convert.RopeFromCard[v.index]];
};
IF
NOT showVerticesOnly
THEN {
Imager.SetStrokeWidth[context, SEGMENTWIDTH];
Imager.MaskVector [context, p1, p2 ]; -- Draw [v, nextVertex]
};
trajectory ← ImagerPath.MoveTo[p2];
Imager.SetStrokeWidth[context, DOTWIDTH];
Imager.MaskStrokeTrajectory[context, trajectory];
IF labelVertices
THEN {
context.SetXY[[p2.x, p2.y + 7.]];
context.ShowRope[Convert.RopeFromCard[nextVertex.index]];
};
};
};
vAdjList ← vAdjList.rest;
ENDLOOP;
};
UpperPolygonStart: Menus.MenuProc = {
self: CombinerViewer ← NARROW[parent, ViewerClasses.Viewer];
saveVertexIndex ← RVHU.vertexIndex;
upperStructureOpen ← TRUE;
MessageWindow.Append[
message : "Enter your polygon",
clearFirst: TRUE];
};
UpperPolygonDone: Menus.MenuProc = {
self: CombinerViewer ← NARROW[parent, ViewerClasses.Viewer];
selfData: CombinerViewerData ← NARROW[self.data];
upperStructureprev: PlaneStructure;
outline: BOOL ← TRUE;
IF (
NOT upperStructureOpen)
THEN {
MessageWindow.Append[
message : "No upperStructure is open now",
clearFirst: TRUE];
MessageWindow.Blink;
RETURN;
};
IF
NOT
RVHU.ThreeOrMoreVertices[upperStructure]
THEN {
MessageWindow.Append[
message : "Input upperStructure has fewer than three vertices; reenter",
clearFirst: TRUE];
MessageWindow.Blink;
upperStructure ← RVHU.InitVertexHandle[];
RVHU.vertexIndex ← saveVertexIndex;
upperStructureOpen ← FALSE;
RETURN;
};
Test that the polygon is convex; first need to get preceding vertex Note that the call to PreviousOutlineVertex amounts to an assumption that the polygon has at least three vertices. ConvexPolygon( or PreviousOutlineVertex?) will loop if < three vertices.
upperStructureprev ← RVHU.PreviousOutlineVertex[upperStructure];
IF
NOT
RVHU.ConvexPolygon[upperStructureprev, upperStructure, outline]
THEN {
MessageWindow.Append[
message : "Input upperStructure is not convex; reenter",
clearFirst: TRUE];
MessageWindow.Blink;
upperStructure ← RVHU.InitVertexHandle[];
RVHU.vertexIndex ← saveVertexIndex;
upperStructureOpen ← FALSE;
};
upperStructureOpen ← FALSE;
};
Union: Menus.MenuProc = {
self: CombinerViewer ← NARROW[parent, ViewerClasses.Viewer];
selfData: CombinerViewerData ← NARROW[self.data];
v: CombinerStructure;
L: RVHU.ImagerPolygonAndStateList;
IF upperStructureOpen
THEN {
MessageWindow.Append[
message : "You have an open input polygon",
clearFirst: TRUE];
MessageWindow.Blink;
RETURN;
};
RVHU.DumpVertexHandle[ lowerStructure, Rope.Cat[FS.GetDefaultWDir[],"LowerPlaneStructure"]];
RVHU.DumpVertexHandle[ upperStructure, Rope.Cat[FS.GetDefaultWDir[],"UpperPlaneStructure"]];
v ← RVHU.PreviousOutlineVertex[upperStructure];
L ← RVHU.PolygonExtractor[ v, upperStructure ];
RVHU.ClearVisitedFields[v, upperStructure];
lowerStructure ← SCB.Combiner[L.first.trajectory, Union, lowerStructure];
upperStructure ← RVHU.InitVertexHandle[];
selfData.lowerStructure ← lowerStructure; --update Viewer data fields (InitViewer actions)
selfData.upperStructure ← upperStructure;
ViewerOps.PaintViewer[viewer: self, hint: client, whatChanged: NIL, clearClient: TRUE];
};
Difference: Menus.MenuProc = {
self: CombinerViewer ← NARROW[parent, ViewerClasses.Viewer];
selfData: CombinerViewerData ← NARROW[self.data];
v: CombinerStructure;
L: RVHU.ImagerPolygonAndStateList;
IF upperStructureOpen
THEN {
MessageWindow.Append[
message : "You have an open input polygon",
clearFirst: TRUE];
MessageWindow.Blink;
RETURN;
};
RVHU.DumpVertexHandle[ lowerStructure, Rope.Cat[FS.GetDefaultWDir[],"LowerPlaneStructure"]];
RVHU.DumpVertexHandle[ upperStructure, Rope.Cat[FS.GetDefaultWDir[],"UpperPlaneStructure"]];
v ← RVHU.PreviousOutlineVertex[upperStructure];
L ← RVHU.PolygonExtractor[ v, upperStructure ];
RVHU.ClearVisitedFields[v, upperStructure];
lowerStructure ← SCB.Combiner[L.first.trajectory, Difference, lowerStructure];
upperStructure ← RVHU.InitVertexHandle[];
selfData.lowerStructure ← lowerStructure; --update Viewer data fields (InitViewer actions)
selfData.upperStructure ← upperStructure;
ViewerOps.PaintViewer[viewer: self, hint: client, whatChanged: NIL, clearClient: TRUE];
};
Outlines: Menus.MenuProc ~ {
self: CombinerViewer ← NARROW[parent, ViewerClasses.Viewer];
globalOutlineList ← SCB.OutlinesFromCombinerStructure[lowerStructure];
ViewerOps.PaintViewer[viewer: self, hint: client, whatChanged: $Outlines, clearClient: TRUE];
};
DumpBothPlaneStructures: Menus.MenuProc = {
IF lowerStructure =
NIL
OR upperStructure =
NIL
THEN {
MessageWindow.Append[
message : "You don't have a lowerStructure and a upperStructure polygon",
clearFirst: TRUE];
MessageWindow.Blink;
RETURN;
};
RVHU.DumpVertexHandle[ lowerStructure, Rope.Cat[FS.GetDefaultWDir[],"LowerPlaneStructure"]];
RVHU.DumpVertexHandle[ upperStructure, Rope.Cat[FS.GetDefaultWDir[],"UpperPlaneStructure"]];
};
ReadBothPlaneStructures: Menus.MenuProc = {
self: CombinerViewer ← NARROW[parent, ViewerClasses.Viewer];
selfData: CombinerViewerData ← NARROW[self.data];
numberVertices: CARDINAL;
maxVertexIndex: CARDINAL ← 0;
RCB.out.PutF["\n\nVerify lowerStructure argument"];
maxVertexIndex ← RVHU.VertexVerifyIOVHLFromFile[Rope.Cat[FS.GetDefaultWDir[],"LowerPlaneStructure"], RCB.out];
[lowerStructure, numberVertices ] ← RVHU.VHandleFromIOVHL[ RVHU.ReadIOVHLFromFile[Rope.Cat[FS.GetDefaultWDir[],"LowerPlaneStructure"], RCB.out] ];
RVHU.vertexIndex ← MAX[maxVertexIndex, numberVertices]; -- don't repeat indices
RCB.out.PutF["\n\nVerify upperStructure argument"];
maxVertexIndex ← RVHU.VertexVerifyIOVHLFromFile[Rope.Cat[FS.GetDefaultWDir[],"UpperPlaneStructure"], RCB.out];
RCB.out.PutF["\n"];
[upperStructure, numberVertices ] ← RVHU.VHandleFromIOVHL[ RVHU.ReadIOVHLFromFile[Rope.Cat[FS.GetDefaultWDir[],"UpperPlaneStructure"], RCB.out] ];
RVHU.vertexIndex ← MAX[ RVHU.vertexIndex + numberVertices, maxVertexIndex];
RVHU.vertexIndex ← RVHU.vertexIndex + 1; -- set next vertex to be allocated
selfData.lowerStructure ← lowerStructure; -- InitViewer actions
selfData.upperStructure ← upperStructure;
upperStructureOpen ← FALSE; -- Override other input action in progress
ViewerOps.PaintViewer[viewer: self, hint: client, whatChanged: NIL, clearClient: TRUE];
};
DumpLowerPlaneStructure: Menus.MenuProc = {
RVHU.DumpVertexHandle[ lowerStructure, Rope.Cat[FS.GetDefaultWDir[],"LowerPlaneStructure"]];
};
ReadLowerPlaneStructure: Menus.MenuProc = {
self: CombinerViewer ← NARROW[parent, ViewerClasses.Viewer];
selfData: CombinerViewerData ← NARROW[self.data];
numberVertices: CARDINAL;
maxVertexIndex: CARDINAL ← 0;
RCB.out.PutF["\n\nVerify lowerStructure argument"];
maxVertexIndex ← RVHU.VertexVerifyIOVHLFromFile[Rope.Cat[FS.GetDefaultWDir[],"LowerPlaneStructure"], RCB.out];
[lowerStructure, numberVertices ] ← RVHU.VHandleFromIOVHL[ RVHU.ReadIOVHLFromFile[Rope.Cat[FS.GetDefaultWDir[],"LowerPlaneStructure"], RCB.out] ];
RVHU.vertexIndex ← MAX[maxVertexIndex, numberVertices]; -- don't repeat indices
RVHU.vertexIndex ← RVHU.vertexIndex + 1; -- next index to be assigned to a vertex
selfData.lowerStructure ← lowerStructure;
ViewerOps.PaintViewer[viewer: self, hint: client, whatChanged: NIL, clearClient: TRUE];
};
Reset: Menus.MenuProc = {
self: CombinerViewer ← NARROW[parent, ViewerClasses.Viewer];
selfData: CombinerViewerData ← NARROW[self.data];
globalState ← CSI.defaultState;
globalOutlineList ← NIL;
lowerStructure ← RVHU.InitVertexHandle[];
RVHU.vertexIndex ← 1;
upperStructure ← RVHU.InitVertexHandle[];
upperStructureOpen ← FALSE;
selfData.lowerStructure ← RVHU.InitVertexHandle[]; -- repeat InitViewer actions
selfData.upperStructure ← RVHU.InitVertexHandle[];
ViewerOps.PaintViewer[viewer: self, hint: client, whatChanged: NIL, clearClient: TRUE];
};
StateGeometry: Menus.MenuProc = {
self: CombinerViewer ← NARROW[parent, ViewerClasses.Viewer];
ViewerOps.PaintViewer[viewer: self, hint: client, whatChanged: $StateGeometry, clearClient: TRUE];
};
EdgesVertices: Menus.MenuProc = {
self: CombinerViewer ← NARROW[parent, ViewerClasses.Viewer];
ViewerOps.PaintViewer[viewer: self, hint: client, whatChanged: $EdgesVertices, clearClient: TRUE];
};
VertexLabels: Menus.MenuProc = {
self: CombinerViewer ← NARROW[parent, ViewerClasses.Viewer];
ViewerOps.PaintViewer[viewer: self, hint: client, whatChanged: $VertexLabels, clearClient: TRUE];
};
PlaneStructureDraw: Menus.MenuProc = {
self: CombinerViewer ← NARROW[parent, ViewerClasses.Viewer];
fillDraw ← FALSE;
ViewerOps.PaintViewer[viewer: self, hint: client, whatChanged: NIL, clearClient: TRUE];
};
FillDraw: Menus.MenuProc = {
self: CombinerViewer ← NARROW[parent, ViewerClasses.Viewer];
fillDraw ← TRUE;
ViewerOps.PaintViewer[viewer: self, hint: client, whatChanged: NIL, clearClient: TRUE];
};
Zoom: Menus.MenuProc = {
self: CombinerViewer ← NARROW[parent, ViewerClasses.Viewer];
selfData: CombinerViewerData ← NARROW[self.data];
IF mouseButton=red
THEN {
selfData.scale ← selfData.scale*2;
selfData.x ← selfData.x - (1.0 / selfData.scale) * 300.0;
selfData.y ← selfData.y - (1.0 / selfData.scale) * 350.0
}
ELSE {
selfData.x ← selfData.x + (1.0 / selfData.scale) * 300.0;
selfData.y ← selfData.y + (1.0 / selfData.scale) * 350.0;
selfData.scale ← selfData.scale/2
};
ViewerOps.PaintViewer[viewer: self, hint: client, whatChanged: NIL, clearClient: TRUE];
};
Horizontal: Menus.MenuProc = {
self: CombinerViewer ← NARROW[parent, ViewerClasses.Viewer];
selfData: CombinerViewerData ← NARROW[self.data];
IF mouseButton=red
THEN selfData.x ← selfData.x - (1.0 / selfData.scale) * 100.0
ELSE
selfData.x ← selfData.x + (1.0 / selfData.scale) * 100.0;
ViewerOps.PaintViewer[viewer: self, hint: client, whatChanged: NIL, clearClient: TRUE];
};
Vertical: Menus.MenuProc = {
self: CombinerViewer ← NARROW[parent, ViewerClasses.Viewer];
selfData: CombinerViewerData ← NARROW[self.data];
IF mouseButton=red
THEN selfData.y ← selfData.y + (1.0 / selfData.scale) * 100.0
ELSE
selfData.y ← selfData.y - (1.0 / selfData.scale) * 100.0;
ViewerOps.PaintViewer[viewer: self, hint: client, whatChanged: NIL, clearClient: TRUE];
};
DoConvexHull: Menus.MenuProc ~ {
self: CombinerViewer ← NARROW[parent, ViewerClasses.Viewer];
selfData: CombinerViewerData ← NARROW[self.data];
M: RVHU.PointList;
x, y: REAL;
xRat, yRat: RN.RatNum;
state: CSI.State;
Generate random points, compute convex hull,
globalPointList: RVHU.PointList ← NIL;
globalPointListEnd: RVHU.PointList ← NIL;
numGlobalPoints: CARDINAL ← 10;
FOR I:
CARDINAL
IN [1..numGlobalPoints]
DO
x ← Real.Float [Random.ChooseInt[min:1, max:600]];
y ← Real.Float [Random.ChooseInt[min:1, max:400]];
xRat ← RN.RatNumFromREAL[(1.0 / selfData.scale) * x - selfData.x];
yRat ← RN.RatNumFromREAL[ (1.0 / selfData.scale) * y - selfData.y];
IF globalPointList =
NIL
THEN
globalPointList ← globalPointListEnd ← CONS[ [xRat, yRat], NIL]
ELSE {
globalPointListEnd.rest ← CONS[ [xRat,yRat], NIL];
globalPointListEnd ← globalPointListEnd.rest;
};
ENDLOOP;
M ← RVHU.ConvexHull[globalPointList];
upperStructure ← NIL;
state ←
NEW[InclusionRelation ←
inside ];
WHILE M#
NIL
DO
upperStructure ← RVHU.AddVertexToPolygon [upperStructure, M.first.x, M.first.y, state ];
M ← M.rest;
ENDLOOP;
selfData.upperStructure ← upperStructure;
ViewerOps.PaintViewer[viewer: self, hint: client, whatChanged: NIL, clearClient: TRUE];
};
InitViewer: ViewerClasses.InitProc
-- [self: ViewerClasses.Viewer] -- = {
size: REAL = 100.0;
self.data ←
NEW[CombinerViewerDataRec ← [
lowerStructure: RVHU.InitVertexHandle[],
upperStructure: RVHU.InitVertexHandle[],
x: 0.0,
y: 0.0
]];
self.name ← "CombinerViewer";
};
Notify: ViewerClasses.NotifyProc
-- [self:ViewerClasses.Viewer,input:LIST OF REF ANY] -- ={
xy: TIPUser.TIPScreenCoords ← NARROW[input.first];
x, y: RN.RatNum;
clearVal: BOOL ← TRUE;
selfData: CombinerViewerData ← NARROW[self.data];
x ← RN.RatNumFromREAL[(1.0 / selfData.scale) * xy.mouseX - selfData.x];
y ← RN.RatNumFromREAL[ (1.0 / selfData.scale) * xy.mouseY - selfData.y];
SELECT input.rest.first
FROM
$RedRelease => {
IF upperStructureOpen
THEN {
upperStructure ← RVHU.AddVertexToPolygon [upperStructure, x, y, globalState ];
selfData.upperStructure ← upperStructure;
ViewerOps.PaintViewer[viewer: self, hint: client, whatChanged: NIL, clearClient: TRUE];
};
};
ENDCASE => ERROR;
};
Paint: ViewerClasses.PaintProc = {
[self: Viewer, context: Imager.Context, whatChanged: REF, clear: BOOL]
See ImagerInterpress to expand to write Interpress master, /indigo/peach for how to use Versatec
RenderPolygons:
PROC ~ {
v, w: PlaneStructure;
rgbHandle: REF ImagerColor.RGB ← NARROW[selfData.lowerExternalState];
context.SetColor[ImagerColor.ColorFromRGB[rgbHandle^]];
context.MaskRectangleI[self.cx, self.cy, self.cw, self.ch];
context.ScaleT[selfData.scale];
context.TranslateT[[selfData.x, selfData.y]];
w ← selfData.lowerStructure;
IF
NOT RVHU.ThreeOrMoreVertices[w]
THEN {
context.SetColor[ImagerColor.ColorFromAtom[$Black]];
DrawPlaneStructure[context: context, v: w, showState: FALSE, showVerticesOnly: FALSE, labelVertices: FALSE]
}
ELSE {
v ← RVHU.PreviousOutlineVertex[w];
RenderPolygonList[context, RVHU.PolygonExtractor[ v, w ], $Red ];
RVHU.ClearVisitedFields[v, w];
};
w ← selfData.upperStructure;
IF
NOT RVHU.ThreeOrMoreVertices[w]
THEN {
context.SetColor[ImagerColor.ColorFromAtom[$Black]];
DrawPlaneStructure[context: context, v: w, showState: FALSE, showVerticesOnly: FALSE, labelVertices: FALSE]
}
ELSE {
v ← RVHU.PreviousOutlineVertex[w];
RenderPolygonList[context, RVHU.PolygonExtractor[ v, w ], $Green ];
RVHU.ClearVisitedFields[v, w];
};
};
DrawViewerPlaneStructures:
PROC ~ {
context.SetColor[ImagerColor.ColorFromRGB[rgb]];
context.MaskRectangleI[self.cx, self.cy, self.cw, self.ch];
context.ScaleT[selfData.scale];
context.TranslateT[[selfData.x, selfData.y]];
context.SetColor[ImagerColor.ColorFromAtom[$Red]];
DrawPlaneStructure[context: context, v: selfData.lowerStructure, showState: showState, showVerticesOnly: showVerticesOnly, labelVertices: labelVertices];
context.SetColor[ImagerColor.ColorFromAtom[$Green]];
DrawPlaneStructure[context: context, v: selfData.upperStructure, showState: showState, showVerticesOnly: showVerticesOnly, labelVertices: labelVertices];
};
DrawOutlines:
PROC ~ {
L: LIST OF SCB.Outline ← globalOutlineList;
context.ScaleT[selfData.scale];
context.TranslateT[[selfData.x, selfData.y]];
context.SetColor[ImagerColor.ColorFromAtom[$Blue]];
context.SetStrokeEnd[round];
context.SetStrokeJoint[round];
context.SetStrokeWidth[SEGMENTWIDTH];
WHILE L#
NIL
DO
context.MaskStrokeTrajectory[L.first];
L ← L.rest;
ENDLOOP;
};
selfData: CombinerViewerData ← NARROW[self.data];
context.ScaleT[0.0254/72]; -- conversion from meters to inches not needed????
SELECT whatChanged
FROM
$PlaneStructureDraw => {
context.DoSaveAll[DrawViewerPlaneStructures];
};
NIL => {
IF fillDraw THEN context.DoSaveAll[RenderPolygons] ELSE context.DoSaveAll[DrawViewerPlaneStructures];
};
$StateGeometry => {
showState ← NOT showState;
context.DoSaveAll[DrawViewerPlaneStructures];
};
$EdgesVertices => {
showVerticesOnly ← NOT showVerticesOnly;
context.DoSaveAll[DrawViewerPlaneStructures];
};
$VertexLabels => {
labelVertices ← NOT labelVertices;
context.DoSaveAll[DrawViewerPlaneStructures];
};
$Outlines => {
context.DoSaveAll[DrawOutlines];
};
ENDCASE => ERROR;
};
RegisterCombinerViewerClass:
PROC ~ {
menu: Menus.Menu ← Menus.CreateMenu[3];
combinerViewerClass: ViewerClasses.ViewerClass;
Menus.AppendMenuEntry[menu:menu, entry:Menus.CreateEntry [name:"Reset", proc: Reset], line:0];
Menus.AppendMenuEntry[menu:menu, entry:Menus.CreateEntry [name:"DumpLower ", proc: DumpLowerPlaneStructure], line:0];
Menus.AppendMenuEntry[menu:menu, entry:Menus.CreateEntry [name:"LoadLower ", proc: ReadLowerPlaneStructure], line:0];
Menus.AppendMenuEntry[menu:menu, entry:Menus.CreateEntry [name:"DumpBoth ", proc: DumpBothPlaneStructures], line:0];
Menus.AppendMenuEntry[menu:menu, entry:Menus.CreateEntry [name:"LoadBoth ", proc: ReadBothPlaneStructures], line:0];
Menus.AppendMenuEntry[menu:menu, entry:Menus.CreateEntry [name:"UppStart ", proc: UpperPolygonStart], line:1];
Menus.AppendMenuEntry[menu:menu, entry:Menus.CreateEntry [name:"UppDone ", proc: UpperPolygonDone], line:1];
Menus.AppendMenuEntry[menu:menu, entry:Menus.CreateEntry [name:"RandHull", proc: DoConvexHull], line:1];
Menus.AppendMenuEntry[menu:menu, entry:Menus.CreateEntry [name:"Union ", proc: Union], line:1];
Menus.AppendMenuEntry[menu:menu, entry:Menus.CreateEntry [name:"Difference ", proc: Difference], line:1];
Menus.AppendMenuEntry[menu:menu, entry:Menus.CreateEntry [name:"Outlines ", proc: Outlines], line:1];
Menus.AppendMenuEntry[menu:menu, entry:Menus.CreateEntry [name:"StateGeometry ", proc: StateGeometry], line:2];
Menus.AppendMenuEntry[menu:menu, entry:Menus.CreateEntry [name:"EdgesVertices ", proc: EdgesVertices], line:2];
Menus.AppendMenuEntry[menu:menu, entry:Menus.CreateEntry [name:"VertexLabels ", proc: VertexLabels], line:2];
Menus.AppendMenuEntry[menu:menu, entry:Menus.CreateEntry [name:"PlaneStructDraw ", proc: PlaneStructureDraw], line:2];
Menus.AppendMenuEntry[menu:menu, entry:Menus.CreateEntry [name:"FillDraw ", proc: FillDraw], line:2];
Menus.AppendMenuEntry[menu:menu, entry:Menus.CreateEntry [name:"Zoom ", proc: Zoom], line:2];
Menus.AppendMenuEntry[menu:menu, entry:Menus.CreateEntry [name:"Horizontal ", proc: Horizontal], line:2];
Menus.AppendMenuEntry[menu:menu, entry:Menus.CreateEntry [name:"Vertical ", proc: Vertical], line:2];
combinerViewerClass ←
NEW[ViewerClasses.ViewerClassRec ← [
flavor: $CombinerViewer,
init: InitViewer,
notify: Notify,
tipTable: TIPUser.InstantiateNewTIPTable["Combiner.tip"],
paint: Paint,
menu: menu
]];
ViewerOps.RegisterViewerClass[flavor: $CombinerViewer, class: combinerViewerClass];
};
**** Top level variables
Combiner Log title
logTitle: Rope.ROPE;
Global objects
globalState: CSI.State;
globalOutlineList: LIST OF SCB.Outline;
(Lower and Upper) Structure display options
showState: BOOL ← TRUE; -- global variables for control of PlaneStructure display format
showVerticesOnly: BOOL ← FALSE;
labelVertices: BOOL ← TRUE;
fillDraw: BOOL ← TRUE;
Lower Structure objects
lowerStructure: PlaneStructure; -- The convention is that if the lower structure exists, then lowerStructure is one of its outline vertices (remark: lowerStructures cannot be read in).
Upper Structure objects
upperStructure: PlaneStructure; -- The convention is that if the upper structure exists, then upperStructure is one of its outline vertices
upperStructureOpen: BOOLEAN; -- true when an upperStructure (which currently must be a polygon) is being read in
saveVertexIndex: INT; -- for backup if unacceptable upperStructure read
**** End of Top level variables
RegisterCombinerViewerClass[];
Step through Reset procedure, creating CombinerViewer along the way (in place of painting the existing viewer), and relying on InitViewer to set PlaneStructure fields of viewer (in place of setting them explicitly).
globalState ← CSI.defaultState;
globalOutlineList ← NIL;
lowerStructure ← RVHU.InitVertexHandle[];
RVHU.vertexIndex ← 1;
upperStructure ← RVHU.InitVertexHandle[];
upperStructureOpen ← FALSE;
[] ← ViewerOps.CreateViewer[flavor: $CombinerViewer, info: [iconic:FALSE, column: color] ];
End of Step through Reset procedure
Create Combiner Log
logTitle ← IO.PutFR["Combiner Log"];
[RCB.in, RCB.out] ← ViewerIO.CreateViewerStreams[logTitle];
Initialize random numbers
[] ← Random.Create[range: 0, seed: -1];
END.