Homework 2 Hints

1. Thermometer Application:

For each of the 3 views and the temperature control slider, you can specify the position by using

setLocation(x,y);

This will allow you to space out the windows so they won't be on top of each other upon running your code.

1. b. Use an Area object to create the filled bulb and stem:

You actually won't use fillOval or fillRect. You will create Area objects for each of the stem and bulb, then take their union and display the Area resulting from that union. The pseudocode might be something like:

create a 2D rectangle object for the stem, passing in x, y, width, height
create a 2D ellipse object for the bulb, passing in x, y, width, height
create an area object for the stem, passing in the 2D rectangle for stem
create an area object for the bulb, passing in the 2D ellipse for bulb
augment the stem area by adding the bulb area to it as in
  stemarea.add(bulbarea);
display the augmented stem area with fill()

Of course, you'll have to specify what x, y, width, and height are. When I say "passing in", I mean passing in to the constructor for the respective graphics class (rectangle, ellipse, area).

You can use a similar technique for part 4 of the homework.

Be sure to use Graphics2D by adding

Graphics2D g2 = (Graphics2D)g;

to the beginning of paintComponent() and use g2 for all the drawing.

Be sure "import java.awt.geom.*;" is at the top of the code file.

1.c.a. Gauge view with arrow:

To get a chorded half oval, you can draw an Arc2D.Double, where its arguments are x, y, width, height, 0, 180, and Arc2D.CHORD.

Drawing the line and arrow (needle):

This is my way of doing it, which will mean that Brad's equations need to be altered slightly, as I will point out later. Given the tail point of the needle (the center of the oval) (P1), the length of the needle line, and the angle, I will derive the point at the tip (P2).

It is acceptable to use a fixed needle length, you don't have to adjust the length to fit perfectly in the oval.

To calculate dx and dy:

dx = needlelength*cos(angle)
dy = needlelength*sin(angle)

needlelength is line_length in Brad's equations.

angle is computed based on the current temperature. Be sure to convert the angle to RADIANS when using Math.sin and Math.cos.

Given P1 (x1 and y1), then to calculate the point at the tip, P2:

x2 = x1 + dx
y2 = y1 - dy

You can now simply draw a line, passing in x1, y1, x2, and y2. This will be the needle line (without the arrow head).

Then to get the arrow:

normdx = dx/needlelength
normdy = dy/needlelength

Choose a suitable arrowlength and arrowwidth.

Then calculate the endpoints of the arrow with these equations:

arrowx1 = x2 - arrowlength * normdx - arrowwidth * normdy
arrowy1 = y2 + arrowlength * normdy - arrowwidth * normdx
arrowx2 = x2 - arrowlength * normdx + arrowwidth * normdy
arrowy2 = y2 + arrowlength * normdy + arrowwidth * normdx

Note the 4 highlighted + and - signs in the equations for arrowy1 and arrowy2 that are flipped from what they were in Brad's equations.

Now create an array of xpoints and an array of ypoints. The first point is (arrowx1, arrowy1), the second is (x2, y2), and the third is (arrowx2, arrowy2).

Call both drawPolygon and fillPolygon, passing in xpoints, ypoints, and the number of points (3). Calling both functions will make the arrowhead look a little nicer.

1.c.b. Filled pie arc view:

Be sure the amount to fill the arc is based on 360 degrees, and not 180 degrees.

Temperature controller code:

The two arguments to pass in are the model variable and new JFrame().

The slider code has a good example of how to integrate the controller code with the rest of your thermometer code. In particular, the parts about observers, setValue() in SliderModel.java and valueChanged() in SliderGraphicalView.java and Slider.java. The slider code can be found here:

http://www.cs.utk.edu/~bvz/gui/notes/javaGraphics/index.html

2. DisplayImage:

There is a good example of code that displays an image at:

http://www.cs.utk.edu/~bvz/gui/notes/javaGraphics/index.html

Of course, after drawing the image, you will need to add code to write the caption under it. You can use the same technique as in the thermometer code for HW 1. To center the text underneath the image, the starting position of the text will be based on the width and height of the image.

3. DisplayTile:

There is a code example in the lecture notes at:

http://www.cs.utk.edu/~bvz/gui/notes/texture.java

It shows how to create a buffered image and a TexturePaint object.

After the code for creating an ImageIcon from the image, and before creating a buffered image, add the code for scaling the image. First use getScaledInstance() of the Image class to get a scaled version of the image. The third argument can just be a 1. After this, create an ImageIcon from the scaled image with

Image scaledimage2 = new ImageIcon(scaledimage).getImage()

where scaledimage is the image resulting from getScaledInstance(). If you don't include the above line of code, the image will not display on the Ubuntu machines.

Also, on the Ubuntu machines, if your window size is the same size as the rectangle (210x50), the image tiling will not fill the entire window. Don't worry about this, it is an issue with Java, not your code.

4. Composite object using Area class:

Use the technique outlined in 1.b., which discusses creating the stem and bulb of the thermometer. There are a couple ways you can do this. One way is to keep augmenting the same Area object with successive intersections, unions, xors, or differences of other Area objects and draw the entire object at the end. However, if you want different parts to be different colors, this won't work, as it will draw the entire object in the most recently set color. If you want to use different colors, then you can draw portions of the object in increments, and change colors inbetween. Either way is acceptable. A good example that displays a pear is at

http://java.sun.com/docs/books/tutorial/2d/advanced/complexshapes.html

The object you create doesn't need to be this sophisticated, but it shows you the idea.

5. Function plotter:

You do not need to worry about the case where all of a, b, and c are 0, that is, the function degenerates to a horizontal line. This is a special case that makes the problem more complicated than it needs to be.

Below is some pseudocode that shows how to use the GeneralPath class and draw a curve. Assuming you have an array of xpoints and an array of ypoints that make up the curve, the algorithm is:

create a new GeneralPath variable, say "curve", with arguments GeneralPath.WIND_EVEN_ODD and xpoints.length
curve.moveTo(xpoints[0], ypoints[0])
for index from 1 to xpoints.length-1
  curve.lineTo(xpoints[index], ypoints[index])
g2.draw(curve)

This algorithm came from an example in the Java tutorial at this link:

http://java.sun.com/docs/books/tutorial/2d/geometry/arbitrary.html