ELSE {
DoWithValue:
PROC [action:
PROC [value:
REAL]] ~ {
FOR k:
INT
IN [0..nz)
DO
z: REAL ¬ box.min.z+tool.size*(REAL[k]-1.5);
FOR j:
INT
IN [0..ny)
DO
y: REAL ¬ box.min.y+tool.size*(REAL[j]-1.5);
FOR i:
INT
IN [0..nx)
DO
x: REAL ¬ box.min.x+tool.size*(REAL[i]-1.5);
action[tool.function[[x, y, z], tool.client.data]];
ENDLOOP;
ENDLOOP;
ENDLOOP;
};
MinMax: PROC [value: REAL] ~ {min ¬ MIN[min, value]; max ¬ MAX[max, value]};
Output: PROC [value: REAL] ~ {IO.PutByte[out, BYTE[Real.Round[(value-min)*scale]]]};
out: IO.STREAM;
min: REAL ¬ Real.PlusInfinity;
max, scale: REAL ¬ Real.MinusInfinity;
box: Box ¬ G3dShape.BoundingBox[tool.tool3d.shapes[0]];
objectSize: Triple ¬ G3dVector.Sub[box.max, box.min];
halfGrid: REAL ¬ 0.5*tool.size;
# cells is objectSize/tool.size, which results in 1+objectSize/tool.size samples;
however, samples are shifted -tool.size/2 so the first cell fully encloses the object;
this requires an additional, final cell, so total # samples is 2+objectSize/tool.size.
Actually, for some discontinuous tilers, gradients are computed and thus require
an additional cell in all six directions, so # samples is 4+objectSize/tool.size.
nx: INT ¬ 4+Real.Ceiling[objectSize.x/tool.size];
ny: INT ¬ 4+Real.Ceiling[objectSize.y/tool.size];
nz: INT ¬ 4+Real.Ceiling[objectSize.z/tool.size];
prompt:
ROPE ¬
IO.PutFLR[
"(%g, %g, %g) grid (%g elements), filename (<CR> to abort): ", LIST[
IO.int[nx], IO.int[ny], IO.int[nz], IO.int[nx*ny*nz]]];
name: ROPE ¬ Controls.TypescriptRead[tool.tool3d.typescript, prompt];
IF Rope.IsEmpty[name] THEN RETURN;
IF Rope.Fetch[name, 0] # '/ THEN name ¬ Rope.Concat[tool.tool3d.directory, name];
out ¬ PFS.StreamOpen[PFS.PathFromRope[name], $create];
DoWithValue[MinMax];
scale ¬ 255.0/(max-min);
IO.PutF[out, "-- %g discrete implicit function values from ImplicitDesign: %g\n",
IO.int[nx*ny*nz], IO.rope[tool.tool3d.name]];
IO.PutF[out, "-- initial function range from %g to %g mapped to 0 to 255\n",
IO.real[min], IO.real[max]];
IO.PutF[out, "-- isovalue is %g, which maps to %g\n",
IO.real[tool.level], IO.real[(tool.level-min)*scale]];
IO.PutFL[out, "-- surface bounds: (%5.3f, %5.3f, %5.3f) to (%5.3f, %5.3f, %5.3f)\n",
LIST[IO.real[box.min.x], IO.real[box.min.y], IO.real[box.min.z],
IO.real[box.max.x], IO.real[box.max.y], IO.real[box.max.z]]];
IO.PutFL[out, "-- grid bounds: (%5.3f, %5.3f, %5.3f) to (%5.3f, %5.3f, %5.3f)\n",
LIST[
IO.real[box.min.x-halfGrid], IO.real[box.min.y-halfGrid], IO.real[box.min.z-halfGrid],
IO.real[box.max.x+halfGrid], IO.real[box.max.y+halfGrid], IO.real[box.max.z+halfGrid]]];
IO.PutF1[out, "-- fixed cubical grid spacing is %g\n", IO.real[tool.size]];
IO.PutF[out, "-- x, y, z resolution: %g, %g, %g\n", IO.int[nx], IO.int[ny], IO.int[nz]];
IO.PutRope[out, "-- z is the outer loop, y the middle loop, x the inner loop\n"];
DoWithValue[Output];
IO.Close[out];
};