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 ] = { 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] = { vAdjList: RVHU.AdjacencyHandleList _ v.adjacentVertices; lastVertex, nextVertex: PlaneStructure; done: BOOL; vToNext, NextTov: RVHU.AdjacencyHandle; v.visited _ visitedValue; -- record that we've visited this vertex 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; }; 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; 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]; }; }; $YellowRelease => { }; $BlueRelease => { }; ENDCASE => ERROR; }; Paint: ViewerClasses.PaintProc = { RenderPolygons: PROC ~ { v, w: PlaneStructure; 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.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]; 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]; }; logTitle: Rope.ROPE; globalState: CSI.State; globalOutlineList: LIST OF SCB.Outline; showState: BOOL _ TRUE; -- global variables for control of PlaneStructure display format showVerticesOnly: BOOL _ FALSE; labelVertices: BOOL _ TRUE; fillDraw: BOOL _ TRUE; 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). 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 RegisterCombinerViewerClass[]; 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] ]; logTitle _ IO.PutFR["Combiner Log"]; [RCB.in, RCB.out] _ ViewerIO.CreateViewerStreams[logTitle]; [] _ Random.Create[range: 0, seed: -1]; END. pSimpleCombinerTester.mesa Last Edited by: Arnon, June 20, 1985 4:46:23 pm PDT This algorithm assumes that a PlaneStructure is an RVHU.VertexHandleList. Does Depth First Search. Assumes context color already set. Assumes two or more vertices Record that we've visited v Recursive calls for adjacencies of v 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. Generate random points, compute convex hull, [self: Viewer, context: Imager.Context, whatChanged: REF, clear: BOOL] See ImagerInterpress to expand to write Interpress master, /indigo/peach for how to use Versatec rgbHandle: REF ImagerColor.RGB _ NARROW[selfData.lowerExternalState]; context.SetColor[ImagerColor.ColorFromRGB[rgbHandle^]]; context.MaskRectangleI[self.cx, self.cy, self.cw, self.ch]; context.SetColor[ImagerColor.ColorFromRGB[rgb]]; context.MaskRectangleI[self.cx, self.cy, self.cw, self.ch]; context.ScaleT[0.0254/72]; -- conversion from meters to inches not needed???? **** Top level variables Combiner Log title Global objects (Lower and Upper) Structure display options Lower Structure objects Upper Structure objects **** End of Top level variables 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). End of Step through Reset procedure Create Combiner Log Initialize random numbers Κ’˜šœ™J™3J™—šΟk ˜ Jšœœ#˜8Jšœœ˜Jšœœ²œ˜ΓJšœ œ˜"Jšœ œ˜%Jšœ œ˜&Jšœœ˜Jšœœ˜Jšœœ<˜GJšœœ˜$Jšœœ˜!Jšœœ˜'Jšœ œ ˜Jšœœ ˜Jšœœœ˜Jšœœρ˜„Jšœœ4˜HJšœœ+˜8JšœœS˜fJšœ œ˜%Jšœ œ2˜AJ˜—InamešΟnœœ˜#šœœ₯œ ˜ΤJšœ ˜—Jšœœœ œœœ œ˜gJ˜Jšœœœ˜)Jšœœœ˜,J˜JšœœΟc'˜˜>šœ œœ5˜LJšœœ:œ5˜Š—Lšœ&˜&Lšœ˜Lšœ˜—L˜L˜—šžœœœ8œœœœœœ˜€J•commentTRUEšœ3œO™†Jšœœ˜J˜š œœœœŸ˜'J˜—Jšœ$˜$Lšœ&˜&šœœœŸ ˜0Jšœ œœ#˜8Jšœœ˜)Jšœ?˜?šœœ˜Jšœ!˜!Jšœ0˜0J˜—J˜—šœŸ˜Jšœ˜Jšœ,œœ œŸ˜yJ˜—J˜J˜—š žœœ8œœœœ˜žJšŸ™Jšœ œ*˜8Jšœœ˜(Jšœœ˜ Jšœœ˜'J˜Jšœ™JšœŸ(˜BJ˜Jšœ$™$Jšœ$˜$JšœŸJ˜eJšœœ˜ šœœ˜Jšœ#˜#JšœœœŸ(˜Všœ%˜+Jšœ6œœ œ˜g—šœ˜Jšœœ ˜;š œœ œœœ2œ˜SJšœ œœ#˜8Jšœ œœ,˜AJšœ:˜:Jšœœ˜)J˜1šœœ˜Jšœ!˜!Jšœ0˜0J˜—šœœœ˜Jšœ œ˜-Jšœ"œŸœ˜>J˜—Jšœ#˜#Jšœœ˜)J˜1šœœ˜Jšœ!˜!Jšœ9˜9J˜—J˜—J˜—Jšœ˜Jšœ˜—Jšœ˜J™J˜—šžœ˜%Jšœœ˜