On this page, I examine the built in functions that came from the
i_algbr library. These functions were originally based on a comp.graphics.rendering.raytracing
article by Tore Nordstrand, and was originally implemented as an external library.
These functions are now included in the program code,
so they can be used without using external library calls.

There are some special parameters with complicated effects that are found in several of these functions.
Rather than describe them each time they occur, I'll describe them here, and refer to them later as
"Field Strength" and "Field Limit" etc.
Field Strength The numerical value at a point in space generated by the
function is multiplied by the Field Strength. The set of points where the function
evaluates to zero are unaffected by any positive value of this parameter,
so if you're just using the function on its own with
threshold = 0, the generated surface is still the same.
In some cases, the field strength has a considerable effect on the speed and accuracy
of rendering the surface. In general, increasing the field strength speeds up
the rendering, but if you set the value too high the surface starts to break up and
may disappear completely.
The surface generated with threshold = 0.1 and field strength 1 is the same as
the surface generated with threshold = 0.2 and field strength 2. Doubling the
field strength has doubled the numeric value at a point in space, but doubling
the threshold tells the program to look for points where the numeric value is double.
Setting the field strength to a negative value produces the inverse of the surface, like
setting sign 1.
Field Limit The numerical value at a point in space generated by the
function is limited to plus or minus the field limit. E.g. if you set the field limit to 2,
then the value returned for a point that is a large distance from the surface will be +2 or 2.
This won't make any difference to the generated surface if you're using threshold that's
within the field limit (and will kill the surface completely if the threshold is greater than the field limit).
However, it may make a huge difference to the rendering times.
If you use the function to generate a pigment, then all points that are a long way from
the surface will have the same colour, the colour that corresponds to the numerical value
of the field limit.
SOR Switch If greater than zero, the curve is swept out as a surface
of revolution. If the value is zero or negative, the curve is extruded linearly in the Z direction.
SOR Offset If the SOR switch is on, then the curve is shifted
this distance in the X direction before being swept out.
SOR Angle If the SOR switch is on, then the curve is rotated
this number of degrees about the Z axis before being swept out.


An algebraic cylinder is what you get if you take any 2d curve and plot it in 3d.
The 2d curve is simply extruded along the third axis, in this case the z axis.
In the article that started all this, Tore Nordstrand just happened to mention
four particular 2d curves that could be used in this way, and these have become the Algbr_Cyl
functions that are implemented.
function {f_algbr_cyl1(x,y,z,1,1,0,0,0)}


The parameters of all the algebraic cylinders are:
 Field Strength.
 Field Limit.
 SOR Switch.
 SOR Offset.
 SOR Angle.
function { f_algbr_cyl2(x,y,z,1,1,0,0,0)}


function { f_algbr_cyl3(x,y,z,1,1,0,0,0)}


function { 0  f_algbr_cyl4(x,y,z,1,1,0,0,0)}


This is Algebraic Cylinder #1 again, but this time with the SOR Switch
switched on. The figureofeight curve is now rotated around the Y axis instead
of being extruded along the Z axis.
I've sliced these three images in half so that you can see the 2d figureofeight
curve that generates them more easily.
function { f_algbr_cyl1(x,y,z,1,1,1,0,0)}


This time the figureofeight curve has been shifted 0.4 units to the right
before being swept out
by setting SOR Offset to 0.4.
function { f_algbr_cyl1(x,y,z,1,1,1,0.4,0)}


This time the figureofeight curve has been rotated by 90 degrees and shifted 0.6 units to the right
before being swept out
by setting SOR Angle to 90.
function { f_algbr_cyl1(x,y,z,1,1,1,0.6,90)}


The bicorn surface looks something like the top part of a paraboloid
bounded below by another paraboloid.
The parameters are:
 Field Strength.
 Scale. The surface is always the same shape. Changing this parameter
has the same effect as adding a scale modifier. Setting the scale to 1
gives a surface with a radius of about 1 unit.
function {  f_bicorn(x,y,z,1,1)}


I've cut this bifolia in half to make the structure clearer.
The surface is a surface of revolution.
The parameters are:
 Field Strength.
 Scale. The mathematics of this surface suggest that the shape should
be different for different values of this parameter. In practice the difference
in shape is hard to spot. Setting the scale to 3 gives a surface with a radius
of about 1 unit.
function {  f_bifolia(x,y,z,1,3)}


The "Boy_surface" is a model of the projective plane without singularities. Found
by Werner Boy on assignment from David Hilbert.
For this surface, it helps if the field strength is set extremely low,
otherwise the surface has a tendency to break up or disappear entirely.
This has the side effect of making the rendering times extremely long  this
image took 16 times longer to render than any other surface on this page.
The parameters are:
 Field Strength.
 Scale. The surface is always the same shape. Changing this parameter
has the same effect as adding a scale modifier.
function {  f_boy_surface(x,y,z,0.0000001,1)}


The Ovals of Cassini are a generalisation of the torus shape.
The parameters are:
 Field Strength.
 Major radius  like the major radius of a torus.
 Filling. Set this to zero, and you get a torus. Set this to a higher value
and the hole in the middle starts to heal up. Set it even higher and you get
an ellipsoid with a dimple.
 Thickness. The higher you set this value, the plumper is the result.
function {  f_ovals_of_cassini
(x, y, z, 1, 0.5, 0.24, 5)}


This is a cubic saddle.
The parameters are:
 Field Strength.
For this surface, it helps if the field strength is set quite low,
otherwise the surface has a tendency to break up or disappear entirely.
function { f_cubic_saddle(x,y,z,0.1)}


This is the "Cushion" surface.
The parameters are:
 Field Strength.
function {  f_cushion(x,y,z,1)}


This is the "Devil's Curve" surface.
The parameters are:
 Field Strength.
function { f_devils_curve(x,y,z,1)}


The 2d devil's curve can be extruded along the z axis, like this,
or using the SOR parameters it can be made into a surface of revolution.
The parameters are:
 Field Strength.
 X factor.
 Y factor.
 SOR Switch.
 SOR Offset.
 SOR Angle.
The X and Y factors control the size of the central feature. If the X factor is
slightly stronger than the Y factor, then the side pieces are linked to the
central piece by a horizontal bridge at each corner. If the Y factor is slightly
greater than the X factor, then there is a vertical gap between the side pieces
and the central piece at each corner. If the X and Y factors are equal
each of the four corners meets at a point.
function { f_devils_curve_2d
(x, y, z, 1, 1.5, 1.52, 0, 0, 0) }


The Dupin Cyclid can take several forms depending on the parameters.
This particular configuration is known as a "double crescent".
A Dupin Cyclid can be considered to be the envelope of all the possible spheres
that just kiss three other spheres. It can also be considered to be the
envelope of all spheres on a conic section that just touch a given sphere. And
it can also be considered to be the "inversion" of a torus.
function { f_dupin_cyclid
(x, y, z, 0.0001, 4.9, 5, 2, 0, 3)}


The parameters of the Dupin Cyclid consider it to be generated by
the "inversion" of a torus. (Inversion here has some weird mathematical meaning,
don't confuse it with the POV concept of "inverse").
The parameters are:
 Field Strength.
 Major radius of torus.
 Minor radius of torus.
 X displacement of torus.
 Y displacement of torus.
 radius of inversion.
This particular Dupin Cyclid is called a "degenerate w. arch".
function { f_dupin_cyclid
(x, y, z, 0.000001, 3, 5, 3, 0, 9)}


This is a "plain" Dupin Cyclid.
function {  f_dupin_cyclid
(x,y,z,0.0000001, 6, 0.5, 3, 0, 12)}

