# Connexions

You are here: Home » Content » GAME 2302-0110: Updating the Game Math Library for Graphics

### Recently Viewed

This feature requires Javascript to be enabled.

# GAME 2302-0110: Updating the Game Math Library for Graphics

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

Summary: Learn how to update the game-math library to provide new capabilities including the addition of graphics and set methods for column matrices, points, vectors, and lines. Also study sample programs that illustrate the use of the new capabilities and learn how to draw on off-screen images.

## 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 module, I presented and explained two sample programs and a sample game-programming math library named GM2D01 , which were intended to implement concepts from Kjell's tutorial in Java code.

The library named GM2D01 is purely mathematical. By that, I mean that the library doesn't provide any mechanism for rendering objects of the ColMatrix , Line , Point , or Vector classes in a visual graphics context. That capability will be added to the version that I will present in this module.

What you will learn

In this module, you will learn how to update the math library to provide a number of new capabilities including the addition of graphics and various set methods. You will also learn that the addition of set methods exposes certain vulnerabilities, and you will learn how to protect against those vulnerabilities. Finally, you will learn how to draw on off-screen images.

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

## General background information

So far, we have been dealing with column matrices, points, vectors, and lines. (We will get to other topics in future modules.)

What is a point?

According to Kjell, a point is simply a location in space. It has no width, depth, or height. Therefore, it cannot be seen by the human eye, which means that we can't draw a point on the computer screen. However, it is possible to draw an object on the computer screen that indicates the location of the point.

What do I mean by this?

Suppose you go out onto your driveway and establish that one corner of the driveway represents the origin in a rectangular Cartesian coordinate framework. Then you use measuring devices to identify a specific location on the driveway. You can point to that location with your finger, and others can see your finger, but they can't see the point. Once again, the point has no width, height, or depth, and therefore cannot be seen by the human eye.

Mark the point

What you can do, however, is to take a piece of chalk and draw a small circle around your finger. Then others can see the mark that you have drawn as an estimate of the location of the point. It is very important however to remember that the chalk mark is not the point. It is simply a visual object that indicates the location of the point to some degree of accuracy. The actual location of the point is a piece of underlying data . The chalk mark is a graphic object that you have invented to represent that underlying data in a visual way to a human observer.

Program output

Both of the sample programs that I will explain in this module will produce the same graphic screen output, which is shown in Image 1 .

The left image in Image 1 contains seven small circles. Each of those seven circles marks the location of a point in the 2D space of the image. However, those circles are not the points. The seven points consist solely of coordinate values and are not visible to the human eye. The seven circles are graphics objects that were placed there to mark the locations in space of the seven points. The points existed in the 2D space before the graphics objects were created, and would have existed even if I had not caused the circles to be drawn to mark the locations of the points.

What is a line segment?

This can be even more confusing. Kjell tells us that a line segment is the straight path between two points, and that it has no thickness. Since it has no thickness, a line cannot be seen by the human eye.

The left image in Image 1 contains six graphic objects that we are likely to call lines or line segments. True enough, those graphic objects mark the path taken by the lines that represent straight paths between the pairs of points whose locations are indicated by the circles. However, those graphic objects are not lines in the context of this discussion. Rather, they are simply graphic objects that were used to mark the paths of the lines in a visual way for the benefit of a human observer.

Why am I emphasizing this so heavily?

Shortly, you will see the changes that I made to the game-math library in preparation for this module. That library makes it possible for you to easily create and manipulate underlying data objects for column matrices, points, vectors, and lines. Those changes include the ability for points, lines, and vectors to create graphical objects that represent themselves and to display those graphical objects on a specified graphics context upon request.

The left image in Image 1 shows the manner in which GM2D02.Point objects and GM2D02.Line objects represent themselves on a graphics context.

The right image in Image 1 shows the manner in which GM2D02.Vector objects represent themselves on a graphics context.

It is very important to understand the difference between the objects that encapsulate the underlying data and the graphic objects that represent those objects for visible human consumption. Later on, we will be doing math using the underlying data objects. However, it is generally not possible to do math using the graphic objects shown in Image 1 .

Additional modifications that I made to the library for this module makes it is easy to modify the values encapsulated in one of the underlying data objects. However, once the graphical representation of one of those data objects is drawn on the graphics context, it is fairly difficult to modify, particularly if it overlaps another graphic object that you don't want to modify. The library does not provide that capability.

All Java parameters are passed to methods by value

Moving to a completely different topic, when you call out the name of a variable as a parameter to be passed to a method in Java, a copy of the contents of that variable is made and the copy is passed to the method. Code in the method can modify the copy but it cannot modify the contents of the original variable. This is typically referred to as passing parameters by value . (Despite what you may have read elsewhere, unlike C and C++, Java parameters are never passed by reference.)

However, Java supports both primitive variables and reference variables. Passing reference variables by value exposes some vulnerabilities in the original version of the library when set methods are added to the library. A complete explanation of this topic is beyond the scope of this module. However, I will show you how I modified the code in the library to protect against such vulnerabilities.

## Preview

I will explain the changes to the library in this module in conjunction with two programs that illustrate the impact of those changes. Both programs produce the screen output shown in Image 1 , but they do so in significantly different ways.

The primary topics to be discussed have to do with:

• Making it possible for the underlying data objects to represent themselves by drawing graphical objects on a specified 2D graphics context upon request.
• Making it possible to call set methods to modify the data encapsulated in the underlying data objects.
• Protecting the data from corruption due to certain vulnerabilities exposed by adding set methods to 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

Much of the code in the library remains unchanged. I explained that code in the previous module and I won't repeat that explanation in this module. Rather, in this module, I will concentrate on explaining the modifications that I made to the library.

### The game-programming library named GM2D02

A complete listing of the modified game-programming library named GM2D02 is provided in Listing 26 .

This library is an update of the earlier game-math library named GM2D01 . This update added the following new capabilities:

• Draw circles to represent GM2D02.Point objects.
• Draw visible lines to represent GM2D02.Line objects.
• Draw visible lines and circles to represent GM2D02.Vector objects.
• Call a setData method to change the values in a GM2D02.ColMatrix object.
• Call a setData method to change the values in a GM2D02.Point object.
• Call a setData method to change the values in a GM2D02.Vector object.
• Call a setHead method or a setTail method to change one of the points that defines a GM2D02.Line object.

Constructors were updated to ensure that existing points, vectors, and lines are not corrupted by using the new set methods to change the values in the ColMatrix and/or Point objects originally used to construct the points, vectors, and lines. The updated constructors create and save clones of the ColMatrix and/or Point objects originally used to define the Point , Vector , and/or Line objects.

I will explain the new code in the library in conjunction with the explanations of the programs named PointLine03 and PointLine04 .

### The program named PointLine03

A complete listing of the program named PointLine03 is provided in Listing 27 .

This program illustrates the use of draw methods that were added to the GM2D02 game-math library to produce visual manifestations of Point , Line , and Vector objects instantiated from classes in the game-math library. The program also illustrates drawing on off-screen images and then copying those images to a Canvas object in an overridden paint method.

As mentioned earlier, this program produces the screen output shown in Image 1 .

Beginning of the class named PointLine03 and the class named GUI

Listing 1 shows the beginning of the class named PointLine03 (including the main method) and the beginning of the class named GUI .

2
Listing 1: Beginning of the class named PointLine03 and the class named GUI.
class PointLine03{
public static void main(String[] args){
GUI guiObj = new GUI();
}//end main
}//end controlling class PointLine03
//======================================================//

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


The code in the main method instantiates an object of the GUI class. The code showing in the GUI class definition declares several instance variables, initializing some of them.

Beginning of the constructor for the GUI class

Listing 2 shows the beginning of the constructor for the GUI class.

3
Listing 2: Beginning of the constructor for the GUI class.
  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()/2;
osiHeight = myCanvas.getHeight();


The code in Listing 2 is straightforward and shouldn't require an explanation beyond the embedded comments.

Create two off-screen images

Here is where things begin to get interesting. Listing 3 creates two off-screen images and gets a graphics context on each of them.

4
Listing 3: Create two off-screen images.
    osiA = createImage(osiWidth,osiHeight);
Graphics2D g2Da = (Graphics2D)(osiA.getGraphics());

osiB = createImage(osiWidth,osiHeight);
Graphics2D g2Db = (Graphics2D)(osiB.getGraphics());


Java programs are not constrained to simply draw on the screen. It is possible to create an off-screen image, get a graphics context on it, and use methods of the Graphics and/or Graphics2D classes to draw on the off-screen image.

The off-screen image can then be used for a variety of purposes including:

• writing the image into a disk file.
• copying the image to a Canvas object for display on the screen.

Will copy off-screen images to the screen

In this program, we will copy each of the off-screen images to a Canvas object in a side-by-side format (see Image 1 ) and display the Canvas object on the content pane in a JFrame object.

While animation is not the purpose of using off-screen images in this program, such off-screen images are often used to produce clean animation. Code is executed to produce an off-screen image and then the entire image is copied to the screen in a single blast. This prevents the user from seeing the development of the image that might otherwise be visible if the code was executed to produce the image directly onto the screen.

The createImage method

There are seven different versions of the createImage method in the JDK 1.7 standard library. The version of the method used in this program is defined in the Component class and inherited into the JFrame class. According to the Sun documentation, this method creates an off-screen drawable image to be used for double buffering.

The two required parameters are width and height. If the image is later displayed on the screen, the units of width and height are measured in pixels. The values contained in the width and height parameters in Listing 3 were computed in Listing 2 . The width of each off-screen image is set to half the width of the canvas. The height of each off-screen image is set to the height of the canvas. This facilitates the display of the two images in the side-by-side format shown in Image 1 .

Also, according to the Sun documentation, the method returns "an off-screen drawable image, which can be used for double buffering. The return value may be null if the component is not displayable." The returned value is type Image .

The getGraphics method

There are eleven different versions of the getGraphics method in the JDK 1.7 standard library. The version of the method used in this program is defined in the Image class. This method is called on the Image object returned by the createImage method in Listing 3 .

According to the Sun documentation, this method creates a graphics context for drawing to an off-screen image. You will note that the reference to the graphics context was cast to type Graphics2D and saved in a reference variable of the type Graphics2D . I explained the relationship between the Graphics class and the Graphics2D class in an earlier module.

At this point, we have two off-screen image objects of type Image and we have a graphics context on each of them. This makes it possible to use the methods of the Graphics class and/or the methods of the Graphics2D class to draw on either of the off-screen images.

Remaining code in the constructor

Listing 4 shows the remainder of the constructor for the GUI class.

5
Listing 4: Remaining code in the constructor.
    drawOffscreen(g2Da,g2Db);

myCanvas.repaint();

}//end constructor


Listing 4 begins by calling the method named drawOffscreen to draw some points, lines, and vectors on the two off-screen images. Note that references to each of the two graphics contexts are passed as parameters to the drawOffscreen method.

Then Listing 4 calls the repaint method belonging to the MyCanvas object to cause the overridden paint method belonging to that object to be executed. Later, we will see that the overridden paint method copies the two off-screen images to the canvas in the side-by-side format shown in Image 1 causing the contents of those off-screen images to be displayed in a JFrame object.

Beginning of the drawOffscreen method

The beginning of the drawOffscreen method is shown in Listing 5 . The purpose of this method is to define points, lines, and vectors as underlying data objects and then to cause a visual manifestation of some of the points, lines, and vectors to be drawn onto the two off-screen images.

6
Listing 5: Beginning of the drawOffscreen method.
  void drawOffscreen(Graphics2D g2Da,Graphics2D g2Db){

//Draw a label on each off-screen image.
g2Da.drawString("Off-screen image A",
osiWidth/8,
osiHeight/8);
g2Db.drawString("Off-screen image B",
osiWidth/8,
osiHeight/8);


Before getting into the underlying data objects, however, Listing 5 calls the drawString method belonging to the Graphics class to draw the two text strings shown in Image 1 on the two off-screen images.

Instantiate four Line objects that will be used to draw borders

Listing 6 instantiates four GM2D02.Line objects that will ultimately be used to draw the borders around the left and right images shown in Image 1 .

7
Listing 6: Define four lines that will be used to draw borders.
    //First define four points that will be used to define
// the ends of the four lines.
GM2D02.Point upperLeftPoint = new GM2D02.Point(
new GM2D02.ColMatrix(1.0,1.0));
GM2D02.Point upperRightPoint = new GM2D02.Point(
new GM2D02.ColMatrix(osiWidth-1,1.0));
GM2D02.Point lowerRightPoint = new GM2D02.Point(
new GM2D02.ColMatrix(osiWidth-1,osiHeight-1));
GM2D02.Point lowerLeftPoint = new GM2D02.Point(
new GM2D02.ColMatrix(1.0,osiHeight-1));

//Now define the four lines based on the endpoints.
GM2D02.Line top = new GM2D02.Line(upperLeftPoint,
upperRightPoint);
GM2D02.Line rightSide = new GM2D02.Line(
upperRightPoint,
lowerRightPoint);
GM2D02.Line bottom = new GM2D02.Line(lowerLeftPoint,
lowerRightPoint);
GM2D02.Line leftSide = new GM2D02.Line(upperLeftPoint,
lowerLeftPoint);


Nothing new here

There is nothing in Listing 6 that is new relative to what you learned in the previous module. Listing 6 starts by defining four GM2D02.Point objects that will be used to define the ends of the line segments. References to these Point objects are passed to the constructor for the GM2D02.Line class to instantiate the four Line objects.

Note that the locations of the points, and hence the positions of the lines were one pixel away from the edges of the canvas towards the center of the canvas. These locations were chosen to ensure that the resulting visual manifestations of the lines would be visible on the canvas.

It is also extremely important to understand that the GM2D02.Point and GM2D02.Line objects instantiated in Listing 6 are not graphical objects. Rather, they are underlying data objects, which are suitable for use in mathematical operations.

Draw a visual manifestation of each line

Listing 7 calls the draw method of the GM2D02.Line class four times in succession for each off-screen image. Note that a reference to the off-screen image is passed as a parameter to the draw method each time the method is called on one of the GM2D02.Line objects.

8
Listing 7: Draw a visual manifestation of each line.
    //Now draw a visual manifestation of each line
// on g2Da.
top.draw(g2Da);
rightSide.draw(g2Da);
bottom.draw(g2Da);
leftSide.draw(g2Da);

//Now draw a visual manifestation of each of the same
// four lines on g2Db
top.draw(g2Db);
rightSide.draw(g2Db);
bottom.draw(g2Db);
leftSide.draw(g2Db);


As you will see shortly, each of these calls to the draw method causes an object of the standard Java Line2D.Double class to be rendered onto the specified off-screen image. When the off-screen image is ultimately copied to the canvas object by the overridden paint method, this produces a visual manifestation of the GM2D02.Line object.

Once again, however, it is very important to understand that the Line2D.Double object is a graphical object and the GM2D02.Line is an underlying data object. They are completely independent objects.

Also, it is important to understand that the Line2D.Double class is a member of the standard Java library, whereas the GM2D02.Line class is a member of my special game math library named GM2D02 .

The draw method of the GM2D02.Line class

Now it's time to explain one of the methods that was added to the original game-math library named GM2D01 to produce the new library named GM2D02 . At this point, I will start switching back and forth between code in the GM2D02 library and code in the program named PointLine03 .

Listing 8 shows the draw method that was called repeatedly on the GM2D02.Line objects in Listing 7 . This code belongs to the GM2D02 library.

9
Listing 8: The draw method of the GM2D02.Line class.
    public void draw(Graphics2D g2D){
Line2D.Double line = new Line2D.Double(
getTail().getData(0),
getTail().getData(1),
g2D.draw(line);
}//end draw


Construct and render a Line2D.Double object on the graphics context

Listing 8 calls the getTail and getHead methods to get the x and y coordinate values (relative to the current coordinate frame) that define the ends of the line segment represented by the GM2D02.Line object on which the draw method was called.

These four values are passed as parameters to the constructor for the Java standard Line2D.Double class to define the endpoints of a Line2D.Double object.

Then the draw method of the Graphics2D class is called on the reference to the incoming graphics context parameter to cause the Line2D.Double object to be rendered onto that graphics context.

In this case, that graphics context is an off-screen graphics context. However, it could just as easily be an on-screen graphics context such as the graphics context that is received as a parameter to an overridden paint method.

#### Note:

Two different draw methods are involved:

The code in my custom draw method, which is a member of my custom GM2D02.Line class, turns around and calls a completely different method named draw , which is a member of the standard Java Graphics2D class.

Hallmarks of object-oriented programming

An object of the GM2D02.Line class knows how to produce a visual manifestation of itself onto a specified graphics context as illustrated by the borders surrounding the left and right images in Image 1 .

This is one of the hallmarks of object-oriented programming. Objects know how to do useful things for themselves. Later on, we will see other hallmarks such as the ability of an object of the GM2D02.Vector class to add itself to another object of the same class and return a new vector object that is the sum of the two vectors.

Draw a visual manifestation of a GM2D02.Point object

Returning to the drawOffScreen method of the program named PointLine03 , Listing 9 begins by calling the translate method of the Graphics class on the off-screen image shown in the left side of Image 1 for the purpose of changing the origin from the upper-left corner of the graphics context to the center of the graphics context.

10
Listing 9: Draw a visual manifestation of a GM2D02.Point object.
    g2Da.translate(osiWidth/2.0,osiHeight/2.0);

GM2D02.Point origin = new GM2D02.Point(
new GM2D02.ColMatrix(0.0,0.0));
origin.draw(g2Da);


This is equivalent to changing the coordinate frame described by Kjell and discussed in the previous module.

Then the code in Listing 9 defines a GM2D02.Point object located at the origin of the new coordinate frame and calls the draw method on that object to produce the visual manifestation of the object in the center of the left image in Image 1 .

Once again, the GM2D02.Point object is an underlying data object. The visual manifestation will be produced by an object of the Java standard class named Ellipse2D.Double , which will be a completely independent object.

The draw method of the GM2D02.Point class

Listing 10 shows the draw method that was added to the GM2D02.Point class to produce the updated game-math library. This method draws a small circle around the location of the point on the specified graphics context.

11
Listing 10: The draw method of the GM2D02.Point class.
    public void draw(Graphics2D g2D){
Ellipse2D.Double circle =
new Ellipse2D.Double(getData(0)-3,
getData(1)-3,
6,
6);
g2D.draw(circle);
}//end draw


The logic behind this method is very similar to the logic that I explained relative to Listing 8 . The constructor for the Java standard Ellipse2D.Double class requires four incoming parameters that specify the coordinates of the upper-left corner of a rectangle followed by the width and the height of the rectangle. The new object of type Ellipse2D.Double represents an ellipse that is bounded by the four sides of the rectangle. If the rectangle is square, the ellipse becomes a circle.

(In this case, the rectangle is a 6x6 square, thus producing a circle with a diameter of six pixels.)

Listing 10 calls the draw method of the Graphics2D class to render the ellipse (circle) at the specified location on the graphics context specified by the incoming parameter. Thus the code in Listing 9 produces a visual manifestation of a point at the origin of the current coordinate frame. The visual manifestation consists of a small circle centered on the location of the point, resulting in the small circle at the center of the left image in Image 1 .

Draw the vertices of a hexagon

Returning once more to the drawOffScreen method of the program named PointLine03 , Listing 11 instantiates six GM2D02.Point objects that represent the vertices of a hexagon that is symmetrically located relative to the origin in the current coordinate frame

12
Listing 11: Draw the vertices of a hexagon.
    //First define three constants to make it easier to
// write the code.
final double aVal = osiWidth/4.0*0.5;
final double bVal = osiWidth/4.0*0.866;
final double cVal = osiWidth/4.0;
//Now define the points.
GM2D02.Point point0 = new GM2D02.Point(
new GM2D02.ColMatrix(cVal,0.0));
GM2D02.Point point1 = new GM2D02.Point(
new GM2D02.ColMatrix(aVal,bVal));
GM2D02.Point point2 = new GM2D02.Point(
new GM2D02.ColMatrix(-aVal,bVal));
GM2D02.Point point3 = new GM2D02.Point(
new GM2D02.ColMatrix(-cVal,0.0));
GM2D02.Point point4 = new GM2D02.Point(
new GM2D02.ColMatrix(-aVal,-bVal));
GM2D02.Point point5 = new GM2D02.Point(
new GM2D02.ColMatrix(aVal,-bVal));

//Now draw a visual manifestation of each of the six
// points on g2Da.
point0.draw(g2Da);
point1.draw(g2Da);
point2.draw(g2Da);
point3.draw(g2Da);
point4.draw(g2Da);
point5.draw(g2Da);


Then Listing 11 calls the draw method of the GM2D02.Point class six times in succession to cause small circles that represent the six points to be rendered on the specified off-screen image. You can see those six circles in the left image in Image 1 .

Draw six lines connecting the vertices of the hexagon

Listing 12 instantiates six objects of the GM2D02.Line class whose endpoints are specified by the six GM2D02.Point objects from Listing 11 , taken in pairs.

13
Listing 12: Draw six lines connecting the vertices of the hexagon.
    GM2D02.Line line01 = new GM2D02.Line(point0,point1);
GM2D02.Line line12 = new GM2D02.Line(point1,point2);
GM2D02.Line line23 = new GM2D02.Line(point2,point3);
GM2D02.Line line34 = new GM2D02.Line(point3,point4);
GM2D02.Line line45 = new GM2D02.Line(point4,point5);
GM2D02.Line line50 = new GM2D02.Line(point5,point0);

//Now draw a visual manifestation of each line
// on g2Da.
line01.draw(g2Da);
line12.draw(g2Da);
line23.draw(g2Da);
line34.draw(g2Da);
line45.draw(g2Da);
line50.draw(g2Da);

Then Listing 12 calls the draw method belonging to the GM2D02.Line class six times in succession to cause visible lines to be rendered on the specified off-screen image. You can see those six lines in the left image in Image 1 .

That completes the drawing that is performed on the off-screen image shown in the left image in Image 1 . Next I will explain the drawing that is performed on the off-screen image that is shown as the right image in Image 1 .

Instantiate three objects of type GM2D02.Vector

According to Kjell, "A vector is a geometrical object that has two properties: length and direction ." He also tells us, "A vector does not have a position."

The right image in Image 1 shows visual manifestations of three different objects of the GM2D02.Vector class. One vector is represented as a red line with a small red circle at its head. A second vector is represented as a blue line with a small blue circle at its head. The third vector is shown in three different positions represented by green lines with small green circles at their heads.

Listing 13 instantiates three objects of the GM2D02.Vector class, which are visually represented by the red, green, and blue lines in Image 1 . References to these three objects are saved in the variables named vecA , vecB , and vecC in Listing 13 .

14
Listing 13: Instantiate three objects of type GM2D02.Vector.
    GM2D02.Vector vecA = new GM2D02.Vector(
new GM2D02.ColMatrix(50,100));
GM2D02.Vector vecB = new GM2D02.Vector(
new GM2D02.ColMatrix(75,25));
GM2D02.Vector vecC = new GM2D02.Vector(
new GM2D02.ColMatrix(125,125));


Note that each vector is described by two values in a GM2D02.ColMatrix object.

Call the draw method to draw the vector

Listing 14 begins by setting the drawing color to red for the off-screen image on which the visual manifestation of the first Vector object will be drawn. Then Listing 14 calls the draw method of the GM2D02.Vector class to cause the object referred to by vecA to be represented as a (red) line with its tail at the origin. (Unlike the image on the left side of Image 1 , the origin for the image on the right was not translated to the center.)

15
Listing 14: Call the draw method to draw the vector.
    g2Db.setColor(Color.RED);

vecA.draw(g2Db,new GM2D02.Point(
new GM2D02.ColMatrix(0,0)));


Note that two parameter are passed to the draw method in Listing 14:

• A reference to the off-screen graphics context on which the visual manifestation of the vector will be drawn.
• A new object of the class GM2D02.Point that will be used to determine the position on the off-screen image in which the visual manifestation will appear.

Remember that according to Kjell, a vector doesn't have a position. Hence, there is nothing in the underlying data for a GM2D02.Vector object that specifies a position. In other words, the visual manifestation of a vector can be placed anywhere in space, and one placement is just as correct as the next. However, if you become heavily involved in the use of vectors, you will learn that certain placements may be preferable to others in some cases so as to better represent the problem being modeled by the use of vectors.

The draw method of the GM2D02.Vector class

Switching once again to the GM2D02 library, Listing 15 shows the draw method that was added to the GM2D02.Vector class. This method is a little longer than the draw methods that I explained earlier for points and lines. This is mainly because:

• it is necessary to deal with the issue of positioning the visual manifestation of the GM2D02.Vector object, and
• it is necessary to embellish the drawing to make it possible to visually determine which end is the tail and which end is the head.

This method renders a visual manifestation of a GM2D02.Vector on the specified graphics context, with the tail of the vector located at a point specified by the contents of a GM2D02.Point object. A small circle is drawn to visually identify the head of the vector.

16
Listing 15: The draw method of the GM2D02.Vector class.
    public void draw(Graphics2D g2D,GM2D02.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


Why a circle and not an arrowhead?

When we draw vectors, (particularly when drawing by hand) , we often draw a small arrowhead at the head of the vector. Remember, a vector has only two properties: length and direction . The arrowhead normally points in the direction indicated by the direction property. However, there is nothing magic about an arrowhead. Circles are much easier to draw with a computer than arrowheads. As long as you can identify the head of the vector, you can always determine the direction. Although I didn't give a lot of thought to optimization when developing this library, this is one case where I took the approach that is likely to consume the minimum amount of computational resources.

In Image 1 , the length of each of the lines in the right image indicates the length property of the respective vector, and the small circle indicates the head. The orientation relative to the current coordinate frame represents the direction .

Beyond that, further explanation of the code in Listing 15 should not be required.

Three visual manifestations of the same vector

Returning again to the drawOffScreen method of the program named PointLine03 , Listing 16 produces three visual manifestations at three different positions for the same Vector object referred to by the reference variable named vecB . All three of the visual manifestations are colored green in Image 1 .

17
Listing 16: Three visual manifestations of the same vector.
    g2Db.setColor(Color.GREEN);
vecB.draw(g2Db,new GM2D02.Point(new GM2D02.ColMatrix(
vecA.getData(0),vecA.getData(1))));
vecB.draw(g2Db,new GM2D02.Point(new GM2D02.ColMatrix(
vecA.getData(0)-10,vecA.getData(1)+15)));
vecB.draw(g2Db,new GM2D02.Point(new GM2D02.ColMatrix(
vecA.getData(0)+10,vecA.getData(1)-60)));


This is a perfectly legitimate thing to do since the underlying data encapsulated in the Vector object does not contain any information relating to the position of the visual manifestation.

In one visual manifestation, Listing 16 causes the tail of vecB to coincide with the head of vecA . This is one of those cases where drawing the vector in one position is preferable to drawing it in a different position. Later on when we get into the topic of vector addition, I will explain that one way to perform graphical addition of vectors is to position the vectors in a tail-to-head relationship as indicated by the red and green vectors in Image 1 . The sum of the vectors can then be determined graphically by drawing a line from the tail of the first vector to the head of the last vector as indicated by the blue line in Image 1 . The length of the sum (or resultant) vector is indicated by the length of that line, and the direction of the resultant vector is indicated by the orientation of that line.

A practical example

This is the solution to a classical problem in a freshman engineering class. Assume that a boat is traveling diagonally across a river with a strong current. Assume that the green vector in Image 1 represents the speed and direction of the current in the river. Assume that the red vector represents the speed and direction that the boat would travel if there were no current. Because of the effect of the current on the boat, the actual speed and direction of the boat will be given by the blue vector, which is different from the speed and direction indicated by the red vector. If the blue vector is pointing at the desired landing point on the other side of the river, everything is okay. Otherwise, the captain needs to change the speed and/or the direction of the boat to compensate for the effect of the current on the boat.

Draw the blue vector

Listing 17 produces the blue visual manifestation of the Vector object referred to by vecC as shown in Image 1 .

18
Listing 17: Draw the blue vector.
    g2Db.setColor(Color.BLUE);
vecC.draw(g2Db,new GM2D02.Point(
new GM2D02.ColMatrix(0,0)));

}//end drawOffscreen


Listing 17 also signals the end of the method named drawOffscreen .

The MyCanvas class and the overridden paint method

Listing 18 shows the entire inner class named MyCanvas including the overridden paint method belonging to that class.

19
Listing 18: The MyCanvas class and the overridden paint method.
  //This is an inner class of the GUI class.
class MyCanvas extends Canvas{
public void paint(Graphics g){
g.drawImage(osiA,0,0,this);
g.drawImage(osiB,this.getWidth()/2,0,this);
}//end overridden paint()

}//end inner class MyCanvas

}//end class GUI


The overridden paint 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 method is also called when some screen activity requires the JFrame to be redrawn (such as minimizing and then restoring the JFrame ) .

The purpose of the paint method in this program is to call the drawImage method twice in succession to draw the two off-screen images on the screen in the side-by-side format shown in Image 1 .

The first parameter to the drawImage method is the off-screen image that is to be drawn on the canvas. The second and third parameters specify the location where the upper-left corner of the image will be drawn.

The fourth parameter is a reference to an ImageObserver object, which is essentially a dummy image observer in this case, because an actual image observer isn't needed. (To learn more about image observers, see The AWT Package, Graphics- Introduction to Images .)

End of the program

Listing 18 also signals the end of the GUI class and the end of the program named PointLine03 ..

### The program named PointLine04

A complete listing of this program is provided in Listing 28 . Just like the previous program named PointLine03 , this program produces the screen output shown in Image 1 . However, it produces that output in a significantly different way.

This program emphasizes the differences between graphics objects and underlying data objects. It also illustrates the use of the new setData methods of the Point class and the Vector class, along with the new setTail and setHead methods of the Line class. These methods were added to the game-math library when it was updated to the GM2D02 version.

Dealing with some vulnerabilities

The addition of the new set methods exposed some vulnerabilities in the original version of the game-math library. I will explain how the code in the library was modified to deal with that issue. In particular, constructors were updated to ensure that existing points, vectors, and lines are not corrupted by using the new set methods to change the values in the ColMatrix and/or Point objects originally used to construct the points, vectors, and lines. The updated constructors create and save clones of the ColMatrix and/or Point objects originally used to define the Point , Vector , and/or Line objects.

Will explain the code in fragments

As before, I will explain the code in fragments. Some of the code in this program is identical to or very similar to code that I have already explained in the program named PointLine03 . I won't repeat that explanation. Instead, I will concentrate on the differences between the two programs.

The setData method of the ColMatrix class

The new setData method of the ColMatrix class is shown in Listing 19 . Note that this code is part of the GM2D02 library. At this point, I will begin switching back and forth between the library and the program named PointLine04 .

20
Listing 19: The setData method of the ColMatrix class.
    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 is a very simple method, which should not require further explanation. I am presenting it here mainly for the purpose of leading into a discussion of the vulnerabilities that this method could expose on Point and Vector objects instantiated from the original math class named GM2D01 ,

You may recall from the module titled Getting Started that the constructor for the Point class in the original library received and saved a reference to an object of the ColMatrix class that contained the two values required to define the Point . Now that it is possible to change the values stored in an object of the ColMatrix class, if such an object is used to instantiate an object of the Point class and then the values stored in the ColMatrix object are changed, the values that define the Point object will change accordingly. That is not good.

Updated constructor for the Point class in GM2D02

Continuing with code in the GM2D02 library, Listing 20 shows the updated constructor in the new version of the library.

21
Listing 20: Updated constructor for the Point class in GM2D02.
  public static class Point{
GM2D02.ColMatrix point;

Point(GM2D02.ColMatrix point){//constructor
this.point =
new ColMatrix(point.getData(0),point.getData(1));
}//end constructor


The new version of the constructor for the Point class creates and saves 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 the use of its new setData method.

Updated constructor for the Vector class in GM2D02

Because the constructor for the Vector class in the original library was essentially the same as the constructor for the Point class, the addition of the setData method to the ColMatrix class created the same vulnerability for objects instantiated from the Vector class. Essentially the same correction was made for the constructor for the Vector class. You can view the new code in Listing 26 .

In addition to the changes described above, the following changes were made to the game-math library to update it from version GM2D01 to GM2D02 . All of the changes were straightforward and shouldn't require an explanation beyond the embedded comments. You can view the new code for all of these changes in Listing 26 .

• Added a setData method for the Point class.
• Updated the constructor for the Line class to deal with the same kind of vulnerability described above.
• Added a setTail method for the Line class.

The drawOffscreen method of the program named PointLine04

Most of the differences between the programs named PointLine03 and PointLine04 occur in the method named drawOffscreen . I will concentrate my discussion there.

Switching now to code in the program named PointLine04 , the drawOffscreen method begins in Listing 21 .

22
Listing 21: The drawOffscreen method of the program named PointLine04.
  void drawOffscreen(Graphics2D g2Da,Graphics2D g2Db){

//Draw a label on each off-screen image.
g2Da.drawString("Off-screen image A",
osiWidth/8,
osiHeight/8);
g2Db.drawString("Off-screen image B",
osiWidth/8,
osiHeight/8);


As before, the purpose of the drawOffscreen method is to define points, lines, and vectors and then to cause a visual manifestation of some of the points, lines, and vectors to be drawn onto two separate off-screen images. Unlike before, however, this version of the method uses a minimum number of underlying data objects to produce the output, thereby emphasizing the differences between graphics objects and underlying data objects.

The code in Listing 21 is essentially the same as before and doesn't require any explanation.

Borders

As before, and as shown in Image 1 , this method draws borders on each of the off-screen images by drawing lines parallel to the edges of the off-screen images. Each line is offset by one pixel toward the center of the off-screen image.

Instantiate a point at the upper-left corner

Listing 22 instantiates and saves an underlying data object of type Point containing coordinate values for the upper left corner. This object will be used as one endpoint for a moveable Line object from which the top and left borders will be drawn.

23
Listing 22: Instantiate a point at the upper-left corner.
    GM2D02.Point upperLeftPoint = new GM2D02.Point(
new GM2D02.ColMatrix(1.0,1.0));


Instantiate a moveable Point object

Listing 23 instantiates a Point object that will be used as an endpoint for a moveable line in all four locations.

24
Listing 23: Instantiate a moveable Point object.
    GM2D02.Point aPoint = new GM2D02.Point(
new GM2D02.ColMatrix(osiWidth-1,
upperLeftPoint.getData(1)));


The location of this point will be modified several times during the drawing of the border by calling the setData method on the point. The initial location of this point is the upper-right corner. (Recall that the origin is at the upper-left corner of both off-screen images at this point in the program.) The call to the Point constructor causes the y-coordinate to be the same as the y-coordinate for the Point object instantiated in Listing 22 .

Instantiate a moveable Line object

Listing 24 instantiates a Line object that will be modified several times in succession by calling its setHead and setTail methods to place it in four different locations.

25
Listing 24: Instantiate a moveable Line object.
    GM2D02.Line theLine = new GM2D02.Line(
upperLeftPoint,aPoint);
theLine.draw(g2Da);
theLine.draw(g2Db);


This Line object will be used to draw the top, right, bottom, and left lines that make up the border. It is used in Listing 24 to cause a graphical Line2D.Double object to be instantiated and rendered as the line at the top of both of the off-screen images.

Relocate the Line to three more locations

Listing 25 calls various methods of the Point and Line classes (including setData , setTail , and setHead ) to relocate the GM2D02.Line object to three more locations, each parallel to an edge of an off-screen image.

26
Listing 25: Relocate the Line to three more locations.
    //Draw right border.
//Save the previous head as the new tail.
//Modify the location of aPoint. There's no need to
// change the x-coordinate. Just change the
// y-coordinate to move the point down the screen in
// the positive y direction to the lower-right corner.
aPoint.setData(1,osiHeight-1);
//Use the new location of aPoint as the new head.
theLine.draw(g2Da);
theLine.draw(g2Db);

//Draw bottom border. There's no need to change the
// y-coordinate in the new point, which is located
// at the lower-left corner.
aPoint.setData(0,1.0);
theLine.draw(g2Da);
theLine.draw(g2Db);

//Draw left border to close the rectangular border.
theLine.draw(g2Da);
theLine.draw(g2Db);


Draw the border

While the single GM2D02.Line object is at each location, draw methods are called to cause a Line2D.Double object to be instantiated and rendered on each of the off-screen images. This results in four different visual manifestations of the single GM2D02.Line object, producing visible lines at the edges of each off-screen image. Although this code is not particularly straightforward, the embedded comments should suffice to explain it.

Draw the hexagon

Essentially the same process is used to draw the hexagon shown in the left image in Image 1 . You can view the code that does that in Listing 28 . Once you understand the code that I explained above, you should have no difficulty understanding the code that draws the hexagon.

Draw the vectors

A very similar process is used to draw the vectors shown in the right image in Image 1 . You can view the code in Listing 28 . Once again, if you understand the code that I explained above, you should have no difficulty understanding the code that draws the vectors.

That ends the explanation of the program named PointLine04 .

## Documentation for the GM2D02 library

Click here to download a zip file containing standard javadoc documentation for the library named GM2D02 . 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 26 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

Your homework assignment for this module was to study Kjell's CHAPTER 0 -- Points and Lines plus CHAPTER 1 -- Vectors, Points, and Column Matrices down through the topic titled Variables as Elements .

The homework assignment for the next module is to study the Kjell tutorial through Chapter 2 -- Column and Row Matrix Addition .

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 26 , Listing 27 , and Listing 28 , compile it, and execute it. Experiment with it, 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 update the game-math library to provide a number of new capabilities including the addition of graphics to the library and the addition of set methods for column matrices, points, vectors, and lines.

You also saw sample programs that illustrate the use of those new capabilities and you learned how to draw on off-screen images.

## What's next?

In the next module, you will learn 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, and how to get a displacement vector from one point to another.

## Miscellaneous

This section contains a variety of miscellaneous information.

### Note:

Housekeeping material
• Module name: GAME2302-0110: Updating the Game Math Library for Graphics
• File: Game0110.htm
• Published: 10/14/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 26 through Listing 28 below.

27
Listing 26: Source code for the game-math library class named GM2D02.
/*GM2D02.java
Revised 02/03/08

The name GM2Dnn is an abbreviation for GameMath1Dnn.

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

This update added the following new capabilities:

Draw circles around points
Draw lines
Draw vectors
Call a set method to change the values in a
ColMatrix object.
Call a set method to change the values in a
Point object.
Call a set method to change the values in a
Vector object.
Call a set method to change one of the points
that defines a line.

Constructors were updated to ensure that existing points,
vectors, and lines are not corrupted by using the new
set methods to change the values in the ColMatrix and/or
Point objects originally used to construct the points,
vectors, and lines.

The updated constructors create and save clones of the
ColMatrix and/or Point objects originally used to define
the Point, Vector, and/or Line objects.

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

public class GM2D02{

//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];

ColMatrix(double data0,double data1){//constructor
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
//--------------------------------------------------//
}//end class ColMatrix
//====================================================//

public static class Point{
GM2D02.ColMatrix point;

Point(GM2D02.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
//--------------------------------------------------//
}//end class Point
//====================================================//

public static class Vector{
GM2D02.ColMatrix vector;

Vector(GM2D02.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 ColMatrix 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,GM2D02.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
//--------------------------------------------------//
}//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{
GM2D02.Point[] line = new GM2D02.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 GM2D02.ColMatrix(
tail.getData(0),tail.getData(1)));
this.line[1] = new Point(new GM2D02.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 GM2D02.Point getTail(){
return line[0];
}//end getTail
//--------------------------------------------------//

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

public void setTail(GM2D02.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 GM2D02.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 GM2D02.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 GM2D02


.

28
Listing 27: Source code for the program named PointLine03.
/*PointLine03.java
Revised 02/03/08

This program illustrates the use of draw methods that
were added to the GM2D02 game-math library to produce
visual manifestations of point, line, and vector objects
instantiated from classes in the game-math library
named GM2D02.

The program also illustrates drawing on off-screen images
and then copying those images to a Canvas object in an
overridden paint method.

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

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

class GUI extends JFrame{
//Specify the horizontal and vertical size of a JFrame
// object.
int hSize = 400;
int vSize = 200;
Image osiA;//one off-screen image
Image osiB;//another 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()/2;
osiHeight = myCanvas.getHeight();

//Create two off-screen images and get a graphics
// context on each.
osiA = createImage(osiWidth,osiHeight);
Graphics2D g2Da = (Graphics2D)(osiA.getGraphics());

osiB = createImage(osiWidth,osiHeight);
Graphics2D g2Db = (Graphics2D)(osiB.getGraphics());

//Draw some points, lines, and vectors on the two
// off-screen images.
drawOffscreen(g2Da,g2Db);

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

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

//The purpose of this method is to define points, lines,
// and vectors and then to cause a visual manifestation
// of some of the points, lines, and vectors to be
// drawn onto two separate off-screen images.
void drawOffscreen(Graphics2D g2Da,Graphics2D g2Db){

//Draw a label on each off-screen image.
g2Da.drawString("Off-screen image A",
osiWidth/8,
osiHeight/8);
g2Db.drawString("Off-screen image B",
osiWidth/8,
osiHeight/8);

//Define four lines that can be used to draw borders
// on each of the off-screen images.
//First define four points that will be used to define
// the ends of the four lines.
GM2D02.Point upperLeftPoint = new GM2D02.Point(
new GM2D02.ColMatrix(1.0,1.0));
GM2D02.Point upperRightPoint = new GM2D02.Point(
new GM2D02.ColMatrix(osiWidth-1,1.0));
GM2D02.Point lowerRightPoint = new GM2D02.Point(
new GM2D02.ColMatrix(osiWidth-1,osiHeight-1));
GM2D02.Point lowerLeftPoint = new GM2D02.Point(
new GM2D02.ColMatrix(1.0,osiHeight-1));

//Now define the four lines based on the endpoints..
GM2D02.Line top = new GM2D02.Line(upperLeftPoint,
upperRightPoint);
GM2D02.Line rightSide = new GM2D02.Line(
upperRightPoint,
lowerRightPoint);
GM2D02.Line bottom = new GM2D02.Line(lowerLeftPoint,
lowerRightPoint);
GM2D02.Line leftSide = new GM2D02.Line(upperLeftPoint,
lowerLeftPoint);

//Now draw a visual manifestation of each line
// on g2Da.
top.draw(g2Da);
rightSide.draw(g2Da);
bottom.draw(g2Da);
leftSide.draw(g2Da);

//Now draw a visual manifestation of each of the same
// four lines on g2Db
top.draw(g2Db);
rightSide.draw(g2Db);
bottom.draw(g2Db);
leftSide.draw(g2Db);

//Translate the origin of g2Da to the center of the
// off-screen image.
g2Da.translate(osiWidth/2.0,osiHeight/2.0);

//Define a point at the new origin and draw a visual
// manifestation of the point.
GM2D02.Point origin = new GM2D02.Point(
new GM2D02.ColMatrix(0.0,0.0));
origin.draw(g2Da);

//Define six points that define the vertices of a
// hexagon that is symmetrically located relative to
// the origin.  Begin at the right and move clockwise
// around the origin.
//First define three constants to make it easier to
// write the code.
final double aVal = osiWidth/4.0*0.5;
final double bVal = osiWidth/4.0*0.866;
final double cVal = osiWidth/4.0;
//Now define the points.
GM2D02.Point point0 = new GM2D02.Point(
new GM2D02.ColMatrix(cVal,0.0));
GM2D02.Point point1 = new GM2D02.Point(
new GM2D02.ColMatrix(aVal,bVal));
GM2D02.Point point2 = new GM2D02.Point(
new GM2D02.ColMatrix(-aVal,bVal));
GM2D02.Point point3 = new GM2D02.Point(
new GM2D02.ColMatrix(-cVal,0.0));
GM2D02.Point point4 = new GM2D02.Point(
new GM2D02.ColMatrix(-aVal,-bVal));
GM2D02.Point point5 = new GM2D02.Point(
new GM2D02.ColMatrix(aVal,-bVal));

//Now draw a visual manifestation of each of the six
// points on g2Da.
point0.draw(g2Da);
point1.draw(g2Da);
point2.draw(g2Da);
point3.draw(g2Da);
point4.draw(g2Da);
point5.draw(g2Da);

//Now define six lines using the six points taken in
// pairs to define the endpoints of the lines.
GM2D02.Line line01 = new GM2D02.Line(point0,point1);
GM2D02.Line line12 = new GM2D02.Line(point1,point2);
GM2D02.Line line23 = new GM2D02.Line(point2,point3);
GM2D02.Line line34 = new GM2D02.Line(point3,point4);
GM2D02.Line line45 = new GM2D02.Line(point4,point5);
GM2D02.Line line50 = new GM2D02.Line(point5,point0);

//Now draw a visual manifestation of each line
// on g2Da.
line01.draw(g2Da);
line12.draw(g2Da);
line23.draw(g2Da);
line34.draw(g2Da);
line45.draw(g2Da);
line50.draw(g2Da);

//Now define three vectors and draw visual
// manifestations of the vectors on g2Db.
GM2D02.Vector vecA = new GM2D02.Vector(
new GM2D02.ColMatrix(50,100));
GM2D02.Vector vecB = new GM2D02.Vector(
new GM2D02.ColMatrix(75,25));
GM2D02.Vector vecC = new GM2D02.Vector(
new GM2D02.ColMatrix(125,125));

//Draw vecA in red with its tail at the origin, which
// is still at the upper-left corner of the g2Db
// off-screen image
g2Db.setColor(Color.RED);
vecA.draw(g2Db,new GM2D02.Point(
new GM2D02.ColMatrix(0,0)));

//Draw three visual manifestations of vecB.  Cause
// the tail of vecB to coincide with the head of vecA
// in one of the three visual manifestations. Make all
// three of them green.
g2Db.setColor(Color.GREEN);
vecB.draw(g2Db,new GM2D02.Point(new GM2D02.ColMatrix(
vecA.getData(0),vecA.getData(1))));
vecB.draw(g2Db,new GM2D02.Point(new GM2D02.ColMatrix(
vecA.getData(0)-10,vecA.getData(1)+15)));
vecB.draw(g2Db,new GM2D02.Point(new GM2D02.ColMatrix(
vecA.getData(0)+10,vecA.getData(1)-60)));

//Draw vecC in blue with its tail at the origin.
g2Db.setColor(Color.BLUE);
vecC.draw(g2Db,new GM2D02.Point(
new GM2D02.ColMatrix(0,0)));

}//end drawOffscreen
//====================================================//

//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 two
// off-screen images on the screen in a side-by-side
// format.
public void paint(Graphics g){
g.drawImage(osiA,0,0,this);
g.drawImage(osiB,this.getWidth()/2,0,this);
}//end overridden paint()

}//end inner class MyCanvas

}//end class GUI


.

29
Listing 28: Source code for the program named PointLine04.
/*PointLine04.java
Revised 02/03/08

This program emphasizes the differences between graphics
objects and underlying data objects.  It also illustrates
the use of the new setData methods of the Point class and
the Vector class, along with the new setTail and setHead
methods of the Line class. The methods were added to the
game-math library when it was updated to the GM2D02
version.

This program produces the same graphic output as that
produced by PointLine03, but it produces that output in
a significantly different way.

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

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

class GUI extends JFrame{
//Specify the horizontal and vertical size of a JFrame
// object.
int hSize = 400;
int vSize = 200;
Image osiA;//one off-screen image
Image osiB;//another 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()/2;
osiHeight = myCanvas.getHeight();

//Create two off-screen images and get a graphics
// context on each.
osiA = createImage(osiWidth,osiHeight);
Graphics2D g2Da = (Graphics2D)(osiA.getGraphics());

osiB = createImage(osiWidth,osiHeight);
Graphics2D g2Db = (Graphics2D)(osiB.getGraphics());

//Draw some points, lines, and vectors on the two
// off-screen images.
drawOffscreen(g2Da,g2Db);

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

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

//The purpose of this method is to define points, lines,
// and vectors and then to cause a visual manifestation
// of some of the points, lines, and vectors to be
// drawn onto two separate off-screen images. The method
// uses a minimum number of underlying data objects to
// produce the output, thereby emphasizing the
// differences between graphics objects and underlying
// data objects.
void drawOffscreen(Graphics2D g2Da,Graphics2D g2Db){

//Draw a label on each off-screen image.
g2Da.drawString("Off-screen image A",
osiWidth/8,
osiHeight/8);
g2Db.drawString("Off-screen image B",
osiWidth/8,
osiHeight/8);

//Draw borders on each of the off-screen images by
// drawing lines parallel to the edges of the
// off-screen. Each line is offset by one pixel toward
// the center of the off-screen image.
//First define and save a point at the upper left
// corner that will be used as an endpoint of the
// top and left borders.
GM2D02.Point upperLeftPoint = new GM2D02.Point(
new GM2D02.ColMatrix(1.0,1.0));

//Define a point that will be used as an endpoint for
// all four lines. The location of this point will be
// modified several times during the drawing of the
// border by calling the set method on the point. The
// initial location of this point is the upper-right
// corner. Remember, the origin is at the upper-left
// corner of the off-screen images at this point in
// the program. Make the y-coordinate the same as the
// y-coordinate for the upperLeftPoint.
GM2D02.Point aPoint = new GM2D02.Point(
new GM2D02.ColMatrix(osiWidth-1,
upperLeftPoint.getData(1)));

//Define a line that will be modified several times in
// succession by calling its set methods to draw the
// top, right, bottom, and left lines that make up the
// border. Use it here to draw the line at the top
// of both of the off-screen images.
GM2D02.Line theLine = new GM2D02.Line(
upperLeftPoint,aPoint);
theLine.draw(g2Da);
theLine.draw(g2Db);

//Draw right border.
//Save the previous head as the new tail.
//Modify the location of aPoint. There's no need to
// change the x-coordinate. Just change the
// y-coordinate to move the point down the screen in
// the positive y direction to the lower-right corner.
aPoint.setData(1,osiHeight-1);
//Use the new location of aPoint as the new head.
theLine.draw(g2Da);
theLine.draw(g2Db);

//Draw bottom border. There's no need to change the
// y-coordinate in the new point, which is located
// at the lower-left corner.
aPoint.setData(0,1.0);
theLine.draw(g2Da);
theLine.draw(g2Db);

//Draw left border to close the rectangular border.
theLine.draw(g2Da);
theLine.draw(g2Db);

//Translate the origin of g2Da to the center of the
// off-screen image.
g2Da.translate(osiWidth/2.0,osiHeight/2.0);

//Define a point at the new origin and draw a visual
// manifestation of the point.
GM2D02.Point origin = new GM2D02.Point(
new GM2D02.ColMatrix(0.0,0.0));
origin.draw(g2Da);

//Define two points and one line and use them to
// define and draw a hexagon that is symmetrically
// located relative to the origin.  Begin at the right
// and move clockwise around the origin.

//First establish three constants to make it easier
// to write the code.
final double aVal = osiWidth/4.0*0.5;
final double bVal = osiWidth/4.0*0.866;
final double cVal = osiWidth/4.0;

//The coordinates of the following point are modified
// several times in succession to define the vertices
// of the hexagon.  Instantiate the point and draw it.
GM2D02.Point thePoint = new GM2D02.Point(
new GM2D02.ColMatrix(cVal,0.0));
thePoint.draw(g2Da);

//Save a clone of thePoint to be used to draw the
// first line and the last line that closes the
// hexagon.
GM2D02.Point startAndEndPoint = new GM2D02.Point(
new GM2D02.ColMatrix(
thePoint.getData(0),thePoint.getData(1)));

//Now call the set method twice to modify the location
// of thePoint, Draw thePoint, and use it to
// instantiate and draw a line from the starting
// location to the new location.
thePoint.setData(0,aVal);
thePoint.setData(1,bVal);
thePoint.draw(g2Da);
GM2D02.Line aLine = new GM2D02.Line(
startAndEndPoint,thePoint);
aLine.draw(g2Da);

//Repeat the process four more times using
// startAndEndPoint, thePoint, and aLine to draw the
// remaining vertices and lines.
//Modify aLine, saving the previous head as the new
// tail.
//Modify the location of aPoint and draw it. There's
// no need to change the y-coordinate of the point.
thePoint.setData(0,-aVal);
thePoint.draw(g2Da);
//Modify the endpoint of aLine and draw it.
aLine.draw(g2Da);

thePoint.setData(0,-cVal);
thePoint.setData(1,0.0);
thePoint.draw(g2Da);
aLine.draw(g2Da);

thePoint.setData(0,-aVal);
thePoint.setData(1,-bVal);
thePoint.draw(g2Da);
aLine.draw(g2Da);

thePoint.setData(0,aVal);
//No need to change the y-coordinate.
thePoint.draw(g2Da);
aLine.draw(g2Da);

//Now modify and draw aLine to close the hexagon.
aLine.draw(g2Da);

//Now define a vector, call the set method to modify
// it several times, and draw different visual
// manifestations of the vector on g2Db.
//First define two constants to make it easier to
// write the code.
final double firstTail = 50;

GM2D02.Vector vec = new GM2D02.Vector(
//Draw vec in red with its tail at the origin, which
// is still at the upper-left corner of the g2Db
// off-screen image
g2Db.setColor(Color.RED);
vec.draw(g2Db,new GM2D02.Point(
new GM2D02.ColMatrix(0,0)));

//Call the set method to modify vec.
vec.setData(0,75);
vec.setData(1,25);
//Draw three visual manifestations of vec.  Cause
// the tail to coincide with the head of the previous
// visual manifestation of vec in one of the three new
// visual manifestations. Make all three of them
// green.
g2Db.setColor(Color.GREEN);
vec.draw(g2Db,new GM2D02.Point(new GM2D02.ColMatrix(
vec.draw(g2Db,new GM2D02.Point(new GM2D02.ColMatrix(
vec.draw(g2Db,new GM2D02.Point(new GM2D02.ColMatrix(

//Call the set method to modify vec again.
vec.setData(0,125);
vec.setData(1,125);

//Draw the modified vec in blue with its tail at the
// origin.
g2Db.setColor(Color.BLUE);
vec.draw(g2Db,new GM2D02.Point(
new GM2D02.ColMatrix(0,0)));

}//end drawOffScreen
//====================================================//

//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 two
// off-screen images on the screen in a side-by-side
// format.
public void paint(Graphics g){
g.drawImage(osiA,0,0,this);
g.drawImage(osiB,this.getWidth()/2,0,this);
}//end overridden paint()

}//end inner class MyCanvas

}//end class GUI


## Exercises

### Exercise 1

Using Java and the game-math library named GM2D02 , or using a different programming environment of your choice, write a program that draws a horizontal line segment and a vertical line segment representing the x and y axes in a 2D Cartesian coordinate system as shown in Image 2 .

Cause the origin of your reference frame be at the center of your drawing.

Cause the positive x direction be to the right.

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

Cause the program to display your name in some manner.

### Exercise 2

Using Java and the game-math library named GM2D02 , or using a different programming environment of your choice, write a program that draws x and y axes in a 2D Cartesian coordinate system as shown in Image 3 .

Cause the origin of your reference frame be at the center of your drawing.

Cause the positive x direction be to the right.

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

Then draw small circles that represent the locations of points at the following coordinates in the reference frame as shown in Image 3 .

• x = -30, y = -40
• x = 30, y = -40
• x = 30, y = 40

Cause the program to display your name in some manner.

### Exercise 3

Using Java and the game-math library named GM2D02 , or using a different programming environment of your choice, write a program that draws x and y axes in a 2D Cartesian coordinate system as shown in Image 4 .

Cause the origin of your reference frame be at the center of your drawing.

Cause the positive x direction be to the right.

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

Create six random values in the range from -128 to +127. Use those values as the x and y coordinates for three points in the 2D reference frame. (The code fragment in Listing 29 shows how to generate random values in the required range in Java.)

Display the six values on a text screen labeled in such a way that it is possible to associate the values with the points as shown in Image 5 .

Draw three small circles that represent the locations of the points.

Draw three line segments that connect the three points in pairs creating the shape of a triangle.

Cause the program to display your name in some manner.

.

33
Image 5: Text output from Exercise 3.

point0X: -55
point0Y: 17
point1X: 9
point1Y: -37
point2X: 14
point2Y: 62

.

34
Listing 29: Code for generating random values in Java.

//Define three randomly located points.
Random generator = new Random(new Date().getTime());
point0X = (byte)generator.nextInt();
point0Y = (byte)generator.nextInt();
point1X = (byte)generator.nextInt();
point1Y = (byte)generator.nextInt();
point2X = (byte)generator.nextInt();
point2Y = (byte)generator.nextInt();


### Exercise 4

Using Java and the game-math library named GM2D02 , or using a different programming environment of your choice, write a program that draws three small circles that represent the locations of points at the following coordinates in a 2D reference frame.

• point0X = -30
• point0Y = 0
• point1X = 30
• point1Y = 40
• point2X = 30
• point2Y = -40

Then draw three line segments that extend from edge-to-edge of your drawing and intersect the three points in pairs as shown in Image 6 .

Cause the origin of your reference frame be at the center of your drawing.

Cause the positive x direction to be to the right.

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

Cause the program to display your name in some manner.

### Exercise 5

Using Java and the game-math library named GM2D02 , or using a different programming environment of your choice, write a program that draws 24 vectors tail-to-tail in alternating colors of red, green, and blue as shown in Image 7 .

The first vector is red.

The length of each vector is 100 pixels.

The direction of the first vector is +7.5 degrees relative to the horizontal.

The direction of each successive vector is increased by 15 degrees.

For example, the directions of the first four vectors are:

• 7.5
• 22.5
• 37.5
• 52.5

Draw the symbol of your choice to identify the head of each vector.

Draw the axes for a Cartesian coordinate system in the reference frame.

Cause the positive x direction to be to the right.

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

Cause positive angles to be either clockwise or counter-clockwise according to your choice.

Cause the program to display your name in some manner.

### Exercise 6

Using Java and the game-math library named GM2D02 , or using a different programming environment of your choice, write a program that draws 24 vectors tail-to-head in alternating colors of red, green, and blue as shown in Image 8 .

The first vector is red.

The length of each vector is approximately 17 pixels.

Draw the symbol of your choice to identify the head of each vector.

Draw the axes for a Cartesian coordinate system in the reference frame.

Cause the positive x direction to be to the right.

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

Cause positive angles to be either clockwise or counter-clockwise according to your choice.

Cause the program to display your name in some manner.

### Exercise 7

Using Java and the game-math library named GM2D02 , or using a different programming environment of your choice, write a program that draws 24 vectors tail-to-head in alternating colors of red, green, and blue as shown in Image 9 .

The first vector is red.

Begin with a length of 24 pixels for the first vector and reduce the length of each successive vector by one pixel.

Draw the symbol of your choice to identify the head of each vector.

Draw the axes for a Cartesian coordinate system in the reference frame.

Cause the positive x direction to be to the right.

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

Cause positive angles to be either clockwise or counter-clockwise according to your choice.

Cause the program to display your name in some manner.

-end-

## Content actions

PDF | EPUB (?)

### What is an EPUB file?

EPUB is an electronic book format that can be read on a variety of mobile devices.

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