In this chapter, you’ll extend the lessons you’ve learned so far to build a complex design with OpenSCAD. Specifically, you’ll employ an iterative design cycle to plan and complete a larger project. First, you’ll apply computational thinking to analyze and plan your design. Then, you’ll apply the popular walking skeleton approach to evolve a low-fidelity prototype from a basic, abstract design into a highly detailed final design. Using this method, you’ll connect all the project’s major components before fleshing out each component’s individual details. As a final step, you’ll fill in the smaller details to finish the project.
The design cycle is a common methodology with four sequential stages to help develop solutions to complex design projects:
Investigate
Plan
Create
Evaluate
Keep in mind that the stages of the design cycle are more like a looping cycle. You will probably revisit stages several times throughout the process until you are satisfied with your final design.
Let’s follow the design cycle to create a model of Italy’s famous Leaning Tower of Pisa (Figure 7-1).
The focus of this project is to combine the design process with computational thinking, so we’ll create a recognizable likeness of this famous building, rather than an architecturally accurate scale model.
The first step is to search for photos of the Leaning Tower of Pisa to help visualize the final design. We collected images showing different views to provide a sense of what the building looks like from every angle, including front, back, left, right, and top. We (unsurprisingly) couldn’t find a photo of the bottom view, but we looked for photos that clearly show how the tower interacts with the ground.
The Investigate step of the design cycle is important even if you want to build something of your own invention. If you can’t find an exact picture of what you want to build, look for something similar. If you don’t have any luck, sketch a rough draft of your intended design by hand. Visualizing your design before you code it will save you much time and frustration. The idea is to draw a map of your development process before typing a single line of code.
With a firm understanding of what the Leaning Tower of Pisa looks like, you’ll analyze the building to identify where you can apply the principles of computational thinking: decomposition, patterns, abstraction, and algorithms. Applying these principles when creating designs with OpenSCAD (or any other programming language for that matter) will help you work smarter, not harder, and will allow the computer to do the tedious work for you.
Decomposition is the process of breaking a large, complex problem into smaller, easier-to-describe subproblems, which helps you recognize when to create modules and separate files for a large project. One way to decompose the Leaning Tower of Pisa is to divide the building into three distinct sections (bottom, middle, and top), all of which are “leaning” at the same angle. You then can break those three sections into smaller subcomponents, like columns, levels, fences, and archways (Figure 7-2).
Finding patterns in a design is a bit like decomposition, because the goal is to break a complex design into smaller, more manageable pieces. However, the objective with patterns is to summarize the process by which elements repeat (Figure 7-3).
For instance, the middle section of the Leaning Tower of Pisa is composed of essentially the same group of shapes repeated six times. Each of those “levels” also includes repeated arches/columns around its outside circumference. In fact, both the bottom and the top sections also contain repeated arches/columns (although at different sizes and intervals from the middle section). Additionally, the top section has two fences with repeated posts, as well as a repeated archway shape in numerous sizes.
Abstraction is the process of summarizing smaller details with higher-level descriptions in order to communicate big-picture information. Rendering each section of the Leaning Tower of Pisa as a cylinder is a general abstraction that omits a lot of detail (Figure 7-4).
Abstracting the three sections as cylinders allows you to focus on larger elements (like the angle of the tower’s lean and each section’s proportional sizing) before considering the smaller, less consequential features.
Because so much repetition exists within the Leaning Tower of Pisa’s architecture, our design algorithm for creating the tower requires numerous loops. For instance, the columns around the tower’s perimeter involve a loop that repeatedly increments the angle of rotation. The looping columns occur in all three sections (bottom, middle, and top), although each section contains different numbers of repeating columns of various sizes.
The multiple use cases for the different sizes of columns around the tower’s perimeter suggest that a parameterized column module would be an appropriate algorithmic choice; incorporating parameters in the module allows you to reuse the same basic code for each section of the tower. In fact, the design for this project provides many opportunities to use modules in your code. Each of the basic components you identify during a project’s Decomposition and Patterns analysis will likely be a candidate for a module. In this case, you can create modules for the top section, middle section, bottom section, level, column, archway, and fence.
The goals of the first two steps of the design cycle are understanding what you want to build and creating a well-defined strategy for breaking a large, complex project into a collection of manageable pieces. In step 3, you start coding by using the walking skeleton development process, allowing you to evolve the design from rough building blocks into a final highly detailed finished piece. You’ll use this approach to create several versions of the tower, making incremental improvements with each design iteration (Figure 7-5).
The first versions of the top, middle, and bottom sections in Figure 7-5 are rough abstractions of the final, detailed versions of those same sections. The design’s main pieces are connected first as an architectural skeleton, then fleshed out over time in an evolutionary process—hence the name, walking skeleton.
The “final” step of the design cycle is more of a question than anything else. Does your design accomplish what you intended? Based on the answer, decide which steps of the design process you need to revisit.
To answer that question for the tower example, you’ll visually compare the rendered OpenSCAD model of the tower with a photograph of the real Leaning Tower of Pisa. In fact, you’ll apply the Evaluate step after each iteration of the walking skeleton to determine which features to add for the next iteration.
For the remainder of this chapter, you’ll build several versions of the Leaning Tower of Pisa in a series of design iterations to demonstrate the walking skeleton development process. Each version will add more details, so you’ll compare each iteration with the reference photo and reconsider your plan and algorithms as you go. This approach allows you to apply the design cycle to each iteration without having to worry too much about the way the code is organized or connected.
The goal for the first version of the tower design is to create and connect the building’s three sections: top, middle, and bottom. You’ll also include a platform for stability (the tower is leaning, after all).
Decomposing the building’s overall design into smaller pieces provides the setup to evolve the design in stages, as you’ll be able to edit the tower’s various sections independently. Initially, you’ll generate only basic cylinders as big-picture approximations of each section’s design, because the first stage of a walking skeleton focuses solely on connecting the project’s separate building blocks (Figure 7-6).
Although you could use a series of modules contained within one very large file, you’ll instead separate these sections into stand-alone files (bottom.scad, middle.scad, and top.scad) and create one connector file (tower.scad). Having the code in separate files allows you to create, find, and edit relevant modules for each section easily. You could also use this multi-file approach to collaborate with others, so each person could focus on a different file simultaneously.
The trickiest part of this first step is considering how the different components of the design interact with each other. Usually, this means identifying the crucial information each piece of the design needs in order to be drawn. For instance, to draw an abstract, cylinder-based representation of each section, you need, at minimum, a height and radius for that section. The main project file (tower.scad) will communicate that information to each section via module parameters.
Because the top, middle, and bottom sections all use a cylinder as an abstract representation of the final design, creating those files first is relatively easy. The code for each section looks very similar at this stage of the design, which is another advantage of abstraction. You don’t need to worry about small details at the moment, so you can copy and paste code in the three files with only minimal changes.
The bottom.scad file defines a cylinder to create a simple version of the tower’s lowest section:
// bottom.scad v1
1 module bottom_section(width, height) {
radius = 0.5 * width;
cylinder(h=height, r=radius);
}
The tower.scad file communicates the dimensions for the bottom section to the bottom_section
module via the width
and height
parameters 1.
Next, the middle.scad file defines a starting version of the middle section:
// middle.scad v1
1 module middle_section(width, height) {
radius = 0.5 * width;
cylinder(h=height, r=radius);
}
Again, the tower.scad file communicates the width and height to the middle_section
module via the width
and height
parameters 1.
Similarly, the top.scad file defines a basic cylinder to represent the tower’s top section:
// top.scad v1
1 module top_section(width, height) {
radius = 0.5 * width;
2 cylinder(h=height, r=radius);
}
As with the bottom and middle sections, the tower.scad file uses parameters to supply needed dimensions to the top_section
module 1. The order and number of parameters in each of the three modules is the same. This is a deliberate choice to simplify the design’s architecture. As the complexity of the design increases, this consistent interface between top.scad, bottom.scad, middle.scad, and tower.scad will make adjusting the proportions of each section easier. The decision to think of each cylinder’s measurements in terms of the structure’s radius rather than its diameter 2 was also deliberate (though somewhat arbitrary). At this stage, using width as the cylinder’s diameter would also make sense.
Next we create tower.scad, which provides the necessary dimensions and connects the tower’s three sections with the platform:
// tower.scad v1
1 use <bottom.scad>
use <middle.scad>
use <top.scad>
2 tower_height = 100;
tower_width = 0.3 * tower_height;
bottom_height = 0.2 * tower_height;
middle_height = 0.65 * tower_height;
top_height = 0.15 * tower_height;
base_width = 2 * tower_width;
base_height = 0.1 * tower_width;
lean_angle = 4;
3 $fn = 20;
4 rotate([lean_angle, 0, 0]) {
color("grey") {
bottom_section(tower_width, bottom_height);
}
color("lightgrey") {
translate([0, 0, bottom_height])
middle_section(tower_width, middle_height);
}
color("white") {
translate([0, 0, bottom_height + middle_height])
5 top_section(tower_width, top_height);
}
}
color("lightgreen") {
6 cube([base_width, base_width, base_height], center=true);
}
The first section of the tower.scad file links to the three files described previously that define the tower’s top, middle, and bottom sections 1. The next section defines variables to help organize the tower’s important characteristics 2.
Since the design includes not only the tower but also a platform for stability, you create variables to organize the overall tower’s height and width (tower_height
and tower_width
), the height of each section of the tower (bottom_height
, middle_height
, and top_height
), the height and width of the platform (base_height
and base_width
), and the overall angle of the “lean” of the tower (lean_angle
). You initially set the tower_height
variable to an arbitrary value, and then use it as part of the definition for most of the other variables. For instance, the height of the bottom section is 20 percent of the tower_height
variable, so if you want to change the size of the entire design, you need to change only the tower_height
variable’s value.
Next, you use a relatively small number of segments (20) to approximate curved shapes to speed up the rendering of the initial designs 3. The last design iteration increases the number of segments to 100 in order to generate smoother curved surfaces in the final design.
To avoid duplicating the same rotate operation for all three sections, you use a single operation to apply a consistent angle of rotation to each of the three sections 4. Each section is called via the appropriate module, with parameters to adjust its width and height. The translate
operation moves the middle and top sections along the z-axis 5.
Finally, you draw the platform as a simple cuboid 6. You also apply different colors to the ground and each section to signify basic proportionality.
From this point on, you won’t need to make major changes to the tower.scad file. Your initial efforts to size and place each section correctly will form the architectural “skeleton” of the tower design, while your next design iterations will fill in missing details for the tower’s top, middle, and bottom sections. The only changes you might need to make to this file in the future would involve adjusting parameters to tweak proportionality as your design evolves, or changing $fn
to increase the rendered model’s smoothness. You’d simply swap out numerical values rather than write new code statements to make those changes.
Let’s take a closer look at the tower’s middle section (middle.scad) for the second iteration and apply some computational thinking techniques from the planning stage—namely, decomposition and finding patterns. In the middle section, the same collection of shapes (or levels) repeats vertically six times (Figure 7-7).
Figure 7-8 shows just one of those repeated level shapes.
To create these repeated levels, you need to make the following changes to the middle.scad file:
// middle.scad v2
level(50, 25);
module middle_section(width, height) {
level_height = height / 6;
level_radius = 0.5 * width;
1 for (h=[0:1:5]) {
floor_offset = h * level_height;
translate([0, 0, floor_offset])
level(level_radius, level_height);
}
}
2 module level(level_radius, level_height) {
lip_height = 0.1 * level_height;
inner_radius = 0.7 * level_radius;
overhang_height = 0.3 * level_height;
3 overhang_radius = 0.95 * level_radius;
// lip
translate([0, 0, level_height - lip_height])
cylinder(h=lip_height, r=level_radius);
// overhang
translate([0, 0, level_height - lip_height - overhang_height])
cylinder(h=overhang_height, r=overhang_radius);
// inner structure
cylinder(h=level_height, r=inner_radius);
}
These changes add more detail to the middle section so it’s no longer an abstract cylinder. The level
module 2 organizes all the shapes that construct each floor of the middle section, and a for
loop 1 creates a new level
shape repeatedly for each of the six floors in the section. Each level of this section now includes a lip that extends to the full radius of the tower, an overhang that provides a ceiling for columns, and an inner structure to house stairs, doors, and so forth. You create several variables to relate the size of each level feature (lip_height
, inner_radius
, overhang_height
, and overhang_radius
) to the level
module parameters (level_radius
and level_height
) 3.
With this repeating level
module, you can simultaneously update all six floors at once by making a change in exactly one place. For instance, if you want to make each level’s lip a little thicker or change the overhang radius to provide more room for columns, you can make a single, simple change to the level
module definition. Because you are adding detail to only the middle_section
module in this phase of our walking skeleton approach, middle.scad is the only file you needed to update for the second iteration of the tower design.
To see these new changes reflected in the overall design (Figure 7-7), save middle.scad, and then preview the entire design in tower.scad. In addition to making your design changes permanent, saving the middle.scad file lets OpenSCAD know you want other files to use the updated code. If you want to see the middle_section
or level
shapes in isolation, create the shape at the top of middle.scad and then preview that file. You can include a statement to draw a middle_section
or level
shape in middle.scad without worrying that the shape will also automatically show up in other files. Connecting another file with middle.scad with a use
directive simply means that module definitions from middle.scad will be accessible in tower.scad. No drawn shapes from middle.scad will be shown unless the connected file uses a module from middle.scad.
The next pattern to consider in your computational thinking is the repetition of columns and arches along each floor’s perimeter in the middle section (Figure 7-9).
To apply these new patterns to the design, you create a column
shape and repeat that new shape along the circumference of the level
module. This means you need to modify the middle.scad file again, as that’s where the level
module is defined. To create a column
shape, you also define a column
module in a new column.scad file.
In the design cycle’s planning phase, you noticed that columns and arches repeat around the circumference of each of the tower’s three sections. Because you need to include column shapes in multiple files, defining the column module in a separate file makes it easier for different sections to use that new shape definition. Columns and arches repeat in different patterns in each section, and they also vary in their ornamentation. That’s why at this initial stage, you’ll focus on creating an abstract column with basic components (Figure 7-10). You can then update this basic definition of a column in a later design iteration.
Creating a column
module in a separate file called column.scad makes it easier to share and evolve your use of columns in the future as needed:
// column.scad v3
1 module column(col_width, col_height) {
col_radius = 0.5 * col_width;
2 orn_height = 0.05 * col_height;
translate([-col_radius, -col_radius, col_height - orn_height])
cube([col_width, col_width, orn_height]);
cylinder(h=col_height, r=col_radius);
translate([-col_radius, -col_radius, 0])
cube([col_width, col_width, orn_height]);
}
As with other modules, you include two parameters (col_width
and col_height
) in the column
module 1 to provide the necessary information to create a column shape. Based on the column height and column width, variables are created (col_radius
and orn_height
) to describe the column’s radius and the ornamentation’s height included at both the top and bottom of a column 2. While it may seem to make the module definition more complicated, defining and using these variables rather than placing repeated arithmetic calculations as module parameters or inside operations reduces the number of possibilities for error, groups all of the design assumptions at the top of the module, and makes it easier to update all uses of a measurement.
To invoke this new column
module, you then modify the level
module in middle.scad to draw repeating columns and arches around the circumference of each level:
// middle.scad v3
1 use <column.scad>
...
module level(level_radius, level_height) {
2 lip_height = 0.1 * level_height;
inner_radius = 0.7 * level_radius;
overhang_height = 0.3 * level_height;
overhang_radius = 0.95 * level_radius;
num_cols = 24;
angle_size = 360 / num_cols;
col_height = 0.65 * level_height;
col_width = 0.2 * col_height;
arch_depth = 2 * (level_radius - inner_radius);
// lip
translate([0, 0, level_height - lip_height])
cylinder(h=lip_height, r=level_radius);
translate([0, 0, col_height]) {
difference() {
// overhang
cylinder(h=overhang_height, r=overhang_radius);
// arches
3 for (i=[0:1:num_cols-1]) {
angle = i * angle_size + angle_size/2;
rotate([0, 0, angle])
translate([inner_radius, 0, 0])
rotate([0, 90, 0])
cylinder(h=arch_depth, r=col_width, center=true);
}
}
}
// inner structure
cylinder(h=level_height, r=inner_radius);
// columns
4 for (i=[0:1:num_cols-1]) {
angle = i * angle_size;
rotate([0, 0, angle])
translate([overhang_radius - 0.5 * col_width, 0, 0])
column(col_width, col_height);
}
}
Comparing this updated version of middle.scad with the version from your second design iteration reveals three major additions to the level
module. First, column.scad is connected to this file 1 with a use
directive so that you can use the new column
module to draw column shapes in this file. Next, variables are defined to describe the number of columns per level (num_cols
), the angle at which the columns should be repeated along the circumference of the tower (angle_size
), the width and height of each column (col_width
and col_height
), and the depth of the arch connecting every two columns that will be carved away from the overhang of each level (arch_depth
) 2.
After creating the overhang, you include a for
loop within a difference operation to carve away arches between the location of each column 3. A final for
loop repeats columns along the level’s circumference 4. You could combine these two loops into a single for
loop that uses an if
statement; however, the loops are separated here to make the logic clearer.
As before, to see these new changes reflected in the overall design, save both middle.scad and column.scad; then preview the entire tower design in tower.scad. To see only the middle section without the rest of the tower, include a statement to draw a middle_section
shape at the top of middle.scad; then preview the design in middle.scad. You can also easily see only a column shape by including a statement to draw a column
shape at the top of column.scad and then previewing the design in that file.
After using a relatively small amount of code to add a large number of repeating columns and arches to the middle section, that section of the tower (Figure 7-11) is now more recognizably similar to our reference photo of the Leaning Tower of Pisa (Figure 7-1).
However, as you can see in Figure 7-11, the top and bottom sections are still abstract simplifications. Applying the design cycle’s Evaluate step after each iteration of the walking skeleton helps identify missing details that might offer the most noticeable improvements to a design. After this iteration, you should once again consult the reference photo (Figure 7-1) to decide which section of the tower now most needs improvement.
The top of the tower is missing fences, repeating columns, and archways (windows and doors), so the next iteration focuses on adding those details. You’ll add two fences to the top section, as well as alternating archways of different sizes and heights (Figure 7-12), so you’ll modify top.scad by adding a fence
module and an archway
module. You’ll draw the archway
module in different sizes to create the doors and windows shown in the top section of our reference photograph (Figure 7-1).
This updated version of the top.scad file adds the fence and archway details to the tower’s top section:
// top.scad v4
module top_section(width, height) {
1 top_radius = 0.4 * width;
room_radius = 0.75 * top_radius;
num_doors= 5;
door_angle= 360 / num_doors;
overhang_height = 0.1 * height;
overhang_width = 1.1 * top_radius;
door_height = 0.6 * height;
door_width = 0.35 * height;
window_height = 0.25 * height;
window_width = 0.15 * height;
// overhang
translate([0, 0, height - overhang_height])
cylinder(h=overhang_height, r=overhang_width);
//inner structure
difference() {
cylinder(h=height, r=top_radius);
translate([0, 0, 1]) {
cylinder(h=height-2, r=room_radius);
2 for (i=[0:1:num_doors-1]) {
angle = i * door_angle;
rotate([0, 0, angle])
translate([top_radius-2, 0, 0.25*height])
// doors
archway(door_height, door_width, room_radius);
rotate([0, 0, angle+0.5*door_angle])
translate([top_radius - 2, 0, 0.6*height])
// windows
archway(window_height, window_width, room_radius);
}
}
}
//fencing
translate([0, 0, height])
fence(15, 3, top_radius, 1);
3 fence(20, 3, 0.5*width, 1);
}
4 module fence(num_posts, fence_height, fence_radius, post_width) {
post_radius = 0.5 * post_width;
angle_size = 360/num_posts;
ring_height = 0.5;
post_height = fence_height - ring_height;
translate([0, 0, post_height])
ring(fence_radius - post_width, fence_radius, ring_height);
translate([0, 0, post_height / 2])
ring(fence_radius - post_width, fence_radius, ring_height);
for (i=[0:1:num_posts-1]) {
angle = i * angle_size;
rotate([0, 0, angle])
translate([fence_radius - post_radius, 0, 0])
cylinder(h=post_height, r=post_radius);
}
}
5 module ring(inner_radius, outer_radius, height) {
difference() {
cylinder(h=height, r=outer_radius);
translate([0, 0, 1])
cylinder(h=height+2, r=inner_radius, center=true);
}
}
6 module archway(height, width, depth) {
radius = 0.5 * width;
rotate([90, 0, -90]) {
translate([0, (height - radius) / 2, -depth / 2])
cylinder(h=depth, r=radius);
cube([width, height - radius, depth], center=true);
}
}
As with the other module definitions, you begin by defining variables to describe the top section’s various features 1. You base the number of windows on the number of doors (num_doors
), but otherwise, you deliberately choose variable names that are self-documenting. A for
loop contained within a difference
operation subtracts repeated windows and doors from the top section’s inner structure 2. Windows and doors have similar shapes, so you define a single archway
module that lets you vary the size of window and door shapes with the height
, width
, and depth
parameters 6.
The top_section
module ends by drawing two fence shapes 3. These fences are basically the same shape but different sizes, so you define a fence
module to construct them 4. You also include a ring
module to make it easier to create various fencing rings 5. This definition of a ring
module is transferred from a previous Design Time activity (see Chapter 5). Reusing modules from prior projects can save a lot of time and effort.
To simplify the project’s organization, you include the fence
, ring
, and archway
modules only in the top.scad file since no other section contains those shapes. As with previous design iterations, save your updates to top.scad; then preview the design to see those changes in other files.
The top_section
module now produces a more detailed version of the top of the tower (Figure 7-13).
Comparing this design iteration with the tower’s reference photo (Figure 7-1), your evaluation suggests that the bottom section now needs the most attention.
This update modifies the bottom.scad file to include the major missing features (columns and arches):
// bottom.scad v5
1 use <column.scad>
module bottom_section(width, height) {
radius = 0.5 * width;
inner_radius = 0.9 * radius;
lip_radius = 1.05 * radius;
lip_height = 0.05 * height;
overhang_height = 0.2 * height;
num_cols = 14;
angle_size = 360 / num_cols;
col_height = height - overhang_height;
col_width = 0.1 * col_height;
// lip
translate([0, 0, height - lip_height])
cylinder(h=lip_height, r=lip_radius);
// inner structure
cylinder(h=height, r=inner_radius);
// columns
2 for (i=[0:1:num_cols-1]) {
angle = i * angle_size;
rotate([0, 0, angle])
translate([radius - 0.5*col_width, 0, 0])
column(col_width, col_height);
}
// arches
translate([0, 0, col_height])
difference( ) {
// overhang
cylinder(h=overhang_height, r=radius);
// arches
3 for (i=[0:1:num_cols-1]) {
angle = i * angle_size + angle_size/2;
rotate([0, 0, angle])
translate([inner_radius, 0, 0])
rotate([0, 90, 0])
cylinder(h=radius-inner_radius, r=col_width);
}
}
}
You first include column.scad in order to access the column
module 1. This allows you to use a for
loop to draw columns around the bottom section’s perimeter 2. Columns in the bottom section are bigger than those in the middle section, so parameters for drawing a column are set accordingly. You add the arches next, also with a for
loop 3.
Save bottom.scad and then preview the design to reveal new details in the tower’s bottom section (Figure 7-14).
The tower is now visually similar to the actual Leaning Tower of Pisa. You can apply the Evaluate stage one more time, but adding more details might not produce much benefit if you intend to make a small 3D print of the model.
At this stage, the tower looks very similar to the Leaning Tower of Pisa. Making a slight modification to $fn
in tower.scad increases the design’s smoothness, providing an even closer likeness (Figure 7-15).
You left the smallest details for last, which is a deliberate feature of the walking skeleton approach to project development. Every design iteration focuses on one major area, specifically chosen to provide the most noticeable improvement to the overall tower design. As mentioned previously, because you plan to 3D-print this model, you omit especially small details, but could have included the following:
We mention these missing features as potential exercises for readers who want to continue doing design iterations of this model. Larger 3D prints potentially could reveal those smaller design features.
For your first design iteration, you split the building into three low-fidelity sections, each having a separate .scad file. This way, all you needed to do was preview only one file (tower.scad), because that file connected together the three other files. Figure 7-16 shows the initial project’s organization, which reduced the amount of code in any one file, making it easier to find and modify specific parts.
Throughout the design process, you used decomposition to find opportunities to break larger components of the tower into smaller pieces. After your last iteration, the project organization evolved to contain many modules and an additional file (Figure 7-17). This final project organization illustrates the main principle of the walking skeleton approach to development. Your initial project organization focused on connecting big pieces of the project, while your final organization reveals all of the smaller details you added incrementally during each iteration.
The organization and development process described here is only one way to build this project. Aside from organizing the project into a different collection of separate .scad files (or even one massive .scad file), you could have created a different set of modules to decompose the tower into smaller building blocks.
We also missed several opportunities to reduce the need for repeating code by including additional if
statements or for
loops. For instance, you could have created a separate column_ring
module to “factor out” the inclusion of columns and arches around the tower’s circumference. With careful use of if
statements and parameters, you could have used the column_ring
module to draw both the columns and arches in all three sections, greatly simplifying the code required in the top_section
, middle_section
, and bottom_section
modules.
A design can evolve over time without major changes to the overall project’s organization. You don’t need to know all the modules or files you’ll need to create at the beginning of a project; you can make those decisions as you gain a better understanding of what you’re building. Each time you apply the Evaluate stage of the design cycle, you have an opportunity to reconsider which changes to make to your design.
This chapter introduced the benefits of deliberately following the design cycle when building a complex project. You applied computational thinking to guide the planning phase and a walking skeleton approach to combine the Build and Evaluate stages into a looping procedure. You connected the design’s most important features first and then incrementally developed each component’s major features. Only during the final stages of development did you consider the smaller, more nuanced details.
To recap, keep these concepts in mind when designing a complex project:
The design cycle and walking skeleton development model are common approaches, and you can find abundant material online for further reading. We encourage you to explore these concepts further as you create new designs with OpenSCAD.
3.90.35.86