"Realistic" Shapes

© Mike Williams 2003,2004

Up | Previous: Mathematical Zoo | Next: Seashells | Alphabetical Index

Well, they're slightly more realistic than most of the images in this tutorial.


This is a parametric isosurface using the functions:
#declare Flare=function(u){u/(2*pi) + pow(u/(2*pi),20)*2}

#declare Fx = function(u,v)
   {(2 + u/(2*pi)*cos(v))*sin(u) - 0.1*u}
#declare Fy = function(u,v)
   {(2 + Flare(u)*cos(v))*cos(u) + 0.5*u}
#declare Fz = function(u,v)
Once again I started with a parametric torus. In this case I happened to start with
#declare Fx = function(u,v){(2 + cos(v))*sin(u)}
#declare Fy = function(u,v){(2 + cos(v))*cos(u)}
#declare Fz = function(u,v){sin(v)}
I initially added u/(2*pi) factors to all three components, but then replaced these by Flare(u) in Fy and Fz. The Flare(u) function is designed so that it looks very similar to u/(2*pi) when u lies between 0 and about 1.8*pi, but increases rapidly between u=1.8*pi and u=2*pi. Thus causing the final widening at the top of the instrument in the Z and Y directions.

The final - 0.1*u and + 0.5*u factors fine tune the position of the top of the instrument.

Tudor Rose

This surface was inspired by a stylised rose decoration on a wrought iron gate.

I've cheated slightly by adding a flattened sphere to the centre. That sphere is not part of the actual parametric surface.

The functions are:

#declare R = function(u,v){
    * max(abs(sin(4*u)), 0.9-0.2*abs(cos(8*u)))

#declare Fx= function(u,v){R(u,v)*cos(u)*cos(v)}
#declare Fy= function(u,v){R(u,v)*sin(u)*cos(v)}
#declare Fz= function(u,v){R(u,v)*sin(v)*0.5}

sphere {-0.2*z,0.2 scale <1,1,0.5>} 
This shape renders rather slowly as a real parametric isosurface, so I suggest using Ingo's param.inc macro to approximate it.

I started from the parametric functions for a sphere:

#declare Fx= function(u,v){R*cos(u)*cos(v)}
#declare Fy= function(u,v){R*sin(u)*cos(v)}
#declare Fz= function(u,v){R*sin(v)}
Then replaced the constant R with the function R(u,v).

There are three main parts to the function R(u,v). This bit

#declare R = function(u,v){cos(v)*cos(v)}
controls the 2d shape we see if we take a vertical cross section. It's a sort of figure-8. By using this figure-8 to modify the radius of the sphere, we get something like a torus but with the central hole just filled in.

The abs(sin(4*u)) varies the radius as we go round the longitude of the sphere. So

#declare R = function(u,v){cos(v)*cos(v) * abs(sin(4*u))}
gives the shape shown in the second image on the left, and
#declare R = function(u,v){cos(v)*cos(v)
    * 0.9-0.2*abs(cos(8*u))}
gives the shape shown in the third image.

The max() operation takes the union of those two shapes.

Another Heart

The f_heart() shape tends to render with a subtle crease across the middle because the numbers involved in the calculation get rather extreme. Here's a different heart shape that's not quite as true to the conventional Valentine's shape, but doesn't have a crease.
#declare R=function(u,v)
   {4*cos(v)*pow(sin(abs(u)),abs(u)) }

#declare Fx = function(u,v){R(u,v)*cos(u)*cos(v)*1.6}
#declare Fy = function(u,v){R(u,v)*sin(u)*cos(v)}
#declare Fz = function(u,v){2*sin(v)}
The functions are based on the parametric form of the sphere, but with the radius varying under the control of the R() function rather then being constant.

The *1.6 in Fx and the *2 in Fz are simply there to perform scaling. I could just as easily left them out of the functions and performed scale <1.6, 1, 2> on the completed surface.

Yet Another Heart

Here's another heart, and a heart hoop, that I discovered recently. They render extremely quickly and do look quite like the conventional Valentine shape.

These shapes are created by performing variable transformations on the standard f_torus() and f_sphere() functions. The y variable is replaced by y-pow(abs(x),0.8)*0.5 which causes the shape to be bent upwards.The z variable is replaced by z*2 in the f_sphere() to perform simple scaling.

  function { f_torus(y-pow(abs(x),0.8)*0.5,z,x,0.8,0.1) }
  function { f_sphere(y-pow(abs(x),0.8)*0.5,z*2,x,0.6) }


This surface is generated by the functions
#declare Fx = function(u,v){cos(u)*(R1 + R2*cos(v))
                     + pow((v/pi),100)}
#declare Fy = function(u,v){sin(u)*(R1 + R2*cos(v)) 
                     + 0.25*cos(5*u)}
#declare Fz = function(u,v){-2.3*ln(1 - v*0.3157) 
                     + 6*sin(v) +2*cos(v)}
The stalk of the apple really is part of the surface.

The shape is based on a fat torus, but with the tube part of the torus made slightly elliptical and tilted by means of the +2*cos(v) at the end of the Fz function.

The ln(1 - v*0.3157) bit in Fz becomes significant when v approaches pi (0.3157 is just a little lower than 1/pi). It creates the stalk.

The + pow((v/pi),100) bit in Fx adds a curve to the stalk. The effect only happens when v is very close to pi, so when using Ingo's macro to approximate the parametric it is necessary to use a large number of segments in the v direction.

The +0.25*cos(5*u) bit in Fy adds a gentle ripple to the shape.

NACA 4-digit airfoil section

The National Advisory Committee for Aeronautics published a system of standard airfoils designated by 4-digit and 5-digit codes. This parametric isosurface is an approximation to the NACA5415 aerofoil.

The code can be used to generate any NACA 4-digit aerofoil by changing the settings of "M", "P" and "T".

A description of the system can be found at www.aerospaceweb.org/question/airfoils/q0100.shtml.

Download a zip file containing the POV source files for all the images that appear on this page. The zip file contains versions of each shape using real parametric isosurfaces and using the param.inc approximation macro.

Up | Previous: Mathematical Zoo | Next: Seashells | Alphabetical Index