TubeContourImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Bloomenthal, February 24, 1987 6:14:39 pm PST
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];
};