<<>> <> <> <> DIRECTORY Basics, Commander, IO, Rope; ImplicitTestCubeEdgesImpl: CEDAR PROGRAM IMPORTS Basics, Commander, IO <> ~ BEGIN Dir: TYPE ~ {cw, ccw}; Face: TYPE ~ {l, r, t, b, n, f}; Edge: TYPE ~ {lb, lt, ln, lf, rb, rt, rn, rf, bn, bf, tn, tf}; Corner: TYPE ~ {lbn, lbf, ltn, ltf, rbn, rbf, rtn, rtf}; TwoCorners: TYPE ~ RECORD [c1, c2: Corner]; Cube: TYPE ~ ARRAY Corner OF BOOL; CornerName: PROC [c: Corner] RETURNS [Rope.ROPE] ~ { RETURN[SELECT c FROM lbn => "lbn", lbf => "lbf", ltn => "ltn", ltf => "ltf", rbn => "rbn", rbf => "rbf", rtn => "rtn", ENDCASE => "rtf"]; }; Bit: PROC [i: WORD, c: Corner] RETURNS [BOOL] ~ { exp: NAT _ SELECT c FROM lbn=>0,lbf=>1,ltn=>2,ltf=>3,rbn=>4,rbf=>5,rtn=>6,ENDCASE=>7; RETURN[IF Basics.BITAND[i, Basics.BITSHIFT[1, exp]] # 0 THEN TRUE ELSE FALSE]; }; NextCWEdge: PROC [edge: Edge, face: Face] RETURNS [ret: Edge] ~ { ret _ SELECT edge FROM lb => IF face = l THEN lf ELSE bn, lt => IF face = l THEN ln ELSE tf, ln => IF face = l THEN lb ELSE tn, lf => IF face = l THEN lt ELSE bf, rb => IF face = r THEN rn ELSE bf, rt => IF face = r THEN rf ELSE tn, rn => IF face = r THEN rt ELSE bn, rf => IF face = r THEN rb ELSE tf, bn => IF face = b THEN rb ELSE ln, bf => IF face = b THEN lb ELSE rf, tn => IF face = t THEN lt ELSE rn, ENDCASE => IF face = t THEN rt ELSE lf; }; OtherFace: PROC [edge: Edge, face: Face] RETURNS [ret: Face] ~ { ret _ SELECT edge FROM lb => IF face = b THEN l ELSE b, lt => IF face = l THEN t ELSE l, ln => IF face = l THEN n ELSE l, lf => IF face = f THEN l ELSE f, rb => IF face = r THEN b ELSE r, rt => IF face = t THEN r ELSE t, rn => IF face = n THEN r ELSE n, rf => IF face = r THEN f ELSE r, bn => IF face = n THEN b ELSE n, bf => IF face = b THEN f ELSE b, tn => IF face = t THEN n ELSE t, ENDCASE => IF face = f THEN t ELSE f; }; CornersFromEdge: PROC [e: Edge] RETURNS [tc: TwoCorners] ~ { tc _ SELECT e FROM lb => [lbn, lbf], lt => [ltn, ltf], ln => [lbn, ltn], lf => [lbf, ltf], rb => [rbn, rbf], rt => [rtn, rtf], rn => [rbn, rtn], rf => [rtf, rbf], bn => [lbn, rbn], bf => [lbf, rbf], tn => [ltn, rtn], ENDCASE => [ltf, rtf]; }; TestCubeEdgesCmd: Commander.CommandProc ~ { CheckPolys: PROC [cube: Cube] ~ { DirectedFace: PROC [edge: Edge, dir: Dir] RETURNS [face: Face] ~ { <> Test: PROC [c: Corner] RETURNS [b: BOOL] ~ INLINE { b _ IF dir = cw THEN cube[c] ELSE NOT cube[c]; }; face _ SELECT edge FROM lb => IF Test[lbn] THEN l ELSE b, lt => IF Test[ltn] THEN t ELSE l, ln => IF Test[lbn] THEN n ELSE l, lf => IF Test[lbf] THEN l ELSE f, rb => IF Test[rbn] THEN b ELSE r, rt => IF Test[rtn] THEN r ELSE t, rn => IF Test[rbn] THEN r ELSE n, rf => IF Test[rbf] THEN f ELSE r, bn => IF Test[lbn] THEN b ELSE n, bf => IF Test[lbf] THEN f ELSE b, tn => IF Test[ltn] THEN n ELSE t, ENDCASE => IF Test[ltf] THEN t ELSE f; }; VertexExists: PROC [e: Edge] RETURNS [BOOL] ~ { tc: TwoCorners _ CornersFromEdge[e]; RETURN[cube[tc.c1] # cube[tc.c2]]; }; MakePolys: PROC [dir: Dir, output: BOOL _ TRUE] RETURNS [nPolys: INTEGER _ 0] ~ { done: ARRAY Edge OF BOOL _ ALL[FALSE]; IF output THEN IO.PutF[cmd.out, "\t%g: ", IO.rope[IF dir = cw THEN "cw" ELSE "ccw"]]; FOR edge: Edge IN Edge DO IF NOT done[edge] AND VertexExists[edge] THEN { nVertices: INTEGER _ 1; e, start: Edge _ edge; face: Face _ DirectedFace[e, dir]; nPolys _ nPolys+1; DO done[e _ NextCWEdge[e, face]] _ TRUE; IF e = start THEN EXIT; IF NOT VertexExists[e] THEN LOOP; nVertices _ nVertices+1; face _ OtherFace[e, face]; ENDLOOP; IF output THEN { IO.PutF[cmd.out, "#%g (%g verts), ", IO.int[nPolys], IO.int[nVertices]]; maxNVertices _ MAX[maxNVertices, nVertices]; maxNPolys _ MAX[maxNPolys, nPolys]; }; }; ENDLOOP; IF output THEN IO.PutF[cmd.out, "\n"]; }; nPositive: INTEGER _ 0; FOR c: Corner IN Corner DO IF cube[c] THEN nPositive _ nPositive+1; ENDLOOP; [] _ MakePolys[IF nPositive > 4 THEN cw ELSE ccw]; <<[] _ MakePolys[IF MakePolys[cw, FALSE] > MakePolys[ccw, FALSE] THEN cw ELSE ccw];>> }; cube: Cube; maxNVertices, maxNPolys: INTEGER _ 0; FOR i: INTEGER IN [0..256) DO IO.PutF[cmd.out, "Test %g (+ corners = ", IO.int[i]]; FOR c: Corner IN Corner DO IF (cube[c] _ Bit[i, c]) THEN IO.PutF[cmd.out, "%g ", IO.rope[CornerName[c]]]; ENDLOOP; IO.EraseChar[cmd.out, ' ]; IO.PutF[cmd.out, ")\n"]; CheckPolys[cube]; ENDLOOP; IO.PutF[cmd.out, "max # vertices per polygon = %g\n", IO.int[maxNVertices]]; IO.PutF[cmd.out, "max # polygons = %g\n", IO.int[maxNPolys]]; }; Commander.Register["TestCubeEdges", TestCubeEdgesCmd]; END.