the purpose of the 'tabulated' include file is to provide a macro for documenting key parameters, data, or other information inside rendered images, in formatted tables. achieving a consistent "look and feel" across a series of images, for instance when illustrating an object collection, as shown in one of the examples, becomes very easy.
the Tabulated()
macro uses a dictionary for
its input, and there are a good number of optional keys
to "tweak" the appearance and layout of tables.
only two keys, however,
are actually required to create a table –
one to provide the data to display,
the second to define the types of values stored in
the column(s).
each table is composed of two types of "cell",
labels and data, which form the columns and rows,
and an overlaying frame/grid.
labels are optional, as is the table caption,
though tables are rarely useful without.
data may be of any of POV-Ray's basic types,
that is,
booleans and strings, floats and integers, and vectors,
can be specified.
tables are aligned with their top-left corner
at origin (approximately),
extending in to
+x
and
-y
,
are less than half of one POV-Ray unit deep,
and are created with a no_shadow
modifier.
table dimensions are calculated from the space required
by the various items,
in relation to the respective font's largest glyph.
labels, caption, and data
each use a different TrueType font,
at slightly different, fixed, scales.
// counts {boxes, cylinders, spheres} #declare D = dictionary { .DataColumns: array [1] {"I"}, .DataTable : array [3] {23,8,17}, .RowLabels : array [3] {"b","c","s"} }; object { Tabulated(D) scale some_factor translate some_place }
for example, say you're experimenting with some complex shape made up from many, still changing numbers of, boxes, spheres, and cylinders. the snippet shows how to make a quick, basic table to document the numbers used in a given "try".
the Scene Description Language (SDL) code is written for the Persistence of Vision Raytracer version 3.8, or later[1].
shortcomings – a couple of known "issues"/bugs: a caption cannot be wider than the table, an error (with message) is thrown; if all labels are empty strings, the boxes for the column names are still shown. the macro, as is, does not provide a means to emphasise, or highlight, individual items, columns, and or rows. both external and internal border lines are drawn with the same (cylinder) radius, currently. while some of this stuff may get done, I am thinking about a different design altogether, a shift away from the current, column-driven approach, to "cell centric", for the next version. a design which will allow column groups, row and or column spanning cells, wrapping long text/string data into multiple lines, images in cells, etc.
seen from the user's perspective,
the include file provides three globally
"visible" identifiers:
one macro and two variables.
there are however others and all visible identifiers,
except Tabulated()
and the variables,
are prefixed 'tabu_'.
Tabulated_{min,max}_extent
these variables provide, for convenience,
the overall dimensions of the table in 3-vectors,
as returned by
min_extent()
and
max_extent()
calls.
both variables are (re-)created every time
Tabulated()
runs.
Tabulated(dict)
the Tabulated()
macro takes a single
'dictionary {}
' argument,
and returns ("expands to") an
'union {}
' of objects
forming a table.
of the list of keys below only the first two are required. all others will be given "sensible" default values, where applicable, when omitted. it is ok to add your own key/value pairs to the dictionary (except '.Hilite' and '.Note', which are reserved for future use).
[row][col]
,
or just a single column ([col]
).
or you may have "sets" of differing values,
in which case a 1D array ([row]
s) of
array mixed
can be used.
examples of all of these are shown in the demo scenes,
see the "examples" section below.
.x
and .y
components
of the vector specify the cell-internal amount of padding
for labels and data.
the values represent percentages
of the largest glyph in the respective font.
the 'x' value is added on both sides
of an item, and 'y' above and below.
the default is <.35,.2>
,
thirty-five and twenty percent, respectively.
cylinder {}
' objects.
use this key to provide a radius, and a colour index,
cf '.Fg'.
the built-in defaults are
'{.025,4}
',
for thin, red "lines".
1
to 40
units, or -1
for "don't care".
if a given width is insufficient for displaying the actual
label or data,
an error message will be shown.
pigment {color rgb .nn}
'
type values.
use 'pigment {color rgbt 1}
'
for transparent backgrounds.
{4,0,0}
'.
emission
keyword.
the default, when omitted, is 'false',
ie use a non-emissive finish (for lit scenes).
see '.Finishes' below.
{ambient .1 diffuse .8 specular .1}
'
and
'{ambient 0 emission .85}
',
respectively;
cf '.Emissive'.
{"disabled","enabled"}
.
Tabulated()
will print a summary "header" of the various
settings to POV-Ray's debug stream.
default 'false'.
for all strings, whether Row/Column labels or type
"S"
data columns,
all provisos regarding POV-Ray's
'text {}
'
object apply,
that is, no newlines and such.
as mentioned above,
Tabulated()
calculates the required dimensions using
a font's largest glyph.
to clarify,
for each font only the glyphs corresponding to
chr(1)
through to
chr(255)
are looked at;
fonts may have larger glyphs in subsequent, higher
"pages",
than in the first.
this section introduces the demo code,
example scenes which, taken together,
illustrate the basic usage of
the Tabulated()
macro.
each of the three examples named
'ex?.pov'
demonstrates the use of
one particular "shape" of array.
two other scenes included simply show further
usages of the macro,
but they use specific fonts which you may need
to change/adapt.
the archive also includes a little script which generates a "sampler" scene, a simple viewer for a given TrueType font. you will need a BASH (Bourne Again Shell) to run the script, as discussed below.
note – all scene code can be accessed
by clicking on the corresponding image,
which shows a render of the table
"after adding bling".
each example scene file,
as shipped,
will render the (mostly) all-defaults
"before bling"
version,
the modifications needed are commented out,
for quick editing.
also, you may prefer to switch to an
orthographic
type camera instead,
particularly when rendering wider tables.
the first image shown is included simply
to make the point that a table does not
necessarily have to look like
"a table".
without borders,
Tabulated()
's
output can make a passable billboard.
it is also the only image where I
"cheated",
using a separate utility to crop the rendered image.
the first example demonstrates use of an
"ordinary"
2D data array,
where the first dimension represents the rows,
and the second the columns.
the scene uses the POV-Ray
'superellipsoid {}
'
object.
the array has six sets (rows) of
two parameters (columns),
corresponding to the shape's
"east-west"
and
"north-south"
parameters;
hence the array name
en_
.
there are a couple of arrays storing colours
and colour names,
also with six elements each.
these are used to colour-code the shapes,
and to provide row labels for the table.
the column labels are provided "inline".
because the superellipsoids are lined-up
to the right of table,
the rendered image is taller than wide.
to compensate, a
camera
aspect ratio of
3/4
is used.
... /* object colours */ #declare cv_ = array [6] { <0,0,1>, <0,1,0>, <0,1,1>, <1,0,0>, <1,0,1>, <1,1,0> }; #declare cn_ = array [6] { "blue", "green", "cyan", "red", "magenta", "yellow" }; /* east + north */ #declare en_ = array [6][2] { {.50,.16}, {.50,.32}, {.50,.48}, {.50,.64}, {.50,.80}, {.50,.96} }; ... #declare D = dictionary { .DataColumns: array [2] {"F3","F3"}, .DataTable : en_ }; ...
when declaring the input
dictionary
for the macro,
the (most) important thing
is to provide the correct data type specification
for each column, in order.
since both parameters in this data table
are of the same type, so are the column types;
we use "F3"
to get the
float
values displayed with three decimal digits precision.
we then add the data array using its identifier.
the second image shows the wildly unexciting result
of rendering the table after adding labels and caption,
as well as enabling the '.Ledger' style feature.
it also shows that tables really need
some labelling to provide context, meaning.
jr@crow:tabu$ cd demo jr@crow:demo$ povray ex1.pov +l.. +w600 +h800 +a0.1
presuming that your current working directory is
the archive's top (ie '/path/to/tabu'),
the second snippet shows how to quick test render this
example, and the others below.
the library_path
(+l..
)
option let's POV-Ray find the include file.
the second example,
shown in the third image,
is based on an 1D array where
every element ("row") is an
array mixed
,
think database table,
storing information about the objects displayed,
both calculated and entered "by hand" values.
each of the four objects is a POV-Ray
mesh2
type,
and part of a fictional science fiction objects collection.
the meshes were created from GNU Triangulated Surfaces
data files[2]
found on the interweb.
a plain background image was added to relieve the
"drabness".
the objects, from left to right, correspond to the data rows, in order. their names are the same as the declared "identifiers", and the include file names; they are used to source the files, and as row labels in the table.
the thing to note is the "V33"
type spec for the second column,
a macro is used to round the object dimensions,
an '<x,y,z>' vector,
to the third decimal.
the other columns,
integers and booleans,
do not have a precision.
while functional, the table's default colours sort of clash with the background, hence '.Fg', '.Bg', and '.Lines' keys were set to address this. also, given the image's width, the table can be made a little wider. '.ColWidths' is used to set the columns to uniform widths.
well,
there are only so many examples one can contrive ;-),
so the third, and final, is even more
"lame" than the previous.
it demonstrates the use of a single column table (array),
with three rows storing the corner points of a
'triangle {}
'.
the points are randomly generated,
and the table displays those values
(rounded up to make them look "nice"),
as well as the seed
value used;
the seed is a number derived from
the system time,
and every render will draw a different triangle.
the fourth image shows an instance.
as in the second example, the necessary (for the visuals) dictionary keys were added to make the result a little less plain; namely the foreground colours and background pigments, and '.Lines'.
you may feel .. hampered by the limited
number of foreground (and line) colours.
since the Tabulated()
macro uses a simple 1D array of 3-vector RGB values,
it is easy, and safe, to override that
by providing your own.
simply, after including 'tabulated.inc',
but before running the Tabulated()
macro,
declare an array like the one shown in the snippet,
that is, the exact same name and number of elements,
plus your colour vectors.
then those will be used for the remaining scene code.
#declare tabu__data_colours_ = array [8] { <0,0,0>, <0,0,1>, <0,1,0>, <0,1,1>, <1,0,0>, <1,0,1>, <1,1,0>, <1,1,1> };
the final, fifth, image was rendered from a scene
created by the aforementioned (BASH) script utility,
'mkfntview.sh'.
the scene uses the 'verdana.ttf' font,
and the utility's output was
"calibrated" using that font.
some visual "bells and whistles" were added
to make an appealing (I hope) example image.
each generated scene displays one (of four) 16x16 glyph
"pages", and a three-line "sampler"
set in the selected font.
for convenience, a page can be selected from the
command-line via POV-Ray's
declare=page=N
syntax,
where N
must be in range
0,..,3
.
note – the camera settings,
and the table scales and positions,
will, almost always, need tweaking,
as fonts are so diverse.
the snippet assumes that the utility has been copied to
a PATH
directory.
naming a non-existing font,
or a misspelling,
will go unnoticed until POV-Ray tries to use the font.
$ mkfntview.sh verdana.ttf $ povray view_verdana_ttf.pov +w600 +h800 +a0.1
although 'tabulated.inc' does not depend on any other includes, one of the three example/demo scenes does, for convenience. the necessary 'foreach.inc' was published in the POV-Ray news groups, but the download link below points to the current version. I also include a link to the latest 'ruled.inc', because, in my (biased :-)) opinion, it complements 'tabulated.inc' well.
POV-Ray
dictionary {}
'
array/data type,
in particular.
GTS
mesh
'
types very easy.
Foreach()
Ruled()
"The End". enjoy.