Creating figures 

Graph of a function 




Let's think about what we'll need to draw this figure.
In fact, each of the items above will be an object. 

BoundingBox 

The viewing rectangle will be important for setting up the change of coordinates and for drawing both the grid and the graph. We will create a class BoundingBox to help us pass the information around easily. public class BoundingBox { public double llx, lly, urx, ury; public BoundingBox(double lowerLeftX, double lowerLeftY, double upperRightX, double upperRightY) { llx = lowerLeftX; lly = lowerLeftY; urx = upperRightX; ury = upperRightY; } } Notice that all a BoundingBox does is store information. 

FigurePanel 

We will create an extension of JPanel, called FigurePanel, in a moment. Let's think about what we want out of it.


FigurePanel's constructor 

public FigurePanel(double llx, double lly, double urx, double ury) { bbox = new BoundingBox(llx, lly, urx, ury); } 

FigurePanel's paintComponent method 

Here we will simply determine the AffineTransform and ask the grid and graph to draw themselves on the Graphics2D.
public void paintComponent(Graphics gfx) { super.paintComponent(gfx); Rectangle size = getBounds(); if (size.width != width  size.height != height  transform == null) { width = size.width; height = size.height; float ratioX = (float) (width / (bbox.urx  bbox.llx)); float ratioY = (float) (height/(bbox.ury  bbox.lly)); transform = new AffineTransform(); transform.scale(ratioX, ratioY); transform.translate(bbox.llx, bbox.ury); } Graphics2D g = (Graphics2D) gfx; g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); for (int i = 0; i < plotables.size(); i++) ((Plotable) plotables.elementAt(i)).plot(g, bbox, transform); } 

What is a plotable? 

The graphical elements will simply contain code for drawing themselves. We will have them extend a class called Plotable. Axes GraphicalEllipse GraphicalFunction GraphicalLine GraphicalPoint Grid 

Plotable 

import java.awt.*; import java.awt.geom.*; public abstract class Plotable { Color color = Color.black; public abstract void plot(Graphics2D g, BoundingBox bbox, AffineTransform transform); public void setColor(Color c) { color = c; } } 

How do we extend Plotable? 

Here is Grid.java: import java.awt.*; import java.awt.geom.*; public class Grid extends Plotable { public void plot(Graphics2D g, BoundingBox bbox, AffineTransform transform) { GeneralPath path = new GeneralPath(); int minX = (int) Math.floor(Math.min(bbox.llx, bbox.urx)); int maxX = (int) Math.ceil(Math.max(bbox.llx, bbox.urx)); for (int x = minX; x <= maxX; x++) { path.moveTo(x, (float) bbox.lly); path.lineTo(x, (float) bbox.ury); } int minY = (int) Math.floor(Math.min(bbox.lly, bbox.ury)); int maxY = (int) Math.ceil(Math.max(bbox.lly, bbox.ury)); for (int y = minY; y <= maxY; y++) { path.moveTo((float) bbox.llx, y); path.lineTo((float) bbox.urx, y); } g.setPaint(color); g.draw(transform.createTransformedShape(path)); } } Notice that this arrangement allows us to concentrate on drawing the grid in this class without worrying about the other details. 

GraphicalPoint.java 

Here is CubicPoint.java: import java.awt.*; import java.awt.geom.*; public class GraphicalPoint extends Plotable implements Moveable { public static final int CIRCLE = 0; public static final int SQUARE = 1; int style = CIRCLE; double size = 2; public double x, y; Shape shape; public GraphicalPoint(double xp, double yp) { x = xp; y = yp; } public void setPoint(double xp, double yp) { x = xp; y = yp; } public void setSize(double s) { size = s; } public void setStyle(int s) { style = s; } public void plot(Graphics2D g, BoundingBox bbox, AffineTransform transform) { Point2D.Double point = new Point2D.Double(x, y); transform.transform(point, point); if (style == CIRCLE) shape = new Ellipse2D.Double(point.x  size, point.y  size, 2*size, 2*size); else shape = new Rectangle2D.Double(point.x  size, point.y  size, 2*size, 2*size); g.setPaint(color); g.fill(shape); g.setPaint(Color.black); g.draw(shape); } } 

Let's draw a simple figure 


Graphing functions 

We first need to model a function public interface Function { public double valueAt(double x, double[] params); } For instance, here is the method in an implementation of Function. public double valueAt(double x, double[] params) { return x*x*x+params[0]*x; } 

GraphicalFunction 

import java.awt.*; import java.awt.geom.*; public class GraphicalFunction extends Plotable { Function function; Stroke stroke; int steps = 50; double[] params; double x0, x1; boolean domainSet = false; public GraphicalFunction(Function f, double[] p) { function = f; params = p; stroke = new BasicStroke(1f); } public void setSteps(int s) { steps = s; } public void setStroke(Stroke s) { stroke = s; } public void setDomain(double xp0, double xp1) { domainSet = true; x0 = xp0; x1 = xp1; } public void plot(Graphics2D g, BoundingBox bbox, AffineTransform transform) { if (!domainSet) { x0 = bbox.llx; x1 = bbox.urx; } double stepsize = (x1  x0)/steps; GeneralPath path = new GeneralPath(); Point2D.Float point = new Point2D.Float((float) x0, (float) function.valueAt(x0, params)); transform.transform(point, point); path.moveTo(point.x, point.y); for (int i = 1; i <= steps; i++) { double x = x0 + i*stepsize; point = new Point2D.Float((float) x, (float) function.valueAt(x, params)); transform.transform(point, point); path.lineTo(point.x, point.y); } g.setPaint(color); Stroke savedStroke = g.getStroke(); g.setStroke(stroke); g.draw(path); g.setStroke(savedStroke); } } 

Let's add a function 


Putting everything into a package 

By now, we have quite a few classes that work together to create illustrations. Let's see how to bundle them together into a package. Our classes are: Axes FigurePanel Grid GraphicalPoint BoundingBox GraphicalPoint Plotable 

To create a package called figure: 



Interactivity 

We can set up our figure package to allow for interactive diagrams. 

Get the figure package 

Download the figure package and unpack it using the command tar xzvf figure.tgz 

Applets 

An example


Writing applets 



Converting applications to applets 



An example 

Here is an example of how an application, our CubicGraph from Chapter 3, can be converted to an applet.


Another example 



Preparing the HTML file 

lineMover.html 

Testing the applet 

You can test the applet using a program called appletviewer:
appletviewer lineMover.html 