<> <> <> <> <> <<>> DIRECTORY Atom, GGDescribe, GGInterfaceTypes, GGModelTypes, GGSegmentTypes, GGTouch, GGTraj, IO, Rope; GGDescribeImpl: CEDAR PROGRAM IMPORTS Atom, GGTouch, GGTraj, IO, Rope EXPORTS GGDescribe = BEGIN AlignmentPoint: TYPE = GGInterfaceTypes.AlignmentPoint; EntityGenerator: TYPE = GGModelTypes.EntityGenerator; FeatureData: TYPE = GGInterfaceTypes.FeatureData; GargoyleData: TYPE = GGInterfaceTypes.GargoyleData; Outline: TYPE = GGModelTypes.Outline; OutlineDescriptor: TYPE = GGModelTypes.OutlineDescriptor; Segment: TYPE = GGSegmentTypes.Segment; Sequence: TYPE = GGModelTypes.Sequence; SequenceGenerator: TYPE = GGModelTypes.SequenceGenerator; Slice: TYPE = GGModelTypes.Slice; SliceDescriptor: TYPE = GGModelTypes.SliceDescriptor; SliceParts: TYPE = GGModelTypes.SliceParts; TouchGroup: TYPE = GGSegmentTypes.TouchGroup; TouchItem: TYPE = GGSegmentTypes.TouchItem; TouchItemGenerator: TYPE = GGTouch.TouchItemGenerator; Traj: TYPE = GGModelTypes.Traj; TrajGenerator: TYPE = GGModelTypes.TrajGenerator; NotYetImplemented: PUBLIC SIGNAL = CODE; terseSlice: BOOL _ FALSE; DescribeFeature: PUBLIC PROC [feature: FeatureData, gargoyleData: GargoyleData] RETURNS [rope: Rope.ROPE] = { IF feature = NIL THEN RETURN["nothing"] ELSE { SELECT feature.resultType FROM outline => { outline: Outline _ NARROW[feature.shape, OutlineDescriptor].slice; tParts: SliceParts _ outline.class.newParts[outline, feature.hitPart, gargoyleData.drag.selectState]; rope _ outline.class.describe[outline, tParts]; }; slice => IF terseSlice THEN rope _ Rope.Concat[Atom.GetPName[NARROW[feature.shape, SliceDescriptor].slice.class.type], " slice"] ELSE { -- do this because feature doesn't carry hitParts for slices, so we ask the slice to tell us its hitParts and then describe itself using those parts tSlice: Slice _ NARROW[feature.shape, SliceDescriptor].slice; tParts: SliceParts _ tSlice.class.newParts[tSlice, feature.hitPart, gargoyleData.drag.selectState]; rope _ tSlice.class.describe[tSlice, tParts]; }; distanceLine => rope _ "distance line"; slopeLine => rope _ "slope line"; angleLine => rope _ "angle line"; symmetryLine => rope _ "symmetry line"; radiiCircle => rope _ "compass circle"; intersectionPoint => { firstObj, secondObj: Rope.ROPE; alignPoint: AlignmentPoint _ NARROW[feature.shape]; line1: FeatureData _ alignPoint.curve1; line2: FeatureData _ alignPoint.curve2; tangent: BOOL _ alignPoint.tangent; IF line1 = NIL AND line2 = NIL THEN { rope _ IO.PutFR["the anchor"]; } ELSE { firstObj _ IF line1 # NIL THEN DescribeSourceFeature[line1, gargoyleData] ELSE "unknown"; secondObj _ IF line2 # NIL THEN DescribeSourceFeature[line2, gargoyleData] ELSE "unknown"; IF tangent THEN rope _ IO.PutFR["a %g/%g tangency point", [rope[firstObj]], [rope[secondObj]] ] ELSE rope _ IO.PutFR["a %g/%g intersection point", [rope[firstObj]], [rope[secondObj]] ]; }; }; midpoint => { seqPart: GGInterfaceTypes.SequencePart _ NARROW[feature.hitPart]; segNum: NAT _ seqPart.segNum; rope _ IO.PutFR["midpoint of segment %g", [integer[segNum]]]; }; anchor => { rope _ IO.PutFR["anchor"]; }; ENDCASE => ERROR; }; }; DescribeSourceFeature: PUBLIC PROC [feature: FeatureData, gargoyleData: GargoyleData] RETURNS [rope: Rope.ROPE] = { IF feature = NIL THEN RETURN["nothing"] ELSE { SELECT feature.type FROM outline => rope _ "outline"; slice => rope _ Rope.Concat[Atom.GetPName[NARROW[feature.shape, SliceDescriptor].slice.class.type], " slice"]; distanceLine => rope _ "distance line"; slopeLine => rope _ "slope line"; angleLine => rope _ "angle line"; symmetryLine => rope _ "symmetry line"; radiiCircle => rope _ "compass circle"; intersectionPoint => { firstObj, secondObj: Rope.ROPE; firstObj _ IF NARROW[feature.shape, AlignmentPoint].curve1 # NIL THEN DescribeSourceFeature[NARROW[feature.shape, AlignmentPoint].curve1, gargoyleData] ELSE "unknown"; secondObj _ IF NARROW[feature.shape, AlignmentPoint].curve2 # NIL THEN DescribeSourceFeature[NARROW[feature.shape, AlignmentPoint].curve2, gargoyleData] ELSE "unknown"; rope _ IO.PutFR["a %g/%g intersection point", [rope[firstObj]], [rope[secondObj]] ]; }; midpoint => rope _ IO.PutFR["midpoint of segment ???"]; ENDCASE => ERROR; }; }; DescribeTraj: PUBLIC PROC [traj: Traj] RETURNS [text: Rope.ROPE] = { text _ SELECT traj.role FROM open => IO.PutFR["a %g-segment open trajectory", [integer[traj.segCount]]], fence => IO.PutFR["a %g-segment fence", [integer[traj.segCount]]], hole => IO.PutFR["a %g-segment hole", [integer[traj.segCount]]], ENDCASE => ""; }; DescribeJoint: PUBLIC PROC [traj: Traj, jointNum: NAT] RETURNS [text: Rope.ROPE] = { end: BOOL; end _ GGTraj.IsEndJoint[traj, jointNum]; IF end THEN text _ IO.PutFR["end joint %g on ", [integer[jointNum]] ] ELSE text _ IO.PutFR["joint %g on ", [integer[jointNum]] ]; text _ Rope.Concat[text, DescribeSegment[traj, IF GGTraj.HiJoint[traj]=jointNum AND traj.role=open THEN jointNum-1 ELSE jointNum]]; <> }; DescribeControlPoint: PUBLIC PROC [traj: Traj, segNum: NAT, cpNum: NAT] RETURNS [text: Rope.ROPE] = { text _ Rope.Cat[IO.PutFR["control point %g on ", [integer[cpNum]]], DescribeSegment[traj, segNum] ]; }; DescribeSegment: PUBLIC PROC [traj: Traj, segNum: NAT] RETURNS [text: Rope.ROPE] = { IF segNum=LAST[NAT] THEN text _ Rope.Cat["a segment on ", DescribeTraj[traj]] ELSE { seg: Segment _ GGTraj.FetchSegment[traj, segNum]; text _ Rope.Cat[seg.class.describe[seg, TRUE, TRUE, TRUE, NIL], IO.PutFR[" segment %g on ", [integer[segNum]]], DescribeTraj[traj]]; <> }; }; DescribeSequence: PUBLIC PROC [seq: Sequence] RETURNS [text: Rope.ROPE] = { text _ Rope.Cat[IO.PutFR["One or more parts of "], DescribeTraj[seq.traj]]; }; DescribeItem: PROC [f: IO.STREAM, item: TouchItem] = { SELECT item.touchingPartType FROM joint => f.PutF["Item: joint on %g", [rope[DescribeTraj[NARROW[item.traj]]]]]; segment => f.PutF["Item: segment on %g", [rope[DescribeTraj[NARROW[item.traj]]]]]; ENDCASE => ERROR; }; DescribeTouchGroup: PUBLIC PROC [group: TouchGroup] RETURNS [text: Rope.ROPE] = { f: IO.STREAM; touchGen: TouchItemGenerator; f _ IO.ROS[]; f.PutF["TouchGroup: (%1.2f, %1.2f)\n", [real[group.point.x]], [real[group.point.y]]]; touchGen _ GGTouch.AllTouchItems[group]; FOR item: TouchItem _ GGTouch.NextTouchItem[touchGen], GGTouch.NextTouchItem[touchGen] UNTIL item = NIL DO f.PutChar[IO.TAB]; DescribeItem[f, item]; f.PutChar[IO.CR]; ENDLOOP; text _ IO.RopeFromROS[f]; }; END.