import java.awt.*;
/**
* A class which shows the fundamental domain corresponding to the current
* trace value and display parameters, on a portion of the boundary of
* hyperbolic space.
*
* @author Jonathan A. Poritz
* @version 1.7, 10 Sep 1998
*/
public class BoundaryPanel extends Plane {
/**
* The (1,1) entry of the element cannonically associated with the current
* trace.
*/
public Complex z11 = new Complex();
/**
* The currently selected axis distance.
*/
public double dist;
/**
* A reference to the label in outputpanel declaring the portion of
* the boundary of hyperbolic space which is currently visible.
*
* @see OutputPanel#boundarypanellabel
*/
public Label boundarypanellabel;
/**
* The maxpow calculated for a Ford domain with the current trace -- not
* necessarily valid for a Dirichlet domain with the same trace, but used
* nonetheless.
*/
public int calcmaxpow;
/**
* The overriding maxpow chosen by the user if so desired taken from
* maxpowchoice.
*/
public int chosenmaxpow;
/**
* A boolean telling if we should use the calcmaxpow or some other
* choice, to be found in chosenmaxpow.
*/
public boolean usecalcmaxpow;
/**
* A reference to the choice in outputpanel of displaying disks,
* circles or circle with labeling indices.
*
* @see OutputPanel#diskorcircle
*/
public Choice diskorcircle;
/**
* A reference to the choice in outputpanel of computing Ford or
* Dirichlet domains.
*
* @see OutputPanel#fordordirichlet
*/
public Choice fordordirichlet;
/**
* An array of BoundaryCircles with positive indices.
*/
protected BoundaryCircle pc[] = null;
/**
* An array of BoundaryCircles with negative indices.
*/
protected BoundaryCircle nc[] = null;
/**
* The location of a mousedown in this plane, to compute the extent of
* a drag that may occur; in abstract coordinates.
*/
protected double[] prev = new double[2];
/**
* The location of a mousedown in this plane, to compute the extent of
* a drag that may occur; in pixel coordinates.
*/
protected int[] previ = new int[2];
/**
* The abstract x-coordinate of the left side of the boundary plane display.
*/
public static final double CX = -1.5D;
/**
* The abstract y-coordinate of the upper edge of the boundary plane display.
*/
public static final double CY = 2D;
/**
* The width, in abstract units, of the boundary plane display.
*/
public static final double SX = 4D;
/**
* The height, in abstract units, of the boundary plane display.
*/
public static final double SY = 4D;
/**
* The width, in pixels, of the boundary plane display. Good defaults are:
*
- 200
*
- for small screens,
*
- 300
*
- for large screens
*
*/
public static final int X = 300;
/**
* The height, in pixels, of the boundary plane display. Good defaults are:
* - 200
*
- for small screens,
*
- 300
*
- for large screens
*
*/
public static final int Y = 300;
/**
* Constructor for BoundaryPanels.
*
* @param bdrypnllbl the label describing the current window on the boundary
* plane
* @param dskrcrcl the choice of display styles of the isometric or
* equidistant circles
* @param frdrdrchlt the choice of making Ford or Dirichlet domains.
*/
public BoundaryPanel(Label bdrypnllbl, Choice dskrcrcl, Choice frdrdrchlt) {
// creat the ambient plane, with axes and xticks shown
super(CX, CY, SX, SY, X, Y);
draw_axes = true;
show_xticks = true;
// we start using the calculated maxpows
usecalcmaxpow = true;
// save the references to the boundary panel label, disk or circle choice
// and Ford or Dirichlet domain choice
boundarypanellabel = bdrypnllbl;
diskorcircle = dskrcrcl;
fordordirichlet = frdrdrchlt;
// set the boundary panel label correctly
boundarypanellabel.setText(this.toString());
}
/**
* Java 1.0 handling of mouseDown events.
*
* @param e the event to be handled
* @param x the x-coordinate (in pixels) of the mouseDown
* @param y the y-coordinate (in pixels) of the mouseDown
*/
public boolean mouseDown(Event e, int x, int y) {
// always save pixel location of mouseDown
previ[0] = x;
previ[1] = y;
if ((e.modifiers & e.META_MASK) != 0) {
// right button zoom, all we needed was to save location of mouseDown,
// can now return
return true;
}
// left or middle button translate, save abstract coordinates as well
prev[0] = (pixelsToAbstract(x, y))[0];
prev[1] = (pixelsToAbstract(x, y))[1];
return true;
}
/**
* Java 1.0 handling of mouseDrag events.
*
* @param e the event to be handled
* @param x the x-coordinate (in pixels) of the mouseDrag
* @param y the y-coordinate (in pixels) of the mouseDrag
*/
public boolean mouseDrag(Event e, int x, int y) {
// convert to abstract coordinates
double xx = (pixelsToAbstract(x, y))[0];
double yy = (pixelsToAbstract(x, y))[1];
if ((e.modifiers & e.META_MASK) != 0) {
// right button zoom
zoom(1D - ((double)(previ[1] - y)) / 50D);
}
else {
// left or middle mouse translate
corner[0] += prev[0] - xx;
corner[1] += prev[1] - yy;
boundarypanellabel.setText(this.toString());
repaint();
}
previ[0] = x;
previ[1] = y;
return true;
}
/**
* Paint the BoundaryPanel by painting the basic plane, calling the paint
* on each of the current negative and positive BoundaryCircles, then
* drawing the tickmarks.
*
* @param g the Graphics object upon which to paint the TracePlanePanel
*/
public synchronized void paint(Graphics g) {
// paint the basic plane
super.paint(g);
// paint the positive and negative BoundaryCircles, in a rainbow of
// colors, up to the maxpow in use at the moment
int max = usecalcmaxpow ? calcmaxpow : chosenmaxpow;
for (int i=0; i < max; i++) {
int j = 255*i/max;
g.setColor(new Color(j,0,j));
pc[i].paint(g, this, diskorcircle);
g.setColor(new Color(0,j,255-j));
nc[i].paint(g, this, diskorcircle);
}
drawTickmarks(g);
}
/**
* Scales the size of the visible window onto the boundary of
* hyperbolic space.
*
* @param factor the scaling factor, can be any positive number
*/
public void zoom(double factor) {
corner[0] = corner[0] + .5D * size[0] - .5D * size[0] * factor;
size[0] *= factor;
corner[1] = corner[1] - .5D * size[1] + .5D * size[1] * factor;
size[1] *= factor;
boundarypanellabel.setText(this.toString());
repaint();
}
/**
* Recreates the current positive and negative BoundaryCircles and then
* repaints, called when some relevant parameter has changed.
*/
public synchronized void update() {
// make a arrays of positive and negative BoundaryCircles
// of the appropriate length
int max = usecalcmaxpow ? calcmaxpow : chosenmaxpow;
pc = new BoundaryCircle[max];
nc = new BoundaryCircle[max];
if ((z11.y == 0D) && ((z11.x == 1D) || (z11.x == -1D))) {
// parabolic generator, call the appropriate BoundaryCircle constructor
for (int i=0; i < max; i++) {
pc[i] = new BoundaryCircle(i+1);
nc[i] = new BoundaryCircle(-i-1);
}
}
else {
// elliptic or loxodromic generator
int domaintype = fordordirichlet.getSelectedIndex();
Complex z11powers = new Complex(Complex.ONE);
for (int i=0; i < max; i++) {
// take the power of the generator
z11powers = Complex.multiply(z11powers, z11);
// make a positive BoundaryCircle with the right constructor,
// then make a negative version of it
BoundaryCircle poscirc = new BoundaryCircle(z11powers, dist, i+1, domaintype);
pc[i] = poscirc;
nc[i] = BoundaryCircle.makeNeg(poscirc);
}
}
repaint();
}
}