# Introduction to 3D Modeling. Section 5. Primer in Python Programming

### 5 Primer in Python Programming

In order to take full advantage of PLaSM, one should learn more about the Python programming language. This primer will give you a useful basic information. If you are interested in computer programming, NCLab provides a comprehensive course that includes a textbook, interactive exercises, review questions, and solution manual.

#### 5.1 Defining and using variables

We learned before that it is a good habit to make our designs parametric. This allows us to adjust them easily any time. Designs that use parameters (variables) rather than raw numbers also tend to be more elegant and less prone to mistakes.

To illustrate this, let us create a 3D model of a pill that is formed by a cylinder with radius 3.0 mm and height 10.0 mm, that ends at both sides with a spherical cap. Moreover the pill has two colors – one half is red and one half blue. Of course this can be done as follows:

c1 = CYL(3.0, 5.0)
c2 = COPY(c1)
MOVE(c2, 0, 0, 5.0)
s1 = SPHERE(3.0)
s2 = COPY(s1)
MOVE(s1, 0, 0, 10.0)
half_1 = UNION(c1, s1)
half_2 = UNION(c2, s2)
COLOR(half_1, RED)
COLOR(half_2, BLUE)
SHOW(half_1, half_2)

This is a "brute force" approach which does not use any parameters. The result shown in Fig. 90 is correct. Fig. 90: 3D model of a pill.

But imagine that we need to change the length of the base cylinder from 10.0 mm to 12.0 mm. We have to make changes on lines 1, 2, and 4 – so there are at least three places where a mistake can easily be made.

The design can be made safer by using variables. Let us define variables r and h on the first two lines, and then use them instead of raw numbers:

r = 3.0
h = 10.0

c1 = CYL(r, h / 2.0)
c2 = COPY(c1)
MOVE(c2, 0, 0, h / 2.0)
s1 = SPHERE(r)
s2 = COPY(s1)
MOVE(s2, 0, 0, h)
half_1 = UNION(c1, s1)
half_2 = UNION(c2, s2)
COLOR(half_1, RED)
COLOR(half_2, BLUE)
SHOW(half_1, half_2)

Not counting the first two lines, this script has the same length as the previous one. But, any change of the pill’s dimensions is now effortless. No need to study the program and make changes at several places - it is enough to change the values of r and h at the beginning of the program.

#### 5.2 The Numpy library

Python comes with powerful computational libraries that we can use for our PLaSM designs. In particular, Numpy (numerical computations library) contains vast functionality related to mathematical functions and numerical computations. Whenever we want to use some constant such as π or e, or when we want to use some mathematical function such as log(x), sin(x) or , we import it from Numpy:

from numpy import pi, e, log, sin, sqrt

We can also import everything using the asterisk symbol ’*’:

from numpy import *

Applications of the Numpy library will be shown in the examples at the end of this section.

#### 5.3 Python lists

Whenever we need to create a set of objects, such as a set of points, we can use a Python list for that. Empty Python list is created using a pair of square brackets:

L = []

Here, L is the name of the list, and any other name would be fine as well, as long as it does not clash with some Python or PLaSM command. We can also create a nonempty list. Say that we need a list that contains the points (0, 0), (1, 0), (0, 1). This can be done as follows:

L = [[0, 0], [1, 0], [0, 1]]

You are right, each point is a list as well! Sometimes we need to fill a list using some procedure because not all its items are known at the beginning. For this, we can use the command append(). For example, the point (2, 4) can be added to the existing list L via

L.append([2, 4])

Python provides a number of useful operations with lists including inserting an item at an arbitrary position, deleting an item from an arbitrary position, reversing and sorting lists, merging lists, counting occurences of some item, etc. These are beyond our primer but you can find them in the NCLab Python textbook.

#### 5.4 Printing

Control prints are a practical way to check that all values are as they should be. Printing is done via the print command. For example, the script

L = [[0, 0], [1, 0], [0, 1]]
print L

has the following output:

[[0, 0], [1, 0], [0, 1]]

Printing the value of a single variable is done in the same way, and we can make the output more informative by actually describing what is printed. The script

h = 5.0
print ~h =~, h

yields the following output:

h = 5.0

#### 5.5 Loops

Let us mention one last scripting technique for now, which is to repeat some command or sequence of commands several times. To repeat something N times, we use the following construct:

for i in range(N):
do_something

The indentation matters as it indicates the body of the loop (set of commands to be repeated). For example, the following script will print a sequence of integers between 0 and 5 (not including 5):

for i in range(5):
print i

Output:

0
1
2
3
4

Once more – notice that the printed sequence ends with 4, not with 5. This is a common source of beginner’s mistakes.

Let us show one more example of how repetition can be used: We will create a list of points (0, 0), (1, 0), (2, 0), ..., (N, 0) where N is some positive integer. Let us write the script initially for N = 5, and at the end we will print it:

N = 5
L = []
for i in range(N+1):
L.append([i, 0])
print ~L =~, L

Output:

L = [[0, 0], [1, 0], [2, 0], [3, 0], [4, 0], [5, 0]]

If we needed to create another list for N = 100, the script would remain the same, just the line where N is defined would be changed to

N = 100

Scripting can save lots of work! Let us practice our scripting skills on some simple examples.

#### 5.6 Example 1 - programming a polygon

First we will generate a polygon with N equally-long edges that is inscribed in a circle with radius R. Notice that the points (R cos(a),R sin(a)) where a is an angle between 0 and 2π, lie on the circle with center (0, 0) and radius R. We begin with importing the sine and cosine fundtions, and the number π from Numpy:

from numpy import sin, cos, pi

Next create a variable R for the radius and N for the number of edges:

N = 15
R = 5

Now the scripting part comes: We create an empty list points, and in a loop append the N points that lie on the circle:

points = []
for i in range(N):
a = i * 2. * pi / N
points.append([R * cos(a), R * sin(a)])
poly = CHULL(points)

Note the asterisk ’*’ in front of the list points on the last line. Its purpose is to "take the square brackets off the list" – decompose the list points into a sequence of its entries as expected by the CHULL command.

Finally, let us view the polygon poly in copper color:

COLOR(poly, COPPER)
SHOW(poly)

The result is displayed in Fig. 91. Fig. 91: Equilateral polygon with 15 edges.

#### 5.7 Example 2 - programming a cone

Next let us tweak the above script to construct a cone with radius R and height H. All we need to do is to add a zero third coordinate to all points and add one more point for the apex. The CHULL command will take care of the rest. Since the script is so similar to the last one, it is not necessary to comment all steps in detail:

from numpy import sin, cos, pi
R = 5
H = 10
subdiv = 128

The only other thing worth mentioning is the parameter subdiv that plays the role of N from the previous script – in fact this is the optional third parameter of the CONE command!

The list of 3D points forming the cone is created as follows:

points = []
for i in range(subdiv):
angle = i * 2. * pi / subdiv
points.append([R * cos(angle), R * sin(angle), 0])
points.append([0, 0, H])
c = CHULL(points)

Finally, let us view the polygon poly in copper color:

COLOR(c, COPPER)
SHOW(c)

The result is displayed in Fig. 92. Fig. 92: Cone whose curved surface is approximated with 128 straight segments.

#### 5.8 Example 3 - programming arrays of objects

In this example, we will create a field of 400 cylindrical poles. Certainly this is something that we would like to do manually. Here is a script that does it for us:

# Define master cylinder and N:
c = CYL(0.1, 1, 16)
N = 20
# Duplicate the cylinder N^2 times:
columns = []
for i in range(N):
for j in range(N):
d = COPY(c)
MOVE(d, i, j, 0)
columns.append(d)
# View the result:
SHOW(columns)

The result for N = 20, which means 400 columns, is shown in Fig. 93. Fig. 93: 400 columns.

More columns? By changing N to 50 and running the script again, we instantly create 2,500 of them: Fig. 94: 2500 columns.