Draw3dImpl:
CEDAR
PROGRAM
IMPORTS Clip3d, Draw2d, Imager, Matrix3d, Spline3d
EXPORTS Draw3d
~ BEGIN
Context: TYPE ~ Imager.Context;
Pair: TYPE ~ Vector3d.Pair;
Triple: TYPE ~ Vector3d.Triple;
Quad: TYPE ~ Vector3d.Quad;
Matrix: TYPE ~ Matrix3d.Matrix;
Coeffs: TYPE ~ Spline3d.Coeffs;
Bezier: TYPE ~ Spline3d.Bezier;
Mark:
PUBLIC
PROC [p: Triple, context: Context, m: Matrix, type: Draw2d.MarkType ← cross, label: Rope.
ROPE ←
NIL] ~ {
IF type # none
THEN {
q: Quad ← Matrix3d.TransformH[p, m];
IF q.z+q.w >= 0.0
THEN {
pp: Pair ← [q.x/q.w, q.y/q.w];
Draw2d.Mark[context, pp, type];
IF label # NIL THEN Draw2d.Label[context, pp, label];
};
};
};
PP:
PUBLIC
PROC [p0, p1: Triple, c: Context, m: Matrix, type: Draw2d.DrawType ← solid] ~ {
c0, c1: Pair;
IF Matrix3d.HasPerspective[m]
THEN {
off: BOOL;
[c0, c1, off] ← Clip3d.NearH[Matrix3d.TransformH[p0, m], Matrix3d.TransformH[p1, m]];
IF NOT off THEN Draw2d.Draw[c, c0, c1, type];
}
ELSE {
c0 ← Matrix3d.TransformD[p0, m];
c1 ← Matrix3d.TransformD[p1, m];
Draw2d.Draw[c, c0, c1, type];
};
};
PV:
PUBLIC
PROC [p, v: Triple, label: Rope.
ROPE ←
NIL, context: Context, m: Matrix, mark: Draw2d.MarkType ← none, scale:
REAL ← 0.2] ~ {
c0, c1, d: Pair;
pp: Triple ← [p.x+v.x, p.y+v.y, p.z+v.z];
IF Matrix3d.HasPerspective[m]
THEN {
off: BOOL;
[c0, c1, off] ← Clip3d.NearH[Matrix3d.TransformH[p, m], Matrix3d.TransformH[pp, m]];
IF off THEN RETURN;
IF mark # none THEN Mark[p, context, m, mark];
}
ELSE {
c0 ← Matrix3d.TransformD[p, m];
c1 ← Matrix3d.TransformD[pp, m];
IF mark # none THEN Draw2d.Mark[context, c0, mark];
};
d ← [c1.x-c0.x, c1.y-c0.y];
c1 ← [c0.x+scale*d.x, c0.y+scale*d.y];
Draw2d.Arrow[context, c1, c0];
IF label # NIL THEN Draw2d.Label[context, c1, label];
};
V:
PUBLIC
PROC [v: Triple, name: Rope.
ROPE ←
NIL, context: Context, m: Matrix] ~ {
xv: Triple ← Matrix3d.TransformVec[v, m];
Draw2d.Solid[context, [m[3][0], m[3][1]], [xv.x, xv.y]];
Draw2d.Label[context, [xv.x, xv.y], name];
};
Axes:
PUBLIC
PROC [context: Context, m: Matrix] ~ {
PV[[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], "X", context, m];
PV[[0.0, 0.0, 0.0], [0.0, 1.0, 0.0], "Y", context, m];
PV[[0.0, 0.0, 0.0], [0.0, 0.0, 1.0], "Z", context, m];
};
The following procedures are for drawing three-dimensional splines.
DrawCurve:
PUBLIC
PROC [c: Coeffs, context: Context, m: Matrix ←
NIL] ~ {
IF c #
NIL
THEN {
persp: BOOL ← Matrix3d.HasPerspective[m];
xc: Coeffs ← IF m = NIL THEN c ELSE Matrix3d.Mul[c, m];
nSegs: INTEGER ← Spline3d.Resolution[xc, 1.0];
dif: Coeffs ← Spline3d.FwdDif[xc, nSegs];
nCoords: NAT ← IF persp THEN 3 ELSE 1;
p0, p1: Pair ← [dif[0][0], dif[0][1]];
q0, q1: Quad ← [dif[0][0], dif[0][1], dif[0][2], dif[0][3]];
FOR i:
INTEGER
IN[0..nSegs)
DO
IF persp
THEN q1 ← [q0.x+dif[1][0], q0.y+dif[1][1], q0.z+dif[1][2], q0.w+dif[1][3]]
ELSE p1 ← [p0.x+dif[1][0], p0.y+dif[1][1]];
FOR j:
INTEGER
IN[0..nCoords]
DO
dif[1][j] ← dif[1][j]+dif[2][j];
dif[2][j] ← dif[2][j]+dif[3][j];
ENDLOOP;
IF persp
THEN {
c0, c1: Pair;
offScreen: BOOL;
[c0, c1, offScreen] ← Clip3d.NearH[q0, q1];
IF NOT offScreen THEN Draw2d.Solid[context, c0, c1];
q0 ← q1;
}
ELSE {
Draw2d.Solid[context, p0, p1];
p0 ← p1;
};
ENDLOOP;
};
};
DotCurve:
PUBLIC
PROC [c: Coeffs, context: Context, m: Matrix ←
NIL] ~ {
persp: BOOL ← Matrix3d.HasPerspective[m];
xc: Coeffs ← IF m = NIL THEN c ELSE Matrix3d.Mul[c, m];
nSegs: INTEGER ← 4*Spline3d.Resolution[xc, 1.0];
dif: Coeffs ← Spline3d.FwdDif[xc, nSegs];
nCoords: NAT ← IF persp THEN 3 ELSE 1;
p: Pair ← [dif[0][0], dif[0][1]];
q: Quad ← [dif[0][0], dif[0][1], dif[0][2], dif[0][3]];
FOR i:
INTEGER
IN[0..nSegs)
DO
IF persp
THEN {IF q.w+q.z >= 0.0 THEN Imager.MaskRectangle[context, [q.x/q.w, q.y/q.w, 1, 1]]}
ELSE Imager.MaskRectangle[context, [p.x, p.y, 1, 1]];
IF persp
THEN q ← [q.x+dif[1][0], q.y+dif[1][1], q.z+dif[1][2], q.w+dif[1][3]]
ELSE p ← [p.x+dif[1][0], p.y+dif[1][1]];
FOR j:
INTEGER
IN[0..nCoords]
DO
dif[1][j] ← dif[1][j]+dif[2][j];
dif[2][j] ← dif[2][j]+dif[3][j];
ENDLOOP;
ENDLOOP;
};
DrawBezierPolygon:
PUBLIC
PROC [b: Bezier, context: Context, m: Matrix ←
NIL, type: Draw2d.DrawType ← solid, close:
BOOL ←
FALSE] ~ {
PP[b.b0, b.b1, context, m, type];
PP[b.b1, b.b2, context, m, type];
PP[b.b2, b.b3, context, m, type];
IF close THEN PP[b.b0, b.b3, context, m, type];
};