Mega Code Archive

 
Categories / Java / Development Class
 

Matrix manipulation

/**  * Copyright (c) 2003, www.pdfbox.org  * All rights reserved.  *  * Redistribution and use in source and binary forms, with or without  * modification, are permitted provided that the following conditions are met:  *  * 1. Redistributions of source code must retain the above copyright notice,  *    this list of conditions and the following disclaimer.  * 2. Redistributions in binary form must reproduce the above copyright notice,  *    this list of conditions and the following disclaimer in the documentation  *    and/or other materials provided with the distribution.  * 3. Neither the name of pdfbox; nor the names of its  *    contributors may be used to endorse or promote products derived from this  *    software without specific prior written permission.  *  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE  * DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  *  * http://www.pdfbox.org  *  */ import java.awt.geom.AffineTransform; /**  * This class will be used for matrix manipulation.  *  * @author <a href="mailto:ben@benlitchfield.com">Ben Litchfield</a>  * @version $Revision: 1.14 $  */ public class Matrix implements Cloneable {     private float[] single =      {          1,0,0,         0,1,0,         0,0,1     };     /**      * Constructor.      */     public Matrix()     {         //default constructor     }          /**      * Create an affine transform from this matrix's values.      *       * @return An affine transform with this matrix's values.      */     public AffineTransform createAffineTransform()     {         AffineTransform retval = new AffineTransform(             single[0], single[1],              single[3], single[4],             single[6], single[7] );         return retval;     }          /**      * Set the values of the matrix from the AffineTransform.      *       * @param af The transform to get the values from.      */     public void setFromAffineTransform( AffineTransform af )     {         single[0] = (float)af.getScaleX();         single[1] = (float)af.getShearY();         single[3] = (float)af.getShearX();         single[4] = (float)af.getScaleY();         single[6] = (float)af.getTranslateX();         single[7] = (float)af.getTranslateY();     }     /**      * This will get a matrix value at some point.      *      * @param row The row to get the value from.      * @param column The column to get the value from.      *      * @return The value at the row/column position.      */     public float getValue( int row, int column )     {         return single[row*3+column];     }     /**      * This will set a value at a position.      *      * @param row The row to set the value at.      * @param column the column to set the value at.      * @param value The value to set at the position.      */     public void setValue( int row, int column, float value )     {         single[row*3+column] = value;     }          /**      * Return a single dimension array of all values in the matrix.      *       * @return The values ot this matrix.      */     public float[][] getValues()     {         float[][] retval = new float[3][3];         retval[0][0] = single[0];         retval[0][1] = single[1];         retval[0][2] = single[2];         retval[1][0] = single[3];         retval[1][1] = single[4];         retval[1][2] = single[5];         retval[2][0] = single[6];         retval[2][1] = single[7];         retval[2][2] = single[8];         return retval;     }          /**      * Return a single dimension array of all values in the matrix.      *       * @return The values ot this matrix.      */     public double[][] getValuesAsDouble()     {         double[][] retval = new double[3][3];         retval[0][0] = single[0];         retval[0][1] = single[1];         retval[0][2] = single[2];         retval[1][0] = single[3];         retval[1][1] = single[4];         retval[1][2] = single[5];         retval[2][0] = single[6];         retval[2][1] = single[7];         retval[2][2] = single[8];         return retval;     }     /**      * This will take the current matrix and multipy it with a matrix that is passed in.      *      * @param b The matrix to multiply by.      *      * @return The result of the two multiplied matrices.      */     public Matrix multiply( Matrix b )     {         Matrix result = new Matrix();         float[] bMatrix = b.single;         float[] resultMatrix = result.single;         resultMatrix[0] = single[0] * bMatrix[0] + single[1] * bMatrix[3] + single[2] * bMatrix[6];         resultMatrix[1] = single[0] * bMatrix[1] + single[1] * bMatrix[4] + single[2] * bMatrix[7];         resultMatrix[2] = single[0] * bMatrix[2] + single[1] * bMatrix[5] + single[2] * bMatrix[8];         resultMatrix[3] = single[3] * bMatrix[0] + single[4] * bMatrix[3] + single[5] * bMatrix[6];         resultMatrix[4] = single[3] * bMatrix[1] + single[4] * bMatrix[4] + single[5] * bMatrix[7];         resultMatrix[5] = single[3] * bMatrix[2] + single[4] * bMatrix[5] + single[5] * bMatrix[8];         resultMatrix[6] = single[6] * bMatrix[0] + single[7] * bMatrix[3] + single[8] * bMatrix[6];         resultMatrix[7] = single[6] * bMatrix[1] + single[7] * bMatrix[4] + single[8] * bMatrix[7];         resultMatrix[8] = single[6] * bMatrix[2] + single[7] * bMatrix[5] + single[8] * bMatrix[8];         return result;     }          /**      * Create a new matrix with just the scaling operators.      *       * @return A new matrix with just the scaling operators.      */     public Matrix extractScaling()     {         Matrix retval = new Matrix();                  retval.single[0] = this.single[0];         retval.single[4] = this.single[4];                  return retval;     }          /**      * Convenience method to create a scaled instance.       *       * @param x The xscale operator.      * @param y The yscale operator.      * @return A new matrix with just the x/y scaling      */     public static Matrix getScaleInstance( float x, float y)     {         Matrix retval = new Matrix();                  retval.single[0] = x;         retval.single[4] = y;                  return retval;     }          /**      * Create a new matrix with just the translating operators.      *       * @return A new matrix with just the translating operators.      */     public Matrix extractTranslating()     {         Matrix retval = new Matrix();                  retval.single[6] = this.single[6];         retval.single[7] = this.single[7];                  return retval;     }          /**      * Convenience method to create a translating instance.       *       * @param x The x translating operator.      * @param y The y translating operator.      * @return A new matrix with just the x/y translating.      */     public static Matrix getTranslatingInstance( float x, float y)     {         Matrix retval = new Matrix();                  retval.single[6] = x;         retval.single[7] = y;                  return retval;     }     /**      * Clones this object.      * @return cloned matrix as an object.      */     public Object clone()     {         Matrix clone = new Matrix();         System.arraycopy( single, 0, clone.single, 0, 9 );         return clone;     }     /**      * This will copy the text matrix data.      *      * @return a matrix that matches this one.      */     public Matrix copy()     {         return (Matrix) clone();     }     /**      * This will return a string representation of the matrix.      *      * @return The matrix as a string.      */     public String toString()     {         StringBuffer result = new StringBuffer( "" );         result.append( "[[" );         result.append( single[0] + "," );         result.append( single[1] + "," );         result.append( single[2] + "][");         result.append( single[3] + "," );         result.append( single[4] + "," );         result.append( single[5] + "][");         result.append( single[6] + "," );         result.append( single[7] + "," );         result.append( single[8] + "]]");                  return result.toString();     }          /**      * Get the xscaling factor of this matrix.      * @return The x-scale.      */     public float getXScale()     {         float xScale = single[0];                  /**          * BM: if the trm is rotated, the calculation is a little more complicated           *           * The rotation matrix multiplied with the scaling matrix is:          * (   x   0   0)    ( cos  sin  0)    ( x*cos x*sin   0)          * (   0   y   0) *  (-sin  cos  0)  = (-y*sin y*cos   0)          * (   0   0   1)    (   0    0  1)    (     0     0   1)          *          * So, if you want to deduce x from the matrix you take          * M(0,0) = x*cos and M(0,1) = x*sin and use the theorem of Pythagoras          *           * sqrt(M(0,0)^2+M(0,1)^2) =          * sqrt(x2*cos2+x2*sin2) =          * sqrt(x2*(cos2+sin2)) = <- here is the trick cos2+sin2 is one          * sqrt(x2) =          * abs(x)           */         if( !(single[1]==0.0f && single[3]==0.0f) )         {             xScale = (float)Math.sqrt(Math.pow(single[0], 2)+                                       Math.pow(single[1], 2));         }          return xScale;     }          /**      * Get the y scaling factor of this matrix.      * @return The y-scale factor.      */     public float getYScale()     {         float yScale = single[4];         if( !(single[1]==0.0f && single[3]==0.0f) )         {             yScale = (float)Math.sqrt(Math.pow(single[3], 2)+                                       Math.pow(single[4], 2));         }          return yScale;     }          /**      * Get the x position in the matrix.      * @return The x-position.      */     public float getXPosition()     {         return single[6];     }          /**      * Get the y position.      * @return The y position.      */     public float getYPosition()     {         return single[7];     } }