1.5 Constructive Solid Geometry




Part I - CSG with surfaces

So far we have seen what tools we have at our disposal for specifying locations in space (using different kinds of coordinate systems), creating 2D entities such as lines, curves and surfaces, and finally, in the last tutorial, you were introduced to some of the basic solid primitives that you can create using Rosetta. This alone already provides you with enough knowledge to create very simple drawings and models but if you have come this far, chances are, you wish to know how to create much more complex shapes then mere lines or solids.

In the field of solid modelling there is a concept known as Constructive Solid Geometry (or CSG) which consists in using Boolean operators to combine objects, or solid primitives, and create seemingly complex shapes. Rosetta provides you with the tools needed to perform these actions and they come in the form of the functions union , subtraction and intersection . All three can be used with either 2D entities, such as surfaces, and 3D objects but for now let’s consider the two-dimensional case.

Given the regions R0 and R1, their union – R0 ∪ R1 – will be the set of points which belong to either R0 or R1, in other words, all the points in R0 and all the points in R1. The union operation can be performed with Rosetta using the function union . Consider we have a rectangular surface and a circular surface positioned at one of its corners. To compute the union of these two surfaces we need only create them using the already known functions surface-rectangle and surface-circle and place them inside a union operation as such:

(union (surface-rectangle (xy 0 0) (xy 10 10))
       (surface-circle (xy 10 10) 5))

As you’d expect the result is simply the two surfaces combined as seen in the first image of Figure 1. Another possible operation is the intersection. The intersection of two regions R0 and R1 – U0 ∩ U1 – will produce only the points that are common to both regions, i.e., the part where these two regions are coincidental. Using the function intersection in the previous example, we have:

(intersection (surface-rectangle (xy 0 0) (xy 10 10))
              (surface-circle (xy 10 10) 5))

The result can be seen in the second image of Figure 1. Finally, given two regions R0 and R1, the subtraction of one by the other – R0 \ R1 – produces the number of points which belong to one region but not to the other. Unlike the two previous operations, the operation of subtraction is not commutative so keep in mind that subtracting a circle to a square and subtracting a square to a circle is not the same thing. We can test both cases with the same example as before and see the results in Figure 1:

(subtraction (surface-rectangle (xy 0 0) (xy 10 10))
              (surface-circle (xy 10 10) 5))

(subtraction (surface-circle (xy 10 10) 5)
             (surface-rectangle (xy 0 0) (xy 10 10)))



FIGURE 1 | From left to right: union, intersection and subtractions.
The outlines we included for better visualization and are not a result of the functions.


Besides these function Rosetta also provides two others which are very important: the function empty-shape and universal-shape . The function empty-shape returns an empty set of points in space and it represents the neutral element for union operations. In contrast, the universal-shape represents the set of all points in space and it represents the neutral element for intersection operations. Although not yet apparent how and why these two functions are useful it is important to know they exist. In later tutorials, when we start working with recursion, this importance will become obvious.



Part II - CSG with Solids

All the above functions can also be used with 3D entities and they wield much more interesting results. Taking the three-dimensional equivalent of the last example, a cube for the square and a sphere for the circle, we can see these operations in action in a very simple example:

(union (box (xyz 0 0 0) (xyz 10 10 10))
       (sphere (xyz 10 10 10) 5))

(intersection (box (xyz 20 0 0) (xyz 30 10 10))
              (sphere (xyz 30 10 10) 5))

(subtraction (box (xyz 40 0 0) (xyz 50 10 10))
             (sphere (xyz 50 10 10) 5))

(subtraction (sphere (xyz 70 10 10) 5)
             (box (xyz 60 0 0) (xyz 70 10 10)))



FIGURE 2 | From left to right: union, intersection and subtractions.


We could also consider the intersection of four spheres, laid out in a pyramid shape.

(intersection (sphere (pol 6 0) 10)
              (sphere (pol 6 (/ 2pi 3)) 10)
              (sphere (pol 6 (/ 4pi 3)) 10)
              (sphere (xyz 0 0 10) 10))

Or, instead of an intersection, we could subtract to the top sphere all the others. Since the subtraction operation is not commutative and we have more than one solid to subtract we must place the three spheres we are going to subtract inside a list or, alternatively, we could first apply a union to them and then perform the subtraction.

(subtraction (sphere (xyz 0 0 10) 10)
             (list (sphere (pol 6 0) 10)
                   (sphere (pol 6 (/ 2pi 3)) 10)
                   (sphere (pol 6 (/ 4pi 3)) 10)))


FIGURE 3 | The intersection and subtraction of four spheres.


Another interesting example is the intersection of three cylinders, laid out as if they were contained inside a cube.

(intersection
 (cylinder (xyz -10 0 0) 10 (xyz 10 0 0))
 (cylinder (xyz 0 -10 0) 10 (xyz 0 10 0))
 (cylinder (xyz 0 0 -10) 10 (xyz 0 0 10)))



FIGURE 4 | The intersection of three cylinders.


A more “galactic” example would be the subtraction of three tori to a sphere.

(subtraction (sphere (xyz 0 0 0) 10)
             (list (torus (xyz 0 0 0) 10 4)
                   (torus (xyz 0 0 5.4) 5 4)
                   (torus (xyz 0 0 -5.4) 5 4)))



FIGURE 5 | Subtraction of three torus to a sphere.


If we want to make a hollow cube with rounded off edges we could have the intersection of a cube and a sphere to which we subtract three cylinders.

(subtraction (sphere (xyz 0 0 0) 10)
             (list (torus (xyz 0 0 0) 10 4)
                   (torus (xyz 0 0 5.4) 5 4)
                   (torus (xyz 0 0 -5.4) 5 4)))



FIGURE 6 | Hollowed out cube with rounded off edges.


We could get a similar shape with the subtraction of seven spheres in a cross shape. We can also use an intersection instead to get another interesting result.

(subtraction (sphere (xyz 0 0 0) 10)
             (sphere (sph 10 0 0) 7.3)
             (sphere (sph 10 pi pi) 7.3)
             (sphere (sph 10 pi pi/2) 7.3)
             (sphere (sph 10 0 pi/2) 7.3)
             (sphere (sph 10 pi/2 pi/2) 7.3)
             (sphere (sph 10 pi/2 -pi/2) 7.3))

(intersection (sphere (xyz 0 0 0) 10)
              (union (sphere (sph 10 0 0) 7.3)
                     (sphere (sph 10 pi pi) 7.3)
                     (sphere (sph 10 pi pi/2) 7.3)
                     (sphere (sph 10 0 pi/2) 7.3)
                     (sphere (sph 10 pi/2 pi/2) 7.3)
                     (sphere (sph 10 pi/2 -pi/2) 7.3)))


FIGURE 7 | Subtraction and intersection of spheres


If we wanted to create a vaulted “roof” we could intersect half cylinders. Let’s consider the intersection of three cylinders that we then hollow out using smaller cylinders. To the result of that intersection we can subtract another cylinder, which can in fact by any other shape provided it is larger than the footprint of this shape, to “delete” the bottom part.

(subtraction
 (subtraction
 (list (union (cylinder (xyz 0 0 0) 10 (pol 10 (* 1 (/ 2pi 3))))
              (cylinder (xyz 0 0 0) 10 (pol 10 (* 2 (/ 2pi 3))))
              (cylinder (xyz 0 0 0) 10 (pol 10 (* 3 (/ 2pi 3)))))
       (union (cylinder (xyz 0 0 0) 8 (pol 10 (* 1 (/ 2pi 3))))
              (cylinder (xyz 0 0 0) 8 (pol 10 (* 2 (/ 2pi 3))))
              (cylinder (xyz 0 0 0) 8 (pol 10 (* 3 (/ 2pi 3))))))
 (cylinder (xyz 0 0 0) 16 -10)))



FIGURE 8 | Subtraction of cylinders.


We could use a similar approach, although a bit forced and lengthy, to simulate a cube with all six faces in the shape of vaults.

(subtraction (right-cuboid (xyz 0 0 0) 10 10 10)
             (list (cylinder (x 17) 13 10)
                   (cylinder (x -17) 13 10)
                   (cylinder (y 17) 13 10)
                   (cylinder (y -17) 13 10)
                   (cylinder (yz -5 -12) 13 (yz 5 -12))
                   (cylinder (yz -5 22) 13 (yz 5 22))
                   (cylinder (xyz 17 -5 5) 13 (xyz 17 5 5))
                   (cylinder (xyz -17 -5 5) 13 (xyz -17 5 5))
                   (cylinder (xyz -5 17 5) 13 (xyz 5 17 5))
                   (cylinder (xyz -5 -17 5) 13 (xyz 5 -17 5))
                   (cylinder (xz -5 22) 13 (xz 5 22))
                   (cylinder (xz -5 -12) 13 (xz 5 -12))))



FIGURE 9 | A “vaulted” cube.


One more example. If we take a box and subtract spheres to all vertices we get the following shape.

(subtraction (box (xyz 0 0 0) 10 10 10)
             (list (sphere (xyz 0 0 0) 5.5)
                   (sphere (xyz 10 0 0) 5.5)
                   (sphere (xyz 10 10 0) 5.5)
                   (sphere (xyz 0 10 0) 5.5)
                   (sphere (xyz 0 0 10) 5.5)
                   (sphere (xyz 10 0 10) 5.5)
                   (sphere (xyz 10 10 10) 5.5)
                   (sphere (xyz 0 10 10) 5.5)))



FIGURE 10 | Subtraction of spheres.


Finally, placing spheres along a bigger sphere and then subtracting them will produce the following shape:

(subtraction
 (subtraction (sphere (xyz 0 0 0) 10)
              (list (sphere (sph 10 0 0) 5.3)
                    (sphere (sph 10 0 pi/4) 5.3)
                    (sphere (sph 10 0 pi/2) 5.3)
                    (sphere (sph 10 0 (/ 3pi 4)) 5.3)
                    (sphere (sph 10 0 pi) 5.3)
                    (sphere (sph 10 0 -pi/4) 5.3)
                    (sphere (sph 10 0 (/ -3pi 4)) 5.3)
                    (sphere (sph 10 0 (/ 3pi 2)) 5.3)
                    (sphere (sph 10 pi/2 pi/2) 5.3)
                    (sphere (sph 10 pi/2 pi/4) 5.3)
                    (sphere (sph 10 pi/2 -pi/4) 5.3)
                    (sphere (sph 10 -pi/2 pi/2) 5.3)
                    (sphere (sph 10 -pi/2 (/ 3pi 4)) 5.3)
                    (sphere (sph 10 -pi/2 (/ -3pi 4)) 5.3)))
 (torus (xyz 0 0 0) 10 4))



FIGURE 11 | Subtraction of spheres and a torus.




As you can see, simply by using simple operations with solid primitives we can obtain very complex shapes. One thing you may have noticed though is that some of these examples require quite lengthy definitions even though the end result may not show it. One to the drawbacks of CSG is indeed that the effort to create a certain shape may not be entirely worth it at the end. Another problem reflected in the previous examples is the amount of positions and sizes that need to be calculated to get a certain desired result. Both these problems can be easily solved once we start working with data structures and recursion. These two concepts will be introduced in the intermediate section.

Top