Hi dear gegl developers :),

I have a proposition to refactor [gegl_]path_calc_values :

static void path_calc_values (GeglPathList *path,
+                           gdouble       pos_min,
+                           gdouble       pos_max,
                              guint         num_samples,
                              gdouble      *xs,
                              gdouble      *ys)

This modification is consistent with gegl_curve_calc_values which can return
a windowed lookup table.
The refactoring merge redundant code (path_calc and path_calc_values).
It also fixed what appeared to me as a bug : offset value was just dropped
in the 'M' case, which could lead to a noticeable rounding error.

See attached patch :
[PATCH] Refactor [gegl_]path_calc_values

* moded gegl/property-types/gegl-path.[c|h]
Add pos_min and pos_max parameters to get sample points on an arbitrary
portion of the path
This reduces code and should be very useful to extract gegl_path_stroke in a
proper operation.

I did not build a test case yet (if anyone has such code and is willing to
share, i'd be grateful).

Please review.
Regards.

   Damien
From c82ebc3cb0cf7dad45eedc6122bf901215d49ed7 Mon Sep 17 00:00:00 2001
From: Damien de Lemeny <d.delem...@gmail.com>
Date: Sun, 30 May 2010 04:52:11 +0200
Subject: [PATCH] Refactor [gegl_]path_calc_values

* moded gegl/property-types/gegl-path.[c|h]
Add pos_min and pos_max parameters to get sample points on an arbitrary portion of the path
This reduces code and should be very useful to extract gegl_path_stroke in a proper operation.
---
 gegl/property-types/gegl-path.c |  109 ++++++++++++++++++++++++++++++++++-----
 gegl/property-types/gegl-path.h |    4 ++
 2 files changed, 100 insertions(+), 13 deletions(-)

diff --git a/gegl/property-types/gegl-path.c b/gegl/property-types/gegl-path.c
index bf514ca..9b20e53 100644
--- a/gegl/property-types/gegl-path.c
+++ b/gegl/property-types/gegl-path.c
@@ -383,6 +383,7 @@ GeglPathList * gegl_path_list_append (GeglPathList *head,
   return head;
 }
 
+#if 0
 static void
 path_calc (GeglPathList *path,
            gdouble       pos,
@@ -467,7 +468,6 @@ path_calc (GeglPathList *path,
       iter=iter->next;
     }
 }
-
 static void path_calc_values (GeglPathList *path,
                               guint         num_samples,
                               gdouble      *xs,
@@ -559,7 +559,96 @@ static void path_calc_values (GeglPathList *path,
       iter=iter->next;
     }
 }
+#endif
+static void path_calc_values (GeglPathList *path,
+                              gdouble       pos_min,
+                              gdouble       pos_max,
+                              guint         num_samples,
+                              gdouble      *xs,
+                              gdouble      *ys)
+{
+  gdouble length = path_get_length (path);
+  GeglPathList *iter = path;
+  
+  gint count_samples=0;
+  
+  gfloat x = 0, y = 0;
+  gfloat spacing = 0;
+  gfloat pos = 0, next_pos = 0, next_sample = 0, start = pos_min, stop = pos_max;
+  gboolean to_end = FALSE;
+
+  if ((pos_max > length) || (pos_max < pos_min))
+  /* Use the last point of the path as end */
+    {
+      stop = length;
+      count_samples++;
+      to_end = TRUE;
+    }
 
+  spacing = (start - stop) / num_samples;
+  next_sample = start;
+
+  while (iter)
+    {
+      switch (iter->d.type)
+        {
+          case 'M':
+            x = iter->d.point[0].x;
+            y = iter->d.point[0].y;
+            break;
+          case 'L':
+            {
+              Point a,b;
+              gfloat distance;
+              
+              a.x = x;
+              a.y = y;
+              b.x = iter->d.point[0].x;
+              b.y = iter->d.point[0].y;
+              
+              distance = point_dist (&a, &b);
+              next_pos += distance;
+              
+              while (next_pos > next_sample)
+                {
+                  Point spot;
+                  gfloat ratio = (next_sample - pos) / (next_pos - pos);
+          
+                  lerp (&spot, &a, &b, ratio);
+
+                      xs[count_samples]=spot.x;
+                      ys[count_samples]=spot.y;
+
+                  count_samples++;
+                  if (count_samples < num_samples)
+                    next_sample += spacing;
+                  else
+                    {
+                      if (to_end)
+                        {
+                          while (iter->next);
+                          xs[num_samples-1]=b.x;
+                          ys[num_samples-1]=b.y;
+                        }
+                      return;
+                    }
+                }
+                x = b.x;
+                y = b.y;
+              }
+            break;
+          case 'u':
+            g_error ("can't compute length for uninitialized path\n");
+            break;
+          case 's':
+            break;
+          default:
+            g_error ("can't compute length for instruction: %i\n", iter->d.type);
+            break;
+        }
+      iter=iter->next;
+    }
+}
 #if 0
 /* FIXME: this is terribly inefficient */
 static void
@@ -796,12 +885,6 @@ static void ensure_flattened (GeglPath *vector)
 }
 
 static void
-path_calc_values (GeglPathList *path,
-                  guint         num_samples,
-                  gdouble      *xs,
-                  gdouble      *ys);
-
-static void
 gegl_path_init (GeglPath *self)
 {
   GeglPathPrivate *priv;
@@ -1002,7 +1085,6 @@ void gegl_path_get_bounds (GeglPath *self,
 }
 
 
-
 void
 gegl_path_calc (GeglPath   *self,
                 gdouble     pos,
@@ -1013,12 +1095,14 @@ gegl_path_calc (GeglPath   *self,
   if (!self)
     return;
   ensure_flattened (self);
-  path_calc (priv->flat_path, pos, xd, yd);
+  path_calc_values (priv->flat_path, pos, pos, 1, xd, yd);
 }
 
 
 void
 gegl_path_calc_values (GeglPath *self,
+                         gdouble    pos_min,
+                         gdouble    pos_max,
                          guint      num_samples,
                          gdouble   *xs,
                          gdouble   *ys)
@@ -1027,10 +1111,9 @@ gegl_path_calc_values (GeglPath *self,
   if (!self)
     return;
   ensure_flattened (self);
-  path_calc_values (priv->flat_path, num_samples, xs, ys);
+  path_calc_values (priv->flat_path, 0, -1, num_samples, xs, ys);
 }
 
-
 /* --------------------------------------------------------------------------
  * A GParamSpec class to describe behavior of GeglPath as an object property
  * follows.
@@ -1621,7 +1704,7 @@ gegl_path_closest_point (GeglPath *path,
       return 0.0;
     }
 
-  gegl_path_calc_values (path, n, samples_x, samples_y);
+  gegl_path_calc_values (path, 0, -1, n, samples_x, samples_y);
 
   for (i=0;i<n;i++)
     {
@@ -1800,7 +1883,7 @@ void gegl_path_fill (GeglBuffer *buffer,
 
     xs = g_newa (gdouble, samples);
     ys = g_newa (gdouble, samples);
-    path_calc_values (priv->flat_path, samples, xs, ys);
+    path_calc_values (priv->flat_path, 0, -1, samples, xs, ys);
 
     /* clear scanline intersection lists */
     scanlines = g_newa (GSList*, extent.height * versubi);
diff --git a/gegl/property-types/gegl-path.h b/gegl/property-types/gegl-path.h
index e872e8a..5a1f7eb 100644
--- a/gegl/property-types/gegl-path.h
+++ b/gegl/property-types/gegl-path.h
@@ -239,6 +239,8 @@ void                 gegl_path_calc           (GeglPath     *path,
 /**
  * gegl_path_calc_values:
  * @path: a #GeglPath
+ * @pos_min: start sampling position
+ * @pos_max: stop sampling position, -1 for the end of the path
  * @num_samples: number of samples to compute
  * @xs: return location for x coordinates
  * @ys: return location for y coordinates
@@ -247,6 +249,8 @@ void                 gegl_path_calc           (GeglPath     *path,
  * the returned values include the start and end positions of the path.
  */
 void                 gegl_path_calc_values    (GeglPath    *path,
+                                               gdouble      pos_min,
+                                               gdouble      pos_max,
                                                guint        num_samples,
                                                gdouble     *xs,
                                                gdouble     *ys);
-- 
1.6.3.3

_______________________________________________
Gegl-developer mailing list
Gegl-developer@lists.XCF.Berkeley.EDU
https://lists.XCF.Berkeley.EDU/mailman/listinfo/gegl-developer

Reply via email to