ImplicitTestTetEdgesImpl:
CEDAR
PROGRAM
IMPORTS Basics, Commander, Controls, G3dDraw, G3dPolygon, G3dTool, G3dVector, Imager, ImagerColor, ImagerFont, IO, Rope
~
BEGIN
Triple: TYPE ~ G3dTool.Triple;
Corner: TYPE ~ RECORD [positive: BOOL, point: Triple];
Direction: TYPE ~ {lbn, lbf, ltn, ltf, rbn, rbf, rtn, rtf};
Triangle: TYPE ~ RECORD [p1, p2, p3, center, normal: Triple];
Tetrahedron:
TYPE ~
RECORD [p1, p2, p3, p4: Triple];
Cube:
TYPE ~
RECORD [
lbn, lbf, ltn, ltf: Corner,
rbn, rbf, rtn, rtf: Corner,
triangles: LIST OF Triangle ¬ NIL,
tetrahedra: LIST OF Tetrahedron ¬ NIL];
Data:
TYPE ~
RECORD [
tool: G3dTool.Tool ¬ NIL,
select: INTEGER ¬ 0,
nrms, text, tets, lab: BOOL ¬ TRUE,
cubes1, cubes2: ARRAY [0..256) OF REF Cube ¬ ALL[NIL]];
TestTetEdgesCmd: Commander.CommandProc ~ {
d: REF Data ¬ NEW[Data];
buttons: Controls.ButtonList ¬
LIST[
Controls.ClickButton["STEP", But, d],
Controls.ClickButton["SET", But, d],
Controls.ClickButton["Text: On", But, d],
Controls.ClickButton["Tets: On", But, d],
Controls.ClickButton["Labs: On", But, d],
Controls.ClickButton["Nrms: On", But, d]];
FOR i: INTEGER IN [0..256) DO d.cubes1[i] ¬ MakeCube[i, 1]; ENDLOOP;
FOR i: INTEGER IN [0..256) DO d.cubes2[i] ¬ MakeCube[i, 2]; ENDLOOP;
d.tool ¬ G3dTool.MakeTool["TetEdges", buttons,,, [io: TRUE], [draw: Draw, data: d],,,,, 275];
};
Poly:
PROC [cube:
REF Cube, type:
NAT] ~ {
VertexID:
PROC [c1, c2: Corner]
RETURNS [Triple] ~ {
IF c1.positive = c2.positive THEN ERROR;
RETURN[G3dVector.Midpoint[c1.point, c2.point]];
};
TriangulateTetrahedron:
PROC [a, b, c, d: Corner] ~ {
corners presumed oriented such that b, c, d appear clockwise when viewed from a
Output:
PROC [a, b, c: Triple] ~
INLINE {
t: Triangle ¬
[a, b, c, G3dPolygon.TriangleCenter[a,b,c], G3dPolygon.TriangleNormal[a,b,c,TRUE]];
cube.triangles ¬ IF cube.triangles = NIL THEN LIST[t] ELSE CONS[t, cube.triangles];
};
index: INT ¬ 0;
aPos, bPos, cPos, dPos: BOOL;
e1, e2, e3, e4, e5, e6: Triple;
tet: Tetrahedron ¬ [a.point, b.point, c.point, d.point];
IF (aPos ¬ a.positive) THEN index ¬ index+8;
IF (bPos ¬ b.positive) THEN index ¬ index+4;
IF (cPos ¬ c.positive) THEN index ¬ index+2;
IF (dPos ¬ d.positive) THEN index ¬ index+1;
IF index
IN [1..14]
THEN cube.tetrahedra ¬
IF cube.tetrahedra = NIL THEN LIST[tet] ELSE CONS[tet, cube.tetrahedra];
IF aPos # bPos THEN e1 ¬ VertexID[a, b];
IF aPos # cPos THEN e2 ¬ VertexID[a, c];
IF aPos # dPos THEN e3 ¬ VertexID[a, d];
IF bPos # cPos THEN e4 ¬ VertexID[b, c];
IF bPos # dPos THEN e5 ¬ VertexID[b, d];
IF cPos # dPos THEN e6 ¬ VertexID[c, d];
SELECT index
FROM
1 => Output[e5, e6, e3];
2 => Output[e2, e6, e4];
3 => {Output[e3, e5, e4]; Output[e3, e4, e2]};
4 => Output[e1, e4, e5];
5 => {Output[e3, e1, e4]; Output[e3, e4, e6]};
6 => {Output[e1, e2, e6]; Output[e1, e6, e5]};
7 => Output[e1, e2, e3];
8 => Output[e1, e3, e2];
9 => {Output[e1, e5, e6]; Output[e1, e6, e2]};
10 => {Output[e1, e3, e6]; Output[e1, e6, e4]};
11 => Output[e1, e5, e4];
12 => {Output[e3, e2, e4]; Output[e3, e4, e5]};
13 => Output[e6, e2, e4];
14 => Output[e5, e3, e6];
ENDCASE; -- 0, 15
};
IF type = 1
THEN {
TriangulateTetrahedron[cube.lbn, cube.lbf, cube.ltn, cube.rbn];
TriangulateTetrahedron[cube.ltf, cube.ltn, cube.lbf, cube.rtf];
TriangulateTetrahedron[cube.rbf, cube.rbn, cube.rtf, cube.lbf];
TriangulateTetrahedron[cube.rtn, cube.rtf, cube.rbn, cube.ltn];
TriangulateTetrahedron[cube.lbf, cube.ltn, cube.rbn, cube.rtf];
}
ELSE {
TriangulateTetrahedron[cube.lbf, cube.rbf, cube.ltf, cube.lbn];
TriangulateTetrahedron[cube.ltn, cube.ltf, cube.rtn, cube.lbn];
TriangulateTetrahedron[cube.rbn, cube.rbf, cube.lbn, cube.rtn];
TriangulateTetrahedron[cube.rtf, cube.rtn, cube.ltf, cube.rbf];
TriangulateTetrahedron[cube.lbn, cube.ltf, cube.rtn, cube.rbf];
};
};
MakeCube:
PROC [i:
INTEGER, type:
NAT]
RETURNS [c:
REF Cube] ~ {
Bit:
PROC [i:
WORD, c: Direction]
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];
};
Point:
PROC [c: Direction]
RETURNS [t: Triple] ~ {
t ¬
SELECT
c
FROM
lbn => [-.4,-.4,-.4], lbf => [-.4,-.4,.4], ltn => [-.4,.4,-.4], ltf => [-.4,.4,.4],
rbn => [.4,-.4,-.4], rbf => [.4,-.4,.4], rtn => [.4,.4,-.4], ENDCASE => [.4,.4,.4];
};
c ¬ NEW[Cube];
c.lbn ¬ [Bit[i, lbn], Point[lbn]];
c.lbf ¬ [Bit[i, lbf], Point[lbf]];
c.ltn ¬ [Bit[i, ltn], Point[ltn]];
c.ltf ¬ [Bit[i, ltf], Point[ltf]];
c.rbn ¬ [Bit[i, rbn], Point[rbn]];
c.rbf ¬ [Bit[i, rbf], Point[rbf]];
c.rtn ¬ [Bit[i, rtn], Point[rtn]];
c.rtf ¬ [Bit[i, rtf], Point[rtf]];
Poly[c, type];
};
Draw: G3dTool.DrawProc ~ {
NTetrahedra:
PROC [c:
REF Cube]
RETURNS [n:
INTEGER ¬ 0] ~ {
FOR l: LIST OF Tetrahedron ¬ c.tetrahedra, l.rest WHILE l # NIL DO n ¬ n+1; ENDLOOP;
};
NTriangles:
PROC [c:
REF Cube]
RETURNS [n:
INTEGER ¬ 0] ~ {
FOR l: LIST OF Triangle ¬ c.triangles, l.rest WHILE l # NIL DO n ¬ n+1; ENDLOOP;
};
ShowRope:
PROC [x, y:
REAL, r: Rope.
ROPE] ~ {
Imager.SetXY[context, [x, y]];
Imager.ShowRope[context, r];
};
SetColor:
PROC [rgb: Triple] ~ {
IF color#rgb THEN Imager.SetColor[context,ImagerColor.ColorFromRGB[[rgb.x,rgb.y,rgb.z]]];
color ¬ rgb;
};
DrawAll:
PROC [c:
REF Cube, type:
NAT] ~ {
DrawBox: PROC [p: Triple] ~ {G3dDraw.Box[context, p, view, vp, 6, 6]};
DrawSeg: PROC [a, b: Triple] ~{G3dDraw.DrawSegment[context, a, b, view, vp]};
DrawEdge: PROC [c1, c2: Corner] ~ {DrawSeg[c1.point, c2.point]};
Label: PROC [p: Triple, r: Rope.ROPE] ~ {G3dDraw.Mark[context, p, view, vp, r, none]};
DrawTriangle:
PROC [t: Triangle, color: Triple, showNormal:
BOOL] ~ {
SetColor[color];
DrawSeg[t.p1, t.p2];
DrawSeg[t.p2, t.p3];
DrawSeg[t.p3, t.p1];
IF showNormal AND d.lab THEN {
Label[t.p1, "1"];
Label[t.p2, "2"];
Label[t.p3, "3"];
};
IF showNormal
THEN {
fwd: BOOL ¬ G3dVector.FrontFacing[t.normal, t.center, view];
label: Rope.ROPE ¬ NIL; -- IF fwd THEN "forward" ELSE "backward";
SetColor[[0.0, 0.0, 1.0]];
G3dDraw.DrawVector[context, t.center, t.normal, view, vp, label];
};
};
DrawTetrahedron:
PROC [t: Tetrahedron] ~ {
DrawTriangle[[t.p1, t.p2, t.p3], [0.0, 1.0, 1.0], FALSE];
DrawTriangle[[t.p1, t.p2, t.p4], [0.0, 1.0, 1.0], FALSE];
DrawTriangle[[t.p1, t.p3, t.p4], [0.0, 1.0, 1.0], FALSE];
DrawTriangle[[t.p2, t.p3, t.p4], [0.0, 1.0, 1.0], FALSE];
};
DrawCube:
PROC [c:
REF Cube] ~ {
SetColor[[0.0, 0.0, 0.0]];
DrawEdge[c.lbn, c.ltn];
DrawEdge[c.ltn, c.rtn];
DrawEdge[c.rtn, c.rbn];
DrawEdge[c.rbn, c.lbn];
DrawEdge[c.lbf, c.ltf];
DrawEdge[c.ltf, c.rtf];
DrawEdge[c.rtf, c.rbf];
DrawEdge[c.rbf, c.lbf];
DrawEdge[c.lbn, c.lbf];
DrawEdge[c.ltn, c.ltf];
DrawEdge[c.rtn, c.rtf];
DrawEdge[c.rbn, c.rbf];
IF d.lab THEN {
Label[c.lbn.point, "lbn"];
Label[c.lbf.point, "lbf"];
Label[c.ltn.point, "ltn"];
Label[c.ltf.point, "ltf"];
Label[c.rbn.point, "rbn"];
Label[c.rbf.point, "rbf"];
Label[c.rtn.point, "rtn"];
Label[c.rtf.point, "rtf"];
};
};
vp: G3dTool.Viewport ¬ v.viewport;
vp.translate.x ¬ vp.translate.x+(IF type = 1 THEN -150 ELSE 150);
IF d.text
THEN {
SetColor[[0.0, 0.0, 0.0]];
ShowRope[vp.translate.x-75,
35,
IO.PutFR["#%g
(type %g)",
IO.int[d.select],
IO.int[type]]];
ShowRope[vp.translate.x-75, 20,
IO.PutFR["%g triangles, %g tetrahedra",
IO.int[NTriangles[c]], IO.int[NTetrahedra[c]]]];
};
DrawCube[c];
IF d.tets
THEN
FOR l:
LIST
OF Tetrahedron ¬ c.tetrahedra, l.rest
WHILE l #
NIL
DO
DrawTetrahedron[l.first];
ENDLOOP;
FOR
l:
LIST
OF
Triangle
¬
c.triangles,
l.rest
WHILE
l
#
NIL
DO
DrawTriangle[l.first, [0.0, 1.0, 0.0], d.nrms];
ENDLOOP;
SetColor[[1.0, 0.0, 0.0]];
FOR
l:
LIST
OF
Corner¬
LIST[c.lbn,c.lbf,c.ltn,c.ltf,c.rbn,c.rbf,c.rtn,c.rtf],
l.rest
WHILE
l#
NIL
DO
IF l.first.positive THEN DrawBox[l.first.point];
ENDLOOP;
};
d: REF Data ¬ NARROW[clientData];
color: Triple ¬ [1.0, 1.0, 1.0];
v: G3dTool.View ¬ G3dTool.GetView[viewer, d.tool];
view: G3dTool.Matrix ¬ v.camera.matrix;
Imager.SetFont[context, font];
DrawAll[d.cubes1[d.select], 1];
DrawAll[d.cubes2[d.select], 2];
};
But: Controls.ClickProc ~ {
d: REF Data ¬ NARROW[clientData];
SELECT
TRUE
FROM
Rope.Equal[parent.name, "STEP"] =>
d.select ¬ MIN[255, MAX[0, d.select+(IF mouseButton = red THEN 1 ELSE -1)]];
Rope.Equal[parent.name, "SET"]
=>
d.select ¬ MIN[255, MAX[0, Controls.GetNat[d.tool.typescript, "select: ", d.select]]];
Rope.Find[parent.name, "Nrms"] # -1 =>
Controls.ButtonToggle[d.tool.outerData, d.nrms ¬ NOT d.nrms, "Nrms: On", "Nrms: Off"];
Rope.Find[parent.name, "Text"] # -1 =>
Controls.ButtonToggle[d.tool.outerData, d.text ¬ NOT d.text, "Text: On", "Text: Off"];
Rope.Find[parent.name, "Tets"] # -1 =>
Controls.ButtonToggle[d.tool.outerData, d.tets ¬ NOT d.tets, "Tets: On", "Tets: Off"];
Rope.Find[parent.name, "Labs"] # -1 =>
Controls.ButtonToggle[d.tool.outerData, d.lab ¬ NOT d.lab, "Labs: On", "Labs: Off"];
ENDCASE;
G3dTool.Repaint[d.tool];
};
font: ImagerFont.Font ¬ ImagerFont.Find["xerox/tiogafonts/helvetica10"];
Commander.Register["TestTetEdges", TestTetEdgesCmd];