Project 2
Due Wednesday Friday, Feb. 25 27, 9pm -- No late assignments
will be accepted.
Introduction
This project is a chance for your inner artist to shine! One of the really exciting applications of computers today is in computer generated graphics. There are many interesting and useful applications for computer imaging ranging all the way from entertainment to medicine, science, and space exploration.
In this project you'll write several classes that use the uwcse.graphics package to create and display several images.
Project Requirements
1. The goal of this project is for you to write several new classes that create and manage lists of shapes (Lines, Ovals, Rectangles, etc) from the graphics library. Each class defines the particular shapes and their sizes and locations in order to draw a specific scene of your own design. For your inspiration and viewing pleasure, the images from a similar CSE 142 assignment last quarter are available at:
www.cs.washington.edu/education/courses/142/03au/pictures/hw3fame/fame.html
2. Every class that creates a scene must provide certain methods so that the scene can be managed and displayed. The required methods are identified in interface PatternElement. Download the zip file (proj2-skeleton.zip) containing the PatterElement.java file that defines the interface and unzip it. Read the PatternElement interface specification to make sure you understand what the methods should do. You need to create your new java source files in the same folder as PatternElement.java (or move PatternElement.java to the folder where you want to work).
3. You are to write the class Artist that has only a main(String[] arg) method. This is the place where the program starts running. This method creates at least three windows (using the uwcse.graphics.GWindow class) and adds one or more PatternElements to each window. An example of how a portion of this code could look is:
GWindow gwB = new GWindow("A Framed View Outside");
gwB.setExitOnClose();
PatternElement scene = new NatureScene(100,100);
scene.addTo(gwB);
PatternElement border = new Border(scene,10,10);
border.addTo(gwB);
4. You are to write four different classes, each of which "implements PatternElement". The first three classes are used to draw scenes in a window, as described below. The fourth is a Border class that is used to draw a border around a scene. At least one of your windows must include a Border.
a. BlobWorld. A scene consisting only of Ovals. Remember that you can set the location, size, proportions, and color of these Ovals when you create them. Use your imagination to create a scene in the window. This scene must include at least one group of Ovals that were created in a loop in your code. Looping is a very common technique for generating shapes that are similar to each other but vary in some easily calculated way each pass through the loop.
b. NatureScene. A scene from nature (a landscape or other outdoor scene). Use a wider variety of shapes in this scene. The library provides Arc, Line, Oval, Polygon, Rectangle, Triangle, TextShape, and ImageShape. You must use at least five of these shapes at least once in your NatureScene. Again, looping is an efficient way to generate recurring patterns of shapes in your scene.
c. FreeScene. A scene with anything you like in it. This can be abstract, a more elaborate landscape, or anything else. Make it interesting! What does "interesting" mean? Here's an interestingness test: show the picture you create to some people not in CSE142. Ask them if they would call it interesting. Then show it to someone in the class (ideally, someone who is not already your friend). See if they judge it interesting. If all those people think it is interesting, chances are your TA will, too!
d. Border. Like the previous three classes, this class also implements PatternElement, but it is a little different because the Border constructor must take one PatternElement object and then build a new PatternElement that fits around it. You should use the getBoundingBox() method of the input PatternElement to find out how big the input image is, then create and manage a list of one or more Shapes to provide a frame around the original pattern.
5. The basic design of each of the above classes is the same.
In each class, the constructor must use the new operator to create graphics objects and then store the objects in an ArrayList. The constructor must not display the graphics objects, that is done in the addTo() method.
The specific parameter list of each constructor is up to you, except that the Border constructor must take one parameter that is a reference to a PatternElement, in addition to anything else you want to give it.
The two constructors in the simple sample code quoted above in step 3 are examples, not requirements.
For example, the sample NatureScene constructor takes two integer values to specify the (x,y) location of the upper left corner of the scene. This lets the caller place that scene at different places in the window, and perhaps repeat it several times in the same window.
Also for example, in the same sample code the Border constructor takes three arguments: the PatternElement to be framed, and two values to define the gap between the bounding box of the scene and the inner edge of the frame. Your Border constructor should also take a PatternElement as an argument, but the rest of the parameters and how you use them are up to you.
The various methods in the class must manage and display the objects in the list. Generally, some sort of loop is used to look at all the objects in the list and do something with them or to them. When you get an object from the list, you can cast it to type Shape, since all of the various graphical classes implement this interface. The addTo(GWindow gw) method is the one that actually adds the Shapes in the ArrayList to the window and thus makes them visible. Read the PatternElement interface specification for more detail.
6. Each class that you write must include a toString() method that describes the contents of the PatternElement (include at least the class name, the number of Shapes, and the bounding box). Use System.out.println() in your main() method to print out a description of the content of your windows using the toString() method of each PatternElement shown in the window.
7. Once you have all your code running, select the image that you think is the "best" and make a copy of it and store it to disk for electronic turnin along with your code.
In order to turn in an image file, you need to copy it from the display and save it to disk. Here is one way to do that for Windows. If it doesn't work, or you are not using Windows, ask for advice on the Message Board. First, get the window you want to capture fully visible on the screen and make sure it is the active window. Locate the button on your keyboard marked Print Screen. Press ALT and hold it down, then press PrintScreen. This action may seem to do nothing, but actually it places a copy of the window on the clipboard. Next, open a program that knows how to process image files. There are many of these, including Paint, IrfanView (use Google to find the download site), Photoshop, and others. Paste (from the clipboard) into the program. You should see your screen image. Save it to disk as an image file (bmp, gif, png).
8. When you are all done, turn in Artist.java, BlobWorld.java, NatureScene.java, FreeScene.java, Border.java, and your image file. A link to the turnin page will be provided here.
Additional Notes on the Design of these Classes
Having the Shapes stored in a list means that we can work with the collection of Shapes as a logical unit. We have implemented getBoundingBox() as one example of this kind of capability, but there are many other reasons why graphical elements are often stored this way. Some enhancements that could be implemented with this design include the following:
a. Perform calculations on the list of Shapes similar the getBoundingBox() method. For example, methods to find the center of the bounding box, calculate the opaque area vs bounding box area percentage, find a bounding circle instead of a bounding box, and so on might be useful in some applications.
b. Change some aspect of all the Shapes in the PatternElement as a group. For example, we might have a function brighter() that would go through and make the Color of each Shape in the PatternElement brighter. Similarly, we could change the Shapes from filled to outline, move them in a coordinated fashion, make them all darker or resize them, perhaps in response to user inputs of some sort. Some of these capabilities could be implemented by just using a method in the Shape interface, others would require creating a new list of Shape objects based on the old list but modified appropriately, removing the old Shapes from the window, and then adding the new list to the window.
c. Perform dynamic calculations to assist in implementing a user interface. Methods like boolean intersects(Shape) that would check to see if the given Shape intersects any of the Shapes in the PatternElement, setEnabled(boolean) to enable/disable response to user actions, etc, might be useful in interactive applications.
Note that NONE of these capabilities (a, b, c) are required features, they are only here to show you the kind of capabilities that classes like this often have.
What to turn in
Use this turnin form to turnin the files that make up your project and
the picture file you produced. Do not turn in the PatternElement.java
file. Your code will be compiled along with the original PatternElement.java
file that was distributed with the starter code.
|