Blame gegl/gegl-matrix.c

Packit bc1512
/* This file is part of GEGL
Packit bc1512
 *
Packit bc1512
 * GEGL is free software; you can redistribute it and/or
Packit bc1512
 * modify it under the terms of the GNU Lesser General Public
Packit bc1512
 * License as published by the Free Software Foundation; either
Packit bc1512
 * version 3 of the License, or (at your option) any later version.
Packit bc1512
 *
Packit bc1512
 * GEGL is distributed in the hope that it will be useful,
Packit bc1512
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit bc1512
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit bc1512
 * Lesser General Public License for more details.
Packit bc1512
 *
Packit bc1512
 * You should have received a copy of the GNU Lesser General Public
Packit bc1512
 * License along with GEGL; if not, see <http://www.gnu.org/licenses/>.
Packit bc1512
 *
Packit bc1512
 * Copyright 2006 Philip Lafleur
Packit bc1512
 */
Packit bc1512
Packit bc1512
#include "config.h"
Packit bc1512
#include <math.h>
Packit bc1512
#include <string.h>
Packit bc1512
#include <stdlib.h>
Packit bc1512
Packit bc1512
#include "gegl-matrix.h"
Packit bc1512
Packit bc1512
Packit bc1512
#if 0
Packit bc1512
static void gegl_matrix3_debug (GeglMatrix3 *matrix)
Packit bc1512
{
Packit bc1512
  if (matrix)
Packit bc1512
    {
Packit bc1512
      gchar *str = gegl_matrix3_to_string (matrix);
Packit bc1512
      g_print("%s\n", str);
Packit bc1512
      g_free (str);
Packit bc1512
    }
Packit bc1512
  else
Packit bc1512
    {
Packit bc1512
      g_print("NULL matrix\n");
Packit bc1512
    }
Packit bc1512
}
Packit bc1512
#endif
Packit bc1512
Packit bc1512
GeglMatrix3 *
Packit bc1512
gegl_matrix3_new (void)
Packit bc1512
{
Packit bc1512
  return g_new0(GeglMatrix3, 1);
Packit bc1512
}
Packit bc1512
Packit bc1512
GType
Packit bc1512
gegl_matrix3_get_type (void)
Packit bc1512
{
Packit bc1512
  static GType matrix_type = 0;
Packit bc1512
Packit bc1512
  if (!matrix_type) {
Packit bc1512
    matrix_type = g_boxed_type_register_static ("GeglMatrix3",
Packit bc1512
                                               (GBoxedCopyFunc) gegl_matrix3_copy,
Packit bc1512
                                               (GBoxedFreeFunc) g_free);
Packit bc1512
  }
Packit bc1512
Packit bc1512
  return matrix_type;
Packit bc1512
}
Packit bc1512
Packit bc1512
void
Packit bc1512
gegl_matrix3_identity (GeglMatrix3 *matrix)
Packit bc1512
{
Packit bc1512
  matrix->coeff [0][0] = matrix->coeff [1][1] = matrix->coeff [2][2] = 1.;
Packit bc1512
Packit bc1512
  matrix->coeff [0][1] = matrix->coeff [0][2] = 0.;
Packit bc1512
  matrix->coeff [1][0] = matrix->coeff [1][2] = 0.;
Packit bc1512
  matrix->coeff [2][0] = matrix->coeff [2][1] = 0.;
Packit bc1512
}
Packit bc1512
Packit bc1512
gboolean
Packit bc1512
gegl_matrix3_equal (GeglMatrix3 *matrix1,
Packit bc1512
                    GeglMatrix3 *matrix2)
Packit bc1512
{
Packit bc1512
  gint x, y;
Packit bc1512
Packit bc1512
  for (y = 0; y < 3; y++)
Packit bc1512
    for (x = 0; x < 3; x++)
Packit bc1512
      if (matrix1->coeff [y][x] != matrix2->coeff [y][x])
Packit bc1512
        return FALSE;
Packit bc1512
  return TRUE;
Packit bc1512
}
Packit bc1512
Packit bc1512
gboolean
Packit bc1512
gegl_matrix3_is_identity (GeglMatrix3 *matrix)
Packit bc1512
{
Packit bc1512
  GeglMatrix3 identity;
Packit bc1512
  gegl_matrix3_identity (&identity);
Packit bc1512
  return gegl_matrix3_equal (&identity, matrix);
Packit bc1512
}
Packit bc1512
Packit bc1512
gboolean
Packit bc1512
gegl_matrix3_is_scale (GeglMatrix3 *matrix)
Packit bc1512
{
Packit bc1512
  GeglMatrix3 copy;
Packit bc1512
  gegl_matrix3_copy_into (&copy, matrix);
Packit bc1512
  copy.coeff [0][0] = copy.coeff [1][1] = 1.;
Packit bc1512
  copy.coeff [0][2] = copy.coeff [1][2] = 0.;
Packit bc1512
  return gegl_matrix3_is_identity (©);
Packit bc1512
}
Packit bc1512
Packit bc1512
gboolean
Packit bc1512
gegl_matrix3_is_translate (GeglMatrix3 *matrix)
Packit bc1512
{
Packit bc1512
  GeglMatrix3 copy;
Packit bc1512
  gegl_matrix3_copy_into (&copy, matrix);
Packit bc1512
  copy.coeff [0][2] = copy.coeff [1][2] = 0.;
Packit bc1512
  return gegl_matrix3_is_identity (©);
Packit bc1512
}
Packit bc1512
Packit bc1512
void
Packit bc1512
gegl_matrix3_copy_into (GeglMatrix3 *dst,
Packit bc1512
                        GeglMatrix3 *src)
Packit bc1512
{
Packit bc1512
  memcpy (dst->coeff [0], src->coeff [0], 3 * sizeof (gdouble));
Packit bc1512
  memcpy (dst->coeff [1], src->coeff [1], 3 * sizeof (gdouble));
Packit bc1512
  memcpy (dst->coeff [2], src->coeff [2], 3 * sizeof (gdouble));
Packit bc1512
}
Packit bc1512
Packit bc1512
GeglMatrix3 *
Packit bc1512
gegl_matrix3_copy (GeglMatrix3 *matrix)
Packit bc1512
{
Packit bc1512
  return (GeglMatrix3 *) g_memdup (matrix, sizeof (GeglMatrix3));
Packit bc1512
}
Packit bc1512
Packit bc1512
gdouble
Packit bc1512
gegl_matrix3_determinant (GeglMatrix3 *matrix)
Packit bc1512
{
Packit bc1512
  gdouble determinant;
Packit bc1512
Packit bc1512
  determinant = matrix->coeff [0][0] * (matrix->coeff [1][1] * matrix->coeff [2][2] -
Packit bc1512
                                 matrix->coeff [1][2] * matrix->coeff [2][1])
Packit bc1512
              - matrix->coeff [0][1] * (matrix->coeff [1][0] * matrix->coeff [2][2] -
Packit bc1512
                                 matrix->coeff [1][2] * matrix->coeff [2][0])
Packit bc1512
              + matrix->coeff [0][2] * (matrix->coeff [1][0] * matrix->coeff [2][1] -
Packit bc1512
                                 matrix->coeff [1][1] * matrix->coeff [2][0]);
Packit bc1512
  return determinant;
Packit bc1512
}
Packit bc1512
Packit bc1512
void
Packit bc1512
gegl_matrix3_invert (GeglMatrix3 *matrix)
Packit bc1512
{
Packit bc1512
  GeglMatrix3 copy;
Packit bc1512
  gdouble coeff;
Packit bc1512
Packit bc1512
  gegl_matrix3_copy_into (&copy, matrix);
Packit bc1512
  coeff = 1 / gegl_matrix3_determinant (matrix);
Packit bc1512
Packit bc1512
  matrix->coeff [0][0] = (copy.coeff [1][1] * copy.coeff [2][2] -
Packit bc1512
                   copy.coeff [1][2] * copy.coeff [2][1]) * coeff;
Packit bc1512
  matrix->coeff [1][0] = (copy.coeff [1][2] * copy.coeff [2][0] -
Packit bc1512
                   copy.coeff [1][0] * copy.coeff [2][2]) * coeff;
Packit bc1512
  matrix->coeff [2][0] = (copy.coeff [1][0] * copy.coeff [2][1] -
Packit bc1512
                   copy.coeff [1][1] * copy.coeff [2][0]) * coeff;
Packit bc1512
Packit bc1512
  matrix->coeff [0][1] = (copy.coeff [0][2] * copy.coeff [2][1] -
Packit bc1512
                   copy.coeff [0][1] * copy.coeff [2][2]) * coeff;
Packit bc1512
  matrix->coeff [1][1] = (copy.coeff [0][0] * copy.coeff [2][2] -
Packit bc1512
                   copy.coeff [0][2] * copy.coeff [2][0]) * coeff;
Packit bc1512
  matrix->coeff [2][1] = (copy.coeff [0][1] * copy.coeff [2][0] -
Packit bc1512
                   copy.coeff [0][0] * copy.coeff [2][1]) * coeff;
Packit bc1512
Packit bc1512
  matrix->coeff [0][2] = (copy.coeff [0][1] * copy.coeff [1][2] -
Packit bc1512
                   copy.coeff [0][2] * copy.coeff [1][1]) * coeff;
Packit bc1512
  matrix->coeff [1][2] = (copy.coeff [0][2] * copy.coeff [1][0] -
Packit bc1512
                   copy.coeff [0][0] * copy.coeff [1][2]) * coeff;
Packit bc1512
  matrix->coeff [2][2] = (copy.coeff [0][0] * copy.coeff [1][1] -
Packit bc1512
                   copy.coeff [0][1] * copy.coeff [1][0]) * coeff;
Packit bc1512
}
Packit bc1512
Packit bc1512
Packit bc1512
void
Packit bc1512
gegl_matrix3_multiply (GeglMatrix3 *left,
Packit bc1512
                       GeglMatrix3 *right,
Packit bc1512
                       GeglMatrix3 *product)
Packit bc1512
{
Packit bc1512
  GeglMatrix3 temp;
Packit bc1512
  gint    i;
Packit bc1512
Packit bc1512
  for (i = 0; i < 3; i++)
Packit bc1512
    {
Packit bc1512
      temp.coeff [i][0] = left->coeff [i][0] * right->coeff [0][0]
Packit bc1512
                    + left->coeff [i][1] * right->coeff [1][0]
Packit bc1512
                    + left->coeff [i][2] * right->coeff [2][0];
Packit bc1512
      temp.coeff [i][1] = left->coeff [i][0] * right->coeff [0][1]
Packit bc1512
                    + left->coeff [i][1] * right->coeff [1][1]
Packit bc1512
                    + left->coeff [i][2] * right->coeff [2][1];
Packit bc1512
      temp.coeff [i][2] = left->coeff [i][0] * right->coeff [0][2]
Packit bc1512
                    + left->coeff [i][1] * right->coeff [1][2]
Packit bc1512
                    + left->coeff [i][2] * right->coeff [2][2];
Packit bc1512
    }
Packit bc1512
Packit bc1512
  gegl_matrix3_copy_into (product, &temp);
Packit bc1512
}
Packit bc1512
Packit bc1512
void
Packit bc1512
gegl_matrix3_originate (GeglMatrix3 *matrix,
Packit bc1512
                   gdouble x,
Packit bc1512
                   gdouble y)
Packit bc1512
{
Packit bc1512
Packit bc1512
  /* assumes last row is [0 0 1] (true for affine transforms) */
Packit bc1512
  matrix->coeff [0][2] = matrix->coeff [0][0] * (-x) +
Packit bc1512
                  matrix->coeff [0][1] * (-y) +
Packit bc1512
                  matrix->coeff [0][2] + x;
Packit bc1512
  matrix->coeff [1][2] = matrix->coeff [1][0] * (-x) +
Packit bc1512
                  matrix->coeff [1][1] * (-y) +
Packit bc1512
                  matrix->coeff [1][2] + y;
Packit bc1512
}
Packit bc1512
Packit bc1512
void
Packit bc1512
gegl_matrix3_transform_point (GeglMatrix3  *matrix,
Packit bc1512
                              gdouble     *x,
Packit bc1512
                              gdouble     *y)
Packit bc1512
{
Packit bc1512
  gdouble xp, yp, w;
Packit bc1512
  
Packit bc1512
  w = (*x * matrix->coeff [2][0] + *y * matrix->coeff [2][1] + matrix->coeff [2][2]);
Packit bc1512
Packit bc1512
  xp = (*x * matrix->coeff [0][0] + *y * matrix->coeff [0][1] + matrix->coeff [0][2]) /w;
Packit bc1512
  yp = (*x * matrix->coeff [1][0] + *y * matrix->coeff [1][1] + matrix->coeff [1][2]) /w;
Packit bc1512
Packit bc1512
  *x = xp;
Packit bc1512
  *y = yp;
Packit bc1512
}
Packit bc1512
Packit bc1512
void
Packit bc1512
gegl_matrix3_parse_string (GeglMatrix3  *matrix,
Packit bc1512
                           const gchar *string)
Packit bc1512
{
Packit bc1512
  gegl_matrix3_identity (matrix);
Packit bc1512
  if (strstr (string, "translate"))
Packit bc1512
    {
Packit bc1512
      gchar *p = strchr (string, '(');
Packit bc1512
      gfloat a;
Packit bc1512
      gfloat b;
Packit bc1512
      if (!p) return;
Packit bc1512
      p++;
Packit bc1512
      a = strtod(p, &p);
Packit bc1512
      if (!p) return;
Packit bc1512
      p = strchr (string, ',');
Packit bc1512
      if (!p) return;
Packit bc1512
      p++;
Packit bc1512
      b = strtod (p, &p);
Packit bc1512
      if (!p) return;
Packit bc1512
Packit bc1512
      matrix->coeff [0][2] = a;
Packit bc1512
      matrix->coeff [1][2] = b;
Packit bc1512
    }
Packit bc1512
  else if (strstr (string, "matrix"))
Packit bc1512
    {
Packit bc1512
      gchar *p = strchr (string, '(');
Packit bc1512
      gfloat a;
Packit bc1512
      gint i,j;
Packit bc1512
      if (!p) return;
Packit bc1512
      p++;
Packit bc1512
Packit bc1512
Packit bc1512
      for (i=0;i<3;i++)
Packit bc1512
        for (j=0;j<3;j++)
Packit bc1512
          {
Packit bc1512
            a = strtod(p, &p);
Packit bc1512
            matrix->coeff [j][i] = a;
Packit bc1512
            if (!p) return;
Packit bc1512
            p = strchr (p, ',');
Packit bc1512
            if (!p) return;
Packit bc1512
            p++;
Packit bc1512
          }
Packit bc1512
    }
Packit bc1512
}
Packit bc1512
Packit bc1512
gchar *gegl_matrix3_to_string (GeglMatrix3 *matrix)
Packit bc1512
{
Packit bc1512
  gchar *res;
Packit bc1512
  GString *str = g_string_new ("matrix(");
Packit bc1512
  gint i, j;
Packit bc1512
  gint a=0;
Packit bc1512
Packit bc1512
  for (i=0;i<3;i++)
Packit bc1512
    for (j=0;j<3;j++)
Packit bc1512
      {
Packit bc1512
        if (a!=0)
Packit bc1512
          g_string_append (str, ",");
Packit bc1512
        a=1;
Packit bc1512
        g_string_append_printf (str, "%f", matrix->coeff[j][i]);
Packit bc1512
      }
Packit bc1512
  g_string_append (str, ")");
Packit bc1512
  res = str->str;
Packit bc1512
  g_string_free (str, FALSE);
Packit bc1512
Packit bc1512
  return res;
Packit bc1512
}