Defining and Combining Shapes with Functions
Jakob Schmid 2004-09-27
This tutorial delves briefly into the wonderful world of functionally defined shapes, 2D as well 3D. This tutorial should be of interest of students of geometry and 3D modellers. The 3D examples can be used directly in POV-ray. The tutorial itself is made with Maple and converted to HTML.
We start out by defining a simple circle and a rectangle, transforming them, and combining them into new shapes. The next section takes the investigation one dimension further, as we define spheres and boxes, 3D-transformations and the combination of solid objects, also known as "Constructive Solid Modelling".
setup
| > | restart:with(plots): |
Warning, the name changecoords has been redefined
| > | setoptions(axes=normal, linestyle=SOLID, adaptive, resolution=50, scaling=CONSTRAINED, view=[-1.1 .. 1.1, -1.1 .. 1.1]); |
Defining 2D Shapes with Functions
The Circle
Remember the formula for a circle?
| > | x^2 + y^2 = r^2; |
This is the same as:
| > | x^2 + y^2 - r^2 = 0; |
We can make a circle function which takes the radius as the input value:
| > | circle := r -> x^2 + y^2 - r^2: |
Then we can plot it - the plot shows the set of points where the equation 'circle(1) = 0' is true:
| > | implicitplot(circle(1) = 0, x=-1..1, y=-1..1); |
The values inside the circle are all negative , and the values outside the circle are all positive . Thus, the formula for a disk is:
| > | x^2 + y^2 - r^2 < 0: |
This can be visualized by this density plot:
| > | densityplot(circle(1), x=-1..1, y=-1..1, grid=[20,20]); |
The Rectangle
The rectangle is a bit more complex.
We know that 'y^2' always will be positive. But if we subtract a constant value, e.g. 'y^2 - c' the expression will be negative for low absolute values of y and positive for high absolute values of y .
| > | implicitplot( y^2 - 0.5^2 = 0 ,x=-1..1, y=-1..1); |
Graphically, we now have a horizontal field, inside which all values are negative and outside which all values are positive:
| > | densityplot(y^2 - 0.5^2, x=-1..1, y=-1..1, grid=[20,20]); |
Similarly, we can make a vertical field:
| > | implicitplot( x^2 - 0.5^2 = 0 ,x=-1..1, y=-1..1); |
| > | densityplot(x^2 - 0.5^2, x=-1..1, y=-1..1, grid=[20,20]); |
... and now for the tricky part:
We define a new function, which is the maximum value of the two functions above .
This function has the property that the points inside both the fields defined by the functions above all are negative , and the points outside the two fields are positive . Thus, we have defined a rectangle.
The rectangle is defined by its width and height as:
| > | rectangle:=(w,h) -> max(x^2 - w^2, y^2 - h^2); |
| > | implicitplot(rectangle(.7,.7)=0,x=-1..1,y=-1..1); |
The formula for a rectangular area is:
| > | max(x^2 - w^2, y^2 - h^2) < 0: |
A density plot of the function:
| > | densityplot(rectangle(.7,.7), x=-1..1, y=-1..1, grid=[20,20]); |
Transformations
When we want to do transformations on the shapes, we substitute 'x' and 'y' in the shape function with transformed versions of same variables. The transformed versions look like the inverse of the required transformation, e.g. if you want to scale with 2, you have to divide 'x' and 'y' with 2, etc.
Scaling
Scaling by a factor 's' is done by substituting variable v with 'v/s'
We'll try scaling a circle with radius 1 down to half height - we do this by substituting 'y' with '2y':
| > | implicitplot( x^2 + (y*2)^2 - 1 = 0, x=-1..1, y=-1..1); |
Translation
Translation by (xt,yt) is done by substituting (x-xt) for x and (y-yt) for y:
We'll translate a circle with radius 0.5 to the upper-right quadrant:
| > | implicitplot( (x-0.5)^2 + (y-0.5)^2 - .5^2 = 0, x=-1..1, y=-1..1); |
Constructive Plane Geometry
Intersection
The rectangle function showed us that the maximum value of two shape functions is the set of points common to the two functions. This is remeniscent of an AND operation or an intersection between sets.
Now, we can plot the intersection between a rectangle and a circle:
| > | implicitplot( max( rectangle(0.8,0.8) , circle(0.9) ) = 0 ,x=-1..1,y=-1..1,grid=[80,80]); |
Union
Conversely, the minimum of two shape functions is like an OR operation or a union .
| > | implicitplot( min( rectangle(0.8,0.8) , circle(0.9) ) = 0 ,x=-1..1,y=-1..1,grid=[80,80]); |
Inversion
We can also inverse a function. When intersected with another function, it will graphically "cut iself out" of the other shape:
| > | implicitplot( max(rectangle(0.8,0.8), -circle(0.5)) = 0 ,x=-1..1,y=-1..1,grid=[80,80]); |
Defining 3D Shapes with Functions
setup
| > | rng := -1.1 .. 1.1: setoptions3d(style=hidden, axes=none, scaling=CONSTRAINED, color=black, projection=normal): |
The Sphere
The sphere function is very similar to the circle function:
| > | sphere := r -> x^2 + y^2 + z^2 - r^2: implicitplot3d(sphere(1)=0,x=rng,y=rng,z=rng, grid=[15,15,15], projection=normal, lightmodel=light2, orientation=[25,55]); |
The Box
The box is very similar to the rectangle:
| > | box := (w,h,d) -> max((x^2-w^2),(y^2-h^2),(z^2-d^2)): implicitplot3d(box(1,1,1)=0,x=rng,y=rng,z=rng, grid=[15,15,15], projection=normal, lightmodel=light2, orientation=[25,55]); |
Transformations
3D transformations are just like their 2D counterparts. We'll just show a single example.
| > | implicitplot3d(x^2 + (y*2)^2 + z^2 - 1, x=rng,y=rng,z=rng, grid=[15,15,15], projection=normal, lightmodel=light2, orientation=[25,55]); |
Constructive Solid Geometry
Again, 3D constructive geometry is excactly like 2D constructive geometry.
The intersection between the sphere and the box:
| > | implicitplot3d( max( sphere(1) , box(0.8,0.8,0.8) ) = 0 , x=rng,y=rng,z=rng, grid=[25,25,25], projection=normal, lightmodel=light2, orientation=[25,55]); |
A little more complex: the intersection between a box and an inverted sphere - inside this is a sphere with a inverted small (translated) sphere "cut-out":
| > | implicitplot3d( min( max( sphere(0.7) , -((x-1)^2 + y^2 + z^2 - .3) ), max( box(0.8,0.8,0.8) , -sphere(1) ) ) = 0, x=rng,y=rng,z=rng, grid=[25,25,25], projection=normal, lightmodel=light2, orientation=[25,55]); |
| > |