//
// MouseBehaviorJ2D.java
//

/*
VisAD system for interactive analysis and visualization of numerical
data.  Copyright (C) 1996 - 2017 Bill Hibbard, Curtis Rueden, Tom
Rink, Dave Glowacki, Steve Emmerson, Tom Whittaker, Don Murray, and
Tommy Jasmin.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Library General Public License for more details.

You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA
*/

package visad.java2d;

import visad.*;

import java.lang.reflect.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.NoninvertibleTransformException;

/**
   MouseBehaviorJ2D is the VisAD class for mouse behaviors for Java2D
*/

public class MouseBehaviorJ2D implements MouseBehavior {

  /** DisplayRenderer for Display */
  DisplayRendererJ2D display_renderer;
  DisplayImpl display;

  private MouseHelper helper = null;

  /**
   * Construct a MouseBehavior for the DisplayRenderer specified
   * @param  r  DisplayRenderer to use
   */
  public MouseBehaviorJ2D(DisplayRendererJ2D r) {
    this(r, MouseHelper.class);
  }

  /**
   * Construct a MouseBehavior for the DisplayRenderer specified
   * @param  r  DisplayRenderer to use
   * @param  mhClass  MouseHelper subclass to use
   */
  public MouseBehaviorJ2D(DisplayRendererJ2D r, Class mhClass) {
    try {
      Class[] param = new Class[] {DisplayRenderer.class, MouseBehavior.class};
      Constructor mhConstructor =
        mhClass.getConstructor(param);
      helper = (MouseHelper) mhConstructor.newInstance(new Object[] {r, this});
    }
    catch (Exception e) {
      throw new VisADError("cannot construct " + mhClass);
    }
    // helper = new MouseHelper(r, this);

    display_renderer = r;
    display = display_renderer.getDisplay();
  }

  /**
   * Get the helper class used by this MouseBehavior.  
   * The MouseHelper defines the actions taken based
   * on MouseEvents.
   * @return  MouseHelper being used.
   */
  public MouseHelper getMouseHelper() {
    return helper;
  }

  /**
   * Return the VisAD ray corresponding to the component coordinates.
   * @param  screen_x  x coordinate of the component
   * @param  screen_y  y coordinate of the component
   * @return  corresponding VisADRay
   * @see visad.VisADRay
   * @see visad.LocalDisplay#getComponent()
   */
  public VisADRay findRay(int screen_x, int screen_y) {
    // System.out.println("findRay " + screen_x + " " + screen_y);
    VisADCanvasJ2D canvas = display_renderer.getCanvas();
    AffineTransform trans = canvas.getTransform();

    if (trans == null) return null;

    double[] coords = {(float) screen_x, (float) screen_y};
    double[] newcoords = new double[2];
    try {
      trans.inverseTransform(coords, 0, newcoords, 0, 1);
    }
    catch (NoninvertibleTransformException e) {
      throw new VisADError("MouseBehaviorJ2D.findRay: " +
                           "non-invertable transform");
    }

    VisADRay ray = new VisADRay();
    ray.position[0] = newcoords[0];
    ray.position[1] = newcoords[1];
    ray.position[2] = 0.0;
    ray.vector[0] = 0.0;
    ray.vector[1] = 0.0;
    ray.vector[2] = -1.0;
    return ray;
  }

  /**
   * Return the VisAD ray corresponding to the VisAD cursor coordinates.
   * @param  cursor  array (x,y) of cursor location
   * @return  corresponding VisADRay
   * @see visad.VisADRay
   * @see visad.DisplayRenderer#getCursor()
   */
  public VisADRay cursorRay(double[] cursor) {
    VisADRay ray = new VisADRay();
    ray.position[0] = cursor[0];
    ray.position[1] = cursor[1];
    ray.position[2] = 0.0;
    ray.vector[0] = 0.0;
    ray.vector[1] = 0.0;
    ray.vector[2] = -1.0;
    return ray;
  }

  /**
   * Return the screen coordinates corresponding to the VisAD coordinates.
   * @param  position  array of VisAD coordinates
   * @return  corresponding (x, y) screen coordinates
   */
  public int[] getScreenCoords(double[] position) {
    VisADCanvasJ2D canvas = display_renderer.getCanvas();
    AffineTransform trans = canvas.getTransform();

    if (trans == null) return null;

    double[] newcoords = new double[2];
    trans.transform(position, 0, newcoords, 0, 1);

    int[] coords = new int[2];
    for (int i=0; i<2; i++) coords[i] = (int) newcoords[i];
    return coords;
  }

  /**
   * Create a translation matrix.
   * @param  transx   x translation amount
   * @param  transy   y translation amount
   * @param  transz   z translation amount
   * @return  new translation matrix.  This can be used to translate
   *          the current matrix
   * @see #multiply_matrix(double[] a, double[] b)
   */
  public double[] make_translate(double transx, double transy, double transz) {
    return make_matrix(0.0, 0.0, 0.0, 1.0, transx, -transy, transz);
  }

  /**
   * Create a translation matrix.  
   * @param  transx   x translation amount
   * @param  transy   y translation amount
   * @return  new translation matrix.  This can be used to translate
   *          the current matrix
   * @see #multiply_matrix(double[] a, double[] b)
   */
  public double[] make_translate(double transx, double transy) {
    return make_translate(transx, transy, 0.0);
  }

  /**
   * Multiply the two matrices together.
   * @param  a  first matrix
   * @param  b  second matrix
   * @return  new resulting matrix
   */
  public double[] multiply_matrix(double[] a, double[] b) {
    AffineTransform ta = new AffineTransform(a);
    AffineTransform tb = new AffineTransform(b);
    ta.concatenate(tb);
    double[] c = new double[6];
    ta.getMatrix(c);
    return c;
  }

  /**
   * Make a transformation matrix to perform the given rotation, scale and
   * translation.  This function uses the fast matrix post-concatenation
   * techniques from Graphics Gems.  
   * @param rotx  x rotation
   * @param roty  y rotation
   * @param rotz  z rotation
   * @param scale  scaling factor
   * @param transx  x translation
   * @param transy  y translation
   * @param transz  z translation
   * @return  new matrix
   */
  public double[] make_matrix(double rotx, double roty, double rotz,
         double scale, double transx, double transy, double transz) {
     return make_matrix(rotx, roty, rotz, scale, scale, scale,
                        transx, transy, transz);
  }

  /**
   * Make a transformation matrix to perform the given rotation, scale and
   * translation.  This function uses the fast matrix post-concatenation
   * techniques from Graphics Gems.  
   * @param rotx  x rotation
   * @param roty  y rotation
   * @param rotz  z rotation
   * @param scalex  x scaling factor
   * @param scaley  y scaling factor
   * @param scalez  z scaling factor
   * @param transx  x translation
   * @param transy  y translation
   * @param transz  z translation
   * @return  new matrix
   */
  public double[] make_matrix(double rotx, double roty, double rotz,
         double scalex, double scaley, double scalez, 
         double transx, double transy, double transz) {

    double sx, sy, sz, cx, cy, cz, t;
    int i, j, k;
    double deg2rad = 1.0 / 57.2957;
    double[] matrix = new double[6];
    double[][] mat = new double[4][4];

    /* Get sin and cosine values */
    sx = Math.sin(rotx * deg2rad);
    cx = Math.cos(rotx * deg2rad);
    sy = Math.sin(roty * deg2rad);
    cy = Math.cos(roty * deg2rad);
    sz = Math.sin(rotz * deg2rad);
    cz = Math.cos(rotz * deg2rad);

    /* Start with identity matrix */
    mat[0][0] = 1.0;  mat[0][1] = 0.0;  mat[0][2] = 0.0;  mat[0][3] = 0.0;
    mat[1][0] = 0.0;  mat[1][1] = 1.0;  mat[1][2] = 0.0;  mat[1][3] = 0.0;
    mat[2][0] = 0.0;  mat[2][1] = 0.0;  mat[2][2] = 1.0;  mat[2][3] = 0.0;
    mat[3][0] = 0.0;  mat[3][1] = 0.0;  mat[3][2] = 0.0;  mat[3][3] = 1.0;

    /* Z Rotation */
    for (i=0;i<4;i++) {
      t = mat[i][0];
      mat[i][0] = t*cz - mat[i][1]*sz;
      mat[i][1] = t*sz + mat[i][1]*cz;
    }

    /* X rotation */
    for (i=0;i<4;i++) {
      t = mat[i][1];
      mat[i][1] = t*cx - mat[i][2]*sx;
      mat[i][2] = t*sx + mat[i][2]*cx;
    }

    /* Y Rotation */
    for (i=0;i<4;i++) {
      t = mat[i][0];
      mat[i][0] = mat[i][2]*sy + t*cy;
      mat[i][2] = mat[i][2]*cy - t*sy;
    }

    /* Scale */
    for (i=0;i<3;i++) {
      mat[i][0] *= scalex;
      mat[i][1] *= scaley;
      mat[i][2] *= scalez;
    }

    /* Translation */
    mat[0][3] = transx;
    mat[1][3] = transy;
    mat[2][3] = transz;

    matrix[0] = mat[0][0];
    matrix[1] = mat[1][0];
    matrix[2] = mat[0][1];
    matrix[3] = mat[1][1];
    matrix[4] = mat[0][3];
    matrix[5] = mat[1][3];
    return matrix;
  }

  static final double EPS = 0.000001;

  /**
   * Get the rotation, scale and translation parameters for the specified
   * matrix.  Results are not valid for non-uniform aspect (scale).
   * @param  rot  array to hold x,y,z rotation values
   * @param  scale  array to hold scale value
   * @param  trans  array to hold x,y,z translation values
   */
  public void instance_unmake_matrix(double[] rot, double[] scale,
                                     double[] trans, double[] matrix) {
    double  sx, sy, sz, cx, cy, cz;
    int i, j;
    double[][] mat = new double[4][4];
    double[][] nat = new double[4][4];

    double scalex, scaley, scalez, cxa, cxb, cxinv;
    double[] scaleinv = new double[3];

    if (rot == null || rot.length != 3) return;
    if (scale == null || !(scale.length != 1 || scale.length !=3)) return;
    if (trans == null || trans.length != 3) return;
    if (matrix == null || matrix.length != 6) return;

    /* Start with identity matrix */
    mat[0][0] = 1.0;  mat[0][1] = 0.0;  mat[0][2] = 0.0;  mat[0][3] = 0.0;
    mat[1][0] = 0.0;  mat[1][1] = 1.0;  mat[1][2] = 0.0;  mat[1][3] = 0.0;
    mat[2][0] = 0.0;  mat[2][1] = 0.0;  mat[2][2] = 1.0;  mat[2][3] = 0.0;
    mat[3][0] = 0.0;  mat[3][1] = 0.0;  mat[3][2] = 0.0;  mat[3][3] = 1.0;

    mat[0][0] = matrix[0];
    mat[1][0] = matrix[1];
    mat[0][1] = matrix[2];
    mat[1][1] = matrix[3];
    mat[0][3] = matrix[4];
    mat[1][3] = matrix[5];

    /* translation */
/* WLH 24 March 2000, for consistency with change
                      of 22 Dec 97 in static_make_matrix
    trans[0] = mat[3][0];
    trans[1] = mat[3][1];
    trans[2] = mat[3][2];
*/
    trans[0] = mat[0][3];
    trans[1] = mat[1][3];
    trans[2] = mat[2][3];

    /* scale */
    scalex = scaley = scalez = 0.0;
    for (i=0; i<3; i++) {
      scalex += mat[0][i] * mat[0][i];
      scaley += mat[1][i] * mat[1][i];
      scalez += mat[2][i] * mat[2][i];
    }
    if (Math.abs(scalex - scaley) > EPS || Math.abs(scalex - scalez) > EPS) {
      // System.out.println("problem " + scalex + " " + scaley + " " + scalez);
    }
    if (scale.length == 1) {
      scale[0] = Math.sqrt((scalex + scaley + scalez)/3.0);
      scaleinv[0] = Math.abs(scale[0]) > EPS ? 1.0 / scale[0] : 1.0 / EPS;
      scaleinv[1] = scaleinv[2] = scaleinv[0];
    } else {
      scale[0] = Math.sqrt(scalex);
      scale[1] = Math.sqrt(scaley);
      scale[2] = Math.sqrt(scalez);
      for (i=0; i<3; i++) {
        scaleinv[i] = Math.abs(scale[i]) > EPS ? 1.0 / scale[i] : 1.0 / EPS;
      }
    }

    for (i=0; i<3; i++) {
      for (j=0; j<3; j++) {
        nat[j][i] = scaleinv[j] * mat[j][i];
      }
    }

    /* rotation */
    sx = -nat[2][1];

    cxa = Math.sqrt(nat[2][0]*nat[2][0] + nat[2][2]*nat[2][2]);
    cxb = Math.sqrt(nat[0][1]*nat[0][1] + nat[1][1]*nat[1][1]);

    if (Math.abs(cxa - cxb) > EPS) {
      // System.out.println("problem2 " + cxa + " " + cxb);
    }
    /* the sign of cx does not matter;
       it is an ambiguity in 3-D rotations:
       (rotz, rotx, roty) = (180+rotz, 180-rotx, 180+roty) */
    cx = (cxa + cxb) / 2.0;
    if (Math.abs(cx) > EPS) {
      cxinv = 1.0 / cx;
      sy = nat[2][0] * cxinv;
      cy = nat[2][2] * cxinv;
      sz = nat[0][1] * cxinv;
      cz = nat[1][1] * cxinv;
    }
    else {
      /* if cx == 0 then roty and rotz are ambiguous:
         assume rotx = 0.0 */
      sy = 0.0;
      cy = 1.0;
      sz = nat[0][2];
      cz = nat[1][2];
    }

    rot[0] = 57.2957 * Math.atan2(sx, cx);
    rot[1] = 57.2957 * Math.atan2(sy, cy);
    rot[2] = 57.2957 * Math.atan2(sz, cz);
    return;
  }

}


 

Ads help maintain this website.