/**
   * Rotate the oriented bounding box of the 3D image about the specified axis with the specified
   * angle.
   *
   * @param transform The transform and its matrix by which to rotate the image.
   */
  public void rotateFrameBy(Transform3D transform) {

    double rY, rX, rZ;
    double sinrX, sinrY, sinrZ, cosrX, cosrY, cosrZ;
    Matrix3d matrix = new Matrix3d();

    transform.get(matrix);

    rY = -Math.asin(matrix.m02);

    if (Math.cos(rY) != 0) {
      rX = -Math.atan2(matrix.m12, matrix.m22);
      rZ = Math.atan2(matrix.m01, matrix.m00);
    } else {
      rX = -Math.atan2(matrix.m10, matrix.m11);
      rZ = 0;
    }

    cosrX = Math.cos(rX);
    sinrX = Math.sin(rX);
    cosrY = Math.cos(rY);
    sinrY = Math.sin(rY);
    cosrZ = Math.cos(rZ);
    sinrZ = Math.sin(rZ);

    matrix.m00 = cosrZ * cosrY;
    matrix.m01 = -sinrZ * cosrY;
    matrix.m02 = sinrY;

    matrix.m10 = (cosrZ * sinrY * sinrX) + (sinrZ * cosrX);
    matrix.m11 = (-sinrZ * sinrY * sinrX) + (cosrZ * cosrX);
    matrix.m12 = -cosrY * sinrX;

    matrix.m20 = (-cosrZ * sinrY * cosrX) + (sinrZ * sinrX);
    matrix.m21 = (sinrZ * sinrY * cosrX) + (cosrZ * sinrX);
    matrix.m22 = cosrY * cosrX;

    m_kRotate.set(matrix);
    m_akAxis[0] = new Vector3f(1.0f, 0.0f, 0.0f);
    m_akAxis[1] = new Vector3f(0.0f, 1.0f, 0.0f);
    m_akAxis[2] = new Vector3f(0.0f, 0.0f, 1.0f);

    for (int i = 0; i < 3; i++) {
      m_kRotate.transform(m_akAxis[i]);
    }

    orthonormalize(m_akAxis);

    for (int i = 0; i < 3; i++) {
      setAxis(i, m_akAxis[i]);
    }
  }
  public void rotateAroundPointer(double x_rot, double y_rot) {
    if (hTerrain < 0) hTerrain = 0;
    if (Math.abs(point_dist * Math.sin(x_rot)) > hTerrain / 10)
      x_rot = Math.asin(hTerrain / point_dist / 10) * (x_rot >= 0 ? 1 : -1);
    if (Math.abs(point_dist * Math.sin(y_rot)) > hTerrain / 10)
      y_rot = Math.asin(hTerrain / point_dist / 10) * (y_rot >= 0 ? 1 : -1);

    // translateSideway(dist*Math.sin(x_rot))
    double d_x = point_dist * Math.sin(x_rot);
    lla = globe.getEllipsoid().forwGeodesic(lat, lon, -d_x * Math.cos(ha), az + Math.PI / 2., lla);
    lat = lla.lat;
    lon = lla.lon;
    az = Ellipsoid.adjlonPos(lla.az + Math.PI / 2.);

    // translateUpDown(dist*Math.sin(y_rot));
    double d_y = point_dist * Math.sin(y_rot);
    hEllps += d_y * Math.sin(Math.PI / 2. + ha);
    lla = globe.getEllipsoid().forwGeodesic(lat, lon, d_y * Math.cos(Math.PI / 2. + ha), az, lla);
    lat = lla.lat;
    lon = lla.lon;
    az = Ellipsoid.adjlonPos(lla.az + Math.PI);

    // translateForward(dist*(1-Math.cos(x_rot))*(1-Math.cos(y_rot)));
    double d_xy = point_dist * (1 - Math.cos(x_rot)) * (1 - Math.cos(y_rot));
    hEllps += d_xy * Math.sin(ha);
    lla = globe.getEllipsoid().forwGeodesic(lat, lon, d_xy * Math.cos(ha), az, lla);
    lat = lla.lat;
    lon = lla.lon;
    az = Ellipsoid.adjlonPos(lla.az + Math.PI + x_rot);

    ha -= y_rot;
    if (ha > Math.PI / 2) ha = Math.PI / 2;
    if (ha < -Math.PI / 2) ha = -Math.PI / 2;
    ele_changed = lat_changed = lon_changed = az_changed = ha_changed = true;
    h = Double.MAX_VALUE;
  }