/**
  * Constructs a 3D affine transformation using the given matrix.
  *
  * <p>Affine transformations can be applied to 3D or homogeneous 3D coordinates. A 3 by 3 matrix
  * sets the rotation and shear portion of the transformation. A 4 by 4 matrix sets rotation,
  * shear, and translation. A null matrix sets the transformation to the identity transformation.
  *
  * @param mat double[][]
  */
 public Affine3DMatrix(double[][] matrix) {
   if (matrix == null) { // identity matrix
     this.matrix[0][0] = this.matrix[1][1] = this.matrix[2][2] = this.matrix[3][3] = 1;
     return;
   }
   for (int i = 0; i < matrix.length; i++) { // loop over the rows
     System.arraycopy(matrix[i], 0, this.matrix, 0, matrix[i].length);
   }
 }
 /**
  * Transforms the given point.
  *
  * @param point the coordinates to be transformed
  */
 public double[] direct(double[] point) {
   int n = point.length;
   double[] tempPoint = new double[n];
   System.arraycopy(point, 0, tempPoint, 0, n);
   for (int i = 0; i < n; i++) {
     point[i] = 0;
     for (int j = 0; j < n; j++) {
       point[i] += matrix[i][j] * tempPoint[j];
     }
   }
   return point;
 }
 /**
  * Transforms the given point using the inverse transformation (if it exists).
  *
  * <p>If the transformation is not invertible, then a call to this method must throw a
  * UnsupportedOperationException exception.
  *
  * @param point the coordinates to be transformed
  */
 public double[] inverse(double[] point) throws UnsupportedOperationException {
   if (!inverted) {
     calcInverse(); // computes inverse using LU decompostion
   }
   if (inverse == null) { // inverse does not exist
     throw new UnsupportedOperationException("inverse matrix does not exist.");
   }
   int n = point.length;
   double[] pt = new double[n];
   System.arraycopy(point, 0, pt, 0, n);
   for (int i = 0; i < n; i++) {
     point[i] = 0;
     for (int j = 0; j < n; j++) {
       point[i] += inverse[i][j] * pt[j];
     }
   }
   return point;
 }