CS 161 Homework 5 - Sampler Quilt

Due Wed Mar 11 at 11:59pm

Overview

In this assignment, you will write a program that draws a picture of a particular type of quilt called a sampler quilt, which is composed of several different block types that illustrate a variety of quilting styles. You will use the java.awt graphics library to generate a drawing such as the one below:

The quilt consists of five patterns, illustrated by the first 5 patches in the top row:

  1. A "log cabin" block consisting of a nested pattern of rectangles
  2. A bullseye design of concentric circles
  3. A hybrid pattern combining elements of the log cabin and the bullseye
  4. A patch with a written message
  5. A design of your choosing (indicated by a question mark in this diagram)--you are free to replace this pattern with whatever design you like!

You can use whatever colors you want for these designs; hopefully your quilt will look less garish than mine! More details about how to create each of these designs are given below.

This assignment should be completed individually. You are welcome to ask for help (either from me or from your classmates), but remember the Gilligan's Island rule!

Class Quilts: section A, section B.

Objectives

Necessary Files

You should download and extract the BlueJ project from the Hw5.zip file. This project includes the beginnings of your Quilt class to provide an example and get you started. It also includes a README.txt file that you will need to complete.

Background: Graphics

Assignment Details

To draw your quilt, you will be making a single Java class called Quilt. I have provided the beginnings of this class for you, so you don't need to start from scratch. In this class you will define methods to draw each patch, calling these methods from a single paintComponent() method in order to paint a picture of the quilt. More details about each of the patches can be found below, as well as example documentation that can be found at the bottom of the page. (Looking at this documentation is a great way to figure out what your method signatures should be!)

Positioning Patches

  1. If you look at the quilt as a whole, you'll notice that each patch shows up more than once. That means that each patch will need to be able to be drawn anywhere in the quilt!
  2. Thus each method will need to take additional parameters that specify the relative position of the patch to the upper-left corner of the screen. Methods should thus take an rx (relative x) and ry (relative y) as parameters. See the below documentation for an example. The rx and ry should refer to the location of the upper-left corner of the patch.
    • All of your drawing commands (the methods you call on the Graphics paintbrush) will then need to take coordinates relative to these parameters. You can treat the (rx,ry) as the "origin" (kind of like (0,0)) for the patch.
    • So instead of drawing a dot at (50,50), you'd draw a dot at (rx+50, ry+50), where (rx,ry) is the origin for the patch.
    • This will allow you to easily re-draw the patch at a different location, simply by calling the draw method with a different rx and ry.
    • Remember how with the Robot in Lab C you have it a relative position? This is the same idea!
  3. In order to then draw the patches within the grid, you want to make sure that you specify the relative origin (the rx and ry) to match with the upper-left corner of the grid. Since each patch is the same size (the PATCH_SIZE constant), you can use that as an "offset" for how much to move each patch over by.
  4. Thus there will be a patch at (0,0), one at (PATCH_SIZE,0) one at (2*PATCH_SIZE,0), etc.
    • Note if you are on a high-resolution screen and your quilt is too tiny, you can change the PATCH_SIZE to 200.
  5. Lastly, notice that each patch-drawing method will need to take a Graphics object as a parameter; this will let you tell the method which paintbrush it should use to draw!
  6. To get a feel for how all this works, I recommend you start by creating and fill in the drawBullseyePatch() method, with appropriate parameters. If you tell this patch to draw a single red circle using:
    brush.setColor(Color.RED);
    brush.fillOval(...params...);
    you should be able to get it to draw the circle anywhere on the screen just by calling your method (from the paintComponent() method) with different parameters.
    • Make sure you can draw your patch in each of the 4 squares in the upper-left corner: that is a good test that everything is working!

Bullseye Patch

While not in the order above, I recommend you start with the Bullseye Patch (it's a bit easier). This patch is made up of a series of concentric circles centered on the block. You will need to use a loop to draw multiple circles.

  1. Start by drawing a single circle within the patch. Note that unlike the circle's we've worked with before, the Graphics method for drawing circles (drawOval()) measures an x and y position not from the center of the circle where you would expect, but from the upper left corner of the enclosing rectangle (similar to the Triangle from previous labs). So drawing an oval involves specifying a rectangle in which the circle will appear.
  2. You will need to write a loop that will draw multiple circles. Each time through the loop, you should reduce the size of the circle (shrinking diameter by 10 or 20 is a good number). You'll need to change both the (x,y) coordinates of the circle, as well as its width and height.
    • Hint: Try making variables for currentX, currentY, and currentDiameter. Declare these variables outside the loop. Then inside the loop's body, reduce the variables (e.g., subtract 10) and pass those variables to the paintbrush's drawOval() method.
  3. Your loop should continue until the diameter of the circle is less than 5 pixels. Because you don't know how many circles you'll need, you should use a while loop to perform indefinite iteration.
  4. Your bullseye patch should use at least two (non-white) colors: e.g., one for the background and one for the circles.
    • Alternatively, you can make a circle "filled in" by using the fillOval() command. If you want to put an outline on it, try using fillOval(), then changing the color, then using drawOval() with the same parameters. (Can you see why this works?)

Log Cabin Patch

This patch is a representation of an authentic quilt pattern that is widely used in traditional quilting. It is composed of a series of frames, each of which is nested inside the next larger one. Each frame is in turn composed of four rectangular boxes laid out to form a square. The outer frame, for example, looks like this: The next frame fills the space inside the outer frame, as follows: This same pattern continues for a specified number of frames, giving rise to the completed picture:

  1. To aid in this repetition, the first thing you should do is make a helper method that will draw a single frame of a specified width and length. You might call this method drawLogCabinFrame().
  2. As a helper method, this method should be private so that others don't call it (it's a secret helping method!)
  3. This method will need to take in a number of parameters: it will need to know which Graphics paintbrush to use, where the relative origin of the frame is, as well as the length and width of each rectangle in this particular frame! Yes, you will have a lot of parameters (but you'll use them all).
    • Note that the width (the short distance) of each rectangle is the same no matter how far you nest, but the length decreases as you move in. In fact, the length is shortened by twice the width at each step (can you see why?)
    • You can draw the 4 rectangles for each grid individually; you are not required to use a loop here.
  4. You can test this helper method by calling it from within the paintComponent() method. Try calling it with different origins and sizes!
  5. One you have the helper method working, you can fill in the actual drawLogCabinPatch() method. This method should call the helper method repeatedly (with successively smaller lengths) in order to draw the entire patch.
  6. But calling the draw method repeatedly is redundant; instead, you should use a loop to call the method at least 4 times.
    • Since you know how many times you'll be calling the method ("definite iteration"), you should use a for loop, though a while loop is acceptable.
    • Note that each time through the loop you will need to "update" the values (e.g., the width and height) passed to the helper method. Be careful about keeping track of these variables!

Hybrid Patch

This patch combines elements from the log cabin (the outer frame) and from the Bullseye. The point of including this patch is to emphasize the benefits of writing re-useable code.

  1. Since you should have a helper method for drawing a single "frame" of the log cabin, and you there is a method for drawing a bullseye, drawing this patch should be simply a matter of calling those two methods.

Text Patch

In this patch, you should write a short text message (it does not need to profess your enjoyment of a particular programming language).

  1. Look at the above list of methods and the documentation for the Graphics class. What method is going to help here?
  2. You can put text on separate lines by using separate calls to the drawString() method. Just make sure to move the x,y position of the text!
  3. You can make the text larger by changing the font via the setFont() method. See the Font class for more details. It is not required that you change the font.

Personal Patch

The last patch is one of your own choosing---a chance for you to flex your creative muscles! You have to include some kind of design, but what that design is remains totally up to you (please keep it appropriate though). You might draw a picture using circles, rectangles, and lines, create another geometic pattern, play with colors, or do whatever you like.

  1. Be sure to give this method a signature of
    public void drawYourNamePatch(Graphics brush, int rx, int ry) //replace your name
  2. I intend to take the patches everyone designs and copy them all into a single program so that we can generate an entire class quilt!

The Patch Grid

Once you have all (or most) of the patch drawing methods defined, you'll need to make it so they all are drawn over the entire quilt.

  1. This drawing should occur directly inside your paintComponent() method.
  2. In order to draw patches in each spot in the quilt grid, you'll need to use a loop. In fact, you'll need to use two! Use one loop to go through the rows, and then inside that loop, use another to go through the columns. This is called a nested loop.
    • Since you know how many ROWS and COLS there are, you can use a pair of for loops for this.
  3. When you call a method to draw a patch, you'll need to specify where that patch is. As mentioned above, the origin of the patch in the upper-left corner is at (0,0) or (0*PATCH_SIZE,0*PATCH_SIZE). The one next to that is at (1*PATCH_SIZE,0), the one next to that is at (2*PATCH_SIZE,0)... etc. (do you see a pattern?). Use the loop control variables (e.g., the i and j). to calculate the location for each patch as you loop through the grid.
  4. If you look at the quilt as a whole, one of the first things to notice is that the different block types are arranged in the quilt so that they form a regular pattern. Each successive row in the quilt has the same blocks in the same cyclic order (e.g., log cabin, bullseye, hybrid, text, custom; log cabin, bullseye, ...).
  5. You can easily produce a cycle by using the modulo operator %. This is a numeric operator (like + - * /): it takes the first operand, divides by the second operand, and returns the remainder. Thus:
    1 % 5 == 1 // 5 goes into 1 zero times, with 1 left over.
    4 % 5 == 4 // 5 goes into 4 zero times, with 4 left over.
    5 % 5 == 0 // 5 goes into 5 one time, with 0 left over.
    7 % 5 == 2 // 5 goes into 7 one time, with 2 left over.
    //...etc

    Consider the following pattern:

    0%3 => 0
    1%3 => 1
    2%3 => 2
    3%3 => 0
    4%3 => 1
    5%3 => 2
    ...

    That is, if you keep modding by the number of options, you can simply add one to a count in order to form a cycle!

  6. Once you have the current "count" of which patch you are drawing from the cycle (e.g., patch #0, patch #1, patch #2, etc), you can use a simple if/else if block to choose which draw method to call. E.g., if you're on patch #0, draw the log cabin; if you're on patch #1, draw the bullseye.
  7. Since each row starts with a different patch in the cycle, to avoid getting straight rows you'll need to offset the start spot in the cycle. Try having the 0th row start at patch #0, the 1th row start at patch #1, etc. Hint: try adding the row number to the cycle count!
  8. In short, inside your paintComponent() method you'll want to use a pair of loops to cycle through all the patches, and then for each spot in the grid you can use the modulo operator to choose which pattern to draw, and then call the appropriate method with the correct (rx,ry) parameters to actually draw the pattern!
  9. This should allow you to produce something similar to what you see at the top of the assignment!

Documentation

  1. While writing your program, be sure to include plenty of comments to explain what you are doing! Use inline comments to explain the "why" of your code, not the "what." Also include a full Javadoc comment (complete with @param and @return tags) for each method in your program.

Timeline

You may be thinking there is a lot to do for this assignment---and you'd be right. This is not an assignment you can just do the last day--get started early! Try writing a pattern each day, and then by the due date you'll be all finished!

  1. Start by working through the relative positioning for the patterns (the rx and ry, described under "Positioning Patches").
  2. After that, I recommend starting with the text patch and the log cabin helper; these don't require any loops, and are good practice working with the Graphics paintbrush. You can do these by Tues Mar 03.
  3. Doing the bullseye is a good next step, and you should be able to do it by Wed Mar 04.
  4. The log cabin can be completed after that, and should be doable by Fri Mar 06.
  5. Finish up the patches (including adding your custom patches) by Mon Mar 09.
  6. You can then add in the final set of nested loops to draw all the patches by the due date on Wed Mar 11.

Submitting

There are a couple of details to keep in mind before you submit your assignment.

  1. Double-check that your methods are completed and work correctly.
    • If your program doesn't compile, I can't give you credit for it!
  2. Make sure that your code is commented. Give lots of inline comments, and include a JavaDoc method comment for each method!
  3. Also confirm that your custom patch method is named appropriately :)
  4. You will also need to fill out the README.txt file. You can open this file in BlueJ by double-clicking on the white paper icon in the upper left corner of the class window. You should place the answer to each question below the question box, replacing the "<Replace this with your response!>". Remember to save your changes (select "Class > Save" from the menu).

  5. You should compress the entire Hwk5 folder into a single zip file (like you did for Lab A), and then submit it to the Hwk5 Submission page on Moodle.
    • Be sure an upload the ENTIRE project folder--that is what includes all your work!
  6. This assignment is due at midnight on Wed, Mar 11.

Grading

This assignment will be graded out of 31 points.

Documentation

Below is sample JavaDoc for the completed Quilt class.



Class Quilt


public class Quilt extends javax.swing.JPanel

A program that draws a sampler quilt

Author:
YOUR NAME HERE

 

Field Summary
 int COLS
          The number of columns in the quilt
 int PATCH_SIZE
          The size of a patch (in pixels)
 int ROWS
          The number of rows in the quilt
 
Constructor Summary
Quilt()
          Creates a new 5x7 quilt.
Quilt(int rows, int cols)
          Creates a new quilt with the given number of rows and columns
 
Method Summary
 void drawBullseyePatch(Graphics brush, int rx, int ry)
          Draws a bullseye pattern at the given coordinates
 void drawGrid(Graphics brush)
          Draws an grid using the given graphics brush
 void drawHybridPatch(Graphics brush, int rx, int ry)
          Draws a hybrid pattern at the given coordinates
 void drawLogCabinPatch(Graphics brush, int rx, int ry)
          Draws a log cabin pattern at the given coordinates
 void drawTextPatch(Graphics brush, int rx, int ry)
          Draws a text pattern at the given coordinates
 void drawYOURNAMEPatch(Graphics brush, int rx, int ry)
          Draws a personal pattern at the given coordinates
 void paintComponent(Graphics brush)
          This method actually draws the quilt.
 
Field Detail

COLS

public final int COLS
The number of columns in the quilt


PATCH_SIZE

public final int PATCH_SIZE
The size of a patch (in pixels)

See Also:
Constant Field Values

ROWS

public final int ROWS
The number of rows in the quilt

Constructor Detail

Quilt

public Quilt()
Creates a new 5x7 quilt.


Quilt

public Quilt(int rows,
             int cols)
Creates a new quilt with the given number of rows and columns

Parameters:
rows - The number of rows
cols - The number of cols
Method Detail

drawBullseyePatch

public void drawBullseyePatch(Graphics brush,
                              int rx,
                              int ry)
Draws a bullseye pattern at the given coordinates

Parameters:
brush - The graphics object to draw with
rx - The relative x-origin
ry - The relative y-origin

drawGrid

public void drawGrid(Graphics brush)
Draws an grid using the given graphics brush

Parameters:
brush - the Graphics paintbrush to draw with.

drawHybridPatch

public void drawHybridPatch(Graphics brush,
                            int rx,
                            int ry)
Draws a hybrid pattern at the given coordinates

Parameters:
brush - The graphics object to draw with
rx - The relative x-origin
ry - The relative y-origin

drawLogCabinPatch

public void drawLogCabinPatch(Graphics brush,
                              int rx,
                              int ry)
Draws a log cabin pattern at the given coordinates

Parameters:
brush - The graphics object to draw with
rx - The relative x-origin
ry - The relative y-origin

drawTextPatch

public void drawTextPatch(Graphics brush,
                     int rx,
                     int ry)
Draws a text pattern at the given coordinates

Parameters:
brush - The graphics object to draw with
rx - The relative x-origin
ry - The relative y-origin

drawYOURNAMEPatch

public void drawYOURNAMEPatch(Graphics brush,
                              int rx,
                              int ry)
Draws a personal pattern at the given coordinates

Parameters:
brush - The graphics object to draw with
rx - The relative x-origin
ry - The relative y-origin

paintComponent

public void paintComponent(Graphics brush)
This method actually draws the quilt. It is called automatically (by Java) when the window appears. You never call this yourself.

Overrides:
paintComponent in class javax.swing.JComponent
Parameters:
brush - The Graphics paintbrush to draw with.