TubeIOImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Bloomenthal, May 22, 1986 11:54:44 pm PDT
DIRECTORY Controls, FS, Imager, ImagerFont, ImagerInterpress, IO, Matrix3d, Spline3d, TubeDefs, TubeDisplay, TubeIO, TubeStructure, Vector3d;
TubeIOImpl: CEDAR PROGRAM
IMPORTS Controls, FS, Imager, ImagerFont, ImagerInterpress, IO, Matrix3d, Spline3d, TubeDisplay, TubeStructure, Vector3d
EXPORTS TubeIO
~ BEGIN
OPEN TubeDefs;
PI:    REAL ~ 3.1415926535;
OuterData: TYPE ~ Controls.OuterData;
PointProc: TYPE ~ TubeIO.PointProc;
PolyProc:  TYPE ~ TubeIO.PolyProc;
QueryAndPointsPolyOut: PUBLIC PROC [tube: Tube, outer: OuterData, m: Matrix ← NIL] ~ {
nPoints, nPolys: INT;
fileName: ROPE ← Controls.TypeScriptReadFileName[outer];
IF fileName = NIL THEN RETURN;
[nPoints, nPolys] ← PointsPolysOut[tube, fileName, m];
Controls.TypeScriptWrite[outer, IO.PutFR["%g points and %g polys written\n",
IO.int[nPoints], IO.int[nPolys]]];
};
QueryAndMaxPointsPolyOut: PUBLIC PROC [tube: Tube, outer: OuterData, m: Matrix ← NIL]
~ {
nPoints, nPolys: INT;
fileName: ROPE ← Controls.TypeScriptReadFileName[outer];
IF fileName = NIL THEN RETURN;
[nPoints, nPolys] ← MaxPointsPolysOut[tube, fileName, m];
Controls.TypeScriptWrite[outer, IO.PutFR["%g points and %g polys written\n", IO.int[nPoints], IO.int[nPolys]]];
};
PointsPolysOut: PUBLIC PROC [tube: Tube, fileName: ROPE, m: Matrix ← NIL]
RETURNS [nPoints, nPolys: INT] ~ {
out: IO.STREAMFS.StreamOpen[fileName, $create];
IO.PutF[out, "Vertices: idx: xyz: nrm: uvw:\n\n"];
nPoints ← Points[tube, out, , m];
IO.PutF[out, "\nPolygons: idx:\n\n"];
nPolys ← Polys[tube, out];
IO.Close[out];
};
MaxPointsPolysOut: PUBLIC PROC [tube: Tube, fileName: ROPE, m: Matrix ← NIL]
RETURNS [nPoints, nPolys: INT] ~ {
out: IO.STREAMFS.StreamOpen[fileName, $create];
nPoints ← Points[tube, out, MaxPointProc, m];
IO.PutF[out, "-1\n"];
nPolys ← Polys[tube, out, MaxPolyProc];
IO.PutF[out, "-1\n"];
IO.Close[out];
};
DefaultPointProc: PUBLIC PointProc ~ {
IO.PutF[out, "%g\t", IO.int[id]];
IO.PutF[out, "%6.5f %6.5f %6.5f\t", IO.real[p.x], IO.real[p.y], IO.real[p.z]];
IO.PutF[out, "%6.5f %6.5f %6.5f\t", IO.real[n.x], IO.real[n.y], IO.real[n.z]];
IO.PutF[out, "%6.5f %6.5f 0.0\n", IO.real[u], IO.real[v]];
};
DefaultPolyProc: PUBLIC PolyProc ~ {
IO.PutF[out,"%g\t%4g %4g %4g\n", IO.int[id], IO.int[p0], IO.int[p1], IO.int[p2]];
};
MaxPointProc: PUBLIC PointProc ~ {
IO.PutF[out, "%g,", IO.int[id]];
IO.PutF[out, "%6.5f,%6.5f,%6.5f,", IO.real[p.x], IO.real[p.y], IO.real[p.z]];
IO.PutF[out, "%6.5f,%6.5f,%6.5f,", IO.real[n.x], IO.real[n.y], IO.real[n.z]];
IO.PutF[out, "%6.5f,%6.5f,\n", IO.real[u], IO.real[v]];
};
MaxPolyProc: PUBLIC PolyProc ~ {
IO.PutF[out, "%g,%g,%g,%g,\n", IO.int[id], IO.int[p0], IO.int[p1], IO.int[p2]];
};
Points: PUBLIC PROC [
tube: Tube, out: IO.STREAM, pointProc: PointProc ← DefaultPointProc, view: Matrix ← NIL]
RETURNS [nPoints: INT] ~ {
See TubeDisplayImpl.ShowNormals
pointId: INT ← 0;
uRangeStart: REAL ← 2.0*PI*tube.r0;
OneSpline: PROC [t: Tube, iStart: NAT, uRange0, v: REAL] ~ {
IF t # NIL THEN { 
uRange1: REAL ← uRange0*(0.5+0.5*(t.r1/t.r0)); -- a compromise
duRange: REAL ← (uRange1-uRange0)/(t.axialRes-1.0);
circle: PairSequence ← TubeStructure.GetCircle[t.circleRes];
tapered: BOOL ← t.r1 # t.r0;
vFactor: REALIF tapered THEN (t.r0-t.r1)/Vector3d.Distance[t.p0, t.p1] ELSE 1.0;
pNow, pPrev: Triple ← t.p0;
odd: BOOL ← t.circleRes MOD 2 = 1;
istart: NATIF t.prev # NIL AND t.prev.next = t AND t.prev.r1 = t.r0 THEN 1 ELSE 0;
FOR i: NAT IN[iStart..t.axialRes) DO
uRange: REAL ← uRange0+i*duRange;
u: REAL ← 0.0;
du: REAL ← 0.5*uRange/t.circleRes;
m: Matrix ← t.frames[i].m;
mm: Matrix ← IF view # NIL THEN Matrix3d.Mul[m, view] ELSE m;
pPrev ← pNow;
pNow ← [m[3][0], m[3][1], m[3][2]];
IF i # 0 THEN v ← v+Vector3d.Distance[pNow, pPrev];
FOR j: NAT IN[0..t.circleRes) DO
p: Triple ← Matrix3d.TransformPair[circle[j], mm];
n: Triple ← Matrix3d.TransformVec[[circle[j].x, circle[j].y, 0.0], mm];
IF tapered THEN {
vv: Triple ← Spline3d.Velocity[t.c, t.frames[i].t];
len: REAL ← Vector3d.Mag[n];
n ← Vector3d.Add[n, Vector3d.Mul[vv, len*vFactor/Vector3d.Mag[vv]]];
};
n ← Vector3d.Normalize[n];
pointProc[out, pointId, p, n, u, v];
pointId ← pointId+1;
u ← IF j < t.circleRes/2 OR odd THEN u+du ELSE u-du; -- radial symmetry for u
ENDLOOP;
ENDLOOP;
IF t.next # NIL AND t.next.circleRes = t.circleRes AND t.next.r0 = t.r1
THEN OneSpline[t.next, 1, uRange1, v]  -- skip first frame
ELSE OneSpline[t.next, 0, uRange1, v];  -- do first frame
FOR n: NAT IN [0..t.nBranches) DO
OneSpline[t.branches[n], 0, uRangeStart, v]; -- use first frame of first tube of branch
ENDLOOP;
};
};
OneSpline[tube, 0, uRangeStart, 0.0];     -- start with first frame of first tube
RETURN[pointId];
};
Polys: PUBLIC PROC [tube: Tube, out: IO.STREAM, polyProc: PolyProc ← DefaultPolyProc]
RETURNS [nPolys: INT] ~ {
polyId, pointId: NAT ← 0;
OneSpline: PROC [t: Tube] ~ {
IF t # NIL THEN { 
cRes: NAT ← t.circleRes;
FOR i: NAT IN [0..t.axialRes-1) DO     -- connect ith frame to (i+1)th frame
n: NAT ← pointId;
FOR ii: NAT IN[0..cRes) DO
nn: NATIF ii = cRes-1 THEN pointId ELSE n+1;
r: NAT ← n+cRes;
rr: NAT ← nn+cRes;
polyProc[out, polyId, r, nn, n];
polyId ← polyId+1;
polyProc[out, polyId, rr, nn, r];
n ← n+1;
polyId ← polyId+1;
ENDLOOP;
pointId ← pointId+cRes;
ENDLOOP;
IF t.next = NIL OR t.next.circleRes # t.circleRes OR t.next.r0 # t.r1
THEN pointId ← pointId+cRes;  -- end of branch or discontinuity from t to t.next
OneSpline[t.next];
FOR n: NAT IN [0..t.nBranches) DO OneSpline[t.branches[n]]; ENDLOOP;
};
};
OneSpline[tube];
RETURN[polyId];
};
NPolys: PROC [tube: Tube] RETURNS [NAT] ~ {
n: NAT ← 0;
FOR t: Tube ← tube, t.next WHILE t # NIL DO
n ← n+2*(t.axialRes-1)*t.circleRes;
ENDLOOP;
RETURN[n];
};
NPoints: PROC [tube: Tube] RETURNS [NAT] ~ {
n: NAT ← 0;
FOR t: Tube ← tube, t.next WHILE t # NIL DO
n ← n+(t.axialRes-1)*t.circleRes;
ENDLOOP;
RETURN[n+tube.circleRes];
};
QueryAndIPOut: PUBLIC PROC [tube: Tube, outer: OuterData, details: Details, m: Matrix] ~ {
fileName: ROPE ← Controls.TypeScriptReadFileName[outer];
IF fileName # NIL THEN {
ref: ImagerInterpress.Ref ← ImagerInterpress.Create[fileName];
IPOut[ref, tube, details, m];
ImagerInterpress.Close[ref];
};
};
IPOut: PUBLIC PROC [ref: ImagerInterpress.Ref, tube: Tube, details: Details, m: Matrix] ~ {
font: ImagerFont.Font ← ImagerFont.Scale[ImagerFont.Find["xerox/pressfonts/helvetica-mrr"], 12.0];
ContextProc: PROC [context: Context] ~ {
metersPerPoint: REAL ~ .0254/72.0;
Imager.ScaleT[context, metersPerPoint];
Imager.SetStrokeWidth[context, 1.0];
Imager.SetStrokeEnd[context, round];
Imager.SetFont[context, font];
Imager.TranslateT[context, [0.0, 0.5*11.0*72.0]];
TubeDisplay.ShowTube[tube, context, details, m];
};
ImagerInterpress.DoPage[ref, ContextProc];
};
WriteTubeInfo: PUBLIC PROC [tube: Tube, outer: OuterData] ~ {
nPoints, nPolys, minCres, maxCres: INTEGER;
[nPoints, nPolys, minCres, maxCres] ← TubeStructure.TubeResInfo[tube];
Controls.TypeScriptWrite[outer, IO.PutFR["%g points, %g polygons, cres: %g-%g\n",
IO.int[nPoints], IO.int[nPolys], IO.int[minCres], IO.int[maxCres]]];
};
END.