TubePickImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Bloomenthal, May 2, 1986 2:23:54 pm PDT
DIRECTORY Matrix3d, Spline3d, Vector3d, TubeDefs, TubePick, TubeStructure;
TubePickImpl:
CEDAR
PROGRAM
IMPORTS Matrix3d, Spline3d, TubeStructure, Vector3d
EXPORTS TubePick
~ BEGIN
OPEN TubeDefs;
ScreenPick:
PUBLIC
PROC [tube: Tube, mouse: Mouse, view: Matrix, pick: Pick] ~ {
IF pick = NIL THEN RETURN;
FindPick[tube, mouse, view, pick];
IF mouse.button = left
THEN PointPick[pick]
ELSE SplinePick[mouse, pick];
};
FindPick:
PUBLIC
PROC [tube: Tube, mouse: Mouse, view: Matrix, pick: Pick] ~ {
temp, dist, minDist: REAL ← 1000.0;
hasPersp: BOOL ← Matrix3d.HasPerspective[view];
IF mouse.state = down
THEN
FOR t: Tube ← tube, t.next
WHILE t #
NIL
DO
t.xc ← Matrix3d.Mul[t.c, view, t.xc];
ENDLOOP;
FOR t: Tube ← tube, t.next
WHILE t #
NIL
DO
[t: temp, dist: dist] ← Spline3d.NearestPair[[mouse.x, mouse.y], t.xc, hasPersp];
IF temp < 0.05 THEN temp ← 0.0 ELSE IF temp > .95 THEN temp ← 1.0;
IF dist < minDist THEN {minDist ← dist; pick.t ← temp; pick.tube ← t};
ENDLOOP;
};
PointPick:
PUBLIC
PROC [pick: Pick] ~ {
pick.tubePick0 ← pick.tubePick1 ← NIL;
IF (pick.dividePending ← pick.t
IN (0.0..1.0))
THEN {
pick.tubePt0 ← pick.tubePt1 ← pick.tube;
pick.tan ← Spline3d.Tangent[pick.tube.c, pick.t];
pick.origPos ← Spline3d.Position[pick.tube.c, pick.t];
}
ELSE {
IF pick.t = 0.0
THEN {
pick.tubePt1 ← pick.tube;
pick.tubePt0 ← pick.tubePt1.prev;
pick.tan ← pick.tube.v0;
pick.origPos ← pick.tube.p0;
}
ELSE {
pick.tubePt0 ← pick.tube;
pick.tubePt1 ← pick.tubePt0.next;
pick.tan ← pick.tube.v1;
pick.origPos ← pick.tube.p1;
};
};
pick.pos ← pick.origPos;
};
SplinePick:
PUBLIC
PROC [mouse: Mouse, pick: Pick] ~ {
pick.tubePick1 ← pick.tube;
IF mouse.button = middle THEN pick.tubePick0 ← pick.tube;
ensure tubePick0 precedes tubePick1:
FOR t: Tube ← pick.tubePick0, t.next
WHILE t #
NIL
DO
IF t = pick.tubePick1 THEN EXIT;
REPEAT
FINISHED => {
temp: Tube ← pick.tubePick0;
pick.tubePick0 ← pick.tubePick1;
pick.tubePick1 ← temp;
};
ENDLOOP;
set selected splines:
FOR t: Tube ← pick.tube, t.prev WHILE t # NIL DO t.selected ← FALSE; ENDLOOP;
FOR t: Tube ← pick.tube, t.next WHILE t # NIL DO t.selected ← FALSE; ENDLOOP;
FOR t: Tube ← pick.tubePick0, t.next
WHILE t #
NIL
AND t # pick.tubePick1.next
DO
t.selected ← TRUE;
ENDLOOP;
};
DivideSpline:
PUBLIC
PROC [pick: Pick] ~ {
IF NOT pick.dividePending OR pick.t NOT IN (0.0..1.0) THEN RETURN;
pick.tubePt0 ← pick.tube;
pick.tubePt1 ←
NEW[TubeRec ← [
c: NEW[Spline3d.CoeffsRep],
xc: NEW[Spline3d.CoeffsRep],
prev: pick.tubePt0,
selected: pick.tubePt0.selected,
next: pick.tubePt0.next,
p1: pick.tubePt0.p1,
r1: pick.tubePt0.r1,
twist1: pick.tubePt0.twist1]];
pick.tubePt0.next ← pick.tubePt1;
pick.tubePt0.p1 ← pick.tubePt1.p0 ← pick.origPos;
pick.tubePt0.r1 ← pick.tubePt1.r0 ← 0.5*(pick.tubePt0.r0+pick.tubePt1.r1);
pick.tubePt0.twist1 ← pick.tubePt1.twist0 ← 0.5*(pick.tubePt0.twist0+pick.tubePt1.twist1);
[] ← Spline3d.Reparameterize[pick.tubePt0.c, pick.t, 1.0, pick.tubePt1.c];
[] ← Spline3d.Reparameterize[pick.tubePt0.c, 0.0, pick.t, pick.tubePt0.c];
pick.tubePt0.v0 ← Spline3d.Tangent[pick.tubePt0.c, 0.0];
pick.tubePt1.v1 ← Spline3d.Tangent[pick.tubePt1.c, 1.0];
pick.tubePt0.v1 ← pick.tubePt1.v0 ← [
0.25*(3.0*(pick.tubePt1.p1.x-pick.tubePt0.p0.x)-pick.tubePt0.v0.x-pick.tubePt1.v1.x),
0.25*(3.0*(pick.tubePt1.p1.y-pick.tubePt0.p0.y)-pick.tubePt0.v0.y-pick.tubePt1.v1.y),
0.25*(3.0*(pick.tubePt1.p1.z-pick.tubePt0.p0.z)-pick.tubePt0.v0.z-pick.tubePt1.v1.z)];
pick.t ← 1.0;
pick.dividePending ← FALSE;
};
NewSplits:
PUBLIC
PROC [pick: Pick] ~ {
IF pick.tubePt0 #
NIL THEN
[] ← Spline3d.CoeffsFromHermite[[pick.tubePt0.p0, pick.tubePt0.p1, pick.tubePt0.v0, pick.tubePt0.v1], pick.tubePt0.c];
IF pick.tubePt1 #
NIL THEN
[] ← Spline3d.CoeffsFromHermite[[pick.tubePt1.p0, pick.tubePt1.p1, pick.tubePt1.v0, pick.tubePt1.v1], pick.tubePt1.c];
};
ChangeTangent:
PUBLIC
PROC [pick: Pick, tangent: Triple] ~ {
pick.tan ← tangent;
IF pick.tubePt0 # NIL THEN pick.tubePt0.v1 ← tangent;
IF pick.tubePt1 # NIL THEN pick.tubePt1.v0 ← tangent;
NewSplits[pick];
};
ChangePosition:
PUBLIC
PROC [pick: Pick, change: Triple] ~ {
pick.pos ← Vector3d.Add[pick.origPos, change];
IF pick.tubePt0 # NIL THEN pick.tubePt0.p1 ← pick.pos;
IF pick.tubePt1 # NIL THEN pick.tubePt1.p0 ← pick.pos;
NewSplits[pick];
};
NumberPicked:
PUBLIC PROC [pick: Pick]
RETURNS [
NAT] ~ {
Return number of splines currently selected:
n: NAT ← 0;
IF pick.tubePick0 = NIL OR pick.tubePick1 = NIL THEN RETURN[0];
FOR t: Tube ← pick.tubePick0, t.next
WHILE t #
NIL
AND t # pick.tubePick1.next
DO
n ← n+1;
ENDLOOP;
RETURN[n];
};
BeforePicked:
PUBLIC PROC [pick: Pick]
RETURNS [
NAT] ~ {
Return number of splines before sPick0:
n: NAT ← 0;
FOR t: Tube ← pick.tubePick0.prev, t.prev WHILE t # NIL DO n ← n+1; ENDLOOP;
RETURN[n];
};
AfterPicked:
PUBLIC PROC [pick: Pick]
RETURNS [
NAT] ~ {
Return number of splines after sPick1:
n: NAT ← 0;
FOR t: Tube ← pick.tubePick1.next, t.next WHILE t # NIL DO n ← n+1; ENDLOOP;
RETURN[n];
};
RemakePicked:
PUBLIC
PROC [pick: Pick, scale, epsilon:
REAL] ~ {
t0: Tube ← IF pick.tubePick0.prev # NIL THEN pick.tubePick0.prev ELSE pick.tubePick0;
t1: Tube ← IF pick.tubePick1.next # NIL THEN pick.tubePick1.next ELSE pick.tubePick1;
FOR t: Tube ← t0, t.next
WHILE t # t1.next
AND t #
NIL
DO
TubeStructure.MakeFrames[t, scale, epsilon];
ENDLOOP;
};
END.
..