gimp r24609 - in trunk: . app/tools



Author: martinn
Date: Mon Jan 14 21:23:02 2008
New Revision: 24609
URL: http://svn.gnome.org/viewvc/gimp?rev=24609&view=rev

Log:
2008-01-14  Martin Nordholts  <martinn svn gnome org>

	* app/tools/tools-utils.[ch]
	(gimp_tool_motion_constrain): Generalized to allow a variable
	number of lines for snapping, and rewritten to make snapping
	happen more intuitively; snap the shortest distance rather than
	only horizontally or vertically.
	(gimp_tool_utils_point_to_line_distance): New helper function.

	* app/tools/gimpblendtool.c
	* app/tools/gimpmeasuretool.c
	* app/tools/gimppainttool.c: Adjust to the new function signature.


Modified:
   trunk/ChangeLog
   trunk/app/tools/gimpblendtool.c
   trunk/app/tools/gimpmeasuretool.c
   trunk/app/tools/gimppainttool.c
   trunk/app/tools/tools-utils.c
   trunk/app/tools/tools-utils.h

Modified: trunk/app/tools/gimpblendtool.c
==============================================================================
--- trunk/app/tools/gimpblendtool.c	(original)
+++ trunk/app/tools/gimpblendtool.c	Mon Jan 14 21:23:02 2008
@@ -46,7 +46,8 @@
 #include "gimp-intl.h"
 
 
-#define TARGET_SIZE 15
+#define TARGET_SIZE  15
+#define N_SNAP_LINES 12
 
 
 /*  local function prototypes  */
@@ -287,7 +288,8 @@
   if (state & GDK_CONTROL_MASK)
     {
       gimp_tool_motion_constrain (blend_tool->start_x, blend_tool->start_y,
-                                  &blend_tool->end_x, &blend_tool->end_y);
+                                  &blend_tool->end_x, &blend_tool->end_y,
+                                  N_SNAP_LINES);
     }
 
   gimp_tool_pop_status (tool, display);
@@ -319,7 +321,8 @@
       if (press)
         {
           gimp_tool_motion_constrain (blend_tool->start_x, blend_tool->start_y,
-                                      &blend_tool->end_x, &blend_tool->end_y);
+                                      &blend_tool->end_x, &blend_tool->end_y,
+                                      N_SNAP_LINES);
         }
 
       gimp_tool_pop_status (tool, display);

Modified: trunk/app/tools/gimpmeasuretool.c
==============================================================================
--- trunk/app/tools/gimpmeasuretool.c	(original)
+++ trunk/app/tools/gimpmeasuretool.c	Mon Jan 14 21:23:02 2008
@@ -54,6 +54,7 @@
 
 #define  TARGET       12
 #define  ARC_RADIUS   30
+#define  N_SNAP_LINES 12
 
 
 /*  local function prototypes  */
@@ -434,7 +435,9 @@
           gdouble  x = measure->x[i];
           gdouble  y = measure->y[i];
 
-          gimp_tool_motion_constrain (measure->x[0], measure->y[0], &x, &y);
+          gimp_tool_motion_constrain (measure->x[0], measure->y[0],
+                                      &x, &y,
+                                      N_SNAP_LINES);
 
           measure->x[i] = ROUND (x);
           measure->y[i] = ROUND (y);
@@ -505,7 +508,9 @@
       y = measure->mouse_y;
 
       if (press)
-        gimp_tool_motion_constrain (measure->x[0], measure->y[0], &x, &y);
+        gimp_tool_motion_constrain (measure->x[0], measure->y[0],
+                                    &x, &y,
+                                    N_SNAP_LINES);
 
       measure->x[measure->point] = ROUND (x);
       measure->y[measure->point] = ROUND (y);

Modified: trunk/app/tools/gimppainttool.c
==============================================================================
--- trunk/app/tools/gimppainttool.c	(original)
+++ trunk/app/tools/gimppainttool.c	Mon Jan 14 21:23:02 2008
@@ -51,6 +51,7 @@
 
 #define HANDLE_SIZE    15
 #define STATUSBAR_SIZE 200
+#define N_SNAP_LINES   12
 
 
 static GObject * gimp_paint_tool_constructor (GType                  type,
@@ -256,7 +257,8 @@
   /* Restrict to multiples of 15 degrees if ctrl is pressed */
   if (state & GDK_CONTROL_MASK)
     gimp_tool_motion_constrain (core->last_coords.x, core->last_coords.y,
-                                &core->cur_coords.x, &core->cur_coords.y);
+                                &core->cur_coords.x, &core->cur_coords.y,
+                                N_SNAP_LINES);
 }
 
 static void

Modified: trunk/app/tools/tools-utils.c
==============================================================================
--- trunk/app/tools/tools-utils.c	(original)
+++ trunk/app/tools/tools-utils.c	Mon Jan 14 21:23:02 2008
@@ -25,34 +25,46 @@
 #include "tools-utils.h"
 
 
+static gdouble gimp_tool_utils_point_to_line_distance (const GimpVector2 *point,
+                                                       const GimpVector2 *point_on_line,
+                                                       const GimpVector2 *normalized_line_direction,
+                                                       GimpVector2       *closest_line_point);
+
+
 /**
- * gimp_tool_motion_constrain_helper:
- * @dx: the (fixed) delta-x
- * @dy: a suggested delta-y
+ * gimp_tool_utils_point_to_line_distance:
+ * @point:              The point to calculate the distance for.
+ * @point_on_line:      A point on the line.
+ * @line_direction:     Normalized line direction vector.
+ * @closest_line_point: Gets set to the point on the line that is
+ *                      closest to @point.
  *
- * Returns: An adjusted dy' near dy such that the slope (dx,dy')
- *          is a multiple of 15 degrees.
+ * Returns: The shortest distance from @point to the line defined by
+ *          @point_on_line and @normalized_line_direction.
  **/
 static gdouble
-gimp_tool_motion_constrain_helper (gdouble dx,
-                                   gdouble dy)
+gimp_tool_utils_point_to_line_distance (const GimpVector2 *point,
+                                        const GimpVector2 *point_on_line,
+                                        const GimpVector2 *line_direction,
+                                        GimpVector2       *closest_line_point)
 {
-  static const gdouble slope[4]   = { 0, 0.26795, 0.57735, 1 };
-  static const gdouble divider[3] = { 0.13165, 0.41421, 0.76732 };
-  gint  i;
+  GimpVector2 distance_vector;
+  GimpVector2 tmp_a;
+  GimpVector2 tmp_b;
+  gdouble     d;
+
+  gimp_vector2_sub (&tmp_a, point, point_on_line);
 
-  if (dy < 0)
-    return - gimp_tool_motion_constrain_helper (dx, -dy);
+  d = gimp_vector2_inner_product (&tmp_a, line_direction);
 
-  dx = fabs (dx);
+  tmp_b = gimp_vector2_mul_val (*line_direction, d);
 
-  for (i = 0; i < 3; i ++)
-    if (dy < dx * divider[i])
-      break;
+  *closest_line_point = gimp_vector2_add_val (*point_on_line,
+                                              tmp_b);
 
-  dy = dx * slope[i];
+  gimp_vector2_sub (&distance_vector, closest_line_point, point);
 
-  return dy;
+  return gimp_vector2_length (&distance_vector);
 }
 
 /**
@@ -61,33 +73,47 @@
  * @start_y:
  * @end_x:
  * @end_y:
+ * @n_snap_lines: Number evenly disributed lines to snap to.
  *
- * Restricts the motion vector to 15 degree steps by changing the end
- * point (if necessary).
+ * Projects a line onto the specified subset of evenly radially
+ * distributed lines. @n_lines of 2 makes the line snap horizontally
+ * or vertically. @n_lines of 4 snaps on 45 degree steps. @n_lines of
+ * 12 on 15 degree steps. etc.
  **/
 void
-gimp_tool_motion_constrain (gdouble   start_x,
-                            gdouble   start_y,
-                            gdouble  *end_x,
-                            gdouble  *end_y)
+gimp_tool_motion_constrain (gdouble  start_x,
+                            gdouble  start_y,
+                            gdouble *end_x,
+                            gdouble *end_y,
+                            gint     n_snap_lines)
 {
-  gdouble dx = *end_x - start_x;
-  gdouble dy = *end_y - start_y;
-
-  /*  This algorithm changes only one of dx and dy, and does not try
-   *  to constrain the resulting dx and dy to integers. This gives
-   *  at least two benefits:
-   *    1. gimp_tool_motion_constrain is idempotent, even if followed by
-   *       a rounding operation.
-   *    2. For any two lines with the same starting-point and ideal
-   *       15-degree direction, the points plotted by
-   *       gimp_paint_core_interpolate for the shorter line will always
-   *       be a superset of those plotted for the longer line.
-   */
-
-  if (fabs (dx) > fabs (dy))
-    *end_y = (start_y + gimp_tool_motion_constrain_helper (dx, dy));
-  else
-    *end_x = (start_x + gimp_tool_motion_constrain_helper (dy, dx));
+  GimpVector2 line_point          = {  start_x,  start_y };
+  GimpVector2 point               = { *end_x,   *end_y   };
+  GimpVector2 constrained_point;
+  GimpVector2 line_dir;
+  gdouble     shortest_dist_moved = G_MAXDOUBLE;
+  gdouble     dist_moved;
+  gdouble     angle;
+  gint        i;
+
+  for (i = 0; i < n_snap_lines; i++)
+    {
+      angle = i * G_PI / n_snap_lines;
+
+      gimp_vector2_set (&line_dir,
+                        cos (angle),
+                        sin (angle));
+
+      dist_moved = gimp_tool_utils_point_to_line_distance (&point,
+                                                           &line_point,
+                                                           &line_dir,
+                                                           &constrained_point);
+      if (dist_moved < shortest_dist_moved)
+        {
+          shortest_dist_moved = dist_moved;
+
+          *end_x = constrained_point.x;
+          *end_y = constrained_point.y;
+        }
+    }
 }
-

Modified: trunk/app/tools/tools-utils.h
==============================================================================
--- trunk/app/tools/tools-utils.h	(original)
+++ trunk/app/tools/tools-utils.h	Mon Jan 14 21:23:02 2008
@@ -23,7 +23,8 @@
 void  gimp_tool_motion_constrain (gdouble   start_x,
                                   gdouble   start_y,
                                   gdouble  *end_x,
-                                  gdouble  *end_y);
+                                  gdouble  *end_y,
+                                  gint      n_snap_lines);
 
 
 #endif  /*  __TOOLS_UTILS_H__  */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]