CS324e - Assignment 4

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 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:

  1. 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.
     

  2. 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);
     

  3. The value from getResult must then be scaled from 0 to 255. (getResult will return a value between -1.0 and 1.0 inclusive.)
     

  4. 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.)
     

  5. If the frame is resized then the image must expand and be redrawn correctly.
     

  6. 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.
     

  7. 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.
     

  8. 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.
     

  9. 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.
     

  10. 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):

  1. 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.)
     

  2. 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). 
     

  3. 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.

  1. Alter the alpha of colors as well as the Red, Green and Blue values: