In our earlier assignments, we saw how the depth property of shapes could be used to simulate a layering effect in drawings, such as with the following snowman:
There are several approaches as to how to render such images, given the underlying geometric model. One approach is to carefully analyze the various geometric shapes, so as to determine precisely which portion of a given shape is visible from the desired point of view. Another approach is to consider each pixel of the image, and to determine which object is closest along the ray into the image.
In this assignment, you will implement a very common (and relatively simple) approach to rendering such an image. It is known as the Painter's Algorithm, based on its history in the visual arts. Instead of trying to calculate the intersections of the shapes, the final image can be produced by drawing each individual shape onto the canvas, one at a time, ordered from greatest depth to least depth. In this way, farther objects will be naturally obscured by any nearer objects which overlap. Of course, all of the intermediate drawings can be hidden from the user, who is only shown the resulting image.
For this assignment, you must work individually in regard to the design and implementation of your project. Please make sure you adhere to the policies on academic integrity.
In earlier assignments, we had provided a working version of a Canvas which was based upon use of the painter's algorithm. In this assignment, we take a step backwards an ask that you provide such an implementation yourself. We will be providing you with a template for a class Canvas which is really a subclass of the original, though with the painter's algorithm functionality stripped away.
Specifically, what is missing from this class is a routine to draw the canvas. This routine should be responsible for making sure that all of the contents of the canvas are drawn appropriately, using the painter's algorithm. You will find a template for that method in the provided Canvas class, declared as:
protected void draw(Drawable[] contents, Graphics2D g)The first parameter is an array of all elements currently contained in the canvas (e.g., the individual shapes). The second parameter is the Graphics2D object; you will need this so as to pass it on to the draw(g) command discussed below, for drawing individual elements.
Note Well: For this assignment you are not responsible for creating the model of the snowman; we have already done that behind the scenes. The array contents, which is being passed to you, already contains all of the individual shapes which are used in the image. Your job is to composite those contents into the final image.
You will notice that the contents of the canvas, that is the array of objects, is specified as an array of type Drawable. All objects on a canvas were required to support some mimimal common behaviors, described by the Drawable interface, as described in the csa120.shape documentation. These behaviors provided precisely the minimal interaction needed by the Canvas in order to assemble the desired image.
public int getDepth()
this allows you to query an object for its depth value.
public void draw(Graphics2D g)
This instructs the object to draw itself on the given Graphics2D
object
(don't worry too much about what such a graphics object
is; it is a Java class which is an underlying part of our canvases).
Your task is to implement the draw routine for the class Canvas, proceeding as follows:
The contents of the given array should be rearranged so that they are sorted according to the depth values. In particular, you are required to implement Selection Sort, as described in Chapter 8.6.3.
A loop can then be used to invoke the draw method for each individual object, proceeding from greatest to least depth.
Keep in mind that you can develop pieces of your software in an order different from the eventual execution. In particular, the sorting algorithm (step 1 above) is the most complicated part of the assignment.
We suggest the following approach for making progress:
Define a new method
Though this method will not be used in your final solution, it is a good first step for two reasons. First, it gives you a simpler subtask which involves writing a loop to access objects of the array, as well as to access the depth value of those objects. Secondly, having this routine will probably be a helpful tool when debugging your sorting algorithm because it will give you a way to get a 'dump' of the data, both before and after it is sorted.
Write a loop which draws all elements, based on the current order of the array. Of course, writing this portion of the program without the sorting algorithm results in pictures of the snowman that are very odd. You will see many of the shapes, but the layering will be wrong as the depths are not yet ordered. Still, it is a step of progress, and code which will be useful to you in the end.
Finally, tackle the job of sorting the array. Chapter 8.6 of the text discusses some such algorithms. In particular, you are required to implement Selection Sort, as described in Chapter 8.6.3. That portion of the text gives a high-level description of the approach, but stops short of providing Java code. That's is left for you to do.
Please make sure that you understand how to do selection sort by hand, before you worry about how to code it. In particular, see Self-Study Exercise 8.13, on page 399, with solution on page 431.
Your part of the software is sent an array
Encountering numerous initial orderings will allow you to do more
robust testing of your sorting algorithm. At the same time, if you
encounter an error, it is convenient for you to be able to recreate
the same initial settings for retesting. For this reason, when you
run the driver it prints a line of output informing you of the value
of the random seed used for that execution. You may re-run the
program using the same seed by sending it as a parameter to the
main routine of PainterDriver. The expected
formatting of this information, if sent as a parameter to
main via BlueJ, would be as:
We have placed a copy of the template files for this assignment, Painter, in each of your home directories on patel2.slu.edu.
We start you with two classes in the project:
Canvas
This is the only file that you should be modifying. It is a
subclass of a Canvas, however with the necessary code missing
for implementing the painter's algorithm.
PainterDriver
This is a file which you should not edit. It is the main driver
to execute your program.
The assignment is worth 10 points. The general criteria will be the correctness and style of your implementation.