[Bf-blender-cvs] [51a699ba78d] soc-2019-bevel-profiles: Profile Widget: Even length sampling option

Hans Goudey noreply at git.blender.org
Sat Aug 17 22:49:50 CEST 2019


Commit: 51a699ba78d4c5236c31a6b81b50c56d85023f02
Author: Hans Goudey
Date:   Sat Aug 17 16:48:58 2019 -0400
Branches: soc-2019-bevel-profiles
https://developer.blender.org/rB51a699ba78d4c5236c31a6b81b50c56d85023f02

Profile Widget: Even length sampling option

Not compatible with !sample_straight_edges, but it's helpful
enought that it's worthwhile to include now.

===================================================================

M	source/blender/blenkernel/BKE_profile_widget.h
M	source/blender/blenkernel/intern/profile_widget.c
M	source/blender/editors/interface/interface_templates.c
M	source/blender/makesdna/DNA_profilewidget_types.h
M	source/blender/makesrna/intern/rna_profile.c

===================================================================

diff --git a/source/blender/blenkernel/BKE_profile_widget.h b/source/blender/blenkernel/BKE_profile_widget.h
index 13f9cc332a8..c5358b3dbd7 100644
--- a/source/blender/blenkernel/BKE_profile_widget.h
+++ b/source/blender/blenkernel/BKE_profile_widget.h
@@ -64,9 +64,9 @@ void BKE_profilewidget_changed(struct ProfileWidget *prwdgt, const bool rem_doub
 /* Need to find the total length of the curve to sample a portion of it */
 float BKE_profilewidget_total_length(const struct ProfileWidget *prwdgt);
 
-void BKE_profilewidget_create_samples_even_spacing(const struct ProfileWidget *prwdgt,
-                                                   double *x_table_out,
-                                                   double *y_table_out);
+void BKE_profilewidget_create_samples_even_spacing(struct ProfileWidget *prwdgt,
+                                                   int n_segments,
+                                                   struct ProfilePoint *r_samples);
 
 /* Length portion is the fraction of the total path length where we want the location */
 void BKE_profilewidget_evaluate_length_portion(const struct ProfileWidget *prwdgt,
diff --git a/source/blender/blenkernel/intern/profile_widget.c b/source/blender/blenkernel/intern/profile_widget.c
index 1077f9efe82..6afe87c8ffb 100644
--- a/source/blender/blenkernel/intern/profile_widget.c
+++ b/source/blender/blenkernel/intern/profile_widget.c
@@ -41,8 +41,6 @@
 #include "BKE_curve.h"
 #include "BKE_fcurve.h"
 
-#define DEBUG_PRWDGT_EVALUATE
-
 void BKE_profilewidget_free_data(ProfileWidget *prwdgt)
 {
   if (prwdgt->path) {
@@ -508,11 +506,6 @@ static float bezt_edge_handle_angle(const BezTriple *bezt, int i_edge)
   sub_v2_v2v2(end_handle_direction, bezt[i_edge + 1].vec[1], bezt[i_edge + 1].vec[0]);
 
   float angle = angle_v2v2(start_handle_direction, end_handle_direction);
-//  printf("bezt_edge_handle_angle: i: %d, angle:%.2f\n", i_edge, RAD2DEGF(angle));
-//  printf("  first point:         (%.2f, %.2f)\n", bezt[i_edge].vec[1][0], bezt[i_edge].vec[1][1]);
-//  printf("  first inner handle:  (%.2f, %.2f)\n", bezt[i_edge].vec[2][0], bezt[i_edge].vec[2][1]);
-//  printf("  second inner handle: (%.2f, %.2f)\n", bezt[i_edge + 1].vec[0][0], bezt[i_edge + 1].vec[0][1]);
-//  printf("  second point:        (%.2f, %.2f)\n", bezt[i_edge + 1].vec[1][0], bezt[i_edge + 1].vec[1][1]);
   return angle;
 }
 
@@ -745,13 +738,20 @@ static void profilewidget_make_segments_table(ProfileWidget *prwdgt)
   ProfilePoint *new_table = MEM_callocN((size_t)(n_samples + 1) * sizeof(ProfilePoint),
                                         "samples table");
 
-  BKE_profilewidget_create_samples(prwdgt, n_samples, prwdgt->flag & PROF_SAMPLE_STRAIGHT_EDGES,
-                               new_table);
+  if (prwdgt->flag & PROF_SAMPLE_EVEN_LENGTHS) {
+    /* Even length sampling incompatible with only straight edge sampling for now. */
+    BKE_profilewidget_create_samples_even_spacing(prwdgt, n_samples, new_table);
+  }
+  else {
+    BKE_profilewidget_create_samples(prwdgt, n_samples, prwdgt->flag & PROF_SAMPLE_STRAIGHT_EDGES,
+                                     new_table);
+  }
 
   if (prwdgt->segments) {
     MEM_freeN(prwdgt->segments);
   }
   prwdgt->segments = new_table;
+
 }
 
 /** Sets the default settings and clip range for the profile widget. Does not generate either
@@ -863,81 +863,83 @@ void BKE_profilewidget_initialize(ProfileWidget *prwdgt, short nsegments)
 {
   prwdgt->totsegments = nsegments;
 
-  /* Calculate the higher resolution tables for display and evaluation. */
+  /* Calculate the higher resolution / segments tables for display and evaluation. */
   BKE_profilewidget_changed(prwdgt, false);
 }
 
 /** Gives the distance to the next point in the widget's sampled table, in other words the length
  * of the ith edge of the table.
  * \note Requires profilewidget_initialize or profilewidget_changed call before to fill table. */
-static float profilewidget_distance_to_next_point(const ProfileWidget *prwdgt, int i)
+static float profilewidget_distance_to_next_table_point(const ProfileWidget *prwdgt, int i)
 {
-  BLI_assert(prwdgt != NULL);
-  BLI_assert(i >= 0);
-  BLI_assert(i < prwdgt->totpoint);
-
-  float x = prwdgt->table[i].x;
-  float y = prwdgt->table[i].y;
-  float x_next = prwdgt->table[i + 1].x;
-  float y_next = prwdgt->table[i + 1].y;
+  BLI_assert(i < PROF_N_TABLE(prwdgt->totpoint));
 
-  return sqrtf(powf(y_next - y, 2) + powf(x_next - x, 2));
+  return len_v2v2(&prwdgt->table[i].x, &prwdgt->table[i + 1].x);
 }
 
 /** Calculates the total length of the profile from the curves sampled in the table.
  * \note Requires profilewidget_initialize or profilewidget_changed call before to fill table. */
 float BKE_profilewidget_total_length(const ProfileWidget *prwdgt)
 {
-  float loc1[2], loc2[2];
   float total_length = 0;
-
-  for (int i = 0; i < PROF_N_TABLE(prwdgt->totpoint); i++) {
-    loc1[0] = prwdgt->table[i].x;
-    loc1[1] = prwdgt->table[i].y;
-    loc2[0] = prwdgt->table[i].x;
-    loc2[1] = prwdgt->table[i].y;
-    total_length += len_v2v2(loc1, loc2);
+  for (int i = 0; i < PROF_N_TABLE(prwdgt->totpoint) - 1; i++) {
+    total_length += len_v2v2(&prwdgt->table[i].x, &prwdgt->table[i + 1].x);
   }
   return total_length;
 }
 
 /** Samples evenly spaced positions along the profile widget's table (generated from path). Fills
  * an entire table at once for a speedup if all of the results are going to be used anyway.
- * \note Requires profilewidget_initialize or profilewidget_changed call before to fill table. */
-/* HANS-TODO: Enable this for an "even length sampling" option (and debug it). */
-void BKE_profilewidget_create_samples_even_spacing(const ProfileWidget *prwdgt,
-                                                   double *x_table_out,
-                                                   double *y_table_out)
+ * \note Requires profilewidget_initialize or profilewidget_changed call before to fill table.
+ * \note Working, but would conflict with "Sample Straight Edges" option, so this is unused for now. */
+void BKE_profilewidget_create_samples_even_spacing(ProfileWidget *prwdgt,
+                                                   int n_segments,
+                                                   ProfilePoint *r_samples)
 {
   const float total_length = BKE_profilewidget_total_length(prwdgt);
-  const float segment_length = total_length / prwdgt->totsegments;
+  const float segment_length = total_length / n_segments;
   float length_travelled = 0.0f;
-  float distance_to_next_point = profilewidget_distance_to_next_point(prwdgt, 0);
-  float distance_to_previous_point = 0.0f;
-  float travelled_since_last_point = 0.0f;
-  float segment_left = segment_length;
-  float f;
-  int i_point = 0;
+  float distance_to_next_table_point = profilewidget_distance_to_next_table_point(prwdgt, 0);
+  float distance_to_previous_table_point = 0.0f;
+  float segment_left, factor;
+  int i_table = 0;
+
+  /* Set the location for the first point. */
+  r_samples[0].x = prwdgt->table[0].x;
+  r_samples[0].y = prwdgt->table[0].y;
 
   /* Travel along the path, recording the locations of segments as we pass them. */
-  for (int i = 0; i < prwdgt->totsegments; i++) {
-    /* Travel over all of the points that could be inside this segment. */
-    while (distance_to_next_point > segment_length * (i + 1) - length_travelled) {
-      length_travelled += distance_to_next_point;
-      segment_left -= distance_to_next_point;
-      travelled_since_last_point += distance_to_next_point;
-      i_point++;
-      distance_to_next_point = profilewidget_distance_to_next_point(prwdgt, i_point);
-      distance_to_previous_point = 0.0f;
+  segment_left = segment_length;
+  for (int i = 1; i < n_segments; i++) {
+    /* Travel over all of the points that fit inside this segment. */
+    while (distance_to_next_table_point < segment_left) {
+      length_travelled += distance_to_next_table_point;
+      segment_left -= distance_to_next_table_point;
+      i_table++;
+      distance_to_next_table_point = profilewidget_distance_to_next_table_point(prwdgt, i_table);
+      distance_to_previous_table_point = 0.0f;
     }
-    /* We're now at the last point that fits inside the current segment. */
-    f = segment_left / (distance_to_previous_point + distance_to_next_point);
-    x_table_out[i] = (double)interpf(prwdgt->table[i_point].x, prwdgt->table[i_point + 1].x, f);
-    y_table_out[i] = (double)interpf(prwdgt->table[i_point].x, prwdgt->table[i_point + 1].x, f);
-    distance_to_next_point -= segment_left;
-    distance_to_previous_point += segment_left;
+    /* We're at the last table point that fits inside the current segment, use interpolation. */
+    factor = (distance_to_previous_table_point + segment_left) / (distance_to_previous_table_point + distance_to_next_table_point);
+    r_samples[i].x = interpf(prwdgt->table[i_table + 1].x, prwdgt->table[i_table].x, factor);
+    r_samples[i].y = interpf(prwdgt->table[i_table + 1].y, prwdgt->table[i_table].y, factor);
+#ifdef DEBUG_PRWDGT_EVALUATE
+    BLI_assert(factor <= 1.0f && factor >= 0.0f);
+    printf("segment_left: %.3f\n", segment_left);
+    printf("i_table: %d\n", i_table);
+    printf("distance_to_previous_table_point: %.3f\n", distance_to_previous_table_point);
+    printf("distance_to_next_table_point: %.3f\n", distance_to_next_table_point);
+    printf("Interpolating with factor %.3f from (%.3f, %.3f) to (%.3f, %.3f)\n\n",
+           factor,
+           prwdgt->table[i_table].x, prwdgt->table[i_table].y,
+           prwdgt->table[i_table + 1].x, prwdgt->table[i_table + 1].y);
+#endif
 
+    /* We sampled in between this table point and the next, so the next travel step is smaller. */
+    distance_to_next_table_point -= segment_left;
+    distance_to_previous_table_point += segment_left;
     length_travelled += segment_left;
+    segment_left = segment_length;
   }
 }
 
@@ -964,7 +966,7 @@ void BKE_profilewidget_evaluate_length_portion(const ProfileWidget *prwdgt,
     if (i == PROF_N_TABLE(prwdgt->totpoint) - 2) {
       break;
     }
-    float new_length = profilewidget_distance_to_next_point(prwdgt, i);
+    float new_length = profilewidget_d

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list