Placed Online: Friday, October 12
Due: Thursday, October 25, no later than 11 pm
Points: 100, about 10% of the final grade
Program Files: RandomArt.java
Pair Assignment. You may work with one other person on this assignment using the pair programming technique. Review this paper on pair programming. You are not required to work in a pair on the assignment. (You may complete it by yourself if you wish.) If you begin working with one partner and do not wish to finish the assignment with that partner you must complete the assignment individually. If you work with a partner, the intent is that you work together, at the same computer. One person "drives" (does the typing and explains what they are doing) and the other person "navigates" (watches and asks questions when something is unclear). You should not partition the work, work on your own, and then put things together.
You and your partner may not acquire from any source (e.g. another student or an internet site) a partial or complete solution to a problem or project that has been assigned. You and your partner may not show other students your solution to an assignment. You may not have another person (current student other than your partner, former student, tutor, friend, anyone) “walk you through” how to solve an assignment. You may get help from the instructional staff and use code from class.
If you are working with a partner turn in one version of the assignment to one partner's turnin account. If you work with a partner, both student's in a pair will get the same grade on the assignment.
The purpose of the first assignment is to practice using Color objects and creating buttons and menu options to control the behavior of a GUI.
This assignment is based on the Random Art Nifty Assignment created by Christopher Stone which in turn was inspired by Andrej Bauer's Random Art project.
The images below were generated using a random algorithm.
The assignment uses the same framework we have used in class and on assignment 2 and 3. I am providing providing 1 file RandomArt.java that has 4 classes in it: RandomArt.java with the main method, ArtFrame, ArtPanel and RandomExpression.java. The RandomArt class is complete. The ArtFrame and ArtPanel classes are partially completed. The RandomExpression class works as is, but you will make an addition to the class as the last part of the assignment.
When you complete steps 1 - 6 below completed and run your program a GUI with the following should appear:
The frame contains a panel with the display of random art based on the postfix equation xxACSSxCAyCyxASASCAyCCAyyyAAxMSxCxCAxSySMMCMCSMSCS. The operators are C = cosine, S = sine, M = multipy, A = average.
The program works by generating a random mathematical expression and feeding the coordinates of every pixel to the random expression and then converting the result to a color for that pixel.
The random expression consists of the mathematical functions sin, cos, average, and multiply.
The inputs to the functions are x and y.
x and y are always between -1.0 and 1.0, inclusive.
x and y represent the coordinates of a pixel in the panel scaled from -1.0 to 1.0. So for example if we had a panel that was 200 pixels wide by 400 pixels tall, the upper left corner pixel with coordinates (0,0) would be scaled to (-1.0, -1.0). This assumes we have not translated or scaled the graphics objects. The pixel at the lower right corner would have coordinates(199, 399) and this would scale to (1.0, 1.0). Pixels in between are scaled based on the size of the panel.
For a given pixel the random function returns a value that is also between -1.0 and 1.0. This value is then scaled to a grayscale value. -1.0 is black, Color (0,0,0) and 1.0 is white, Color(255, 255, 255). The graphics object is set to that color and a rectangle of size 1 is filled at the coordinates for that pixel. (You may find using fillRect instead of fill on a Rectangle object improves the speed of your program.)
To create a color image the same equation an be used with different parameters or 3 random equations can be used, one for each color channel. (red, green, blue)
The shell I have given you creates the frame, the art panel, the menu bar, the equation field, and the button panel. Initially the art panel just fills the panel with a green rectangle. The buttons and menu options don't do anything at this point.
What to do for the assignment:
The default constructor of the ArtPanel class creates a RandomExpression
based on a hard coded expression. That expression should result in the image
shown above. (The image with the GUI that has the "New Gray" and
"New Color" buttons). Redo the paintComponent method in the
RandomPanel class to scale the pixel coordinates of all pixels in the panel to
values between -1.0 and +1.0.
The scaled coordinates are sent to the getResult(double
x, double y) method in
the RandomExpression class. There is an instance variable in RandomPanel named
randExp. randExpression is the current RandomExpression. So the method call will be of the
form:
double value = randExp.getResult(x, y);
The value from getResult must then be scaled from 0 to 255. (getResult will return a value between -1.0 and 1.0 inclusive.)
Use the scaled value between 0 and 255 to create a new Color object
with red, green, and blue all set to that value. The graphics object will be set
to that new color and a rectangle of size 1 will be filled at the original
location. (You should try and optimize this. In the ArtPanel class create
another instance variable, an array of size 256 with all the grayscale color
objects pre-computed.)
If the frame is resized then the image must expand and be redrawn
correctly.
To accomplish all of the above you should add helper methods to
make the paintComponent method understandable. You can also add instance
variables and class constants as necessary.
Once you have the hard coded grayscale expression working
make the buttons work. When the "New Gray" button is pressed the instance
variable exp will be set to a new RandomExpression. This can be accomplished by
calling the RandomExpression default constructor.
randExpression = new RandomExpression();
Note, the randExpression variable is the ArtPanel class and the button is in the
ArtFrame class, so the action listener you create will have to call a method (that
you write) in ArtPanel to assign randExpression to a new RandomExpression to
randExpression or to make
the ArtPanel choose a new RandomExpression. You will also
have to call the repaint method on the panel in the ActionPerformed method you
write.
You can complete steps 8 and 9 in any order you want.
Once you have the "New Gray" working go on to make the "New
Color" button work. When the "New Color" button is pressed a new color image is
generated. Eventually you must implement two ways of generating a color
expression and allow this to be changed by selection the menu options. (More
action listeners just like the buttons!) You can use one random expression and mix parameters or have three
random expressions, one for red, one for green, and one for blue. Or you could
just take the return value from the getResult method and scale it to the number
of colors you want. You can only have one paintComponent method in the
RandomPanel class so it will have to decide (based on a boolean instance
variable perhaps?)
whether it is drawing a grayscale image or a color image.
Add your own operator to the RandomExpression
class. Currently the RandomExpression is
pretty gacky (bad) and should be refactored into a more object oriented
solution, but that is work for me at a later date. Anyway, this is how you add a
new operator:
Determine or define a mathematical operation that has either one or two inputs
(operands).
Inputs must always be between -1.0 and 1.0, inclusive. The mathematical
operation must result in a value that is also between -1.0 and 1.0, inclusive.
So for example, a simple square root won't work because square root of -0.09 is not
between -1.0 and 1.0. (It is equal to 0 + 0.3i, an imaginary number.) But you
could modify square root to handle negative numbers right?
After you have
defined your function go to the OPERATORS constant in the RandomExpression class.
Pick an upper case character for you operation other than S, C, A, or M. If your
operation has one input (operand) like sin or cos you must also add it to the
SINGLE_OPERAND_OPERATORS String in RandomExpression. Part of your grade will be
how interesting the images that include your new operator are.
Now go to the getResult(double x, double y) method in the RandomExpression class and add an else if branch for the character for your operation. The body of the if statement must carry out your operation. You may have to add a method like the average method to carry out the operation.
By way of comparison my solution is 475 lines long including comments and white space. I added a number of instance variables and constants to ArtPanel. I added two methods to ArtFrame and 8 methods to ArtPanel. (Although my solution has 3 ways of generating a color image instead of the required 2.)
When you complete the assignment fill in the header information at the top (Eclipse sometimes collapses this comment, so be sure to expand it.) and turn in your RandomArt.java file which will include all your source code, using the turnin program. This page contains instructions for using turnin. Be sure you upload the file to your CS324e folder. If you are working with a partner turn the file in to only one of your accounts and ensure both names are in the comment at the top.
Going the Extra Mile (No bonus points, but things you might do to the program):
The random formulas are expressed in
postfix notation.
I did this because it is a lot easier to write the evaluation method given a
postfix expression, rather than an infix expressions. The next step would be to
display the expressions as fully parenthesized infix expressions. (or at least
have the option to do so.)
You can create more or less complex RandomExpressions. In the
assignment you are calling the default constructor for new expressions. When
expressions are generated the number of levels deep and expression can go is
based on the EXPRESSION_COMPLEXITY constant. The default value is 10. Smaller
values result in less complex expressions while larger values will have more
complex expressions, but will take longer to evaluate. In order to add more
randomness there is a probability a given operand will be another expression
(assuming we aren't past EXPRESSION_COMPELXITY levels deep) or it may just be a
simple operand like x or y. The default value for this is 0.8 meaning 8 times
out of 10 we make an operand a more complex expression and 2 times out of ten
we make it a simple operand like x or y. That is why sometimes the RandomExpression isn't
complex at all. By increasing this value towards 1 you
are less likely to get simple expressions. (Although I have found some simple
expressions still produce interesting results.) There is a constructor in
RandomExpression that allows you to send in the values to use for
EXPRESSION_COMPLEXITY and PROBABILITY_DEEPER. Try experimenting with different
values. You may get better results on the colored art the expressions are all
the same depth (or very close).
You can also alter the probability a particular operation is
chosen. Every character in the OPERATORS string in RandomExpression has an equal
chance of being chosen. If you want to increase the chance sin being chosen add
more S's to OPERATORS.
Sometimes this leads to more interesting results. (Multiply tends
to make things pretty plain and gray.) I have gotten much more interesting results with
OPERANDS = "SSSSCCCCAM"; which lead to things like this:
which is yxASCSySSxCyCACMMSCSSCC.
Alter the alpha of colors as well as the Red, Green and Blue values: