DIRECTORY Feedback, FeedbackTypes, FS, GGBasicTypes, GGBoundBox, GGCoreOps, GGCoreTypes, GGHistoryTypes, GGInterfaceTypes, GGModelTypes, GGOutline, GGParent, GGParseIn, GGParseOut, GGScene, GGSegmentTypes, GGSequence, GGShapes, GGSlice, GGSliceOps, GGTraj, GGUtility, Imager, ImagerPath, ImagerTransformation, IO, Rope, TextNode, TiogaImager; GGOutlineImplA: CEDAR PROGRAM IMPORTS Feedback, FS, GGBoundBox, GGCoreOps, GGOutline, GGParent, GGParseIn, GGParseOut, GGScene, GGSequence, GGShapes, GGSlice, GGSliceOps, GGTraj, GGUtility, Imager, IO, Rope EXPORTS GGSlice, GGOutline, GGParent = BEGIN AlignBag: TYPE = GGInterfaceTypes.AlignBag; BitVector: TYPE = GGBasicTypes.BitVector; BoundBox: TYPE = GGCoreTypes.BoundBox; Camera: TYPE = GGModelTypes.Camera; Circle: TYPE = GGBasicTypes.Circle; Color: TYPE = Imager.Color; ControlPointGenerator: TYPE = GGModelTypes.ControlPointGenerator; DefaultData: TYPE = GGModelTypes.DefaultData; EditConstraints: TYPE = GGModelTypes.EditConstraints; FeatureData: TYPE = GGInterfaceTypes.FeatureData; MsgRouter: TYPE = FeedbackTypes.MsgRouter; GGData: TYPE = GGInterfaceTypes.GGData; HistoryEvent: TYPE = GGHistoryTypes.HistoryEvent; HitType: TYPE = GGModelTypes.TrajPartType; Joint: TYPE = GGSegmentTypes.Joint; JointGenerator: TYPE = GGModelTypes.JointGenerator; Line: TYPE = GGCoreTypes.Line; OutlineData: TYPE = GGOutline.OutlineData; OutlineDataObj: TYPE = GGOutline.OutlineDataObj; OutlineHitData: TYPE = GGOutline.OutlineHitData; OutlineHitDataObj: TYPE = GGOutline.OutlineHitDataObj; OutlineParts: TYPE = GGOutline.OutlineParts; OutlinePartsObj: TYPE = GGOutline.OutlinePartsObj; Point: TYPE = GGBasicTypes.Point; PointAndDone: TYPE = GGModelTypes.PointAndDone; PointGenerator: TYPE = GGModelTypes.PointGenerator; PointGeneratorObj: TYPE = GGModelTypes.PointGeneratorObj; PointPairAndDone: TYPE = GGModelTypes.PointPairAndDone; PointPairGenerator: TYPE = GGModelTypes.PointPairGenerator; PointPairGeneratorObj: TYPE = GGModelTypes.PointPairGeneratorObj; PointWalkProc: TYPE = GGModelTypes.PointWalkProc; Scene: TYPE = GGModelTypes.Scene; Segment: TYPE = GGSegmentTypes.Segment; SegmentGenerator: TYPE = GGModelTypes.SegmentGenerator; SegmentGeneratorObj: TYPE = GGModelTypes.SegmentGeneratorObj; SelectionClass: TYPE = GGSegmentTypes.SelectionClass; SelectMode: TYPE = GGModelTypes.SelectMode; SequenceGenerator: TYPE = GGSequence.SequenceGenerator; SequenceOfReal: TYPE = GGCoreTypes.SequenceOfReal; Slice: TYPE = GGModelTypes.Slice; SliceClass: TYPE = GGModelTypes.SliceClass; SliceClassObj: TYPE = GGModelTypes.SliceClassObj; SliceDescriptor: TYPE = GGModelTypes.SliceDescriptor; SliceDescriptorGenerator: TYPE = GGModelTypes.SliceDescriptorGenerator; SliceGenerator: TYPE = GGModelTypes.SliceGenerator; SliceObj: TYPE = GGModelTypes.SliceObj; SliceParts: TYPE = GGModelTypes.SliceParts; StrokeEnd: TYPE = Imager.StrokeEnd; StrokeJoint: TYPE = Imager.StrokeJoint; Traj: TYPE = GGModelTypes.Traj; TrajData: TYPE = GGModelTypes.TrajData; TrajEnd: TYPE = GGModelTypes.TrajEnd; TrajParts: TYPE = GGModelTypes.TrajParts; TrajPartType: TYPE = GGModelTypes.TrajPartType; Transformation: TYPE = ImagerTransformation.Transformation; TriggerBag: TYPE = GGInterfaceTypes.TriggerBag; Vector: TYPE = GGBasicTypes.Vector; WalkProc: TYPE = GGModelTypes.WalkProc; MoveToProc: TYPE = ImagerPath.MoveToProc; LineToProc: TYPE = ImagerPath.LineToProc; CurveToProc: TYPE = ImagerPath.CurveToProc; ConicToProc: TYPE = ImagerPath.ConicToProc; ArcToProc: TYPE = ImagerPath.ArcToProc; ClusterData: TYPE = REF ClusterDataObj; ClusterDataObj: TYPE = GGSlice.ClusterDataObj; Problem: PUBLIC SIGNAL [msg: Rope.ROPE] = Feedback.Problem; BuildOutlineSliceClass: PUBLIC PROC [] RETURNS [class: SliceClass] = { class _ NEW[SliceClassObj _ [ type: $Outline, unlink: GGParent.Unlink, getBoundBox: GGParent.GetBoundBox, getTransformedBoundBox: GGSlice.GenericTransformedBoundBox, getTightBox: GGParent.GetTightBox, copy: OutlineCopy, restore: GGParent.Restore, buildPath: OutlineBuildPath, drawBorder: OutlineDrawBorder, drawParts: OutlineDrawParts, drawTransform: OutlineDrawTransform, drawSelectionFeedback: OutlineDrawSelectionFeedback, drawAttractorFeedback: GGParent.DrawAttractorFeedback, attractorFeedbackBoundBox: GGParent.AttractorFeedbackBoundBox, saveSelections: GGParent.SaveSelections, remakeSelections: GGParent.RemakeSelections, transform: GGParent.Transform, describe: OutlineDescribe, describeHit: GGParent.DescribeHit, fileout: OutlineFileout, filein: OutlineFilein, isEmptyParts: GGParent.IsEmptyParts, isCompleteParts: GGParent.IsCompleteParts, newParts: GGParent.NewParts, unionParts: GGParent.UnionParts, differenceParts: GGParent.DifferenceParts, movingParts: OutlineMovingParts, augmentParts: GGParent.AugmentParts, alterParts: GGParent.AlterParts, setSelectedFields: GGParent.SetSelectedFields, pointsInDescriptor: GGParent.PointsInDescriptor, walkPointsInDescriptor: GGParent.WalkPointsInDescriptor, pointPairsInDescriptor: GGParent.PointPairsInDescriptor, segmentsInDescriptor: GGParent.SegmentsInDescriptor, walkSegments: GGParent.WalkSegments, nextPoint: GGParent.NextPoint, nextPointPair: GGParent.NextPointPair, nextSegment: GGParent.NextSegment <<, closestPoint: GGParent.ClosestPoint, closestJointToHitData: GGParent.ClosestJointToHitData, closestPointAndTangent: GGSlice.NoOpClosestPointAndTangent, closestSegment: GGParent.ClosestSegment, lineIntersection: GGParent.LineIntersection, circleIntersection: GGParent.CircleIntersection, hitDataAsSimpleCurve: GGParent.HitDataAsSimpleCurve, setDefaults: GGParent.SetDefaults, setStrokeWidth: GGParent.SetStrokeWidth, getStrokeWidth: GGParent.GetStrokeWidth, setStrokeEnd: GGParent.SetStrokeEnd, getStrokeEnd: GGParent.GetStrokeEnd, setStrokeJoint: GGParent.SetStrokeJoint, getStrokeJoint: GGParent.GetStrokeJoint, setStrokeColor: GGParent.SetStrokeColor, getStrokeColor: GGParent.GetStrokeColor, setFillColor: GGParent.SetFillColor, getFillColor: OutlineGetFillColor, setArrows: GGSlice.NoOpSetArrows, getArrows: GGSlice.NoOpGetArrows, setDashed: GGParent.SetDashed, getDashed: GGParent.GetDashed >> ]]; GGSlice.BuildMoreOutlineSliceClass[class]; }; BuildClusterSliceClass: PUBLIC PROC [] RETURNS [class: SliceClass] = { class _ NEW[SliceClassObj _ [ type: $Cluster, unlink: GGParent.Unlink, getBoundBox: GGParent.GetBoundBox, getTransformedBoundBox: GGSlice.GenericTransformedBoundBox, getTightBox: GGParent.GetTightBox, copy: ClusterCopy, restore: GGParent.Restore, buildPath: GGSlice.NoOpBuildPath, drawBorder: GGSlice.NoOpDrawBorder, drawParts: GGParent.DrawParts, drawTransform: GGParent.DrawTransform, drawSelectionFeedback: ClusterDrawSelectionFeedback, drawAttractorFeedback: DrawAttractorFeedback, attractorFeedbackBoundBox: AttractorFeedbackBoundBox, saveSelections: GGParent.SaveSelections, remakeSelections: GGParent.RemakeSelections, transform: GGParent.Transform, describe: ClusterDescribe, describeHit: GGParent.DescribeHit, fileout: ClusterFileout, filein: ClusterFilein, isEmptyParts: GGParent.IsEmptyParts, isCompleteParts: GGParent.IsCompleteParts, newParts: GGParent.NewParts, unionParts: GGParent.UnionParts, differenceParts: GGParent.DifferenceParts, movingParts: ClusterMovingParts, augmentParts: GGParent.AugmentParts, alterParts: GGParent.AlterParts, setSelectedFields: GGParent.SetSelectedFields, pointsInDescriptor: GGParent.PointsInDescriptor, walkPointsInDescriptor: GGParent.WalkPointsInDescriptor, pointPairsInDescriptor: GGParent.PointPairsInDescriptor, segmentsInDescriptor: GGParent.SegmentsInDescriptor, walkSegments: GGParent.WalkSegments, nextPoint: GGParent.NextPoint, nextPointPair: GGParent.NextPointPair, nextSegment: GGParent.NextSegment <<, closestPoint: GGParent.ClosestPoint, closestJointToHitData: GGParent.ClosestJointToHitData, closestPointAndTangent: GGSlice.NoOpClosestPointAndTangent, closestSegment: GGParent.ClosestSegment, filledPathsUnderPoint: ClusterFilledPathsUnderPoint, lineIntersection: GGParent.LineIntersection, circleIntersection: GGParent.CircleIntersection, hitDataAsSimpleCurve: GGParent.HitDataAsSimpleCurve, setDefaults: GGParent.SetDefaults, setStrokeWidth: GGParent.SetStrokeWidth, getStrokeWidth: GGParent.GetStrokeWidth, setStrokeEnd: GGParent.SetStrokeEnd, getStrokeEnd: GGParent.GetStrokeEnd, setStrokeJoint: GGParent.SetStrokeJoint, getStrokeJoint: GGParent.GetStrokeJoint, setStrokeColor: GGParent.SetStrokeColor, getStrokeColor: GGParent.GetStrokeColor, setFillColor: GGParent.SetFillColor, getFillColor: GGParent.GetFillColor, setArrows: GGSlice.NoOpSetArrows, getArrows: GGSlice.NoOpGetArrows, setDashed: GGParent.SetDashed, getDashed: GGParent.GetDashed >> ]]; GGSlice.BuildMoreClusterSliceClass[class]; }; OutlineFromChildList: PROC [childList: LIST OF Slice, fillColor: Color, oddWrap: BOOL _ TRUE, fillText: TextNode.Ref, screenStyle: BOOL, version: REAL] RETURNS [outline: Slice] = { data: OutlineData _ NEW[OutlineDataObj _ [oddWrap: oddWrap, fillColor: fillColor, children: childList] ]; outline _ NEW[SliceObj _ [ class: GGSlice.FetchSliceClass[$Outline], parent: NIL, data: data, selectedInFull: [FALSE, FALSE, FALSE], tightBox: GGBoundBox.NullBoundBox[], boundBox: GGBoundBox.NullBoundBox[], boxValid: FALSE]]; FOR tL: LIST OF Slice _ childList, tL.rest UNTIL tL=NIL DO tL.first.parent _ outline; ENDLOOP; outline.nullDescriptor _ GGSlice.DescriptorFromParts[outline, NIL]; IF version<8802.04 THEN { -- have to calculate the forward bits from scratch. In older versions, trajectory direction was not important. [] _ GGSliceOps.SetOrientation[childList.first, NIL, ccw, NIL]; -- first child is ccw by convention FOR holeList: LIST OF Slice _ childList.rest, holeList.rest UNTIL holeList=NIL DO [] _ GGSliceOps.SetOrientation[holeList.first, NIL, cw, NIL]; -- other children are cw by convention ENDLOOP; }; GGOutline.SetFillText[outline, fillText, screenStyle, NIL]; }; ClusterFromChildList: PROC [childList: LIST OF Slice, frozen: BOOL, version: REAL] RETURNS [parent: Slice] = { data: OutlineData _ NEW[OutlineDataObj _ [oddWrap: FALSE, fillColor: NIL, children: childList, subclassData: NEW[ClusterDataObj _ [frozen: frozen]] ]]; parent _ NEW[SliceObj _ [ class: GGSlice.FetchSliceClass[$Cluster], parent: NIL, data: data, selectedInFull: [FALSE, FALSE, FALSE], tightBox: GGBoundBox.NullBoundBox[], boundBox: GGBoundBox.NullBoundBox[], boxValid: FALSE]]; FOR tL: LIST OF Slice _ childList, tL.rest UNTIL tL=NIL DO tL.first.parent _ parent; ENDLOOP; parent.nullDescriptor _ GGSlice.DescriptorFromParts[parent, NIL]; }; OutlineDescribe: PROC [sliceD: SliceDescriptor] RETURNS [rope: Rope.ROPE] = { RETURN[GGParent.Describe[sliceD, "outline"]]; }; ClusterDescribe: PROC [sliceD: SliceDescriptor] RETURNS [rope: Rope.ROPE] = { RETURN[GGParent.Describe[sliceD, "cluster"]]; }; ClusterCopy: PROC [slice: Slice, parts: SliceParts _ NIL] RETURNS [copy: LIST OF Slice] = { DoCreateCluster: PROC [newSlice: Slice] RETURNS [parent: Slice] = { newData: OutlineData; parent _ GGSlice.CreateCluster[]; GGSlice.AddChildToCluster[parent, newSlice, -1]; newData _ NARROW[parent.data]; newData.subclassData _ NEW[ClusterDataObj _ [frozen: oldClusterData.frozen]]; }; outlineParts: OutlineParts _ NARROW[parts]; oldData: OutlineData _ NARROW[slice.data]; oldClusterData: ClusterData _ NARROW[oldData.subclassData]; copy _ Copy[slice, parts, DoCreateCluster]; }; ClusterDrawSelectionFeedback: PUBLIC PROC [slice: Slice, selectedParts: SliceParts, hotParts: SliceParts, dc: Imager.Context, camera: Camera, dragInProgress, caretIsMoving, hideHot, quick: BOOL] = { slowNormal, slowHot, completeNormal, completeHot: BOOL _ FALSE; normalOutlineParts: OutlineParts _ NARROW[selectedParts]; hotOutlineParts: OutlineParts _ NARROW[hotParts]; boxDrawn: BOOL _ FALSE; IF caretIsMoving OR dragInProgress THEN RETURN; IF selectedParts=NIL AND hotParts=NIL THEN RETURN; completeNormal _ normalOutlineParts#NIL AND IsComplete[normalOutlineParts]; completeHot _ hotOutlineParts#NIL AND IsComplete[hotOutlineParts]; slowNormal _ selectedParts#NIL AND NOT (quick AND completeNormal); slowHot _ hotParts#NIL AND NOT (quick AND completeHot); GGParent.DrawSelectionFeedback[slice, selectedParts, hotParts, dc, camera, dragInProgress, caretIsMoving, hideHot, quick]; IF NOT slowNormal AND completeNormal THEN { boundBox: BoundBox _ GetBoundBox[slice, NIL]; GGShapes.DrawBoundBox[dc, boundBox, camera.cpScale]; GGShapes.DrawQuickSelectedJoint[dc, [boundBox.loX, boundBox.loY], normal, camera.cpScale]; boxDrawn _ TRUE; }; IF NOT slowHot AND completeHot THEN { boundBox: BoundBox _ GetBoundBox[slice, NIL]; GGShapes.DrawBoundBox[dc, boundBox, camera.cpScale]; GGShapes.DrawQuickSelectedJoint[dc, [boundBox.loX, boundBox.loY], hot, camera.cpScale]; boxDrawn _ TRUE; }; IF NOT boxDrawn AND (NOT IsEmpty[normalOutlineParts] OR NOT IsEmpty[hotOutlineParts]) THEN { boundBox: BoundBox _ GetBoundBox[slice, NIL]; GGShapes.DrawBoundBox[dc, boundBox, camera.cpScale]; }; }; ClusterFileout: PUBLIC PROC [slice: Slice, f: IO.STREAM] = { outlineData: OutlineData _ NARROW[slice.data]; clusterData: ClusterData _ NARROW[outlineData.subclassData]; f.PutF["frozen: "]; GGParseOut.WriteBool[f, clusterData.frozen]; f.PutChar[IO.CR]; GGParent.Fileout[slice, f]; }; ClusterFilein: PUBLIC PROC [f: IO.STREAM, version: REAL, router: MsgRouter, camera: Camera] RETURNS [slice: Slice] = { frozen, good: BOOL _ TRUE; childList: LIST OF Slice; GGParseIn.ReadWRope[f, "frozen:"]; [frozen, good] _ GGParseIn.ReadBool[f, version]; childList _ GGParent.Filein[f, version, router, camera]; IF childList#NIL THEN slice _ ClusterFromChildList[childList, frozen, version]; }; ClusterMovingParts: PROC [slice: Slice, selectedParts: SliceParts, editConstraints: EditConstraints, bezierDrag: GGInterfaceTypes.BezierDragRecord] RETURNS [background, overlay, rubber, drag: SliceDescriptor] = { outlineData: OutlineData _ NARROW[slice.data]; RETURN GGParent.MovingParts[slice, selectedParts, TRUE, editConstraints, bezierDrag]; }; Unlink: PUBLIC PROC [slice: Slice] = { IF slice.data#NIL THEN { outlineData: OutlineData _ NARROW[slice.data]; GGSlice.UnlinkSlice[slice]; FOR childList: LIST OF Slice _ outlineData.children, childList.rest UNTIL childList=NIL DO IF childList.first.data#NIL THEN GGSliceOps.Unlink[childList.first]; -- unlink circular structures. IMPORTANT ENDLOOP; outlineData.children _ NIL; }; }; GetBoundBox: PUBLIC PROC [slice: Slice, parts: SliceParts] RETURNS [box: BoundBox] = { IF slice.boxValid AND parts=NIL THEN RETURN[slice.boundBox] -- fast case ELSE { outlineParts: OutlineParts _ NARROW[parts]; outlineData: OutlineData _ NARROW[slice.data]; boundBoxList: LIST OF BoundBox; thisBoundBox: BoundBox; IF parts = NIL THEN FOR childList: LIST OF Slice _ outlineData.children, childList.rest UNTIL childList = NIL DO thisBoundBox _ GGSliceOps.GetBoundBox[childList.first]; boundBoxList _ CONS[thisBoundBox, boundBoxList]; ENDLOOP ELSE FOR list: LIST OF SliceDescriptor _ outlineParts.descriptors, list.rest UNTIL list = NIL DO IF list.first#NIL THEN { thisBoundBox _ GGSliceOps.GetBoundBox[list.first.slice, list.first.parts]; boundBoxList _ CONS[thisBoundBox, boundBoxList]; }; ENDLOOP; box _ GGBoundBox.BoundBoxOfBoxes[boundBoxList]; IF parts=NIL THEN { -- set up cache for fast case next time around GGSlice.KillBoundBoxOnly[slice.parent]; -- invalidate ancestor caches slice.boundBox _ box; slice.boxValid _ TRUE; }; }; }; GetTightBox: PUBLIC PROC [slice: Slice, parts: SliceParts] RETURNS [box: BoundBox] = { IF slice.tightBoxValid AND parts=NIL THEN RETURN[slice.tightBox] -- fast case ELSE { outlineParts: OutlineParts _ NARROW[parts]; outlineData: OutlineData _ NARROW[slice.data]; boundBoxList: LIST OF BoundBox; thisBoundBox: BoundBox; IF parts = NIL THEN FOR childList: LIST OF Slice _ outlineData.children, childList.rest UNTIL childList = NIL DO thisBoundBox _ GGSliceOps.GetTightBox[childList.first]; boundBoxList _ CONS[thisBoundBox, boundBoxList]; ENDLOOP ELSE FOR list: LIST OF SliceDescriptor _ outlineParts.descriptors, list.rest UNTIL list = NIL DO IF list.first#NIL THEN { thisBoundBox _ GGSliceOps.GetTightBox[list.first.slice, list.first.parts]; boundBoxList _ CONS[thisBoundBox, boundBoxList]; }; ENDLOOP; box _ GGBoundBox.BoundBoxOfBoxes[boundBoxList]; IF parts=NIL THEN { -- set up cache for fast case next time around GGSlice.KillTightBoxOnly[slice.parent]; -- invalidate ancestor caches slice.tightBox _ box; slice.tightBoxValid _ TRUE; }; }; }; OutlineCopy: PROC [slice: Slice, parts: SliceParts _ NIL] RETURNS [copy: LIST OF Slice] = { DoCreateOutline: PROC [newSlice: Slice] RETURNS [parent: Slice] = { newData: OutlineData; parent _ GGOutline.CreateOutline[newSlice, GGCoreOps.CopyColor[oldData.fillColor]]; newData _ NARROW[parent.data]; newData.oddWrap _ oldData.oddWrap; newData.fillText _ oldData.fillText; newData.screenStyle _ oldData.screenStyle; }; oldData: OutlineData _ NARROW[slice.data]; oldParts: OutlineParts _ NARROW[parts]; copy _ Copy[slice, parts, DoCreateOutline]; IF parts=NIL OR IsComplete[oldParts] THEN { -- if the whole thing is selected GGOutline.SetFillText[copy.first, oldData.fillText, oldData.screenStyle, NIL]; }; }; Copy: PUBLIC PROC [slice: Slice, parts: SliceParts _ NIL, create: PROC [newSlice: Slice] RETURNS [parent: Slice]] RETURNS [copy: LIST OF Slice] = { newParent, newSlice: Slice; oldData, newData: OutlineData; ptr, holeList: LIST OF Slice; outlineParts: OutlineParts _ NARROW[parts]; IF parts=NIL OR IsComplete[outlineParts] THEN { -- if the whole thing is selected AddChild: PROC [child: Slice] RETURNS [done: BOOL _ FALSE] = { IF newSlice = NIL THEN { newSlice _ GGSliceOps.Copy[child].first; newParent _ create[newSlice]; newData _ NARROW[newParent.data]; } ELSE { newSlice _ GGSliceOps.Copy[child].first; [holeList, ptr] _ GGUtility.AddSlice[newSlice, holeList, ptr]; newSlice.parent _ newParent; }; }; oldData _ NARROW[slice.data]; [holeList, ptr] _ GGUtility.StartSliceList[]; [] _ GGParent.WalkChildren[slice, first, AddChild]; IF holeList#NIL THEN newData.children _ GGUtility.AppendSliceList[newData.children, holeList]; copy _ LIST[newParent]; } ELSE { -- each run of each selected child becomes a new slice. CopyWholeTraj: PROC [child: Slice, enclose: BOOL _ FALSE] = { thisFillColor: Imager.Color _ GGCoreOps.CopyColor[GGSliceOps.GetFillColor[slice, NIL].color]; newChild: Slice _ GGSliceOps.Copy[child].first; IF enclose THEN newChild _ GGOutline.CreateOutline[newChild, thisFillColor]; copy _ GGUtility.AppendSliceList[copy, LIST[newChild]]; }; VisitChild: PROC [childD: SliceDescriptor] RETURNS [done: BOOL _ FALSE] = { nextChild: Slice _ childD.slice; childParts: SliceParts _ childD.parts; IF GGSliceOps.GetType[nextChild]#$Traj THEN { copy _ GGUtility.AppendSliceList[copy, GGSliceOps.Copy[nextChild, childParts]]; } ELSE { nextChildParts: TrajParts _ NARROW[childParts]; IF GGSequence.IsComplete[nextChildParts] THEN CopyWholeTraj[nextChild, TRUE] ELSE { nextRuns: GGSequence.SequenceGenerator _ GGSequence.RunsInSequence[nextChildParts].seqGen; FOR nextSeq: TrajParts _ GGSequence.NextSequence[nextRuns], GGSequence.NextSequence[nextRuns] UNTIL nextSeq=NIL DO IF NOT GGSequence.ContainsSomeSegment[nextSeq] THEN { Feedback.PutFByName[$Gargoyle, oneLiner, $Complaint, ". . . Cannot Fetch Joints or CPs by themselves"]; LOOP; }; newSlice _ GGTraj.CopyTrajFromRun[nextChild, nextSeq]; newSlice _ GGOutline.CreateOutline[newSlice, fillColor]; copy _ GGUtility.AppendSliceList[copy, LIST[newSlice]]; ENDLOOP; }; }; }; fillColor: Imager.Color _ GGCoreOps.CopyColor[GGSliceOps.GetFillColor[slice, NIL].color]; [] _ GGParent.WalkIncludedChildren[slice, parts, first, VisitChild]; }; }; Restore: PUBLIC PROC [from: Slice, to: Slice] = { IF to=NIL OR from=NIL THEN ERROR; IF to.class#from.class THEN ERROR; <> BEGIN fromSize: INT _ 0; fromData: OutlineData _ NARROW[from.data]; fromChildren: LIST OF Slice _ fromData.children; toSize: INT _ 0; toData: OutlineData _ NARROW[to.data]; toChildren: LIST OF Slice _ toData.children; lastToChildren: LIST OF Slice _ NIL; toData.oddWrap _ fromData.oddWrap; toData.fillColor _ fromData.fillColor; toData.fillText _ fromData.fillText; toData.screenStyle _ fromData.screenStyle; FOR fromList: LIST OF Slice _ fromChildren, fromList.rest UNTIL fromList=NIL DO fromSize _ fromSize+1; ENDLOOP; FOR toList: LIST OF Slice _ toChildren, toList.rest UNTIL toList=NIL DO toSize _ toSize+1; ENDLOOP; IF GGSlice.copyRestore THEN IF fromSize>=toSize THEN { UNTIL toChildren=NIL DO GGSliceOps.Restore[from: fromChildren.first, to: toChildren.first]; toChildren.first.parent _ to; -- must be restored in case it was reused at top level lastToChildren _ toChildren; fromChildren _ fromChildren.rest; toChildren _ toChildren.rest; ENDLOOP; IF lastToChildren#NIL THEN { -- put back the remaining "from" children. lastToChildren.rest _ fromChildren; -- hook up the lists FOR adoptees: LIST OF Slice _ fromChildren, adoptees.rest UNTIL adoptees=NIL DO adoptees.first.parent _ to; ENDLOOP; } } ELSE { -- fromSize= 8810.24 THEN GGParseIn.ReadWRope[f, "Children:"] ELSE GGParseIn.ReadWRope[f, "Trajectories:"]; GGParseIn.ReadWRope[f, "["]; count _ GGParseIn.ReadWNAT[f]; GGParseIn.ReadWRope[f, "]"]; IF count>0 THEN { [childList, ptr] _ GGUtility.StartSliceList[]; FOR i: NAT IN [0..count) DO nextChild _ GGSliceOps.FileinSlice[f, version, router, camera, IF version>=8802.04 THEN NIL ELSE trajClass]; -- older files had only trajectories as children of outlines IF someChild=NIL AND nextChild#NIL AND GGSliceOps.GetType[nextChild]=$Traj AND NARROW[nextChild.data, TrajData].role=circle THEN { fillColor _ NIL; -- needed for the transition from circle/disc class NARROW[nextChild.data, TrajData].role _ fence; -- fixup the kludge from TrajFilein }; IF nextChild#NIL THEN { someChild _ nextChild; [childList, ptr] _ GGUtility.AddSlice[nextChild, childList, ptr]; } ELSE ComplainAboutFile[f, "Parent", "NIL child detected", router]; ENDLOOP; RETURN[childList]; } ELSE ComplainAboutFile[f, "Parent", "parental object with no children detected", router]; }; OutlineFileout: PUBLIC PROC [slice: Slice, f: IO.STREAM] = { outlineData: OutlineData _ NARROW[slice.data]; f.PutF["fillColor: "]; GGParseOut.WriteColor[f, outlineData.fillColor]; f.PutF[" ow: "]; GGParseOut.WriteBool[f, outlineData.oddWrap]; f.PutF[" fillText: "]; GGParseOut.WriteText[f, outlineData.fillText, outlineData.screenStyle]; f.PutChar[IO.CR]; GGParent.Fileout[slice, f]; }; OutlineFilein: PUBLIC PROC [f: IO.STREAM, version: REAL, router: MsgRouter, camera: Camera] RETURNS [slice: Slice] = { oddWrap, good: BOOL _ TRUE; fillColor: Color; fillText: TextNode.Ref; screenStyle: BOOL _ TRUE; childList: LIST OF Slice; IF trajClass=NIL THEN trajClass _ GGSlice.FetchSliceClass[$Traj]; GGParseIn.ReadWRope[f, "fillColor:"]; fillColor _ GGParseIn.ReadColor[f, version]; IF version>=8802.04 THEN { GGParseIn.ReadWRope[f, "ow:"]; [oddWrap, good] _ GGParseIn.ReadBool[f, version]; }; IF version>=8803.24 THEN { GGParseIn.ReadWRope[f, "fillText:"]; [fillText, screenStyle] _ GGParseIn.ReadText[f, version]; }; IF version < 8702.26 THEN { -- read and discard StrokeEnd from older formats GGParseIn.ReadWRope[f, "strokeEnd:"]; [] _ GGParseIn.ReadStrokeEnd[f]; }; childList _ GGParent.Filein[f, version, router, camera]; IF childList#NIL THEN slice _ OutlineFromChildList[childList, fillColor, oddWrap, fillText, screenStyle, version]; }; ComplainAboutFile: PROC [f: IO.STREAM, className, complaint: Rope.ROPE, router: MsgRouter] = { of: FS.OpenFile; fileName: Rope.ROPE _ NIL; of _ FS.OpenFileFromStream[f ! IO.Error => { fileName _ "not a file"; CONTINUE }; ]; IF fileName=NIL THEN fileName _ FS.GetName[of].fullFName; Feedback.PutF[router, oneLiner, $Complaint, "Filein Error for %g: %g slice, %g", [rope[fileName]], [rope[className]], [rope[complaint]] ]; }; IsEmptyParts: PUBLIC PROC [sliceD: SliceDescriptor] RETURNS [BOOL _ FALSE] = { realParts: OutlineParts _ NARROW[sliceD.parts]; RETURN[IsEmpty[realParts]]; }; IsEmpty: PUBLIC PROC [realParts: OutlineParts] RETURNS [BOOL _ FALSE] = { IF realParts=NIL THEN RETURN[TRUE]; -- NIL means Empty, Bier, June 29, 1990 FOR list: LIST OF SliceDescriptor _ realParts.descriptors, list.rest UNTIL list = NIL DO IF list.first#NIL AND NOT GGSliceOps.IsEmptyParts[list.first] THEN RETURN[FALSE]; ENDLOOP; RETURN[TRUE]; }; IsCompleteParts: PUBLIC PROC [sliceD: SliceDescriptor] RETURNS [BOOL _ FALSE] = { realParts: OutlineParts _ NARROW[sliceD.parts]; RETURN[IsComplete[realParts]]; }; IsComplete: PUBLIC PROC [realParts: OutlineParts] RETURNS [BOOL _ FALSE] = { IF realParts=NIL THEN RETURN[FALSE]; -- NIL means empty, Bier, June 29, 1990 FOR list: LIST OF SliceDescriptor _ realParts.descriptors, list.rest UNTIL list = NIL DO IF list.first=NIL OR NOT GGSliceOps.IsCompleteParts[list.first] THEN RETURN[FALSE]; ENDLOOP; RETURN[TRUE]; }; NewParts: PUBLIC PROC [slice: Slice, hitData: REF ANY, mode: SelectMode] RETURNS [sliceD: SliceDescriptor] = { outlineData: OutlineData _ NARROW[slice.data]; outlineHitData: OutlineHitData _ NARROW[hitData]; newParts: OutlineParts _ NEW[OutlinePartsObj]; SELECT mode FROM none, slice, topLevel => { -- build a complete descriptor ptr: LIST OF SliceDescriptor; [newParts.descriptors, ptr] _ GGUtility.StartSliceDescriptorList[]; FOR children: LIST OF Slice _ outlineData.children, children.rest UNTIL children=NIL DO child: Slice _ children.first; childD: SliceDescriptor _ IF mode=none THEN NIL ELSE GGSliceOps.NewParts[child, NIL, slice]; [newParts.descriptors, ptr] _ GGUtility.AddSliceDescriptor[childD, newParts.descriptors, ptr]; ENDLOOP; sliceD _ GGSlice.DescriptorFromParts[slice, newParts]; -- empty or complete parts }; ENDCASE => { -- all other cases need a legit hitData FOR children: LIST OF Slice _ outlineData.children, children.rest UNTIL children=NIL DO child: Slice _ children.first; IF child=outlineHitData.child THEN { childD: SliceDescriptor _ GGSliceOps.NewParts[child, outlineHitData.childHitData, mode]; sliceD _ GGParent.DescriptorFromChildDescriptor[slice, childD]; -- hit parts RETURN; }; ENDLOOP; SIGNAL Problem["Unmatched outline and hitData in OutlineNewParts"]; }; }; UnionParts: PUBLIC PROC [partsA: SliceDescriptor, partsB: SliceDescriptor] RETURNS [aPlusB: SliceDescriptor] = { realPartsA: OutlineParts _ NARROW[partsA.parts]; realPartsB: OutlineParts _ NARROW[partsB.parts]; IF partsA.parts = NIL THEN RETURN[partsB]; IF partsB.parts = NIL THEN RETURN[partsA]; IF IsEmpty[realPartsA] THEN RETURN[partsB]; IF IsEmpty[realPartsB] THEN RETURN[partsA]; IF IsComplete[realPartsA] THEN RETURN[partsA]; IF IsComplete[realPartsB] THEN RETURN[partsB]; BEGIN ptr: LIST OF SliceDescriptor; union: OutlineParts _ NEW[OutlinePartsObj]; listA: LIST OF SliceDescriptor _ realPartsA.descriptors; listB: LIST OF SliceDescriptor _ realPartsB.descriptors; [union.descriptors, ptr] _ GGUtility.StartSliceDescriptorList[]; UNTIL listA = NIL DO IF listA.first = NIL THEN [union.descriptors, ptr] _ GGUtility.AddSliceDescriptor[listB.first, union.descriptors, ptr] ELSE IF listB.first = NIL THEN [union.descriptors, ptr] _ GGUtility.AddSliceDescriptor[listA.first, union.descriptors, ptr] ELSE { newSeq: SliceDescriptor _ GGSliceOps.UnionParts[listA.first, listB.first]; [union.descriptors, ptr] _ GGUtility.AddSliceDescriptor[IF GGSliceOps.IsEmptyParts[newSeq] THEN NIL ELSE newSeq, union.descriptors, ptr]; }; listA _ listA.rest; listB _ listB.rest; ENDLOOP; aPlusB _ GGSlice.DescriptorFromParts[partsA.slice, union]; END; }; DifferenceParts: PUBLIC PROC [partsA: SliceDescriptor, partsB: SliceDescriptor] RETURNS [aMinusB: SliceDescriptor] = { realPartsA, realPartsB: OutlineParts; diff: OutlineParts; listA: LIST OF SliceDescriptor; listB: LIST OF SliceDescriptor; ptr: LIST OF SliceDescriptor; IF partsA.parts = NIL OR partsB = NIL OR partsB.parts = NIL THEN RETURN[partsA]; realPartsA _ NARROW[partsA.parts]; realPartsB _ NARROW[partsB.parts]; listA _ realPartsA.descriptors; listB _ realPartsB.descriptors; diff _ NEW[OutlinePartsObj]; [diff.descriptors, ptr] _ GGUtility.StartSliceDescriptorList[]; UNTIL listA = NIL DO IF listA.first = NIL THEN [diff.descriptors, ptr] _ GGUtility.AddSliceDescriptor[NIL, diff.descriptors, ptr] ELSE IF listB = NIL OR listB.first = NIL THEN [diff.descriptors, ptr] _ GGUtility.AddSliceDescriptor[listA.first, diff.descriptors, ptr] ELSE { newSeq: SliceDescriptor _ GGSliceOps.DifferenceParts[listA.first, listB.first]; [diff.descriptors, ptr] _ GGUtility.AddSliceDescriptor[IF GGSliceOps.IsEmptyParts[newSeq] THEN NIL ELSE newSeq, diff.descriptors, ptr]; }; listA _ listA.rest; listB _ listB.rest; ENDLOOP; aMinusB _ GGSlice.DescriptorFromParts[partsA.slice, diff]; }; OutlineMovingParts: PROC [slice: Slice, selectedParts: SliceParts, editConstraints: EditConstraints, bezierDrag: GGInterfaceTypes.BezierDragRecord] RETURNS [background, overlay, rubber, drag: SliceDescriptor] = { outlineData: OutlineData _ NARROW[slice.data]; filled: BOOL _ outlineData.fillColor#NIL OR outlineData.fillText#NIL; RETURN GGParent.MovingParts[slice, selectedParts, filled, editConstraints, bezierDrag]; }; MovingParts: PUBLIC PROC [slice: Slice, selectedParts: SliceParts, treatAsAUnit: BOOL _ FALSE, editConstraints: EditConstraints, bezierDrag: GGInterfaceTypes.BezierDragRecord] RETURNS [background, overlay, rubber, drag: SliceDescriptor] = { outlineData: OutlineData; outlineParts: OutlineParts _ NARROW[selectedParts]; bkgdParts, overParts, rubberParts, dragParts: OutlineParts; bkgdSeq, overSeq, rubberSeq, dragSeq: SliceDescriptor; bkgdPtr, overPtr, rubberPtr, dragPtr: LIST OF SliceDescriptor; children: LIST OF Slice; nullD: SliceDescriptor _ slice.nullDescriptor; forNow: BOOL _ TRUE; IF IsEmpty[outlineParts] THEN { background _ overlay _ rubber _ drag _ nullD; RETURN; }; IF IsComplete[outlineParts] THEN { background _ overlay _ rubber _ nullD; drag _ GGSlice.DescriptorFromParts[slice, selectedParts]; RETURN; }; bkgdParts _ NEW[OutlinePartsObj]; overParts _ NEW[OutlinePartsObj]; rubberParts _ NEW[OutlinePartsObj]; dragParts _ NEW[OutlinePartsObj]; [bkgdParts.descriptors, bkgdPtr] _ GGUtility.StartSliceDescriptorList[]; [overParts.descriptors, overPtr] _ GGUtility.StartSliceDescriptorList[]; [rubberParts.descriptors, rubberPtr] _ GGUtility.StartSliceDescriptorList[]; [dragParts.descriptors, dragPtr] _ GGUtility.StartSliceDescriptorList[]; outlineData _ NARROW[slice.data]; children _ outlineData.children; FOR list: LIST OF SliceDescriptor _ outlineParts.descriptors, list.rest UNTIL list = NIL DO IF list.first = NIL THEN { [rubberParts.descriptors, rubberPtr] _ GGUtility.AddSliceDescriptor[NIL, rubberParts.descriptors, rubberPtr]; [dragParts.descriptors, dragPtr] _ GGUtility.AddSliceDescriptor[NIL, dragParts.descriptors, dragPtr]; IF treatAsAUnit THEN { overSeq _ GGSliceOps.NewParts[children.first, NIL, slice]; -- complete descriptor [overParts.descriptors, overPtr] _ GGUtility.AddSliceDescriptor[overSeq, overParts.descriptors, overPtr]; [bkgdParts.descriptors, bkgdPtr] _ GGUtility.AddSliceDescriptor[NIL, bkgdParts.descriptors, bkgdPtr]; } ELSE { bkgdSeq _ GGSliceOps.NewParts[children.first, NIL, slice]; -- complete descriptor [bkgdParts.descriptors, bkgdPtr] _ GGUtility.AddSliceDescriptor[bkgdSeq, bkgdParts.descriptors, bkgdPtr]; [overParts.descriptors, overPtr] _ GGUtility.AddSliceDescriptor[NIL, overParts.descriptors, overPtr]; }; } ELSE { [bkgdSeq, overSeq, rubberSeq, dragSeq] _ GGSliceOps.MovingParts[list.first.slice, list.first.parts, editConstraints, bezierDrag]; -- for now bezierDrag is extra IF treatAsAUnit OR forNow THEN { [bkgdParts.descriptors, bkgdPtr] _ GGUtility.AddSliceDescriptor[NIL, bkgdParts.descriptors, bkgdPtr]; [overParts.descriptors, overPtr] _ GGUtility.AddSliceDescriptor[overSeq, overParts.descriptors, overPtr]; [rubberParts.descriptors, rubberPtr] _ GGUtility.AddSliceDescriptor[rubberSeq, rubberParts.descriptors, rubberPtr]; [dragParts.descriptors, dragPtr] _ GGUtility.AddSliceDescriptor[dragSeq, dragParts.descriptors, dragPtr]; } ELSE { [bkgdParts.descriptors, bkgdPtr] _ GGUtility.AddSliceDescriptor[overSeq, bkgdParts.descriptors, bkgdPtr]; [overParts.descriptors, overPtr] _ GGUtility.AddSliceDescriptor[NIL, overParts.descriptors, overPtr]; [rubberParts.descriptors, rubberPtr] _ GGUtility.AddSliceDescriptor[rubberSeq, rubberParts.descriptors, rubberPtr]; [dragParts.descriptors, dragPtr] _ GGUtility.AddSliceDescriptor[dragSeq, dragParts.descriptors, dragPtr]; }; }; children _ children.rest; ENDLOOP; background _ GGSlice.DescriptorFromParts[slice, bkgdParts]; overlay _ GGSlice.DescriptorFromParts[slice, overParts]; rubber _ GGSlice.DescriptorFromParts[slice, rubberParts]; drag _ GGSlice.DescriptorFromParts[slice, dragParts]; }; AugmentParts: PUBLIC PROC [sliceD: SliceDescriptor, selectClass: SelectionClass] RETURNS [more: SliceDescriptor] = { ptr: LIST OF SliceDescriptor; outlineParts: OutlineParts _ NARROW[sliceD.parts]; newParts: OutlineParts; IF outlineParts = NIL THEN RETURN[sliceD]; newParts _ NEW[OutlinePartsObj]; [newParts.descriptors, ptr] _ GGUtility.StartSliceDescriptorList[]; FOR nextParts: LIST OF SliceDescriptor _ outlineParts.descriptors, nextParts.rest UNTIL nextParts=NIL DO nextPart: SliceDescriptor _ nextParts.first; [newParts.descriptors, ptr] _ GGUtility.AddSliceDescriptor[IF nextPart#NIL THEN GGSliceOps.AugmentParts[nextPart, selectClass] ELSE NIL, newParts.descriptors, ptr]; ENDLOOP; more _ GGSlice.DescriptorFromParts[sliceD.slice, newParts]; }; AlterParts: PUBLIC PROC [sliceD: SliceDescriptor, action: ATOM] RETURNS [alteredD: SliceDescriptor] = { outlineParts: OutlineParts _ NARROW[sliceD.parts]; outlineData: OutlineData _ NARROW[sliceD.slice.data]; newParts: OutlineParts _ NEW[OutlinePartsObj]; childD: SliceDescriptor _ GGParent.FirstIncludedChild[sliceD.slice, sliceD.parts, first]; child: Slice _ childD.slice; BEGIN SELECT action FROM $Forward, $Backward => { IF IsComplete[outlineParts] THEN RETURN[NIL]; IF GGSliceOps.IsCompleteParts[childD] THEN { beforeEnt, ent, afterEnt: LIST OF Slice; [beforeEnt, ent, afterEnt, ----] _ GGUtility.FindSliceAndNeighbors[child, outlineData.children]; IF action = $Forward THEN alteredD _ IF afterEnt = NIL THEN NIL ELSE GGParent.DescriptorFromChild[sliceD.slice, afterEnt.first] ELSE alteredD _ IF beforeEnt = NIL THEN NIL ELSE GGParent.DescriptorFromChild[sliceD.slice, beforeEnt.first]; } ELSE GOTO Recurse; }; $Grow => { IF IsComplete[outlineParts] THEN RETURN[NIL]; IF GGSliceOps.IsCompleteParts[childD] THEN alteredD _ GGSliceOps.NewParts[sliceD.slice, NIL, slice] ELSE GOTO Recurse; }; $ShrinkForward => { IF IsComplete[outlineParts] THEN alteredD _ GGParent.DescriptorFromChild[sliceD.slice, OutlineLastChild[sliceD.slice]] ELSE GOTO Recurse; }; $ShrinkBackward => { IF IsComplete[outlineParts] THEN alteredD _ GGParent.DescriptorFromChild[sliceD.slice, OutlineFirstChild[sliceD.slice]] ELSE GOTO Recurse; }; ENDCASE => ERROR; EXITS Recurse => { alteredChildD: SliceDescriptor _ GGSliceOps.AlterParts[childD, action]; alteredD _ IF alteredChildD = NIL THEN NIL ELSE GGParent.DescriptorFromChildDescriptor[sliceD.slice, alteredChildD]; }; END; }; OutlineFirstChild: PROC [slice: Slice] RETURNS [child: Slice] = { outlineData: OutlineData _ NARROW[slice.data]; child _ outlineData.children.first; }; OutlineLastChild: PROC [slice: Slice] RETURNS [child: Slice] = { outlineData: OutlineData _ NARROW[slice.data]; FOR list: LIST OF Slice _ outlineData.children, list.rest UNTIL list = NIL DO child _ list.first; ENDLOOP; }; SetSelectedFields: PUBLIC PROC [sliceD: SliceDescriptor, selected: BOOL, selectClass: SelectionClass] = { outlineParts: OutlineParts _ NARROW[sliceD.parts]; IF outlineParts = NIL THEN RETURN; FOR nextParts: LIST OF SliceDescriptor _ outlineParts.descriptors, nextParts.rest UNTIL nextParts=NIL DO nextPart: SliceDescriptor _ nextParts.first; IF nextPart#NIL THEN GGSliceOps.SetSelectedFields[nextPart, selected, selectClass]; ENDLOOP; }; PointGeneratorData: TYPE = REF PointGeneratorDataObj; PointGeneratorDataObj: TYPE = RECORD [ seqPtr: LIST OF SliceDescriptor, pointGen: PointGenerator -- the point generator for the first sequence of seqPtr ]; PointPairGeneratorData: TYPE = REF PointPairGeneratorDataObj; PointPairGeneratorDataObj: TYPE = RECORD [ seqPtr: LIST OF SliceDescriptor, pointGen: PointPairGenerator -- the pair generator for first sequence of seqPtr ]; SegmentGeneratorData: TYPE = REF SegmentGeneratorDataObj; SegmentGeneratorDataObj: TYPE = RECORD [ seqPtr: LIST OF SliceDescriptor, segGen: SegmentGenerator -- the point generator for the first sequence of seqPtr ]; PointsInDescriptor: PUBLIC PROC [sliceD: SliceDescriptor] RETURNS [pointGen: PointGenerator] = { outlineParts: OutlineParts _ NARROW[sliceD.parts]; descriptors: LIST OF SliceDescriptor; childPointGen: PointGenerator; pointGenData: PointGeneratorData; descriptors _ IF outlineParts = NIL THEN NIL ELSE outlineParts.descriptors; childPointGen _ IF descriptors = NIL OR descriptors.first = NIL THEN NIL ELSE GGSliceOps.PointsInDescriptor[descriptors.first]; pointGenData _ NEW[PointGeneratorDataObj _ [descriptors, childPointGen]]; pointGen _ NEW[PointGeneratorObj _ [sliceD, 0, 0, pointGenData]]; }; WalkPointsInDescriptor: PUBLIC PROC [sliceD: SliceDescriptor, walkProc: PointWalkProc] = { outlineParts: OutlineParts _ NARROW[sliceD.parts]; descriptors: LIST OF SliceDescriptor; IF outlineParts = NIL THEN RETURN; descriptors _ outlineParts.descriptors; FOR descriptors: LIST OF SliceDescriptor _ outlineParts.descriptors, descriptors.rest UNTIL descriptors = NIL DO IF descriptors.first # NIL THEN GGSliceOps.WalkPointsInDescriptor[descriptors.first, walkProc]; ENDLOOP; }; PointPairsInDescriptor: PUBLIC PROC [sliceD: SliceDescriptor] RETURNS [pointPairGen: GGModelTypes.PointPairGenerator] = { outlineParts: OutlineParts _ NARROW[sliceD.parts]; descriptors: LIST OF SliceDescriptor; childPointPairGen: PointPairGenerator; pointPairGenData: PointPairGeneratorData; descriptors _ IF outlineParts = NIL THEN NIL ELSE outlineParts.descriptors; childPointPairGen _ IF descriptors = NIL OR descriptors.first = NIL THEN NIL ELSE GGSliceOps.PointPairsInDescriptor[descriptors.first]; pointPairGenData _ NEW[PointPairGeneratorDataObj _ [descriptors, childPointPairGen]]; pointPairGen _ NEW[PointPairGeneratorObj _ [sliceD, 0, 0, pointPairGenData]]; }; SegmentsInDescriptor: PUBLIC PROC [sliceD: SliceDescriptor] RETURNS [segGen: SegmentGenerator] = { outlineParts: OutlineParts _ NARROW[sliceD.parts]; descriptors: LIST OF SliceDescriptor _ IF outlineParts = NIL THEN NIL ELSE outlineParts.descriptors; IF descriptors#NIL THEN { segGenData: SegmentGeneratorData _ NEW[SegmentGeneratorDataObj _ [ seqPtr: descriptors, -- one descriptor per child in outline, including NILs for unincluded descriptors segGen: IF descriptors.first=NIL THEN NIL ELSE GGSliceOps.SegmentsInDescriptor[descriptors.first] -- segGen for first child ]]; segGen _ NEW[SegmentGeneratorObj _ [ toGo: 9999, -- for debugging sliceD: sliceD, completeSeq: FALSE, classSpecific: segGenData ]]; }; }; NextSegment: PUBLIC PROC [slice: Slice, segGen: SegmentGenerator] RETURNS [seg: Segment, transform: ImagerTransformation.Transformation] = { segGenData: SegmentGeneratorData _ NARROW[segGen.classSpecific]; descriptors: LIST OF SliceDescriptor _ segGenData.seqPtr; IF segGen.toGo#9999 THEN ERROR; -- for debugging WHILE TRUE DO IF descriptors.first # NIL THEN { -- maybe some seg left in this child [seg, transform] _ GGSliceOps.NextSegment[descriptors.first.slice, segGenData.segGen]; IF seg#NIL THEN { segGenData.seqPtr _ descriptors; RETURN; }; descriptors _ descriptors.rest; -- on to the next child }; UNTIL descriptors = NIL OR descriptors.first # NIL DO descriptors _ descriptors.rest ENDLOOP; IF descriptors = NIL THEN RETURN[NIL, NIL]; segGenData.segGen _ GGSliceOps.SegmentsInDescriptor[descriptors.first]; -- segGen for next child ENDLOOP; }; WalkSegments: PUBLIC PROC [slice: Slice, walkProc: WalkProc] RETURNS [sliceD: SliceDescriptor] = { ptr: LIST OF SliceDescriptor; outlineData: OutlineData _ NARROW[slice.data]; newParts: OutlineParts _ NEW[OutlinePartsObj]; [newParts.descriptors, ptr] _ GGUtility.StartSliceDescriptorList[]; FOR children: LIST OF Slice _ outlineData.children, children.rest UNTIL children=NIL DO child: Slice _ children.first; childD: SliceDescriptor _ GGSliceOps.WalkSegments[child, walkProc]; [newParts.descriptors, ptr] _ GGUtility.AddSliceDescriptor[childD, newParts.descriptors, ptr]; ENDLOOP; sliceD _ GGSlice.DescriptorFromParts[slice, newParts]; }; NextPoint: PUBLIC PROC [slice: Slice, pointGen: PointGenerator] RETURNS [pointAndDone: GGModelTypes.PointAndDone] = { pgd: PointGeneratorData _ NARROW[pointGen.classSpecific]; descriptors: LIST OF SliceDescriptor _ pgd.seqPtr; IF descriptors = NIL THEN RETURN[[[0,0], TRUE]]; WHILE TRUE DO IF descriptors.first # NIL THEN { -- maybe some point left in this child pointAndDone _ GGSliceOps.NextPoint[descriptors.first.slice, pgd.pointGen]; IF NOT pointAndDone.done THEN { pgd.seqPtr _ descriptors; RETURN; }; descriptors _ descriptors.rest; -- on to the next child }; UNTIL descriptors = NIL OR descriptors.first # NIL DO descriptors _ descriptors.rest ENDLOOP; IF descriptors = NIL THEN RETURN[[[0,0], TRUE]]; pgd.pointGen _ GGSliceOps.PointsInDescriptor[descriptors.first]; -- pointGen for next child ENDLOOP; }; NextPointPair: PUBLIC PROC [slice: Slice, pointPairGen: PointPairGenerator] RETURNS [pointPairAndDone: PointPairAndDone] = { pgd: PointPairGeneratorData _ NARROW[pointPairGen.classSpecific]; descriptors: LIST OF SliceDescriptor _ pgd.seqPtr; IF descriptors = NIL THEN RETURN[[[0,0], [0,0], TRUE]]; WHILE TRUE DO IF descriptors.first # NIL THEN { -- maybe some pair left in this child pointPairAndDone _ GGSliceOps.NextPointPair[descriptors.first.slice, pgd.pointGen]; IF NOT pointPairAndDone.done THEN { pgd.seqPtr _ descriptors; RETURN; }; descriptors _ descriptors.rest; -- on to the next child }; UNTIL descriptors = NIL OR descriptors.first # NIL DO descriptors _ descriptors.rest ENDLOOP; IF descriptors = NIL THEN RETURN[[[0,0], [0,0], TRUE]]; pgd.pointGen _ GGSliceOps.PointPairsInDescriptor[descriptors.first]; ENDLOOP; }; fillColor: PUBLIC Imager.Color _ Imager.MakeGray[0.5]; trajClass: SliceClass; -- filled in by OutlineFilein END. ฦGGOutlineImplA.mesa Contents: Implementations of the Parent Meta-Class and the Outline class. Copyright ำ 1986, 1987, 1988, 1989 by Xerox Corporation. All rights reserved. Pier, August 15, 1991 9:36 pm PDT Eisenman, October 2, 1987 9:22:03 pm PDT Bier, June 1, 1992 3:38 pm PDT Doug Wyatt, December 18, 1989 2:48:02 pm PST The Outline Class Fundamentals Drawing Transforming Textual Description Parts Part Generators Hit Testing Hit Testing moved to GGOutlineImplB Style Style moved to GGOutlineImplB Fundamentals Drawing Transforming Textual Description Parts Part Generators Hit Testing Hit Testing moved to GGOutlineImplB Style Style moved to GGOutlineImplB Textual Description The Cluster Class Fundamentals Drawing Draw the big boxes for speed, if you can. Textual Description Parts The Parent Meta-Class Fundamentals GGModelTypes.SliceBoundBoxProc bound box of all the children GGModelTypes.SliceBoundBoxProc bound box of all the children This PROC assumes that only Trajs can be copied in part. All other classes are copied in entirety. Since outlineParts represents a complete cluster or outline, copying a given child produces a single slice. Creates the parent and adds the child to its list of children. Since outlineParts represents a complete cluster or outline, copying a given child produces a single slice. Add the rest of the children to the list. GGModelTypes.SliceRestoreProc from and to must be nearly identically structured slices, probably because from was made as a copy of to. Restore the contents of "to", getting all non-REF values from "from". Good luck. CAN THIS LEAD TO OBSOLETE DESCRIPTORS?? Reparent !! Reparent !! to.nullDescriptor is always valid to.fullDescriptor is unused Drawing GGModelTypes.SliceBuildPathProc transformParts=NIL => complete parts. transform=NIL => don't transform any parts GGModelTypes.SliceDrawBorderProc drawParts=NIL => draw ALL parts. transformParts=NIL => transform ALL parts. transform=NIL => don't transform any parts. This routine assumes it is called without needing to transform any of its parts or needing to take EditConstraints into account. Currently draws entire outline. Draw the fill. Draw the strokes. Draw the fill text. Currently draws entire cluster. Draw children back to front. "parts" describes which children of slice are to be transformed (and which are to be drawn in place). If parts is NIL, then all children are to be transformed (or not if transform = NIL); Fill in the outline if appropriate. Draw the strokes. parts=NIL => transform entire slice If some joints are both normal and hot selected, a special symbol is drawn at them, and separate symbols are drawn at other joints. If the parent is entirely selected or entirely hot, and we are allowed to try fast feedback, a single large box is drawn for that selection type for the entire slice. IF caretIsMoving OR dragInProgress THEN RETURN; IF selectedParts=NIL AND hotParts=NIL THEN RETURN; Draw the big boxes for speed, if you can. The selectedParts are a hint as to what is being dragged. Attractor feedback for the moving part is suppressed if the attractor is part of something that is moving. Find out which parts of the child should not be highlighted (because they are moving). The selectedParts are a hint as to what is being dragged. Attractor feedback for the moving part is suppressed if the attractor is part of something that is moving. Find out which parts of the child should not be highlighted (because they are moving). Return which parts of child are mentioned in parts. GGModelTypes.SliceSaveSelectionsProc Ya gotta clear out them bits first because there may have been NO SELECTION! GGModelTypes.SliceRemakeSelectionsProc Transforming Call GGSliceOps.Transform on each child, with history=NIL so the children will not make history list entries. The outline will make one instead. This proc assumes that every Box in the outline is filled if any are filled This proc assumes that every Box in the outline is filled if any are filled Textual Description IF realParts describes exactly one child, return that child. Otherwise return NIL. An outlineHitData is now [child: Slice, childHitData: REF ANY]; Filein: PUBLIC PROC [f: IO.STREAM, version: REAL, router: MsgRouter, camera: Camera] RETURNS [children: LIST OF Slice] = { 8803.24, 8810.24 count: NAT _ 0; class: SliceClass; className: Rope.ROPE; someChild, nextChild: Slice; childList, ptr: LIST OF Slice; IF version >= 8810.24 THEN GGParseIn.ReadWRope[f, "Children:"] ELSE GGParseIn.ReadWRope[f, "Trajectories:"]; GGParseIn.ReadWRope[f, "["]; count _ GGParseIn.ReadWNAT[f]; GGParseIn.ReadWRope[f, "]"]; IF count>0 THEN { [childList, ptr] _ GGUtility.StartSliceList[]; FOR i: NAT IN [0..count) DO IF version>=8802.04 THEN { className _ GGParseIn.ReadWWord[f]; class _ IF className=NIL THEN NIL ELSE GGSlice.FetchSliceClass[Atom.MakeAtom[className]]; IF class=NIL THEN {ComplainAboutFile[f, "unknown class", "NIL child detected", feedback]; LOOP;}; } ELSE { className _ "Traj"; class _ trajClass; }; nextChild _ class.filein[f, version, feedback, camera]; IF someChild=NIL AND nextChild#NIL AND class.type=$Traj AND NARROW[nextChild.data, TrajData].role=circle THEN { I think this is a bug (changing the global fillColor) but I don't know what its about and it is probably never happening so ... KAP. January 4, 1989 fillColor _ NIL; -- needed for the transition from circle/disc class NARROW[nextChild.data, TrajData].role _ fence; -- fixup the kludge from TrajFilein }; IF nextChild#NIL THEN { someChild _ nextChild; [childList, ptr] _ GGUtility.AddSlice[nextChild, childList, ptr]; } ELSE ComplainAboutFile[f, className, "NIL child detected", feedback]; ENDLOOP; RETURN[childList]; } ELSE ComplainAboutFile[f, "Parent", "parental object with no children detected", feedback]; }; I think this is a bug (changing the global fillColor) but I don't know what its about and it is probably never happening so ... KAP. January 4, 1989 8803.24, 8810.24 Parts An outlineHitData is now [child: Slice, childHitData: REF ANY]; Filled outlines have the property that if any of their subparts are on the overlay plane, then all of their parts are on the overlay plane. (For now, all outline children are either completely on the overlay or completely off -- Bier, March 14, 1988) Some parts are selected, but not all (the hard case) This trajectory is not at all selected. If this parent is to be treated as a unit, put it on the overlay. Otherwise, leave it in the background. Some or all of this trajectory is selected. If the outline is treatAsAUnit, put all on overlay. Otherwise, put non-moving parts on background. Like, if you (normal) select a segment, you should select its end joints as well. This PROC gives new classes a chance to invent their own rules for augmenting selections. Set the selected fields of all of the joints and segments mentioned in sliceD. Hit Testing It looks like GGSliceOps.WalkPointsInDescriptor has to return a "done" BOOLEAN for this to work properly. on to next non-NIL child end of the line ?? Takes a slice and calls the walkProc for each segment in the slice with the segment data and possibly an associated transformation. It returns a slice descriptor which describes all segments of the slice for which the walkProc returned TRUE. on to next non-NIL child on to next non-NIL child สCŠ– "cedar" style•NewlineDelimiter ˜Icodešœ™šฯbœA™IKšœN™NKšœ!™!Kšœ(™(K™K™,—K™šฯk ˜ Jšœžœ‘žœ˜ฬ—K˜šฯnœžœž˜Jšžœ žœ”žœ˜ฐKšžœ ž˜-K˜Kšœ žœ˜+Kšœ žœ˜)Kšœ žœ˜&Kšœžœ˜#Kšœžœ˜#Kšœžœ˜Kšœžœ&˜AKšœ žœ˜-Kšœžœ ˜5Kšœ žœ ˜1Jšœ žœ˜*Kšœžœ˜'Kšœžœ˜1Kšœ žœ˜*Kšœžœ˜#Kšœžœ˜3Kšœžœ˜Kšœ žœ žœ ˜*Kšœžœ˜0Kšœžœ˜0Kšœžœ˜6Kšœžœ˜,Kšœžœ˜2Kšœžœ˜!Kšœžœ˜/Kšœžœ˜3Kšœžœ"˜9Kšœžœ!˜7Kšœžœ#˜;Kšœžœ&˜AKšœžœ˜1Kšœžœ˜!Kšœ žœ˜'Kšœžœ!˜7Kšœžœ$˜=Kšœžœ!˜5Kšœ žœ˜+Kšœžœ ˜7Kšœžœ˜2Kšœžœ˜!Kšœ žœ˜+Kšœžœ˜1Kšœžœ ˜5Kšœžœ)˜GKšœžœ˜3Kšœ žœ˜'Kšœ žœ˜+Iprocšœ žœ˜#Kšœ žœ˜'Kšœžœ˜Kšœ žœ˜'Kšœ žœ˜%Kšœ žœ˜)Kšœžœ˜/Kšœžœ'˜;Kšœ žœ˜/Kšœžœ˜#Kšœ žœ˜'K˜Kšœ žœ˜)Kšœ žœ˜)Kšœ žœ˜+Kšœ žœ˜+Kšœ žœ˜'K˜Lšœ žœžœ˜'Lšœžœ˜.K˜KšŸœžœžœ žœ˜;—head1šœ™K™—šŸœžœžœžœ˜Fšœžœ˜Kšœ˜Kšœ˜Kš ™ Kšœ"˜"Kšœ Ÿœ˜;Kšœ"˜"Kšœ˜K˜Kš™K˜K˜Kšœ˜Kšœ$˜$Kšœ4˜4Kšœ6˜6Kšœ>˜>K˜(Kšœ,˜,Kš ™ Kšœ˜Kš™Kšœ˜Kšœ"˜"Kšœ˜Kšœ˜Kš™Kšœ$˜$Kšœ*˜*Kšœ˜Kšœ ˜ Kšœ*˜*Kšœ ˜ Kšœ$˜$Kšœ ˜ Kšœ.˜.Kš™Kšœ0˜0K˜8Kšœ8˜8Kšœ4˜4Kšœ$˜$Kšœ˜Kšœ&˜&Kšœ!˜!šฯi˜Kšะbi ™ Kšก#™#—Kš $˜$Kš 6˜6Kš ;˜;Kš (˜(Kš ,˜,Kš 0˜0š 4˜4Kšก™Kšก™—Kš "˜"Kš (˜(Kš (˜(Kš $˜$Kš $˜$Kš (˜(Kš (˜(Kš (˜(Kš (˜(Kš $˜$Kš "˜"Kš !˜!Kš !˜!Kš ˜Kš ˜Kš ˜K˜—KšŸ"œ˜*K˜K˜—šŸœžœžœžœ˜Fšœžœ˜Kšœ˜Kšœ˜Kš ™ Kšœ"˜"Kšœ Ÿœ˜;Kšœ"˜"Kšœ˜K˜Kš™K˜!K˜#Kšœ˜Kšœ&˜&Kšœ4˜4Kšœ-˜-K˜5K˜(Kšœ,˜,Kš ™ Kšœ˜Kš™Kšœ˜Kšœ"˜"Kšœ˜Kšœ˜Kš™Kšœ$˜$Kšœ*˜*Kšœ˜Kšœ ˜ Kšœ*˜*Kšœ ˜ Kšœ$˜$Kšœ ˜ Kšœ.˜.Kš™Kšœ0˜0K˜8Kšœ8˜8Kšœ4˜4Kšœ$˜$Kšœ˜Kšœ&˜&Kšœ!˜!š ˜Kšก ™ Kšก#™#—Kš $˜$Kš 6˜6Kš ;˜;Kš (˜(Kš 4˜4Kš ,˜,Kš 0˜0š 4˜4Kšก™Kšก™—Kš "˜"Kš (˜(Kš (˜(Kš $˜$Kš $˜$Kš (˜(Kš (˜(Kš (˜(Kš (˜(Kš $˜$Kš $˜$Kš !˜!Kš !˜!Kš ˜Kš ˜K˜K˜—KšŸ"œ˜*K˜K˜—šŸœžœ žœžœ#žœžœ'žœ žœžœ˜ตKšœžœR˜išœ žœ ˜Kšœ)˜)Kšœžœ˜ K˜ Kšœžœžœžœ˜&Kšœ$˜$Kšœ$˜$Kšœ žœ˜—š žœžœžœžœžœž˜:Kšœ˜Kšžœ˜—Kšœ>žœ˜Cšžœžœฯcn˜ˆKšœ0žœœžœข#˜cš žœ žœžœ'žœ žœž˜QKšœ/žœœžœข&˜dKšžœ˜—K˜—Kšœ6žœ˜;Kšœ˜K˜—šŸœžœ žœžœžœ žœžœ˜oKš œžœžœ žœ%žœ'˜—šœ žœ ˜Kšœ)˜)Kšœžœ˜ K˜ Kšœžœžœžœ˜&Kšœ$˜$Kšœ$˜$Kšœ žœ˜—š žœžœžœžœžœž˜:Kšœ˜Kšžœ˜—Kšœ<žœ˜AKšœ˜—K™Kšœ™šŸœžœžœ žœ˜MKšžœ'˜-K˜—šŸœžœžœ žœ˜MKšžœ'˜-K˜—M™Kšœ ™ š Ÿ œžœ$žœžœžœžœ ˜[šŸœžœžœ˜CKšœ˜Kšœ!˜!Kšœ0˜0Kšœ žœ˜Kšœžœ3˜MK˜—Lšœžœ˜+Kšœžœ ˜*Kšœžœ˜;L˜Kšœ+˜+K˜—K˜Kšœ™šŸœž œ”žœ˜ฦKšœ2žœžœ˜?Kšœ#žœ˜9Kšœ žœ ˜1Kšœ žœžœ˜K˜Kšžœžœžœžœ˜/Kš žœžœžœ žœžœžœ˜2K˜Kšœ$žœžœ ˜KKšœžœžœ˜BKš œžœžœžœžœ˜BKš œžœžœžœžœ˜7K˜Kšœz˜zKš)™)šžœžœ žœžœ˜+Kšœ(žœ˜-Kšœ4˜4KšœZ˜ZKšœ žœ˜K˜—šžœžœ žœ žœ˜%Kšœ(žœ˜-Kšœ4˜4KšœW˜WKšœ žœ˜K˜—šžœžœ žœžœžœžœžœ˜\Kšœ(žœ˜-Kšœ4˜4K˜—K˜—K˜Kšœ™šŸœž œžœžœ˜šžœ žœžœ˜šœ(˜(Kšœk™k—šœ˜K™>—Kšœ žœ˜!K˜—šžœ˜šœ(˜(Kšœk™k—Kšœ>˜>Kšœ˜K˜—K˜—Kšœ žœ ˜Lšœ-˜-Kšœ3˜3šžœ ž˜KšžœJ˜N—Kšœ)™)Kšœžœ ˜K˜—šžœข7˜>šŸ œžœžœžœ˜=KšœQžœ ˜]Kšœ/˜/Kšžœ žœ=˜LJšœ'žœ ˜7Kšœ˜—š Ÿ œžœžœžœžœ˜KKšœ ˜ Kšœ&˜&šžœ%žœ˜-Jšœ'œ˜OK˜—šžœž˜Kšœžœ ˜/Kšžœ'žœžœ˜Lšžœ˜JšœZ˜Zšžœ[žœ žœž˜ršžœžœ)žœ˜5Kšœh˜hKšžœ˜Kšœ˜—Jšœ6˜6Jšœ8˜8Jšœ'žœ ˜7Jšžœ˜—J˜—J˜—J˜—KšœMžœ ˜YJšœD˜DJ˜—K˜K˜—šŸœž œžœ˜1Kšœ™K™ผKš žœžœžœžœžœžœ˜!Kšžœžœžœ˜"K˜Kšœžœžœžœ˜'Kš žœ žœžœ žœžœžœ˜1K˜šž˜Kšœ žœ˜Kšœžœ ˜*Kšœžœžœ˜0Kšœžœ˜Kšœžœ ˜&Kšœ žœžœ˜,Kšœžœžœ žœ˜$K˜Kšœฯt œฃ˜"Kšœฃ œ ฃ˜&Kšœฃ œฃ˜$Kšœฃ œ ฃ˜*K˜š žœ žœžœ%žœž˜OK˜Kšžœ˜—š žœ žœžœ!žœž˜GKšœ˜Kšžœ˜—K˜šัbklœ  œค˜šžœžœ˜šžœ žœž˜Kšœ œ1˜CKšœข6˜TKšœ˜Kšœ!˜!Kšœ˜Kšžœ˜—šžœžœžœข*˜GKšข'™'šœ$ข˜8K™ —š žœ žœžœ%žœ žœž˜OKšœ˜Kšžœ˜—K˜—K˜—šžœข˜šžœžœž˜Kšœ œ1˜CKšœข6˜TKšœ˜Kšœ!˜!Kšœ˜Kšžœ˜—Kš žœžœžœžœขQ˜‡K˜K˜——šคœ˜K™ š žœ žœžœ*žœ žœž˜TKšœ˜Kšžœ˜—Kšœ%ข˜9K˜—K˜Kšœ)ข˜:Kšœžœข˜5Kšœžœข˜2Kšœžœข˜5Kšœžœข˜4K™!K™K˜Kšœ&˜&Kšœ˜Kšœ˜Kšœ˜Kšœ"˜"Kšœ˜Kšœ ˜ K™Kšžœ˜—K˜K˜K˜—K™šœ™K˜—šŸœž œู˜๖Kšœ™KšœP™PKšœžœ ˜.Kšœ&žœ˜=Kšœ žœ žœ˜"Kš œžœ žœžœžœ˜:Kšœžœžœžœžœžœžœžœ#˜tš žœ žœžœ-žœ žœž˜YKšœ žœ,žœžœ*˜mšžœ žœข&˜9Kšžœ žœ&žœžœ;˜|Kšžœžœžœ&žœF˜ˆKšžœ&žœžœžœžœžœ!žœžœžœžœžœF˜๋K˜—Kšžœžœžœ.˜LKšžœ˜—K˜K˜—šŸœž œ‰žœžœ.˜แKšœ ™ Kšœy™yKšœžœ ˜.Kšœ!žœ ˜3Kšœ&žœ˜=Kšœ žœ žœ˜"Kš œžœ žœžœžœ˜:Kšœ žœ žœ˜Kšœžœžœžœžœžœžœžœ#˜tKš œžœžœžœ žœžœžœ˜_š žœ žœžœ-žœ žœž˜Yš žœ žœžœžœข ˜MKšžœ žœ'žœ žœžœžœžœžœ%˜›Kšžœžœžœ'žœ žœžœžœžœ0˜งKšžœ'žœ žœžœžœžœžœžœžœžœ!žœžœžœžœžœ0˜ŠK˜—Kšžœžœžœ.˜LKšžœžœžœ$˜=Kšžœ˜—K˜—K˜šŸœž œNžœ˜tK™€K™šŸ œ˜!š žœ žœžœ-žœ žœž˜YKšœžœ%˜1Kš žœžœžœœžœžœ2ข˜Kšžœ˜—K˜—Kšœžœ ˜.Kš™šžœžœžœ˜#Kšœ.˜.Kšœ7˜7K˜—Kš™š žœ žœžœ-žœ žœž˜YKš œžœžœžœžœ˜NKšžœ˜—Kš™šž˜š Ÿ œžœžœ žœžœ˜BKšœ-˜-K˜—K˜;Kšžœ˜—K˜K˜—šŸ œžœžœNžœ˜mK™K™Kšœžœ ˜.š žœ žœžœ-žœ žœž˜YKšœ%žœ˜=Kšžœ˜—K˜K™—šŸœž œ$žœf˜ฎKšœผ™ผšŸ œ˜!Kšœ žœžœ˜#Kšœ˜Kš œ žœžœžœžœžœ˜Iš žœ žœžœ-žœ žœž˜YKšœžœ žœžœžœžœžœžœ˜aKšœžœ žœžœžœžœ žœžœ˜Fdefaultšžœžœ"˜(Nšžœs˜w—Kšžœ žœžœ˜3Kšžœ˜—K˜—Kšœžœ ˜.Kšœžœ˜+Kšœ žœžœ˜%Kšœ˜K˜Kš œžœžœžœžœžœ˜KKš#™#šžœžœžœ˜#Kšžœžœ9˜YKšžœ/˜3Kšœ7˜7K˜—Kš™šž˜Kšœ˜š žœ žœžœ-žœ žœž˜YNšœžœ žœžœžœžœžœžœ˜cNšœžœžœžœžœžœ žœžœ˜JNšœ&žœ!žœ˜bKšžœžœžœ ˜9Kšžœ˜—Kšžœ˜—K˜K˜—šŸ œžœžœ$žœf˜งKšœžœ™#Kšœžœ ˜.Kšœžœ˜+Kšœ žœžœ˜#K˜Kšœ˜K˜'K˜Kš œ žœžœžœžœžœ˜Iš žœ žœžœ-žœ žœž˜YKšœ˜šžœ žœžœข˜8Kšœ žœ˜Kšœ˜K˜—š žœžœžœžœข˜:Kšœ#˜#Kšœ˜K˜—šžœข˜$Kšœ žœ˜Kšœžœ˜K˜—KšœP˜PKšžœ ž œ žœ˜4Kšžœ˜—K˜K˜—šŸœž œ”žœ˜ฟK™ซKšœžœžœ˜-Kšœ2žœžœ˜?Kšœ#žœ˜9Kšœ žœ ˜1Kšžœžœžœžœ™/Kš žœžœžœ žœžœžœ™2Kšœ$žœžœ ˜KKšœžœžœ˜BKš œžœžœžœžœ˜BKš œžœžœžœžœ˜7šžœ žœ žœ˜ Kšœ&˜&šžœ>žœ žœž˜Xšžœžœžœข<˜ZKš œ œ1žœžœžœžœžœP˜ร—š žœžœžœžœข(˜GKšœ œžœR˜‹—Kšœ˜Kšžœ˜—K˜—šžœžœ žœ˜šžœ>žœžœž˜ZKš žœžœžœ œ1žœ=˜ฐKšžœ˜—K˜—šžœžœ žœ˜šžœ5žœ žœž˜NKš žœžœžœ œžœR˜งKšžœ˜—K˜—K˜K˜—šŸœž œ”žœ˜ฦKšœ2žœžœ˜?Kšœ˜Kšœ#žœ˜9Kšœ žœ ˜1K˜Kšžœžœžœžœ˜/Kš žœžœžœ žœžœžœ˜2K˜Kšœ$žœžœ ˜KKšœžœžœ˜BKš œžœžœžœžœ˜BKš œžœžœžœžœ˜7K˜Kšœz˜zKš)™)šžœžœ žœžœžœ žœžœ˜NKšœžœžœ&žœ#˜‚K–([sliceD: GGModelTypes.SliceDescriptor]šœF˜FK–F[slice: GGModelTypes.Slice, pointGen: GGModelTypes.PointGenerator]šœV˜VKšœ˜—šžœžœ žœž˜)KšœH˜H—šžœžœ žœ ž˜#KšœE˜E—K˜K˜—šะbnœž œWžœK˜ศJ™ฅJšœ žœžœ˜Jšœ˜Jšœ˜JšœDข`˜คKšžœ žœžœžœ˜K™VKšœŸœ%˜MKšœ~˜~K˜K˜—šŸœž œWžœ4žœ˜ะJ™ฅJšœ žœžœ˜Jšœ˜Jšœ˜JšœDขA˜…Kšžœ žœžœžœ˜K™VKšœŸœ%˜MKšœ„˜„K˜K˜—šŸœžœ1žœ˜nKšœ3™3Kšœžœ˜+Kš žœžœžœžœžœžœ˜+š žœžœžœ>žœ žœž˜nKš žœžœžœžœžœ˜`Kšžœ˜—K˜K˜—šŸœž œC˜^Kšœ$™$K™LKšœ žœžœ žœ#˜Cš žœžœžœ&žœžœž˜ZKšœ/žœข˜_Kšžœ˜—šžœžœžœข˜2Kšœžœ˜+Kšœžœžœ˜'Kšžœžœžœžœ˜"Kšœ*˜*š žœžœžœ6žœžœž˜lKšžœžœžœ œF˜€Kšžœ˜—K˜—K˜K˜—šฅœž œ-žœ˜iKšœ&™&Kšœ˜Kšœžœ˜2Kšœ žœžœ˜Kšœžœžœ˜Kšœ žœžœ žœ#˜CKšœG˜Gš žœžœžœ%žœžœž˜WKšœ'œ"˜YKšžœžœžœ ž˜&šžœ˜KšœH˜HKšœ žœ˜K˜—šœ!˜!KšœD˜D—Jšžœ˜—Kšžœ žœžœ žœ˜9K˜—K™šœ ™ K˜—šŸ œž œ$žœn˜ซKšœžœ˜+Kšœžœ ˜.Kšœ‘™‘šžœžœžœ˜š žœžœžœ)žœžœž˜MKšœ!žœะbkœ˜GKšžœ˜—K˜—šžœ˜š žœžœžœ7žœžœž˜[Kšžœ žœžœVฆœ˜qKšžœ˜—K˜—Kšœ˜KšžœžœžœžœT˜Ššžœžœžœ˜$š Ÿœžœžœžœžœข˜VK™KKšœ/˜/Kš žœ žœžœžœžœข˜>Kšœ6ข˜TKšœข&˜CKšžœžœข˜!K˜—š Ÿ œžœžœžœžœข˜UK™Kšžœžœข-˜QKšœT˜TKšœ3˜3Kšœ;˜;Kšœ˜K˜—K˜—Kšœ˜Kšœžœžœ˜*K˜K˜KšœJ˜JKšžœžœ>˜TKšœ˜—K˜—K˜šœ™K˜—šŸœžœžœ ˜XKšœS™Sš žœžœžœ4žœžœž˜Xšžœ žœžœ˜Kš žœ žœžœžœžœข˜7Kšžœ˜K˜—Kšžœ˜—K˜K˜—š Ÿœžœžœ+žœžœ žœ˜cKšœ˜Kšœ˜Kšžœžœžœžœ ˜-Kšœ žœ˜!šžœ*žœžœ˜6Kšœ%˜%K˜—šžœ˜š žœžœžœ4žœžœž˜XJšžœ žœžœžœ<˜YJšžœ˜—Jšœ9˜9J˜—K˜K˜—š Ÿ œž œžœžœžœ žœ˜WKšœžœ ˜.Kšœ!žœ ˜1Kšœžœ˜K™?š žœ žœžœ-žœ žœž˜WKšœ˜šžœžœ˜$Kšœžœ˜Kšžœžœžœ$˜VKšžœžœ ˜5Kšžœžœžœ.˜RKšœ\˜\Kšžœ˜K˜—Kšœ˜Kšžœ˜—Kšžœ@˜FK˜K˜—šŸœž œžœžœ˜5Lšœžœ ˜.Lšœžœ˜š žœ žœžœ.žœ žœž˜\Lšœ˜Lšžœ˜—Lšœ-˜-š žœ žœžœ.žœ žœž˜\Lšœ-ข/˜\Lšžœ˜—Lšœ˜L˜—šŸœžœžœžœžœ žœ%žœ žœžœ ™zLšœ™Lšœžœ™Lšœ™Kšœžœ™L™Lšœžœžœ™Lšžœžœ$™>Lšžœ)™-Lšœ™Lšœ™Lšœ™šžœžœ™Lšœ.™.šžœžœžœ ž™šžœžœ™Kšœ#™#Kš œžœ žœžœžœžœ3™YKšžœžœžœIฆœ™aK™—šžœ™Kšœ™Kšœ™K™—Lšœ7™7šžœ žœžœ žœžœžœžœ'žœ™oKšœ•™•Kšœ žœข3™DKšžœ)ข#™RK™—šžœ žœžœ™Kšœ™KšœA™AK™—KšžœA™ELšžœ™—Lšžœ ™L™—LšžœW™[L™K™—šŸœžœžœžœžœ žœ%žœ žœžœ ˜zLšœžœ˜L˜Lšœžœžœ˜Lšžœžœ$˜>Lšžœ)˜-Lšœ˜Lšœ˜Lšœ˜šžœžœ˜Lšœ.˜.šžœžœžœ ž˜Lš œ?žœžœžœžœ ข<˜ฉ–[slice: GGModelTypes.Slice]šžœ žœžœ žœžœ%žœžœ'žœ˜‚Kšœ•™•Kšœ žœข3˜DKšžœ)ข#˜RK˜—šžœ žœžœ˜Kšœ˜KšœA˜AK˜—K–[atom: ATOM]šžœ>˜BLšžœ˜—Lšžœ ˜L˜—LšžœU˜YL˜K™—šŸœž œžœžœ˜Kšœ žœžœ˜Kšœ.˜.Kšœžœžœ˜K˜šžœžœ˜Kšœ-˜-Kšžœ˜K˜—šžœžœ˜"Kšœ&˜&Kšœ9˜9Kšžœ˜K˜K˜—Kš4™4Kšœ žœ˜!Kšœ žœ˜!Kšœžœ˜#Kšœ žœ˜!K˜KšœH˜HKšœH˜HKšœL˜LKšœH˜HK˜Kšœžœ ˜!Kšœ ˜ š žœžœžœ7žœžœž˜[šžœžœžœ˜Jš’™’JšœDžœ&˜mJšœ@žœ"˜ešžœžœ˜Jšœ.žœ ข˜QJšœi˜iJšœ@žœ"˜eJ˜—šžœ˜Jšœ.žœ ข˜QJšœi˜iJšœ@žœ"˜eJ˜—J˜—šžœ˜Jš™Jšœ‚ข˜ šžœžœžœ˜ Jšœ@žœ"˜eJšœi˜iJšœs˜sJšœi˜iJ˜—šžœ˜Jšœi˜iJšœ@žœ"˜eJšœs˜sJšœi˜iJ˜—J˜—J˜Jšžœ˜—Jšœ;˜;Jšœ8˜8Jšœ9˜9Jšœ5˜5J˜J˜—šŸ œž œ8žœ˜tK™ฌKšœžœžœ˜Kšœžœ˜2Kšœ˜Kšžœžœžœžœ ˜*Kšœ žœ˜ KšœC˜Cš žœ žœžœ<žœ žœž˜hKšœ,˜,Kš œ;žœ žœžœ  œžœžœ˜คKšžœ˜—Kšœ;˜;K˜K˜—š Ÿ œžœžœ#žœžœ ˜gKšœžœ˜2Kšœžœ˜5Kšœžœ˜.KšœY˜YKšœ˜šž˜šžœž˜˜Kšžœžœžœžœ˜-šžœ$žœ˜,Kšœžœžœ˜(KšœขœA˜`šžœž˜šœ žœ žœžœž˜%Kšžœ;˜?——šž˜šœ žœ žœžœž˜&Kšžœ=˜A——K˜—Kšžœžœ ˜K˜—˜ Kšžœžœžœžœ˜-šžœ$ž˜*Kšœ-žœ˜8—Kšžœžœ ˜K˜—˜šžœž˜ KšœU˜U—Kšžœžœ ˜K˜—˜šžœž˜ KšœV˜V—Kšžœžœ ˜K˜—Kšžœžœ˜—šž˜˜ KšœG˜Gšœ žœžœžœž˜*KšžœE˜I—K˜——Kšžœ˜—K˜K˜—šŸœžœžœ˜AKšœžœ ˜.Kšœ#˜#K˜K˜—šŸœžœžœ˜@Kšœžœ ˜.š žœžœžœ)žœžœž˜MJšœ˜Jšžœ˜—K˜K˜—šŸœž œ%žœ"˜iKšœN™NK™Kšœžœ˜2Kšžœžœžœžœ˜"š žœ žœžœ<žœ žœž˜hKšœ,˜,Kšžœ žœžœ œ"˜SKšžœ˜—K˜—K˜™ K™—Kšœžœžœ˜5šœžœžœ˜&Kšœžœžœ˜ Kšœข7˜PKšœ˜K˜—Kšœžœžœ˜=šœžœžœ˜*Kšœžœžœ˜ Kšœข2˜OKšœ˜K˜—Kšœžœžœ˜9šœžœžœ˜(Kšœžœžœ˜ Kšœข7˜PKšœ˜—K˜šฅœž œžœ˜`Kšœžœ˜2Kšœ žœžœ˜%Kšœ˜Kšœ!˜!Kš œžœžœžœžœžœ˜KKšœžœžœžœžœžœžœžœ2˜Kšœžœ7˜IKšœ žœ3˜AK˜K˜—šŸœž œ7˜ZKšœžœ˜2Kšœ žœžœ˜%Kšžœžœžœžœ˜"Kšœ'˜'š žœžœžœ>žœžœž˜pKšžœžœžœ œ˜_KšœGžœ™iKšžœ˜—K˜K˜—šฅœž œžœ4˜yKšœžœ˜2Kšœ žœžœ˜%Kšœ&˜&Kšœ)˜)Kš œžœžœžœžœžœ˜KKšœžœžœžœžœžœžœžœ6˜‡Kšœžœ?˜UKšœžœ;˜MK˜K˜—šฅœž œžœ˜bKšœžœ˜2Kšœ žœžœžœžœžœžœžœ˜d–[seq: GGModelTypes.Sequence]šžœ žœžœ˜šœ#žœ˜BKšœขQ˜fKšœžœžœžœžœžœ œข˜{Kšœ˜—šœ žœ˜$Kšœ ข˜Kšœ˜Kšœ žœ˜Kšœ˜Kšœ˜—K˜—K˜K˜—šŸ œž œ*žœC˜ŒKšœ#žœ˜@Kšœ žœžœ%˜9Kšžœžœžœข˜0šžœžœž˜ šžœžœžœข$˜FK–)[segGen: GGModelTypes.SegmentGenerator]šœ œ-˜Všžœžœžœ˜Kšœ ˜ Kšžœ˜K˜—Kšœ ข˜7K˜—K™Kš žœžœžœžœžœ žœ˜]K™Kš žœžœžœžœžœžœ˜+K–[seq: GGModelTypes.Sequence]šœœข˜`Kšžœ˜—K˜K˜—šŸ œž œ$žœ˜bKšœํžœ™๒Kšœžœžœ˜Kšœžœ ˜.Kšœžœ˜.KšœC˜Cš žœ žœžœ-žœ žœž˜WKšœ˜Kšœ% œ˜CKšœ^˜^Kšžœ˜—Kšœ6˜6K˜K˜—šฅ œž œ*žœ.˜uKšœžœ˜9Kšœ žœžœ˜2Kš žœžœžœžœ žœ˜0šžœžœž˜ šžœžœžœข&˜HKšœ œ(˜Kšžœžœžœ˜Kšœ˜Kšžœ˜K˜—Kšœ ข˜7K˜—K™Kš žœžœžœžœžœ žœ˜]Kš žœžœžœžœ žœ˜0Kšœœข˜[Kšžœ˜—K˜K˜—šฅ œž œ2žœ)˜|Kšœžœ˜AKšœ žœžœ˜2Kš žœžœžœžœžœ˜7šžœžœž˜ šžœžœžœข%˜GKšœ œ(˜Sšžœžœžœ˜#Kšœ˜Kšžœ˜K˜—Kšœ ข˜7K˜—K™Kš žœžœžœžœžœ žœ˜]Kš žœžœžœžœžœ˜7Kšœœ˜DKšžœ˜—K˜—K˜Kšœ žœ%˜6Kšœข˜4K˜Kšžœ˜J˜—…—๑ฬR