DIRECTORY GGCircles, GGLines, GGGravity, GGModelTypes, GGInterfaceTypes, GGObjects, GGRefresh, GGShapes, GGVector, Imager, Real, RealFns; GGGravityImpl: CEDAR PROGRAM IMPORTS GGCircles, GGLines, GGObjects, GGRefresh, GGShapes, GGVector, Imager, RealFns EXPORTS GGGravity = BEGIN Angle: TYPE = GGModelTypes.Angle; BoundBox: TYPE = GGModelTypes.BoundBox; Camera: TYPE = GGModelTypes.Camera; Circle: TYPE = GGModelTypes.Circle; Edge: TYPE = GGModelTypes.Edge; FeatureData: TYPE = REF FeatureDataObj; FeatureDataObj: TYPE = GGGravity.FeatureDataObj; GargoyleData: TYPE = GGInterfaceTypes.GargoyleData; JointGenerator: TYPE = GGObjects.JointGenerator; Line: TYPE = GGModelTypes.Line; ObjectBag: TYPE = REF ObjectBagObj; ObjectBagObj: TYPE = GGGravity.ObjectBagObj; Segment: TYPE = GGModelTypes.Segment; SegmentGenerator: TYPE = GGObjects.SegmentGenerator; Sequence: TYPE = GGModelTypes.Sequence; SymmetryGroup: TYPE = GGGravity.SymmetryGroup; Traj: TYPE = GGModelTypes.Traj; Point: TYPE = GGModelTypes.Point; Vector: TYPE = GGModelTypes.Vector; Map: PUBLIC PROC [testPoint: Point, criticalR: REAL, environ: ObjectBag, gargoyleData: GargoyleData] RETURNS [resultPoint: Point, feature: FeatureData] = { SELECT gargoyleData.hitTest.gravityType FROM strictDistance => [resultPoint, feature] _ StrictDistance[testPoint, criticalR, environ]; innerCircle => [resultPoint, feature] _ InnerCircle[testPoint, criticalR, gargoyleData.hitTest.innerR, environ]; sectors => [resultPoint, feature] _ Sector[testPoint, criticalR, environ]; none => { resultPoint _ testPoint; feature _ NIL; }; ENDCASE => ERROR; }; NotYetImplemented: PUBLIC ERROR = CODE; NearestSegment: PROC [testPoint: Point, seq: Sequence, tolerance: REAL] RETURNS [bestDist: REAL, bestSeg: NAT, bestPoint: Point, success: BOOL] = { thisDist2, bestDist2: REAL; thisPoint: Point; segGen: SegmentGenerator; thisSuccess: BOOL; next: GGObjects.SegAndIndex; success _ FALSE; segGen _ GGObjects.SegmentsInSequence[seq]; next _ GGObjects.NextSegmentAndIndex[segGen]; IF next.seg = NIL THEN { -- The sequence is a single joint bestDist _ 99999.0; -- magic number meaning no segment bestSeg _ 999; -- magic number for debugging bestPoint _ [-1.0, -1.0]; RETURN; }; [bestPoint, thisSuccess] _ next.seg.class.closestPoint[next.seg, testPoint, tolerance]; IF NOT thisSuccess THEN { bestDist2 _ 99999.0; bestSeg _ 999; bestPoint _ [-1.0, -1.0]; } ELSE { bestDist2 _ GGVector.DistanceSquared[bestPoint, testPoint]; bestSeg _ 0; success _ TRUE; }; FOR next _ GGObjects.NextSegmentAndIndex[segGen], GGObjects.NextSegmentAndIndex[segGen] UNTIL next.seg = NIL DO [thisPoint, thisSuccess] _ next.seg.class.closestPoint[next.seg, testPoint, tolerance]; IF NOT thisSuccess THEN { thisDist2 _ 99999.0; thisPoint _ [-1.0, -1.0]; } ELSE { thisDist2 _ GGVector.DistanceSquared[thisPoint, testPoint]; success _ TRUE; }; IF thisDist2 < bestDist2 THEN { bestDist2 _ thisDist2; bestSeg _ next.index; bestPoint _ thisPoint; }; ENDLOOP; bestDist _ RealFns.SqRt[bestDist2]; }; NearestJoint: PROC [testPoint: Point, seq: Sequence] RETURNS [bestDist: REAL, bestJoint: NAT, bestPoint: Point] = { thisPoint: Point; thisDist2, bestDist2: REAL; index: INT; jointGen: JointGenerator; jointGen _ GGObjects.JointsInSequence[seq]; index _ GGObjects.NextJoint[jointGen]; bestPoint _ GGObjects.FetchJointPos[seq.traj, index]; bestDist2 _ GGVector.DistanceSquared[bestPoint, testPoint]; bestJoint _ index; FOR index _ GGObjects.NextJoint[jointGen], GGObjects.NextJoint[jointGen] UNTIL index = -1 DO thisPoint _ GGObjects.FetchJointPos[seq.traj, index]; thisDist2 _ GGVector.DistanceSquared[thisPoint, testPoint]; IF thisDist2 < bestDist2 THEN { bestDist2 _ thisDist2; bestJoint _ index; bestPoint _ thisPoint; }; ENDLOOP; bestDist _ RealFns.SqRt[bestDist2]; }; EmptyBag: PROC [objectBag: ObjectBag] RETURNS [BOOL] = { RETURN[ objectBag.seqs = NIL AND objectBag.slopeLines = NIL AND objectBag.symmetryLines = NIL AND objectBag.radiiCircles = NIL AND objectBag.distanceLines = NIL AND objectBag.vectors = NIL AND objectBag.intersectionPoints = NIL]; }; UpdateBestCurve: PROC [thisCurve, bestCurve: GoodCurve] = { bestCurve.dist _ thisCurve.dist; bestCurve.segNum _ 999; -- magic number for debugging bestCurve.point _ thisCurve.point; bestCurve.featureData _ thisCurve.featureData; }; UpdateBestPoint: PROC [thisPoint, bestPoint: GoodPoint] = { bestPoint.dist _ thisPoint.dist; bestPoint.point _ thisPoint.point; bestPoint.joint _ 999; -- magic number for debugging bestPoint.featureData _ thisPoint.featureData; }; BestPointAndCurve: PROC [objectBag: ObjectBag, testPoint: Point, tolerance: REAL] RETURNS [bestPoint: GoodPoint, bestCurve: GoodCurve] = { epsilon: REAL = 1.0e-3; thisPoint: GoodPoint; thisCurve: GoodCurve; featureData: FeatureData; success: BOOL; thisCurve _ NEW[GoodCurveObj]; bestCurve _ NEW[GoodCurveObj]; thisPoint _ NEW[GoodPointObj]; bestPoint _ NEW[GoodPointObj]; bestCurve.dist _ 99999.0; -- magic numbers for debugging bestPoint.dist _ 99999.0; -- magic numbers for debugging FOR slopeLines: LIST OF FeatureData _ objectBag.slopeLines, slopeLines.rest UNTIL slopeLines = NIL DO featureData _ slopeLines.first; thisCurve.dist _ GGLines.LineDistance[testPoint, featureData.line]; thisCurve.point _ GGLines.PointProjectedOntoLine[testPoint, featureData.line]; thisCurve.featureData _ featureData; IF thisCurve.dist < bestCurve.dist THEN UpdateBestCurve[thisCurve, bestCurve]; ENDLOOP; FOR dLines: LIST OF FeatureData _ objectBag.distanceLines, dLines.rest UNTIL dLines = NIL DO featureData _ dLines.first; thisCurve.dist _ GGLines.LineDistance[testPoint, featureData.line]; thisCurve.point _ GGLines.PointProjectedOntoLine[testPoint, featureData.line]; thisCurve.featureData _ featureData; IF thisCurve.dist < bestCurve.dist THEN UpdateBestCurve[thisCurve, bestCurve]; ENDLOOP; FOR iPoints: LIST OF FeatureData _ objectBag.intersectionPoints, iPoints.rest UNTIL iPoints = NIL DO featureData _ iPoints.first; thisPoint.dist _ GGVector.Distance[featureData.point, testPoint]; thisPoint.point _ featureData.point; thisPoint.featureData _ featureData; IF thisPoint.dist < bestPoint.dist THEN UpdateBestPoint[thisPoint, bestPoint]; ENDLOOP; FOR circles: LIST OF FeatureData _ objectBag.radiiCircles, circles.rest UNTIL circles = NIL DO featureData _ circles.first; thisCurve.dist _ GGCircles.CircleDistance[testPoint, featureData.circle]; thisCurve.point _ GGCircles.PointProjectedOntoCircle[testPoint, featureData.circle]; thisCurve.featureData _ featureData; IF thisCurve.dist < bestCurve.dist THEN UpdateBestCurve[thisCurve, bestCurve]; ENDLOOP; FOR trajs: LIST OF FeatureData _ objectBag.seqs, trajs.rest UNTIL trajs = NIL DO featureData _ trajs.first; [thisCurve.dist, thisCurve.segNum, thisCurve.point, success] _ NearestSegment[testPoint, featureData.tseq, tolerance]; IF success THEN { IF thisCurve.dist - epsilon <= bestCurve.dist THEN { -- so segments are preferred to slopelines bestCurve.dist _ thisCurve.dist; bestCurve.segNum _ thisCurve.segNum; bestCurve.point _ thisCurve.point; bestCurve.featureData _ featureData; }; }; [thisPoint.dist, thisPoint.joint, thisPoint.point] _ NearestJoint[testPoint, featureData.tseq]; IF thisPoint.dist - epsilon <= bestPoint.dist THEN {-- joints are preferred to intersection Points bestPoint.dist _ thisPoint.dist; bestPoint.point _ thisPoint.point; bestPoint.joint _ thisPoint.joint; bestPoint.featureData _ featureData; }; ENDLOOP; }; StrictDistance: PUBLIC PROC [testPoint: Point, criticalR: REAL, environ: ObjectBag] RETURNS [resultPoint: Point, feature: FeatureData] = { bestCurve: GoodCurve; bestPoint: GoodPoint; IF EmptyBag[environ] THEN { resultPoint _ testPoint; feature _ NIL; RETURN; }; [bestPoint, bestCurve] _ BestPointAndCurve[environ, testPoint, criticalR]; IF bestPoint.dist = 99999.0 THEN ERROR; IF bestCurve.dist = 99999.0 THEN ERROR; IF bestPoint.dist < criticalR AND bestPoint.dist <= bestCurve.dist THEN { -- use the best point feature _ bestPoint.featureData; ExtractResultFromPoint[bestPoint, feature]; resultPoint _ bestPoint.point; } ELSE IF bestCurve.dist < criticalR THEN { feature _ bestCurve.featureData; ExtractResultFromCurve[bestCurve, feature]; resultPoint _ bestCurve.point; } ELSE { feature _ NIL; resultPoint _ testPoint; }; }; -- StrictDistance GoodCurve: TYPE = REF GoodCurveObj; GoodCurveObj: TYPE = RECORD [ dist: REAL, -- the distance from point to testPoint segNum: NAT, -- the best segment of this curve (if it is a trajectory) point: Point, -- the best point on this curve featureData: FeatureData -- this curve ]; GoodPoint: TYPE = REF GoodPointObj; GoodPointObj: TYPE = RECORD [ dist: REAL, point: Point, joint: NAT, -- the joint of the trajectory mentioned in FeatureData (if this is a joint) featureData: FeatureData -- this point ]; ExtractResultFromCurve: PROC [curve: GoodCurve, feature: FeatureData] = { SELECT curve.featureData.type FROM sequence => { feature.segNum _ curve.segNum; feature.resultType _ segment; }; slopeLine => feature.resultType _ slopeLine; radiiCircle => feature.resultType _ radiiCircle; distanceLine => feature.resultType _ distanceLine; ENDCASE => ERROR NotYetImplemented; }; ExtractResultFromPoint: PROC [goodPoint: GoodPoint, feature: FeatureData] = { SELECT goodPoint.featureData.type FROM sequence => { feature.jointNum _ goodPoint.joint; feature.resultType _ joint; }; intersectionPoint => { feature.resultType _ intersectionPoint; }; ENDCASE => ERROR NotYetImplemented; }; InnerCircle: PUBLIC PROC [testPoint: Point, criticalR: REAL, innerR: REAL, environ: ObjectBag] RETURNS [resultPoint: Point, feature: FeatureData] = { bestCurve: GoodCurve; bestPoint: GoodPoint; IF EmptyBag[environ] THEN { resultPoint _ testPoint; feature _ NIL; RETURN; }; [bestPoint, bestCurve] _ BestPointAndCurve[environ, testPoint, criticalR]; IF bestPoint.dist < innerR OR (bestPoint.dist < criticalR AND bestPoint.dist <= bestCurve.dist) THEN { -- use the best point feature _ bestPoint.featureData; ExtractResultFromPoint[bestPoint, feature]; resultPoint _ bestPoint.point; } ELSE IF bestCurve.dist < criticalR THEN { feature _ bestCurve.featureData; ExtractResultFromCurve[bestCurve, feature]; resultPoint _ bestCurve.point; } ELSE { feature _ NIL; resultPoint _ testPoint; }; }; -- InnerCircle Sector: PUBLIC PROC [testPoint: Point, criticalR: REAL, environ: ObjectBag] RETURNS [resultPoint: Point, feature: FeatureData] = {}; CreateObjectBag: PUBLIC PROC [] RETURNS [objectBag: ObjectBag] = { objectBag _ NEW[ObjectBagObj _ [ seqs: NIL, slopeLines: NIL, symmetryLines: NIL, radiiCircles: NIL, distanceLines: NIL, vectors: NIL, intersectionPoints: NIL ]]; }; AddFeature: PRIVATE PROC [featureData: FeatureData, objectBag: ObjectBag] = { iPoint: Point; parallel: BOOL; points: ARRAY[1..2] OF Point; hitCount: NAT; SELECT featureData.type FROM sequence => { IF NOT featureData.tseq.all AND featureData.tseq.parts = NIL THEN ERROR; -- empty sequence objectBag.seqs _ CONS[featureData, objectBag.seqs]; }; distanceLine => objectBag.distanceLines _ CONS[featureData, objectBag.distanceLines]; slopeLine => objectBag.slopeLines _ CONS[featureData, objectBag.slopeLines]; symmetryLine => objectBag.symmetryLines _ CONS[featureData, objectBag.symmetryLines]; radiiCircle => objectBag.radiiCircles _ CONS[featureData, objectBag.radiiCircles]; intersectionPoint => objectBag.intersectionPoints _ CONS[featureData, objectBag.intersectionPoints]; ENDCASE => ERROR; IF featureData.type = slopeLine THEN { FOR lineList: LIST OF FeatureData _ objectBag.slopeLines.rest, lineList.rest UNTIL lineList = NIL DO [iPoint, parallel] _ GGLines.LineMeetsLine[lineList.first.line, featureData.line]; IF NOT parallel THEN { AddIntersectionPointFeature[iPoint, featureData, lineList.first, objectBag]; }; ENDLOOP; FOR circleList: LIST OF FeatureData _ objectBag.radiiCircles, circleList.rest UNTIL circleList = NIL DO [points, hitCount] _ GGCircles.LineMeetsCircle[featureData.line, circleList.first.circle]; FOR i: NAT IN [1..hitCount] DO AddIntersectionPointFeature[points[i], featureData, circleList.first, objectBag]; ENDLOOP; ENDLOOP; FOR dlineList: LIST OF FeatureData _ objectBag.distanceLines, dlineList.rest UNTIL dlineList = NIL DO [iPoint, parallel] _ GGLines.LineMeetsLine[dlineList.first.line, featureData.line]; IF NOT parallel THEN { AddIntersectionPointFeature[iPoint, featureData, dlineList.first, objectBag]; }; ENDLOOP; }; IF featureData.type = radiiCircle THEN { FOR lineList: LIST OF FeatureData _ objectBag.slopeLines, lineList.rest UNTIL lineList = NIL DO [points, hitCount] _ GGCircles.LineMeetsCircle[lineList.first.line, featureData.circle]; FOR i: NAT IN [1..hitCount] DO AddIntersectionPointFeature[points[i], lineList.first, featureData, objectBag]; ENDLOOP; ENDLOOP; FOR circleList: LIST OF FeatureData _ objectBag.radiiCircles.rest, circleList.rest UNTIL circleList = NIL DO [points, hitCount] _ GGCircles.CircleMeetsCircle[circleList.first.circle, featureData.circle]; FOR i: NAT IN [1..hitCount] DO AddIntersectionPointFeature[points[i], circleList.first, featureData, objectBag]; ENDLOOP; ENDLOOP; FOR dlineList: LIST OF FeatureData _ objectBag.distanceLines, dlineList.rest UNTIL dlineList = NIL DO [points, hitCount] _ GGCircles.LineMeetsCircle[dlineList.first.line, featureData.circle]; FOR i: NAT IN [1..hitCount] DO AddIntersectionPointFeature[points[i], dlineList.first, featureData, objectBag]; ENDLOOP; ENDLOOP; }; IF featureData.type = distanceLine THEN { FOR lineList: LIST OF FeatureData _ objectBag.slopeLines, lineList.rest UNTIL lineList = NIL DO [iPoint, parallel] _ GGLines.LineMeetsLine[lineList.first.line, featureData.line]; IF NOT parallel THEN { AddIntersectionPointFeature[iPoint, featureData, lineList.first, objectBag]; }; ENDLOOP; FOR circleList: LIST OF FeatureData _ objectBag.radiiCircles, circleList.rest UNTIL circleList = NIL DO [points, hitCount] _ GGCircles.LineMeetsCircle[featureData.line, circleList.first.circle]; FOR i: NAT IN [1..hitCount] DO AddIntersectionPointFeature[points[i], featureData, circleList.first, objectBag]; ENDLOOP; ENDLOOP; FOR dlineList: LIST OF FeatureData _ objectBag.distanceLines.rest, dlineList.rest UNTIL dlineList = NIL DO [iPoint, parallel] _ GGLines.LineMeetsLine[dlineList.first.line, featureData.line]; IF NOT parallel THEN { AddIntersectionPointFeature[iPoint, featureData, dlineList.first, objectBag]; }; ENDLOOP; }; }; SameCircle: PRIVATE PROC [point: Point, radius: REAL, list: LIST OF FeatureData] RETURNS [coincident: FeatureData] = { epsilon: REAL = 1.0e-5; FOR l: LIST OF FeatureData _ list, l.rest UNTIL l = NIL DO IF l.first.circle.origin = point AND l.first.circle.radius = radius 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; FOR l: LIST OF FeatureData _ list, l.rest UNTIL l = NIL DO IF l.first.degrees = degrees AND GGLines.LineDistance[point, l.first.line] < epsilon THEN RETURN[l.first]; ENDLOOP; RETURN[NIL]; }; JointAddSlopeLine: PUBLIC PROC [degrees: REAL, direction: Vector, point: Point, jointNum: NAT, traj: Traj, objectBag: ObjectBag] = { line: Line; featureData, coincident: FeatureData; coincident _ LineThru[point, degrees, objectBag.slopeLines]; IF coincident # NIL THEN { coincident.triggerPoints _ CONS[point, coincident.triggerPoints]; } ELSE { line _ GGLines.LineFromPointAndVector[point, direction]; featureData _ NEW[FeatureDataObj]; featureData.type _ slopeLine; featureData.line _ line; featureData.degrees _ degrees; featureData.triggerPoints _ CONS[point, NIL]; featureData.jointNum _ jointNum; featureData.traj _ traj; AddFeature[featureData, objectBag]; }; }; JointAddVector: PUBLIC PROC [vector: Vector, point: Point, jointNum: NAT, traj: Traj, objectBag: ObjectBag] = { }; JointAddCircle: PUBLIC PROC [radius: REAL, point: Point, jointNum: NAT, traj: Traj, objectBag: ObjectBag] = { circle: Circle; featureData, coincident: FeatureData; coincident _ SameCircle[point, radius, objectBag.radiiCircles]; IF coincident # NIL THEN { coincident.triggerPoints _ CONS[point, coincident.triggerPoints]; } ELSE { circle _ GGCircles.CircleFromPointAndRadius[point, radius]; featureData _ NEW[FeatureDataObj]; featureData.type _ radiiCircle; featureData.circle _ circle; featureData.triggerPoints _ CONS[point, NIL]; featureData.jointNum _ jointNum; featureData.traj _ traj; AddFeature[featureData, objectBag]; }; }; JointAddPoint: PUBLIC PROC [point: Point, jointNum: NAT, traj: Traj, objectBag: ObjectBag] = { }; SegmentAddTwoAngleLines: PUBLIC PROC [degrees: REAL, p1, p2: Point, segNum, traj: Traj, objectBag: ObjectBag] = { }; SegmentAddDistanceLines: PUBLIC PROC [distance: REAL, segNum: NAT, traj: Traj, objectBag: ObjectBag] = { line, leftLine, rightLine: Line; featureData: FeatureData; seg: Segment _ GGObjects.FetchSegment[traj, segNum]; line _ GGLines.LineFromPoints[seg.lo, seg.hi]; leftLine _ GGLines.LineLeftOfLine[line, distance]; featureData _ NEW[FeatureDataObj]; featureData.type _ distanceLine; featureData.line _ leftLine; featureData.segNum _ segNum; featureData.traj _ traj; AddFeature[featureData, objectBag]; IF ABS[distance] > 0.0 THEN { rightLine _ GGLines.LineRightOfLine[line, distance]; featureData _ NEW[FeatureDataObj]; featureData.type _ distanceLine; featureData.line _ rightLine; featureData.segNum _ segNum; featureData.traj _ traj; AddFeature[featureData, objectBag]; }; }; SegmentAddEdge: PUBLIC PROC [point: Point, jointNum: NAT, traj: Traj, objectBag: ObjectBag] = { }; AddTrajectory: PUBLIC PROC [traj: Traj, objectBag: ObjectBag] = { featureData: FeatureData; seq: Sequence _ GGObjects.CreateCompleteSequence[traj]; featureData _ NEW[FeatureDataObj]; featureData.type _ sequence; featureData.tseq _ seq; AddFeature[featureData, objectBag]; }; AddSequence: PUBLIC PROC [seq: Sequence, objectBag: ObjectBag] = { featureData: FeatureData; featureData _ NEW[FeatureDataObj]; featureData.type _ sequence; featureData.tseq _ seq; AddFeature[featureData, objectBag]; }; SymmetryAddLines: PUBLIC PROC [group: SymmetryGroup, entity: REF ANY, objectBag: ObjectBag] = { }; SymmetryAddPoints: PUBLIC PROC [group: SymmetryGroup, entity: REF ANY, objectBag: ObjectBag] = { }; CoordFrameAddPoint: PUBLIC PROC [point: Point, objectBag: ObjectBag] = { }; CoordFrameAddXLine: PUBLIC PROC [xVal: REAL, objectBag: ObjectBag] = { }; CoordFrameAddYLine: PUBLIC PROC [yVal: REAL, objectBag: ObjectBag] = { }; AddIntersectionPointFeature: PUBLIC PROC [point: Point, feature1, feature2: FeatureData, objectBag: ObjectBag] = { featureData: FeatureData; featureData _ NEW[FeatureDataObj]; featureData.type _ intersectionPoint; featureData.line _ NIL; featureData.line1Feature _ feature1; featureData.line2Feature _ feature2; featureData.degrees _ 999.0; featureData.seg _ NIL; featureData.point _ point; AddFeature[featureData, objectBag]; }; FlushObjectBag: PUBLIC PROC [objectBag: ObjectBag] = { ERROR NotYetImplemented; }; AdjustVisibilityPoint: PUBLIC PROC [testPoint: Point, tolerance: REAL, objectBag: ObjectBag] = { dist: REAL; feature: FeatureData; success: BOOL; FOR slopeLineList: LIST OF FeatureData _ objectBag.slopeLines, slopeLineList.rest UNTIL slopeLineList = NIL DO feature _ slopeLineList.first; dist _ GGLines.LineDistance[testPoint, feature.line]; IF dist < tolerance THEN feature.visible _ TRUE ELSE feature.visible _ FALSE; ENDLOOP; FOR seqList: LIST OF FeatureData _ objectBag.seqs, seqList.rest UNTIL seqList = NIL DO feature _ seqList.first; [dist, ----, ----, success] _ NearestSegment[testPoint, feature.tseq, tolerance]; IF success AND dist < tolerance THEN feature.visible _ TRUE ELSE feature.visible _ FALSE; ENDLOOP; FOR circleList: LIST OF FeatureData _ objectBag.radiiCircles, circleList.rest UNTIL circleList = NIL DO feature _ circleList.first; dist _ GGCircles.CircleDistance[testPoint, feature.circle]; IF dist < tolerance THEN feature.visible _ TRUE ELSE feature.visible _ FALSE; ENDLOOP; }; AdjustVisibilityBox: PUBLIC PROC [box: BoundBox, tolerance: REAL, objectBag: ObjectBag] = {}; DrawObjectBag: PUBLIC PROC [dc: Imager.Context, objectBag: ObjectBag, camera: Camera, gargoyleData: GargoyleData] = { feature: FeatureData; Imager.SetStrokeWidth[dc, 1.0]; Imager.SetColor[dc, Imager.MakeGray[0.6]]; FOR slopeLineList: LIST OF FeatureData _ objectBag.slopeLines, slopeLineList.rest UNTIL slopeLineList = NIL DO feature _ slopeLineList.first; IF feature.visible THEN GGShapes.DrawLine[dc, feature.line]; ENDLOOP; FOR seqList: LIST OF FeatureData _ objectBag.seqs, seqList.rest UNTIL seqList = NIL DO feature _ seqList.first; IF feature.visible THEN GGRefresh.DrawSequence[dc, feature.tseq, gargoyleData]; ENDLOOP; FOR circleList: LIST OF FeatureData _ objectBag.radiiCircles, circleList.rest UNTIL circleList = NIL DO feature _ circleList.first; IF feature.visible THEN GGShapes.DrawCircle[dc, feature.circle]; ENDLOOP; FOR dLineList: LIST OF FeatureData _ objectBag.distanceLines, dLineList.rest UNTIL dLineList = NIL DO feature _ dLineList.first; IF feature.visible THEN GGShapes.DrawLine[dc, feature.line]; ENDLOOP; }; DrawObjectBagRegardless: PUBLIC PROC [dc: Imager.Context, objectBag: ObjectBag, camera: Camera, gargoyleData: GargoyleData] = { feature: FeatureData; IF objectBag = NIL THEN RETURN; Imager.SetStrokeWidth[dc, 1.0]; Imager.SetColor[dc, Imager.MakeGray[0.6]]; FOR slopeLineList: LIST OF FeatureData _ objectBag.slopeLines, slopeLineList.rest UNTIL slopeLineList = NIL DO feature _ slopeLineList.first; GGShapes.DrawLine[dc, feature.line]; ENDLOOP; FOR seqList: LIST OF FeatureData _ objectBag.seqs, seqList.rest UNTIL seqList = NIL DO feature _ seqList.first; GGRefresh.DrawSequence[dc, feature.tseq, gargoyleData]; ENDLOOP; FOR circleList: LIST OF FeatureData _ objectBag.radiiCircles, circleList.rest UNTIL circleList = NIL DO feature _ circleList.first; GGShapes.DrawCircle[dc, feature.circle]; ENDLOOP; FOR dLineList: LIST OF FeatureData _ objectBag.distanceLines, dLineList.rest UNTIL dLineList = NIL DO feature _ dLineList.first; GGShapes.DrawLine[dc, feature.line]; ENDLOOP; }; END. ΪGGGravityImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Last edited by Bier on October 17, 1985 3:16:06 pm PDT Contents: Procedures which take a test point and map it to a point on a nearby set of objects. Calls one of the procedures below, depending on the current gravity type. Snapping to Nearby Objects Finds the nearest joint of traj to testPoint (and its distance from testPoint). Here we find both the nearest point and the nearest line. The winning object is simply the closest. Pick the closer of the curve and the point. Here we find both the nearest point and the nearest line. Within innerR, points get preference. Look at the closest point first. If it is within innerR, use it. Otherwise, pick the closer of the curve and the point. IF bestPoint.dist = 99999.0 THEN ERROR; IF bestCurve.dist = 99999.0 THEN ERROR; Building the Object Bag Now for the N2 part. First we find slopeLine x slopeLine intersections. Joint Firing Rules: SlopeLine, Vector, Circle, Vertex The angle (degrees) and direction vector are the global information. [point, jointNum, traj] describes the joint. lineList is used to avoid redundant lines. For now, each slope line only remembers one of the joints which it passes thru. vector is global. [point, jointNum, traj] describes the joint. Not yet implemented. radius is global. [point, jointNum, traj] describes the joint. Each circle remembers all of the joints at its center. For efficiency, this is a Noop. In fact, some sequence of the trajectory will be placed in the objectBag all at once. Segment Firing Rules: FourAngleLines, ColinearLine, Segment degrees is global. [p1, p2, segNum, traj] describes the segment. Not yet implemented. No global information is needed. [p1, p2, segNum, traj] describes the segment. For efficiency, this is a Noop. In fact, some sequence of the trajectory will be placed in the objectBag all at once. See AddTrajectory below. This serves double duty as a set of SegmentAddEdge and VertexAddPoint calls. This serves double duty as a set of SegmentAddEdge and VertexAddPoint calls. Symmetry Firing Rules: SymmetryAddLines, SymmetryAddPoints [group, entity] describes the group and the entity to which it belongs. Not Yet Implemented. [group, entity] describes the group and the entity to which it belongs. Not Yet Implemented. Coordinate Frame Firing Rules: AddPoint AddXLine AddYLine: For now, only the global coordinate frame is considered. Not Yet Implemented. For now, only the global coordinate frame is considered. Add the line x = xVal. Not Yet Implemented. For now, only the global coordinate frame is considered. Add the line y = yVal. Not Yet Implemented. Second level Features: (See AddFeature) Drawing Object Bags Make visible all objects which pass within tolerance of testPoint, and make all others invisible. Draws all objects which have been marked "visible" by AdjustVisibilityPoint or AdjustVisibilityBox. Draws all objects in the object bag regardless of how they have been marked. ΚH˜head1™Icodešœ Οmœ1™˜qMšœA™AM™M˜M˜—š Ÿœžœžœ žœ žœ'˜hMšœO™OMšœ ˜ Jšœ˜Mšœ4˜4Mšœ.˜.J˜Mšœ2˜2Jšœžœ˜"Jšœ ˜ Jšœ˜Jšœ˜Jšœ˜Jšœ#˜#J˜šžœžœžœ˜Mšœ4˜4Jšœžœ˜"Jšœ ˜ Jšœ˜Jšœ˜Jšœ˜Jšœ#˜#J˜—M˜M˜—š’žœžœžœ'˜_Mšœ™M˜M˜—šŸ œžœžœ'˜AJšœL™LJšœ˜Jšœ7˜7Jšœžœ˜"Jšœ˜Jšœ˜Jšœ#˜#J˜—J˜šŸ œž œ*˜BJšœL™LJšœ˜Jšœžœ˜"Jšœ˜Jšœ˜Jšœ#˜#J˜J˜—J˜Mšœ’#™;J˜š ’œžœžœ žœžœ˜_JšœG™GJ™Jšœ˜J˜—š ’œžœžœ žœžœ˜`JšœG™GJ™Jšœ˜J˜—J™Jšœ:™:J™šŸœžœžœ)˜HJ™8J™J˜J˜—šŸœžœžœžœ˜FJ™PJ™J˜J˜—šŸœžœžœžœ˜FJ™PJ™J˜J˜—J™™'J˜—J˜šŸœžœžœJ˜rJšœ˜Jšœžœ˜"Jšœ%˜%Jšœžœ˜Jšœ$˜$Jšœ$˜$Jšœ˜Jšœžœ˜Jšœ˜Jšœ#˜#J˜J˜—šŸœžœžœ˜6Jšžœ˜Jšœ˜—J˜J™J™šŸœžœžœžœ˜`Jšœa™aJšœžœ˜ J˜Jšœ žœ˜š žœžœžœ8žœžœž˜nJšœ˜šœ5˜5Jšžœžœž˜/Jšžœžœ˜——Jšžœ˜š žœ žœžœ,žœ žœž˜VJšœ˜šœ‘œ‘œ@˜QJšžœ žœžœž˜;Jšžœžœ˜——Jšžœ˜š žœ žœžœ7žœžœž˜gJšœ˜šœ;˜;Jšžœžœž˜/Jšžœžœ˜——Jšžœ˜Jšœ˜J˜—šŸœžœžœžœ˜]J˜—šŸ œžœžœ[˜uJšœc™cJ˜J˜Jšœ*˜*š žœžœžœ8žœžœž˜nJšœ˜Jšžœžœ%˜<—Jšžœ˜š žœ žœžœ,žœ žœž˜VJšœ˜Jšžœžœ8˜O—Jšžœ˜š žœ žœžœ7žœžœž˜gJšœ˜Jšžœžœ)˜@—Jšžœ˜š žœ žœžœ7žœ žœž˜eJšœ˜Jšžœžœ%˜<—Jšžœ˜Jšœ˜J˜—šŸœžœžœ[˜JšœL™LJ˜Jšžœ žœžœžœ˜J˜Jšœ*˜*š žœžœžœ8žœžœž˜nJšœ˜Jšœ$˜$—Jšžœ˜š žœ žœžœ,žœ žœž˜VJšœ˜Jšœ7˜7—Jšžœ˜š žœ žœžœ7žœžœž˜gJšœ˜Jšœ(˜(—Jšžœ˜š žœ žœžœ7žœ žœž˜eJšœ˜Jšœ$˜$—Jšžœ˜Jšœ˜—J˜J˜Jšžœ˜J˜—…—VZ{|