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