Comp 360 Lab 2 : Affine Graphics
Due Monday, 28 September 2009, 11:59 PM
Overview
In this project you will implement the CODO (COnnect the DOts) language for affine graphics. Using this language, you will render simple and complex two dimensional shapes. You will also generate fractals using iterated function systems.
This project is due at 11:59 PM on Monday, September 28. It is worth 100 points.
For this lab, you must work with a different partner than the one you worked with in lab 1. As soon as possible, send an email with your partner's name and username to powei.feng@rice.edu. If you have trouble finding a partner, let us know and we will try to pair you up.
Specification
The user interface for this program is similar to the interface in your turtle program. The program will parse and execute commands entered by the user at the command line. In addition, the program will respond to certain keys, as indicated below.
The first portion of the lab involves implementing the basic constructors of the CODO shapes. Higher-level constructors should be implemented in terms of simple constructors. For example, a polygon is created by applying rotation to an initial point. You will get no credit for turning in a turtle-based implementation of any command.
The global coordinate system is set up so that the origin lies in the center of the program window, the x-axis increases horizontally to the right, and the y-axis increases upward.
Your program accepts one optional command-line argument, a string specifying the name of a file. The file will be executed as a script (see the section "Script Files," below). Under Windows, opening your program by dragging a file onto the program's icon will pass the name of the file as an argument to your main() routine.
The CODO Language
CODO Data Types
There are four types of objects (or data types) that are specified in CODO:
- Points
- Vectors
- Lines
- Transformations
Most of the commands listed below involve creating, manipulating, naming, and drawing these data types. Any object of any data type can have a name. Points and lines can be drawn on the screen, but vectors and transformations cannot.
The CODO Namespace
There is a single CODO namespace shared by all data types. Each name the user defines is associated with a unique object. Once defined, a named object cannot be modified or removed from the namespace, except through the clearNames command. In particular, if a name exists in the namespace, a new object may not be associated with this name (until the namespace is cleared).
Names are not case-sensitive, so point1 is the same name as Point1. You will not be required to implment the CODO namespace functionality.
CODO Constants
Two constants are defined in CODO. These names cannot be modified or removed from the CODO namespace.
C: The point representing the origin of the global coordinate system, with affine coordinates C = (0,0,1).
W: The unit vector pointing along the x-axis of the global coordinate system, with affine coordinates W = (1,0,0).
CODO Command Syntax
The commands that your program must respond to are similar in format to the turtle commands of lab 1. As in lab 1, command tokens are separated by one or more blank spaces.
There are two kinds of CODO commands: utility functions and constructor functions. Utility functions do not return data; instead, they cause some kind of change to the program's state, such as drawing new geometry. Constructor functions create a new CODO object. (Note that constructor functions are used exclusively as arguments to utility functions or other constructor functions.) You are not required to implement the utility functions.
All numeric arguments passed to commands should be treated as doubles, except for parameters that must be integers (such as the number of edges or the fractal level). Arguments that are CODO data types, such as points, may be given either as names from the CODO namespace or as constructor functions.
CODO Utilities
If you do not use the framework, you will need to write the code to support these functions. If you are using the framework, remember whitespace separates all tokens.
Basic CODO Commands and Utilities
- clearScreen ( )
Remove all geometry currently being drawn on the screen. The namespace is unaffected.
- clearNames ( )
Remove all named objects from the CODO namespace, except the CODO constants C, W given above. The screen is unaffected.
- reset ( )
Clear both the screen and the CODO namespace; equivalent to clearScreen followed by clearNames.
- print ( name )
Print information about the given name to the console. Minimally, this command should state whether name exists in the CODO namespace, and report what kind of data type the name represents (point, vector, etc.).
- printAll ( )
Print information about every item in the CODO namespace to the console. Equivalent to calling "print ( name )" on every named object.
- set ( name constructor )
Associate the object given by constructor with the given name. (In a programming language like C, this would be written name = constructor.) The constructor argument must be a constructor function. If name already exists in the CODO namespace, or if name matches an existing function name, the command should be ignored and an error posted on the console.
- load ( file )
Load and execute the named file as a script (see the script section, below).
Drawing commands
- lineWidth ( w )
This command causes any lines or points drawn after its execution to have width w, where w is given in number of pixels. Note that w is a double-precision value.
- color ( r g b )
This command causes any lines or points drawn after its execution to have the color given by the (red, green, blue) triple (r, g, b), where each element is a double between 0 and 1.
- draw ( object )
Draw the geometry specified by object. The object can be either a name in the CODO namespace, or a constructor function. If object evaluates to a vector or a transformation, nothing is drawn and an error is posted to the program console. (Note: Draw will have special functionality for fractals. This functionality will be described later).
Constructor Functions (100 Points Total)
Geometry Fundamentals (5 Points)
- vector ( P Q )
Construct the vector (Q-P) from points P and Q.
- line ( P Q )
Construct the line object that connects points P and Q.
- transform ( X M )
Construct the object created by transforming the object X by the transformation M. X may be either a vector, a point, or a set of lines. The newly constructed object will have the same data type as X.
Affine Transformations (15 Points)
- translate ( V )
Construct the transformation that translates points by the vector V.
- rotate ( Q d )
Construct the transformation that rotates points or vectors counterclockwise around the point Q by d degrees.
- scale ( Q s )
Construct the transformation that scales distance by a factor of s about the point Q.
- Nscale ( Q V s )
Construct the transformation that scales distance from the point Q in the direction of the vector V by the factor s.
- image ( A B C P Q R )
Construct the affine transformation that maps the points A, B, and C onto the points P, Q, R.
- compose ( T1 T2 ... Tk )
Construct a new transformation by composing the transformations T1 through Tk. The resulting transformation should be equivalent to transforming first by T1, then by T2, and so on through Tk. This function must be given at least two arguments.
Simple Shapes (15 Points)
- polygon ( P Q n )
Construct a regular polygon of n sides, centered at point P, with point Q as a vertex.
- circle ( P r )
Construct a circle centered at point P with radius r.
- ellipse ( P V a b )
Construct an ellipse centered at point P, with semi-major axis direction V, semi-major axis length a, and semi-minor axis length b.
- wheel ( P Q n )
Construct a wheel. The arguments are identical to those of the polygon command.
- rosette (P Q n )
Construct a rosette. The arguments are identical to those of the polygon command.
- spiral ( P Q n s d )
Construct a polygonal spiral with n arms, centered at point P, and with the first vertex at point Q. Each successive arm should be scaled by a factor of s, and the angle between each adjacent spiral arms should be d degrees.
Simple Operators (15 Points)
- shiftOp ( V k object )
Construct k copies of object, where each successive copy is translated by the vector V. The object, which may be either a named object or a constructor function, must represent a set of points or lines. If object is of some other data type, an error should be reported to the console.
- spinOp ( P d k object )
Construct k copies of object, where each successive copy is rotated by d degrees around the point P. As in shiftOp, the object must represent a set of points or lines, or an error should be generated.
- scaleOp ( P s k object )
Construct k copies of object, where each successive copy is scaled by a factor of s around the point P. As in shiftOp and spinOp, the object must represent a set of points or lines, or an error should be generated.
Fractals (25 Points)
For each fractal command given below, k specifies the level of iteration and basecase is the object used to initiate the iteration. The basecase must be a named set of lines or points or a constructor function for a set of points or lines. Fractal figures should be centered on the origin and scaled to fit within the window.
- gasket ( n s k basecase )
Construct a polygonal gasket with n sides, where each self-similar part is a polygonal gasket scaled by a factor of s.
- squareGasket ( k basecase )
Construct the square gasket as in the diagram below.
- fractalStairs ( k basecase )
Construct the fractal staircase as in the diagram below.

The Square Gasket and the Fractal Staircase.
- fractalHangman ( k basecase )
Construct the fractal hangman as in the diagram below.
- fractalBush ( k basecase )
Construct the fractal bush as in the diagram below.
- fractalTree ( k basecase )
Construct the fractal tree as in the diagram below.
- fractalC ( k basecase )
Construct the fractal C-Curve illustrated in Lecture 2, Figure 1.

The Hangman Fractal, a Fractal Bush, and a Fractal Tree.
Pretty Pictures (25 Points)
Create new constructor functions or script files for interesting and unique geometry of your own. Be creative. You should document how to produce your pictures in your README file.
For full credit, you need to create at least five interesting pictures. At least two of these should be new fractal commands. The others may be new commands or interesting script files.
Notes
Other Requirements
- Drawing Fractals. When drawing fractals there is one extra bit of functionality. When the user presses the '-' or '+' keys, the fractals should either decrease or increase their level of rendering. This functionality does not apply to their base cases (so if a child fractal is the base case to a parent fractal then the child will not be affected by this functionality). If you are using the framework, then this functionality is handled by the incr and decr methods for fractals which you will need to implement.
The keystrokes `-' and `+' can only modify the geometry visible on the screen. Objects in the namespace are not affected. As an example, consider the following set of commands.
- set ( myVec transform ( W compose ( scale ( C 50 ) rotate ( C 90 ) ) ) )
- set ( myPoint transform ( C translate ( myVec ) ) )
- set( myTri polygon ( C myPoint 3 ) )
- set ( mySierp gasket ( 3 .5 2 myTri ) )
- draw ( mySierp )
These commands draw the 2nd-level Sierpinski gasket. If the user then presses the `+' key, the screen will change to display the equivalent 3rd-level gasket. However, the named object mySierp will still correspond to a 2nd-level gasket.
Note that the user should not be able to decrease the fractal level below 0, regardless of how many times she hits the `-' key.
- Your program should exit any time the user presses the escape key.
- You should not use any OpenGL commands other than the ones you used in lab 1. OpenGL provides the ability to set up and apply transformation matrices, but you should not use OpenGL for this purpose within this lab. You will need to create your own facilities for composing and applying affine transformations.
- There are no commands to define points and vectors by specifying their coordinates. You should not extend the command set to allow such definitions. All points and vectors must be derived from the CODO constants by applying transformations. (This is an absolute condition for commands and script files.)
- There are blank class definitions for Polygons, Rosettes, Transformations, etc. It is your responsibility to fill in the definitions of these classes. The Point, Vector, and Line classes have been partially populated for you to give you some hints as to how to proceed with your implementation. Each class has a draw method that is used to render the object defined by the class. All rendering code should be placed in this function for an object type. Assume that this method is only called from the context of the rendering callback function. Each class also has Print and Copy methods for which you will have to provide the code.
- Please implement any linear algebra you might use ON YOUR OWN. Linear algebra is one of the main things you should learn from this lab. Of course, we cannot stop you from looking at existing code out on the web, but please do not directly copy other people's code, and please document your sources if you do use concepts from other people's code. I recommend using sites like wikipedia and mathworld to implement your own routines.
- Fractals should be invariant of their base cases. So when building your fractal, you can build your fractal using some fixed size and not have to worry about finding the size of the base case. Make sure you document what those sizes are, so I can test your program.
Hints
- If your program is not drawing, it could be because your object is black.
- For some objects like Polygon, you could store the object as a collection of lines. In the Polygon's draw function, call the draw function of the lines. Note that, you will need to override the setColor function to set the color of the lines.
Script Files
The commands given above to draw a basic Sierpinski gasket probably look tedious. Nobody wants to spend a lot of time defining points and vectors, but CODO only provides one point (C) and one vector (W), from which all other points and vectors must be derived. One solution is to collect a series of commonly used definitions into a script file.
There are two ways to load a script file: as a command-line argument, and through the load command. The general rule that command tokens are separated by one or more blank spaces extends to the script file format. The Sierpinski gasket example given above might look as follows in a script file:
set ( myVec transform ( W compose ( scale ( C 50 ) rotate ( C 90 ) ) ) )
set ( myPoint transform ( C translate ( myVec ) ) )
set ( myTri polygon ( C myPoint 3 ) )
set ( mySierp gasket ( 3 .5 2 myTri ) )
draw ( mySierp )
If you are using the framework, there should be one command per line and the entire command should be contained in that line. Additionally, the ability to comment out lines has been provided - any line that starts with the character '#' will be ignored.
What To Turn In
Create the directory lab2. This directory should contain your source code and all files needed to build your program in Visual Studio (or a CMakeList.txt file). Also include a README file containing:
- The names of you and your partner.
- A brief overview of how your code is organized.
- Instructions for creating your additional fractals and shapes.
- Any known bugs or incomplete features.
- Any other implementation details you think your grader should know.
Only one partner per group should turn in code.
If your project will be completed late, email your labby and let him know.
Please follow the instruction on the COMP 360 home page to submit your lab.
File translated from
TEX
by
TTH,
version 3.85.
On 15 Sep 2009, 10:10.