In the final task of CS151, students were asked to use the TurtleTk3D package to create lsystems and shapes in 3d space. Using visual thinking and our vast repertoire of pythonic knowledge, students are asked to make visually appealing and complex 3d objects.
The first task of this project was to write code for 4 basic shapes by creating new Shape classes. In the Shapes.py file, I added classes for a Cube, a Diamond, a Rhombus, and a Wedge that inherit from the Shape class.
The structure of these classes isn’t very different from the classes for the 2d shapes-- there is only one method (_init), which takes in the distance and the color f the lines, and then calls the __init_ method of the Shape class with these parameters, the default angle size, and the string to be drawn. The string is where these classes are really any different. By using the new characters ^, &, ?, and \, the turtle moves into 3d space. Here is an image of the code for my Cube class.
Here is an image of my four shapes in one image, rotated at several different angles.
To draw the shapes, I store each object in a variable, and then use its draw method. To change the styles, I simply call the setStyle method of each class before drawing it.
TWO and THREE
Step two of the project asked us to incorporate the new concept of recursion into some aspect of our project. I decided to put it into my scene. When trying to imagine a scene that could be built with Wedges, Diamonds, Rhombuses, and Cubes, I began fiddling with recursion. I Wrote code for a function that creates a Wedge object at orientation <z> (a parameter), draws the shape, and then calls itself again but with a slightly larger orientation. The effect of this is awesome, and draws the Wedge in a fractal sort of pattern. Here is my abstract interpretation of a cake (with the cube being the platter.
As evident, I applied this recursive effect to the Diamonds and Rhombuses as well. Here is the code:
This fulfills the making of an abstract scene (Task 1) and the use of recursion (Task 2).
For this task, students were asked to tackle a significant extension. Therefore, I decided to implement user input into my project. It felt necessary at the close of CompSci, and the result is very cool.
In order to let the user input a string in the terminal and see it drawn immediately, I had to create a new class in <shapes.py>. Unlike the other classes descended from Shape, this class is not a child class. This is because inheritance will not update with each new string the user inputs-- it waits until the user exits the program to draw anything at all.
In this class, the _init_ method takes in a distance and a color, and then calls the <loop> method. <loop> begins by creating an infinite While Loop, and assigning the value of <string> to a raw_input. Thus, when the program begins, the string “Please enter a string\n” appears in terminal, and whatever the user types is assigned to the variable string. Next, two If Statements are created. The first checks if the string is ‘exit’ or ‘Exit’. If it is, the loop breaks, and uses the exit() function to stop the program.
The next If statement corrects for the case where the user does not input a string. If the string is empty, a square is drawn. After this If Statement, a Shape object is stored in the variable <new_shape>, and then its draw method is called with the <string> variable as the shape to be drawn. All of this occurs in the While Loop, so that after each raw input, the string is drawn and the user is prompted again. Here is the code:
Attached is a video of the interactive program running.
The First extension I completed was to make an additional scene. I really enjoyed the recursive effect of rotating my shapes around each other, but I wanted to make something even more abstract. To accomplish this, I randomized the shape drawn after each change in orientation.
I began the function with an If statement to exit recursion after a certain point, and then stored Wedge, Diamond, and Rhombus objects in variables. Then, I created a list <shapeList> with each of these shapes in it. I then uses the random package to select one of these shapes at random. The effect is cool and very abstract. Here are the pictures.
Here is the code:
The second extension I did was to write simple code for complex shapes. I hade the idea to make a cylinder earlier in the project, but found that the circle function of the TurtleTk3D package was “expensive”-- it takes up a lot of data and crashes the window after a little bit of rotating the shape. Therefore, I thought about the shape, and reasoned that I could draw it with a lot of squares rotated about one side. In a function in my <shape_examples.py> file, I defined a variable with a Square object, and then use recursion within an If statement to draw the squares multiple times.
The function also takes the parameters <grain> and <z>. <z> is plugged in in the orientation of the call to the <draw> method, and grain is used in the recursive call. By calling the function recursively and changing z by adding grain to it, the user can select how accurate to make the cylinder. A <grain> value of 1 makes a near perfect cylinder, higher makes the squares more noticeable. Here is the code:
And here are some variations of it:
The second shape I did was a helix, also constructed with squares. The format of the function is the same as the others (create object, setStyle, etc.), but when it is drawn recursively, the zposition AND the orientation are controlled by the variable <z>. In the recursive call, I add the parameter <step> to the z parameter, thus letting the user control the distance between each branch of the helix.
Here is the code:
And here are some pictures:
WHAT I LEARNED:
In this project, I learned more about the raw_input command and the implementation of classes and methods-- making the interactive was no small feat, and required that I understand these two concepts thoroughly.
WHO I WORKED WITH:
For this project I received help from Prashant, the Monday night TA’s, and Roger (my lab TA).