Mega Code Archive

 
Categories / Java / 2D Graphics GUI
 

A 3x3 matrix implementation

/**  * Copyright (c) 2008-2010  Morten Silcowitz.  *  * This file is part of the Jinngine physics library  *  * Jinngine is published under the GPL license, available   * at http://www.gnu.org/copyleft/gpl.html.   */ //package jinngine.math; import java.io.Serializable; //3x3 matrix for optimized matrix ops /**  * A 3x3 matrix implementation  */ public class Matrix3 {   public double a11, a12, a13;   public double a21, a22, a23;   public double a31, a32, a33;      public Matrix3() {       a11=0; a12=0; a13=0;       a21=0; a22=0; a23=0;       a31=0; a32=0; a33=0;   }    /**     * Assign the zero matrix to this matrix     * @return <code>this</code>     */   public final Matrix3 assignZero() {     a11 = 0; a12 = 0; a13 = 0;     a21 = 0; a22 = 0; a23 = 0;     a31 = 0; a32 = 0; a33 = 0;           return this;   }      /**    * Construct a 3x3 matrix using specified fields    * @param a11    * @param a12    * @param a13    * @param a21    * @param a22    * @param a23    * @param a31    * @param a32    * @param a33    */   public Matrix3(double a11, double a12, double a13, double a21, double a22,     double a23, double a31, double a32, double a33) {     this.a11 = a11;   this.a12 = a12;   this.a13 = a13;   this.a21 = a21;   this.a22 = a22;   this.a23 = a23;   this.a31 = a31;   this.a32 = a32;   this.a33 = a33; }  /**   * create a 3x3 matrix using a set of basis vectors   * @param e1   * @param e2   * @param e3   */   public Matrix3( Vector3 e1, Vector3 e2, Vector3 e3) {     a11 = e1.x;     a21 = e1.y;     a31 = e1.z;          a12 = e2.x;     a22 = e2.y;     a32 = e2.z;          a13 = e3.x;     a23 = e3.y;     a33 = e3.z;   }      /**    * Construct a new 3x3 matrix as a copy of the given matrix B    * @param B    * @throws NullPointerException    */   public Matrix3( Matrix3 B) {    assign(B);   }    /**    * assign the value of B to this Matrix3    * @param B    */   public final Matrix3 assign(Matrix3 B) {     a11 = B.a11; a12 = B.a12; a13 = B.a13;     a21 = B.a21; a22 = B.a22; a23 = B.a23;     a31 = B.a31; a32 = B.a32; a33 = B.a33;           return this;   }   /**    * Assign the scale matrix given by s, to this matrix    */   public final Matrix3 assignScale(final double s) {     a11 = s; a12 = 0; a13 = 0;     a21 = 0; a22 = s; a23 = 0;     a31 = 0; a32 = 0; a33 = s;           return this;   }   /**    * Assign the non-uniform scale matrix given by s1, s2 and s3, to this matrix    */   public final Matrix3 assignScale(double sx, double sy, double sz) {     a11 = sx; a12 = 0.; a13 = 0.;     a21 = 0.; a22 = sy; a23 = 0.;     a31 = 0.; a32 = 0.; a33 = sz;     return this;   }      /**    * Assign the identity matrix to this matrix    */   public final Matrix3 assignIdentity() {     a11 = 1; a12 = 0; a13 = 0;     a21 = 0; a22 = 1; a23 = 0;     a31 = 0; a32 = 0; a33 = 1;           return this;   }     public Matrix3 assign(             double a11, double a12, double a13,             double a21, double a22, double a23,             double a31, double a32, double a33) {         this.a11 = a11;  this.a12 = a12;  this.a13 = a13;   this.a21 = a21;  this.a22 = a22;  this.a23 = a23;   this.a31 = a31;  this.a32 = a32;  this.a33 = a33;         return this;     }   /**    * Get the n'th column vector of this matrix    * @param n    * @return    * @throws IllegalArgumentException    */   public final Vector3 column(int n) {     switch (n) {     case 0:       return new Vector3(a11,a21,a31);     case 1:       return new Vector3(a12,a22,a32);     case 2:       return new Vector3(a13,a23,a33);               default:                   throw new IllegalArgumentException();     }     }      /**    * Get the n'th row vector of this matrix    * @param n    * @return    */   public Vector3 row(int n) {     switch (n) {     case 0:       return new Vector3(a11,a12,a13);     case 1:       return new Vector3(a21,a22,a23);     case 2:       return new Vector3(a31,a32,a33);               default:                   throw new IllegalArgumentException();     }     }      /**    * Get all column vectors of this matrix    * @param c1    * @param c2    * @param c3    */   public void getColumnVectors( Vector3 c1, Vector3 c2, Vector3 c3) {     c1.x = a11;     c1.y = a21;     c1.z = a31;     c2.x = a12;     c2.y = a22;     c2.z = a32;          c3.x = a13;     c3.y = a23;     c3.z = a33;   }      /**    * Get all row vectors of this matrix    * @param r1    * @param r2    * @param r3    */   public void getRowVectors( Vector3 r1, Vector3 r2, Vector3 r3) {     r1.x = a11;     r1.y = a12;     r1.z = a13;     r2.x = a21;     r2.y = a22;     r2.z = a23;          r3.x = a31;     r3.y = a32;     r3.z = a33;   }        /**    * Return a new identity Matrix3 instance    * @return    */   public static Matrix3 identity() {     return new Matrix3().assignIdentity();   }      /**    * Multiply this matrix by a scalar, return the resulting matrix    * @param s    * @return    */   public final Matrix3 multiply( double s) {     Matrix3 A = new Matrix3();     A.a11 = a11*s; A.a12 = a12*s; A.a13 = a13*s;     A.a21 = a21*s; A.a22 = a22*s; A.a23 = a23*s;     A.a31 = a31*s; A.a32 = a32*s; A.a33 = a33*s;         return A;   }      /**    * Right-multiply by a scaling matrix given by s, so M.scale(s) = M S(s)    * @param s    * @return    */   public final Matrix3 scale( Vector3 s ) {     Matrix3 A = new Matrix3();     A.a11 = a11*s.x; A.a12 = a12*s.y; A.a13 = a13*s.z;     A.a21 = a21*s.x; A.a22 = a22*s.y; A.a23 = a23*s.z;     A.a31 = a31*s.x; A.a32 = a32*s.y; A.a33 = a33*s.z;         return A;   }      /**    * Multiply this matrix by the matrix A and return the result    * @param A    * @return    */   public Matrix3 multiply(Matrix3 A) {     return multiply(this,A,new Matrix3());   }     /**    * Multiply this matrix by the matrix A and return the result    * @param A    * @return    */   public Matrix3 assignMultiply(Matrix3 A) {     return multiply(this,A,this);   }      //C = AxB    public static Matrix3 multiply( final Matrix3 A, final Matrix3 B, final Matrix3 C ) {     //               B | b11 b12 b13     //                 | b21 b22 b23     //                 | b31 b32 b33     //     -------------------------     //  A  a11 a12 a13 | c11 c12 c13     //     a21 a22 a23 | c21 c22 c23     //     a31 a32 a33 | c31 c32 c33  C          double t11 = A.a11*B.a11 + A.a12*B.a21 + A.a13*B.a31;     double t12 = A.a11*B.a12 + A.a12*B.a22 + A.a13*B.a32;     double t13 = A.a11*B.a13 + A.a12*B.a23 + A.a13*B.a33;          double t21 = A.a21*B.a11 + A.a22*B.a21 + A.a23*B.a31;     double t22 = A.a21*B.a12 + A.a22*B.a22 + A.a23*B.a32;     double t23 = A.a21*B.a13 + A.a22*B.a23 + A.a23*B.a33;          double t31 = A.a31*B.a11 + A.a32*B.a21 + A.a33*B.a31;     double t32 = A.a31*B.a12 + A.a32*B.a22 + A.a33*B.a32;     double t33 = A.a31*B.a13 + A.a32*B.a23 + A.a33*B.a33;     //copy to C     C.a11 = t11;     C.a12 = t12;     C.a13 = t13;     C.a21 = t21;     C.a22 = t22;     C.a23 = t23;     C.a31 = t31;     C.a32 = t32;     C.a33 = t33;     return C;   }      //functional   /**    * Multiply a vector by this matrix, return the resulting vector    */   public final Vector3 multiply( final Vector3 v) {     Vector3 r = new Vector3();     Matrix3.multiply(this, v, r);     return r;   }         //A = A^T    public Matrix3 assignTranspose() {     double t;   t=a12; a12=a21; a21=t;   t=a13; a13=a31; a31=t;   t=a23; a23=a32; a32=t;     return this;   }      /**    * Functional method. Transpose this matrix and return the result    * @return    */   public final Matrix3 transpose() {    return new Matrix3(this).assignTranspose();   }   //C = A-B   public static Matrix3 subtract( final Matrix3 A, final Matrix3 B, final Matrix3 C ) {     C.a11 = A.a11-B.a11; C.a12 = A.a12-B.a12; C.a13 = A.a13-B.a13;     C.a21 = A.a21-B.a21; C.a22 = A.a22-B.a22; C.a23 = A.a23-B.a23;     C.a31 = A.a31-B.a31; C.a32 = A.a32-B.a32; C.a33 = A.a33-B.a33;     return C;   }  /**    * Substract to this matrix the matrix B, return result in a new matrix instance    * @param B    * @return    */   public Matrix3 subtract( Matrix3 B ) {     return subtract(this,B,new Matrix3());   }   /**    * Substract to this matrix the matrix B, return result in a new matrix instance    * @param B    * @return    */   public Matrix3 assignSubtract( Matrix3 B ) {     return subtract(this,B,this);   }   /**    * Add to this matrix the matrix B, return result in a new matrix instance    * @param B    * @return    */   public Matrix3 add( Matrix3 B ) {     return add(this,B,new Matrix3());   }   /**    * Add to this matrix the matrix B, return result in a new matrix instance    * @param B    * @return    */   public Matrix3 assignAdd( Matrix3 B ) {     return add(this,B,this);   }      //C = A+B   public static Matrix3 add( final Matrix3 A, final Matrix3 B, final Matrix3 C ) {     C.a11 = A.a11+B.a11; C.a12 = A.a12+B.a12; C.a13 = A.a13+B.a13;     C.a21 = A.a21+B.a21; C.a22 = A.a22+B.a22; C.a23 = A.a23+B.a23;     C.a31 = A.a31+B.a31; C.a32 = A.a32+B.a32; C.a33 = A.a33+B.a33;     return C;   }      // rT = (vT)A   NOTE that the result of this is actually a transposed vector!!    public static Vector3 transposeVectorAndMultiply( final Vector3 v, final Matrix3 A, final Vector3 r ){     //            A  | a11 a12 a13     //               | a21 a22 a23     //               | a31 a32 a33     //      ----------------------     // vT   v1 v2 v3 |  c1  c2  c3          double t1 = v.x*A.a11+v.y*A.a21+v.z*A.a31;     double t2 = v.x*A.a12+v.y*A.a22+v.z*A.a32;     double t3 = v.x*A.a13+v.y*A.a23+v.z*A.a33;          r.x = t1;     r.y = t2;     r.z = t3;     return r;   }   /**    * Multiply v by A, and place result in r, so r = Av    * @param A 3 by 3 matrix    * @param v Vector to be multiplied    * @param r Vector to hold result of multiplication    * @return Reference to the given Vector3 r instance    */   public static Vector3 multiply( final Matrix3 A, final Vector3 v, final Vector3 r ) {     //                        //               V | v1     //                 | v2     //                 | v3                          //     -----------------     //  A  a11 a12 a13 | c1     //     a21 a22 a23 | c2     //     a31 a32 a33 | c3             double t1 = v.x*A.a11+v.y*A.a12+v.z*A.a13;     double t2 = v.x*A.a21+v.y*A.a22+v.z*A.a23;     double t3 = v.x*A.a31+v.y*A.a32+v.z*A.a33;          r.x = t1;     r.y = t2;     r.z = t3;          return r;   }     /**    * Compute the determinant of Matrix3 A    * @param A    * @return     */   public double determinant() {     return a11*a22*a33- a11*a23*a32 + a21*a32*a13 - a21*a12*a33 + a31*a12*a23-a31*a22*a13;   }    /**  * Compute the inverse of the matrix A, place the result in C  */   public static Matrix3 inverse( final Matrix3 A, final Matrix3 C ) {     double d = (A.a31*A.a12*A.a23-A.a31*A.a13*A.a22-A.a21*A.a12*A.a33+A.a21*A.a13*A.a32+A.a11*A.a22*A.a33-A.a11*A.a23*A.a32);     double t11 =  (A.a22*A.a33-A.a23*A.a32)/d;     double t12 = -(A.a12*A.a33-A.a13*A.a32)/d;     double t13 =  (A.a12*A.a23-A.a13*A.a22)/d;     double t21 = -(-A.a31*A.a23+A.a21*A.a33)/d;     double t22 =  (-A.a31*A.a13+A.a11*A.a33)/d;     double t23 = -(-A.a21*A.a13+A.a11*A.a23)/d;     double t31 =  (-A.a31*A.a22+A.a21*A.a32)/d;     double t32 = -(-A.a31*A.a12+A.a11*A.a32)/d;     double t33 =  (-A.a21*A.a12+A.a11*A.a22)/d;     C.a11 = t11; C.a12 = t12; C.a13 = t13;     C.a21 = t21; C.a22 = t22; C.a23 = t23;     C.a31 = t31; C.a32 = t32; C.a33 = t33;     return C;   }   public final Matrix3 assignInverse() {       return inverse(this,this);   }   public final Matrix3 inverse() {         return inverse(this,new Matrix3());   }   public static Matrix3 scaleMatrix( double xs, double ys, double zs) {       return new Matrix3().assignScale(xs,ys,zs);   }      public static Matrix3 scaleMatrix( double s ) {       return new Matrix3().assignScale(s);         }         @Override   public String toString() {     return "["+a11+", " + a12 + ", " + a13 + "]\n"          + "["+a21+", " + a22 + ", " + a23 + "]\n"          + "["+a31+", " + a32 + ", " + a33 + "]" ;   }      /**    * Check matrix for NaN values     */   public final boolean isNaN() {     return Double.isNaN(a11)||Double.isNaN(a12)||Double.isNaN(a13)     || Double.isNaN(a21)||Double.isNaN(a22)||Double.isNaN(a23)     || Double.isNaN(a31)||Double.isNaN(a32)||Double.isNaN(a33);   }      public double[] toArray() {        return new double[]{                   a11, a21, a31,                   a12, a22, a32,                   a13, a23, a33};   }   /**    * Return the Frobenius norm of this Matrix3    * @return    */   public final double fnorm() {     return Math.sqrt(  a11*a11 + a12*a12 + a13*a13  + a21*a21 + a22*a22  + a23*a23  + a31*a31 + a32*a32 + a33*a33 );    }     /**      *      * @param v      * @return      * @throws NullPointerException      */     public static Matrix3 crossProductMatrix(Vector3 v) {         return new Matrix3(                 0., -v.z, v.y,                 v.z, 0., -v.x,                 -v.y, v.x, 0.);     } } /**  * <code>Vector3d</code> defines a Vector for a three double value tuple.  * <code>Vector3d</code> can represent any three dimensional value, such as a  * vertex or normal.  *  * The functional methods like add, sub, multiply that returns new instances, and  * left <code>this</code> unchanged.  *  * Static methods store the resulting vector on a existing reference, which avoid  * allowcation an can improove performances around 20% (profiling performend on vector  * addition).  *  * Deprecated methods will be removed on October 2010  *  * @author Morten Silcowitz  * @author Pierre Labatut   */  final class Vector3 implements Serializable {   private static final long serialVersionUID = 1L;         /**          * The x coordinate.          */   public double x;         /**          * The y coordinate.          */         public double y;         /**          * The z coordinate.          */         public double z;            public transient final static double e = 1e-9f;   /**          * Constructs and initializes a <code>Vector3</code> to [0., 0., 0.]          */   public Vector3 () {     x=0; y=0; z=0;   }         /**          * Constructs and initializes a <code>Vector3</code> from the specified          * xyz coordinates.          * @param x the x coordinate          * @param y the y coordinate          * @param z the z coordinate          */   public Vector3( double x, double y, double z) {     this.x=x; this.y=y; this.z=z;   }         /**          * Constructs and initializes a <code>Vector3</code> with the coordinates          * of the given <code>Vector3</code>.          * @param v the <code>Vector3</code> containing the initialization x y z data          * @throws NullPointerException when v is null          */   public Vector3( Vector3 v ) {     x=v.x; y=v.y; z = v.z;   }     /**      * Create a new unit vector heading positive x      * @return a new unit vector heading positive x      */     public static Vector3 i() {         return new Vector3(1., 0., 0.);     }     /**      * Create a new unit vector heading positive y      * @return a new unit vector heading positive y      */     public static Vector3 j() {         return new Vector3(0., 1., 0.);     }     /**      * Create a new unit vector heading positive z      * @return a new unit vector heading positive z      */     public static Vector3 k() {         return new Vector3(0., 0., 1.);     }         /**          * Adds a provided vector to this vector creating a resultant          * vector which is returned.          * Neither <code>this</code> nor <code>v</code> is modified.          *          * @param v the vector to add to this.          * @return resultant vector          * @throws NullPointerException if v is null          */   public final Vector3 add( Vector3 v) {     return new Vector3( x+v.x, y+v.y, z+v.z );   }         /**          * Multiply the vector coordinates by -1. creating a resultant vector          * which is returned.          * <code>this</code> vector is not modified.          *          * @return resultant vector          * @throws NullPointerException if v is null          */   public final Vector3 negate() {     return new Vector3(-x,-y,-z);   }   /**          * Returns true if one of the coordinated is not a number          * <code>this</code> vector is not modified.          * @return true if one of the coordinated is not a number          */   public final boolean isNaN() {     return Double.isNaN(x)||Double.isNaN(y)||Double.isNaN(z);   }         /**          * Get a coordinate from a dimention ordinal.          * @param i the dimention ordinal number. 1 is x, 2 is y 3 is z.          * @return <ul>          *<li>         x coordiante when i is 0</li>          *<li>         y coordiante when i is 1</li>          *<li>         z coordiante when i is 2</li>          * </ul>          */   public double get( int i ) {     return i>0?(i>1?z:y):x;    }         /**          * Set a coordinate from a dimention ordinal.          * @param i the dimention ordinal number. 1 is x, 2 is y 3 is z.          * @param v new coordinate value          */   public void set( int i, double v ) {     if (i == 0) {       x = v;     } else {       if ( i==1) {         y=v;       }else {         z=v;       }     }   }            /**          * Add two vectors and place the result in v1.          * <code>v2</code> is not modified.          * @param v1 a not null reference, store the sum          * @param v2 a not null reference          * @throws NullPointerException if v1 or v2 is null          */   public static void add( final Vector3 v1, final Vector3 v2 ) {     v1.x += v2.x;     v1.y += v2.y;     v1.z += v2.z;   }         /**          * Substract two vectors and place the result in v1.          * <code>v2</code> is not modified.          * @param v1 a not null reference, store the difference          * @param v2 a not null reference          * @throws NullPointerException if v1 or v2 is null          */   public static void sub( final Vector3 v1, final Vector3 v2 ) {     v1.x -= v2.x;     v1.y -= v2.y;     v1.z -= v2.z;   }         /**          * Substracts a provided vector to this vector creating a resultant          * vector which is returned.          * Neither <code>this</code> nor <code>v</code> is modified.          *          * @param v the vector to add to this.          * @return resultant vector          */         public final Vector3 sub( Vector3 v ) {     return new Vector3( x-v.x, y-v.y, z-v.z );   }         /**          * Multiply this vector by a provided scalar creating a resultant          * vector which is returned.          * <code>this</code> vector is not modified.          *          * @param s multiplication coeficient          * @return resultant vector          */   public final Vector3 multiply( double s ) {     return new Vector3( x*s, y*s, z*s);   }      /**    * Scale vector by the scale matrix given by s.          * <code>this</code> vector is not modified.    * @param s scale direction and factor    * @return an new vector    */   public final Vector3 scale( Vector3 s) {     return new Vector3(x*s.x, y*s.y, z*s.z);   }         /**          * Multiply a given vector by a scalar and place the result in v          * @param v vector multipled          * @param s scalar used to scale the vector          * @throws NullPointerException if v is null          */   public static void multiply( Vector3 v, double s) {     v.x*=s; v.y*=s; v.z*=s;   }         /**          *          * @param v          * @param s          * @param result          * @throws NullPointerException if v ot result is null          */   public static void multiplyAndAdd( Vector3 v, double s, Vector3 result) {     result.x += v.x*s;      result.y += v.y*s;      result.z += v.z*s;   }   /**    * Multiply v by s, and store result in v. Add v to result and store in result    * @param v    * @param s    * @param result          * @throws NullPointerException if v ot result is null    */   public static void  multiplyStoreAndAdd( Vector3 v, double s, Vector3 result) {     v.x *= s;     v.y *= s;     v.z *= s;         result.x += v.x;      result.y += v.y;      result.z += v.z;   }         /**          * Returns the dot product of this vector and vector v.          * Neither <code>this</code> nor <code>v</code> is modified.          * @param v the other vector          * @return the dot product of this and v1          * @throws NullPointerException if v is null          */   public final double dot( Vector3 v ) {     return this.x*v.x+this.y*v.y+this.z*v.z;   }    /**          * Returns the dot product of this vector and vector v.          * Neither <code>this</code> nor <code>v</code> is modified.          * z coordinated if trucated          * @param v the other vector          * @return the dot product of this and v1          * @throws NullPointerException          */     public final double xydot( Vector3 v ) {     return this.x*v.x+this.y*v.y;   }   /**          * Return a new new set to the cross product of this vectors and v          * Neither <code>this</code> nor <code>v</code> is modified.          * @param v a not null vector          * @return the cross product          * @throws NullPointerException when v is null          */   public final Vector3 cross( final Vector3 v ) {     return new Vector3( y*v.z-z*v.y, z*v.x-x*v.z, x*v.y-y*v.x );    }        /**         * Sets result vector to the vector cross product of vectors v1 and v2.         * Neither <code>v1</code> nor <code>v2</code> is modified.         * @param v1 the first vector         * @param v2 the second vector         * @param result         */   public static void crossProduct( final Vector3 v1, final Vector3 v2, final Vector3 result ) {     final double tempa1 = v1.y*v2.z-v1.z*v2.y;     final double tempa2 = v1.z*v2.x-v1.x*v2.z;     final double tempa3 = v1.x*v2.y-v1.y*v2.x;     result.x = tempa1;     result.y = tempa2;     result.z = tempa3;   }         /**          * Return a new vector set to the normalization of vector v1.          * <code>this</code> vector is not modified.          * @return the normalized vector          */   public final Vector3 normalize() {     double l = Math.sqrt(x*x+y*y+z*z);     if ( l == 0.0 ) {return new Vector3(1,0,0); }                 l=1./l;     return new Vector3( x*l, y*l, z*l);   }         /**          * Sets the value of this <code>Vector3</code> to the specified x, y and  coordinates.          * @param x the x coordinate          * @param y the y coordinate          * @param z the z coordinate          * @return return this          */         public final Vector3 assign( double x, double y, double z ) {     this.x = x;     this.y = y;     this.z = z;     return this;   }         /**          * A this vector to the provided coordinates creating a new resultant vector.          * <code>this</code> vector is not modified          * @param x the x coordinate          * @param y the y coordinate          * @param z the z coordinate          * @return the result vector          */   public final Vector3 add( double x, double y, double z ) {     return new Vector3( this.x+x, this.y+y, this.z+z);   }   /**          * Sets the value of this vector to the value of the xyz coordinates of the          * given vector.          * <code>v</code> is not modified          * @param v the vector to be copied          * @return <code>this</code>          * @throws NullPointerException          */   public final Vector3 assign( Vector3 v ) {     double t1 =v.x;     double t2 =v.y;     double t3 =v.z;     x = t1;     y = t2;     z = t3;     return this;   }         /**          *          * @return          */   public final Vector3 assignZero() {     x = 0;     y = 0;     z = 0;     return this;   }           /**          * Returns the length of this vector.          * <code>this</code> vector is not modified.          * @return Returns the length of this vector.          */   public final double norm() {     return Math.sqrt( x*x + y*y + z*z );   }   /**          * Returns the length of this vector.          * z coordinate is truncated.          * <code>this</code> vector is not modified.          * @return Double.NaN when Double.isNaN(x) || Double.isNaN(y)          */   public final double xynorm() {     return Math.sqrt( x*x + y*y );   }                 /**          * Returns the length of this vector.          * <code>this</code> vector is not modified.          * @return the length of this vector          */   public final double squaredNorm() {     return x*x+y*y+z*z;   }             /**      * Returns <tt>true</tt> if the absolute value of the three coordinates are      * smaller or equal to epsilon.      *      * @param epsilon positive tolerance around zero      * @return true when the coordinates are next to zero      *         false in the other cases      */     public final boolean isEpsilon(double epsilon) {         if (epsilon < 0.) {             throw new IllegalArgumentException("epsilon must be positive");         }         return -epsilon <= x && x <= epsilon                 && -epsilon <= y && y <= epsilon                 && -epsilon <= z && z <= epsilon;     }         /**          * Pack the three coorindates into a new double array          * <code>this</code> vector is not modified.          * @return a array set with x, y and z          */   public final double[] toArray() {     return new double[]{x,y,z};   }         /**          * Returns a string representation of this vector.  The string          * representation consists of the three dimentions in the order x, y, z,          * enclosed in square brackets (<tt>"[]"</tt>). Adjacent elements are          * separated by the characters <tt>", "</tt> (comma and space).          * Elements are converted to strings as by {@link Double#toString(double)}.          *          * @return a string representation of this vector          */   @Override   public final String toString() {     return  "[" + x + ", " +y+ ", " +z + "]";   } }