<> <> <> <> <> <<>> DIRECTORY BiScrollers, GGBasicTypes, AtomButtons, GGCaret, GGCircles, GGCircleCache, GGLines, GGGravity, GGMultiGravity, GGModelTypes, GGInterfaceTypes, GGShapes, GGSegmentTypes, GGSequence, GGStatistics, GGTraj, GGVector, Imager, ImagerBackdoor, ImagerTransformation, Process, Real, RealFns, Rope; GGGravityImpl: CEDAR PROGRAM IMPORTS BiScrollers, AtomButtons, GGCaret, GGCircles, GGCircleCache, GGLines, GGMultiGravity, GGSequence, GGShapes, GGStatistics, GGTraj, GGVector, Imager, ImagerBackdoor, Process, RealFns EXPORTS GGGravity = BEGIN AlignmentCircle: TYPE = REF AlignmentCircleObj; AlignmentCircleObj: TYPE = GGInterfaceTypes.AlignmentCircleObj; AlignmentLine: TYPE = REF AlignmentLineObj; AlignmentLineObj: TYPE = GGInterfaceTypes.AlignmentLineObj; AlignmentPoint: TYPE = REF AlignmentPointObj; AlignmentPointObj: TYPE = GGInterfaceTypes.AlignmentPointObj; Angle: TYPE = GGBasicTypes.Angle; BoundBox: TYPE = GGModelTypes.BoundBox; Caret: TYPE = GGInterfaceTypes.Caret; Circle: TYPE = GGBasicTypes.Circle; Edge: TYPE = GGBasicTypes.Edge; FeatureData: TYPE = REF FeatureDataObj; FeatureDataObj: TYPE = GGModelTypes.FeatureDataObj; GargoyleData: TYPE = GGInterfaceTypes.GargoyleData; JointGenerator: TYPE = GGModelTypes.JointGenerator; Line: TYPE = GGBasicTypes.Line; ObjectBag: TYPE = REF ObjectBagObj; ObjectBagObj: TYPE = GGInterfaceTypes.ObjectBagObj; Outline: TYPE = GGModelTypes.Outline; OutlineDescriptor: TYPE = REF OutlineDescriptorObj; OutlineDescriptorObj: TYPE = GGModelTypes.OutlineDescriptorObj; Point: TYPE = GGBasicTypes.Point; Segment: TYPE = GGSegmentTypes.Segment; SegmentGenerator: TYPE = GGModelTypes.SegmentGenerator; Sequence: TYPE = GGModelTypes.Sequence; Slice: TYPE = GGModelTypes.Slice; SliceDescriptor: TYPE = REF SliceDescriptorObj; SliceDescriptorObj: TYPE = GGModelTypes.SliceDescriptorObj; SliceParts: TYPE = GGModelTypes.SliceParts; Traj: TYPE = GGModelTypes.Traj; TriggerBag: TYPE = GGInterfaceTypes.TriggerBag; Vector: TYPE = GGBasicTypes.Vector; Problem: PUBLIC SIGNAL [msg: Rope.ROPE] = CODE; <> maxDistance: REAL = 99999.0; noPoint: Point = [0.0, 0.0]; noJoint: NAT = 9999; noCP: NAT = 8888; noSeg: NAT = 7777; <> FeatureFromOutline: PUBLIC PROC [outline: Outline, parts: SliceParts _ NIL] RETURNS [feature: FeatureData] = { sliceParts: SliceParts _ IF parts=NIL THEN outline.class.newParts[outline, NIL, slice] ELSE parts; outlineD: OutlineDescriptor _ NEW[OutlineDescriptorObj _ [slice: outline, parts: sliceParts]]; feature _ NEW[FeatureDataObj]; feature.type _ outline; feature.shape _ outlineD; }; FeatureFromSlice: PUBLIC PROC [slice: Slice, parts: SliceParts _ NIL] RETURNS [feature: FeatureData] = { sliceParts: SliceParts _ IF parts=NIL THEN slice.class.newParts[slice, NIL, slice] ELSE parts; -- may get a descriptor of the whole slice sliceD: SliceDescriptor _ NEW[SliceDescriptorObj _ [slice: slice, parts: sliceParts]]; feature _ NEW[FeatureDataObj]; feature.type _ slice; feature.shape _ sliceD; }; FeatureFromAnchor: PUBLIC PROC [anchor: Caret] RETURNS [feature: FeatureData] = { feature _ NEW[FeatureDataObj]; feature.type _ anchor; -- that is, anchor => the member of the enumerated type feature.shape _ anchor; -- that is, anchor => the parameter }; <> CreateObjectBag: PUBLIC PROC [] RETURNS [objectBag: ObjectBag] = { objectBag _ NEW[ObjectBagObj _ [ slopeLines: NIL, angleLines: NIL, radiiCircles: NIL, distanceLines: NIL, midpoints: NIL, intersectionPoints: NIL ]]; }; FlushObjectBag: PUBLIC PROC [objectBag: ObjectBag] = { objectBag.slopeLines _ NIL; objectBag.angleLines _ NIL; objectBag.radiiCircles _ NIL; objectBag.distanceLines _ NIL; objectBag.midpoints _ NIL; objectBag.intersectionPoints _ NIL; }; JointAddSlopeLine: PUBLIC PROC [degrees: REAL, direction: Vector, point: Point, objectBag: ObjectBag] RETURNS [feature: FeatureData] = { <> <> line: Line; coincident: FeatureData _ LineThru[point, degrees, objectBag.slopeLines]; IF coincident # NIL THEN { alignmentLine: AlignmentLine _ NARROW[coincident.shape]; alignmentLine.triggerPoints _ CONS[point, alignmentLine.triggerPoints]; feature _ NIL; } ELSE { alignmentLine: AlignmentLine; line _ GGLines.LineFromPointAndVector[point, direction]; alignmentLine _ NEW[AlignmentLineObj _ [line: line, degrees: degrees, triggerPoints: CONS[point, NIL]]]; feature _ NEW[FeatureDataObj]; feature.type _ slopeLine; feature.shape _ alignmentLine; AddFeature[feature, objectBag]; }; }; JointAddCircle: PUBLIC PROC [radius: REAL, point: Point, objectBag: ObjectBag] RETURNS [feature: FeatureData] = { <> <> circle: Circle; coincident: FeatureData; coincident _ SameCircle[point, radius, objectBag.radiiCircles]; IF coincident # NIL THEN { alignmentCircle: AlignmentCircle _ NARROW[coincident.shape]; alignmentCircle.triggerPoints _ CONS[point, alignmentCircle.triggerPoints]; feature _ NIL; } ELSE { alignmentCircle: AlignmentCircle; circle _ GGCircles.CircleFromPointAndRadius[point, radius]; alignmentCircle _ NEW[AlignmentCircleObj _ [circle: circle, triggerPoints: CONS[point, NIL]]]; feature _ NEW[FeatureDataObj]; feature.type _ radiiCircle; feature.shape _ alignmentCircle; AddFeature[feature, objectBag]; }; }; SameCircle: PRIVATE PROC [point: Point, radius: REAL, list: LIST OF FeatureData] RETURNS [coincident: FeatureData] = { circle: Circle; FOR l: LIST OF FeatureData _ list, l.rest UNTIL l = NIL DO circle _ NARROW[l.first.shape, AlignmentCircle].circle; <> IF RealFns.AlmostEqual[circle.origin.x, point.x, -10] AND RealFns.AlmostEqual[circle.origin.y, point.y, -10] AND RealFns.AlmostEqual[circle.radius, radius, -10] THEN RETURN[l.first]; ENDLOOP; RETURN[NIL]; }; LineThru: PRIVATE PROC [point: Point, degrees: REAL, list: LIST OF FeatureData] RETURNS [coincident: FeatureData] = { epsilon: REAL = 1.0e-5; line: Line; FOR l: LIST OF FeatureData _ list, l.rest UNTIL l = NIL DO line _ NARROW[l.first.shape, AlignmentLine].line; IF NARROW[l.first.shape, AlignmentLine].degrees = degrees AND GGLines.LineDistance[point, line] < epsilon THEN RETURN[l.first]; ENDLOOP; RETURN[NIL]; }; SegmentAddTwoAngleLines: PUBLIC PROC [degrees: REAL, segNum: NAT, lo, hi: Point, objectBag: ObjectBag] RETURNS [line1, line2: FeatureData] = { loLine: Line _ GGLines.LineFromPointAndAngle[pt: lo, degrees: GGVector.AngleFromVector[[x: hi.x-lo.x, y: hi.y-lo.y]]+degrees]; hiLine: Line _ GGLines.LineFromPointAndAngle[pt: hi, degrees: GGVector.AngleFromVector[[x: lo.x-hi.x, y: lo.y-hi.y]]+degrees]; line1 _ NEW[FeatureDataObj]; line1.type _ angleLine; line1.shape _ NEW[AlignmentLineObj _ [line: loLine, degrees: degrees, triggerPoints: NIL]]; <> AddFeature[line1, objectBag]; line2 _ NEW[FeatureDataObj]; line2.type _ angleLine; line2.shape _ NEW[AlignmentLineObj _ [line: hiLine, degrees: degrees, triggerPoints: NIL]]; <> AddFeature[line2, objectBag]; }; SegmentAddDistanceLines: PUBLIC PROC [distance: REAL, segNum: NAT, lo, hi: Point, objectBag: ObjectBag] RETURNS [line1, line2: FeatureData] = { <> line, leftLine, rightLine: Line; line _ GGLines.LineFromPoints[lo, hi]; leftLine _ GGLines.LineLeftOfLine[line, distance]; line1 _ NEW[FeatureDataObj]; line1.type _ distanceLine; line1.shape _ leftLine; <> AddFeature[line1, objectBag]; IF ABS[distance] > 0.0 THEN { rightLine _ GGLines.LineRightOfLine[line, distance]; line2 _ NEW[FeatureDataObj]; line2.type _ distanceLine; line2.shape _ rightLine; <> AddFeature[line2, objectBag]; } ELSE line2 _ NIL; }; SegmentAddMidpoint: PUBLIC PROC [segNum: NAT, lo, hi: Point, objectBag: ObjectBag] RETURNS [feature: FeatureData] = { <> midpoint: Point; alignmentPoint: AlignmentPoint; midpoint _ GGVector.Scale[GGVector.Add[lo, hi], 0.5]; alignmentPoint _ NEW[AlignmentPointObj _ [point: midpoint, tangent: FALSE]]; feature _ NEW[FeatureDataObj]; feature.type _ midpoint; feature.shape _ alignmentPoint; feature.hitPart _ NEW[GGInterfaceTypes.SequencePartObj _ [segNum, -1, -1]]; AddFeature[feature, objectBag]; }; AddFeature: PRIVATE PROC [featureData: FeatureData, objectBag: ObjectBag] = { Process.CheckForAbort[]; <> <