GGTraj.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Last edited by Bier on November 13, 1986 4:52:20 pm PST
Contents: Procedures to implement the Traj Slice Class. Trajectories consist of Segments. One motivation for creating this module now is the GGOutlineImpl is too big to compile.
DIRECTORY
GGBasicTypes, GGModelTypes, GGInterfaceTypes, GGSegmentTypes, Imager, ImagerTransformation, IO;
GGTraj: CEDAR DEFINITIONS =
BEGIN
BoundBox: TYPE = GGBasicTypes.BoundBox;
CameraData: TYPE = GGModelTypes.CameraData;
Circle: TYPE = GGBasicTypes.Circle;
GargoyleData: TYPE = GGInterfaceTypes.GargoyleData;
Joint: TYPE = GGSegmentTypes.Joint;
Line: TYPE = GGBasicTypes.Line;
Point: TYPE = GGBasicTypes.Point;
Scene: TYPE = GGModelTypes.Scene;
Segment: TYPE = GGSegmentTypes.Segment;
Sequence: TYPE = GGModelTypes.Sequence;
SelectionClass: TYPE = GGInterfaceTypes.SelectionClass;
Traj: TYPE = GGModelTypes.Traj;
TrajEnd: TYPE = GGModelTypes.TrajEnd;
Vector: TYPE = GGBasicTypes.Vector;
Routine Creation
The lifetime of a trajectory goes something like this: It begins as a single point. The sole purpose of this point is to be an "endpoint" to which the first segment can be attached. Subsequent segments are also added to endpoints. In Gargoyle, trajectories never appear at the top level of a scene; they are always part of an outline. Usually a CreateTraj call will be followed immediately by a GGObjects.CreateOutline call.
Trajectory-Only Routines
CreateTraj: PROC [point: Point] RETURNS [traj: Traj];
Will there be an arrowhead on the lo end of traj? On the hi end?
AddSegment: PROC [traj: Traj, trajEnd: TrajEnd, seg: Segment, segEnd: TrajEnd] RETURNS [success: BOOL];
Moves seg so that the specified end of seg coincides with the specified end of traj. In other words, seg is translated. If success = FALSE, AddSegment sends an error message to GGError and returns.
CloseWithSegment: PROC [traj: Traj, seg: Segment, segEnd: TrajEnd];
Like AddSegment, except that here we rotate, scale, and translate seg as needed so that both of its endpoints coincide with the endpoints of traj (which must not already be closed). The endpoint correspondence is made so that the hi end of traj touches the named (segEnd) end of seg, leaving the other ends to touch each other.
CloseByDistorting: PROC [traj: Traj, distortEnd: TrajEnd];
Move either the first joint or the last joint (depending on the distortEnd argument) to coincide with the other end. This will reduce the number of joints in the trajectory by one (making all sequences which refer to this trajectory obsolete. new traj will have role = fence.
Building Trajectories from Parts
CopyTrajFromRun: PROC [run: Sequence] RETURNS [copy: Traj];
Creates a new trajectory from the consecutive set of segments described by run. All of the segments are copied, so run.traj is untouched.
CopyTrajFromRange: PROC [original: Traj, start: INT, len: INT] RETURNS [piece: Traj];
Like CopyTrajFromRun, but we specify the run with a start segment and a number of segments.
Concat: PROC [fixed: Traj, fixedEnd: TrajEnd, moving: Traj, movingEnd: TrajEnd] RETURNS [longer: Traj];
Creates a new trajectory by concatenating two existing trajectories. Copies are made, so fixed and moving are unchanged. moving is translated so that its movingEnd touches the fixedEnd of fixed.
SpliceIn: PROC [run: Sequence, traj: Traj] RETURNS [newTraj: Traj];
Run describes a part of run.traj that is to be replaced by traj. The result is similar to Rope.Cat[Rope.Substr[...], newRope, Rope.Substr[...]] except that a Traj can be a circular structure.
Orientation
ReverseTraj: PROC [traj: Traj];
IsClockwiseTraj: PROC [traj: Traj] RETURNS [BOOL];
IsClockwiseTrajTransformSeq: PROC [seq: Sequence, transform: ImagerTransformation.Transformation] RETURNS [BOOL];
Fundamental Routines
GetBoundBox: PROC [traj: Traj] RETURNS [bBox: BoundBox];
CopyTraj: PROC [original: Traj] RETURNS [copy: Traj];
Drawing
DrawSequenceFeedback: PROC [dc: Imager.Context, seq: Sequence, normalSeq: Sequence, camera: CameraData, quick: BOOLFALSE, selectClass: SelectionClass ← normal];
DrawTraj: PROC [dc: Imager.Context, traj: Traj];
DrawTrajTransformSeq: PROC [dc: Imager.Context, selSeq: Sequence, transform: ImagerTransformation.Transformation];
DrawSelectionFeedback: PROC [traj: Traj, selectedParts, hotParts: Sequence, dc: Imager.Context, camera: CameraData, dragInProgress, caretIsMoving, hideHot, quick: BOOL];
Transforming
TransformTraj: PROC [traj: Traj, transform: ImagerTransformation.Transformation];
Individually translates each joint and control point of the trajectory.
TranslateTraj: PROC [traj: Traj, vector: Vector];
A convenience routine which does a TransformTraj, where transform is a simple translation.
TransformSequence: PROC [seq: Sequence, transform: ImagerTransformation.Transformation];
Textual Description
Fileout: PROC [f: IO.STREAM, traj: Traj];
Filein: PROC [f: IO.STREAM, version: REAL] RETURNS [traj: Traj, hasCircle: BOOLFALSE];
Accessing Parts
FetchSegment: PROC [traj: Traj, index: NAT] RETURNS [seg: Segment];
FetchJoint: PROC [traj: Traj, index: NAT] RETURNS [joint: Joint];
FetchJointPos: PROC [traj: Traj, index: NAT] RETURNS [point: Point];
LastJointPos: PROC [traj: Traj] RETURNS [point: Point];
SetJointPos: PROC [traj: Traj, index: NAT, newPos: Point];
HiSegment: PROC [traj: Traj] RETURNS [highestIndex: NAT];
Returns traj.segCount-1 for both open and closed trajectories.
HiJoint: PROC [traj: Traj] RETURNS [highestIndex: NAT];
PreviousSegment: PROC [traj: Traj, segNum: NAT] RETURNS [prev: Segment];
PreviousSegmentNum: PROC [traj: Traj, segNum: NAT] RETURNS [prevNum: NAT];
FollowingSegmentNum: PROC [traj: Traj, segNum: NAT] RETURNS [followNum: NAT];
FollowingJoint: PROC [traj: Traj, index: NAT] RETURNS [nextIndex: NAT];
segCount for open trajectories, segCount -1 for closed trajectories.
IsEndJoint: PROC [traj: Traj, index: NAT] RETURNS [BOOL];
Hit Testing
PointsInDescriptor: PROC [seq: Sequence] RETURNS [pointGen: GGModelTypes.PointGenerator];
PointPairsInDescriptor: PROC [seq: Sequence] RETURNS [pointPairGen: GGModelTypes.PointPairGenerator];
NextPoint: PROC [pointGen: GGModelTypes.PointGenerator] RETURNS [pointAndDone: GGModelTypes.PointAndDone];
NextPointPair: PROC [pointGen: GGModelTypes.PointPairGenerator] RETURNS [pointPairAndDone: GGModelTypes.PointPairAndDone];
NearestSegment: PROC [testPoint: Point, seq: Sequence, tolerance: REAL] RETURNS [bestDist: REAL, bestSeg: NAT, bestPoint: Point, success: BOOL];
NearestJoint: PROC [testPoint: Point, seq: Sequence, tolerance: REAL] RETURNS [bestDist: REAL, bestJoint: NAT, bestPoint: Point, success: BOOL];
NearestControlPoint: PROC [testPoint: Point, seq: Sequence, tolerance: REAL] RETURNS [bestDist: REAL, bestSeg: NAT, bestControlPoint: NAT, bestPoint: Point, success: BOOL];
LineIntersection: PROC [seq: Sequence, line: Line] RETURNS [points: LIST OF Point, pointCount: NAT];
CircleIntersection: PROC [seq: Sequence, circle: Circle] RETURNS [points: LIST OF Point, pointCount: NAT];
Style
SetArrows: PROC [traj: Traj, loArrow, hiArrow: BOOL];
Use sparingly:
IndexOfJoint: PROC [joint: Joint, traj: Traj] RETURNS [index: INT];
Returns -1 if it doesn't exist.
IndexOfSegment: PROC [segment: Segment, traj: Traj] RETURNS [index: INT];
END.