DIRECTORY Contours, Matrix3d, Real, TubeDefs, TubeContour, TubeGeometry, TubeMisc, Vector2; TubeContourImpl: CEDAR PROGRAM IMPORTS Contours, Matrix3d, Real, TubeGeometry, TubeMisc, Vector2 EXPORTS TubeContour ~ BEGIN OPEN TubeDefs; ContourRep: TYPE ~ Contours.ContourRep; ContourSequenceRep: TYPE ~ Contours.ContourSequenceRep; NContours: PUBLIC PROC [tube: Tube] RETURNS [INTEGER] ~ { RETURN[IF tube.contours # NIL THEN tube.contours.length ELSE 0]; }; TestContourSequence: PROC [contours: ContourSequence] RETURNS [ContourSequence] ~ { IF contours = NIL OR contours.length >= contours.maxLength THEN contours _ LengthenContourSequence[contours]; RETURN[contours]; }; LengthenContourSequence: PROC [contours: ContourSequence] RETURNS [ContourSequence] ~ { nContours: INTEGER _ IF contours = NIL THEN 0 ELSE contours.length; new: ContourSequence _ NEW[ContourSequenceRep[MAX[5, Real.RoundI[1.3*nContours]]]]; FOR i: NAT IN[0..nContours) DO new[i] _ contours[i]; ENDLOOP; FOR i: NAT IN[nContours..new.maxLength) DO new[i] _ NEW[ContourRep]; ENDLOOP; new.length _ nContours; RETURN[new]; }; AddContour: PUBLIC PROC [tube: Tube, contour: Contour] ~ { InsertContour: PROC [contour: Contour, contours: ContourSequence, n: NAT] ~ { FOR i: INT DECREASING IN [n..contours.length) DO contours[n+1] _ contours[n]; ENDLOOP; contours[n] _ contour; }; new: Contour _ NEW[ContourRep _ contour^]; tube.contours _ TestContourSequence[tube.contours]; SELECT TRUE FROM tube.contours.length = 0 => tube.contours[0] _ new; new.t < tube.contours[0].t => InsertContour[new, tube.contours, 0]; new.t > tube.contours[tube.contours.length-1].t => tube.contours[tube.contours.length] _ new; ENDCASE => { n: NAT _ 0; WHILE tube.contours[n].t < new.t DO n _ n+1; ENDLOOP; IF tube.contours[n].t = new.t THEN { tube.contours[n] _ new; RETURN; }; InsertContour[new, tube.contours, n]; }; tube.contours.length _ tube.contours.length+1; }; DivideContours: PUBLIC PROC [tube, tube0, tube1: Tube, t: REAL] ~ { circle: Contour _ Contours.Circle[tube.circleRes]; NewTs: PROC [tube: Tube, t0, t1: REAL] ~ { div: REAL _ IF t0 = t1 THEN 1.0 ELSE 1.0/(t1-t0); FOR n: NAT IN [0..tube.contours.length) DO tube.contours[n].t _ (tube.contours[n].t-t0)*div; ENDLOOP; }; IF tube.contours # NIL THEN { contours: ContourSequence _ tube.contours; -- tube may = tube0 or tube1 divideContour: Contour _ TContour[contours, circle, t]; tube0.contours _ tube1.contours _ NIL; AddContour[tube1, divideContour]; FOR n: NAT IN [0..contours.length) DO SELECT contours[n].t FROM <= t => AddContour[tube0, contours[n]]; >= t => AddContour[tube1, contours[n]]; ENDCASE; ENDLOOP; AddContour[tube0, divideContour]; NewTs[tube0, 0.0, t]; NewTs[tube1, t, 1.0]; }; }; Alpha: PROC [t, t0, t1: REAL] RETURNS [REAL] ~ { RETURN[IF t0 = t1 THEN t0 ELSE (t-t0)/(t1-t0)]; }; TContour: PUBLIC PROC [contours: ContourSequence, circle: Contour, t: REAL] RETURNS [Contour] ~ { IF contours = NIL THEN RETURN[circle] ELSE { c0, c1: Contour _ NIL; FOR n: NAT IN [0..contours.length) WHILE contours[n].t <= t DO c0 _ contours[n]; ENDLOOP; FOR n: NAT DECREASING IN [0..contours.length) WHILE contours[n].t >= t DO c1 _ contours[n]; ENDLOOP; RETURN[SELECT TRUE FROM c0 = NIL AND c1 = NIL => circle, c0 = NIL => Contours.Interpolate[circle, c1, Alpha[t, 0.0, c1.t]], c1 = NIL => Contours.Interpolate[c0, circle, Alpha[t, c0.t, 1.0]], ENDCASE => Contours.Interpolate[c0, c1, Alpha[t, c0.t, c1.t]]]; }; }; Skin: PUBLIC PROC [tube: Tube] ~ { InnerSkin: TubeProc ~ { circle: Contour _ Contours.Circle[tube.circleRes]; FOR n: INTEGER IN [0..TubeGeometry.NFrames[tube]) DO f: Frame _ tube.frames[n]; f.contour _ TContour[tube.contours, circle, f.t]; f.normals _ SELECT TRUE FROM f.contour = circle => f.contour.pairs, ENDCASE => Contours.Normals[f.contour]; ENDLOOP; }; TubeMisc.ApplyToTube[tube, InnerSkin]; }; PropagateCircleRes: PUBLIC PROC [tube: Tube, circleRes: INTEGER] ~ { tubeProc: TubeProc ~ { IF tube = NIL THEN RETURN; tube.circleRes _ circleRes; FOR n: NAT IN [0..TubeGeometry.NFrames[tube]) DO f: Frame _ tube.frames[n]; IF f.contour # NIL AND f.contour.circle THEN f.contour _ circle; ENDLOOP; }; circle: Contour _ Contours.Circle[circleRes]; TubeMisc.ApplyToTube[tube, tubeProc]; }; ScreenCircleRes: PUBLIC PROC [tube: Tube, view: Matrix] RETURNS [INTEGER] ~ { CircleRes: PROC [p: Triple, r: REAL] RETURNS [NAT] ~ { q: Vector2.VEC _ Matrix3d.TransformD[p, view]; q1: Vector2.VEC _ Matrix3d.TransformD[[p.x+r, p.y, p.z], view]; q2: Vector2.VEC _ Matrix3d.TransformD[[p.x, p.y+r, p.z], view]; l: REAL _ MAX[Vector2.Length[Vector2.Sub[q, q1]], Vector2.Length[Vector2.Sub[q, q2]]]; RETURN[3+Real.RoundI[0.4*l]]; }; res: INTEGER _ IF tube.frames = NIL THEN 0 ELSE MAX[ CircleRes[tube.p0, tube.frames[0].scale], CircleRes[tube.p1, tube.frames[tube.frames.length-1].scale]]; IF res MOD 2 = 1 THEN res _ res+1; RETURN[res]; }; END. †TubeContourImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Bloomenthal, February 24, 1987 6:14:39 pm PST Κx˜šœ™Jšœ Οmœ1™Kšœ˜Kšžœ˜—š žœžœž œžœžœž˜IKšœ˜Kšžœ˜—šžœžœžœž˜Kšœžœžœžœ ˜ Kšœžœ:˜BKšœžœ:˜BKšžœ8˜?—K˜——K˜K˜—š œžœžœ˜"š  œ˜Kšœ2˜2šžœžœžœ!ž˜4K˜K˜1šœ žœžœž˜Kšœ&˜&Kšžœ ˜'—Kšžœ˜—K˜—K˜&K˜K˜—š œžœžœžœ˜Dš œ˜Kšžœžœžœžœ˜Kšœ˜šžœžœžœ!ž˜0K˜Kšžœ žœžœžœ˜@Kšžœ˜—K˜—Kšœ-˜-K˜%K˜K˜—š  œžœžœžœžœ˜Mš   œžœžœžœžœ˜6Jšœ žœ ˜/Jšœ žœ0˜?Jšœ žœ0˜?JšœžœžœI˜VJšžœ˜J˜—šœžœžœž˜#Jšžœ˜šžœžœ˜ Jšœ)˜)Jšœ=˜=——Jšžœžœžœ ˜"Jšžœ˜ J˜J˜——Jšžœ˜—…—