[Bf-blender-cvs] [65aa1620a13] soc-2019-bevel-profiles: ProfileWidget: Updated insert algorithm.

Hans Goudey noreply at git.blender.org
Mon Jun 24 06:41:25 CEST 2019


Commit: 65aa1620a134ee855152c2c15c8727fb184a6959
Author: Hans Goudey
Date:   Mon Jun 24 00:38:23 2019 -0400
Branches: soc-2019-bevel-profiles
https://developer.blender.org/rB65aa1620a134ee855152c2c15c8727fb184a6959

ProfileWidget: Updated insert algorithm.

The choice of neighbors for the inserted point now uses the minimum
distance to the other line segments rather than their X positions.

Luckily there is a dist_squared_to_line_segment_v2 already in Blender!

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

M	source/blender/blenkernel/intern/profile_path.c

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

diff --git a/source/blender/blenkernel/intern/profile_path.c b/source/blender/blenkernel/intern/profile_path.c
index ab3e518da42..4796966927f 100644
--- a/source/blender/blenkernel/intern/profile_path.c
+++ b/source/blender/blenkernel/intern/profile_path.c
@@ -223,79 +223,57 @@ void profilepath_remove(ProfilePath *prpath, const short flag)
   prpath->totpoint -= removed;
 }
 
+/* The choice for which points to place the new vertex between is more complex with a profile than
+ * with a mapping function. We can't just find the new neighbors with X value comparisons. Instead
+ * this function checks which line segment is closest to the new point with a handy pre-made
+ * function.
+*/
 ProfilePoint *profilepath_insert(ProfilePath *prpath, float x, float y)
 {
-  ProfilePoint *pts = MEM_callocN(((size_t)prpath->totpoint + 1) * sizeof(ProfilePoint),
-                                  "path points");
-  ProfilePoint *newpt = NULL;
-  int a, b;
-  bool foundloc = false;
-
+  ProfilePoint *new_pt;
+  float new_loc[2] = {x, y};
 #if DEBUG_PRWDGT
-  printf("PROFILEPATH INSERT");
-  printf("(begin total points = %d)", prpath->totpoint);
+  printf("PROFILEPATH INSERT\n");
 #endif
 
-  /* insert fragments of the old one and the new point to the new curve */
+  float distance;
+  float min_distance = FLT_MAX;
+  int insert_i;
+  for (int i = 0; i < prpath->totpoint - 1; i++) {
+    float loc1[2] = {prpath->path[i].x, prpath->path[i].y};
+    float loc2[2] = {prpath->path[i + 1].x, prpath->path[i + 1].y};
+
+    distance = dist_squared_to_line_segment_v2(new_loc, loc1, loc2);
+    if (distance < min_distance) {
+      min_distance = distance;
+      insert_i = i + 1;
+    }
+  }
+
+  /* Insert the new point at the location we found and copy all of the old points in as well */
   prpath->totpoint++;
-  for (a = 0, b = 0; a < prpath->totpoint; a++) {
-    /* Insert the new point at the correct X location */
-    if ((foundloc == false) && ((a + 1 == prpath->totpoint) || (x < prpath->path[a].x))) {
-      pts[a].x = x;
-      pts[a].y = y;
-      pts[a].flag = PROF_SELECT;
-      foundloc = true;
-      newpt = &pts[a];
+  ProfilePoint *new_pts = MEM_mallocN(((size_t)prpath->totpoint) * sizeof(ProfilePoint),
+                                      "path points");
+  for (int i_new = 0, i_old = 0; i_new < prpath->totpoint; i_new++) {
+    if (i_new != insert_i) {
+      /* Insert old point */
+      new_pts[i_new].x = prpath->path[i_old].x;
+      new_pts[i_new].y = prpath->path[i_old].y;
+      new_pts[i_new].flag = prpath->path[i_old].flag & ~PROF_SELECT; /* Deselect old points */
+      i_old++;
     }
     else {
-      /* Copy old point over to the new array */
-      pts[a].x = prpath->path[b].x;
-      pts[a].y = prpath->path[b].y;
-      /* make sure old points don't remain selected */
-      pts[a].flag = prpath->path[b].flag & ~PROF_SELECT;
-      pts[a].shorty = prpath->path[b].shorty;
-      b++;
+      /* Insert new point */
+      new_pts[i_new].x = x;
+      new_pts[i_new].y = y;
+      new_pts[i_new].flag = PROF_SELECT;
+      new_pt = &new_pts[i_new];
     }
   }
-#if DEBUG_PRWDGT
-  printf("(end total points = %d)\n", prpath->totpoint);
-#endif
-
-  /* free old path and replace it with the new one */
-  MEM_freeN(prpath->path);
-  prpath->path = pts;
 
-  return newpt;
-}
-
-/* HANS-TODO: New insertion algorithm. Find closest points in 2D and then insert them in the
- * middle of those. Maybe just lengthen the size of the array instead of allocating a new one
- * too, but that probbaly doesn't matter so much.
- *
- * New algorithm would probably be: Sort the points by their proximity to the new location. Then
- * find the two points closest to the new position that are ordered one after the next in the
- * original array of points (this will probably be the two closest points, but for more
- * complicated profiles it could be points on opposite sides of the profile). Then insert the new
- * point between the two we just found. */
-ProfilePoint *profilepath_insert2(ProfilePath *prpath, float x, float y)
-{
-  ProfilePoint *new_pts = MEM_callocN(((size_t)prpath->totpoint + 1) * sizeof(ProfilePoint),
-                                  "path points");
-  ProfilePoint *new_pt = NULL;
-  int a, b;
-  bool foundloc = false;
-  int *sorted_indices = MEM_callocN((size_t)prpath->totpoint * sizeof(int), "points sorted i");
-
-
-
-
-
-  /* free old path and replace it with the new one */
+  /* Free the old points and use the new ones */
   MEM_freeN(prpath->path);
   prpath->path = new_pts;
-
-  MEM_freeN(sorted_indices);
-
   return new_pt;
 }
 
@@ -351,19 +329,19 @@ void profilepath_reset(ProfilePath *prpath, int preset)
 /**
  * \param type: eBezTriple_Handle
  */
-void profilepath_handle_set(ProfilePath *cuma, int type)
+void profilepath_handle_set(ProfilePath *prpath, int type)
 {
 #if DEBUG_PRWDGT
   printf("PROFILEPATH HANDLE SET\n");
 #endif
 
-  if (cuma->path->flag & PROF_SELECT) {
-    cuma->path->flag &= ~(PROF_HANDLE_VECTOR | PROF_HANDLE_AUTO_ANIM);
+  if (prpath->path->flag & PROF_SELECT) {
+    prpath->path->flag &= ~(PROF_HANDLE_VECTOR | PROF_HANDLE_AUTO_ANIM);
     if (type == HD_VECT) {
-      cuma->path->flag |= PROF_HANDLE_VECTOR;
+      prpath->path->flag |= PROF_HANDLE_VECTOR;
     }
     else if (type == HD_AUTO_ANIM) {
-      cuma->path->flag |= PROF_HANDLE_AUTO_ANIM;
+      prpath->path->flag |= PROF_HANDLE_AUTO_ANIM;
     }
     else {
       /* pass */
@@ -380,7 +358,7 @@ void profilepath_handle_set(ProfilePath *cuma, int type)
 static void calchandle_profile(BezTriple *bezt, const BezTriple *prev, const BezTriple *next)
 {
 #if DEBUG_PRWDGT
-  printf("CALCHANDLE PROFILE\n");
+  printf("CALCHANDLE PROFILE");
 #endif
   /* defines to avoid confusion */
 #define p2_h1 ((p2)-3)
@@ -496,6 +474,9 @@ static void calchandle_profile(BezTriple *bezt, const BezTriple *prev, const Bez
   if (bezt->h2 == HD_VECT) {
     madd_v2_v2v2fl(p2_h2, p2, dvec_b, 1.0f / 3.0f);
   }
+#if DEBUG_PRWDGT
+  printf("(finished)\n");
+#endif
 
 #undef p2_h1
 #undef p2_h2
@@ -551,7 +532,7 @@ static void profilepath_make_table(ProfilePath *prpath, const rctf *clipr)
 
   /* first and last handle need correction, instead of pointing to center of next/prev,
    * we let it point to the closest handle */
-  /* HANS-TODO: Remove this correction  */
+  /* HANS-TODO: Remove this correction?  */
   if (prpath->totpoint > 2) {
     float hlen, nlen, vec[3];



More information about the Bf-blender-cvs mailing list