# OpenStax-CNX

You are here: Home » Content » GAME 2302-0125: Vector Addition

### Recently Viewed

This feature requires Javascript to be enabled.

Module by: R.G. (Dick) Baldwin. E-mail the author

Summary: Learn how to add two or more vectors. Also learn about the head-to-tail rule in vector addition, about the vector addition parallelogram, about the relationship between the length of the sum of vectors and the lengths of the individual vectors in the sum, how to add a vector to a point, how to get the length of a vector, and how to represent an object in different coordinate frames.

## Preface

This module is one in a collection of modules designed for teaching GAME2302 Mathematical Applications for Game Development at Austin Community College in Austin, TX.

What you have learned

In the previous couple of modules, you learned:

• How to compare column matrices for equality
• How to compare two points for equality
• How to compare two vectors for equality
• How to add one column matrix to another
• How to subtract one column matrix from another
• How to get a displacement vector from one point to another

What you will learn

In this module you will learn:

• How to add two or more vectors
• About the relationship between the length of the sum of vectors and the lengths of the individual vectors in the sum
• How to add a vector to a point
• How to get the length of a vector
• How to represent an object in different coordinate frames

### Viewing tip

I recommend that you open another copy of this module in a separate browser window and use the following links to easily find and view the Images and Listings while you are reading about them.

#### Images

• Image 1 . Screen output from the program named VectorAdd01.
• Image 2 . Screen output from CoordinateFrame01 at startup.
• Image 3 . Screen output from CoordinateFrame01 after changes to the coordinate frame.
• Image 4 . Screen output from the program named VectorAdd02.
• Image 5 . Graphic screen output from the program named VectorAdd03.
• Image 6 . Command-line output from the program named VectorAdd03.
• Image 7 . Screen output from the program named VectorAdd04.
• Image 8 . Screen output from Exercise 1.
• Image 9 . Screen output from Exercise 2.

## Preview

In this module, I will present and explain several updates to the game-math library. In addition, I will present and explain five sample programs that illustrate the use of the new features of the library.

I will also provide exercises for you to complete on your own at the end of the module. The exercises will concentrate on the material that you have learned in this module and previous modules.

## Discussion and sample code

The game-math library was updated and the name was changed to GM2D04 in preparation for this module. Much of the code in the updated library remains unchanged. I explained that code in the previous modules and I won't repeat that explanation in this module. I will concentrate on explaining the modifications that I made to the library in this module.

### The game-math library named GM2D04

A complete listing of the library program is provided in Listing 19 near the end of the module.

This update added the following new capabilities to the library:

• GM2D04.Vector.add - Adds this Vector object to a Vector object received as an incoming parameter and returns the sum as a new Vector object.
• GM2D04.Vector.getLength - Returns the length of a Vector as type double .
• GM2D04.Point.addVectorToPoint - Adds a Vector object to a Point object returning a new Point object.

These three new methods are presented in Listing 1 , Listing 2 , and Listing 3 below. These methods are so simple that no explanation should be required for you to understand them.

1
Listing 1: The add method of the GM2D04.Vector class.
    //Adds this vector to a vector received as an incoming
// parameter and returns the sum as a vector.
return new GM2D04.Vector(new ColMatrix(
vec.getData(0)+vector.getData(0),
vec.getData(1)+vector.getData(1)));


.

2
Listing 2: The getLength method of the GM2D04.Vector class.
    //Returns the length of a Vector object.
public double getLength(){
return Math.sqrt(
getData(0)*getData(0) + getData(1)*getData(1));
}//end getLength


.

3
Listing 3: The addVectorToPoint method of the GM2D04 class.
    //Adds a Vector to a Point producing a new Point.
GM2D04.Vector vec){
return new GM2D04.Point(new GM2D04.ColMatrix(
getData(0) + vec.getData(0),
getData(1) + vec.getData(1)));


Simple but powerful

Although these new methods are individually very simple, when combined with the other methods in the library, they significantly increase the power of the library. For example, in the next module I will show you that the library in its current form supports translation and animation.

I will illustrate the use of these new methods in the sample programs that follow.

This program illustrates the addition of two and then three vectors. It also illustrates the head-to-tail rule described by Kjell. A complete listing of the program is provided in Listing 20 near the end of the module.

Screen output from the program named VectorAdd01

The screen output from the program is shown in Image 1 .

You will recall that the game-math library represents a Vector object graphically as a straight line with a small circle at the head. Thus, there are five vectors drawn in Image 1 . I will explain the meaning of the output in conjunction with the explanation of the program.

Beginning of the program named VectorAdd01

Listing 4 shows the entire class named VectorAdd01 along with the beginning of the class named GUI including the constructor for the GUI class.

5
Listing 4: Beginning of the program named VectorAdd01.
class VectorAdd01{
public static void main(String[] args){
GUI guiObj = new GUI();
}//end main
//======================================================//

class GUI extends JFrame{
//Specify the horizontal and vertical size of a JFrame
// object.
int hSize = 275;
int vSize = 200;
Image osi;//an off-screen image
int osiWidth;//off-screen image width
int osiHeight;//off-screen image height
MyCanvas myCanvas;//a subclass of Canvas

GUI(){//constructor
//Set JFrame size, title, and close operation.
setSize(hSize,vSize);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

//Create a new drawing canvas and add it to the
// center of the JFrame.
myCanvas = new MyCanvas();

//This object must be visible before you can get an
// off-screen image.  It must also be visible before
// you can compute the size of the canvas.
setVisible(true);
osiWidth = myCanvas.getWidth();
osiHeight = myCanvas.getHeight();

//Create an off-screen image and get a graphics
// context on it.
osi = createImage(osiWidth,osiHeight);
Graphics2D g2D = (Graphics2D)(osi.getGraphics());

//Draw some graphical objects on the off-screen
// image that represent underlying data objects in
// 2D space.
drawOffScreen(g2D);

//Cause the overridden paint method belonging to
// myCanvas to be executed.
myCanvas.repaint();

}//end constructor


Very familiar code

The code in Listing 4 is very similar to code that I explained in the earlier module titled GAME 2302-0110: Updating the Math Library for Graphics . Therefore, I won't explain that code again in this module.

This code is mainly needed to get everything set up for graphics.

Note that the code in Listing 4 makes a call to the method named drawOffScreen near the end of the listing. That is where we find the interesting code.

Beginning of the method named drawOffScreen

The beginning of the drawOffScreen method is shown in Listing 5 .

The purpose of this method is to add some Vector objects and to cause visual manifestations of the raw Vector objects and the resultant Vector objects to be drawn onto an off-screen image.

6
Listing 5: Beginning of the method named drawOffScreen.
  void drawOffScreen(Graphics2D g2D){
setCoordinateFrame(g2D);


Listing 5 begins by calling the method named setCoordinateFrame , which is shown in its entirety in Listing 6 . I will put the discussion of the drawOffScreen method on hold while I explain the method named setCoordinateFrame .

The method named setCoordinateFrame

This method sets the origin to a point near the upper-left corner of the off-screen image (see Image 1 ) and draws orthogonal axes on the off-screen image intersecting at the origin.

7
Listing 6: The method named setCoordinateFrame.
  private void setCoordinateFrame(Graphics2D g2D){
//Translate the origin.
g2D.translate(0.2*osiWidth,0.2*osiHeight);

//Draw new X and Y-axes in default BLACK
g2D.drawLine(-(int)(0.2*osiWidth),0,
(int)(0.8*osiWidth),0);

g2D.drawLine(0,-(int)(0.2*osiHeight),
0,(int)(0.8*osiHeight));

}//end setCoordinateFrame method


There is no intention to perform mathematical operations on the axes, so they are drawn independently of the classes and methods in the game-math library using the simplest method available for drawing a line.

The name of that simple method is drawLine , and it is a method of the standard Java Graphics class. The translate method is also a method of the Graphics class. Given that information, the code in Listing 6 is straightforward and should not require further explanation.

Returning to the method named drawOffScreen , Listing 7 begins by instantiating two objects of the GM2D04.Vector class.

8
    GM2D04.Vector vecA = new GM2D04.Vector(
new GM2D04.ColMatrix(50,100));
GM2D04.Vector vecB = new GM2D04.Vector(
new GM2D04.ColMatrix(75,25));



Then Listing 7 calls the new add method (see Listing 1 ) on one of the vectors, passing the other vector as a parameter to the method. The add method returns a third vector that is the sum of the other two vectors. The new vector is referred to as sumOf2 in Listing 7 .

Draw vecA in RED with its tail at the origin

Recall that a vector has only two properties: length and direction. It does not have a position property. Therefore, if you decide to draw a vector, you can draw it anywhere in space, and one position is equally as valid as any other position.

Listing 8 sets the drawing color to RED and calls the draw method on vecA producing the red visual manifestation of the Vector object shown in Image 1 .

(Note that there is also a magenta vector in Image 1 , and it may be difficult to distinguish from the red vector, depending on the quality of the color on your monitor. The magenta vector is longer than the red vector.)

9
Listing 8: Draw vecA in RED with its tail at the origin.
    g2D.setColor(Color.RED);
vecA.draw(g2D,new GM2D04.Point(
new GM2D04.ColMatrix(0,0)));


Note that I elected to draw the vector with its tail at the origin, but that was an arbitrary decision that I will discuss in more detail later.

Draw vecB in GREEN head-to-tail with vecA

While it's legal to draw a vector anywhere in space, certain positions may have advantages over other positions in some cases. You will see what I mean shortly. In the meantime, Listing 9 creates a visual manifestation of the vecB object with its tail at the head of the vecA object as shown by the green vector in Image 1 .

10
Listing 9: Draw vecB in GREEN head-to-tail with vecA.
    g2D.setColor(Color.GREEN);
vecB.draw(g2D,new GM2D04.Point(new GM2D04.ColMatrix(
vecA.getData(0),vecA.getData(1))));


Draw sumOf2 in MAGENTA with its tail at the origin

Listing 10 creates a visual manifestation of the sumOf2 object with its tail at the origin as shown by the magenta vector in Image 1 .

(In case you don't recognize the name of the color magenta, it looks similar to violet or purple. As mentioned earlier, it is somewhat longer than the red vector)

More correctly, Listing 10 draws the sumOf2 object with its tail coinciding with the tail of vecA . I elected to position the tails of the two vectors at the origin to keep the code a little simpler.

11
Listing 10: Draw sumOf2 in MAGENTA with its tail at the origin.
    g2D.setColor(Color.MAGENTA);
sumOf2.draw(g2D,new GM2D04.Point(new GM2D04.ColMatrix(
0.0,0.0)));


We have just illustrated a very important rule that can make it much easier to visualize the results of vector addition. It is often called the head-to-tail rule.

If you add two or more vectors to produce a sum vector, and then draw the vectors that were included in the sum with the tail of one vector coinciding with the head of another vector, (as illustrated by the red and green vectors in Image 1 ) , the head of the last vector that you draw will be positioned at some particular point in space.

If you then draw the vector that represents the sum vector with its tail coinciding with the tail of the first vector that you drew, its head will coincide with the head of the last vector that you drew as shown by the magenta vector in Image 1 .

The tail of the magenta vector coincides with the tail of the red vector, and the head of the magenta vector coincides with the head of the green vector.

(It doesn't matter whether or not the coinciding tails are drawn at the origin.)

Furthermore, this rule will hold regardless of the number of vectors included in the sum.

Extending the example to three vectors

Listing 11 extends this example to three vectors.

12
Listing 11: Extending the example to three vectors.
    //Now define another vector and add it to vecA and
// vecB.
GM2D04.Vector vecC = new GM2D04.Vector(
new GM2D04.ColMatrix(30,-150));

//Draw vecD in BLUE with its tail positioned at the
// sum of vecA and vecB
g2D.setColor(Color.BLUE);
vecC.draw(g2D,new GM2D04.Point(new GM2D04.ColMatrix(
sumOf2.getData(0),sumOf2.getData(1))));

//Define a vector as the sum of vecA, vecB, and vecC

//Draw sumOf3 in BLACK with its tail at the origin.
g2D.setColor(Color.BLACK);
sumOf3.draw(g2D,new GM2D04.Point(
new GM2D04.ColMatrix(0.0,0.0)));

}//end drawOffScreen

You should understand this code

By now, you should have no difficulty understanding the code in Listing 11 . The only tricky thing that I would call your attention to is the syntax of the code that adds the three vectors shown below for emphasis.

You should make certain that you understand this syntax.

#### Note:

It is at times like this when I wish that Java supported overloaded operators in a manner similar to C++. Overloading the + operator would make the syntax much more intuitive than that shown by the code in Listing 11 .

Back to the drawing

Now turn your attention back to the drawing in Image 1 . The red, green, and blue vectors are drawn in a head-to-tail manner as described earlier. The sumOf3 (black) vector is drawn with its tail coinciding with the tail of the first (red) vector. Note that the head of the black vector coincides with the head of the last (blue) vector in the sum. Although not a definitive proof, this is at least a strong indication that the head-to-tail rule works for adding any number of vectors.

An overridden paint method

The MyCanvas class also includes an overridden paint method. However, the code in that method is very similar to code that I explained in the earlier module titled GAME 2302-0110: Updating the Math Library for Graphics . Therefore, I won't explain that code again in this module. You can view the overridden paint method in Listing 20 .

That concludes the discussion of the program named VectorAdd01 .

### The program named CoordinateFrame01

A complete listing of this program is provided in Listing 21 near the end of the module. This program illustrates the relationship between the coordinate frame and a geometric object described in that coordinate frame.

A GUI allows the user to move the origin of the coordinate frame. Proper mathematical corrections are made such that a geometric object described in that coordinate frame maintains its position relative to world coordinates even when the coordinate frame is changed. This causes its position relative to the coordinate frame to change.

Screen output at startup

Image 2 shows the screen output of the program at startup.

The axes are difficult to see

At this point, the origin is at the upper-left corner of the canvas. Although orthogonal axes are drawn intersecting at the origin, they are at the very edge of the canvas and are only barely visible. I will later refer to this coordinate frame with the origin in the upper-left corner as world coordinates .

A point has been defined (but not drawn) at a location specified by X equal to 196 and Y equal to 165. Even though the point is not drawn, a red vector has been drawn with its tail located at that point. A green vector has been drawn with its tail at the head of the red vector. A blue vector has been computed as the sum of the red and green vectors and it has been drawn with its tail at the tail of the red vector. As you learned in the previous program, this results in a closed polygon that is drawn at the point defined above.

Modify the coordinate frame

Image 3 shows the result of modifying the coordinate frame and then causing everything to be re-drawn. The coordinate frame is modified by entering values into the two user input fields and clicking the Replot button at the bottom of the GUI.

The new location of the origin

In Image 3 , the origin of the coordinate frame has been moved to the right by an amount that is equal to 40-percent of the width of the off-screen image, and has been moved down by an amount that is 60-percent of the height of the off-screen image. Then a pair of orthogonal axes was drawn, intersecting at the new location of the origin.

A point is simply a location in space

Although a vector doesn't have a location property and therefore is immune to changes in the coordinate frame, a point does have a location property. In fact that is the only property that a point does have, because a point is simply a location in space. Furthermore, that location is always specified relative to some coordinate frame. In order to cause the point to remain in the same location relative to world coordinates, (which was the objective here) , its values relative to the current coordinate frame must be modified each time the coordinate frame is modified.

After the values representing the point were modified appropriately, the three vectors were drawn in Image 3 with the tails of the red and blue vectors located at the point. This caused the geometric object described by the three vectors to remain in the same location relative to world coordinates. However, when the current coordinate frame no longer matched the world coordinate frame, the location of the geometric object changed relative to the current coordinate frame. The geometric object is closer to the origin of the current coordinate frame in Image 3 than was the case in Image 2 .

More complicated code

The code in this program is somewhat more complicated than the code in the previous program, mainly due to the inclusion of an interactive GUI in the program. I have published many previous tutorials that explain how to write interactive programs in Java, and I won't repeat that explanation here. Instead, I will concentrate on the use of the game-math library in my explanation of this program. What this really means is that I am only going to explain the following three methods in this program:

• actionPerformed
• setCoordinateFrame
• drawOffScreen

You can view the remaining program code in Listing 21 near the end of the module.

The actionPerformed method

This method must be defined in the class named GUI because the GUI class implements the ActionListener interface. Because an object of the GUI class is registered as a listener on the Replot button shown in Image 2 , the actionPerformed method is called each time the user clicks the button.

15
Listing 12: The actionPerformed method.
  public void actionPerformed(ActionEvent e){
//Reset the coordinate frame to world coordinates by
// reversing the most recent translation.
setCoordinateFrame(g2D,-xOffset,-yOffset);

//Compute new translation offsets based on user input.
xOffsetFactor =
Double.parseDouble(xOffsetField.getText());
yOffsetFactor =
Double.parseDouble(yOffsetField.getText());

xOffset = osiWidth*xOffsetFactor;
yOffset = osiHeight*yOffsetFactor;

//Draw a new off-screen image based on user inputs
// and copy it to the canvas. Note that the
// drawOffScreen method will call the
// setCoordinateFrame method again with the new
// offset values for the origin of the coordinate
// frame.
drawOffScreen(g2D);
myCanvas.repaint();
}//end actionPerformed


What does the actionPerformed method do?

There is nothing complicated about the code in Listing 12 . This code performs the following actions as indicated by the embedded comments:

• Call the setCoordinateFrame method to reset the coordinate frame to world coordinates.
• Get user input values and use them to compute and save new offset values that will be used to define the origin of the new coordinate frame.
• Call the drawOffScreen method to erase the current image from the off-screen image and draw a new image on it using the new coordinate frame. Note that the drawOffScreen method will call the setCoordinateFrame method to establish the new coordinate frame before drawing the new image on the off-screen image.
• Call the repaint method to cause the off-screen image to be copied to the canvas and displayed on the computer screen.

The setCoordinateFrame method

This method, which is shown in Listing 13 , is used to set the coordinate frame of the off-screen image by setting the origin to the specified offset values relative to origin of the world coordinate frame.

16
Listing 13: The setCoordinateFrame method.
  private void setCoordinateFrame(
Graphics2D g2D,double xOff,double yOff){

//Paint the background white
g2D.setColor(Color.WHITE);
g2D.fillRect(0,0,osiWidth,osiHeight);

//Translate the origin by the specified amount
g2D.translate((int)xOff,(int)yOff);

//Draw new X and Y-axes in BLACK
g2D.setColor(Color.BLACK);
g2D.drawLine(-(int)xOff,0,(int)(osiWidth-xOff),0);
g2D.drawLine(0,-(int)yOff,0,(int)((osiHeight-yOff)));

}//end setCoordinateFrame method


What does the setCoordinateFrame method do?

As mentioned earlier, the origin of the world coordinate frame is the upper-left corner of the off-screen image. The setCoordinateFrame method assumes that the current coordinate frame coincides with the world coordinate frame when the method is called. This is because the method changes the coordinate frame relative to the current coordinate frame.

The method begins by painting the background white erasing anything already there. (Note that this step erases the entire image only when the coordinate frame coincides with the world coordinate frame when the method is called.)

Then the method establishes the new coordinate frame by translating the origin of the off-screen image using the X and Y offset values received as incoming parameters.

Finally, the method draws black orthogonal axes intersecting at the origin of the new coordinate frame on the off-screen image.

Beginning of the drawOffScreen method

The code for the method named drawOffScreen begins in Listing 14 . This method is called once in the constructor for the GUI class (see Listing 21 ) , and again each time the user clicks the Replot button shown in Image 2 .

The purpose of this method is to create some Vector objects and to cause visual manifestations of the Vector objects to be drawn onto an off-screen image.

17
Listing 14: Beginning of the drawOffScreen method.
  void drawOffScreen(Graphics2D g2D){
setCoordinateFrame(g2D,xOffset,yOffset);


The drawOffScreen method begins by calling the setCoordinateFrame method to establish a new coordinate frame using offset values entered by the user, (or default offset values of 0.0 at startup) .

Define a point to position the vectors

Listing 15 instantiates a new GM2D04.Point object that will be used to locate the three vectors that form the closed polygon shown in Image 2 . The location of the polygon relative to the world coordinate frame will remain the same regardless of how the current coordinate frame is changed.

18
Listing 15: Define a point to position the vectors.
    double startPointX = (196 - xOffset);
double startPointY = (165 - yOffset);
GM2D04.Point startPoint = new GM2D04.Point(
new GM2D04.ColMatrix(startPointX,startPointY));


The code in Listing 15 is probably the most important code in the entire program relative to the objective of the program. As I mentioned earlier, if you want the location of a point to remain the same relative to the world coordinate frame when you change the current coordinate frame, you must modify the values that represent that point whenever you cause the current coordinate frame to be different from the world coordinate frame. The code in Listing 15 makes that modification.

Remaining code in the drawOffScreen method

The remaining code in the drawOffScreen method is shown in Listing 16 .

19
Listing 16: Remaining code in the drawOffScreen method.
    //Instantiate three Vector objects that form a closed
double vecAx = 25;
double vecAy = 50;
GM2D04.Vector vecA = new GM2D04.Vector(
new GM2D04.ColMatrix(vecAx,vecAy));

double vecBx = 37;
double vecBy = -12;
GM2D04.Vector vecB = new GM2D04.Vector(
new GM2D04.ColMatrix(37,12));

//Define vecC as the sum of vecA and vecB. It will be
// of the correct length and direction to close the
// polygon when drawn such that its tail coincides
// with the tail of vecA.

//Draw vecA in red with its tail at startPoint.
g2D.setColor(Color.RED);
vecA.draw(g2D,startPoint);

//Compute the location of the head of vecA relative to
// the current coordinate frame.
vecA.getData(0) + startPoint.getData(0);
vecA.getData(1) + startPoint.getData(1);

//Draw vecB in GREEN with its tail at the head of
// vecA.
g2D.setColor(Color.GREEN);
vecB.draw(g2D,new GM2D04.Point(

//Draw vecC in BLUE with its tail at startPoint,
// coinciding with the tail of vecA. This forms a
// closed polygon.
g2D.setColor(Color.BLUE);
vecC.draw(g2D,startPoint);

}//end drawOffScreen


With one exception, there is nothing in Listing 16 that I haven't already explained in earlier programs in this or previous modules. Therefore, I won't repeat those explanations here.

The one exception

Recall from Image 2 that we need to draw the green vector with its tail located at the head of the red vector. In order to do that, we must be able to determine the location of the head of the red vector relative to the current coordinate frame.

The getData method of the Vector class knows nothing about position. That method simply returns the X and Y coordinate values that describe the length of the vector relative to its tail.

(For the special case where the tail is located at the origin, the getData method returns the X and Y coordinates of the head of the vector.)

However, because the tail of the red vector in this case is not necessarily located at the origin, we must calculate the position of the head of the red vector taking the position of its tail ( startPoint ) into account. The code in Listing 16 does just that.

That concludes the discussion of the program named CoordinateFrame01 .

Hopefully, you have been studying the Kjell tutorial as instructed in the section titled Homework assignment . This program illustrates the addition of two vectors using two different approaches that result in the parallelogram described by Kjell. That parallelogram is shown in the screen output in Image 4 .

The method named drawOffScreen

A complete listing of this program is provided in Listing 22 near the end of the module. Most of the new material is contained in the method named drawOffScreen . Therefore, I will limit my explanation to the method named drawOffScreen , which begins in Listing 17 .

21
Listing 17: Beginning of the method named drawOffScreen of the program named VectorAdd02.
  void drawOffScreen(Graphics2D g2D){

//Translate the origin to a position near the bottom-
// left corner of the off-screen image and draw a pair
// of orthogonal axes that intersect at the origin.
setCoordinateFrame(g2D);

//Define two vectors.
GM2D04.Vector vecA = new GM2D04.Vector(
new GM2D04.ColMatrix(50,-100));
GM2D04.Vector vecB = new GM2D04.Vector(
new GM2D04.ColMatrix(75,-25));

//Draw vecA in RED with its tail at the origin
g2D.setColor(Color.RED);
vecA.draw(g2D,new GM2D04.Point(
new GM2D04.ColMatrix(0,0)));

//Draw vecB in GREEN with its tail at the head of vecA
g2D.setColor(Color.GREEN);
vecB.draw(g2D,new GM2D04.Point(new GM2D04.ColMatrix(
vecA.getData(0),vecA.getData(1))));

//Define a third vector as the sum of the first
// two vectors defined above by adding vecB to vecA.

//Draw sumA in BLACK with its tail at the origin.
// green vecB.
g2D.setColor(Color.BLACK);
sumA.draw(g2D,new GM2D04.Point(
new GM2D04.ColMatrix(0.0,0.0)));


There is nothing new in Listing 17 . The code in Listing 17 produces the black vector in Image 4 plus the red and green vectors that appear above the black vector.

Do the same operations in a different order

Listing 18 begins by drawing the red and green vectors again. However, this time the green vector is drawn with its tail at the origin, and the red vector is drawn with its tail at the head of the green vector as shown by the green and red vectors below the black vector in Image 4 . This is perfectly legal because a vector has no location property. We can draw a vector anywhere we please provided we draw it with the correct length and direction.

22
Listing 18: Do the same operations in a different order.
    //Draw vecB in GREEN with its tail at the origin.
g2D.setColor(Color.GREEN);
vecB.draw(g2D,new GM2D04.Point(
new GM2D04.ColMatrix(0,0)));

//Draw vecA in RED with its tail at the head of vecB.
g2D.setColor(Color.RED);
vecA.draw(g2D,new GM2D04.Point(new GM2D04.ColMatrix(
vecB.getData(0),vecB.getData(1))));

//Define a fourth vector as the sum of the first
// two vectors defined above by adding vecA to vecB.

//Draw sumB in BLACK with its tail at the origin.
// red vecA, and the visual manifestation of sumB will
// overlay the visual manifestation of sumA
g2D.setColor(Color.BLACK);
sumB.draw(g2D,new GM2D04.Point(
new GM2D04.ColMatrix(0.0,0.0)));

}//end drawOffScreen


Then Listing 18 creates another vector by adding the red and green vectors and refers to the new vector as sumB . In the case of Listing 17, vecB is added to vecA to produce sumA . In Listing 18, vecA is added to vecB to produce sumB . In other words, the two addition operations are performed in reverse order in the two listings. As I have mentioned before, the order in which you add vectors doesn't matter. The result will be the same no matter the order in which you add them.

This is demonstrated in Listing 18 by drawing the vector referred to by sumB in black. As you can see in Image 4 , the drawing of sumB overlays the earlier drawing of sumA and you can't tell one from the other.

(You know that the length of the two vectors is the same because the little circles at the heads of the two vectors overlay one another. You know that the directions are the same because sumB completely covers sumA .)

That concludes the discussion of the program named VectorAdd02 .

This program illustrates the fact that the length of the sum of two vectors is not necessarily equal to the sum of the lengths of the two vectors.

Two vectors are added by the program. The length of the sum is much smaller than the length of either of the original vectors. This is shown in Image 5 where the red vector is added to the green vector producing the shorter black vector.

Command-line output

In addition to the graphic output shown in Image 5 , this program also produces three lines of text on the command-line screen as shown in Image 6 .

24
Image 6: Command-line output from the program named VectorAdd03.
Red length = 111.80339887498948
Green length = 115.43396380615195
Black length = 18.027756377319946


The text output on the command-line screen shows the length of each vector. As you can see in Image 6 , the length of the black vector is much less than the length of either the red vector or the blue vector.

Not much that is new

The only thing that is new in this program is the call to the new getLength method of the GM2D04.Vector class to compute and display the length of each vector in Image 6 .

The source code for the getLength method is shown in Listing 2 . This code computes the length of the vector as the square root of the sum of the squares of the X and Y components of the vector. Other than that code, there is no code in this program that warrants further explanation.

You can view a complete listing of the program in Listing 23 near the end of the module.

This program illustrates the addition of a Vector object to a Point object producing a new Point object. Both points and the vector are drawn on the screen as shown in Image 7 .

The only thing that is new in this program is the call to the new addVectorToPoint method of the GM2D04.Point class to add the vector to the point producing a new point.

The source code for the addVectorToPoint method is shown in Listing 3 . You can view a complete listing of the program in Listing 24 near the end of the module.

A very powerful capability

Don't be fooled by the apparent simplicity of the addVectorToPoint method. The ability to add a vector to a point provides a powerful new capability to the game-math library. As you will see in the next module, this capability makes it possible not only to translate geometrical objects from one location in space to another, but also makes it possible to animate geometrical objects.

## Documentation for the GM2D04 library

Click here to download a zip file containing standard javadoc documentation for the library named GM2D04 . Extract the contents of the zip file into an empty folder and open the file named index.html in your browser to view the documentation.

Although the documentation doesn't provide much in the way of explanatory text (see Listing 19 and the explanations given above) , the documentation does provide a good overview of the organization and structure of the library. You may find it helpful in that regard.

## Homework assignment

The homework assignment for this module was to study the Kjell tutorial through Chapter 3 - Vector Addition.

The homework assignment for the next module is to study the Kjell tutorial through Chapter 5 - Vector Direction .

In addition to studying the Kjell material, you should read at least the next two modules in this collection and bring your questions about that material to the next classroom session.

Finally, you should have begun studying the physics material at the beginning of the semester and you should continue studying one physics module per week thereafter. You should also feel free to bring your questions about that material to the classroom for discussion.

## Run the programs

I encourage you to copy the code from Listing 19 through Listing 24 . Compile the code and execute it in conjunction with the game-math library provided in Listing 19 . Experiment with the code, making changes, and observing the results of your changes. Make certain that you can explain why your changes behave as they do.

## Summary

In this module you learned

• How to add two or more vectors
• About the relationship between the length of the sum of vectors and the lengths of the individual vectors in the sum
• How to add a vector to a point
• How to get the length of a vector
• How to represent an object in different coordinate frames

## What's next?

In the next module you will learn how to use the game-math library for translation and animation in two dimensions.

## Miscellaneous

This section contains a variety of miscellaneous information.

### Note:

Housekeeping material
• Module name: GAME 2302-0125: Vector Addition
• File: Game0125.htm
• Published: 10/15/12
• Revised: 12/31/12

### Note:

Disclaimers:

Financial : Although the Connexions site makes it possible for you to download a PDF file for this module at no charge, and also makes it possible for you to purchase a pre-printed version of the PDF file, you should be aware that some of the HTML elements in this module may not translate well into PDF.

I also want you to know that, I receive no financial compensation from the Connexions website even if you purchase the PDF version of the module.

In the past, unknown individuals have copied my modules from cnx.org, converted them to Kindle books, and placed them for sale on Amazon.com showing me as the author. I neither receive compensation for those sales nor do I know who does receive compensation. If you purchase such a book, please be aware that it is a copy of a module that is freely available on cnx.org and that it was made and published without my prior knowledge.

Affiliation : I am a professor of Computer Information Technology at Austin Community College in Austin, TX.

## Complete program listings

Complete listings of the programs discussed in this module are shown in Listing 19 through Listing 24 below.

26
Listing 19: Source code for the game-math library named GM2D04.
/*GM2D04.java
Revised 02/08/08

The name GM2Dnn is an abbreviation for GameMath2Dnn.

See the file named GM2D01.java for a general description
of this game-math library file. This file is an update of
GM2D03.

This update added the following new capabilities:

object received as an incoming parameter and returns the
sum as a resultant Vector object.

Added a method named getLength that returns the length
of a vector as type double.

a Point producing a new Point.

Tested using JDK 1.6 under WinXP.
*********************************************************/
import java.awt.geom.*;
import java.awt.*;

public class GM2D04{

//An object of this class represents a 2D column matrix.
// An object of this class is the fundamental building
// block for several of the other classes in the
// library.
public static class ColMatrix{
double[] data = new double[2];

public ColMatrix(double data0,double data1){
data[0] = data0;
data[1] = data1;
}//end constructor
//--------------------------------------------------//

public String toString(){
return data[0] + "," + data[1];
}//end overridden toString method
//--------------------------------------------------//

public double getData(int index){
if((index < 0) || (index > 1)){
throw new IndexOutOfBoundsException();
}else{
return data[index];
}//end else
}//end getData method
//--------------------------------------------------//

public void setData(int index,double data){
if((index < 0) || (index > 1)){
throw new IndexOutOfBoundsException();
}else{
this.data[index] = data;
}//end else
}//end setData method
//--------------------------------------------------//

//This method overrides the equals method inherited
// from the class named Object. It compares the values
// stored in two matrices and returns true if the
// values are equal or almost equal and returns false
// otherwise.
public boolean equals(Object obj){
if(obj instanceof GM2D04.ColMatrix &&
Math.abs(((GM2D04.ColMatrix)obj).getData(0) -
getData(0)) <= 0.00001 &&
Math.abs(((GM2D04.ColMatrix)obj).getData(1) -
getData(1)) <= 0.00001){
return true;
}else{
return false;
}//end else

}//end overridden equals method
//--------------------------------------------------//

//Adds one ColMatrix object to another ColMatrix
// object, returning a ColMatrix object.
return new GM2D04.ColMatrix(
getData(0)+matrix.getData(0),
getData(1)+matrix.getData(1));
}//end subtract
//--------------------------------------------------//

//Subtracts one ColMatrix object from another
// ColMatrix object, returning a ColMatrix object. The
// object that is received as an incoming parameter
// is subtracted from the object on which the method
// is called.
public GM2D04.ColMatrix subtract(
GM2D04.ColMatrix matrix){
return new GM2D04.ColMatrix(
getData(0)-matrix.getData(0),
getData(1)-matrix.getData(1));
}//end subtract
//--------------------------------------------------//
}//end class ColMatrix
//====================================================//

public static class Point{
GM2D04.ColMatrix point;

public Point(GM2D04.ColMatrix point){//constructor
//Create and save a clone of the ColMatrix object
// used to define the point to prevent the point
// from being corrupted by a later change in the
// values stored in the original ColMatrix object
// through use of its set method.
this.point =
new ColMatrix(point.getData(0),point.getData(1));
}//end constructor
//--------------------------------------------------//

public String toString(){
return point.getData(0) + "," + point.getData(1);
}//end toString
//--------------------------------------------------//

public double getData(int index){
if((index < 0) || (index > 1)){
throw new IndexOutOfBoundsException();
}else{
return point.getData(index);
}//end else
}//end getData
//--------------------------------------------------//

public void setData(int index,double data){
if((index < 0) || (index > 1)){
throw new IndexOutOfBoundsException();
}else{
point.setData(index,data);
}//end else
}//end setData
//--------------------------------------------------//

//This method draws a small circle around the location
// of the point on the specified graphics context.
public void draw(Graphics2D g2D){
Ellipse2D.Double circle =
new Ellipse2D.Double(getData(0)-3,
getData(1)-3,
6,
6);
g2D.draw(circle);
}//end draw
//--------------------------------------------------//

//Returns a reference to the ColMatrix object that
// defines this Point object.
public GM2D04.ColMatrix getColMatrix(){
return point;
}//end getColMatrix
//--------------------------------------------------//

//This method overrides the equals method inherited
// from the class named Object. It compares the values
// stored in the ColMatrix objects that define two
// Point objects and returns true if they are equal
// and false otherwise.
public boolean equals(Object obj){
if(point.equals(((GM2D04.Point)obj).
getColMatrix())){
return true;
}else{
return false;
}//end else

}//end overridden equals method
//--------------------------------------------------//

//Gets a displacement vector from one Point object to
// a second Point object. The vector points from the
// object on which the method is called to the object
// passed as a parameter to the method. Kjell
// describes this as the distance you would have to
// walk along the x and then the y axes to get from
// the first point to the second point.
public GM2D04.Vector getDisplacementVector(
GM2D04.Point point){
return new GM2D04.Vector(new GM2D04.ColMatrix(
point.getData(0)-getData(0),
point.getData(1)-getData(1)));
}//end getDisplacementVector
//--------------------------------------------------//

//Adds a Vector to a Point producing a new Point.
GM2D04.Vector vec){
return new GM2D04.Point(new GM2D04.ColMatrix(
getData(0) + vec.getData(0),
getData(1) + vec.getData(1)));
//--------------------------------------------------//
}//end class Point
//====================================================//

public static class Vector{
GM2D04.ColMatrix vector;

public Vector(GM2D04.ColMatrix vector){//constructor
//Create and save a clone of the ColMatrix object
// used to define the vector to prevent the vector
// from being corrupted by a later change in the
// values stored in the original ColVector object.
this.vector = new ColMatrix(
vector.getData(0),vector.getData(1));
}//end constructor
//--------------------------------------------------//

public String toString(){
return vector.getData(0) + "," + vector.getData(1);
}//end toString
//--------------------------------------------------//

public double getData(int index){
if((index < 0) || (index > 1)){
throw new IndexOutOfBoundsException();
}else{
return vector.getData(index);
}//end else
}//end getData
//--------------------------------------------------//

public void setData(int index,double data){
if((index < 0) || (index > 1)){
throw new IndexOutOfBoundsException();
}else{
vector.setData(index,data);
}//end else
}//end setData
//--------------------------------------------------//

//This method draws a vector on the specified graphics
// context, with the tail of the vector located at a
// specified point, and with a small circle at the
public void draw(Graphics2D g2D,GM2D04.Point tail){
Line2D.Double line = new Line2D.Double(
tail.getData(0),
tail.getData(1),
tail.getData(0)+vector.getData(0),
tail.getData(1)+vector.getData(1));

//Draw a small circle to identify the head.
Ellipse2D.Double circle = new Ellipse2D.Double(
tail.getData(0)+vector.getData(0)-2,
tail.getData(1)+vector.getData(1)-2,
4,
4);
g2D.draw(circle);
g2D.draw(line);
}//end draw
//--------------------------------------------------//

//Returns a reference to the ColMatrix object that
// defines this Vector object.
public GM2D04.ColMatrix getColMatrix(){
return vector;
}//end getColMatrix
//--------------------------------------------------//

//This method overrides the equals method inherited
// from the class named Object. It compares the values
// stored in the ColMatrix objects that define two
// Vector objects and returns true if they are equal
// and false otherwise.
public boolean equals(Object obj){
if(vector.equals((
(GM2D04.Vector)obj).getColMatrix())){
return true;
}else{
return false;
}//end else

}//end overridden equals method
//--------------------------------------------------//

// parameter and returns the sum as a vector.
return new GM2D04.Vector(new ColMatrix(
vec.getData(0)+vector.getData(0),
vec.getData(1)+vector.getData(1)));
//--------------------------------------------------//

//Returns the length of a Vector object.
public double getLength(){
return Math.sqrt(
getData(0)*getData(0) + getData(1)*getData(1));
}//end getLength
//--------------------------------------------------//
}//end class Vector
//====================================================//

//A line is defined by two points. One is called the
// tail and the other is called the head.
public static class Line{
GM2D04.Point[] line = new GM2D04.Point[2];

//Create and save clones of the points used to
// define the line to prevent the line from being
// corrupted by a later change in the coordinate
// values of the points.
this.line[0] = new Point(new GM2D04.ColMatrix(
tail.getData(0),tail.getData(1)));
this.line[1] = new Point(new GM2D04.ColMatrix(
}//end constructor
//--------------------------------------------------//

public String toString(){
return "Tail = " + line[0].getData(0) + ","
+ line[0].getData(1) + "\nHead = "
+ line[1].getData(0) + ","
+ line[1].getData(1);
}//end toString
//--------------------------------------------------//

public GM2D04.Point getTail(){
return line[0];
}//end getTail
//--------------------------------------------------//

return line[1];
//--------------------------------------------------//

public void setTail(GM2D04.Point newPoint){
//Create and save a clone of the new point to
// prevent the line from being corrupted by a
// later change in the coordinate values of the
// point.
this.line[0] = new Point(new GM2D04.ColMatrix(
newPoint.getData(0),newPoint.getData(1)));
}//end setTail
//--------------------------------------------------//

//Create and save a clone of the new point to
// prevent the line from being corrupted by a
// later change in the coordinate values of the
// point.
this.line[1] = new Point(new GM2D04.ColMatrix(
newPoint.getData(0),newPoint.getData(1)));
//--------------------------------------------------//

public void draw(Graphics2D g2D){
Line2D.Double line = new Line2D.Double(
getTail().getData(0),
getTail().getData(1),
g2D.draw(line);
}//end draw
//--------------------------------------------------//
}//end class Line
//====================================================//

}//end class GM2D04
//======================================================//


.

27
Listing 20: Source code for the program named VectorAdd01.
/*VectorAdd01.java
Revised 02/10/08

This program illustrates the addition of two or more
vectors. It also illustrates the Head-to-Tail rule
described by Kjell.

Tested using JDK 1.6 under WinXP.
*********************************************************/
import java.awt.*;
import javax.swing.*;
import java.awt.geom.*;

public static void main(String[] args){
GUI guiObj = new GUI();
}//end main
//======================================================//

class GUI extends JFrame{
//Specify the horizontal and vertical size of a JFrame
// object.
int hSize = 275;
int vSize = 200;
Image osi;//an off-screen image
int osiWidth;//off-screen image width
int osiHeight;//off-screen image height
MyCanvas myCanvas;//a subclass of Canvas

GUI(){//constructor
//Set JFrame size, title, and close operation.
setSize(hSize,vSize);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

//Create a new drawing canvas and add it to the
// center of the JFrame.
myCanvas = new MyCanvas();

//This object must be visible before you can get an
// off-screen image.  It must also be visible before
// you can compute the size of the canvas.
setVisible(true);
osiWidth = myCanvas.getWidth();
osiHeight = myCanvas.getHeight();

//Create an off-screen image and get a graphics
// context on it.
osi = createImage(osiWidth,osiHeight);
Graphics2D g2D = (Graphics2D)(osi.getGraphics());

//Draw some graphical objects on the off-screen
// image that represent underlying data objects in
// 2D space.
drawOffScreen(g2D);

//Cause the overridden paint method belonging to
// myCanvas to be executed.
myCanvas.repaint();

}//end constructor
//----------------------------------------------------//

//The purpose of this method is to add some Vector
// objects and to cause visual manifestations of the raw
// Vector objects and the resultant Vector objects to be
// drawn onto an off-screen image.
void drawOffScreen(Graphics2D g2D){

//Translate the origin on the off-screen
// image and draw a pair of orthogonal axes on it.
setCoordinateFrame(g2D);

//Define two vectors.
GM2D04.Vector vecA = new GM2D04.Vector(
new GM2D04.ColMatrix(50,100));
GM2D04.Vector vecB = new GM2D04.Vector(
new GM2D04.ColMatrix(75,25));

//Define a third vector as the sum of the first
// two vectors defined above.

//Draw vecA in RED with its tail at the origin
g2D.setColor(Color.RED);
vecA.draw(g2D,new GM2D04.Point(
new GM2D04.ColMatrix(0,0)));

//Draw vecB in GREEN with its tail at the head of vecA
g2D.setColor(Color.GREEN);
vecB.draw(g2D,new GM2D04.Point(new GM2D04.ColMatrix(
vecA.getData(0),vecA.getData(1))));

//Draw sumOf2 in MAGENTA with its tail at the origin.
g2D.setColor(Color.MAGENTA);
sumOf2.draw(g2D,new GM2D04.Point(new GM2D04.ColMatrix(
0.0,0.0)));

//Now define another vector and add it to vecA and
// vecB.
GM2D04.Vector vecC = new GM2D04.Vector(
new GM2D04.ColMatrix(30,-150));

//Draw vecD in BLUE with its tail positioned at the
// sum of vecA and vecB
g2D.setColor(Color.BLUE);
vecC.draw(g2D,new GM2D04.Point(new GM2D04.ColMatrix(
sumOf2.getData(0),sumOf2.getData(1))));

//Define a vector as the sum of vecA, vecB, and vecC

//Draw sumOf3 in BLACK with its tail at the origin.
g2D.setColor(Color.BLACK);
sumOf3.draw(g2D,new GM2D04.Point(
new GM2D04.ColMatrix(0.0,0.0)));

}//end drawOffScreen
//----------------------------------------------------//

//This method is used to set the origin to a point near
// the upper-left corner of the off-screen image  and
// draw orthogonal axes on the off-screen image. There
// is no intention to perform mathematical operations on
// the axes, so they are drawn independently of the
// classes and methods in the game-math library using
// the simplest method available for drawing a line.
private void setCoordinateFrame(Graphics2D g2D){
//Translate the origin.
g2D.translate(0.2*osiWidth,0.2*osiHeight);

//Draw new X and Y-axes in default BLACK
g2D.drawLine(-(int)(0.2*osiWidth),0,
(int)(0.8*osiWidth),0);

g2D.drawLine(0,-(int)(0.2*osiHeight),
0,(int)(0.8*osiHeight));

}//end setCoordinateFrame method
//====================================================//

//This is an inner class of the GUI class.
class MyCanvas extends Canvas{
//Override the paint() method. This method will be
// called when the JFrame and the Canvas appear on the
// screen or when the repaint method is called on the
// Canvas object.
//The purpose of this method is to display the
// off-screen image on the screen.
public void paint(Graphics g){
g.drawImage(osi,0,0,this);
}//end overridden paint()

}//end inner class MyCanvas

}//end class GUI
//======================================================//


.

28
Listing 21: Source code for the program named CoordinateFrame01.
/*CoordinateFrame01.java
Revised 02/14/08

This program illustrates the relationship between the
coordinate frame and a geometric object described in that
coordinate frame.

A GUI allows the user to move the origin of the coordinate
frame. Proper mathematical corrections are made such that
a geometric object described in that coordinate frame
maintains its position relative to world coordinates even
when the coordinate frame is changed. This causes its
position relative to the coordinate frame to change.

Tested using JDK 1.6 under WinXP.
*********************************************************/
import java.awt.*;
import javax.swing.*;
import java.awt.geom.*;
import java.awt.event.*;

class CoordinateFrame01{
public static void main(String[] args){
GUI guiObj = new GUI();
}//end main
}//end controlling class CoordinateFrame01
//======================================================//

class GUI extends JFrame implements ActionListener{
//Specify the horizontal and vertical size of a JFrame
// object.
int hSize = 400;
int vSize = 400;
Image osi;//an off-screen image
int osiWidth;//off-screen image width
int osiHeight;//off-screen image height
MyCanvas myCanvas;//a subclass of Canvas

//The following offset values are applied to the width
// and the height of the off-screen image to modify the
// coordinate frame. They are used to store user input
// values.
double xOffsetFactor = 0.0;
double yOffsetFactor = 0.0;

//The following offset values are computed using the
// user-specified offset factor values.
double xOffset;
double yOffset;

Graphics2D g2D;//Off-screen graphics context.

//User input fields.
JTextField xOffsetField;
JTextField yOffsetField;
//----------------------------------------------------//

GUI(){//constructor
//Set JFrame size, title, and close operation.
setSize(hSize,vSize);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

//Create a new drawing canvas and add it to the
// center of the content pane.
myCanvas = new MyCanvas();
BorderLayout.CENTER,myCanvas);

//Create and populate a JPanel to be used as a user-
// input panel and add it to the SOUTH position on
// the content pane.
JPanel controlPanel = new JPanel();
xOffsetField = new JTextField("0.0",3);

yOffsetField = new JTextField("0.0",3);

JButton button = new JButton("Replot");
BorderLayout.SOUTH,controlPanel);

//Register this object as an action listener on the
// button.

//This object must be visible before you can get an
// off-screen image.  It must also be visible before
// you can compute the size of the canvas.
setVisible(true);

//Make the size of the off-screen image match the
// size of the canvas.
osiWidth = myCanvas.getWidth();
osiHeight = myCanvas.getHeight();

//Create an off-screen image and get a graphics
// context on it.
osi = createImage(osiWidth,osiHeight);
g2D = (Graphics2D)(osi.getGraphics());

//Create some underlying data objects in
// 2D space and draw visual manifestations of them.
drawOffScreen(g2D);

//Cause the overridden paint method belonging to
// myCanvas to be executed.
myCanvas.repaint();

}//end constructor
//----------------------------------------------------//

//The purpose of this method is to create some Vector
// objects and to cause visual manifestations of them to
// be drawn onto an off-screen image.
void drawOffScreen(Graphics2D g2D){

//Establish the current coordinate frame and prepare
// the off-screen image with axes, etc.
setCoordinateFrame(g2D,xOffset,yOffset);

//Define a Point that will be used to locate three
// vectors that form a closed polygon. The physical
// location of the polygon on the canvas (world)
// remains the same regardless of how the coordinate
// frame is changed.
double startPointX = (196 - xOffset);
double startPointY = (165 - yOffset);
GM2D04.Point startPoint = new GM2D04.Point(
new GM2D04.ColMatrix(startPointX,startPointY));

//Instantiate three Vector objects that form a closed
double vecAx = 25;
double vecAy = 50;
GM2D04.Vector vecA = new GM2D04.Vector(
new GM2D04.ColMatrix(vecAx,vecAy));

double vecBx = 37;
double vecBy = -12;
GM2D04.Vector vecB = new GM2D04.Vector(
new GM2D04.ColMatrix(37,12));

//Define vecC as the sum of vecA and vecB. It will be
// of the correct length and direction to close the
// polygon when drawn such that its tail coincides
// with the tail of vecA.

//Draw vecA in red with its tail at startPoint.
g2D.setColor(Color.RED);
vecA.draw(g2D,startPoint);

//Compute the location of the head of vecA relative to
// the current coordinate frame.
vecA.getData(0) + startPoint.getData(0);
vecA.getData(1) + startPoint.getData(1);

//Draw vecB in GREEN with its tail at the head of
// vecA.
g2D.setColor(Color.GREEN);
vecB.draw(g2D,new GM2D04.Point(

//Draw vecC in BLUE with its tail at startPoint,
// coinciding with the tail of vecA. This forms a
// closed polygon.
g2D.setColor(Color.BLUE);
vecC.draw(g2D,startPoint);

}//end drawOffScreen
//----------------------------------------------------//

//This method is used to set the coordinate frame of
// the off-screen image by setting the origin to the
// specified offset values relative to origin of the
// world. The origin of the world is the upper-left
// corner of the off-screen image.
//The method draws black orthogonal axes on the
// off-screen image.
//There is no intention to perform mathematical
// operations on the axes, so they are drawn
// independently of the classes and methods in the
// game-math library.
//The method paints the background white erasing
private void setCoordinateFrame(
Graphics2D g2D,double xOff,double yOff){

//Paint the background white
g2D.setColor(Color.WHITE);
g2D.fillRect(0,0,osiWidth,osiHeight);

//Translate the origin by the specified amount
g2D.translate((int)xOff,(int)yOff);

//Draw new X and Y-axes in BLACK
g2D.setColor(Color.BLACK);
g2D.drawLine(-(int)xOff,0,(int)(osiWidth-xOff),0);
g2D.drawLine(0,-(int)yOff,0,(int)((osiHeight-yOff)));

}//end setCoordinateFrame method
//----------------------------------------------------//

//This method must be defined because the class
// implements the ActionListener interface. Because an
// object of this class is registered as a listener on
// the button, this method is called each time the user
// presses the button.
public void actionPerformed(ActionEvent e){
//Reset the coordinate frame to world coordinates by
// reversing the most recent translation.
setCoordinateFrame(g2D,-xOffset,-yOffset);

//Compute new translation offsets based on user input.
xOffsetFactor =
Double.parseDouble(xOffsetField.getText());
yOffsetFactor =
Double.parseDouble(yOffsetField.getText());

xOffset = osiWidth*xOffsetFactor;
yOffset = osiHeight*yOffsetFactor;

//Draw a new off-screen image based on user inputs
// and copy it to the canvas. Note that the
// drawOffScreen method will call the
// setCoordinateFrame method again with the new
// offset values for the origin of the coordinate
// frame.
drawOffScreen(g2D);
myCanvas.repaint();
}//end actionPerformed
//====================================================//

//This is an inner class of the GUI class.
class MyCanvas extends Canvas{
//Override the paint() method. This method will be
// called when the JFrame and the Canvas appear on the
// screen or when the repaint method is called on the
// Canvas object.
//The purpose of this method is to display the
// off-screen image on the screen.
public void paint(Graphics g){
g.drawImage(osi,0,0,this);
}//end overridden paint()

}//end inner class MyCanvas

}//end class GUI
//======================================================//


.

29
Listing 22: Source code for the program named VectorAdd02.
/*VectorAdd02.java
Revised 02/14/08

This program illustrates the addition of two vectors using
two different approaches that result in the parallelogram
described by Kjell. It also illustrates the Head-to-Tail
rule described by Kjell.

Tested using JDK 1.6 under WinXP.
*********************************************************/
import java.awt.*;
import javax.swing.*;
import java.awt.geom.*;

public static void main(String[] args){
GUI guiObj = new GUI();
}//end main
//======================================================//

class GUI extends JFrame{
//Specify the horizontal and vertical size of a JFrame
// object.
int hSize = 225;
int vSize = 225;
Image osi;//an off-screen image
int osiWidth;//off-screen image width
int osiHeight;//off-screen image height
MyCanvas myCanvas;//a subclass of Canvas

GUI(){//constructor
//Set JFrame size, title, and close operation.
setSize(hSize,vSize);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

//Create a new drawing canvas and add it to the
// center of the JFrame.
myCanvas = new MyCanvas();

//This object must be visible before you can get an
// off-screen image.  It must also be visible before
// you can compute the size of the canvas.
setVisible(true);
osiWidth = myCanvas.getWidth();
osiHeight = myCanvas.getHeight();

//Create an off-screen image and get a graphics
// context on it.
osi = createImage(osiWidth,osiHeight);
Graphics2D g2D = (Graphics2D)(osi.getGraphics());

//Draw some graphical objects on the off-screen
// image that represent underlying data objects in
// 2D space.
drawOffScreen(g2D);

//Cause the overridden paint method belonging to
// myCanvas to be executed.
myCanvas.repaint();

}//end constructor
//----------------------------------------------------//

//The purpose of this method is to add some Vector
// objects and to cause visual manifestations of the raw
// Vector objects and the resultant Vector objects to be
// drawn onto an off-screen image.
void drawOffScreen(Graphics2D g2D){

//Translate the origin to a position near the bottom-
// left corner of the off-screen image and draw a pair
// of orthogonal axes that intersect at the origin.
setCoordinateFrame(g2D);

//Define two vectors.
GM2D04.Vector vecA = new GM2D04.Vector(
new GM2D04.ColMatrix(50,-100));
GM2D04.Vector vecB = new GM2D04.Vector(
new GM2D04.ColMatrix(75,-25));

//Draw vecA in RED with its tail at the origin
g2D.setColor(Color.RED);
vecA.draw(g2D,new GM2D04.Point(
new GM2D04.ColMatrix(0,0)));

//Draw vecB in GREEN with its tail at the head of vecA
g2D.setColor(Color.GREEN);
vecB.draw(g2D,new GM2D04.Point(new GM2D04.ColMatrix(
vecA.getData(0),vecA.getData(1))));

//Define a third vector as the sum of the first
// two vectors defined above by adding vecB to vecA.

//Draw sumA in BLACK with its tail at the origin.
// green vecB.
g2D.setColor(Color.BLACK);
sumA.draw(g2D,new GM2D04.Point(
new GM2D04.ColMatrix(0.0,0.0)));

//Do the same operations but in a different order.

//Draw vecB in GREEN with its tail at the origin.
g2D.setColor(Color.GREEN);
vecB.draw(g2D,new GM2D04.Point(
new GM2D04.ColMatrix(0,0)));

//Draw vecA in RED with its tail at the head of vecB.
g2D.setColor(Color.RED);
vecA.draw(g2D,new GM2D04.Point(new GM2D04.ColMatrix(
vecB.getData(0),vecB.getData(1))));

//Define a fourth vector as the sum of the first
// two vectors defined above by adding vecA to vecB.

//Draw sumB in BLACK with its tail at the origin.
// red vecA, and the visual manifestation of sumB will
// overlay the visual manifestation of sumA
g2D.setColor(Color.BLACK);
sumB.draw(g2D,new GM2D04.Point(
new GM2D04.ColMatrix(0.0,0.0)));

}//end drawOffScreen
//----------------------------------------------------//

//This method is used to set the origin of the
// off-screen image to a location near the lower-left
// corner and to draw orthogonal axes that intersect
// at the origin.
private void setCoordinateFrame(Graphics2D g2D){

//Translate the origin to a point near the lower-left
// corner of the off-screen image.
g2D.translate(0.2*osiWidth,0.8*osiHeight);

//Draw new X and Y-axes in default BLACK
g2D.drawLine(-(int)(0.2*osiWidth),0,
(int)(0.8*osiWidth),0);

g2D.drawLine(0,-(int)(0.8*osiHeight),
0,(int)(0.2*osiHeight));

}//end setCoordinateFrame method
//====================================================//

//This is an inner class of the GUI class.
class MyCanvas extends Canvas{
//Override the paint() method. This method will be
// called when the JFrame and the Canvas appear on the
// screen or when the repaint method is called on the
// Canvas object.
//The purpose of this method is to display the
// off-screen image on the screen.
public void paint(Graphics g){
g.drawImage(osi,0,0,this);
}//end overridden paint()

}//end inner class MyCanvas

}//end class GUI
//======================================================//


.

30
Listing 23: Source code for the program named VectorAdd03.
/*VectorAdd03.java
Revised 02/14/08

This program illustrates the fact that the length of the
sum of two vectors is not necessarily equal to the sum of
the lengths of the two vectors. Two vectors are added such
and the length of the sum is much smaller than the length
of either of the original vectors. The red and green
vectors shown in the screen output are added producing the
black vector. The lengths of all three vectors are
displayed on the command-line screen, demonstrating that
the length of the black vector is much less than the
length of either the red vector or the blue vector.

The only thing that is new in this program is the
getLength method of the GM2D04.Vector class.

Tested using JDK 1.6 under WinXP.
*********************************************************/
import java.awt.*;
import javax.swing.*;
import java.awt.geom.*;

public static void main(String[] args){
GUI guiObj = new GUI();
}//end main
//======================================================//

class GUI extends JFrame{
//Specify the horizontal and vertical size of a JFrame
// object.
int hSize = 225;
int vSize = 225;
Image osi;//an off-screen image
int osiWidth;//off-screen image width
int osiHeight;//off-screen image height
MyCanvas myCanvas;//a subclass of Canvas

GUI(){//constructor
//Set JFrame size, title, and close operation.
setSize(hSize,vSize);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

//Create a new drawing canvas and add it to the
// center of the JFrame.
myCanvas = new MyCanvas();

//This object must be visible before you can get an
// off-screen image.  It must also be visible before
// you can compute the size of the canvas.
setVisible(true);
osiWidth = myCanvas.getWidth();
osiHeight = myCanvas.getHeight();

//Create an off-screen image and get a graphics
// context on it.
osi = createImage(osiWidth,osiHeight);
Graphics2D g2D = (Graphics2D)(osi.getGraphics());

//Draw some graphical objects on the off-screen
// image that represent underlying data objects in
// 2D space.
drawOffScreen(g2D);

//Cause the overridden paint method belonging to
// myCanvas to be executed.
myCanvas.repaint();

}//end constructor
//----------------------------------------------------//

//The purpose of this method is to add some Vector
// objects and to cause visual manifestations of the raw
// Vector objects and the resultant Vector objects to be
// drawn onto an off-screen image.
void drawOffScreen(Graphics2D g2D){

//Translate the origin and draw a pair of orthogonal
// axes that intersect at the origin.
setCoordinateFrame(g2D);

//Define two vectors.
GM2D04.Vector vecA = new GM2D04.Vector(
new GM2D04.ColMatrix(50,-100));
GM2D04.Vector vecB = new GM2D04.Vector(
new GM2D04.ColMatrix(-35,110));

//Define a third vector as the sum of the first
// two vectors defined above.

//Draw vecA in RED with its tail at the origin
g2D.setColor(Color.RED);
vecA.draw(g2D,new GM2D04.Point(
new GM2D04.ColMatrix(0,0)));

//Draw vecB in GREEN with its tail at the head of vecA
g2D.setColor(Color.GREEN);
vecB.draw(g2D,new GM2D04.Point(new GM2D04.ColMatrix(
vecA.getData(0),vecA.getData(1))));

//Draw sumOf2 in BLACK with its tail at the origin.
g2D.setColor(Color.BLACK);
sumOf2.draw(g2D,new GM2D04.Point(new GM2D04.ColMatrix(
0.0,0.0)));

System.out.println(
"Red length = " + vecA.getLength());
System.out.println(
"Green length = " + vecB.getLength());
System.out.println(
"Black length = " + sumOf2.getLength());
}//end drawOffScreen
//----------------------------------------------------//

//This method is used to set the origin of the
// off-screen image and to draw orthogonal axes that
// intersect at the origin.
private void setCoordinateFrame(Graphics2D g2D){

//Translate the origin to a point near the lower-left
// corner of the off-screen image.
g2D.translate(0.2*osiWidth,0.8*osiHeight);

//Draw new X and Y-axes in default BLACK
g2D.drawLine(-(int)(0.2*osiWidth),0,
(int)(0.8*osiWidth),0);

g2D.drawLine(0,-(int)(0.8*osiHeight),
0,(int)(0.2*osiHeight));

}//end setCoordinateFrame method
//====================================================//

//This is an inner class of the GUI class.
class MyCanvas extends Canvas{
//Override the paint() method. This method will be
// called when the JFrame and the Canvas appear on the
// screen or when the repaint method is called on the
// Canvas object.
//The purpose of this method is to display the
// off-screen image on the screen.
public void paint(Graphics g){
g.drawImage(osi,0,0,this);
}//end overridden paint()

}//end inner class MyCanvas

}//end class GUI
//======================================================//


.

31
Listing 24: Source code for the program named VectorAdd04.
/*VectorAdd04.java
Revised 02/15/08

This program illustrates the addition of a Vector to a
Point producing a new Point. Both points and the vector
are drawn on the screen.

Tested using JDK 1.6 under WinXP.
*********************************************************/
import java.awt.*;
import javax.swing.*;
import java.awt.geom.*;

public static void main(String[] args){
GUI guiObj = new GUI();
}//end main
//======================================================//

class GUI extends JFrame{
//Specify the horizontal and vertical size of a JFrame
// object.
int hSize = 225;
int vSize = 225;
Image osi;//an off-screen image
int osiWidth;//off-screen image width
int osiHeight;//off-screen image height
MyCanvas myCanvas;//a subclass of Canvas

GUI(){//constructor
//Set JFrame size, title, and close operation.
setSize(hSize,vSize);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

//Create a new drawing canvas and add it to the
// center of the JFrame.
myCanvas = new MyCanvas();

//This object must be visible before you can get an
// off-screen image.  It must also be visible before
// you can compute the size of the canvas.
setVisible(true);
osiWidth = myCanvas.getWidth();
osiHeight = myCanvas.getHeight();

//Create an off-screen image and get a graphics
// context on it.
osi = createImage(osiWidth,osiHeight);
Graphics2D g2D = (Graphics2D)(osi.getGraphics());

//Draw some graphical objects on the off-screen
// image.
drawOffScreen(g2D);

//Cause the overridden paint method belonging to
// myCanvas to be executed.
myCanvas.repaint();

}//end constructor
//----------------------------------------------------//

//The purpose of this method is to add a Vector object
// to a Point object and to draw the result onto an
// off-screen image..
void drawOffScreen(Graphics2D g2D){

//Translate the origin on the off-screen
// image and draw a pair of orthogonal axes on it.
setCoordinateFrame(g2D);

//Define one point
GM2D04.Point point = new GM2D04.Point(
new GM2D04.ColMatrix(50,-25));

//Define one vector.
GM2D04.Vector vecA = new GM2D04.Vector(
new GM2D04.ColMatrix(25,-50));

//Add the Vector object to the Point object producing
// a new Point object

//Draw vecA in RED with its tail at the original
// point.
g2D.setColor(Color.RED);
vecA.draw(g2D,point);

//Draw the original point in GREEN.
g2D.setColor(Color.GREEN);
point.draw(g2D);

//Draw the new point in BLUE.
g2D.setColor(Color.BLUE);
newPoint.draw(g2D);

}//end drawOffScreen
//----------------------------------------------------//

//This method is used to set the origin of the
// off-screen image and to draw orthogonal axes on the
// off-screen image that intersect at the origin.
private void setCoordinateFrame(Graphics2D g2D){

//Translate the origin to a point near the lower-left
// corner of the off-screen image.
g2D.translate(0.2*osiWidth,0.8*osiHeight);

//Draw new X and Y-axes in default BLACK
g2D.drawLine(-(int)(0.2*osiWidth),0,
(int)(0.8*osiWidth),0);

g2D.drawLine(0,-(int)(0.8*osiHeight),
0,(int)(0.2*osiHeight));

}//end setCoordinateFrame method
//====================================================//

//This is an inner class of the GUI class.
class MyCanvas extends Canvas{
//Override the paint() method. This method will be
// called when the JFrame and the Canvas appear on the
// screen or when the repaint method is called on the
// Canvas object.
//The purpose of this method is to display the
// off-screen image on the screen.
public void paint(Graphics g){
g.drawImage(osi,0,0,this);
}//end overridden paint()

}//end inner class MyCanvas

}//end class GUI
//======================================================//


## Exercises

### Exercise 1

Using Java and the game-math library named GM2D04 , or using a different programming environment of your choice, write a program that creates twelve random values in the approximate range from -64 to +63. Use those values in pairs to define six mathematical vectors.

Draw the six vectors in a head-to-tail arrangement in alternating colors of green and blue with the tail of the first vector at the origin as shown in Image 8 .

Compute and draw the sum of the six vectors in red with the tail of the sum vector at the origin.

Cause the origin of your reference frame to be at the center of your drawing and draw the axes for a Cartesian coordinate system in the reference frame in black.

Cause the positive x direction to be to the right.

Cause the positive y direction be either up or down according to your choice.

Use a symbol of your choice to indicate the head of each vector.

Cause the program to display your name in some manner.

### Exercise 2

Using Java and the game-math library named GM2D04 , or using a different programming environment of your choice, write a program that creates four random values in the approximate range from -128 to +127. Use those values in pairs to define two mathematical vectors.

Create a third vector as the sum of the first two vectors.

Using red, green, and blue, draw the three vectors in a way that illustrates the parallelogram rule for vector addition as shown in Image 9 .

Cause the origin of your reference frame to be at the center of your drawing and draw the axes for a Cartesian coordinate system in the reference frame in black.

Cause the positive x direction to be to the right. Cause the positive y direction be either up or down according to your choice.

Use a symbol of your choice to indicate the head of each vector.

Cause the program to display your name in some manner.

Because of the random nature of the vectors, you may need to run your program more than once to open up the vector diagram and get a clear picture of the parallelogram rule for vector addition.

-end-

## Content actions

### Give feedback:

My Favorites (?)

'My Favorites' is a special kind of lens which you can use to bookmark modules and collections. 'My Favorites' can only be seen by you, and collections saved in 'My Favorites' can remember the last module you were on. You need an account to use 'My Favorites'.

| A lens I own (?)

#### Definition of a lens

##### Lenses

A lens is a custom view of the content in the repository. You can think of it as a fancy kind of list that will let you see content through the eyes of organizations and people you trust.

##### What is in a lens?

Lens makers point to materials (modules and collections), creating a guide that includes their own comments and descriptive tags about the content.

##### Who can create a lens?

Any individual member, a community, or a respected organization.

##### What are tags?

Tags are descriptors added by lens makers to help label content, attaching a vocabulary that is meaningful in the context of the lens.

| External bookmarks