Create an applet

Task

Write an applet which allows the experimental exploration of the principles of polar coordinates. Use a conventional JApplet and a 2D canvas to draw the scene on. Visualise a draggable point and its coordinates both in cartesian and polar coordinates. Ensure that changes in one of its coordinates affects the others.

Classes to be used:
  • JApplet, MMG2DCanvas
  • MMAffine2DPoint, MMAffine2DEllipse, MMAffine2DAngle, MMAffine2DLineSegment, MMDouble

Applet Skeleton

We create a file named PolarApplet1.java and define the applet class:

public class PolarApplet1 extends JApplet {
  ...
}

Since we use the standard applet class (JApplet) and not one of the applet base classes of the MathletFactory, we need to initialize the runtime manually:

MathletRuntime runtime = MathletRuntime.createStaticRuntime(null);

Now we create the init method and a 2D canvas:

MMG2DCanvas canvas;

public void init() {
  canvas = new MMG2DCanvas();
}

Since the coordinates should be drawn under the canvas, we need a panel for the controls and an appropriate layout:

JPanel controlPane = new JPanel();
getContentPane().setLayout(new BorderLayout());
getContentPane().add(new JLabel("Polar Coordinates"), BorderLayout.NORTH);
getContentPane().add(canvas, BorderLayout.CENTER);
getContentPane().add(controlPane, BorderLayout.SOUTH);

Mathematical Entities

The basic work is done now, so we can implement the mathematical objects. Note that every mathematical entity needs a proper number field where the arithmetics are executed in. We choose the number class MDouble for real numbers as well as their equivalent MM class for rho and phi:

final Class NUMBER_CLASS = MDouble.class;
MMAffine2DPoint point;
MMAffine2DEllipse circle;
MMAffine2DAngle angle;
MMAffine2DLineSegment line;
MMDouble rho, phi;

public void init() {
  ...
  point = new MMAffine2DPoint(NUMBER_CLASS, 2, 2);
  circle = new MMAffine2DEllipse(new double[] {0, 0}, 0, 1, 1);
  angle = new MMAffine2DAngle(point, 2);
  line = new MMAffine2DLineSegment(NUMBER_CLASS, 0, 0, 2, 2);
  rho = new MMDouble();
  phi = new MMDouble();
}

The objects are added to the canvas and the control panel (also a coordinate system):

canvas.addObject(new MMCoordinateSystem().getAsCanvasContent());
canvas.addObject(point.getAsCanvasContent());
canvas.addObject(circle.getAsCanvasContent());
canvas.addObject(angle.getAsCanvasContent());
canvas.addObject(line.getAsCanvasContent());

controlPane.add(point.getAsContainerContent());
controlPane.add(rho.getAsContainerContent());
controlPane.add(phi.getAsContainerContent());

Since the circle is filled per default and would hide all other objects, we change its display properties:

circle.getDisplayProperties().setFilled(false);

To ensure that our scene fits into the current viewing area of the canvas, we write:

canvas.autoScale(true);

Dependencies

Now our efforts can be viewed in the applet. Obviously nor the point is draggable, neither its coordinates are editable. We solve this by writting:

point.addHandler(new Affine2DMouseTranslateHandler(canvas));
point.addHandler(new Affine2DKeyboardTranslateHandler(canvas));
point.setEditable(true);
rho.setEditable(true);
phi.setEditable(true);

When editing a value or dragging the point, the other entities remain unchanged. We need to establish dependencies between the objects. First we ensure that both the line segment and the angle "follow the point":

DependencyAdapter pointAdapter = new DependencyAdapter() {
  public void doUpdate() {
    line.setEndPoint(point);
    angle.setSecondPoint(point);
  }
};
angle.dependsOn(point, pointAdapter);
line.dependsOn(point, pointAdapter);

Then we update the rho component:

DependencyAdapter rhoAdapter = new DependencyAdapter() {
  public void doUpdate() {
    rho.setDouble(
      Math.sqrt(Math.pow(point.getXAsDouble(), 2) + Math.pow(point.getYAsDouble(), 2)));
  }
};
rho.dependsOn(point, rhoAdapter);

And finally the phi component:

DependencyAdapter phiAdapter = new DependencyAdapter() {
  public void doUpdate() {
    phi.setDouble(
      Math.atan2(point.getYAsDouble(), point.getXAsDouble()));
  }
};
phi.dependsOn(point, phiAdapter);

As we can see, the task is completed now. The full source code is available here.

Add picture from clipboard (Maximum size: 500 MB)