# Parametric spline functions

© Mike Williams 2002, 2003, 2004

 Up | Previous: New Stuff | Next: Patterns and Noise | Alphabetical Index

I've created all the images on this page both with Ingo's param.inc macro. (See param.inc for details), and more slowly, by using real parametric isosurfaces. The zip file at the end of the page contains both sets of source files. ```
#declare Fx = function(x,y)
{S(u).x + sin(v)}
#declare Fy = function(x,y)
{S(u).y + cos(v)}
#declare Fz = function(x,y)
{S(u).z}

#include "param.inc"

object {Parametric(Fx,Fy,Fz,
<0,-pi>,<17,pi>,100,20,"")
pigment {rgbt <1,1,1,0.4>}
finish {phong 0.5 phong_size 10}
}
```
The spline technique shown on the previous page doesn't work with splines that have loops in them. The problem is that we were using the spline control points as our x co-ordinate and expressing y and z in terms of that x. The sequence of control points can't loop back on itself.

The way to follow 3d splines that contain loops is to use all three of the spline dimensions to specify the path of the spline, and express x, y, and z in terms of a fourth variable, call it "u", which follows the control points.

So what we need is a parametric isosurface.

In this case "u" follows the spline control points, and x, y, z are expressed in terms of u like S(u).x, S(u).y, S(u).z. On its own that would give an infinitely thin string that follows the spline path. We can fatten it out by adding some terms in a second variable "v" which describe how far the surface is from the path.

Once again I have made the isosurface transparent and drawn the actual spline path inside it in yellow. ```
#declare Fx = function(x,y) {u}
#declare Fy = function(x,y)
{S(u).y + S2(v).y}
#declare Fz = function(x,y)
{S(u).z + S2(v).z}
```

## Bent prism

This parametric isosurface is equivalent to taking a prism object and bending it to follow an open spline path.

In this case, the prism is a five pointed star with cubic interpolation, given by the spline function S2(). The curved path along which the prism is bent is given by the spline function S(). ```
#declare Fx = function(x,y)
{(S(u).x * sin(v)/2)}
#declare Fy = function(x,y) {u}
#declare Fz = function(x,y)
{(S(u).x * cos(v)/2)}
```

## Lathe

The following examples will be based on this goblet.

I could have created this goblet as a lathe object, as a sor object or I could have used a non-parametric isosurface. However, I've used a parametric isosurface so that I can perform the alterations shown in the later examples.

The spline function S() is a one-dimensional spline which gives the profile of the goblet. ```
#declare Fx = function(x,y) {u}
#declare Fy = function(x,y)
{S(u).y * S2(v).y}
#declare Fz = function(x,y)
{S(u).y * S2(v).z}

```

## Prismatic lathe

This example is a combination of a prism and a lathe.

The profile of the goblet is given by the one-dimensional spline function S(), and the star-shaped cross section is given by the two-dimensional spline function S2(). ```
#declare Fx = function(x,y)
{(S(u).x * sin(v)/2) + S2(u).x}
#declare Fy = function(x,y) {u}
#declare Fz = function(x,y)
{(S(u).x * cos(v)/2) + S2(u).z}

```

## Bent lathe

In the same way that a prism can be bent along a curved spline, it's possible to bend a lathe.

The profile of the goblet is given by the one-dimensional spline function S(), and it is then bent along the two-dimensional spline S2(). ```
#declare Fx = function(x,y)
{(S(u).x * sin(v)/2)}
#declare Fy = function(x,y) {u}
#declare Fz = function(x,y)
{(S(u).z * cos(v)/2)}

```

## Two-way lathe

In this scene, the object almost looks like a lathe, but it has a different profile in the x direction from the z direction.

The x profile is given by the x component of the two-dimensional spline function S(), and the z profile is given by the z component of the same spline function. ## Four-way lathe

It's possible to extend this idea to a shape that uses four different splines to control the profile in the +x, -x, +z and -z directions.

This is achieved by mutiplying one x spline function by (v<=pi) and the other by (v>pi). The comparison operators return 0 for false and 1 for true, so the sum switches from being one spline to the other when v becomes pi.

Similarly the z spline functions are multiplied by (cos(v)<=0) and (cos(v)>0), which switch when v=pi/2 and switch back when v=3*pi/2.

```
#declare Fx  = function(x,y) {sin(v)/2 *
(S(u).x*-(v<=pi) + S2(u).x*-(v>pi)) }
#declare Fy  = function(x,y) {u}
#declare Fz  = function(x,y) {cos(v)/2 *
(S(u).z*(cos(v)<=0) + S2(u).z*(cos(v)>0))}
```
I've drawn in the four splines on one copy of the surface.