DIRECTORY
GGBasicTypes, GGDescribe, GGError, GGInterfaceTypes, GGModelTypes, GGObjects, GGOutline, GGSegmentTypes, GGSelect, GGShapes, GGSequence, GGTouch, GGTransform, Imager, ImagerTransformation, Rope, Rosary;

GGTouchImpl: CEDAR PROGRAM
IMPORTS GGDescribe, GGError, GGObjects, GGOutline, GGSelect, GGSequence, GGShapes, GGTransform, Rosary
EXPORTS GGTouch =
BEGIN

Slice: TYPE = GGModelTypes.Slice;
GargoyleData: TYPE = GGInterfaceTypes.GargoyleData;
Joint: TYPE = GGModelTypes.Joint;
JointGenerator: TYPE = GGSequence.JointGenerator;
Outline: TYPE = GGModelTypes.Outline;
Point: TYPE = GGBasicTypes.Point;
Segment: TYPE = GGSegmentTypes.Segment;
Sequence: TYPE = GGModelTypes.Sequence;
Traj: TYPE = GGModelTypes.Traj;
SegmentGenerator: TYPE = GGModelTypes.SegmentGenerator;
TrajGenerator: TYPE = GGObjects.TrajGenerator;

TouchGroup: TYPE = REF TouchGroupObj;
TouchGroupObj: TYPE = GGSegmentTypes.TouchGroupObj;
TouchingPartType: TYPE = GGSegmentTypes.TouchingPartType;
TouchItem: TYPE = REF TouchItemObj;
TouchItemObj: TYPE = GGSegmentTypes.TouchItemObj;

TouchItemGenerator: TYPE = REF TouchItemGeneratorObj;
TouchItemGeneratorObj: TYPE = GGTouch.TouchItemGeneratorObj;



NotYetImplemented: PUBLIC SIGNAL = CODE;

CreateTouchGroup: PUBLIC PROC [gargoyleData: GargoyleData, point: Point] RETURNS [empty: TouchGroup] = {
empty _ NEW[TouchGroupObj _ [
list: NIL,
point: point
]];
gargoyleData.touching _ CONS[empty, gargoyleData.touching];
};

AddJoint: PUBLIC PROC [traj: Traj, joint: Joint, touchGroup: TouchGroup] RETURNS [item: TouchItem] = {
item _ NEW[TouchItemObj _ [
group: touchGroup,
traj: traj,
touchingPartType: joint,
joint: joint,
seg: NIL,
segPoint: [0.0,0.0]
]];
touchGroup.list _ CONS[item, touchGroup.list];
};

AddSegment: PUBLIC PROC [traj: Traj, seg: Segment, segPoint: Point, touchGroup: TouchGroup] RETURNS [item: TouchItem] = {
item _ NEW[TouchItemObj _ [
group: touchGroup,
traj: traj,
touchingPartType: segment,
joint: NIL,
seg: seg,
segPoint: segPoint
]];
touchGroup.list _ CONS[item, touchGroup.list];
};

MergeGroups: PUBLIC PROC [group1, group2: TouchGroup, gargoyleData: GargoyleData] = {
touchItemGen: TouchItemGenerator;
IF group1 = group2 THEN RETURN;
touchItemGen _ AllTouchItems[group1];
FOR item1: TouchItem _ NextTouchItem[touchItemGen], NextTouchItem[touchItemGen] UNTIL item1 = NIL DO
item1.group _ group2;
group2.list _ CONS[item1, group2.list];
ENDLOOP;
group1.list _ NIL;
gargoyleData.touching _ DeleteTouchGroupFromList[group1, gargoyleData.touching];
};

InitializeTouching: PUBLIC PROC [gargoyleData: GargoyleData] = {
FOR groupList: LIST OF TouchGroup _ gargoyleData.touching, groupList.rest UNTIL groupList = NIL DO
groupList.first.updated _ FALSE;
ENDLOOP;
};

UpdateTouchGroup: PUBLIC PROC [item: TouchItem, point: Point, gargoyleData: GargoyleData] = {
group: TouchGroup _ item.group;
itemGen: TouchItemGenerator;
IF group.updated THEN {
RETURN;
};
group.updated _ TRUE;
group.point _ point;
itemGen _ AllTouchItems[group];
FOR thisItem: TouchItem _ NextTouchItem[itemGen], NextTouchItem[itemGen] UNTIL thisItem = NIL DO
SELECT thisItem.touchingPartType FROM
joint => {
IF NOT GGSelect.IsSelectedInFull[thisItem.joint, gargoyleData.scene, normal] THEN {
thisItem.joint.touchItem _ NIL;
group.list _ DeleteTouchItemFromList[thisItem, group.list];
};
};
segment => {
IF NOT GGSelect.IsSelectedInFull[thisItem.seg, gargoyleData.scene, normal] THEN {
thisItem.seg.touchItemList _ DeleteTouchItemFromList[thisItem, thisItem.seg.touchItemList];
group.list _ DeleteTouchItemFromList[thisItem, group.list];
};
};
ENDCASE => ERROR;
ENDLOOP;
IF group.list = NIL THEN ERROR;
IF group.list.rest = NIL THEN { -- only one item left.  Delete group.
thisItem: TouchItem _ group.list.first;
SELECT thisItem.touchingPartType FROM
joint => {
thisItem.joint.touchItem _ NIL;
group.list _ DeleteTouchItemFromList[thisItem, group.list];
};
segment => {
thisItem.seg.touchItemList _ DeleteTouchItemFromList[thisItem, thisItem.seg.touchItemList];
group.list _ DeleteTouchItemFromList[thisItem, group.list];
};
ENDCASE => ERROR;
gargoyleData.touching _ DeleteTouchGroupFromList[group, gargoyleData.touching];
};
};
SequenceMoved: PUBLIC PROC [seq: Sequence, gargoyleData: GargoyleData, transform: ImagerTransformation.Transformation _ NIL] = {
jointGen: JointGenerator;
joint: Joint;
segGen: SegmentGenerator;
jointGen _ GGSequence.JointsInSequence[seq];
FOR i: INT _ GGSequence.NextJoint[jointGen], GGSequence.NextJoint[jointGen] UNTIL i = -1 DO
joint _ NARROW[Rosary.Fetch[seq.traj.joints, i]];
IF joint.touchItem # NIL THEN {
UpdateTouchGroup[joint.touchItem, joint.point, gargoyleData];
};
ENDLOOP;
segGen _ GGSequence.SegmentsInSequence[seq];
FOR seg: Segment _ GGSequence.NextSegment[segGen], GGSequence.NextSegment[segGen] UNTIL seg = NIL DO
FOR itemList: LIST OF TouchItem _ seg.touchItemList, itemList.rest UNTIL itemList = NIL DO
itemList.first.segPoint _ GGTransform.Transform[transform, itemList.first.segPoint];
UpdateTouchGroup[itemList.first, itemList.first.segPoint, gargoyleData];
ENDLOOP;
ENDLOOP;
};

TrajMoved: PUBLIC PROC [traj: Traj, gargoyleData: GargoyleData, transform: ImagerTransformation.Transformation _ NIL] = {
jointGen: JointGenerator;
joint: Joint;
segGen: SegmentGenerator;
jointGen _ GGSequence.JointsInTraj[traj];
FOR i: INT _ GGSequence.NextJoint[jointGen], GGSequence.NextJoint[jointGen] UNTIL i = -1 DO
joint _ NARROW[Rosary.Fetch[traj.joints, i]];
IF joint.touchItem # NIL THEN {
UpdateTouchGroup[joint.touchItem, joint.point, gargoyleData];
};
ENDLOOP;
segGen _ GGSequence.SegmentsInTraj[traj];
FOR seg: Segment _ GGSequence.NextSegment[segGen], GGSequence.NextSegment[segGen] UNTIL seg = NIL DO
FOR itemList: LIST OF TouchItem _ seg.touchItemList, itemList.rest UNTIL itemList = NIL DO
itemList.first.segPoint _ GGTransform.Transform[transform, itemList.first.segPoint];
UpdateTouchGroup[itemList.first, itemList.first.segPoint, gargoyleData];
ENDLOOP;
ENDLOOP;
};
DeleteTouchItem: PUBLIC PROC [touchItem: TouchItem, gargoyleData: GargoyleData] = {
lastItem: TouchItem;
group: TouchGroup _ touchItem.group;
touchItem.joint _ NIL;
touchItem.seg _ NIL;
group.list _ DeleteTouchItemFromList[touchItem, group.list];
IF group.list.rest = NIL THEN {
lastItem _ group.list.first;
IF lastItem.touchingPartType = joint THEN {
lastItem.joint.touchItem _ NIL;
lastItem.joint _ NIL;
}
ELSE {
lastItem.seg.touchItemList _ DeleteTouchItemFromList[lastItem, lastItem.seg.touchItemList];
lastItem.seg _ NIL;
};
group.list _ NIL;
gargoyleData.touching _ DeleteTouchGroupFromList[group, gargoyleData.touching];
};
};

SequenceDeleted: PUBLIC PROC [seq: Sequence, gargoyleData: GargoyleData] = {
jointGen: JointGenerator;
joint: Joint;
segGen: SegmentGenerator;
jointGen _ GGSequence.JointsInSequence[seq];
FOR i: INT _ GGSequence.NextJoint[jointGen], GGSequence.NextJoint[jointGen] UNTIL i = -1 DO
joint _ NARROW[Rosary.Fetch[seq.traj.joints, i]];
IF joint.touchItem # NIL THEN {
DeleteTouchItem[joint.touchItem, gargoyleData];
joint.touchItem _ NIL;
};
ENDLOOP;
segGen _ GGSequence.SegmentsInSequence[seq];
FOR seg: Segment _ GGSequence.NextSegment[segGen], GGSequence.NextSegment[segGen] UNTIL seg = NIL DO
FOR itemList: LIST OF TouchItem _ seg.touchItemList, itemList.rest UNTIL itemList = NIL DO
DeleteTouchItem[itemList.first, gargoyleData];
ENDLOOP;
seg.touchItemList _ NIL;
ENDLOOP;
};
TrajDeleted: PUBLIC PROC [traj: Traj, gargoyleData: GargoyleData] = {
jointGen: JointGenerator;
joint: Joint;
segGen: SegmentGenerator;
jointGen _ GGSequence.JointsInTraj[traj];
FOR i: INT _ GGSequence.NextJoint[jointGen], GGSequence.NextJoint[jointGen] UNTIL i = -1 DO
joint _ NARROW[Rosary.Fetch[traj.joints, i]];
IF joint.touchItem # NIL THEN {
DeleteTouchItem[joint.touchItem, gargoyleData];
joint.touchItem _ NIL;
};
ENDLOOP;
segGen _ GGSequence.SegmentsInTraj[traj];
FOR seg: Segment _ GGSequence.NextSegment[segGen], GGSequence.NextSegment[segGen] UNTIL seg = NIL DO
FOR itemList: LIST OF TouchItem _ seg.touchItemList, itemList.rest UNTIL itemList = NIL DO
DeleteTouchItem[itemList.first, gargoyleData];
ENDLOOP;
seg.touchItemList _ NIL;
ENDLOOP;
};
OutlineDeleted: PUBLIC PROC [outline: Outline, gargoyleData: GargoyleData] = {
trajGen: TrajGenerator;
trajGen _ GGOutline.TrajsInOutline[outline];
FOR traj: Traj _ GGObjects.NextTraj[trajGen], GGObjects.NextTraj[trajGen] UNTIL traj = NIL DO
TrajDeleted[traj, gargoyleData];
ENDLOOP;
};

SliceDeleted: PUBLIC PROC [slice: Slice, gargoyleData: GargoyleData] = {
ERROR NotYetImplemented;
};

TouchGroupOfItem: PUBLIC PROC [item: TouchItem] RETURNS [touchGroup: TouchGroup] = {
touchGroup _ item.group;
};
AllTouchItems: PUBLIC PROC [touchGroup: TouchGroup] RETURNS [touchItemGen: TouchItemGenerator] = {
touchItemGen _ NEW[TouchItemGeneratorObj _ [
list: touchGroup.list
]];
};

NextTouchItem: PUBLIC PROC [touchItemGen: TouchItemGenerator] RETURNS [item: TouchItem] = {
IF touchItemGen.list = NIL THEN RETURN[NIL];
item _ touchItemGen.list.first;
touchItemGen.list _ touchItemGen.list.rest;
};



DrawAllTouchPoints: PUBLIC PROC [dc: Imager.Context, gargoyleData: GargoyleData] = {
FOR groupList: LIST OF TouchGroup _ gargoyleData.touching, groupList.rest UNTIL groupList = NIL DO
GGShapes.DrawPlus[dc, groupList.first.point];
ENDLOOP;
};

DescribeAllTouchPoints: PUBLIC PROC [gargoyleData: GargoyleData] = {
text: Rope.ROPE;
FOR groupList: LIST OF TouchGroup _ gargoyleData.touching, groupList.rest UNTIL groupList = NIL DO
text _ GGDescribe.DescribeTouchGroup[groupList.first];
GGError.AppendTypescript[gargoyleData.feedback, text, oneLiner];
ENDLOOP;
};


FindTouchItemAndNeighbors: PROC [entity: TouchItem, entityList: LIST OF TouchItem] RETURNS [beforeEnt, ent, afterEnt: LIST OF TouchItem] = {
lastE: LIST OF TouchItem _ NIL;
eList: LIST OF TouchItem _ entityList;
IF eList = NIL THEN ERROR EntityNotFound;
UNTIL eList = NIL DO
IF eList.first = entity THEN {
beforeEnt _ lastE; ent _ eList; afterEnt _ eList.rest; RETURN};
lastE _ eList;
eList _ eList.rest;
ENDLOOP;
SIGNAL EntityNotFound;
};

DeleteTouchItemFromList: PUBLIC PROC [entity: TouchItem, entityList: LIST OF TouchItem] RETURNS [smallerList: LIST OF TouchItem] = {
beforeEnt, ent, afterEnt: LIST OF TouchItem;
notFound: BOOL _ FALSE;
[beforeEnt, ent, afterEnt] _ FindTouchItemAndNeighbors[entity, entityList];
IF notFound THEN RETURN[entityList];
IF beforeEnt = NIL THEN smallerList _ afterEnt
ELSE {
beforeEnt.rest _ afterEnt;
smallerList _ entityList;
};
}; -- end of DeleteTouchItemFromList

FindTouchGroupAndNeighbors: PROC [entity: TouchGroup, entityList: LIST OF TouchGroup] RETURNS [beforeEnt, ent, afterEnt: LIST OF TouchGroup] = {
lastE: LIST OF TouchGroup _ NIL;
eList: LIST OF TouchGroup _ entityList;
IF eList = NIL THEN ERROR EntityNotFound;
UNTIL eList = NIL DO
IF eList.first = entity THEN {
beforeEnt _ lastE; ent _ eList; afterEnt _ eList.rest; RETURN};
lastE _ eList;
eList _ eList.rest;
ENDLOOP;
SIGNAL EntityNotFound;
};
EntityNotFound: PUBLIC SIGNAL = CODE;

DeleteTouchGroupFromList: PUBLIC PROC [entity: TouchGroup, entityList: LIST OF TouchGroup] RETURNS [smallerList: LIST OF TouchGroup] = {
beforeEnt, ent, afterEnt: LIST OF TouchGroup;
notFound: BOOL _ FALSE;
[beforeEnt, ent, afterEnt] _ FindTouchGroupAndNeighbors[entity, entityList];
IF notFound THEN RETURN[entityList];
IF beforeEnt = NIL THEN smallerList _ afterEnt
ELSE {
beforeEnt.rest _ afterEnt;
smallerList _ entityList;
};
}; -- end of DeleteTouchGroupFromList

END.



��T��GGTouchImpl.mesa
Copyright c 1985 by Xerox Corporation.  All rights reserved.
Last edited by Bier on December 28, 1986 3:08:57 pm PST
Contents:  Implements a data structures which remembers which trajectory is touching which other trajectory and where.
Pier, October 20, 1986 5:16:08 pm PDT


Updating when something has moved -- the basic routines.
The group has been updated, already.  Ignore this update.
FOR itemList: LIST OF TouchItem _ group.list, itemList.rest UNTIL itemList = NIL DO
IF itemList.first = item THEN RETURN[TRUE];
ENDLOOP;
RETURN[FALSE];

Updating when something has moved -- convenience routines (which repeatedly call the basic routines for many joints and segments).

Updating when something has been deleted -- the basic routine.
Remove the touch item from the group's list.  If the group has only one remaining object, remove the group from the global list.
Updating when something has been deleted -- convenience routines (which repeatedly call the basic routines for many joints and segments).
Browsing.
Drawing.

List Processing Utilities (will polymorphism never come?)
�Ê
T��˜�code™Kšœ<™<K™7K™vK™%—K™�šÏk	˜	KšœÊ˜ÊK˜�—šœ
œ˜Kšœ_˜fKšœ
˜—Kš˜K˜�Kšœœ˜!Kšœœ!˜3Kšœœ˜!Kšœœ˜1Kšœ	œ˜%Kšœœ˜!Kšœ	œ˜'Kšœ
œ˜'Kšœœ˜Kšœœ!˜7Kšœœ˜.K˜�Kšœœœ˜%Kšœœ ˜3Kšœœ#˜9Kšœœœ˜#Kšœœ˜1K˜�Kšœœœ˜5šœœ!˜<K˜�—˜�K˜�—Kšœœœœ˜(K˜�šÏnœœœ,œ˜hšœœ˜Kšœœ˜
Kšœ˜K˜—Kšœœ˜;K˜K˜�—šžœœœ4œ˜fšœœ˜Kšœ˜Kšœ˜K˜Kšœ
˜
Kšœœ˜	K˜K˜—Kšœœ˜.˜K˜�——šž
œœœEœ˜yšœœ˜Kšœ˜Kšœ˜K˜Kšœœ˜Kšœ	˜	Kšœ˜K˜—Kšœœ˜.˜K˜�——šžœœœ=˜UKšœ!˜!Kšœœœ˜Kšœ%˜%šœMœ	œ˜dKšœ˜Kšœœ˜'—Kšœ˜Kšœœ˜KšœP˜PK˜K˜�—K™�K™8šžœœœ!˜@šœœœ4œ
œ˜bKšœœ˜ —Kšœ˜K˜K˜�—šžœœœ@˜]K˜Kšœ˜šœœ˜K™9šœœœ'œœ™SKšœœœœ™+—Kšœ™Kšœœ™Kšœ˜K˜—Kšœœ˜Kšœ˜Kšœ˜šœFœœ˜`Kšœ˜%˜
šœœGœ˜SKšÏbÐbkœ˜Kšœ;˜;K˜—K˜—˜šœœEœ˜QKšŸZœ˜[Kšœ;˜;K˜—K˜—Kšœœ˜—Kšœ˜Kšœœœœ˜šœœœÏc%˜EKšœ'˜'Kšœ˜%˜
KšŸ œ˜Kšœ;˜;K˜—˜KšŸZœ˜[Kšœ;˜;K˜—Kšœœ˜KšœO˜OK˜—K˜—K™�K™‚šÐbn
œœœ^œ˜€Kšœ˜K˜
K˜Kšœ,˜,šœœBœ˜[Kšœœ#˜1šœœœ˜Kšœ=˜=K˜——Kšœ˜Kšœ,˜,šœOœœ˜dšœœœ.œœ˜ZKšœT˜TKšœH˜H—Kšœ˜—Kšœ˜K˜K˜�—š¢	œœœ[œ˜yKšœ˜K˜
K˜Kšœ)˜)šœœBœ˜[Kšœœ˜-šœœœ˜Kšœ=˜=K˜——Kšœ˜Kšœ)˜)šœOœœ˜dšœœœ.œœ˜ZKšœT˜TKšœH˜H—Kšœ˜—Kšœ˜K˜—K™�K™>šžœœœ7˜SK™€Kšœ˜Kšœ$˜$Kšœœ˜Kšœœ˜Kšœ<˜<šœœœ˜Kšœ˜šœ#œ˜+Kšœœ˜Kšœœ˜K˜—šœ˜Kšœ[˜[Kšœœ˜K˜—Kšœ
œ˜KšœO˜OK˜—K˜—K˜�Kšœ)¡`™‰šžœœœ0˜LKšœ˜K˜
K˜Kšœ,˜,šœœBœ˜[Kšœœ#˜1šœœœ˜Kšœ/˜/Kšœœ˜K˜——Kšœ˜Kšœ,˜,šœOœœ˜dšœœœ.œœ˜ZKšœ.˜.—Kšœ˜Kšœœ˜—Kšœ˜Kšœ˜—šžœœœ-˜EKšœ˜K˜
K˜Kšœ)˜)šœœBœ˜[Kšœœ˜-šœœœ˜Kšœ/˜/Kšœœ˜K˜——Kšœ˜Kšœ)˜)šœOœœ˜dšœœœ.œœ˜ZKšœ.˜.—Kšœ˜Kšœœ˜—Kšœ˜Kšœ˜—šžœœœ3˜NK˜Kšœ,˜,šœGœœ˜]Kšœ ˜ —Kšœ˜K˜K˜�—šžœœœ/˜HKšœ˜K˜K˜�—K™	šžœœœœ˜TKšœ˜K˜—šž
œœœœ'˜bšœœ˜,Kšœ˜K˜—K˜K˜�—šž
œœœ$œ˜[Kš
œœœœœ˜,Kšœ˜Kšœ+˜+K˜K˜�—K˜�K˜�K™šžœœœ5˜Tšœœœ4œ
œ˜bKšœ-˜-—Kšœ˜K˜K˜�—šžœœœ!˜DKšœœ˜šœœœ4œ
œ˜bKšœ6˜6Kšœ@˜@—Kšœ˜K˜K˜�—K™�K™9K˜�šžœœ!œœœœœ˜ŒKšœœœ
œ˜Kšœœœ˜&Kšœ	œœœ˜)šœ	œ˜Kšœœ˜Kšœ7œ˜?Kšœ˜Kšœ˜—Kšœ˜Kšœ˜Kšœ˜K˜�—šžœœœ!œœœœœ˜„Kšœœœ˜,Kšœ
œœ˜KšœK˜KKšœ
œœ
˜$Kšœ
œœ˜.šœ˜Kšœ˜Kšœ˜K˜—Kšœ¡!˜$K˜�—šžœœ"œœ
œœœ˜Kšœœœœ˜ Kšœœœ˜'Kšœ	œœœ˜)šœ	œ˜Kšœœ˜Kšœ7œ˜?Kšœ˜Kšœ˜—Kšœ˜Kšœ˜Kšœ˜—šœœœœ˜%K˜�—šžœœœ"œœ
œœœ˜ˆKšœœœ˜-Kšœ
œœ˜KšœL˜LKšœ
œœ
˜$Kšœ
œœ˜.šœ˜Kšœ˜Kšœ˜K˜—Kšœ¡"˜%—K˜�Kšœ˜K˜�K˜�K˜�—�…—����,¨��>P��