public RotatableCanvas(Object parent, AlignViewport av, Controller c, Vector points, int npoint) {
    this.parent = parent;
    this.points = points;
    this.npoint = npoint;
    this.controller = c;
    this.av = av;

    controller.addListener(this);

    prefsize = getPreferredSize();
    orig = new float[npoint][3];

    for (int i = 0; i < npoint; i++) {
      SequencePoint sp = (SequencePoint) points.elementAt(i);
      for (int j = 0; j < 3; j++) {
        orig[i][j] = sp.coord[j];
      }
    }
    // Initialize the matrices to identity

    for (int i = 0; i < 3; i++) {
      for (int j = 0; j < 3; j++) {
        if (i != j) {
          idmat.addElement(i, j, 0);
          objmat.addElement(i, j, 0);
          rotmat.addElement(i, j, 0);
        } else {
          idmat.addElement(i, j, 0);
          objmat.addElement(i, j, 0);
          rotmat.addElement(i, j, 0);
        }
      }
    }

    axes = new float[3][3];
    initAxes();

    findCentre();
    findWidth();

    scale = findScale();

    //    System.out.println("Scale factor = " + scale);

    addMouseListener(this);
    addKeyListener(this);
    if (getParent() != null) {
      getParent().addKeyListener(this);
    }
    addMouseMotionListener(this);

    // Add rubberband
    rubberband = new RubberbandRectangle(this);
    rubberband.setActive(true);
    rubberband.addListener(this);
  }
 public void printPoints() {
   for (int i = 0; i < npoint; i++) {
     SequencePoint sp = (SequencePoint) points.elementAt(i);
     Format.print(System.out, "%5d ", i);
     for (int j = 0; j < 3; j++) {
       Format.print(System.out, "%13.3f  ", sp.coord[j]);
     }
     System.out.println();
   }
 }
  public void drawScene(Graphics g) {
    boolean darker = false;

    int halfwidth = size().width / 2;
    int halfheight = size().height / 2;

    for (int i = 0; i < npoint; i++) {
      SequencePoint sp = (SequencePoint) points.elementAt(i);
      int x = (int) ((float) (sp.coord[0] - centre[0]) * scale) + halfwidth;
      int y = (int) ((float) (sp.coord[1] - centre[1]) * scale) + halfheight;
      float z = sp.coord[1] - centre[2];
      if (sp.sequence instanceof DrawableSequence) {
        if (((DrawableSequence) sp.sequence).color == Color.black) {
          g.setColor(Color.white);
        } else {
          g.setColor(((DrawableSequence) sp.sequence).color);
        }
      } else {
        g.setColor(Color.red);
      }
      if (av != null) {
        if (av.getSelection().contains(((SequencePoint) points.elementAt(i)).sequence)) {
          g.setColor(Color.gray);
        }
      }
      if (z < 0) {
        g.setColor(g.getColor().darker());
      }

      g.fillRect(x - 3, y - 3, 6, 6);
      g.setColor(Color.red);
    }
    //    //Now the rectangle
    //    if (rectx2 != -1 && recty2 != -1) {
    //      g.setColor(Color.white);
    //
    //      g.drawRect(rectx1,recty1,rectx2-rectx1,recty2-recty1);
    //    }
  }
  public AlignSequenceI findPoint(int x, int y) {

    int halfwidth = size().width / 2;
    int halfheight = size().height / 2;

    int found = -1;

    for (int i = 0; i < npoint; i++) {

      SequencePoint sp = (SequencePoint) points.elementAt(i);
      int px = (int) ((float) (sp.coord[0] - centre[0]) * scale) + halfwidth;
      int py = (int) ((float) (sp.coord[1] - centre[1]) * scale) + halfheight;

      if (Math.abs(px - x) < 3 && Math.abs(py - y) < 3) {
        found = i;
      }
    }
    if (found != -1) {
      return ((SequencePoint) points.elementAt(found)).sequence;
    } else {
      return null;
    }
  }
  public void rectSelect(int x1, int y1, int x2, int y2) {
    boolean changedSel = false;
    for (int i = 0; i < npoint; i++) {
      SequencePoint sp = (SequencePoint) points.elementAt(i);
      int tmp1 = (int) ((sp.coord[0] - centre[0]) * scale + (float) size().width / 2.0);
      int tmp2 = (int) ((sp.coord[1] - centre[1]) * scale + (float) size().height / 2.0);

      if (tmp1 > x1 && tmp1 < x2 && tmp2 > y1 && tmp2 < y2) {
        if (av != null) {
          if (!av.getSelection().contains(sp.sequence)) {
            changedSel = true;
            av.getSelection().addElement(sp.sequence);
          }
        }
      }
    }
    if (changedSel) {
      fireSequenceSelectionEvent(av.getSelection());
    }
  }
  public void mouseDragged(MouseEvent evt) {
    mx = evt.getX();
    my = evt.getY();
    // Check if this is a rectangle drawing drag
    if ((evt.getModifiers() & InputEvent.BUTTON2_MASK) != 0) {
      //      rectx2 = evt.getX();
      //      recty2 = evt.getY();
    } else {
      rotmat.setIdentity();

      rotmat.rotate((float) (my - omy), 'x');
      rotmat.rotate((float) (mx - omx), 'y');

      for (int i = 0; i < npoint; i++) {
        SequencePoint sp = (SequencePoint) points.elementAt(i);
        sp.coord[0] -= centre[0];
        sp.coord[1] -= centre[1];
        sp.coord[2] -= centre[2];

        // Now apply the rotation matrix
        sp.coord = rotmat.vectorMultiply(sp.coord);

        // Now translate back again
        sp.coord[0] += centre[0];
        sp.coord[1] += centre[1];
        sp.coord[2] += centre[2];
      }

      for (int i = 0; i < 3; i++) {
        axes[i] = rotmat.vectorMultiply(axes[i]);
      }
      omx = mx;
      omy = my;

      redrawneeded = true;
      paint(this.getGraphics());
    }

    return;
  }
  public void findWidth() {
    max = new float[3];
    min = new float[3];

    max[0] = (float) -1e30;
    max[1] = (float) -1e30;
    max[2] = (float) -1e30;

    min[0] = (float) 1e30;
    min[1] = (float) 1e30;
    min[2] = (float) 1e30;

    for (int i = 0; i < 3; i++) {
      for (int j = 0; j < npoint; j++) {
        SequencePoint sp = (SequencePoint) points.elementAt(j);
        if (sp.coord[i] >= max[i]) {
          max[i] = sp.coord[i];
        }
        if (sp.coord[i] <= min[i]) {
          min[i] = sp.coord[i];
        }
      }
    }

    //    System.out.println("xmax " + max[0] + " min " + min[0]);
    // System.out.println("ymax " + max[1] + " min " + min[1]);
    // System.out.println("zmax " + max[2] + " min " + min[2]);

    width[0] = Math.abs(max[0] - min[0]);
    width[1] = Math.abs(max[1] - min[1]);
    width[2] = Math.abs(max[2] - min[2]);

    maxwidth = width[0];

    if (width[1] > width[0]) maxwidth = width[1];
    if (width[2] > width[1]) maxwidth = width[2];

    // System.out.println("Maxwidth = " + maxwidth);
  }