Painter

Programming Assignment 7

Due: 8pm, Wednesday 14 April 2004


Contents:


Overview

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.

Newly Introduced Techniques


Collaboration Policy

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.


Your Task

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.

Your task is to implement the draw routine for the class Canvas, proceeding as follows:

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

  2. A loop can then be used to invoke the draw method for each individual object, proceeding from greatest to least depth.


Suggested Steps of Progress

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:

  1. Define a new method printDepths(Drawable[] contents) which prints the depths of all objects in the array.

    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.

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

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


Controlling Randomness

Your part of the software is sent an array Drawable contents[] which is not sorted by depth initially. In fact, we intentionally shuffle the array before it is sent to you, so that each time you run the program, the original order will be different.

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:
{"1080313052972"}


Files You Will Need

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:

In addition, you can rely on the provided input files in subdirectory input.

Submitting Your Assignment

Please see details regarding the submission process from the general programming web page, as well as a discussion of the late policy.

Grading Standards

The assignment is worth 10 points. The general criteria will be the correctness and style of your implementation.


Michael Goldwasser
Last modified: Wednesday, 14 April 2004