DIRECTORY
Feedback, GGBasicTypes, GGBoundBox, GGDescribe, GGModelTypes, GGSegmentTypes, GGSelect, GGSequence, GGTraj, GGUtility, Imager, Rope;

GGSequenceImpl: CEDAR PROGRAM
IMPORTS Feedback, GGBoundBox, GGDescribe, GGSelect, GGSequence, GGTraj, GGUtility
EXPORTS GGSequence = BEGIN

BitMatrix: TYPE = REF BitMatrixObj;
BitMatrixObj: TYPE = GGBasicTypes.BitMatrixObj;
BitVector: TYPE = REF BitVectorObj;
BitVectorObj: TYPE = GGBasicTypes.BitVectorObj;
BoundBox: TYPE = GGBasicTypes.BoundBox;
Color: TYPE = Imager.Color;
ControlPointGenerator: TYPE = REF ControlPointGeneratorObj;
ControlPointGeneratorObj: TYPE = GGModelTypes.ControlPointGeneratorObj;
Joint: TYPE = GGModelTypes.Joint;
JointGenerator: TYPE = REF JointGeneratorObj;
JointGeneratorObj: TYPE = GGModelTypes.JointGeneratorObj;
Point: TYPE = GGBasicTypes.Point;
PointAndDone: TYPE = GGModelTypes.PointAndDone;
SegAndIndex: TYPE = GGSequence.SegAndIndex;
Segment: TYPE = GGSegmentTypes.Segment;
SegmentGenerator: TYPE = REF SegmentGeneratorObj;
SegmentGeneratorObj: TYPE = GGModelTypes.SegmentGeneratorObj;
SelectionClass: TYPE = GGSegmentTypes.SelectionClass;
Sequence: TYPE = REF SequenceObj;
SequenceGenerator: TYPE = REF SequenceGeneratorObj;
SequenceGeneratorObj: TYPE = GGModelTypes.SequenceGeneratorObj;
SequenceObj: TYPE = GGModelTypes.SequenceObj;
SequenceOfReal: TYPE = GGBasicTypes.SequenceOfReal;
SliceDescriptor: TYPE = GGModelTypes.SliceDescriptor;
StrokeEnd: TYPE = Imager.StrokeEnd;
Traj: TYPE = GGModelTypes.Traj;
TrajEnd: TYPE = GGModelTypes.TrajEnd;
TrajPartType: TYPE = GGModelTypes.TrajPartType;

Problem: PUBLIC SIGNAL [msg: Rope.ROPE] = Feedback.Problem;



CreateFromSegments: PUBLIC PROC [traj: Traj, startSeg, endSeg: NAT] RETURNS [seq: Sequence] = {
segCount, temp: NAT;
IF startSeg >= traj.segCount OR endSeg >= traj.segCount THEN ERROR;
IF startSeg = endSeg THEN {seq _ CreateFromSegment[traj, startSeg]; RETURN};
IF traj.role = open THEN {
IF startSeg > endSeg THEN {temp _ startSeg; startSeg _ endSeg; endSeg _ temp};
segCount _ endSeg - startSeg + 1;
}
ELSE {
IF startSeg = (endSeg + 1) MOD traj.segCount THEN {seq _ CreateComplete[traj]; RETURN};
segCount _ ((endSeg - startSeg + traj.segCount) MOD traj.segCount) + 1;
};
seq _ NEW[SequenceObj _ [
traj: traj,
boundBox: GGBoundBox.CopyBoundBox[traj.boundBox],
segments: NewBitVector[traj.segCount],
joints: NewBitVector[GGTraj.HiJoint[traj] + 1],
controlPoints: NewBitMatrix[traj],
segCount: segCount,
controlPointCount: 0, -- will be updated by FillInControlPoints
jointCount: 0 -- will be updated by FillInJoints
]];
IF startSeg < endSeg THEN {
FOR i: NAT IN [startSeg..endSeg] DO
seq.segments[i] _ TRUE;
ENDLOOP;
FillInJoints[seq];
FillInControlPoints[seq];
}
ELSE {
FOR i: NAT IN [startSeg..traj.segCount-1] DO
seq.segments[i] _ TRUE;
ENDLOOP;
FOR i: NAT IN [0..endSeg] DO
seq.segments[i] _ TRUE;
ENDLOOP;
FillInJoints[seq];
FillInControlPoints[seq];
};
};

CreateJointToJoint: PUBLIC PROC [traj: Traj, startJoint, endJoint: NAT] RETURNS [seq: Sequence] = {
temp, hiJoint: NAT;
hiJoint _ GGTraj.HiJoint[traj];
IF traj.role = open AND startJoint = 0 AND endJoint = hiJoint THEN {
seq _ CreateComplete[traj]; RETURN};
IF traj.role = open OR startJoint < endJoint THEN {
IF startJoint > endJoint THEN {temp _ startJoint; startJoint _ endJoint; endJoint _ temp};
IF startJoint < 0 OR endJoint > hiJoint THEN ERROR;
seq _ NEW[SequenceObj _ [
traj: traj,
boundBox: GGBoundBox.CopyBoundBox[traj.boundBox],
segments: NewBitVector[traj.segCount],
joints: NewBitVector[hiJoint+1],
controlPoints: NewBitMatrix[traj],
segCount: endJoint - startJoint,
controlPointCount: 0, -- initialized by FillInControlPoints
jointCount: endJoint - startJoint + 1
]];
FOR i: NAT IN [startJoint..endJoint-1] DO
seq.segments[i] _ TRUE;
seq.joints[i] _ TRUE;
ENDLOOP;
seq.joints[endJoint] _ TRUE;
}
ELSE {
IF startJoint = endJoint THEN {seq _ CreateFromJoint[traj, startJoint]; RETURN};
seq _ NEW[SequenceObj _ [
traj: traj,
boundBox: GGBoundBox.CopyBoundBox[traj.boundBox],
segments: NewBitVector[traj.segCount],
joints: NewBitVector[hiJoint+1],
controlPoints: NewBitMatrix[traj],
segCount: traj.segCount - startJoint + endJoint,
controlPointCount: 0,
jointCount: traj.segCount - startJoint + endJoint + 1
]];
FOR i: NAT IN [startJoint..traj.segCount-1] DO
seq.segments[i] _ TRUE;
seq.joints[i] _ TRUE;
ENDLOOP;
FOR i: NAT IN [0..endJoint-1] DO
seq.segments[i] _ TRUE;
seq.joints[i] _ TRUE;
ENDLOOP;
seq.joints[endJoint] _ TRUE;
};
FillInControlPoints[seq]; -- after all is said and done
};

CreateEmpty: PUBLIC PROC [traj: Traj] RETURNS [seq: Sequence] = {
seq _ NEW[SequenceObj _ [
traj: traj,
boundBox: GGBoundBox.NullBoundBox[],
segments: NewBitVector[traj.segCount],
joints: NewBitVector[GGTraj.HiJoint[traj]+1],
controlPoints: NewBitMatrix[traj],
segCount: 0,
controlPointCount: 0,
jointCount: 0
]];
};

CreateComplete: PUBLIC PROC [traj: Traj] RETURNS [seq: Sequence] = {
jointCount: NAT _ GGTraj.HiJoint[traj] + 1;
seq _ NEW[SequenceObj _ [
traj: traj,
boundBox: IF traj.boundBox = NIL THEN GGBoundBox.NullBoundBox[] ELSE GGBoundBox.CopyBoundBox[traj.boundBox],
segments: NewBitVector[traj.segCount],
joints: NewBitVector[jointCount],
controlPoints: NewBitMatrix[traj],
segCount: traj.segCount,
controlPointCount: 0, -- set by FillInControlPoints
jointCount: jointCount
]];
FOR i: NAT IN [0..GGTraj.HiSegment[traj]] DO
seq.segments[i] _ TRUE;
seq.joints[i] _ TRUE;
ENDLOOP;
seq.joints[jointCount-1] _ TRUE; -- will be redundant for open trajectories
FillInControlPoints[seq]; -- after all is said and done
};

CreateFromJoint: PUBLIC PROC [traj: Traj, jointNum: NAT] RETURNS [seq: Sequence] = {
seq _ CreateEmpty[traj];
seq.joints[jointNum] _ TRUE;
seq.jointCount _ 1;
};

CreateFromSegment: PUBLIC PROC [traj: Traj, segNum: NAT] RETURNS [seq: Sequence] = {
seq _ CreateEmpty[traj];
seq.segments[segNum] _ TRUE;
seq.segCount _ 1;
FillInJoints[seq];
FillInControlPoints[seq]; -- after all is said and done
};

CreateSimpleFromSegment: PUBLIC PROC [traj: Traj, segNum: NAT] RETURNS [seq: Sequence] = {
seq _ CreateEmpty[traj];
seq.segments[segNum] _ TRUE;
seq.segCount _ 1;
};

CreateFromControlPoint: PUBLIC PROC [traj: Traj, segNum: NAT, controlPointNum: NAT] RETURNS [seq: Sequence] = {
seq _ CreateEmpty[traj];
seq.controlPoints[segNum][controlPointNum] _ TRUE;
seq.controlPointCount _ 1;
};

Copy: PUBLIC PROC [seq: Sequence] RETURNS [copy: Sequence] = {
hiSegment: NAT;
IF IsObsolete[seq] THEN ERROR;
hiSegment _ GGTraj.HiSegment[seq.traj];
copy _ NEW[SequenceObj _ [
traj: seq.traj,
boundBox: GGBoundBox.CopyBoundBox[seq.boundBox],
segments: NewBitVector[seq.traj.segCount],
joints: NewBitVector[GGTraj.HiJoint[seq.traj]+1],
controlPoints: NewBitMatrix[seq.traj],
segCount: seq.segCount,
controlPointCount: seq.controlPointCount,
jointCount: seq.jointCount
]];
FOR i: NAT IN [0..hiSegment] DO
cpCount: NAT _ seq.controlPoints[i].len;
copy.segments[i] _ seq.segments[i];
copy.joints[i] _ seq.joints[i];
FOR j: NAT IN [0..cpCount) DO
copy.controlPoints[i][j] _ seq.controlPoints[i][j];
ENDLOOP;
ENDLOOP;
IF seq.traj.role = open THEN copy.joints[hiSegment + 1] _ seq.joints[hiSegment + 1];
};

ComputeBoundBox: PUBLIC PROC [seq: Sequence] RETURNS [box: BoundBox] = {
UpdateBoundBox[seq];
box _ seq.boundBox;
};

UpdateBoundBox:  PUBLIC PROC [seq: Sequence] = {
halfJointSize: REAL = GGModelTypes.halfJointSize + 1;

traj: Traj _ seq.traj;
box: BoundBox _ seq.boundBox;
box.null _ TRUE;

IF seq.jointCount#0 THEN { -- ForAllJointsInTraj
IF traj.role = open THEN { -- ForAllJointsInOpenTraj
IF seq.joints[0] AND NOT seq.segments[0] THEN UpdateBySquare[box, GGTraj.FetchJointPos[traj, 0], halfJointSize]; -- boundary case for joint 0
FOR i: NAT IN [1..traj.segCount-1] DO -- loop for inner joints
IF seq.joints[i] AND NOT seq.segments[i] AND NOT seq.segments[i-1] THEN UpdateBySquare[box, GGTraj.FetchJointPos[traj, i], halfJointSize];
ENDLOOP;
IF seq.joints[traj.segCount] AND NOT seq.segments[traj.segCount-1] THEN UpdateBySquare[box, GGTraj.FetchJointPos[traj, traj.segCount], halfJointSize]; -- boundary case for last joint
}
ELSE { -- ForAllJointsInClosedTraj
FOR i: NAT IN [0..seq.traj.segCount-1] DO 
IF seq.joints[i] AND NOT seq.segments[i] AND NOT seq.segments[(i -1 + seq.traj.segCount) MOD seq.traj.segCount] THEN UpdateBySquare[box, GGTraj.FetchJointPos[traj, i], halfJointSize];
ENDLOOP;
};
};
IF seq.controlPointCount#0 THEN { -- if some control point is in the sequence then ...
FOR i: NAT IN [0..seq.traj.segCount) DO  -- for each segment in the traj
IF NOT seq.segments[i] AND SomeSegCPInSeq[i, seq] THEN { -- if this segment is not already in the sequence and any control point of this segment is selected then ...
seg: Segment _ GGTraj.FetchSegment[traj, i]; -- get the segment
cpCount: NAT _ seq.controlPoints[i].len;
FOR j: NAT IN [0..cpCount) DO -- for all control points in the segment
IF seq.controlPoints[i][j] THEN { -- if this cp is in the sequence
point: Point _ seg.class.controlPointGet[seg, j];
UpdateBySquare[box, point, halfJointSize]; -- update the bounding box with the control point
};
ENDLOOP;
};
ENDLOOP;
};
IF seq.segCount#0 THEN { -- if some segment is in the sequence
FOR s: NAT IN [0..seq.traj.segCount-1] DO  -- for each segment in the traj
IF seq.segments[s] THEN { -- if this segment is in the sequence
seg: Segment _ GGTraj.FetchSegment[traj, s]; -- get the segment
GGBoundBox.EnlargeByBox[bBox: box, by: seg.class.boundBox[seg]]; -- update the bounding box with the segment
};
ENDLOOP;
};
};

ComputeTightBox: PUBLIC PROC [seq: Sequence] RETURNS [box: BoundBox] = {
halfJointSize: REAL = GGModelTypes.halfJointSize + 1;

traj: Traj _ seq.traj;
box _ GGBoundBox.NullBoundBox[];

IF seq.segCount#0 THEN {
FOR s: NAT IN [0..seq.traj.segCount-1] DO  -- for each segment in the traj
IF seq.segments[s] THEN { -- if this segment is in the sequence
seg: Segment _ GGTraj.FetchSegment[traj, s];
GGBoundBox.EnlargeByBox[bBox: box, by: seg.class.tightBox[seg]];
};
ENDLOOP;
};
seq.boundBox _ box;  -- and, finally, store the new result
};
Describe: PUBLIC PROC [seq: Sequence] RETURNS [rope: Rope.ROPE] = {
segNum, cpNum: NAT;
segCount: NAT _ seq.segCount;
jointCount: NAT _ seq.jointCount;
cpCount: NAT _ seq.controlPointCount;
SELECT TRUE FROM
segCount=1 => { -- single segment selected. Describe it
segGen: SegmentGenerator _ GGSequence.SegmentsInSequence[seq];
rope _ GGDescribe.DescribeSegment[seq.traj,
GGSequence.NextSegmentAndIndex[segGen].index];
};
segCount=0 AND cpCount=1 => { -- single CP selected. Describe it
cpGen: ControlPointGenerator _ GGSequence.ControlPointsInSequence[seq];
[segNum, cpNum] _ GGSequence.NextSegNumAndCPNum[cpGen];
rope _ GGDescribe.DescribeControlPoint[seq.traj, segNum, cpNum];
};
segCount=0 AND cpCount=0 AND jointCount=1 => { -- single joint selected. Describe it
jointGen: JointGenerator _ GGSequence.JointsInSequence[seq];
rope _ GGDescribe.DescribeJoint[seq.traj, GGSequence.NextJoint[jointGen]];
};
ENDCASE => rope _ GGDescribe.DescribeSequence[seq];
};



CopyInto: PUBLIC PROC [to: Sequence, from: Sequence] = {
hiSegment: NAT;
IF IsObsolete[from] THEN ERROR;
hiSegment _ GGTraj.HiSegment[from.traj];
to.traj _ from.traj;
to.boundBox _ NIL;
FOR i: NAT IN [0..GGTraj.HiSegment[from.traj]] DO
cpCount: NAT _ from.controlPoints[i].len;
to.segments[i] _ from.segments[i];
FOR j: NAT IN [0..cpCount) DO
to.controlPoints[i][j] _ from.controlPoints[i][j]; -- KAP. April 4, 1986
ENDLOOP;
ENDLOOP;
FOR i: NAT IN [0..GGTraj.HiJoint[from.traj]] DO
to.joints[i] _ from.joints[i];
ENDLOOP;
to.segCount _ from.segCount;
to.controlPointCount _ from.controlPointCount;
to.jointCount _ from.jointCount;
};

FillInJoints: PUBLIC PROC [seq: Sequence] = {
jointCount: NAT _ 0;
IF IsObsolete[seq] THEN ERROR;
IF seq.segCount=0 THEN RETURN; -- can't do anything. seq may have a single joint or CP
IF seq.traj.role = open THEN {
FOR i: NAT IN [0..seq.traj.segCount-1] DO
IF seq.segments[i] THEN {seq.joints[i] _ TRUE; seq.joints[i+1] _ TRUE};
ENDLOOP;
}
ELSE {
FOR i: NAT IN [0..seq.traj.segCount-1] DO
IF seq.segments[i] THEN {seq.joints[i] _ TRUE; seq.joints[(i+1) MOD seq.traj.segCount] _ TRUE;};
ENDLOOP;
};
FOR i: NAT IN [0..GGTraj.HiJoint[seq.traj]] DO
IF seq.joints[i] THEN jointCount _ jointCount + 1;
ENDLOOP;
seq.jointCount _ jointCount;
};

FillInControlPoints: PUBLIC PROC [seq: Sequence] = { -- a sequence with segs and joints filled in. IF there are segments then fill in all the control points for each segment in the sequence, and calculate the new control point count.
segGen: SegmentGenerator;
next: SegAndIndex;
cpCount: NAT;
IF seq.segCount=0 THEN RETURN; -- can't do anything. seq may have a single joint or CP.
seq.controlPointCount _ 0;
segGen _ SegmentsInSequence[seq];
FOR next _ NextSegmentAndIndex[segGen], NextSegmentAndIndex[segGen] UNTIL next.seg=NIL DO
IF NOT seq.segments[next.index] THEN ERROR; -- seq must have this seg, by definition
cpCount _ next.seg.class.controlPointCount[next.seg]; -- number of cps in this segment
FOR j: NAT IN [0..cpCount) DO -- fill them all in
seq.controlPoints[next.index][j] _ TRUE;
seq.controlPointCount _ seq.controlPointCount + 1;
ENDLOOP;
ENDLOOP;
};

TrimSelectedParts: PUBLIC PROC [seq: Sequence, selectedList: LIST OF SliceDescriptor] = {
selSeq: Sequence;
selSeq _ GGSelect.FindSequenceInList[seq.traj, selectedList];
IF selSeq = NIL THEN RETURN; -- no selected parts, so nothing to trim
FOR i: NAT IN [0..GGTraj.HiSegment[seq.traj]] DO
FOR j: NAT IN [0..seq.controlPoints[i].len) DO
IF selSeq.controlPoints[i][j] AND seq.controlPoints[i][j] THEN {
seq.controlPoints[i][j] _ FALSE;
seq.controlPointCount _ seq.controlPointCount - 1;
};
ENDLOOP;
IF selSeq.segments[i] AND seq.segments[i] THEN {
seq.segments[i] _ FALSE;
seq.segCount _ seq.segCount - 1;
};
ENDLOOP;
FOR i: NAT IN [0..GGTraj.HiJoint[seq.traj]] DO
IF selSeq.joints[i] AND seq.joints[i] THEN {
seq.joints[i] _ FALSE;
seq.jointCount _ seq.jointCount -1;
};
ENDLOOP;
};

TrimSelectedControlPointSegments: PUBLIC PROC [seq: Sequence, selectedList: LIST OF SliceDescriptor] = {
SomeSelectedCP: PROC [i: NAT] RETURNS [BOOL] = {
FOR j: NAT IN [0..selSeq.controlPoints[i].len) DO
IF selSeq.controlPoints[i][j] THEN RETURN[TRUE];
ENDLOOP;
RETURN[FALSE];
};
selSeq: Sequence;
selSeq _ GGSelect.FindSequenceInList[seq.traj, selectedList];
IF selSeq = NIL THEN RETURN; -- no CPs selected, so nothing to trim
FOR i: NAT IN [0..GGTraj.HiSegment[seq.traj]] DO
IF seq.segments[i] AND SomeSelectedCP[i] THEN {
seq.segments[i] _ FALSE;
seq.segCount _ seq.segCount - 1;
};
ENDLOOP;
};

AddNonSelectedControlPointSegments: PUBLIC PROC [seq: Sequence, selected: Sequence] = {
SomeSelectedCP: PROC [i: NAT] RETURNS [BOOL] = {
FOR j: NAT IN [0..selected.controlPoints[i].len) DO
IF selected.controlPoints[i][j] THEN RETURN[TRUE];
ENDLOOP;
RETURN[FALSE];
};
IF selected = NIL THEN RETURN; -- no CPs selected, so nothing to add
FOR i: NAT IN [0..GGTraj.HiSegment[seq.traj]] DO
IF NOT seq.segments[i] AND NOT selected.segments[i] AND SomeSelectedCP[i] THEN {
seq.segments[i] _ TRUE;
seq.segCount _ seq.segCount + 1;
};
ENDLOOP;
};

AddNonSelectedJointSegments: PUBLIC PROC [seq: Sequence, selected: Sequence] = {
SomeSelectedJoint: PROC [i: NAT] RETURNS [BOOL] = {
RETURN[
selected.joints[i] OR selected.joints[GGTraj.FollowingJoint[seq.traj, i]]
];
};
IF selected = NIL THEN RETURN; -- no joints selected, so nothing to add
FOR i: NAT IN [0..GGTraj.HiSegment[seq.traj]] DO
IF NOT seq.segments[i] AND NOT selected.segments[i] AND SomeSelectedJoint[i] THEN {
seq.segments[i] _ TRUE;
seq.segCount _ seq.segCount + 1;
};
ENDLOOP;
};

TrimSelectedJointSegments: PUBLIC PROC [seq: Sequence, selectedList: LIST OF SliceDescriptor] = {
SomeSelectedJoint: PROC [i: NAT] RETURNS [BOOL] = {
RETURN[
selSeq.joints[i] OR selSeq.joints[GGTraj.FollowingJoint[seq.traj, i]]
];
};
selSeq: Sequence;
selSeq _ GGSelect.FindSequenceInList[seq.traj, selectedList];
IF selSeq = NIL THEN RETURN; -- no joints selected, so nothing to trim
FOR i: NAT IN [0..GGTraj.HiSegment[seq.traj]] DO
IF seq.segments[i] AND SomeSelectedJoint[i] THEN {
seq.segments[i] _ FALSE;
seq.segCount _ seq.segCount - 1;
};
ENDLOOP;
};


TrimDanglingSegments: PUBLIC PROC [seq: Sequence] = {
runGen: SequenceGenerator;
runCount: NAT;
haveTrimmed: BOOL;
firstSegNum, firstJointNum, lastSegNum, lastJointNum: INT;

IF IsComplete[seq] THEN RETURN; -- nothing is dangling if all joints are included
[runGen, runCount] _ RunsInSequence[seq];
FOR run: Sequence _ NextSequence[runGen], NextSequence[runGen] UNTIL run = NIL DO
haveTrimmed _ FALSE;
firstSegNum _ FirstSegNum[run];
firstJointNum _ FirstJointNum[run];
lastSegNum _ LastSegNum[run, firstSegNum];
lastJointNum _ LastJointNum[run, firstJointNum];
IF firstJointNum = -1 THEN {
IF firstSegNum = -1 THEN ERROR; -- there must be something in the run
IF NOT seq.segments[firstSegNum] THEN ERROR;
seq.segments[firstSegNum] _ FALSE;
seq.segCount _ seq.segCount - 1;
LOOP;
};
IF lastJointNum = -1 THEN ERROR; -- if there was a first joint, there must be a last one (it is equal to the first joint if there is only one).
IF firstSegNum = -1 THEN LOOP; -- there are no segments so there is nothing to trim
IF lastSegNum = -1 THEN ERROR; -- if there was a first segment, there must be a last.
IF firstJointNum # firstSegNum THEN {
IF NOT seq.segments[lastSegNum] THEN ERROR;
seq.segments[firstSegNum] _ FALSE;
seq.segCount _ seq.segCount - 1;
haveTrimmed _ TRUE;
};
IF ((seq.traj.role = open AND lastSegNum + 1 # lastJointNum) OR
(seq.traj.role # open AND ((lastSegNum + 1) MOD seq.traj.segCount) # lastJointNum))
AND (NOT haveTrimmed OR lastSegNum # firstSegNum) THEN {
IF NOT seq.segments[lastSegNum] THEN ERROR;
seq.segments[lastSegNum] _ FALSE;
seq.segCount _ seq.segCount - 1;
};
ENDLOOP;
};

TrimControlPointSegments: PUBLIC PROC [seq: Sequence, controlPointOn: BOOL] = {
SomeIncludedCP: PROC [i: NAT] RETURNS [BOOL] = {
FOR j: NAT IN [0..seq.controlPoints[i].len) DO
IF seq.controlPoints[i][j] = controlPointOn THEN RETURN[TRUE];
ENDLOOP;
RETURN[FALSE];
};
IF IsObsolete[seq] THEN ERROR;
FOR i: NAT IN [0..GGTraj.HiSegment[seq.traj]] DO
IF seq.segments[i] AND SomeIncludedCP[i] THEN {
seq.segments[i] _ FALSE;
seq.segCount _ seq.segCount - 1;
};
ENDLOOP;
};

TrimJointSegments: PUBLIC PROC [seq: Sequence, jointOn: BOOL] = {
SomeSelectedJoint: PROC [i: NAT] RETURNS [BOOL] = {
RETURN[
seq.joints[i] = jointOn OR seq.joints[GGTraj.FollowingJoint[seq.traj, i]] = jointOn
];
};
FOR i: NAT IN [0..GGTraj.HiSegment[seq.traj]] DO
IF seq.segments[i] AND SomeSelectedJoint[i] THEN {
seq.segments[i] _ FALSE;
seq.segCount _ seq.segCount - 1;
};
ENDLOOP;
};

DDifference: PUBLIC PROC [mutable, negative: Sequence] = {
hiJoint: NAT;
IF IsObsolete[mutable] OR IsObsolete[negative] THEN ERROR;
IF mutable.traj # negative.traj THEN ERROR;
FOR i: NAT IN [0..GGTraj.HiSegment[mutable.traj]] DO
cpCount: NAT _ mutable.controlPoints[i].len;
mutable.segments[i] _ mutable.segments[i] AND NOT negative.segments[i];
FOR j: NAT IN [0..cpCount) DO
mutable.controlPoints[i][j] _ mutable.controlPoints[i][j] AND NOT negative.controlPoints[i][j];
ENDLOOP;
mutable.joints[i] _ mutable.joints[i] AND NOT negative.joints[i];
ENDLOOP;
hiJoint _ GGTraj.HiJoint[mutable.traj];
mutable.joints[hiJoint] _ mutable.joints[hiJoint] AND NOT negative.joints[hiJoint];
mutable.segCount _ CountSegments[mutable];
mutable.jointCount _ CountJoints[mutable];
mutable.controlPointCount _ CountControlPoints[mutable];
};

NewBitMatrix: PROC [traj: Traj] RETURNS [bitMatrix: BitMatrix] = {
j: NAT _ 0;
segGen: SegmentGenerator _ GGSequence.SegmentsInTraj[traj];
bitMatrix _ NEW[BitMatrixObj[traj.segCount]];
FOR seg: Segment _ GGSequence.NextSegment[segGen], GGSequence.NextSegment[segGen] UNTIL seg = NIL DO
bitMatrix[j] _ NewBitVector[seg.class.controlPointCount[seg]];
j _ j+1;
ENDLOOP;
};

NewBitVector: PROC [length: NAT] RETURNS [bitVec: BitVector] = {
bitVec _ NEW[BitVectorObj[length]];
SetAllBits[bitVec, FALSE];
};
SetAllBits: PROC [bitVec: BitVector, bool: BOOL] = {
FOR i: NAT IN [0..bitVec.len) DO
bitVec[i] _ bool;
ENDLOOP;
};

SomeSegCPInSeq: PROC [segNum: NAT, seq: Sequence] RETURNS [BOOL] = {
cpCount: NAT _ seq.controlPoints[segNum].len;
FOR j: NAT IN [0..cpCount) DO
IF seq.controlPoints[segNum][j] THEN RETURN[TRUE];
ENDLOOP;
RETURN[FALSE];
};

UpdateBySquare: PROC [bBox: BoundBox, p: Point, halfSquareSide: REAL]  ~ { -- updates the accumulating bBox by a joint or CP

pHalf: REAL _ halfSquareSide + 1;
loX, loY, hiX, hiY: REAL;
IF bBox.infinite THEN RETURN;
loX _ p.x-pHalf;  loY _ p.y-pHalf; hiX _ p.x+pHalf;  hiY _ p.y+pHalf;
IF bBox.null THEN {
bBox.loX _ loX;
bBox.hiX _ hiX;
bBox.loY _ loY;
bBox.hiY _ hiY;
bBox.null _ FALSE;
RETURN;
};
IF loX < bBox.loX THEN bBox.loX _ loX;
IF hiX > bBox.hiX THEN bBox.hiX _ hiX;
IF loY < bBox.loY THEN bBox.loY _ loY;
IF hiY > bBox.hiY THEN bBox.hiY _ hiY;
};

Union: PUBLIC PROC [a, b: Sequence] RETURNS [union: Sequence] = {
hiJoint: NAT;
IF IsObsolete[a] OR IsObsolete[b] THEN ERROR;
IF a.traj # b.traj THEN ERROR;
union _ CreateEmpty[a.traj];
FOR i: NAT IN [0..GGTraj.HiSegment[a.traj]] DO
cpCount: NAT _ a.controlPoints[i].len;
union.segments[i] _ a.segments[i] OR b.segments[i];
FOR j: NAT IN [0..cpCount) DO
union.controlPoints[i][j] _ a.controlPoints[i][j] OR b.controlPoints[i][j];
ENDLOOP;
union.joints[i] _ a.joints[i] OR b.joints[i];
ENDLOOP;
hiJoint _ GGTraj.HiJoint[a.traj];
union.joints[hiJoint] _ a.joints[hiJoint] OR b.joints[hiJoint];
union.segCount _ CountSegments[union];
union.jointCount _ CountJoints[union];
union.controlPointCount _ CountControlPoints[union];
};

Intersection: PUBLIC PROC [a, b: Sequence] RETURNS [intersection: Sequence] = {
hiJoint: NAT;
IF IsObsolete[a] OR IsObsolete[b] THEN ERROR;
IF a.traj # b.traj THEN ERROR;
intersection _ CreateEmpty[a.traj];
FOR i: NAT IN [0..GGTraj.HiSegment[a.traj]] DO
cpCount: NAT _ a.controlPoints[i].len;
intersection.segments[i] _ a.segments[i] AND b.segments[i];
FOR j: NAT IN [0..cpCount) DO
intersection.controlPoints[i][j]_ a.controlPoints[i][j] AND b.controlPoints[i][j];
ENDLOOP;
intersection.joints[i] _ a.joints[i] AND b.joints[i];
ENDLOOP;
hiJoint _ GGTraj.HiJoint[a.traj];
intersection.joints[hiJoint] _ a.joints[hiJoint] AND b.joints[hiJoint];
intersection.segCount _ CountSegments[intersection];
intersection.jointCount _ CountJoints[intersection];
intersection.controlPointCount _ CountControlPoints[intersection];
};

Difference: PUBLIC PROC [a, b: Sequence] RETURNS [aMinusB: Sequence] = {
hiJoint: NAT;
IF IsObsolete[a] OR IsObsolete[b] THEN ERROR;
IF a.traj # b.traj THEN ERROR;
aMinusB _ CreateEmpty[a.traj];
FOR i: NAT IN [0..GGTraj.HiSegment[a.traj]] DO
cpCount: NAT _ a.controlPoints[i].len;
aMinusB.segments[i] _ a.segments[i] AND NOT b.segments[i];
FOR j: NAT IN [0..cpCount) DO
aMinusB.controlPoints[i][j] _ a.controlPoints[i][j] AND NOT b.controlPoints[i][j];
ENDLOOP;
aMinusB.joints[i] _ a.joints[i] AND NOT b.joints[i];
ENDLOOP;
hiJoint _ GGTraj.HiJoint[a.traj];
aMinusB.joints[hiJoint] _ a.joints[hiJoint] AND NOT b.joints[hiJoint];
aMinusB.segCount _ CountSegments[aMinusB];
aMinusB.jointCount _ CountJoints[aMinusB];
aMinusB.controlPointCount _ CountControlPoints[aMinusB];
};

TrajMovingParts: PUBLIC PROC [seq: Sequence] RETURNS [background, overlay, rubber, drag: Sequence] = {
background _ NIL;
drag _ Copy[seq];
rubber _ FindRubberFromSelected[seq];
overlay _ CreateComplete[seq.traj];
DDifference[overlay, drag];
DDifference[overlay, rubber];
};
FindRubberFromSelected: PROC [seq: Sequence] RETURNS [rubber: Sequence] = {
rubber _ CreateEmpty[seq.traj];
AddNonSelectedControlPointSegments[rubber, seq];
AddNonSelectedJointSegments[rubber, seq];
};

Augment: PUBLIC PROC [seq: Sequence, trajEnd: TrajEnd, extend: BOOL] RETURNS [bigger: Sequence] = {
IF seq.traj.role = hole OR seq.traj.role = fence THEN {
bigger _ AugmentClosed[seq, extend];
RETURN;
};
bigger _ CreateEmpty[seq.traj];
bigger.segCount _ seq.segCount;
bigger.controlPointCount _ seq.controlPointCount;
bigger.jointCount _ seq.jointCount;
IF trajEnd = hi THEN {
FOR i: NAT IN [0..seq.segments.len) DO
cpCount: NAT _ seq.controlPoints[i].len;
bigger.segments[i] _ seq.segments[i];
bigger.joints[i] _ seq.joints[i];
FOR j: NAT IN [0..cpCount) DO
bigger.controlPoints[i][j] _ seq.controlPoints[i][j];
ENDLOOP;
ENDLOOP;
IF seq.joints[seq.joints.len - 1] THEN { -- final joint included ??
bigger.joints[seq.joints.len - 1] _ TRUE; -- yes, so include it in bigger
IF extend THEN {
bigger.segments[seq.segments.len] _ TRUE;
bigger.joints[seq.joints.len] _ TRUE;
SetAllBits[bigger.controlPoints[seq.segments.len], TRUE];
bigger.segCount _ bigger.segCount + 1;
bigger.jointCount _ bigger.jointCount + 1;
bigger.controlPointCount _ bigger.controlPointCount + bigger.controlPoints[seq.segments.len].len
};
};
}
ELSE {
FOR i: NAT IN [0..seq.segments.len) DO
cpCount: NAT _ seq.controlPoints[i].len;
bigger.segments[i+1] _ seq.segments[i];
bigger.joints[i+2] _ seq.joints[i+1];
FOR j: NAT IN [0..cpCount) DO
bigger.controlPoints[i+1][j] _ seq.controlPoints[i][j];
ENDLOOP;
ENDLOOP;
IF seq.joints[0] THEN { -- first joint included ??
bigger.joints[1] _ TRUE; -- yes, so include it in bigger
IF extend THEN {
bigger.segments[0] _ TRUE;
bigger.joints[0] _ TRUE;
SetAllBits[bigger.controlPoints[0], TRUE];
bigger.segCount _ bigger.segCount + 1;
bigger.jointCount _ bigger.jointCount + 1;
bigger.controlPointCount _ bigger.controlPointCount + bigger.controlPoints[0].len
};
};
};
};

AugmentClosed: PUBLIC PROC [seq: Sequence, extend: BOOL] RETURNS [bigger: Sequence] = {
bigger _ NEW[SequenceObj _ [
traj: seq.traj,
boundBox: GGBoundBox.NullBoundBox[],
segments: NewBitVector[seq.segments.len+1],
joints: NewBitVector[seq.joints.len],
controlPoints: NewBitMatrix[seq.traj], -- new BitMatrix one segment bigger
segCount: seq.segCount,
controlPointCount: seq.controlPointCount,
jointCount: seq.jointCount
]];
FOR i: NAT IN [0..seq.segments.len) DO
cpCount: NAT _ seq.controlPoints[i].len;
bigger.segments[i] _ seq.segments[i];
bigger.joints[i] _ seq.joints[i];
FOR j: NAT IN [0..cpCount) DO
bigger.controlPoints[i][j] _ seq.controlPoints[i][j]; -- KAP. April 4, 1986
ENDLOOP;
ENDLOOP;
IF seq.joints[seq.joints.len - 1] THEN { -- final joint included ??
bigger.joints[seq.joints.len - 1] _ TRUE; -- yes, so include it in bigger
IF extend THEN {
bigger.segments[seq.segments.len] _ TRUE;
SetAllBits[bigger.controlPoints[seq.segments.len], TRUE];
bigger.segCount _ bigger.segCount + 1;
bigger.controlPointCount _ bigger.controlPointCount + bigger.controlPoints[seq.segments.len].len;
};
};
};

AugmentParts: PUBLIC PROC [seq: Sequence, selectClass: SelectionClass] = {
IF selectClass = normal THEN {
FillInJoints[seq];
FillInControlPoints[seq];
}
ELSE {
FillInControlPoints[seq];
};
};


IsObsolete: PUBLIC PROC [seq: Sequence] RETURNS [BOOL] = {
j: NAT _ 0;
segGen: SegmentGenerator;
IF seq.segments.len # seq.traj.segCount THEN RETURN[TRUE];
IF seq.joints.len # (GGTraj.HiJoint[seq.traj] + 1) THEN RETURN[TRUE];
segGen _ SegmentsInTraj[seq.traj];
FOR nextSeg: Segment _ GGSequence.NextSegment[segGen], GGSequence.NextSegment[segGen] UNTIL nextSeg=NIL DO
IF nextSeg.class.controlPointCount[nextSeg]#seq.controlPoints[j].len THEN RETURN[TRUE];
j _ j+1;
ENDLOOP;
RETURN[FALSE];
};

IsEmpty: PUBLIC PROC [seq: Sequence] RETURNS [BOOL] = {
RETURN[seq.jointCount = 0 AND seq.segCount = 0 AND seq.controlPointCount = 0];
};

ControlPointsOnly: PUBLIC PROC [seq: Sequence] RETURNS [BOOL] = {
RETURN[seq.jointCount = 0 AND seq.segCount = 0];
};

IsComplete: PUBLIC PROC [seq: Sequence] RETURNS [BOOL] = {
RETURN[seq.segCount = seq.traj.segCount AND
(seq.jointCount = GGTraj.HiJoint[seq.traj] + 1)];
};

Overlap: PUBLIC PROC [seq1, seq2: Sequence] RETURNS [BOOL] = {
IF IsObsolete[seq1] OR IsObsolete[seq2] THEN ERROR;
IF seq1.traj # seq2.traj THEN ERROR;
FOR i: NAT IN [0..GGTraj.HiSegment[seq1.traj]] DO
IF seq1.segments[i] AND seq2.segments[i] THEN RETURN[TRUE];
ENDLOOP;
FOR i: NAT IN [0..GGTraj.HiJoint[seq1.traj]] DO
IF seq1.joints[i] AND seq2.joints[i] THEN RETURN[TRUE];
ENDLOOP;
FOR i: NAT IN [0..GGTraj.HiSegment[seq1.traj]] DO
cpCount: NAT _ seq1.controlPoints[i].len;
FOR j: NAT IN [0..cpCount) DO
IF seq1.controlPoints[i][j] AND seq2.controlPoints[i][j] THEN RETURN[TRUE];
ENDLOOP;
ENDLOOP;
RETURN[FALSE];
};

CountSegments: PROC [seq: Sequence] RETURNS [segCount: NAT] = {
segCount _ 0;
FOR i: NAT IN [0..GGTraj.HiSegment[seq.traj]] DO
IF seq.segments[i] THEN segCount _ segCount + 1;
ENDLOOP;
};

CountJoints: PROC [seq: Sequence] RETURNS [jointCount: NAT] = {
jointCount _ 0;
FOR i: NAT IN [0..GGTraj.HiJoint[seq.traj]] DO
IF seq.joints[i] THEN jointCount _ jointCount + 1;
ENDLOOP;
};

CountControlPoints: PROC [seq: Sequence] RETURNS [count: NAT _ 0] = {
FOR i: NAT IN [0..GGTraj.HiSegment[seq.traj]] DO
cpCount: NAT _ seq.controlPoints[i].len;
FOR j: NAT IN [0..cpCount) DO
IF seq.controlPoints[i][j] THEN count _ count + 1;
ENDLOOP;
ENDLOOP;
};

ContainsSegment: PUBLIC PROC [seq: Sequence, segNum: NAT] RETURNS [BOOL] = {
RETURN[seq.segments[segNum]];
};

ContainsSomeSegment: PUBLIC PROC [seq: Sequence] RETURNS [BOOL] = {
RETURN[seq.segCount > 0];
};

ContainsSegmentParts: PUBLIC PROC [seq: Sequence, segNum: NAT] RETURNS [BOOL] = {
RETURN [seq#NIL AND (seq.segments[segNum] OR
NOT GGUtility.AllFalse[seq.controlPoints[segNum]] OR
seq.joints[segNum] OR
seq.joints[IF seq.traj.role=open THEN segNum+1 ELSE (segNum+1) MOD seq.traj.segCount]) ];
};

FirstSegment: PROC [seq: Sequence] RETURNS [index: NAT] ~ {
hiSeg: NAT _ GGTraj.HiSegment[seq.traj];
IF IsObsolete[seq] THEN ERROR;
IF seq.traj.role = open THEN {
FOR i: NAT IN [0..hiSeg] DO
IF seq.segments[i] THEN GOTO Found;
REPEAT
Found => index _ i;
FINISHED => SIGNAL Problem[msg: "the first run begins with a segment."];
ENDLOOP;
}
ELSE {
FOR i: NAT IN [0..hiSeg] DO
IF NOT seq.segments[(i - 1 + seq.traj.segCount) MOD seq.traj.segCount] AND seq.joints[i] THEN GOTO Found;
IF NOT seq.joints[i] AND seq.segments[i] THEN GOTO Found;
REPEAT
Found => index _ i;
FINISHED => SIGNAL Problem[msg: "there is no break in the sequence."];
ENDLOOP;
};
};

FirstSegNum: PUBLIC PROC [run: Sequence] RETURNS [INT] = {
IF run.segCount = 0 THEN RETURN[-1];
IF GGSequence.IsComplete[run] THEN RETURN[0];  --DJK, to make work with complete, closed sequences
RETURN[FirstTransitionInRun[run]];
};

LastSegNum: PUBLIC PROC [run: Sequence, firstSegNum: INT] RETURNS [lastNum: INT] = {
IF firstSegNum = -1 THEN RETURN[-1];
IF run.traj.role = open THEN lastNum _ firstSegNum + run.segCount - 1
ELSE lastNum _ (firstSegNum + run.segCount - 1 + run.traj.segCount) MOD run.traj.segCount;
};

ContainsJoint: PUBLIC PROC [seq: Sequence, jointNum: NAT] RETURNS [BOOL] = {
RETURN[seq.joints[jointNum]];
};

FirstJointNum: PUBLIC PROC [run: Sequence] RETURNS [INT] = {
firstSeg, nextJoint: NAT;
IF run.jointCount = 0 THEN RETURN[-1];
firstSeg _ FirstTransitionInRun[run];
IF run.joints[firstSeg] THEN RETURN[firstSeg] ELSE {
IF run.traj.role = open THEN {
IF run.joints[firstSeg + 1] THEN RETURN[firstSeg + 1]
ELSE ERROR Problem[msg: "Broken invariant."];
}
ELSE {
nextJoint _ GGTraj.FollowingJoint[run.traj, firstSeg];
IF run.joints[nextJoint] THEN RETURN[nextJoint]
ELSE ERROR Problem[msg: "Broken invariant."];
};
};
};

LastJointNum: PUBLIC PROC [run: Sequence, firstJointNum: INT] RETURNS [lastNum: INT] = {
IF firstJointNum = -1 THEN RETURN[-1];
IF run.traj.role = open THEN lastNum _ firstJointNum + run.jointCount - 1
ELSE lastNum _ (firstJointNum + run.jointCount - 1 + run.traj.segCount) MOD run.traj.segCount;
};

LastSegAndJoint: PUBLIC PROC [traj: Traj, trajEnd: TrajEnd] RETURNS [segAndJoint: Sequence] = {
segAndJoint _ CreateEmpty[traj];
IF traj.role = open THEN {
segAndJoint.jointCount _ 1;
segAndJoint.segCount _ 1;
IF trajEnd = lo THEN {
segAndJoint.segments[0] _ TRUE;
segAndJoint.joints[0] _ TRUE;
}
ELSE {
hiSeg: NAT _ GGTraj.HiSegment[traj];
segAndJoint.segments[hiSeg] _ TRUE;
segAndJoint.joints[hiSeg+1] _ TRUE;
};
}
ELSE ERROR;
};

UnpackOnePointSequence: PUBLIC PROC [seq: Sequence] RETURNS [isACP: BOOL, segNum, cpNum, jointNum: NAT] = {
seg: Segment;
FOR i: NAT IN [0..GGTraj.HiJoint[seq.traj]] DO
IF seq.joints[i] THEN {
isACP _ FALSE;
segNum _ 999;
cpNum _ 999;
jointNum _ i;
RETURN;
}
ENDLOOP;
FOR i: NAT IN [0..GGTraj.HiSegment[seq.traj]] DO
seg _ GGTraj.FetchSegment[seq.traj, i];
FOR j: NAT IN [0..seg.class.controlPointCount[seg] - 1] DO
IF seq.controlPoints[i][j] THEN {
isACP _ TRUE;
segNum _ i;
cpNum _ j;
jointNum _ 999;
RETURN;
}
ENDLOOP;
ENDLOOP;
ERROR;
};

UnpackOneSegmentSequence: PUBLIC PROC [seq: Sequence] RETURNS [segNum: NAT] = {
FOR i: NAT IN [0..GGTraj.HiSegment[seq.traj]] DO
IF seq.segments[i] THEN {
segNum _ i;
RETURN;
}
ENDLOOP;
ERROR;
};

UnpackSimpleSequence: PUBLIC PROC [seq: Sequence] RETURNS [success: BOOL, partType: TrajPartType _ none, traj: Traj, joint: Joint _ NIL, jointNum: NAT _ 999, cp: Point _ [0,0], cpNum: NAT _ 999, seg: Segment _ NIL, segNum: NAT _ 999] = {
jointFound, cpFound, segFound: BOOL _ FALSE;
traj _ seq.traj;
FOR i: NAT IN [0..GGTraj.HiJoint[traj]] DO
IF seq.joints[i] THEN {
IF jointFound THEN {success _ FALSE; RETURN};
jointNum _ i;
joint _ GGTraj.FetchJoint[traj, i];
jointFound _ TRUE;
partType _ joint;
}
ENDLOOP;
FOR i: NAT IN [0..GGTraj.HiSegment[traj]] DO
thisSeg: Segment _ GGTraj.FetchSegment[traj, i];
FOR j: NAT IN [0..thisSeg.class.controlPointCount[thisSeg]) DO
IF seq.controlPoints[i][j] THEN {
IF cpFound THEN {success _ FALSE; RETURN};
segNum _ i;
seg _ thisSeg;
cpNum _ j;
cp _ thisSeg.class.controlPointGet[thisSeg, cpNum];
cpFound _ TRUE;
partType _ controlPoint;
}
ENDLOOP;
ENDLOOP;
IF jointFound AND cpFound THEN {success _ FALSE; RETURN};
FOR i: NAT IN [0..GGTraj.HiSegment[traj]] DO
IF seq.segments[i] THEN {
IF segFound THEN {success _ FALSE; RETURN};
segNum _ i;
seg _ GGTraj.FetchSegment[traj, i];
segFound _ TRUE;
partType _ segment;
}
ENDLOOP;
IF (jointFound AND segFound) OR (cpFound AND segFound) THEN {success _ FALSE; RETURN};
IF NOT jointFound AND NOT cpFound AND NOT segFound THEN ERROR;
success _ TRUE;
};
RunsInSequence: PUBLIC PROC [seq: Sequence] RETURNS [seqGen: SequenceGenerator, runCount: NAT] = {
IF IsObsolete[seq] THEN ERROR;
IF seq.traj.role = open THEN [seqGen, runCount] _ RunsInSequenceOpen[seq]
ELSE [seqGen, runCount] _ RunsInSequenceClosed[seq];
};

RunsInSequenceOpen: PROC [seq: Sequence] RETURNS [seqGen: SequenceGenerator, runCount: NAT] = {
in: BOOL _ FALSE;
thisSeq: Sequence;
hiSeg: NAT _ GGTraj.HiSegment[seq.traj];
hiJoint: NAT _ hiSeg + 1;
seqGen _ NEW[SequenceGeneratorObj _ [NIL]];
runCount _ 0;
IF IsEmpty[seq] THEN RETURN;
FOR i: NAT IN [0..hiSeg] DO
[in, seqGen.list, thisSeq, runCount] _ ConsiderJoint[in, seqGen.list, seq, thisSeq, runCount, i];
[in, seqGen.list, thisSeq, runCount] _ ConsiderSegment[in, seqGen.list, seq, thisSeq, runCount, i];
ENDLOOP;
[in, seqGen.list, thisSeq, runCount] _ ConsiderJoint[in, seqGen.list, seq, thisSeq, runCount, hiJoint];
IF in THEN seqGen.list _ AppendToList[seqGen.list, CONS[thisSeq, NIL]];
};

RunsInSequenceClosed: PROC [seq: Sequence] RETURNS [seqGen: SequenceGenerator, runCount: NAT] = {
in: BOOL _ FALSE;
thisSeq: Sequence;
start: NAT;
natGen: NATGenerator;
seqGen _ NEW[SequenceGeneratorObj _ [NIL]];
runCount _ 0;
IF ControlPointsOnly[seq] THEN RETURN;
start _ FirstTransitionInRun[seq];
in _ FALSE;
natGen _ NATsInInterval[start, seq.traj.segCount, seq.traj.segCount];
FOR i: INT _ NextNAT[natGen], NextNAT[natGen] UNTIL i = -1 DO 
[in, seqGen.list, thisSeq, runCount] _ ConsiderJoint[in, seqGen.list, seq, thisSeq, runCount, i];
[in, seqGen.list, thisSeq, runCount] _ ConsiderSegment[in, seqGen.list, seq, thisSeq, runCount, i];
ENDLOOP;
IF in THEN seqGen.list _ AppendToList[seqGen.list, CONS[thisSeq, NIL]];
};

NextSequence: PUBLIC PROC [seqGen: SequenceGenerator] RETURNS [seq: Sequence] = {
IF seqGen.list = NIL THEN RETURN[NIL];
seq _ seqGen.list.first;
seqGen.list _ seqGen.list.rest;
};

FirstTransitionInRun: PROC [seq: Sequence] RETURNS [transitionNum: NAT] = {
hiSeg: NAT _ GGTraj.HiSegment[seq.traj];
IF seq.traj.role = open THEN {
FOR i: NAT IN [0..hiSeg] DO
IF seq.joints[i] THEN RETURN[i];
IF seq.segments[i] THEN RETURN[i];
ENDLOOP;
IF seq.joints[hiSeg+1] THEN RETURN[hiSeg+1];
SIGNAL Problem[msg: "there is no break in the sequence."];
}
ELSE {
FOR i: NAT IN [0..hiSeg] DO
IF NOT seq.segments[(i -1 + seq.traj.segCount) MOD seq.traj.segCount] AND seq.joints[i] THEN GOTO FoundStart;
IF NOT seq.joints[i] AND seq.segments[i] THEN GOTO FoundStart;
REPEAT
FoundStart => transitionNum _ i;
FINISHED => SIGNAL Problem[msg: "there is no break in the sequence."];
ENDLOOP;
};
};

AppendToList: PROC [list1, list2: LIST OF Sequence] RETURNS [result: LIST OF Sequence] = {
pos: LIST OF Sequence;
newCell: LIST OF Sequence;
IF list1 = NIL THEN RETURN[list2];
result _ CONS[list1.first, NIL];
pos _ result;
FOR l: LIST OF Sequence _ list1.rest, l.rest UNTIL l = NIL DO
newCell _ CONS[l.first, NIL];
pos.rest _ newCell;
pos _ newCell;
ENDLOOP;
pos.rest  _ list2;
};

ConsiderJoint: PROC [in: BOOL, list: LIST OF Sequence, seq: Sequence, thisSeq: Sequence, runCount: NAT, i: NAT] RETURNS [newIn: BOOL, newList: LIST OF Sequence, newThisSeq: Sequence, newCount: NAT] = {
newIn _ in;
newList _ list;
newThisSeq _ thisSeq;
newCount _ runCount;
SELECT TRUE FROM
NOT seq.joints[i] AND NOT in => {};
NOT seq.joints[i] AND in => {
newIn _ FALSE;
newList _ AppendToList[list, CONS[thisSeq, NIL]];
newThisSeq _ NIL};
seq.joints[i] AND NOT in => {
newIn _ TRUE;
newThisSeq _ CreateEmpty[seq.traj];
newCount _ newCount + 1;
newThisSeq.joints[i] _ TRUE;
newThisSeq.jointCount _ newThisSeq.jointCount + 1;
};
seq.joints[i] AND in => {
newThisSeq.joints[i] _ TRUE;
newThisSeq.jointCount _ newThisSeq.jointCount + 1;
};
ENDCASE => ERROR;
};

ConsiderSegment: PROC [in: BOOL, list: LIST OF Sequence, seq: Sequence, thisSeq: Sequence, runCount: NAT, i: NAT] RETURNS [newIn: BOOL, newList: LIST OF Sequence, newThisSeq: Sequence, newCount: NAT] = {
newIn _ in;
newList _ list;
newThisSeq _ thisSeq;
newCount _ runCount;
SELECT TRUE FROM
NOT seq.segments[i] AND NOT in => {};
NOT seq.segments[i] AND in => {
newIn _ FALSE;
newList _ AppendToList[list, CONS[thisSeq, NIL]];
newThisSeq _ NIL};
seq.segments[i] AND NOT in => {
newIn _ TRUE;
newThisSeq _ CreateEmpty[seq.traj];
newCount _ newCount + 1;
newThisSeq.segments[i] _ TRUE;
newThisSeq.segCount _ newThisSeq.segCount + 1;
ControlPointsTrue[newThisSeq, i];
};
seq.segments[i] AND in => {
newThisSeq.segments[i] _ TRUE;
newThisSeq.segCount _ newThisSeq.segCount + 1;
ControlPointsTrue[newThisSeq, i];
};
ENDCASE => ERROR;
};

ControlPointsTrue: PROC [seq: Sequence, segNum: NAT] = {
seg: Segment _ GGTraj.FetchSegment[seq.traj, segNum];
cpCount: NAT _ seg.class.controlPointCount[seg];
FOR i: NAT IN [0..cpCount-1] DO
IF NOT seq.controlPoints[segNum][i] THEN {
seq.controlPoints[segNum][i] _ TRUE;
seq.controlPointCount _ seq.controlPointCount + 1;
};
ENDLOOP;
};

NATGenerator: TYPE = REF NATGeneratorObj;
NATGeneratorObj: TYPE = RECORD [
toGo: NAT,
next: NAT,
mod: NAT
];

NATsInInterval: PROC [start, length, mod: NAT] RETURNS [natGen: NATGenerator] = {
natGen _ NEW[NATGeneratorObj _ [
toGo: length,
next: start,
mod: mod]];
};

NextNAT: PROC [natGen: NATGenerator] RETURNS [nextNAT: INT] = {
IF natGen.toGo = 0 THEN RETURN[-1];
natGen.toGo _ natGen.toGo - 1;
nextNAT _ natGen.next;
natGen.next _ (natGen.next + 1) MOD natGen.mod;
};

SegmentsInTraj: PUBLIC PROC [traj: Traj] RETURNS [segGen: SegmentGenerator] =  {
segGen _ NEW[SegmentGeneratorObj _ [
traj: traj,
toGo: traj.segCount,
index: 0,
seq: NIL,
completeSeq: TRUE
]];
};

SegmentsInSequence: PUBLIC PROC [seq: Sequence] RETURNS [segGen: SegmentGenerator] = {
IF IsComplete[seq] THEN RETURN[SegmentsInTraj[seq.traj]];
segGen _ NEW[SegmentGeneratorObj _ [
traj: seq.traj,
toGo: seq.segCount,
index: 0,
seq: seq, -- should we copy it? Bier January 27, 1986 5:37:01 pm PST
completeSeq: FALSE
]];
};

OrderedSegmentsInSequence: PUBLIC PROC [seq: Sequence] RETURNS [segGen: SegmentGenerator] = {
IF IsObsolete[seq] THEN ERROR;
IF IsComplete[seq] THEN RETURN[SegmentsInTraj[seq.traj]];
segGen _ NEW[SegmentGeneratorObj _ [
traj: seq.traj,
toGo: seq.segCount,
index: IF seq.segCount=0 THEN 0 ELSE FirstSegment[seq], -- KAP December 22, 1986
seq: seq, -- should we copy it? Bier January 27, 1986
completeSeq: FALSE
]];
};

NextSegment: PUBLIC PROC [segGen: SegmentGenerator] RETURNS [next: Segment] = {
seq: Sequence _ segGen.seq;
segCount: NAT _ GGTraj.HiSegment[segGen.traj] + 1;
IF segGen.toGo = 0 THEN RETURN[NIL];
IF NOT segGen.completeSeq THEN { -- If we are stepping through a complete traj, seq = NIL
UNTIL seq.segments[segGen.index] DO
segGen.index _ (segGen.index + 1) MOD segCount;
segGen.touched _ segGen.touched + 1;
IF segGen.touched >= segCount THEN SIGNAL Problem[msg: "Broken invariant"];
ENDLOOP;
};
next _ GGTraj.FetchSegment[segGen.traj, segGen.index];
segGen.index _ (segGen.index + 1) MOD segCount;
segGen.touched _ segGen.touched + 1;
segGen.toGo _ segGen.toGo - 1;
};

NextSegmentAndIndex: PUBLIC PROC [segGen: SegmentGenerator] RETURNS [next: SegAndIndex] = {
seq: Sequence _ segGen.seq;
segCount: NAT _ GGTraj.HiSegment[segGen.traj] + 1;
IF segGen.toGo = 0 THEN RETURN[[NIL, 999]];
IF NOT segGen.completeSeq THEN { -- If we are stepping through a complete traj, seq = NIL
UNTIL seq.segments[segGen.index] DO
segGen.index _ (segGen.index + 1) MOD segCount;
segGen.touched _ segGen.touched + 1;
IF segGen.touched >= segCount THEN SIGNAL Problem[msg: "Broken invariant"];
ENDLOOP;
};
next.seg _ GGTraj.FetchSegment[segGen.traj, segGen.index];
next.index _ segGen.index;
segGen.index _ (segGen.index + 1) MOD segCount;
segGen.touched _ segGen.touched + 1;
segGen.toGo _ segGen.toGo - 1;
};

ControlPointsInSequence: PUBLIC PROC [seq: Sequence] RETURNS [cpGen: ControlPointGenerator] = {
IF IsObsolete[seq] THEN ERROR;
cpGen _ NEW[ControlPointGeneratorObj _ [
toGo: seq.controlPointCount,
segIndex: 0,
cpIndex: 0,
seq: seq
]];
};

NextControlPoint: PUBLIC PROC [cpGen: ControlPointGenerator] RETURNS [next: PointAndDone] = {
seq: Sequence _ cpGen.seq;
seg: Segment;
segIndex: NAT _ cpGen.segIndex;
cpIndex: NAT _ cpGen.cpIndex;
hiSeg: NAT _ GGTraj.HiSegment[cpGen.seq.traj];
IF cpGen.toGo = 0 THEN RETURN[[[0,0], TRUE]];
FOR i: NAT IN [segIndex..hiSeg] DO
FOR j: NAT IN [cpIndex..seq.controlPoints[i].len) DO
IF seq.controlPoints[i][j] THEN {
segIndex _ i;
cpIndex _ j;
GOTO Found;
};
ENDLOOP;
cpIndex _ 0;
REPEAT
Found => {
seg _ GGTraj.FetchSegment[cpGen.seq.traj, segIndex];
next.point _ seg.class.controlPointGet[seg, cpIndex];
next.done _ FALSE;
};
FINISHED => ERROR;
ENDLOOP;
cpGen.segIndex _ segIndex;
cpGen.cpIndex _ cpIndex + 1;
cpGen.toGo _ cpGen.toGo - 1;
};

NextSegNumAndCPNum: PUBLIC PROC [cpGen: ControlPointGenerator] RETURNS [segNum, cpNum: NAT, done: BOOL] = {
seq: Sequence _ cpGen.seq;
segIndex: NAT _ cpGen.segIndex;
cpIndex: NAT _ cpGen.cpIndex;
hiSeg: NAT _ GGTraj.HiSegment[cpGen.seq.traj];
IF cpGen.toGo = 0 THEN RETURN[0, 0, TRUE];
FOR i: NAT IN [segIndex..hiSeg] DO
FOR j: NAT IN [cpIndex..seq.controlPoints[i].len) DO
IF seq.controlPoints[i][j] THEN {
segIndex _ i;
cpIndex _ j;
GOTO Found;
};
ENDLOOP;
cpIndex _ 0;
REPEAT
Found => {
segNum _ segIndex;
cpNum _ cpIndex;
done _ FALSE;
};
FINISHED => ERROR;
ENDLOOP;
cpGen.segIndex _ segIndex;
cpGen.cpIndex _ cpIndex + 1;
cpGen.toGo _ cpGen.toGo - 1;
};

JointsInSequence: PUBLIC PROC [seq: Sequence] RETURNS [jointGen: JointGenerator] = {
jointGen _ NEW[JointGeneratorObj _ [ -- this allocate is expensive too.
traj: seq.traj,
toGo: seq.jointCount,
index: 0,
seq: seq,
completeSeq: FALSE -- I'll use this for optimization later, Bier March 10, 1986 5:03:42 pm PST
]];
};

JointsInTraj: PUBLIC PROC [traj: Traj] RETURNS [jointGen: JointGenerator] = {
jointGen _ NEW[JointGeneratorObj _ [
traj: traj,
toGo: GGTraj.HiJoint[traj] + 1,
index: 0,
seq: NIL,
completeSeq: TRUE
]];
};

NextJoint: PUBLIC PROC [jointGen: JointGenerator] RETURNS [next: INT] = {
seq: Sequence;
index: NAT _ jointGen.index;
IF jointGen.toGo = 0 THEN RETURN[-1];
IF jointGen.completeSeq THEN {
next _ index;
}
ELSE {
hiJoint: NAT _ GGTraj.HiJoint[jointGen.traj];
seq _ jointGen.seq;
UNTIL seq.joints[index] OR index > hiJoint DO
index _ index + 1;
ENDLOOP;
IF index > hiJoint THEN ERROR;
next _ index;
};
jointGen.index _ index + 1;
jointGen.toGo _ jointGen.toGo - 1;
};

SetStrokeWidth: PUBLIC PROC [seq: Sequence, strokeWidth: REAL] = {
segGen: SegmentGenerator;
segGen _ GGSequence.SegmentsInSequence[seq];
FOR seg: Segment _ GGSequence.NextSegment[segGen], GGSequence.NextSegment[segGen] UNTIL seg = NIL DO
seg.class.setStrokeWidth[seg, strokeWidth];
ENDLOOP;
GGTraj.UpdateBoundBox[seq.traj];
};

GetStrokeWidth: PUBLIC PROC [seq: Sequence] RETURNS [strokeWidth: REAL _ 1.0] = {
segGen: SegmentGenerator _ GGSequence.SegmentsInSequence[seq];
seg: Segment _ GGSequence.NextSegment[segGen];
strokeWidth _ IF seg#NIL THEN seg.strokeWidth ELSE -1.0;
};

SetStrokeEnd: PUBLIC PROC [seq: Sequence, strokeEnd: StrokeEnd] = {
segGen: SegmentGenerator;
segGen _ GGSequence.SegmentsInSequence[seq];
FOR seg: Segment _ GGSequence.NextSegment[segGen], GGSequence.NextSegment[segGen] UNTIL seg = NIL DO
seg.strokeEnd _ strokeEnd;
ENDLOOP;
};

GetStrokeEnd: PUBLIC PROC [seq: Sequence] RETURNS [strokeEnd: StrokeEnd] = {
segGen: SegmentGenerator _ GGSequence.SegmentsInSequence[seq];
seg: Segment _ GGSequence.NextSegment[segGen];
strokeEnd _ IF seg#NIL THEN seg.strokeEnd ELSE round;
};

SetStrokeColor: PUBLIC PROC [seq: Sequence, color: Color] =  {
segGen: SegmentGenerator;
segGen _ GGSequence.SegmentsInSequence[seq];
FOR seg: Segment _ GGSequence.NextSegment[segGen], GGSequence.NextSegment[segGen] UNTIL seg = NIL DO
seg.color _ color;
ENDLOOP;
};

GetStrokeColor: PUBLIC PROC [seq: Sequence] RETURNS [color: Imager.Color] =  {
segGen: SegmentGenerator _ GGSequence.SegmentsInSequence[seq];
seg: Segment _ GGSequence.NextSegment[segGen];
IF seg#NIL THEN color _ seg.color;
};

SetStrokeDashed: PUBLIC PROC [seq: Sequence, dashed: BOOL, pattern: SequenceOfReal _ NIL, offset: REAL _ 0.0, length: REAL _ -1.0] =  {
segGen: SegmentGenerator;
segGen _ GGSequence.SegmentsInSequence[seq];
FOR seg: Segment _ GGSequence.NextSegment[segGen], GGSequence.NextSegment[segGen] UNTIL seg = NIL DO
seg.dashed _ dashed;
seg.pattern _ pattern;
seg.offset _ offset;
seg.length _ length;
ENDLOOP;
};

GetStrokeDashed: PUBLIC PROC [seq: Sequence] RETURNS [dashed: BOOL, pattern: SequenceOfReal, offset, length: REAL] =  {
segGen: SegmentGenerator _ GGSequence.SegmentsInSequence[seq];
seg: Segment _ GGSequence.NextSegment[segGen];
IF seg#NIL THEN {
dashed _ seg.dashed;
pattern _ seg.pattern;
offset _ seg.offset;
length _ seg.length;
}
ELSE RETURN[FALSE, NIL, 0.0, 0.0];
};

END.


���#
��GGSequenceImpl.mesa
Copyright c 1986 by Xerox Corporation.  All rights reserved.
Last edited by Bier on April 7, 1987 8:31:27 pm PDT
Contents:  Sequences are a way to describe some part of a trajectory without actually pulling the trajectory apart.  The new definition of sequence is that it is ANY subset of the parts of a trajectory (joints and/or segments).  Procedures are provided which make sequences, perform boolean operations on them, and step through them.
Pier, May 12, 1987 6:35:25 pm PDT
Kurlander July 28, 1986 2:41:32 pm PDT

Sequence Creation
The sequence created will include all of the segments from startSeg to endSeg inclusive, and all of the joints which they touch.  startSeg and endSeg must be legal Sequence numbers for this trajectory.  If the trajectory is closed, then startSeg > endSeg is allowed, in which case the segment sequence wraps around.
If startSeg = endSeg, then one segment is added.
If startSeg = endSeg + 1 (modulo the number of segments in traj), then the whole trajectory is selected.
IF the traj is open, then select all segments in the interval [startJoint..endJoint].  If the traj is closed, there are three cases:  1)  IF startJoint < endJoint then proceed as for an open traj (but there is no way to select the whole trajectory.  2)  IF startJoint = endJoint then select a single joint.  3)  IF endJoint < startJoint, wrap around, selecting all segments above startJoint, all segments below endJoint, all joints above startJoint including startJoint, all joints below endJoint, including endJoint.
Closed trajectory with endJoint < startJoint (Case 3).
Returns a sequence which represents the entire trajectory.

Fundamentals

Algorithm:
ForAllJointsInSeq, if joint does not touch a segmentInSeq then update bound box with joint bound box. 
ForAllCPInSeq, update bound box with cp bound box. 
ForAllSegsInSeq, update bound box with segment bound box.
Sequences often arrives here with seq.boundBox = copy of their traj.boundBox (and thus too big), or with seq.boundBox=NIL. We ignore the current contents and calculate the update from scratch.
ForAllJointsInSeq, if joint does not touch a segmentInSeq then update bound box with joint bound box. 
ForAllCPInSeq, update bound box with cp bound box. 
ForAllSegsInSeq, update bound box with segment bound box.
Algorithm:
ForAllSegsInSeq, update bound box with segment tight box.
ForAllSegsInSeq, update bound box with segment bound box.

Textual Description

Procedures which mutate Segments (use with caution)
a sequence with segments filled in. Fill in all the joints for each segment in the sequence, and calculate the new joint count.  Leave in all isolated joints as well.
FOR j: NAT IN [0..seq.joints.len) DO seq.joints[j] _ FALSE;  ENDLOOP;
IF IsObsolete[seq] THEN ERROR; -- expensive, June 24, 1986, Bier
Modifies, mutes, and munges seq, so that it no longer includes any parts mentioned in selectedList.  Used by GGAlign.RemoveMoving.
Modifies, mutes, and munges seq, so that it no longer includes any segments whose control points are mentioned in selectedList.  Used by GGAlign.RemoveMoving.
Adds to seq those segments whose control points are mentioned in selected, but who are not mentioned in selected themselves.
Adds to seq those segments whose joints are mentioned in selected, but who are not mentioned in selected themselves.
Modifies, mutes, and munges seq, so that it no longer includes any segments whose joints are mentioned in selectedList.  Used by GGAlign.RemoveMoving.
For all runs in seq, if either end of the run is a segment (not a joint), remove that segment.
there are no joints in the run.  It only has one segment.  Remove that segment.
Assert: If we reach this point, there is at least one joint and at least one segment.
trim segments with any included control points
If jointOn then for all segments in seq, remove those that have a joint mentioned in seq.  Otherwise, remove those segments that do NOT have a joint mentioned.
This is a destructive form of the Difference operation.  mutable _ mutable - negative.

Utility Routines

Boolean Operations on Sequences

A trajectory doesn't know whether or not it is filled, so it cannot know the difference between background parts and overlay parts.  My convention will be that background is NIL.  Here is the algorithm for the rest:
All selected joints, control points and segments are "drag";
All unselected segments with selected joints or control points are "rubber".
Everything else is overlay.
A segment (and joint) have been added to one end (the trajEnd end) of seq.traj, making seq obsolete.  Create a new sequence bigger which refers to the same joints and segments that seq did, but for the new trajectory.  If extend is TRUE, then bigger will include the newly added segment if seq included the old joint which it was attached to.
Copy the old information.
At this point the counts and bit vectors are consistent.
At this point the counts and bit vectors are consistent.
A segment has been added to one end (the high end) of seq.traj, making seq obsolete.  Create a new sequence bigger which refers to the same joints and segments that seq did, but for the new trajectory.  If extend is TRUE, then bigger will include the newly added segment if seq included the old joint which it was attached to.
At this point bigger.segCount, bigger.jointCount, bigger.controlPointCount are consistent with the segments, joints, and controlPoints bit vectors.
Selected sequences must satisfy the requirement that if a segment is selected its joints and control points are as well.



Queries
TEST if this sequence cannot possibly encode its trajectory, probably because the trajectory has been modified. Not a guarantee that it accurately encodes anything.
Compare the segment bit vectors.
Compare the joint bit vectors.
Returns TRUE if the sequence contains any part of a segment, including its end joints, its control points, or the segment proper.
run had better be a run (a single non-empty contiguous sequence).
run had better be a run (a single non-empty contiguous sequence).
run had better be a run (a single non-empty contiguous sequence).
seq is asserted to be either a single joint or a single control point.  Return the [segNum, cpNum] pair or the jointNum as appropriate.
Look for a joint.

Generators

A run is a sequence with only one contiguous piece.   In other words, each joint in the run touches at least one segment in the run (unless the run is a single joint), and each segment in the run touches at least one joint in the run (unless the run is a single segment).  The run whose lowest joint has the lowest index will be returned first by NextSequence.  The other runs will follow in ascending order.
This is done in two parts.  First we find the first joint or segment that is preceded by a segment or joint that is not in the sequence.  Then we proceed as for open but mod traj.segCount.
Finds the first transition from a joint that's not in the sequence to a segment in the sequence, or from a segment that's not in the sequence to a joint that's in the sequence.  For example, with sequence 0 (0) 1 (1) 2 (2) 3 (3) 4, transition segment (1) ->  joint 2 returns 2.  joint 1 -> segment (2) returns 2.  Hence, if the first run has any segments at all, transitionNum will be the number of the first segment.
Non-destructive (copies the first list).
runCount _ runCount + 1; -- BUG! KAP March 11, 1986
We special case the complete trajectory case to reduce allocations.
IF IsObsolete[seq] THEN ERROR; -- expensive, June 24, 1986, Bier
Returns a generator for all segments in seq, beginning with the lowest numbered one (in the case of open trajectories), or the first segment that follows a segment that is not in seq (for closed trajectories).  If seq.traj is complete, then begins with segment 0.
IF IsEmpty[seq] THEN ERROR; -- why an error?? KAP December 22, 1986
Termination:  segGen.toGo is always decremented.
Invariants:
1)  When this procedure is called, seq.segments[segGen.index] has not yet been looked at OR segGen.toGo = 0.
2)  touched < segCount OR segGen.toGo = 0.
3)  At this point in the procedure, seq.segments[segGen.index] is TRUE.
4)  At this point, touched < segCount.
Termination:  segGen.toGo is always decremented.
Invariants:
1)  When this procedure is called, seq.segments[segGen.index] has not yet been looked at OR segGen.toGo = 0.
2)  touched < segCount OR segGen.toGo = 0.
3)  At this point in the procedure, seq.segments[segGen.index] is TRUE.
4)  At this point, touched < segCount.
IF IsEmpty[seq] THEN ERROR; -- Why an error?? KAP December 22, 1986
It would be nice to have a hiJoint field in the JointGeneratorObj, Bier, January 7, 1987
IF IsObsolete[seq] THEN ERROR; -- expensive (HorizontalBench.script).  Bier, April 7, 1987
I did use for optimization.  Bier, January 7, 1987 0:54:51 am PST.
ELSE ERROR Problem[msg: "No segments to get a stroke width from"];
ELSE ERROR Problem[msg: "No segments to get a stroke end from"];
Ê><��˜�Icodešœ™Kšœ
Ïmœ1™<Kšœ3™3šÏnœšÏkœ¨™ÍKšœ!™!Kšœ#Ÿ™&—K™�šŸ	˜	Jšœ„˜„—K˜�šžœŸœŸ˜JšŸœJ˜QKšŸœŸ˜—˜�KšœŸœŸœ˜#KšœŸœ˜/KšœŸœŸœ˜#KšœŸœ˜/Kšœ
Ÿœ˜'KšœŸœ˜KšœŸœŸœ˜;KšœŸœ)˜GKšœŸœ˜!KšœŸœŸœ˜-KšœŸœ"˜9KšœŸœ˜!KšœŸœ˜/Kšœ
Ÿœ˜+Kšœ	Ÿœ˜'KšœŸœŸœ˜1KšœŸœ$˜=KšœŸœ!˜5Kšœ
ŸœŸœ
˜!KšœŸœŸœ˜3KšœŸœ%˜?Kšœ
Ÿœ˜-KšœŸœ˜3KšœŸœ ˜5KšœŸœ˜#KšœŸœ˜Kšœ	Ÿœ˜%KšœŸœ˜/K˜�—KšžœŸœŸœŸœ˜;˜�K˜�—Kšœ™K˜�š
žœŸœŸœ ŸœŸœ˜_Kšœ»™»Kšœ0™0Kšœh™hKšœŸœ˜KšŸœŸœŸœŸœ˜CKšŸœŸœ+Ÿœ˜LšŸœŸœ˜KšŸœŸœ5˜NKšœ!˜!K˜—šŸœ˜KšŸœŸœŸœŸœ˜WKšœ0Ÿœ˜GK˜—šœŸœ˜Kšœ˜Kšœ1˜1Kšœ&˜&Kšœ/˜/Kšœ"˜"Kšœ˜KšœÏc)˜?Kšœ "˜0Kšœ˜—šŸœŸœ˜šŸœŸœŸœŸ˜#KšœŸœ˜KšŸœ˜—Kšœ˜Kšœ˜K˜—šŸœ˜šŸœŸœŸœŸ˜,KšœŸœ˜KšŸœ˜—šŸœŸœŸœ
Ÿ˜KšœŸœ˜KšŸœ˜—Kšœ˜Kšœ˜K˜—K˜K˜�—š
žœŸœŸœ$ŸœŸœ˜cKšŸœˆŸœrŸœ8ŸœË™…KšœŸœ˜Kšœ˜šŸœŸœŸœŸœ˜DKšœŸœ˜$—šŸœŸœŸœ˜3KšŸœŸœ=˜ZKšŸœŸœŸœŸœ˜3šœŸœ˜Kšœ˜Kšœ1˜1Kšœ&˜&Kšœ ˜ Kšœ"˜"Kšœ ˜ Kšœ %˜;Kšœ%˜%Kšœ˜—šŸœŸœŸœŸ˜)KšœŸœ˜KšœŸœ˜KšŸœ˜—KšœŸœ˜K˜—šŸœ˜KšŸœŸœ+Ÿœ˜PKšœ6™6šœŸœ˜Kšœ˜Kšœ1˜1Kšœ&˜&Kšœ ˜ Kšœ"˜"Kšœ0˜0Kšœ˜Kšœ5˜5Kšœ˜—šŸœŸœŸœŸ˜.KšœŸœ˜KšœŸœ˜KšŸœ˜—šŸœŸœŸœŸ˜ KšœŸœ˜KšœŸœ˜KšŸœ˜—KšœŸœ˜K˜—Kšœ ˜7K˜K˜�—šžœŸœŸœŸœ˜AšœŸœ˜Kšœ˜Kšœ$˜$Kšœ&˜&Kšœ-˜-Kšœ"˜"K˜Kšœ˜K˜
Kšœ˜—K˜K˜�—šžœŸœŸœŸœ˜DK™:KšœŸœ˜+šœŸœ˜Kšœ˜Kš	œ
ŸœŸœŸœŸœ(˜lKšœ&˜&Kšœ!˜!Kšœ"˜"Kšœ˜Kšœ ˜3Kšœ˜Kšœ˜—šŸœŸœŸœŸ˜,KšœŸœ˜KšœŸœ˜KšŸœ˜—KšœŸœ *˜KKšœ ˜7K˜K˜�—š
žœŸœŸœŸœŸœ˜TKšœ˜KšœŸœ˜Kšœ˜K˜K˜�—š
žœŸœŸœŸœŸœ˜TKšœ˜KšœŸœ˜Kšœ˜Kšœ˜Kšœ ˜7K˜K˜�—š
žœŸœŸœŸœŸœ˜ZKšœ˜KšœŸœ˜Kšœ˜K˜K˜�—šžœŸœŸœŸœŸœŸœ˜oKšœ˜Kšœ-Ÿœ˜2Kšœ˜K˜K˜�—šžœŸœŸœŸœ˜>KšœŸœ˜KšŸœŸœŸœ˜Kšœ'˜'šœŸœ˜Kšœ˜Kšœ0˜0Kšœ*˜*Kšœ1˜1Kšœ&˜&Kšœ˜Kšœ)˜)Kšœ˜Kšœ˜—šŸœŸœŸœŸ˜Kšœ	Ÿœ˜(Kšœ#˜#Kšœ˜šŸœŸœŸœŸ˜Kšœ3˜3KšŸœ˜—KšŸœ˜—KšŸœŸœ8˜T˜K˜�——K™�K™K™�šžœŸœŸœŸœ˜HKšœ˜Kšœ˜K˜K˜�—šžœŸœŸœ˜0KšœŸœ"˜5™
K™fK™3K™9—K˜�KšœvŸœG™ÀK˜Kšœ˜KšœŸœ˜K˜�K™fšŸœŸœ ˜0šŸœŸœ ˜4Kš	ŸœŸœŸœŸœD ˜š	ŸœŸœŸœŸœ ˜>KšŸœŸœŸœŸœŸœŸœC˜ŠKšŸœ˜—Kš	ŸœŸœŸœŸœP ˜¶K˜—šŸœ ˜"šŸœŸœŸœŸœ˜*KšŸœŸœŸœŸœŸœ)ŸœŸœC˜·KšŸœ˜—K˜—K˜—Kšœ3™3šŸœŸœ 4˜Vš	ŸœŸœŸœŸœ ˜Hš	ŸœŸœŸœŸœ l˜¥Kšœ- ˜?Kšœ	Ÿœ˜(š	ŸœŸœŸœŸœ (˜FšŸœŸœ  ˜BKšœ1˜1šœ+ 1˜\K˜——KšŸœ˜—K˜—KšŸœ˜—K˜—K™9šŸœŸœ %˜>š	ŸœŸœŸœŸœ ˜JšŸœŸœ %˜?Kšœ- ˜?KšœA +˜lK˜—KšŸœ˜—K˜—K˜K˜�—šžœŸœŸœŸœ˜HKšœŸœ"˜5™
K™9—K˜�K˜Kšœ ˜ K˜�K™9šŸœŸœ˜š	ŸœŸœŸœŸœ ˜JšŸœŸœ %˜?Kšœ,˜,Kšœ'Ïbœ˜@K˜—KšŸœ˜—K˜—Kšœ %˜:K˜—K™�Kšœ™K™�šžœŸœŸœ
Ÿœ˜CKšœŸœ˜Kšœ
Ÿœ˜KšœŸœ˜!Kšœ	Ÿœ˜%šŸœŸœŸ˜šœ '˜7Kšœ>˜>šœ¡œ
˜+Kšœ.˜.—K˜—šœŸœ "˜@KšœG˜GKšœ7˜7Kšœ¡œ˜@K˜—šœŸœŸœ %˜TKšœ<˜<Kšœ¡
œ+˜JK˜—KšŸœ,˜3—K˜K˜�—K˜�K™3K˜�šžœŸœŸœ#˜8KšœŸœ˜KšŸœŸœŸœ˜Kšœ(˜(Kšœ˜KšœŸœ˜šŸœŸœŸœ"Ÿ˜1Kšœ	Ÿœ˜)Kšœ"˜"šŸœŸœŸœŸ˜Kšœ3 ˜HKšŸœ˜—KšŸœ˜—šŸœŸœŸœ Ÿ˜/Kšœ˜KšŸœ˜—Kšœ˜Kšœ.˜.Kšœ ˜ ˜K˜�——šžœŸœŸœ˜-Kšœ¦™¦KšœŸœ˜KšŸœŸœŸœ˜KšŸœŸœŸœ 7˜VKšŸœŸœŸœŸœŸœŸœ™EšŸœŸœ˜šŸœŸœŸœŸ˜)KšŸœŸœŸœŸœ˜GKšŸœ˜—K˜—šŸœ˜šŸœŸœŸœŸ˜)Kš
ŸœŸœŸœŸœŸœ˜`KšŸœ˜—K˜—šŸœŸœŸœŸ˜.KšŸœŸœ˜2KšŸœ˜—Kšœ˜˜K˜�——šžœŸœŸœ ´˜éKšœ˜Kšœ˜Kšœ	Ÿœ˜
KšŸœŸœŸœ !™@KšŸœŸœŸœ 8˜WKšœ˜Kšœ	¡œ˜!šŸœ¡œ
¡œ	Ÿœ
ŸœŸ˜YKš	ŸœŸœŸœŸœ (˜TKšœ6  ˜Vš	ŸœŸœŸœŸœ ˜1Kšœ#Ÿœ˜(Kšœ2˜2KšŸœ˜—KšŸœ˜—K˜K˜�—šžœŸœŸœŸœŸœÐbkœ˜YKšœm¡œ™‚K˜Kšœ=˜=Kš	Ÿœ
ŸœŸœŸœ (˜EšŸœŸœŸœ!Ÿ˜0šŸœŸœŸœŸ˜.šŸœŸœŸœ˜@KšœŸœ˜ Kšœ2˜2K˜—KšŸœ˜—šŸœŸœŸœ˜0KšœŸœ˜Kšœ ˜ K˜—KšŸœ˜—šŸœŸœŸœŸ˜.šŸœŸœŸœ˜,KšœŸœ˜Kšœ#˜#K˜—KšŸœ˜—K˜K˜�—š
ž œŸœŸœŸœŸœ˜hKšœ‰¡œ™žš
žœŸœŸœŸœŸœ˜0šŸœŸœŸœ"Ÿ˜1KšŸœŸœŸœŸœ˜0KšŸœ˜—KšŸœŸœ˜K˜—K˜Kšœ=˜=Kš	Ÿœ
ŸœŸœŸœ &˜CšŸœŸœŸœ!Ÿ˜0šŸœŸœŸœ˜/KšœŸœ˜Kšœ ˜ K˜—KšŸœ˜—K˜K˜�—šž"œŸœŸœ(˜WKšœ|™|š
žœŸœŸœŸœŸœ˜0šŸœŸœŸœ$Ÿ˜3KšŸœŸœŸœŸœ˜2KšŸœ˜—KšŸœŸœ˜K˜—Kš	ŸœŸœŸœŸœ %˜DšŸœŸœŸœ!Ÿ˜0šŸœŸœŸœŸœŸœŸœ˜PKšœŸœ˜Kšœ ˜ K˜—KšŸœ˜—K˜K˜�—šžœŸœŸœ(˜PKšœt™tš
žœŸœŸœŸœŸœ˜3šŸœ˜KšœŸœ4˜IK˜—K˜—Kš	ŸœŸœŸœŸœ (˜GšŸœŸœŸœ!Ÿ˜0šŸœŸœŸœŸœŸœŸœ˜SKšœŸœ˜Kšœ ˜ K˜—KšŸœ˜—K˜K˜�—š
žœŸœŸœŸœŸœ˜aKšœ¡œ™–š
žœŸœŸœŸœŸœ˜3šŸœ˜KšœŸœ2˜EK˜—K˜—K˜Kšœ=˜=Kš	Ÿœ
ŸœŸœŸœ )˜FšŸœŸœŸœ!Ÿ˜0šŸœŸœŸœ˜2KšœŸœ˜Kšœ ˜ K˜—KšŸœ˜—K˜K˜�K˜�—šžœŸœŸœ˜5K™^Kšœ˜Kšœ
Ÿœ˜Kšœ
Ÿœ˜Kšœ6Ÿœ˜:K˜�KšŸœŸœŸœ 1˜QKšœ)˜)šŸœ<ŸœŸœŸ˜QKšœŸœ˜Kšœ˜K˜#Kšœ*˜*K˜0šŸœŸœ˜K™OKšŸœŸœŸœ %˜EKšŸœŸœŸœŸœ˜,KšœŸœ˜"Kšœ ˜ KšŸœ˜K˜—KšŸœŸœŸœ n˜KšŸœŸœŸœ 4˜SKšŸœŸœŸœ 6˜UKšÐbn¡O™UšŸœŸœ˜%KšŸœŸœŸœŸœ˜+KšœŸœ˜"Kšœ ˜ KšœŸœ˜K˜—šŸœŸœ Ÿ˜?KšœŸœŸœ$˜SšŸœŸœ
ŸœŸœ˜8KšŸœŸœŸœŸœ˜+KšœŸœ˜!Kšœ ˜ K˜——KšŸœ˜—K˜K˜�—šžœŸœŸœ!Ÿœ˜OK™.š
žœŸœŸœŸœŸœ˜0šŸœŸœŸœŸ˜.KšŸœ*ŸœŸœŸœ˜>KšŸœ˜—KšŸœŸœ˜K˜—KšŸœŸœŸœ˜šŸœŸœŸœ!Ÿ˜0šŸœŸœŸœ˜/KšœŸœ˜Kšœ ˜ K˜—KšŸœ˜—K˜K˜�—šžœŸœŸœŸœ˜AKšœ„Ÿœ™Ÿš
žœŸœŸœŸœŸœ˜3šŸœ˜KšœŸœ9˜SK˜—K˜—šŸœŸœŸœ!Ÿ˜0šŸœŸœŸœ˜2KšœŸœ˜Kšœ ˜ K˜—KšŸœ˜—K˜K˜�—šžœŸœŸœ"˜:KšœV™VKšœ	Ÿœ˜
KšŸœŸœŸœŸœ˜:KšŸœŸœŸœ˜+šŸœŸœŸœ%Ÿ˜4Kšœ	Ÿœ ˜,Kšœ*ŸœŸœ˜GšŸœŸœŸœŸ˜Kšœ:ŸœŸœ˜_KšŸœ˜—Kšœ&ŸœŸœ˜AKšŸœ˜—šœ'˜'Kšœ2ŸœŸœ˜S—Kšœ*˜*Kšœ*˜*Kšœ8˜8K˜—K™�K™K˜�šžœŸœŸœ˜BKšœŸœ˜Kšœ;˜;KšœŸœ˜-šŸœOŸœŸœŸ˜dKšœ>˜>K˜KšŸœ˜—K˜K˜�—šžœŸœ
ŸœŸœ˜@Kšœ	Ÿœ˜#KšœŸœ˜K˜K™�—šž
œŸœŸœ˜4šŸœŸœŸœŸ˜ Kšœ˜KšŸœ˜—K˜K˜�—š
žœŸœ
ŸœŸœŸœ˜DKšœ	Ÿœ!˜-šŸœŸœŸœŸ˜KšŸœŸœŸœŸœ˜2KšŸœ˜—KšŸœŸœ˜K˜K˜�—šžœŸœ,Ÿœ 1˜|K˜�KšœŸœ˜!KšœŸœ˜KšŸœŸœŸœ˜KšœE˜EšŸœŸœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜KšœŸœ˜KšŸœ˜K˜—KšŸœŸœ˜&KšŸœŸœ˜&KšŸœŸœ˜&KšŸœŸœ˜&K˜—K˜�K™K™�šžœŸœŸœŸœ˜AKšœ	Ÿœ˜
KšŸœŸœŸœŸœ˜-KšŸœŸœŸœ˜Kšœ˜šŸœŸœŸœŸ˜.Kšœ	Ÿœ˜&Kšœ"Ÿœ˜3šŸœŸœŸœŸ˜Kšœ2Ÿœ˜KKšŸœ˜—KšœŸœ
˜-KšŸœ˜—šœ!˜!Kšœ*Ÿœ˜?—Kšœ&˜&Kšœ&˜&Kšœ4˜4K˜K˜�—šžœŸœŸœŸœ˜OKšœ	Ÿœ˜
KšŸœŸœŸœŸœ˜-KšŸœŸœŸœ˜Kšœ#˜#šŸœŸœŸœŸ˜.Kšœ	Ÿœ˜&Kšœ)Ÿœ˜;šŸœŸœŸœŸ˜Kšœ8Ÿœ˜RKšŸœ˜—Kšœ%Ÿœ
˜5KšŸœ˜—šœ!˜!Kšœ1Ÿœ˜G—Kšœ4˜4Kšœ4˜4KšœB˜BK˜K˜�—šž
œŸœŸœŸœ˜HKšœ	Ÿœ˜
KšŸœŸœŸœŸœ˜-KšŸœŸœŸœ˜Kšœ˜šŸœŸœŸœŸ˜.Kšœ	Ÿœ˜&Kšœ$ŸœŸœ˜:šŸœŸœŸœŸ˜Kšœ4ŸœŸœ˜RKšŸœ˜—Kšœ ŸœŸœ
˜4KšŸœ˜—šœ!˜!Kšœ,ŸœŸœ˜F—Kšœ*˜*Kšœ*˜*Kšœ8˜8K˜K˜�—šžœŸœŸœŸœ2˜fKšœ®Ÿœ&™×K™<K™LKšœ™Kšœ
Ÿœ˜Kšœ˜Kšœ%˜%Kšœ#˜#Kšœ˜Kšœ˜K˜—šžœŸœŸœ˜KKšœ˜Kšœ0˜0Kšœ)˜)K˜K˜�—š
žœŸœŸœ+ŸœŸœ˜cKšœèŸœj™ÖšŸœŸœŸœ˜7Kšœ$˜$KšŸœ˜K˜Kš¡™—Kšœ	žœ˜Kšœ˜Kšœ1˜1Kšœ#˜#šŸœŸœ˜šŸœŸœŸœŸ˜&Kšœ	Ÿœ˜(Kšœ¡œ˜%Kšœ!˜!šŸœŸœŸœŸ˜Kšœ5˜5KšŸœ˜—KšŸœ˜—Kš¡8™8šŸœ Ÿœ ˜CKšœ$Ÿœ ˜IšŸœŸœ˜Kšœ$Ÿœ˜)Kšœ Ÿœ˜%Kšœ3Ÿœ˜9Kšœ&˜&Kšœ*˜*Kšœ`˜`K˜—K˜—K˜—šŸœ˜šŸœŸœŸœŸ˜&Kšœ	Ÿœ˜(Kšœ¡
œ˜'Kšœ%˜%šŸœŸœŸœŸ˜Kšœ7˜7KšŸœ˜—KšŸœ˜—Kš¡8™8šŸœŸœ ˜2KšœŸœ ˜8šŸœŸœ˜KšœŸœ˜KšœŸœ˜Kšœ$Ÿœ˜*Kšœ&˜&Kšœ*˜*KšœQ˜QK˜—K˜—K˜—K˜K˜�—š
ž
œŸœŸœŸœŸœ˜WKšœØŸœj™Æšœ	Ÿœ˜Kšœ˜Kšœ$˜$Kšœ+˜+Kšœ%˜%Kšœ' #˜JKšœ˜Kšœ)˜)Kšœ˜Kšœ˜—šŸœŸœŸœŸ˜&Kšœ	Ÿœ˜(Kšœ%˜%Kšœ!˜!šŸœŸœŸœŸ˜Kšœ6 ˜KKšŸœ˜—KšŸœ˜—šŸœ Ÿœ ˜CKšœ$Ÿœ ˜IKš¡“™“šŸœŸœ˜Kšœ$Ÿœ˜)Kšœ3Ÿœ˜9Kšœ&˜&Kšœa˜aK˜—K˜—K˜K˜�—šžœŸœ1˜JK™xšŸœŸœ˜Kšœ˜Kšœ˜K˜—šŸœ˜Kšœ˜K˜—K˜K™�—K˜�K™�K™�K™K˜�š
ž
œŸœŸœŸœŸœ˜:KšŸœ ™¤KšœŸœ˜K˜KšŸœ&ŸœŸœŸœ˜:KšŸœ1ŸœŸœŸœ˜EK˜"šŸœSŸœ	ŸœŸ˜jKšŸœCŸœŸœŸœ˜WK˜KšŸœ˜—KšŸœŸœ˜K˜K˜�—š
žœŸœŸœŸœŸœ˜7KšŸœŸœŸœ˜NK˜K˜�—š
žœŸœŸœŸœŸœ˜AKšŸœŸœ˜0K˜K˜�—š
ž
œŸœŸœŸœŸœ˜:šŸœ"Ÿ˜+Kšœ1˜1—K˜K˜�—š
žœŸœŸœŸœŸœ˜>KšŸœŸœŸœŸœ˜3KšŸœŸœŸœ˜$K™ šŸœŸœŸœ"Ÿ˜1Kš
ŸœŸœŸœŸœŸœ˜;KšŸœ˜K™—šŸœŸœŸœ Ÿ˜/Kš
ŸœŸœŸœŸœŸœ˜7KšŸœ˜—šŸœŸœŸœ"Ÿ˜1Kšœ	Ÿœ˜)šŸœŸœŸœŸ˜Kš
ŸœŸœŸœŸœŸœ˜KKšŸœ˜—KšŸœ˜—KšŸœŸœ˜K˜K˜�—šž
œŸœŸœŸœ˜?Kšœ
˜
šŸœŸœŸœ!Ÿ˜0KšŸœŸœ˜0KšŸœ˜—K˜K˜�—šžœŸœŸœŸœ˜?Kšœ˜šŸœŸœŸœŸ˜.KšŸœŸœ˜2KšŸœ˜—K˜K˜�—šžœŸœŸœ	Ÿœ	˜EšŸœŸœŸœ!Ÿ˜0Kšœ	Ÿœ˜(šŸœŸœŸœŸ˜KšŸœŸœ˜2KšŸœ˜—KšŸœ˜—K˜K˜�—šžœŸœŸœŸœŸœŸœ˜LKšŸœ˜K˜K˜�—š
žœŸœŸœŸœŸœ˜CKšŸœ˜K˜—K˜�šžœŸœŸœŸœŸœŸœ˜QKšœŸœu™šŸœŸœŸœŸ˜,KšŸœ/Ÿ˜4KšœŸ˜Kš	œŸœŸœ
ŸœŸœ˜Y—K˜K˜�—šžœŸœŸœ	Ÿœ˜;KšœŸœ˜(KšŸœŸœŸœ˜šŸœŸœ˜šŸœŸœŸœŸ˜KšŸœŸœŸœ˜#šŸ˜Kšœ˜KšŸœŸœ6˜H—KšŸœ˜—K˜—šŸœ˜šŸœŸœŸœŸ˜KšŸœŸœ*ŸœŸœŸœŸœ˜iKš
ŸœŸœŸœŸœŸœ˜9šŸ˜Kšœ˜KšŸœŸœ4˜F—KšŸœ˜—K˜—K˜K˜�—š
žœŸœŸœŸœŸœ˜:K™AKšŸœŸœŸœ˜$KšŸœŸœŸœ 3˜bKšŸœ˜"K˜K˜�—šž
œŸœŸœŸœŸœŸœ˜TK™AKšŸœŸœŸœ˜$KšŸœŸœ)˜EKšŸœ@Ÿœ˜ZK˜K˜�—šž
œŸœŸœŸœŸœŸœ˜LKšŸœ˜K˜K˜�—š
ž
œŸœŸœŸœŸœ˜<K™AKšœŸœ˜KšŸœŸœŸœ˜&Kšœ%˜%šŸœŸœŸœŸœ˜4šŸœŸœ˜KšŸœŸœŸœ˜5KšŸœŸœ#˜-K˜—šŸœ˜Kšœ6˜6KšŸœŸœŸœ˜/KšŸœŸœ#˜-Kšœ˜—K˜—K˜K˜�—šžœŸœŸœ ŸœŸœŸœ˜XKšŸœŸœŸœ˜&KšŸœŸœ-˜IKšŸœDŸœ˜^K˜K˜�—šžœŸœŸœ Ÿœ˜_Kšœ ˜ šŸœŸœ˜Kšœ˜Kšœ˜šŸœŸœ˜KšœŸœ˜KšœŸœ˜K˜—šŸœ˜KšœŸœ˜$KšœŸœ˜#KšœŸœ˜#K˜—K˜—KšŸœŸœ˜K˜K˜�—šžœŸœŸœŸœ	ŸœŸœ˜kKšœ‡™‡K˜
šŸœŸœŸœŸ˜.šŸœŸœ˜KšœŸœ˜Kšœ
˜
Kšœ˜Kšœ
˜
KšŸœ˜K˜—KšŸœ˜—šŸœŸœŸœ!Ÿ˜0Kšœ'˜'šŸœŸœŸœ+Ÿ˜:šŸœŸœ˜!KšœŸœ˜
Kšœ˜Kšœ
˜
Kšœ˜KšŸœ˜K˜—KšŸœ˜—KšŸœ˜—KšŸœ˜K˜K˜�—š
žœŸœŸœŸœ
Ÿœ˜OšŸœŸœŸœ!Ÿ˜0šŸœŸœ˜Kšœ˜KšŸœ˜K˜—KšŸœ˜—KšŸœ˜K˜K˜�—šžœŸœŸœŸœŸœ<ŸœŸœ"ŸœŸœ
Ÿœ˜íšœŸœ˜,K™—Kšœ˜šŸœŸœŸœŸ˜*šŸœŸœ˜KšŸœŸœŸœŸœ˜-Kšœ
˜
Kšœ#˜#Kšœ
Ÿœ˜Kšœ˜K˜—KšŸœ˜—šŸœŸœŸœŸ˜,Kšœ0˜0šŸœŸœŸœ/Ÿ˜>šŸœŸœ˜!KšŸœ	ŸœŸœŸœ˜*Kšœ˜Kšœ˜Kšœ
˜
Kšœ3˜3Kšœ
Ÿœ˜Kšœ˜K˜—KšŸœ˜—KšŸœ˜—Kš
ŸœŸœ	ŸœŸœŸœ˜9šŸœŸœŸœŸ˜,šŸœŸœ˜KšŸœ
ŸœŸœŸœ˜+Kšœ˜Kšœ#˜#KšœŸœ˜Kšœ˜K˜—KšŸœ˜—KšŸœ
ŸœŸœ
ŸœŸœŸœŸœ˜VKšŸœŸœŸœŸœ	ŸœŸœ
ŸœŸœ˜>Kšœ
Ÿœ˜K˜—K™�K™
K™�š
žœŸœŸœŸœ'Ÿœ˜bKšœ˜™˜KšŸœŸœŸœ˜KšŸœŸœ-˜IKšŸœ0˜4K˜K˜�—šžœŸœŸœ'Ÿœ˜_KšœŸœŸœ˜Kšœ˜KšœŸœ˜(Kšœ	Ÿœ
˜Kšœ	ŸœŸœ˜+Kšœ
˜
KšŸœŸœŸœ˜šŸœŸœŸœŸ˜Kšœa˜aKšœc˜cKšŸœ˜—Kšœg˜gKšŸœŸœ)Ÿœ
Ÿœ˜GK˜K˜�—šžœŸœŸœ'Ÿœ˜aK™¼KšœŸœŸœ˜Kšœ˜KšœŸœ˜Kšœ˜Kšœ	ŸœŸœ˜+Kšœ
˜
KšŸœŸœŸœ˜&Kšœ"˜"KšœŸœ˜KšœE˜EšŸœŸœ$ŸœŸœ˜>Kšœa˜aKšœc˜cKšŸœ˜—KšŸœŸœ)Ÿœ
Ÿœ˜GK˜K˜�—šžœŸœŸœŸœ˜QKš
ŸœŸœŸœŸœŸœ˜&Kšœ˜Kšœ˜K˜K˜�—šžœŸœŸœŸœ˜KKšœ¡™¡KšœŸœ˜(šŸœŸœ˜šŸœŸœŸœŸ˜KšŸœŸœŸœ˜ KšŸœŸœŸœ˜"KšŸœ˜—KšŸœŸœŸœ
˜,KšŸœ4˜:K˜—šŸœ˜šŸœŸœŸœŸ˜KšŸœŸœ)ŸœŸœŸœŸœ˜mKš
ŸœŸœŸœŸœŸœ˜>šŸ˜Kšœ ˜ KšŸœŸœ4˜F—KšŸœ˜—K˜—K˜K˜�—šžœŸœŸœŸœŸœ
ŸœŸœ˜ZKšœŸœŸœ
˜Kšœ	ŸœŸœ
˜K™(KšŸœ	ŸœŸœŸœ˜"Kšœ	ŸœŸœ˜ Kšœ
˜
šŸœŸœŸœŸœŸœŸ˜=Kšœ
Ÿœ
Ÿœ˜Kšœ˜Kšœ˜KšŸœ˜—Kšœ˜K˜K˜�—šž
œŸœŸœŸœŸœ7ŸœŸœŸœ	ŸœŸœŸœ+Ÿœ˜ÉKšœ˜Kšœ˜Kšœ˜Kšœ˜Kš¢¡¢¡¢˜KšŸœŸœŸœ
˜#šŸœŸœ˜KšœŸœ˜KšœŸœ
Ÿœ˜1Kšœ
Ÿœ˜—šœŸœŸœ˜KšœŸœ˜
Kšœ#˜#Kšœ ™3Kšœ˜KšœŸœ˜Kšœ2˜2K˜—šœŸœ˜KšœŸœ˜Kšœ2˜2Kšœ˜—Kš¢¡¢¡˜K˜K˜�—šžœŸœŸœŸœŸœ7ŸœŸœŸœ	ŸœŸœŸœ+Ÿœ˜ËKšœ˜Kšœ˜Kšœ˜Kšœ˜šŸœŸœŸ˜KšŸœŸœŸœ
˜%šŸœŸœ˜KšœŸœ˜KšœŸœ
Ÿœ˜1Kš¡
¢œ˜—šœŸœŸœ˜KšœŸœ˜
Kšœ
¡œ˜#Kšœ˜KšœŸœ˜Kšœ.˜.Kšœ!˜!K˜—šœŸœ˜KšœŸœ˜Kšœ.˜.Kšœ!˜!Kšœ˜—KšŸœŸœ˜—K˜—K˜�šžœŸœŸœ˜8Kšœ5˜5Kšœ	Ÿœ$˜0šŸœŸœŸœŸ˜šŸœŸœŸœ˜*KšœŸœ˜$Kšœ2˜2K˜—KšŸœ˜—K˜—K˜�KšœŸœŸœ˜)šœŸœŸœ˜ KšœŸœ˜
KšœŸœ˜
KšœŸ˜K˜K˜�—šžœŸœŸœŸœ˜Qšœ	Ÿœ˜ K˜
K˜K˜—K˜K˜�—šžœŸœŸœŸœ˜?KšŸœŸœŸœ˜#K˜K˜Kšœ Ÿœ˜/K˜—K˜�šžœŸœŸœŸœ ˜PK™Cšœ	Ÿœ˜$Kšœ˜Kšœ˜Kšœ	˜	KšœŸœ˜	Kšœ
Ÿ˜K˜—˜K˜�——šžœŸœŸœŸœ˜VKšŸœŸœŸœ !™@KšŸœŸœŸœ˜9šœ	Ÿœ˜$Kšœ˜Kšœ˜Kšœ	˜	Kšœ
 :˜DKšœ
Ÿ˜Kšœ˜—K˜K˜�—šžœŸœŸœŸœ˜]Kšœ‡™‡KšŸœŸœŸœ '™CKšŸœŸœŸœ˜KšŸœŸœŸœ˜9šœ	Ÿœ˜$Kšœ˜Kšœ˜KšœŸœŸœŸœ ˜PKšœ
 +˜5Kšœ
Ÿ˜Kšœ˜—K˜K˜�—šžœŸœŸœŸœ˜OKšœ0™0šœ™KšœYŸœ™lKšœŸœ™*—Kšœ˜Kšœ
Ÿœ%˜2KšŸœŸœŸœŸœ˜$šŸœŸœŸœ 8˜YšŸœŸ˜#Kšœ"Ÿœ
˜/Kšœ$˜$KšŸœŸœŸœ"˜KKšŸœ˜—˜KšœBŸœ™GKšœ&™&——Kšœ6˜6Kšœ"Ÿœ
˜/Kšœ$˜$Kšœ˜K˜K˜�—šžœŸœŸœŸœ˜[Kšœ0™0šœ™KšœYŸœ™lKšœŸœ™*—Kšœ˜Kšœ
Ÿœ%˜2KšŸœŸœŸœŸœ˜+šŸœŸœŸœ 8˜YšŸœŸ˜#Kšœ"Ÿœ
˜/Kšœ$˜$KšŸœŸœŸœ"˜KKšŸœ˜—˜KšœBŸœ™GKšœ&™&——Kšœ:˜:Kšœ˜Kšœ"Ÿœ
˜/Kšœ$˜$Kšœ˜K˜K˜�—šžœŸœŸœŸœ#˜_KšŸœŸœŸœ '™CKšŸœŸœŸœ˜šœŸœ˜(Kšœ˜Kšœ˜K˜Kšœ˜Kšœ˜—K˜K˜�—šžœŸœŸœ Ÿœ˜]Kšœ˜K˜
Kšœ
Ÿœ˜Kšœ	Ÿœ˜KšœŸœ$˜.KšŸœŸœŸœ	Ÿœ˜-šŸœŸœŸœŸ˜"šŸœŸœŸœ%Ÿ˜4šŸœŸœ˜!Kšœ
˜
Kšœ˜KšŸœ˜K˜—KšŸœ˜—Kšœ˜šŸ˜˜
Kšœ4˜4Kšœ5˜5KšœŸœ˜K˜—KšŸœŸœ˜—KšŸœ˜—Kšœ˜Kšœ˜Kšœ˜K˜K˜�—šžœŸœŸœ ŸœŸœŸœ˜kKšœ˜Kšœ
Ÿœ˜Kšœ	Ÿœ˜KšœŸœ$˜.KšŸœŸœŸœŸœ˜*šŸœŸœŸœŸ˜"šŸœŸœŸœ%Ÿ˜4šŸœŸœ˜!Kšœ
˜
Kšœ˜KšŸœ˜K˜—KšŸœ˜—Kšœ˜šŸ˜˜
Kšœ˜Kšœ˜KšœŸœ˜
K˜—KšŸœŸœ˜—KšŸœ˜—Kšœ˜Kšœ˜Kšœ˜K˜K˜�—šžœŸœŸœŸœ˜TKšœX™XKšŸœŸœŸœ=™ZšœŸœ "˜GKšœ˜Kšœ˜K˜	Kšœ	˜	šœ
Ÿœ K˜^Kšœ>Ÿœ™B—K˜—K˜K˜�—šžœŸœŸœŸœ˜MšœŸœ˜$Kšœ˜Kšœ˜K˜	KšœŸœ˜	Kšœ
Ÿ˜K˜—Kšœ˜K˜�—š
ž	œŸœŸœŸœŸœ˜IKšœ˜KšœŸœ˜KšŸœŸœŸœ˜%šŸœŸœ˜Kšœ
˜
K˜—šŸœ˜Kšœ	Ÿœ!˜-Kšœ˜šŸœŸœŸ˜-Kšœ˜KšŸœ˜—KšŸœŸœŸœ˜Kšœ
˜
K˜—Kšœ˜Kšœ"˜"K˜—K˜�šžœŸœŸœŸœ˜BK˜Kšœ,˜,šŸœOŸœŸœŸ˜dKšœ+˜+KšŸœ˜—K˜ K˜K˜�—š
žœŸœŸœŸœŸœ˜QKšœ>˜>Kšœ.˜.Kš	œŸœŸœŸœŸœ˜8JšŸ
œ8™BK˜K˜�—šžœŸœŸœ*˜CK˜Kšœ,˜,šŸœOŸœŸœŸ˜dKšœ˜KšŸœ˜—K˜K˜�—š£œŸœŸœŸœ˜LKšœ>˜>Kšœ.˜.Kš	œŸœŸœŸœŸœ˜5JšŸœŸœ6™@K˜K˜�—šžœŸœ#˜>K˜Kšœ,˜,šŸœOŸœŸœŸ˜dKšœ˜KšŸœ˜—K˜K˜�—šžœŸœŸœ˜NKšœ>˜>Kšœ.˜.KšŸœŸœŸœ˜"K˜K˜�—šžœŸœŸœŸœ
ŸœŸœ
˜‡K˜Kšœ,˜,šŸœOŸœŸœŸ˜dKšœ˜Kšœ˜Kšœ˜Kšœ˜KšŸœ˜—K˜K˜�—š£	žœŸœŸœ
Ÿœ+Ÿœ˜wKšœ>˜>Kšœ.˜.šŸœŸœŸœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜K˜—JšŸœŸœŸœŸœ˜"K˜—K˜�KšŸœ˜J˜�J˜�—�…—����¶6��|�