<> <> <> <Documentation>MultiGravity.tioga.>> <<>> DIRECTORY AtomButtons, CodeTimer, GGBasicTypes, GGCaret, GGCircles, GGInterfaceTypes, GGModelTypes, GGMultiGravity, GGSegmentTypes, GGState, GGUtility, Lines2d, Real, RealFns, Rope, Vectors2d; GGMultiGravityImpl: CEDAR PROGRAM IMPORTS AtomButtons, CodeTimer, GGCaret, GGCircles, GGState, Lines2d, RealFns, Vectors2d EXPORTS GGMultiGravity = BEGIN AlignBag: TYPE = REF AlignBagObj; AlignBagObj: TYPE = GGInterfaceTypes.AlignBagObj; AlignmentCircle: TYPE = GGInterfaceTypes.AlignmentCircle; AlignmentLine: TYPE = GGInterfaceTypes.AlignmentLine; AlignmentPoint: TYPE = REF AlignmentPointObj; AlignmentPointObj: TYPE = GGInterfaceTypes.AlignmentPointObj; Arc: TYPE = GGBasicTypes.Arc; Caret: TYPE = GGInterfaceTypes.Caret; Circle: TYPE = GGBasicTypes.Circle; Edge: TYPE = GGBasicTypes.Edge; FeatureData: TYPE = REF FeatureDataObj; FeatureDataObj: TYPE = GGModelTypes.FeatureDataObj; GGData: TYPE = GGInterfaceTypes.GGData; GoodPoint: TYPE = REF GoodPointObj; GoodPointObj: TYPE = GGMultiGravity.GoodPointObj; JointGenerator: TYPE = GGModelTypes.JointGenerator; Line: TYPE = GGBasicTypes.Line; NearDistances: TYPE = REF NearDistancesObj; NearDistancesObj: TYPE = GGMultiGravity.NearDistancesObj; NearFeatures: TYPE = REF NearFeaturesObj; NearFeaturesObj: TYPE = GGMultiGravity.NearFeaturesObj; NearPoints: TYPE = REF NearPointsObj; NearPointsAndCurves: TYPE = REF NearPointsAndCurvesObj; NearPointsAndCurvesObj: TYPE = GGMultiGravity.NearPointsAndCurvesObj; NearPointsObj: TYPE = GGMultiGravity.NearPointsObj; Outline: TYPE = GGModelTypes.Outline; OutlineDescriptor: TYPE = REF OutlineDescriptorObj; OutlineDescriptorObj: TYPE = GGModelTypes.OutlineDescriptorObj; OutlinePointPairGenerator: TYPE = GGModelTypes.OutlinePointPairGenerator; Point: TYPE = GGBasicTypes.Point; PointPairAndDone: TYPE = GGModelTypes.PointPairAndDone; PointPairGenerator: TYPE = GGModelTypes.PointPairGenerator; Segment: TYPE = GGSegmentTypes.Segment; SegmentGenerator: TYPE = GGModelTypes.SegmentGenerator; Sequence: TYPE = GGModelTypes.Sequence; Slice: TYPE = GGModelTypes.Slice; SliceDescriptor: TYPE = GGModelTypes.SliceDescriptor; TriggerBag: TYPE = REF TriggerBagObj; TriggerBagObj: TYPE = GGInterfaceTypes.TriggerBagObj; BestPoints: TYPE = REF BestPointsObj; BestPointsObj: TYPE = RECORD [ size: NAT, max, min: REAL, bestTossed: REAL, -- the distance of the closest object that has been thrown away dTol: REAL, -- min + s innerR: REAL, -- find all curves within this radius even if they are not neighbors of the nearest s: REAL, -- the size of neighborhoods. BestPoints should contain all objects that have been seen such that min <= dist(o, q) <= min+s, unless BestPoints overflows. overflow: BOOL, points: SEQUENCE len: NAT OF GoodPoint]; MultiGravityPool: TYPE = REF MultiGravityPoolObj; MultiGravityPoolObj: TYPE = RECORD [ distances: NearDistances, features: NearFeatures, bestpoints: BestPoints, bestcurves: BestPoints ]; <> <<>> EmptyBag: PROC [alignBag: AlignBag] RETURNS [BOOL] = { RETURN[ alignBag.slopeLines = NIL AND alignBag.angleLines = NIL AND alignBag.radiiCircles = NIL AND alignBag.distanceLines = NIL AND alignBag.midpoints = NIL AND alignBag.intersectionPoints = NIL AND alignBag.anchor = NIL]; }; EmptyTriggers: PROC [triggerBag: TriggerBag] RETURNS [BOOL] = { RETURN[ <> triggerBag.slices = NIL AND triggerBag.intersectionPoints = NIL AND triggerBag.anchor = NIL ]; }; Problem: PUBLIC SIGNAL [msg: Rope.ROPE] = CODE; <> << [Artwork node; type 'ArtworkInterpress on' to command tool] >> <> Map: PUBLIC PROC [testPoint: Point, criticalR: REAL, alignBag: AlignBag, sceneBag: TriggerBag, ggData: GGData, useAlignBag: BOOL] RETURNS [resultPoint: Point, feature: FeatureData, hitData: REF ANY] = { <> ENABLE UNWIND => ggData.multiGravityPool _ NewMultiGravityPool[]; -- in case an ABORT happened while pool was in use CodeTimer.StartInt[$MultiMap, $Gargoyle]; IF GGState.Gravity[ggData] THEN { SELECT ggData.hitTest.gravityType FROM strictDistance => [resultPoint, feature, hitData] _ StrictDistance[testPoint, criticalR, alignBag, sceneBag, ggData]; innerCircle => [resultPoint, feature, hitData] _ PointsPreferred[testPoint, criticalR, ggData.hitTest.innerR, alignBag, sceneBag, ggData, useAlignBag]; ENDCASE => ERROR; } ELSE { resultPoint _ testPoint; feature _ NIL; }; CodeTimer.StopInt[$MultiMap, $Gargoyle]; }; <<>> StrictDistance: PUBLIC PROC [testPoint: Point, criticalR: REAL, alignBag: AlignBag, sceneBag: TriggerBag, ggData: GGData] RETURNS [resultPoint: Point, feature: FeatureData, hitData: REF ANY] = { <> nearPointsAndCurves: NearPointsAndCurves; count: NAT; [nearPointsAndCurves, count] _ MultiStrictDistance[testPoint, criticalR, alignBag, sceneBag, ggData]; IF count = 0 THEN RETURN [testPoint, NIL, NIL]; IF count = 1 THEN RETURN PrepareWinner[nearPointsAndCurves, 0] ELSE { <> mgp: MultiGravityPool _ NARROW[ggData.multiGravityPool, MultiGravityPool]; distances: NearDistances _ mgp.distances; features: NearFeatures _ mgp.features; nearestDist: REAL _ -1; bestSceneObject: INT _ -1; neighborCount: NAT _ 1; s: REAL = 0.072; -- 1/1000 inches FOR i: NAT IN [0..count) DO goodPoint: GoodPoint _ nearPointsAndCurves[i]; distances[i] _ goodPoint.dist; features[i] _ goodPoint.featureData; ENDLOOP; nearestDist _ distances[0]; FOR i: NAT IN [1..count) DO IF distances[i] - nearestDist < s THEN neighborCount _ neighborCount + 1; ENDLOOP; IF neighborCount = 1 THEN RETURN PrepareWinner[nearPointsAndCurves, 0]; <> <<1) Prefer scene objects to alignment lines.>> <<2) Prefer points to lines.>> <> bestSceneObject _ -1; <> <> <