On this page:
7.3.1 Exercises 34
7.3.1.1 Question 121
7.3.1.2 Question 122
7.3.1.3 Question 123
7.3.1.4 Question 124
7.3.1.5 Question 125
7.3.1.6 Question 126
7.3.1.7 Question 127
7.3.1.8 Question 128
7.3.1.9 Question 129
7.3.1.10 Question 130
7.3.1.11 Question 131
7.3.1.12 Question 132
7.3.1.13 Question 133
7.3.1.14 Question 134

7.3 Algebra of Shapes

In the previous section we saw the need for the concept of empty shape, which becomes more evident when we compare the operations for combining shapes with basic algebraic operations, such as sum and product. To begin, let us consider a function that adds numbers in an array:

sum(numbers) =

  if numbers == []

    0

  else

    numbers[1]+sum(numbers[2:end])

  end

As we can see in the previous function, the sum of an empty array of numbers is zero. This makes sense because, when there are no numbers to add, the total is necessarily zero. Moreover, during recursion, there are pending sums and, when it reaches the base case, the function needs to return a value that does not affect those pending sums, which in this case would have to be zero, since it is the neutral element of the sum.

Likewise, if we think of a function that calculates the union of regions in an array, we should write:

unions(regions) =

  if regions == []

    empty_shape()

  else

    union(regions[1], unions(regions[2:end]))

  end

where the empty_shape \(\varnothing\) is the neutral element of the union operation.

Let us now consider a function that multiplies numbers in an array:

product(numbers) =

  if numbers == []

    ???

  else

    numbers[1]*product(numbers[2:end])

  end

What value should the function return in the base case? In other words, what is the product of an empty array of numbers? Though we might be tempted to use zero as the base case value, that would be incorrect because zero is the absorbing element of the product and, therefore, in the case of a non-empty array of numbers, it would be propagated throughout the sequence of pending products, producing a final result of zero. Thus, it becomes clear that the correct value for the basic scenario has to be 1, i.e., the neutral element of the product:

product(numbers) =

  if numbers == []

    1

  else

    numbers[1]*product(numbers[2:end])

  end

This analysis is crucial for the correct definition of a function that computes the intersection of regions in an array. Although it is straightforward to write a first draft:

intersections(regions) =

  if regions == []

    ???

  else

    intersection(regions[1], intersections(regions[2:end]))

  end

it is not entirely clear what to return in the base case. We know that this value has to be the neutral element of the combination operation, which, in this case, is the intersection. This neutral element will have to be, necessarily, the universal shape \(U\), i.e., the shape that includes all the points of space. In Khepri, this imaginary shape is produced by the function universal_shape, allowing us to complete the definition:

intersections(regions) =

  if regions == []

    universal_shape()

  else

    intersection(regions[1], intersections(regions[2:end]))

  end

It is important that we understand that the need for the empty_shape and the universal_shape functions results from us having to assure the correct mathematical behavior of the union, intersection and subtraction operations of regions. That mathematical behavior is dictated by the following functions of the algebra of regions:

\[R \cup \varnothing = \varnothing \cup R = R\] \[R \cup U = U \cup R = U\] \[R \cup R = R\] \[R \cap \varnothing = \varnothing \cap R = \varnothing\] \[R \cap U = U \cap R = R\] \[R \cap R = R\] \[R \setminus \varnothing = R\] \[\varnothing \setminus R = \varnothing\] \[R \setminus R = \varnothing\]

7.3.1 Exercises 34
7.3.1.1 Question 121

The algebra of regions we elaborated is incomplete because it does not include the complement operation of a region. The complement \(R^C\) of a region \(R\) is defined as the subtraction between the universal region \(U\) and the region \(R\):

\[R^C=U\setminus R\]

The complement operation allows the representation of the concept of hole. A hole with the shape of the region \(R\) is obtained simply through \(R^C\). A hole has no obvious geometric representation, as it is difficult to imagine a hole without knowing in which region the hole is located. However, from the mathematical point of view, the concept makes sense as long as the algebraic operations on the regions know how to interpret it. For example, given the hole \(R_1^C\), we can apply it to a region \(R_0\) through the intersection of the two regions \(R_0\cap R_1^C\). As CAD tools do not know how to handle the complement of regions, the operation will have to be translated in terms of other operations already known. In this case, the subtraction is an obvious choice, as \(R_0\cap R_1^C=R_0\setminus R_1\).

To complete the algebra of holes, it is necessary that we define the result of the union, intersection and subtraction operations when applied to holes. Define mathematically those operations, as well as the combination between regions and holes.

7.3.1.2 Question 122

Since Khepri does not implement the concept of complement, define a constructor for the complement of regions. The constructor should receive the region from which the complement is intended and should return an object that symbolically represents the complement of the region. Do not forget that the complement of a region’s complement is the region itself.

Also define a recognizer of complements that receives any type of object and only returns true for those that represent complements of regions.

7.3.1.3 Question 123

Define the union, intersection, and subtraction operations of regions so as to deal with the complement of regions.

7.3.1.4 Question 124

Consider the construction of a region composed by a recursive union of regular polygons successively smaller and centered at the vertices of the polygon immediately bigger, as seen in the three examples presented in the following figure:

image

As it happened with the regular_polygon and vertices_polygon_regular functions defined in section \ref{sec:2DGeometricModeling}, each of these polygons is characterized for having a certain number of sides \(n\), for being inscribed in a circumference centered at a point \(P\) and with a radius \(r\), and for having a vertex that makes an angle \(\phi\) with the \(X\) axis.

Furthermore, the construction of regular polygons is done so that each vertex is the center of a new identical polygon, but inscribed in a circle whose radius is a fraction (given by \(\alpha_r\)) of the radius \(r\), with this process being repeated for a certain number of levels. For example, in the previous figure, the left image was created with \(p=(0,0)\), \(r=1\), \(\phi=0\), \(\alpha_r=0.3\), \(n=4\), and with a number of levels equal to \(2\). In fact, the images were produced by the evaluation of the following expressions:

recursive_polygons(xy(0, 0), 1, 0, 0.3, 4, 2)

recursive_polygons(xy(3, 0), 1, pi/3, 0.3, 3, 3)

recursive_polygons(xy(6, 0), 1, 0, 0.3, 5, 4)

7.3.1.5 Question 125

The Petronas twin towers were designed by the Argentine architect César Pelli and were considered the tallest buildings in the world from 1998 to 2004. This figure shows a perspective of one of the towers.

Petronas Towers, located at Kuala Lumpur, in Malaysia. Photograph by Mel Starrs.

image

The towers’ section, strongly inspired by Islamic motifs, is composed by two intersecting squares, one rotated 45 degrees, to which circles were added at the intersection points, as it can be seen in the scheme below.

image

Note that the circles are tangent to the imaginary edges that connect the vertices.

Define a Julia function named petronas_section that receives the center of the section and the length \(l\), and produces the section of the Petronas towers. Suggestion: use the surface_regular_polygon, surface_circle, and union functions to generate the relevant regions.

7.3.1.6 Question 126

Define the function petronas_tower that, from the base center, builds a succession of sections of the Petronas tower in order to reproduce the real geometry of building, as illustrated in the following perspective where the function was invoked twice to generate towers in different positions. Note that the sections’ length decrease at a given point of the towers’ height.

image

7.3.1.7 Question 127

Consider the construction of a sphere made of cones like the one presented in the following image:

image

Notice that all the cones have their vertex in the same point and are oriented so that the center of the base lies on a virtual sphere. Also note that all the meridians and parallels have the same number of cones, and that the radius of the base of the cones diminishes as we come closer to the poles, so that the cones do not interfere with each other.

Write a Julia program capable of building the sphere of cones. The function should receive the center and radius of the sphere, and the number and radius of the cones on the equator.

7.3.1.8 Question 128

Consider a variation on the sphere of cones from the previous exercise in which, instead of diminishing the radius of the cones’ base as we get closer to the poles, we diminish the number of cones, as presented in the following image:

image

Write a Julia program able to build this sphere of cones. The function should receive the center and radius of the sphere, and the number and radius of the cones on the equator.

7.3.1.9 Question 129

Define a Julia function to create perforated spherical shells, as the ones presented below:

image

The function should have as arguments the center, radius, and thickness of the spherical shell, and the radius and number of perforations to perform along the equator. This number should diminish as we come closer to the poles.

7.3.1.10 Question 130

Consider the following construction built from a random arrangement of perforated spheres:

image

To model the previous image, define a function that receives two points, which define the limits of an imaginary volume (parallel to the coordinated axes) inside which are located the centers of the spheres, the minimum and maximum radius of each sphere, the thickness of the shell, the number of spheres to create, and, finally, the necessary parameters to do the same type of perforations on each sphere.

Note that the interior of the construction should be unobstructed, as illustrated in the following section view:

image

7.3.1.11 Question 131

An impossible cube (also known as irrational cube) is a famous optical illusion in which a cube seems to have some edges in front of others in a seemingly impossible configuration. The following image shows an impossible cube.

image

Define an impossible_cube function that creates impossible cubes.

7.3.1.12 Question 132

Consider a cube built from an arrangement of smaller cubes, as presented in the following image:

image

Each smaller cube has a third of the side of the built cube. Define a function that, from the coordinates of one vertex and the length of the side of the cube, creates a cube with the arrangement of smaller cubes as shown in the previous image.

7.3.1.13 Question 133

The Menger sponge is a well-known fractal invented by the mathematician Karl Menger. The following image illustrates several construction stages of a Menger sponge.

image

Like the previous exercise, building a Menger sponge can be done through the composition of smaller cubes, with the nuance of replacing the smaller cubes by (sub-)sponges of Menger. Naturally, in the case a computer implementation, an infinite recursion is impracticable and thus we need to establish a stopping condition to guarantee that, at a certain point, no more (sub-)sponges of Menger are created.

Define the menger_sponge function that receives the coordinate of one vertex of the sponge, the sponge dimension and the desired level of depth for the recursion.

7.3.1.14 Question 134

Consider the following barrel vaults, composed by semi-cylindrical arches:

image

Define a function called barrel_vault that, given the center of the vault, the radius of the circle that circumscribes the vault, the thickness of the vault, and the number of arches to place, produces vaults as the ones presented above. Make sure your function is able to generate the following vault with only three arches:

image