[gegl/soc-2013-n-point-deformation] add part of n-point deformation library
- From: Marek Dvoroznak <dvoromar src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl/soc-2013-n-point-deformation] add part of n-point deformation library
- Date: Tue, 2 Jul 2013 22:29:23 +0000 (UTC)
commit 1ea27c92ca09c91f1d2cfcf75565ec2a3b75d541
Author: Marek Dvoroznak <dvoromar gmail com>
Date: Wed Jul 3 00:21:54 2013 +0200
add part of n-point deformation library
libs/npd/npd_common.c | 380 +++++++++++++++++++++++++++++++++++++++++++++++++
libs/npd/npd_common.h | 66 +++++----
libs/npd/npd_gegl.c | 66 +++++++++
libs/npd/npd_gegl.h | 31 ++++
libs/npd/npd_math.c | 45 ++++++
libs/npd/npd_math.h | 56 +++++++
6 files changed, 617 insertions(+), 27 deletions(-)
---
diff --git a/libs/npd/npd_common.c b/libs/npd/npd_common.c
new file mode 100644
index 0000000..a79fb1a
--- /dev/null
+++ b/libs/npd/npd_common.c
@@ -0,0 +1,380 @@
+/*
+ * This file is part of n-point image deformation library.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright (C) 2013 Marek Dvoroznak <dvoromar gmail com>
+ */
+
+#include "npd_common.h"
+#include "npd_math.h"
+#include <math.h>
+#include <glib.h>
+#include <glib/gprintf.h>
+
+void
+npd_init_model (NPDModel *model)
+{
+ NPDHiddenModel *hidden_model;
+ GArray *control_points;
+
+ /* init hidden model */
+ hidden_model = g_new (NPDHiddenModel, 1);
+ model->hidden_model = hidden_model;
+ hidden_model->ARAP = TRUE;
+ hidden_model->num_of_bones = 0;
+ hidden_model->num_of_overlapping_points = 0;
+
+ /* init control points */
+ control_points = g_array_new (FALSE, FALSE, sizeof (NPDControlPoint));
+ model->control_points = control_points;
+ model->control_point_radius = 6;
+ model->control_points_visible = TRUE;
+
+ /* init other */
+ model->mesh_visible = TRUE;
+ model->texture_visible = TRUE;
+}
+
+void
+npd_destroy_hidden_model (NPDHiddenModel *hm)
+{
+ gint i;
+ for (i = 0; i < hm->num_of_overlapping_points; i++)
+ {
+ g_free (hm->list_of_overlapping_points[i].points);
+ }
+
+ g_free (hm->list_of_overlapping_points);
+
+ for (i = 0; i < hm->num_of_bones; i++)
+ {
+ g_free (hm->current_bones[i].weights);
+ g_free (hm->current_bones[i].points);
+ g_free (hm->reference_bones[i].points);
+ }
+
+ g_free (hm->current_bones);
+ g_free (hm->reference_bones);
+}
+
+void
+npd_destroy_model (NPDModel *model)
+{
+ /* destroy control points */
+ g_array_free (model->control_points, TRUE);
+
+ /* destroy hidden model */
+ npd_destroy_hidden_model (model->hidden_model);
+ g_free (model->hidden_model);
+}
+
+NPDControlPoint*
+npd_add_control_point (NPDModel *model,
+ NPDPoint *coord)
+{
+ gint num_of_ops, i, closest;
+ gfloat min, current;
+ NPDOverlappingPoints *list_of_ops;
+ NPDControlPoint cp;
+
+ list_of_ops = model->hidden_model->list_of_overlapping_points;
+ num_of_ops = model->hidden_model->num_of_overlapping_points;
+
+ /* find closest overlapping points */
+ closest = 0;
+ min = npd_SED (coord, list_of_ops[0].representative);
+
+ for (i = 1; i < num_of_ops; i++)
+ {
+ NPDPoint *op = list_of_ops[i].representative;
+ current = npd_SED(coord, op);
+
+ if (min > current)
+ {
+ closest = i;
+ min = current;
+ }
+ }
+
+ cp.point.weight = list_of_ops[closest].representative->weight;
+ cp.overlapping_points = &list_of_ops[closest];
+
+ npd_set_point_coordinates (&cp.point, list_of_ops[closest].representative);
+ g_array_append_val (model->control_points, cp);
+
+ return &g_array_index (model->control_points,
+ NPDControlPoint,
+ model->control_points->len - 1);
+}
+
+void
+npd_remove_control_point (NPDModel *model,
+ NPDControlPoint *control_point)
+{
+ gint i;
+ NPDControlPoint *cp;
+
+ for (i = 0; i < model->control_points->len; i++)
+ {
+ cp = &g_array_index(model->control_points, NPDControlPoint, i);
+
+ if (cp == control_point)
+ {
+ npd_set_control_point_weight(cp, 1.0);
+ g_array_remove_index (model->control_points, i);
+ return;
+ }
+ }
+}
+
+void
+npd_remove_all_control_points (NPDModel *model)
+{
+ g_array_remove_range (model->control_points,
+ 0,
+ model->control_points->len);
+}
+
+void
+npd_set_control_point_weight (NPDControlPoint *cp,
+ gfloat weight)
+{
+ npd_set_overlapping_points_weight(cp->overlapping_points, weight);
+}
+
+gboolean
+npd_equal_coordinates (NPDPoint *p1,
+ NPDPoint *p2)
+{
+ return npd_equal_coordinates_epsilon(p1, p2, NPD_EPSILON);
+}
+
+gboolean
+npd_equal_coordinates_epsilon (NPDPoint *p1,
+ NPDPoint *p2,
+ gfloat epsilon)
+{
+ if (npd_equal_floats_epsilon (p1->x, p2->x, epsilon) &&
+ npd_equal_floats_epsilon (p1->y, p2->y, epsilon))
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+NPDControlPoint*
+npd_get_control_point_at (NPDModel *model,
+ NPDPoint *coord)
+{
+ gint i;
+ for (i = 0; i < model->control_points->len; i++)
+ {
+ NPDControlPoint *cp = &g_array_index (model->control_points,
+ NPDControlPoint,
+ i);
+ if (npd_equal_coordinates_epsilon (&cp->point,
+ coord,
+ model->control_point_radius))
+ {
+ return cp;
+ }
+ }
+
+ g_printf ("no control points\n");
+ return NULL;
+}
+
+void
+npd_create_list_of_overlapping_points (NPDHiddenModel *hm)
+{
+ gint i, j, num_of_bones;
+ NPDBone *bone;
+ NPDPoint *point;
+ GPtrArray *list_of_ops;
+ GHashTable *coords_to_cluster;
+
+ list_of_ops = g_ptr_array_new ();
+ num_of_bones = hm->num_of_bones;
+ coords_to_cluster = g_hash_table_new_full
+ (g_str_hash, g_str_equal,
+ g_free, (GDestroyNotify) g_hash_table_destroy);
+
+ for (i = 0; i < num_of_bones; i++)
+ {
+ bone = &hm->current_bones[i];
+
+ for (j = 0; j < bone->num_of_points; j++)
+ {
+ point = &bone->points[j];
+ add_point_to_suitable_cluster (coords_to_cluster,
+ point,
+ list_of_ops);
+ }
+ }
+
+ hm->list_of_overlapping_points = g_new (NPDOverlappingPoints,
+ list_of_ops->len);
+ hm->num_of_overlapping_points = list_of_ops->len;
+
+ for (i = 0; i < list_of_ops->len; i++)
+ {
+ GPtrArray *op = g_ptr_array_index (list_of_ops, i);
+ hm->list_of_overlapping_points[i].points = (NPDPoint**) op->pdata;
+ hm->list_of_overlapping_points[i].num_of_points = op->len;
+ hm->list_of_overlapping_points[i].representative =
+ hm->list_of_overlapping_points[i].points[0];
+
+ g_ptr_array_free (op, FALSE); /* we want to preserve the underlying
+ array */
+ }
+
+ /* free allocated memory */
+ g_hash_table_destroy (coords_to_cluster);
+ g_ptr_array_free (list_of_ops, TRUE);
+}
+
+#define NPD_FLOAT_TO_STRING(name_of_string, value) \
+/* must be freed */ \
+name_of_string = g_new (gchar, 10); \
+g_ascii_dtostr (name_of_string, 10, value);
+
+void
+add_point_to_suitable_cluster (GHashTable *coords_to_cluster,
+ NPDPoint *point,
+ GPtrArray *list_of_overlapping_points)
+{
+ gchar *str_coord_x, *str_coord_y;
+ GHashTable *coord_y;
+ GPtrArray *op;
+
+ NPD_FLOAT_TO_STRING (str_coord_x, point->x);
+ NPD_FLOAT_TO_STRING (str_coord_y, point->y);
+
+ coord_y = g_hash_table_lookup (coords_to_cluster, str_coord_x);
+
+ if (coord_y == NULL)
+ {
+ /* coordinate doesn't exist */
+ coord_y = g_hash_table_new_full (g_str_hash, /* is freed during */
+ g_str_equal, /* destroying */
+ g_free, /* coords_to_cluster */
+ NULL); /* hash table */
+ g_hash_table_insert (coords_to_cluster, str_coord_x, coord_y);
+ }
+
+ op = g_hash_table_lookup (coord_y, str_coord_y);
+ if (op == NULL)
+ {
+ op = g_ptr_array_new ();
+ g_hash_table_insert (coord_y, str_coord_y, op);
+ g_ptr_array_add (list_of_overlapping_points, op);
+ }
+
+ g_ptr_array_add (op, point);
+}
+
+void
+npd_set_overlapping_points_weight (NPDOverlappingPoints *op,
+ gfloat weight)
+{
+ gint i;
+ for (i = 0; i < op->num_of_points; i++)
+ {
+ (*op->points[i]->weight) = weight;
+ }
+}
+
+void
+npd_set_point_coordinates (NPDPoint *target,
+ NPDPoint *source)
+{
+ target->x = source->x;
+ target->y = source->y;
+}
+
+void
+npd_print_hidden_model (NPDHiddenModel *hm,
+ gboolean print_bones,
+ gboolean print_overlapping_points)
+{
+ gint i;
+ g_printf ("NPDHiddenModel:\n");
+ g_printf ("number of bones: %d\n", hm->num_of_bones);
+ g_printf ("ARAP: %d\n", hm->ARAP);
+ g_printf ("number of overlapping points: %d\n", hm->num_of_overlapping_points);
+
+ if (print_bones)
+ {
+ g_printf ("bones:\n");
+ for (i = 0; i < hm->num_of_bones; i++)
+ {
+ npd_print_bone (&hm->current_bones[i]);
+ }
+ }
+
+ if (print_overlapping_points)
+ {
+ g_printf ("overlapping points:\n");
+ for (i = 0; i < hm->num_of_overlapping_points; i++)
+ {
+ npd_print_overlapping_points (&hm->list_of_overlapping_points[i]);
+ }
+ }
+}
+
+void
+npd_print_bone (NPDBone *bone)
+{
+ gint i;
+ g_printf ("NPDBone:\n");
+ g_printf ("number of points: %d\n", bone->num_of_points);
+ g_printf ("points:\n");
+ for (i = 0; i < bone->num_of_points; i++)
+ {
+ npd_print_point (&bone->points[i], TRUE);
+ }
+}
+
+void
+npd_print_point (NPDPoint *point,
+ gboolean print_details)
+{
+ if (print_details)
+ {
+ g_printf ("(NPDPoint: x: %f, y: %f, weight: %f, fixed: %d)\n",
+ point->x, point->y, *point->weight, point->fixed);
+ }
+ else
+ {
+ g_printf ("(NPDPoint: x: %f, y: %f)\n",
+ point->x, point->y);
+ }
+}
+
+void
+npd_print_overlapping_points (NPDOverlappingPoints *op)
+{
+ gint i;
+ g_printf ("NPDOverlappingPoints:\n");
+ g_printf ("number of points: %d\n", op->num_of_points);
+ g_printf ("representative: ");
+ npd_print_point (op->representative, TRUE);
+ g_printf ("points:\n");
+ for (i = 0; i < op->num_of_points; i++)
+ {
+ npd_print_point (op->points[i], TRUE);
+ }
+}
\ No newline at end of file
diff --git a/libs/npd/npd_common.h b/libs/npd/npd_common.h
index c3bb452..27731d1 100644
--- a/libs/npd/npd_common.h
+++ b/libs/npd/npd_common.h
@@ -83,32 +83,44 @@ typedef struct
NPDDisplay *display;
} NPDModel;
-void npd_init_model (NPDModel *model);
-void npd_destroy_hidden_model (NPDHiddenModel *model);
-void npd_destroy_model (NPDModel *model);
-
-NPDControlPoint *npd_add_control_point (NPDModel *model,
- NPDPoint *coord);
-void npd_remove_control_point (NPDModel *model,
- NPDControlPoint *control_point);
-void npd_remove_all_control_points
- (NPDModel *model);
-void npd_set_control_point_weight
- (NPDControlPoint *cp,
- gfloat weight);
-gboolean npd_equal_coordinates (NPDPoint *p1,
- NPDPoint *p2,
- gfloat epsilon);
-NPDControlPoint *npd_get_control_point_at (NPDModel *model,
- NPDPoint *coord);
-
-void npd_create_list_of_overlapping_points
- (NPDHiddenModel *model);
-void npd_set_overlapping_points_weight
- (NPDOverlappingPoints *op,
- gfloat weight);
-
-void npd_set_point_coordinates (NPDPoint *target,
- NPDPoint *source);
+void npd_init_model (NPDModel *model);
+void npd_destroy_hidden_model (NPDHiddenModel *model);
+void npd_destroy_model (NPDModel *model);
+NPDControlPoint *npd_add_control_point (NPDModel *model,
+ NPDPoint *coord);
+void npd_remove_control_point (NPDModel *model,
+ NPDControlPoint *control_point);
+void npd_remove_all_control_points
+ (NPDModel *model);
+void npd_set_control_point_weight
+ (NPDControlPoint *cp,
+ gfloat weight);
+gboolean npd_equal_coordinates (NPDPoint *p1,
+ NPDPoint *p2);
+gboolean npd_equal_coordinates_epsilon
+ (NPDPoint *p1,
+ NPDPoint *p2,
+ gfloat epsilon);
+NPDControlPoint *npd_get_control_point_at (NPDModel *model,
+ NPDPoint *coord);
+void npd_create_list_of_overlapping_points
+ (NPDHiddenModel *model);
+void add_point_to_suitable_cluster
+ (GHashTable *coords_to_cluster,
+ NPDPoint *point,
+ GPtrArray *list_of_overlapping_points);
+void npd_set_overlapping_points_weight
+ (NPDOverlappingPoints *op,
+ gfloat weight);
+void npd_set_point_coordinates (NPDPoint *target,
+ NPDPoint *source);
+void npd_print_hidden_model (NPDHiddenModel *hm,
+ gboolean print_bones,
+ gboolean print_overlapping_points);
+void npd_print_bone (NPDBone *bone);
+void npd_print_point (NPDPoint *point,
+ gboolean print_details);
+void npd_print_overlapping_points
+ (NPDOverlappingPoints *op);
#endif /* __NPD_COMMON_H__ */
\ No newline at end of file
diff --git a/libs/npd/npd_gegl.c b/libs/npd/npd_gegl.c
new file mode 100644
index 0000000..e4f7234
--- /dev/null
+++ b/libs/npd/npd_gegl.c
@@ -0,0 +1,66 @@
+/*
+ * This file is part of n-point image deformation library.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright (C) 2013 Marek Dvoroznak <dvoromar gmail com>
+ */
+
+#include "npd_gegl.h"
+#include <glib.h>
+
+void
+npd_new_matrix (NPDMatrix **matrix)
+{
+ *matrix = g_new (NPDMatrix, 1);
+}
+
+void
+npd_destroy_matrix (NPDMatrix **matrix)
+{
+ g_free (*matrix);
+}
+
+void
+npd_compute_affinity (NPDPoint *p11,
+ NPDPoint *p21,
+ NPDPoint *p31,
+ NPDPoint *p12,
+ NPDPoint *p22,
+ NPDPoint *p32,
+ NPDMatrix *T)
+{
+ GeglMatrix3 Y, X;
+
+ Y.coeff[0][0] = p12->x; Y.coeff[1][0] = p12->y; Y.coeff[2][0] = 1;
+ Y.coeff[0][1] = p22->x; Y.coeff[1][1] = p22->y; Y.coeff[2][1] = 1;
+ Y.coeff[0][2] = p32->x; Y.coeff[1][2] = p32->y; Y.coeff[2][2] = 1;
+
+ X.coeff[0][0] = p11->x; X.coeff[1][0] = p11->y; X.coeff[2][0] = 1;
+ X.coeff[0][1] = p21->x; X.coeff[1][1] = p21->y; X.coeff[2][1] = 1;
+ X.coeff[0][2] = p31->x; X.coeff[1][2] = p31->y; X.coeff[2][2] = 1;
+
+ gegl_matrix3_invert (&X);
+ gegl_matrix3_multiply (&Y, &X, &T->matrix);
+}
+
+void
+npd_apply_transformation (NPDMatrix *T,
+ NPDPoint *src,
+ NPDPoint *dest)
+{
+ gdouble x = src->x, y = src->y;
+ gegl_matrix3_transform_point (T, &x, &y);
+ dest->x = x; dest->y = y;
+}
diff --git a/libs/npd/npd_gegl.h b/libs/npd/npd_gegl.h
new file mode 100644
index 0000000..3bb61f0
--- /dev/null
+++ b/libs/npd/npd_gegl.h
@@ -0,0 +1,31 @@
+/*
+ * This file is part of n-point image deformation library.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright (C) 2013 Marek Dvoroznak <dvoromar gmail com>
+ */
+
+#ifndef __NPD_GEGL_H__
+#define __NPD_GEGL_H__
+
+#include "npd_math.h"
+#include <gegl/gegl-matrix.h>
+
+struct _NPDMatrix
+{
+ GeglMatrix3 matrix;
+};
+
+#endif /* __NPD_GEGL_H__ */
\ No newline at end of file
diff --git a/libs/npd/npd_math.c b/libs/npd/npd_math.c
new file mode 100644
index 0000000..71463c3
--- /dev/null
+++ b/libs/npd/npd_math.c
@@ -0,0 +1,45 @@
+/*
+ * This file is part of n-point image deformation library.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright (C) 2013 Marek Dvoroznak <dvoromar gmail com>
+ */
+
+#include "npd_math.h"
+#include <math.h>
+
+gboolean
+npd_equal_floats (gfloat a,
+ gfloat b)
+{
+ return npd_equal_floats_epsilon (a, b, NPD_EPSILON);
+}
+
+gboolean
+npd_equal_floats_epsilon (gfloat a,
+ gfloat b,
+ gfloat epsilon)
+{
+ return fabs (a - b) < epsilon;
+}
+
+gfloat
+npd_SED (NPDPoint *p1,
+ NPDPoint *p2)
+{
+ gint dx = p1->x - p2->x;
+ gint dy = p1->y - p2->y;
+ return dx * dx + dy * dy;
+}
\ No newline at end of file
diff --git a/libs/npd/npd_math.h b/libs/npd/npd_math.h
new file mode 100644
index 0000000..a4d146e
--- /dev/null
+++ b/libs/npd/npd_math.h
@@ -0,0 +1,56 @@
+/*
+ * This file is part of n-point image deformation library.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright (C) 2013 Marek Dvoroznak <dvoromar gmail com>
+ */
+
+#ifndef __NPD_MATH_H__
+#define __NPD_MATH_H__
+
+#include "npd_common.h"
+
+#define NPD_EPSILON 0.00001
+
+void npd_compute_homography (NPDPoint *p11,
+ NPDPoint *p21,
+ NPDPoint *p31,
+ NPDPoint *p41,
+ NPDPoint *p12,
+ NPDPoint *p22,
+ NPDPoint *p32,
+ NPDPoint *p42,
+ NPDMatrix *T);
+void npd_compute_affinity (NPDPoint *p11,
+ NPDPoint *p21,
+ NPDPoint *p31,
+ NPDPoint *p12,
+ NPDPoint *p22,
+ NPDPoint *p32,
+ NPDMatrix *T);
+void npd_apply_transformation (NPDMatrix *T,
+ NPDPoint *src,
+ NPDPoint *dest);
+gboolean npd_equal_floats_epsilon (gfloat a,
+ gfloat b,
+ gfloat epsilon);
+gboolean npd_equal_floats (gfloat a,
+ gfloat b);
+gfloat npd_SED (NPDPoint *p1,
+ NPDPoint *p2);
+void npd_new_matrix (NPDMatrix **matrix);
+void npd_destroy_matrix (NPDMatrix **matrix);
+
+#endif /* __NPD_MATH_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]