<> <> <> <> <<>> DIRECTORY GGBasicTypes, GGError, GGInterfaceTypes, GGModelTypes, GGOutline, GGObjects, GGSelect, GGSegmentTypes, GGSequence, GGTraj, GGUtility, GGVector, GList, Imager, Rope; GGOutlineImplB: CEDAR PROGRAM IMPORTS GGError, GGObjects, GGOutline, GGSelect, GGSequence, GGTraj, GGUtility, GGVector, GList, Imager EXPORTS GGOutline = BEGIN OPEN GGOutline; BitVector: TYPE = GGBasicTypes.BitVector; BoundBox: TYPE = GGBasicTypes.BoundBox; CameraData: TYPE = GGModelTypes.CameraData; Circle: TYPE = GGBasicTypes.Circle; Color: TYPE = Imager.Color; ControlPointGenerator: TYPE = GGModelTypes.ControlPointGenerator; FeatureData: TYPE = GGInterfaceTypes.FeatureData; GargoyleData: TYPE = GGInterfaceTypes.GargoyleData; Joint: TYPE = GGSegmentTypes.Joint; JointGenerator: TYPE = GGModelTypes.JointGenerator; Line: TYPE = GGBasicTypes.Line; ObjectBag: TYPE = GGInterfaceTypes.ObjectBag; Outline: TYPE = REF OutlineObj; OutlineObj: TYPE = GGModelTypes.OutlineObj; OutlineClass: TYPE = REF OutlineClassObj; OutlineClassObj: TYPE = GGModelTypes.OutlineClassObj; OutlineDescriptor: TYPE = GGModelTypes.OutlineDescriptor; OutlineParts: TYPE = REF OutlinePartsObj; OutlinePartsObj: TYPE = GGOutline.OutlinePartsObj; OutlineSequence: TYPE = GGSelect.OutlineSequence; OutlineSequenceGenerator: TYPE = GGSelect.OutlineSequenceGenerator; Point: TYPE = GGBasicTypes.Point; PointGenerator: TYPE = GGModelTypes.PointGenerator; PointPairGenerator: TYPE = GGModelTypes.PointPairGenerator; Scene: TYPE = GGModelTypes.Scene; Segment: TYPE = GGSegmentTypes.Segment; SegmentGenerator: TYPE = GGModelTypes.SegmentGenerator; SelectMode: TYPE = GGModelTypes.SelectMode; SelectionClass: TYPE = GGSegmentTypes.SelectionClass; Sequence: TYPE = GGModelTypes.Sequence; SliceClass: TYPE = REF SliceClassObj; SliceClassObj: TYPE = GGModelTypes.SliceClassObj; SliceDescriptor: TYPE = GGModelTypes.SliceDescriptor; SliceParts: TYPE = GGModelTypes.SliceParts; Traj: TYPE = REF TrajObj; TrajEnd: TYPE = GGModelTypes.TrajEnd; TrajGenerator: TYPE = REF TrajGeneratorObj; TrajGeneratorObj: TYPE = GGModelTypes.TrajGeneratorObj; TrajObj: TYPE = GGModelTypes.TrajObj; TrajPartType: TYPE = GGModelTypes.TrajPartType; TriggerBag: TYPE = GGInterfaceTypes.TriggerBag; Vector: TYPE = GGBasicTypes.Vector; OutlineDescribeProc: TYPE = GGModelTypes.OutlineDescribeProc; OutlineFileoutProc: TYPE = GGModelTypes.OutlineFileoutProc; OutlineFileinProc: TYPE = GGModelTypes.OutlineFileinProc; OutlineUnionPartsProc: TYPE = GGModelTypes.OutlineUnionPartsProc; OutlineDifferencePartsProc: TYPE = GGModelTypes.OutlineDifferencePartsProc; OutlineFixedPartsProc: TYPE = GGModelTypes.OutlineFixedPartsProc; OutlineAugmentPartsProc: TYPE = GGModelTypes.OutlineAugmentPartsProc; OutlinePointsInDescriptorProc: TYPE = GGModelTypes.OutlinePointsInDescriptorProc; OutlinePointPairsInDescriptorProc: TYPE = GGModelTypes.OutlinePointPairsInDescriptorProc; OutlineNextPointProc: TYPE = GGModelTypes.OutlineNextPointProc; OutlineNextPointPairProc: TYPE = GGModelTypes.OutlineNextPointPairProc; OutlineClosestPointProc: TYPE = GGModelTypes.OutlineClosestPointProc; OutlineClosestPointAndTangentProc: TYPE = GGModelTypes.OutlineClosestPointAndTangentProc; OutlineClosestSegmentProc: TYPE = GGModelTypes.OutlineClosestSegmentProc; OutlineSetArrowsProc: TYPE = GGModelTypes.OutlineSetArrowsProc; OutlineGetArrowsProc: TYPE = GGModelTypes.OutlineGetArrowsProc; Problem: PUBLIC SIGNAL [msg: Rope.ROPE] = GGError.Problem; <> <<>> UnpackOnePointDescriptorOld: PUBLIC PROC [outlineD: OutlineDescriptor] RETURNS [traj: Traj, isACP: BOOL, segNum, cpNum, jointNum: NAT] = { <> parts: OutlineParts; theSeq: Sequence; IF outlineD = NIL THEN RETURN[NIL, FALSE, 999, 999, 999]; parts _ NARROW[outlineD.parts]; traj _ NIL; FOR list: LIST OF Sequence _ parts.seqs, list.rest UNTIL list = NIL DO IF list.first # NIL THEN { IF traj # NIL THEN RETURN[NIL, FALSE, 999, 999, 999] ELSE { theSeq _ list.first; traj _ theSeq.traj; [isACP, segNum, cpNum, jointNum] _ GGSequence.UnpackOnePointSequence[theSeq]; }; }; ENDLOOP; }; UnpackSimpleDescriptorOld: PUBLIC PROC [outlineD: OutlineDescriptor] RETURNS [success: BOOL, partType: TrajPartType, traj: Traj, joint: Joint _ NIL, jointNum: NAT _ 999, cp: Point, cpNum: NAT _ 999, seg: Segment _ NIL, segNum: NAT _ 999] = { parts: OutlineParts; theSeq: Sequence; IF outlineD = NIL THEN RETURN[FALSE, joint, NIL, NIL, 999, [0,0]]; parts _ NARROW[outlineD.parts]; traj _ NIL; FOR list: LIST OF Sequence _ parts.seqs, list.rest UNTIL list = NIL DO IF list.first # NIL THEN { IF traj # NIL THEN RETURN[FALSE, joint, NIL, NIL, 999, [0,0]] ELSE { theSeq _ list.first; traj _ theSeq.traj; [success, partType, traj, joint, jointNum, cp, cpNum, seg, segNum] _ GGSequence.UnpackSimpleSequence[theSeq]; }; }; ENDLOOP; }; UnpackSimpleDescriptor: PUBLIC PROC [sliceD: SliceDescriptor] RETURNS [success: BOOL, partType: TrajPartType, traj: Traj, joint: Joint _ NIL, jointNum: NAT _ 999, cp: Point, cpNum: NAT _ 999, seg: Segment _ NIL, segNum: NAT _ 999] = { ERROR Problem[msg: "Outlines are not slices yet"]; }; UnpackOnePointDescriptor: PUBLIC PROC [sliceD: SliceDescriptor] RETURNS [traj: Traj, isACP: BOOL, segNum, cpNum, jointNum: NAT] = { ERROR Problem[msg: "Outlines are not slices yet"]; }; UnpackOneSegmentDescriptorOld: PUBLIC PROC [outlineD: OutlineDescriptor] RETURNS [traj: Traj, segNum: NAT] = { <> parts: OutlineParts; theSeq: Sequence; IF outlineD = NIL THEN RETURN[NIL, 999]; parts _ NARROW[outlineD.parts]; traj _ NIL; FOR list: LIST OF Sequence _ parts.seqs, list.rest UNTIL list = NIL DO IF list.first # NIL THEN { IF traj # NIL THEN RETURN[NIL, 999] ELSE { theSeq _ list.first; traj _ theSeq.traj; [segNum] _ GGSequence.UnpackOneSegmentSequence[theSeq]; }; }; ENDLOOP; }; UnpackOneSegmentDescriptor: PUBLIC PROC [sliceD: SliceDescriptor] RETURNS [traj: Traj, segNum: NAT] = { ERROR Problem[msg: "Outlines are not slices yet"]; }; FindTrajInDescriptor: PUBLIC PROC [outlineD: OutlineDescriptor, traj: Traj] RETURNS [seq: Sequence] = { outlineParts: OutlineParts; outlineParts _ NARROW[outlineD.parts]; FOR list: LIST OF Sequence _ outlineParts.seqs, list.rest UNTIL list = NIL DO IF list.first # NIL AND list.first.traj = traj THEN RETURN[list.first]; ENDLOOP; RETURN[NIL]; }; PartsFromSequence: PUBLIC PROC [outline: Outline, seq: Sequence] RETURNS [sliceParts: SliceParts] = { realParts: OutlineParts; ptr: LIST OF Sequence; trajGen: GGModelTypes.TrajGenerator; sliceParts _ realParts _ NEW[OutlinePartsObj]; [realParts.seqs, ptr] _ GGUtility.StartSequenceList[]; trajGen _ TrajsInOutline[outline]; FOR traj: Traj _ GGObjects.NextTraj[trajGen], GGObjects.NextTraj[trajGen] UNTIL traj = NIL DO IF traj = seq.traj THEN [realParts.seqs, ptr] _ GGUtility.AddSequence[seq, realParts.seqs, ptr] ELSE [realParts.seqs, ptr] _ GGUtility.AddSequence[NIL, realParts.seqs, ptr]; ENDLOOP; }; CopyParts: PUBLIC PROC [outline: Outline, parts: SliceParts] RETURNS [copy: SliceParts] = { realParts, realCopyParts: OutlineParts; copySeq: Sequence; ptr: LIST OF Sequence; realParts _ NARROW[parts]; copy _ realCopyParts _ NEW[OutlinePartsObj]; [realCopyParts.seqs, ptr] _ GGUtility.StartSequenceList[]; FOR list: LIST OF Sequence _ realParts.seqs, list.rest UNTIL list = NIL DO IF list.first = NIL THEN [realCopyParts.seqs, ptr] _ GGUtility.AddSequence[NIL, realCopyParts.seqs, ptr] ELSE { copySeq _ GGSequence.Copy[list.first]; [realCopyParts.seqs, ptr] _ GGUtility.AddSequence[copySeq, realCopyParts.seqs, ptr] }; ENDLOOP; }; AddHole: PUBLIC PROC [outline: Outline, hole: Traj] RETURNS [holier: Outline] = { <> <> holier _ outline.class.copy[outline]; holier.children _ AppendTrajList[holier.children, LIST[hole]]; hole.parent _ holier; hole.role _ hole; UpdateOutlineBoundBox[holier]; }; ReplaceFence: PUBLIC PROC [outline: Outline, newFence: Traj] RETURNS [newOutline: Outline] = { <> holeGen: TrajGenerator; newTraj: Traj; newOutline _ CreateOutline[newFence, outline.lineEnds, outline.fillColor]; holeGen _ HolesOfOutline[outline]; FOR hole: Traj _ GGObjects.NextTraj[holeGen], GGObjects.NextTraj[holeGen] UNTIL hole = NIL DO newTraj _ GGTraj.CopyTraj[hole]; newOutline.children _ AppendTrajList[newOutline.children, LIST[newTraj]]; newTraj.parent _ newOutline; ENDLOOP; UpdateOutlineBoundBox[newOutline]; }; ReplaceHole: PUBLIC PROC [outline: Outline, oldHole, newHole: Traj] RETURNS [newOutline: Outline] = { <> holeGen: TrajGenerator; newTraj, fence: Traj; fence _ FenceOfOutline[outline]; newTraj _ GGTraj.CopyTraj[fence]; newOutline _ CreateOutline[newTraj, outline.lineEnds, outline.fillColor]; holeGen _ HolesOfOutline[outline]; FOR hole: Traj _ GGObjects.NextTraj[holeGen], GGObjects.NextTraj[holeGen] UNTIL hole = NIL DO IF hole = oldHole THEN { newOutline.children _ AppendTrajList[newOutline.children, LIST[newHole]]; newHole.parent _ newOutline; } ELSE { newTraj _ GGTraj.CopyTraj[hole]; newOutline.children _ AppendTrajList[newOutline.children, LIST[newTraj]]; newTraj.parent _ newOutline; }; ENDLOOP; UpdateOutlineBoundBox[newOutline]; }; OutlineOfTraj: PUBLIC PROC [traj: Traj] RETURNS [outline: Outline] = { <> outline _ traj.parent; }; SaveSelectionsInOutline: PUBLIC PROC [outline: Outline, scene: Scene] = { outlineD: OutlineDescriptor; outlineParts: OutlineParts; <> outlineD _ GGSelect.FindSelectedOutline[outline, scene, hot]; ClearSelectionInOutline[outline, hot]; IF outlineD # NIL THEN { outlineParts _ NARROW[outlineD.parts]; FOR seqList: LIST OF Sequence _ outlineParts.seqs, seqList.rest UNTIL seqList = NIL DO IF seqList.first#NIL THEN SaveSelectionInSequence[seqList.first, hot]; ENDLOOP; }; <> outlineD _ GGSelect.FindSelectedOutline[outline, scene, normal]; ClearSelectionInOutline[outline, normal]; IF outlineD # NIL THEN { outlineParts _ NARROW[outlineD.parts]; FOR seqList: LIST OF Sequence _ outlineParts.seqs, seqList.rest UNTIL seqList = NIL DO IF seqList.first#NIL THEN SaveSelectionInSequence[seqList.first, normal]; ENDLOOP; }; <> outlineD _ GGSelect.FindSelectedOutline[outline, scene, active]; ClearSelectionInOutline[outline, active]; IF outlineD # NIL THEN { outlineParts _ NARROW[outlineD.parts]; FOR seqList: LIST OF Sequence _ outlineParts.seqs, seqList.rest UNTIL seqList = NIL DO IF seqList.first#NIL THEN SaveSelectionInSequence[seqList.first, active]; ENDLOOP; }; }; SaveSelectionInTraj: PUBLIC PROC [traj: Traj, selectClass: SelectionClass, scene: Scene] = { seq: Sequence _ GGSelect.FindSelectedSequence[traj, scene, selectClass]; IF seq=NIL THEN ClearSelectionInTraj[traj, selectClass] ELSE SaveSelectionInSequence[seq, selectClass]; }; ClearSelectionInTraj: PROC [traj: Traj, selectClass: SelectionClass] = { seg: Segment; joint: Joint; FOR i: NAT IN [0..GGTraj.HiSegment[traj]] DO seg _ GGTraj.FetchSegment[traj, i]; SetSegmentField[seg, FALSE, selectClass]; FOR j: NAT IN [0..seg.class.controlPointCount[seg]-1] DO SetControlPointField[seg, j, FALSE, selectClass]; ENDLOOP; ENDLOOP; FOR i: NAT IN [0..GGTraj.HiJoint[traj]] DO joint _ GGTraj.FetchJoint[traj, i]; SetJointField[joint, FALSE, selectClass]; ENDLOOP; }; RemakeSelectionFromTraj: PUBLIC PROC [traj: Traj, scene: Scene, selectClass: SelectionClass] = { seq: Sequence _ GGSequence.CreateEmpty[traj]; seg: Segment; joint: Joint; FOR i: NAT IN [0..GGTraj.HiSegment[traj]] DO seg _ GGTraj.FetchSegment[traj, i]; seq.segments[i] _ GetSegmentField[seg, selectClass]; IF seq.segments[i] THEN seq.segCount _ seq.segCount + 1; FOR j: NAT IN [0..seg.class.controlPointCount[seg]-1] DO seq.controlPoints[i][j] _ GetControlPointField[seg, j, selectClass]; IF seq.controlPoints[i][j] THEN seq.controlPointCount _ seq.controlPointCount + 1; ENDLOOP; ENDLOOP; FOR i: NAT IN [0..GGTraj.HiJoint[traj]] DO joint _ GGTraj.FetchJoint[traj, i]; seq.joints[i] _ GetJointField[joint, selectClass]; IF seq.joints[i] THEN seq.jointCount _ seq.jointCount + 1; ENDLOOP; GGSelect.SelectSequence[seq, scene, selectClass]; }; SaveSelectionInSequence: PROC [seq: Sequence, selectClass: SelectionClass] = { seg: Segment; joint: Joint; FOR i: NAT IN [0..GGTraj.HiSegment[seq.traj]] DO seg _ GGTraj.FetchSegment[seq.traj, i]; SetSegmentField[seg, seq.segments[i], selectClass]; FOR j: NAT IN [0..seg.class.controlPointCount[seg]-1] DO SetControlPointField[seg, j, seq.controlPoints[i][j], selectClass]; ENDLOOP; ENDLOOP; FOR i: NAT IN [0..GGTraj.HiJoint[seq.traj]] DO joint _ GGTraj.FetchJoint[seq.traj, i]; SetJointField[joint, seq.joints[i], selectClass]; ENDLOOP; }; ClearSelectionInOutline: PROC [outline: Outline, selectClass: SelectionClass] = { trajGen: GGModelTypes.TrajGenerator; trajGen _ TrajsInOutline[outline]; FOR traj: Traj _ GGObjects.NextTraj[trajGen], GGObjects.NextTraj[trajGen] UNTIL traj = NIL DO ClearSelectionInTraj[traj, selectClass]; ENDLOOP; }; RemakeSelectionsFromOutline: PUBLIC PROC [outline: Outline, scene: Scene] = { <> trajGen: GGModelTypes.TrajGenerator; trajGen _ TrajsInOutline[outline]; FOR traj: Traj _ GGObjects.NextTraj[trajGen], GGObjects.NextTraj[trajGen] UNTIL traj = NIL DO <> RemakeSelectionFromTraj[traj, scene, hot]; <> RemakeSelectionFromTraj[traj, scene, normal]; <> RemakeSelectionFromTraj[traj, scene, active]; ENDLOOP; }; SequencesOfOutline: PUBLIC PROC [outlineD: OutlineDescriptor] RETURNS [seqList: LIST OF Sequence] = { outlineParts: OutlineParts _ NARROW[outlineD.parts]; ptr: LIST OF Sequence; [seqList, ptr] _ GGUtility.StartSequenceList[]; FOR list: LIST OF Sequence _ outlineParts.seqs, list.rest UNTIL list = NIL DO IF list.first # NIL THEN [seqList, ptr] _ GGUtility.AddSequence[list.first, seqList, ptr]; ENDLOOP; }; RemoveTraj: PUBLIC PROC [outlineD: OutlineDescriptor, traj: Traj] = { <> outlineParts: OutlineParts _ NARROW[outlineD.parts]; seq: Sequence; FOR list: LIST OF Sequence _ outlineParts.seqs, list.rest UNTIL list = NIL DO IF list.first#NIL AND list.first.traj = traj THEN { seq _ list.first; GOTO Done; }; REPEAT Done => { outlineParts.seqs _ NARROW[GList.DSubst[NIL, seq, outlineParts.seqs]]; <> }; FINISHED => NULL; ENDLOOP; }; <<>> NearestJointToHitData: PUBLIC PROC [hitData: REF ANY] RETURNS [jointNum: NAT, traj: Traj] = { outlineHitData: OutlineHitData _ NARROW[hitData]; nextNum: NAT; p1, p2: Point; d1, d2: REAL; traj _ outlineHitData.traj; SELECT outlineHitData.hitType FROM joint => { jointNum _ outlineHitData.jointNum; }; segment, controlPoint => { nextNum _ GGTraj.FollowingJoint[traj, outlineHitData.segNum]; p1 _ GGTraj.FetchJointPos[traj, outlineHitData.segNum]; p2 _ GGTraj.FetchJointPos[traj, nextNum]; d1 _ GGVector.DistanceSquared[p1, outlineHitData.hitPoint]; d2 _ GGVector.DistanceSquared[p2, outlineHitData.hitPoint]; IF d1 <= d2 THEN jointNum _ outlineHitData.segNum ELSE jointNum _ nextNum; }; ENDCASE => ERROR; }; UnpackHitData: PUBLIC PROC [hitData: REF ANY] RETURNS [traj: Traj, hitType: TrajPartType, segNum, cpNum, jointNum: INT, hitPoint: Point] = { <> outlineHitData: OutlineHitData _ NARROW[hitData]; traj _ outlineHitData.traj; hitType _ outlineHitData.hitType; segNum _ outlineHitData.segNum; cpNum _ outlineHitData.cpNum; jointNum _ outlineHitData.jointNum; hitPoint _ outlineHitData.hitPoint; }; UpdateDescriptorBoundBoxes: PUBLIC PROC [outlineD: OutlineDescriptor] = { <> parts: OutlineParts _ NARROW[outlineD.parts]; FOR list: LIST OF Sequence _ parts.seqs, list.rest UNTIL list = NIL DO IF list.first # NIL THEN GGSequence.UpdateBoundBox[list.first]; ENDLOOP; }; <<>> <> HasHoles: PUBLIC PROC [outline: Outline] RETURNS [BOOL] = { RETURN[outline.children.rest # NIL]; }; FenceOfOutline: PUBLIC PROC [outline: Outline] RETURNS [fence: Traj] = { <> fence _ outline.children.first; }; HolesOfOutline: PUBLIC PROC [outline: Outline] RETURNS [trajGen: TrajGenerator] = { <> list: LIST OF Traj _ outline.children.rest; trajGen _ NEW[TrajGeneratorObj _ [ list: list ]]; }; TrajsInOutline: PUBLIC PROC [outline: Outline] RETURNS [trajGen: TrajGenerator] = { <> list: LIST OF Traj _ outline.children; trajGen _ NEW[TrajGeneratorObj _ [ list: list ]]; }; END.