Step 2: Changing the Size and Position

I worked very hard to determine exactly where my ears should go with respect to the head by trial and error. On the other hand, I know that it is not always the case that I will want to see Mickey that large and in the center of the applet. When I change my mind about his position or size later, I do not want to have to remember (or worse yet, figure out again) how to change each number in my code to match my new situation.

Therefore, I have to modify the code to draw Mickey based only on his center and size. Given that little bit of information, I should be able to recreate Mickey automatically. Instead of using literal numbers, I can use variables which can be changed easily. Likewise, I will use equations based on those variables to derive the positions and sizes of Mickey's ears. The question we need to answer is: Given the size and position of Mickey's head, can we calculate what the size and position of the ears ought to be?

Because I want everything to be based on the position and size of the head, I will need three variables to represent these values --- two for his position coordinates and one for his size (since I am assuming Mickey is made up of perfect circles). I decided to name these variables cx, cy, and sz for center x coordinate, center y coordinate, and size of the face.

Here are the numbers I used in the code so far.
Mickey Part (cx,cy) (sz)
Face (200, 200) (200)
Left Ear (90, 90) (120)
Right Ear (310, 90) (120)

Size Relationships

Looking at the table above, we can see several relationships between the numbers. For example, look at the relationship between the head size and the ear size. The head size is 200 and the ear size is 120. We could say the ear size can be calculated by subtracting 80 from the head size. But remember that the point of this exercise is to come up with an equation that works for all cases, not just one specific case. What would happen when the head size is less than 80? What would happen if the head size is 81? Should the ear size really be just 1? Try it and see how silly it looks!

Instead, we want the size of the ears to be proportional to the size of the head. The ratio of the size of an ear to the size of the head is 120 / 200 = 3 / 5; the ears are three-fifths the size of the head. So if the size of the head is x, then the size of an ear should be x*3/5.

Position Relationships

The position of the ears is slightly harder because it involves a combination of factors. Of course, the first thing I notice is that one ear is a mirror image of the other, i.e., the y coordinate should be the same and the x coordinate should be the same distance away from that center for each. Well, when the center of the head is (200, 200) the ear's center is 110 pixels away horizontally. I quickly realize that I cannot simply subtract 110 from the x coordinate, because the head may be smaller than 110 in size. The ear would not touch the head! I also cannot just say that the cx of the ear is 110/200 the cx of the head in this case. Imagine that the head is centered at (200,200) but is only of size 10. Having the left ear be centered at x coordinate 110 means that the ear and the head do not match up!

So clearly my new coordinates must be based on the size of the head in addition to its position. Let's consider this. Starting at the center of the head, how can we describe how to get to the center of the left ear? Let's consider the x coordinate first. To get from the cx of the head to the cx of the left ear, we should travel to the left for some percentage of the head. This is the algebraic expression that takes into account both the size and position of the head and works for every case:

cx_left_ear = cx_head - (some_percentage) * (size_of_head)

We subtract here because the center of the ear is to the left of the center of the head. When we do the right ear the only thing to change about this equation is that we will add to go to the right. What remains is to find the correct percentage. To do this, we plug in the numbers from the table above, and solve for the percentage:

90 = 200 - (x) * (200)
-110 = -(x) * (200)
110 / 200 = x
11 /20 = x

Now we have an equation to get the cx of the left ear, given the cx of the head. Since the right ear is a mirror image, the same equation will work, only we will add to travel to the right from the center instead of subtract.

We have noticed that cy is the same for both ears and since we are using circles for our shapes, the proportions for the vertical change are the same as those for the horizontal change.

Thus, we will use the following equations:
Face (cx, cy) (sz)
Left Ear (cx - sz * 11/20, cy - sz * 11/20) (sz * 3 / 5)
Right Ear (cx + sz * 11/20, cy - sz * 11/20) (sz * 3 / 5)

Final Code

The modified the code looks like the following, we have substituted equations for the "magic" numbers we had previously:

public class Applet extends GP.Containers.Applet
{
    public Applet ()
    {
        // initial position and size
        double cx = 200;
        double cy = 200;
        double sz = 200;

        // create Mickey parts
        GP.Shapes.Oval face = new GP.Shapes.Oval();
        GP.Shapes.Oval leftEar = new GP.Shapes.Oval();
        GP.Shapes.Oval rightEar = new GP.Shapes.Oval();
        
        // set position of Mickey parts
        GP.Attributes.Coordinate center = new GP.Attributes.Coordinate(cx, cy);
        face.SetPosition(center);
        center = new GP.Attributes.Coordinate(cx - sz * 11 / 20, cy - sz * 11 / 20);
        leftEar.SetPosition(center);
        center = new GP.Attributes.Coordinate(cx + sz * 11 / 20, cy - sz * 11 / 20);
        rightEar.SetPosition(center);
        
        // ears are same size, face larger
        GP.Attributes.Dimension size = new GP.Attributes.Dimension(sz, sz);
        face.SetSize(size);
        size = new GP.Attributes.Dimension(sz * 3 / 5, sz * 3 / 5);
        leftEar.SetSize(size);
        rightEar.SetSize(size);

        // all parts are the same color
        GP.Attributes.Color color = new GP.Attributes.Colors.Black();
        face.SetColor(color);
        leftEar.SetColor(color);
        rightEar.SetColor(color);
    }
}
Note that I used variables of type double, Java's type for real numbers, to store my initial values, cx, cy, and sz because I need to make algebraic relationships between these values. Unfortunately, I cannot do algebra with objects like ovals, coordinates, or applets. Moreover, note that these double values can be created using literal numbers, instead of using the Java keyword new.

To test that my equations are correct, I simply change the initial values of the three variables of type double and rebuild my applet code. Now I can create Mickey Mouse, positioned anywhere in the applet and at any given size.