home *** CD-ROM | disk | FTP | other *** search
/ Chip 2005 February / CMCD0205.ISO / Linux / gimp-2.2.0.tar.gz / gimp-2.2.0.tar / gimp-2.2.0 / libgimpmath / gimpmatrix.c < prev    next >
C/C++ Source or Header  |  2003-11-15  |  13KB  |  506 lines

  1. /* LIBGIMP - The GIMP Library
  2.  * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
  3.  *
  4.  * gimpmatrix.c
  5.  * Copyright (C) 1998 Jay Cox <jaycox@earthlink.net>
  6.  *
  7.  * This library is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU Lesser General Public
  9.  * License as published by the Free Software Foundation; either
  10.  * version 2 of the License, or (at your option) any later version.
  11.  *
  12.  * This library is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  * Library General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU Lesser General Public
  18.  * License along with this library; if not, write to the
  19.  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  20.  * Boston, MA 02111-1307, USA.
  21.  */
  22.  
  23. #include "config.h"
  24.  
  25. #include <glib.h>
  26.  
  27. #include "gimpmath.h"
  28.  
  29.  
  30. #define EPSILON 1e-6
  31.  
  32.  
  33. /**
  34.  * gimp_matrix2_identity:
  35.  * @matrix: A matrix.
  36.  *
  37.  * Sets the matrix to the identity matrix.
  38.  */
  39. void
  40. gimp_matrix2_identity (GimpMatrix2 *matrix)
  41. {
  42.   static const GimpMatrix2 identity = { { { 1.0, 0.0 },
  43.                                           { 0.0, 1.0 } } };
  44.  
  45.   *matrix = identity;
  46. }
  47.  
  48. /**
  49.  * gimp_matrix2_mult:
  50.  * @matrix1: The first input matrix.
  51.  * @matrix2: The second input matrix which will be overwritten by the result.
  52.  *
  53.  * Multiplies two matrices and puts the result into the second one.
  54.  */
  55. void
  56. gimp_matrix2_mult (const GimpMatrix2 *matrix1,
  57.                    GimpMatrix2       *matrix2)
  58. {
  59.   GimpMatrix2  tmp;
  60.  
  61.   tmp.coeff[0][0] = (matrix1->coeff[0][0] * matrix2->coeff[0][0] +
  62.                      matrix1->coeff[0][1] * matrix2->coeff[1][0]);
  63.   tmp.coeff[0][1] = (matrix1->coeff[0][0] * matrix2->coeff[0][1] +
  64.                      matrix1->coeff[0][1] * matrix2->coeff[1][1]);
  65.   tmp.coeff[1][0] = (matrix1->coeff[1][0] * matrix2->coeff[0][0] +
  66.                      matrix1->coeff[1][1] * matrix2->coeff[1][0]);
  67.   tmp.coeff[1][1] = (matrix1->coeff[1][0] * matrix2->coeff[0][1] +
  68.                      matrix1->coeff[1][1] * matrix2->coeff[1][1]);
  69.  
  70.   *matrix2 = tmp;
  71. }
  72.  
  73. /**
  74.  * gimp_matrix3_identity:
  75.  * @matrix: A matrix.
  76.  *
  77.  * Sets the matrix to the identity matrix.
  78.  */
  79. void
  80. gimp_matrix3_identity (GimpMatrix3 *matrix)
  81. {
  82.   static const GimpMatrix3 identity = { { { 1.0, 0.0, 0.0 },
  83.                                           { 0.0, 1.0, 0.0 },
  84.                                           { 0.0, 0.0, 1.0 } } };
  85.  
  86.   *matrix = identity;
  87. }
  88.  
  89. /**
  90.  * gimp_matrix3_transform_point:
  91.  * @matrix: The transformation matrix.
  92.  * @x: The source X coordinate.
  93.  * @y: The source Y coordinate.
  94.  * @newx: The transformed X coordinate.
  95.  * @newy: The transformed Y coordinate.
  96.  *
  97.  * Transforms a point in 2D as specified by the transformation matrix.
  98.  */
  99. void
  100. gimp_matrix3_transform_point (const GimpMatrix3 *matrix,
  101.                               gdouble            x,
  102.                               gdouble            y,
  103.                               gdouble           *newx,
  104.                               gdouble           *newy)
  105. {
  106.   gdouble  w;
  107.  
  108.   w = matrix->coeff[2][0] * x + matrix->coeff[2][1] * y + matrix->coeff[2][2];
  109.  
  110.   if (w == 0.0)
  111.     w = 1.0;
  112.   else
  113.     w = 1.0/w;
  114.  
  115.   *newx = (matrix->coeff[0][0] * x +
  116.            matrix->coeff[0][1] * y +
  117.            matrix->coeff[0][2]) * w;
  118.   *newy = (matrix->coeff[1][0] * x +
  119.            matrix->coeff[1][1] * y +
  120.            matrix->coeff[1][2]) * w;
  121. }
  122.  
  123. /**
  124.  * gimp_matrix3_mult:
  125.  * @matrix1: The first input matrix.
  126.  * @matrix2: The second input matrix which will be overwritten by the result.
  127.  *
  128.  * Multiplies two matrices and puts the result into the second one.
  129.  */
  130. void
  131. gimp_matrix3_mult (const GimpMatrix3 *matrix1,
  132.                    GimpMatrix3       *matrix2)
  133. {
  134.   gint         i, j;
  135.   GimpMatrix3  tmp;
  136.   gdouble      t1, t2, t3;
  137.  
  138.   for (i = 0; i < 3; i++)
  139.     {
  140.       t1 = matrix1->coeff[i][0];
  141.       t2 = matrix1->coeff[i][1];
  142.       t3 = matrix1->coeff[i][2];
  143.  
  144.       for (j = 0; j < 3; j++)
  145.         {
  146.           tmp.coeff[i][j]  = t1 * matrix2->coeff[0][j];
  147.           tmp.coeff[i][j] += t2 * matrix2->coeff[1][j];
  148.           tmp.coeff[i][j] += t3 * matrix2->coeff[2][j];
  149.         }
  150.     }
  151.  
  152.   *matrix2 = tmp;
  153. }
  154.  
  155. /**
  156.  * gimp_matrix3_translate:
  157.  * @matrix: The matrix that is to be translated.
  158.  * @x: Translation in X direction.
  159.  * @y: Translation in Y direction.
  160.  *
  161.  * Translates the matrix by x and y.
  162.  */
  163. void
  164. gimp_matrix3_translate (GimpMatrix3 *matrix,
  165.                         gdouble      x,
  166.                         gdouble      y)
  167. {
  168.   gdouble g, h, i;
  169.  
  170.   g = matrix->coeff[2][0];
  171.   h = matrix->coeff[2][1];
  172.   i = matrix->coeff[2][2];
  173.  
  174.   matrix->coeff[0][0] += x * g;
  175.   matrix->coeff[0][1] += x * h;
  176.   matrix->coeff[0][2] += x * i;
  177.   matrix->coeff[1][0] += y * g;
  178.   matrix->coeff[1][1] += y * h;
  179.   matrix->coeff[1][2] += y * i;
  180. }
  181.  
  182. /**
  183.  * gimp_matrix3_scale:
  184.  * @matrix: The matrix that is to be scaled.
  185.  * @x: X scale factor.
  186.  * @y: Y scale factor.
  187.  *
  188.  * Scales the matrix by x and y
  189.  */
  190. void
  191. gimp_matrix3_scale (GimpMatrix3 *matrix,
  192.                     gdouble      x,
  193.                     gdouble      y)
  194. {
  195.   matrix->coeff[0][0] *= x;
  196.   matrix->coeff[0][1] *= x;
  197.   matrix->coeff[0][2] *= x;
  198.  
  199.   matrix->coeff[1][0] *= y;
  200.   matrix->coeff[1][1] *= y;
  201.   matrix->coeff[1][2] *= y;
  202. }
  203.  
  204. /**
  205.  * gimp_matrix3_rotate:
  206.  * @matrix: The matrix that is to be rotated.
  207.  * @theta: The angle of rotation (in radians).
  208.  *
  209.  * Rotates the matrix by theta degrees.
  210.  */
  211. void
  212. gimp_matrix3_rotate (GimpMatrix3 *matrix,
  213.                      gdouble      theta)
  214. {
  215.   gdouble t1, t2;
  216.   gdouble cost, sint;
  217.  
  218.   cost = cos (theta);
  219.   sint = sin (theta);
  220.  
  221.   t1 = matrix->coeff[0][0];
  222.   t2 = matrix->coeff[1][0];
  223.   matrix->coeff[0][0] = cost * t1 - sint * t2;
  224.   matrix->coeff[1][0] = sint * t1 + cost * t2;
  225.  
  226.   t1 = matrix->coeff[0][1];
  227.   t2 = matrix->coeff[1][1];
  228.   matrix->coeff[0][1] = cost * t1 - sint * t2;
  229.   matrix->coeff[1][1] = sint * t1 + cost * t2;
  230.  
  231.   t1 = matrix->coeff[0][2];
  232.   t2 = matrix->coeff[1][2];
  233.   matrix->coeff[0][2] = cost * t1 - sint * t2;
  234.   matrix->coeff[1][2] = sint * t1 + cost * t2;
  235. }
  236.  
  237. /**
  238.  * gimp_matrix3_xshear:
  239.  * @matrix: The matrix that is to be sheared.
  240.  * @amount: X shear amount.
  241.  *
  242.  * Shears the matrix in the X direction.
  243.  */
  244. void
  245. gimp_matrix3_xshear (GimpMatrix3 *matrix,
  246.                      gdouble      amount)
  247. {
  248.   matrix->coeff[0][0] += amount * matrix->coeff[1][0];
  249.   matrix->coeff[0][1] += amount * matrix->coeff[1][1];
  250.   matrix->coeff[0][2] += amount * matrix->coeff[1][2];
  251. }
  252.  
  253. /**
  254.  * gimp_matrix3_yshear:
  255.  * @matrix: The matrix that is to be sheared.
  256.  * @amount: Y shear amount.
  257.  *
  258.  * Shears the matrix in the Y direction.
  259.  */
  260. void
  261. gimp_matrix3_yshear (GimpMatrix3 *matrix,
  262.                      gdouble      amount)
  263. {
  264.   matrix->coeff[1][0] += amount * matrix->coeff[0][0];
  265.   matrix->coeff[1][1] += amount * matrix->coeff[0][1];
  266.   matrix->coeff[1][2] += amount * matrix->coeff[0][2];
  267. }
  268.  
  269.  
  270. /**
  271.  * gimp_matrix3_affine:
  272.  * @matrix: The input matrix.
  273.  * @a:
  274.  * @b:
  275.  * @c:
  276.  * @d:
  277.  * @e:
  278.  * @f:
  279.  *
  280.  * Applies the affine transformation given by six values to @matrix.
  281.  * The six values form define an affine transformation matrix as
  282.  * illustrated below:
  283.  *
  284.  *  ( a c e )
  285.  *  ( b d f )
  286.  *  ( 0 0 1 )
  287.  **/
  288. void
  289. gimp_matrix3_affine (GimpMatrix3 *matrix,
  290.                      gdouble      a,
  291.                      gdouble      b,
  292.                      gdouble      c,
  293.                      gdouble      d,
  294.                      gdouble      e,
  295.                      gdouble      f)
  296. {
  297.   GimpMatrix3 affine;
  298.  
  299.   affine.coeff[0][0] = a;
  300.   affine.coeff[1][0] = b;
  301.   affine.coeff[2][0] = 0.0;
  302.  
  303.   affine.coeff[0][1] = c;
  304.   affine.coeff[1][1] = d;
  305.   affine.coeff[2][1] = 0.0;
  306.  
  307.   affine.coeff[0][2] = e;
  308.   affine.coeff[1][2] = f;
  309.   affine.coeff[2][2] = 1.0;
  310.  
  311.   gimp_matrix3_mult (&affine, matrix);
  312. }
  313.  
  314.  
  315. /**
  316.  * gimp_matrix3_determinant:
  317.  * @matrix: The input matrix.
  318.  *
  319.  * Calculates the determinant of the given matrix.
  320.  *
  321.  * Returns: The determinant.
  322.  */
  323. gdouble
  324. gimp_matrix3_determinant (const GimpMatrix3 *matrix)
  325. {
  326.   gdouble determinant;
  327.  
  328.   determinant  = (matrix->coeff[0][0] *
  329.                   (matrix->coeff[1][1] * matrix->coeff[2][2] -
  330.                    matrix->coeff[1][2] * matrix->coeff[2][1]));
  331.   determinant -= (matrix->coeff[1][0] *
  332.                   (matrix->coeff[0][1] * matrix->coeff[2][2] -
  333.                    matrix->coeff[0][2] * matrix->coeff[2][1]));
  334.   determinant += (matrix->coeff[2][0] *
  335.                   (matrix->coeff[0][1] * matrix->coeff[1][2] -
  336.                    matrix->coeff[0][2] * matrix->coeff[1][1]));
  337.  
  338.   return determinant;
  339. }
  340.  
  341. /**
  342.  * gimp_matrix3_invert:
  343.  * @matrix: The matrix that is to be inverted.
  344.  *
  345.  * Inverts the given matrix.
  346.  */
  347. void
  348. gimp_matrix3_invert (GimpMatrix3 *matrix)
  349. {
  350.   GimpMatrix3 inv;
  351.   gdouble     det;
  352.  
  353.   det = gimp_matrix3_determinant (matrix);
  354.  
  355.   if (det == 0.0)
  356.     return;
  357.  
  358.   det = 1.0 / det;
  359.  
  360.   inv.coeff[0][0] =   (matrix->coeff[1][1] * matrix->coeff[2][2] -
  361.                        matrix->coeff[1][2] * matrix->coeff[2][1]) * det;
  362.  
  363.   inv.coeff[1][0] = - (matrix->coeff[1][0] * matrix->coeff[2][2] -
  364.                        matrix->coeff[1][2] * matrix->coeff[2][0]) * det;
  365.  
  366.   inv.coeff[2][0] =   (matrix->coeff[1][0] * matrix->coeff[2][1] -
  367.                        matrix->coeff[1][1] * matrix->coeff[2][0]) * det;
  368.  
  369.   inv.coeff[0][1] = - (matrix->coeff[0][1] * matrix->coeff[2][2] -
  370.                        matrix->coeff[0][2] * matrix->coeff[2][1]) * det;
  371.  
  372.   inv.coeff[1][1] =   (matrix->coeff[0][0] * matrix->coeff[2][2] -
  373.                        matrix->coeff[0][2] * matrix->coeff[2][0]) * det;
  374.  
  375.   inv.coeff[2][1] = - (matrix->coeff[0][0] * matrix->coeff[2][1] -
  376.                        matrix->coeff[0][1] * matrix->coeff[2][0]) * det;
  377.  
  378.   inv.coeff[0][2] =   (matrix->coeff[0][1] * matrix->coeff[1][2] -
  379.                        matrix->coeff[0][2] * matrix->coeff[1][1]) * det;
  380.  
  381.   inv.coeff[1][2] = - (matrix->coeff[0][0] * matrix->coeff[1][2] -
  382.                        matrix->coeff[0][2] * matrix->coeff[1][0]) * det;
  383.  
  384.   inv.coeff[2][2] =   (matrix->coeff[0][0] * matrix->coeff[1][1] -
  385.                        matrix->coeff[0][1] * matrix->coeff[1][0]) * det;
  386.  
  387.   *matrix = inv;
  388. }
  389.  
  390.  
  391. /*  functions to test for matrix properties  */
  392.  
  393.  
  394. /**
  395.  * gimp_matrix3_is_diagonal:
  396.  * @matrix: The matrix that is to be tested.
  397.  *
  398.  * Checks if the given matrix is diagonal.
  399.  *
  400.  * Returns: TRUE if the matrix is diagonal.
  401.  */
  402. gboolean
  403. gimp_matrix3_is_diagonal (const GimpMatrix3 *matrix)
  404. {
  405.   gint i, j;
  406.  
  407.   for (i = 0; i < 3; i++)
  408.     {
  409.       for (j = 0; j < 3; j++)
  410.         {
  411.           if (i != j && fabs (matrix->coeff[i][j]) > EPSILON)
  412.             return FALSE;
  413.         }
  414.     }
  415.  
  416.   return TRUE;
  417. }
  418.  
  419. /**
  420.  * gimp_matrix3_is_identity:
  421.  * @matrix: The matrix that is to be tested.
  422.  *
  423.  * Checks if the given matrix is the identity matrix.
  424.  *
  425.  * Returns: TRUE if the matrix is the identity matrix.
  426.  */
  427. gboolean
  428. gimp_matrix3_is_identity (const GimpMatrix3 *matrix)
  429. {
  430.   gint i, j;
  431.  
  432.   for (i = 0; i < 3; i++)
  433.     {
  434.       for (j = 0; j < 3; j++)
  435.         {
  436.           if (i == j)
  437.             {
  438.               if (fabs (matrix->coeff[i][j] - 1.0) > EPSILON)
  439.                 return FALSE;
  440.             }
  441.           else
  442.             {
  443.               if (fabs (matrix->coeff[i][j]) > EPSILON)
  444.                 return FALSE;
  445.             }
  446.         }
  447.     }
  448.  
  449.   return TRUE;
  450. }
  451.  
  452. /*  Check if we'll need to interpolate when applying this matrix.
  453.     This function returns TRUE if all entries of the upper left
  454.     2x2 matrix are either 0 or 1
  455.  */
  456.  
  457.  
  458. /**
  459.  * gimp_matrix3_is_simple:
  460.  * @matrix: The matrix that is to be tested.
  461.  *
  462.  * Checks if we'll need to interpolate when applying this matrix as
  463.  * a transformation.
  464.  *
  465.  * Returns: TRUE if all entries of the upper left 2x2 matrix are either
  466.  * 0 or 1
  467.  */
  468. gboolean
  469. gimp_matrix3_is_simple (const GimpMatrix3 *matrix)
  470. {
  471.   gdouble absm;
  472.   gint    i, j;
  473.  
  474.   for (i = 0; i < 2; i++)
  475.     {
  476.       for (j = 0; j < 2; j++)
  477.         {
  478.           absm = fabs (matrix->coeff[i][j]);
  479.           if (absm > EPSILON && fabs (absm - 1.0) > EPSILON)
  480.             return FALSE;
  481.         }
  482.     }
  483.  
  484.   return TRUE;
  485. }
  486.  
  487. /**
  488.  * gimp_matrix4_to_deg:
  489.  * @matrix:
  490.  * @a:
  491.  * @b:
  492.  * @c:
  493.  *
  494.  *
  495.  **/
  496. void
  497. gimp_matrix4_to_deg (const GimpMatrix4 *matrix,
  498.                      gdouble           *a,
  499.                      gdouble           *b,
  500.                      gdouble           *c)
  501. {
  502.   *a = 180 * (asin (matrix->coeff[1][0]) / G_PI_2);
  503.   *b = 180 * (asin (matrix->coeff[2][0]) / G_PI_2);
  504.   *c = 180 * (asin (matrix->coeff[2][1]) / G_PI_2);
  505. }
  506.