<> <> <> 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; <<>> <> 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; <> 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] ~ { <> 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] ~ { <> 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] ~ { <> 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. ..