Topics:
1. Drawing a "complicated" object (smiley face)
- creating procedures to carry out meaningful tasks (e.g. draw a smiley face)
- calculating relative coordinates
Drawing a complicated object (smiley face)
The goal is to create the following drawing:
(click to enlarge)
In this example we used the capabilities of the graphics library and created our own
procedure for drawing a smiley face. This procedure allows us to draw smiley faces of
different sizes while scaling appropriately the features of the face, so that small
faces have relatively small features and bigger faces have relatively bigger features.
In our setup we had the following requirements:
- the radius of each eye is 1/3 of the face radius
- the horizontal (x) distance between the face center and each eye is 1/3 of the face radius
- the vertical (y) distance the face center and the eye line is 1/3 of the face radius
Finally we have the following problem:
Goal: Given a pair of (x, y) coordinates and a radius value draw a smiley face centered at
the given (x,y) location and of the given size (radius) such that the smiley face features
are spaced and sized as indicated above.
Drawing the smiley
We first setup the description of the procedure that does the actual drawing:
- it returns nothing -- thus we use the keyword void
- it is named drawSmiley (any appropriate name would work)
- it takes three inputs: x, y, radius all of which are numbers
the Java keyword double indicates that an input is expected to be a number
Here is the skeleton of the procedure. For clarity instead of x, y, radius we have used
the slightly longer names faceX, faceY, faceRadius for the inputs. Also later there will
be many position and size components, so the new names are chosen to be specific to the
thing we are drawing.
void drawSmiley( double faceX, double faceY, double faceRadius )
{
}
Note: For now the meaning of void is that we are creating a new command/procedure.
Note: The keyword double indicates that the variable/PostIt is a number.
Drawing the smiley -- the face only
We worked in stages. First we made sure we can draw appropriately sized yellow blobs at
the specified locations.
void drawSmiley( double faceX, double faceY, double faceRadius )
{
// draw the face
canvas.drawCircle( faceX, faceY, faceRadius, "yellow" );
}
Here is the final code for the smiley along with sample test cases:
public class SmileyApp
{
void drawSmiley( double faceX, double faceY, double faceRadius )
{
canvas.drawCircle( faceX, faceY, faceRadius, "yellow" );
}
public void run()
{
drawSmiley( 150, 200, 60 );
drawSmiley( 10, 20, 8 );
drawSmiley( 300, 350, 70 );
}
}
Drawing the smiley -- adding the left eye
Next we added the left eye. We had a design that specified how to compute the location
and size of the eye from the face information.
Java allows us to create PostIt notes on which to write/compute new information. To draw
an eye need to know its (x,y) position and size/radius, so we created three PostIts
eyeX, eyeY, eyeRadius and wrote on each the corresponding formula from our design above.
eyeX = faceX + 0.3*faceRadius
eyeY = faceY - 0.3*faceRadius (in our case "above" means subtract)
eyeRadius = 0.2*faceRadius
Note that a person's eye is placed at a distance relative to that person's nose and this
is what the formulas above indicate. For example:
start at nose plus short distance away
----- --------------
eyeX = faceX + 0.3*faceRadius
Here is the code for the left eye. Note that to go up in Y direction we have to subtract:
void drawSmiley( double faceX, double faceY, double faceRadius )
{
// draw the face
canvas.drawCircle( faceX, faceY, faceRadius, "yellow" );
// draw the left eye
double eyeX = faceX + 0.3*faceRadius;
double eyeY = faceY - 0.3*faceRadius;
double eyeRadius = 0.2*faceRadius;
canvas.drawCircle( eyeX, eyeY, eyeRadius, "black" );
}
Drawing the smiley -- adding the right eye
The right eye is similar but we go left from the nose, so need to subtract in the X direction:
eyeX = faceX - 0.3*faceRadius
eyeY = faceY - 0.3*faceRadius (same as left eye)
eyeRadius = 0.2*faceRadius (same as left eye)
Here is the code for the right eye. Notice that we only recompute eyeX. The other PostIts
can be reused, since the two eyes have the same size and Y level.
void drawSmiley( doublefaceX, double faceY, double faceRadius )
{
// draw the face
canvas.drawCircle(faceX, faceY, faceRadius, "yellow" );
// draw the left eye
double eyeX = faceX + 0.3*faceRadius;
double eyeY = faceY - 0.3*faceRadius;
double eyeRadius = 0.2*faceRadius;
canvas.drawCircle( eyeX, eyeY, eyeRadius, "black" );
// draw the right eye -- only the x coordinate needs to be updated
eyeX = faceX - 0.3*faceRadius;
canvas.drawCircle( eyeX, eyeY, eyeRadius, "black" );
}
Note: In the expression
eyeX = faceX - 0.3*faceRadius;
there is no keyword double. The keyword double indicates that we are creating a PostIt
(a variable). Since eyeX has already been created earlier we do not specify double anymore
when we use eyeX -- it is an error to put double every time for the same PostIt.
Here is the final code for the smiley along with sample test cases:
public class SmileyApp
{
// draws a smiley face centered at the given "(x,y)" and of the given "radius"
// the face features are scaled relative to the face radius
void drawSmiley( double faceX, double faceY, double faceRadius )
{
// draw the face
canvas.drawCircle(faceX, faceY, faceRadius, "yellow" );
// draw the left eye
double eyeX = faceX + 0.3*faceRadius;
double eyeY = faceY - 0.3*faceRadius;
double eyeRadius = 0.2*faceRadius;
canvas.drawCircle( eyeX, eyeY, eyeRadius, "black" );
// draw the right eye -- only the x coordinate needs to be updated
eyeX = faceX - 0.3*faceRadius;
canvas.drawCircle( eyeX, eyeY, eyeRadius, "black" );
}
public void run()
{
drawSmiley( 150, 200, 60 );
drawSmiley( 10, 20, 8 );
drawSmiley( 300, 350, 70 );
}
}