[Bf-blender-cvs] [f504422d92c] soc-2021-curves: Added support for cutting Poly and NURBS splines

dilithjay noreply at git.blender.org
Fri Aug 6 05:15:11 CEST 2021


Commit: f504422d92cda23efc18bd9c085ec8fc05543741
Author: dilithjay
Date:   Thu Aug 5 18:53:26 2021 +0530
Branches: soc-2021-curves
https://developer.blender.org/rBf504422d92cda23efc18bd9c085ec8fc05543741

Added support for cutting Poly and NURBS splines

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

M	source/blender/editors/curve/editcurve_pen.c

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

diff --git a/source/blender/editors/curve/editcurve_pen.c b/source/blender/editors/curve/editcurve_pen.c
index 0f90f782ee7..361c657fa0c 100644
--- a/source/blender/editors/curve/editcurve_pen.c
+++ b/source/blender/editors/curve/editcurve_pen.c
@@ -46,7 +46,7 @@
 /* Data structure to keep track of details about the cut location */
 typedef struct CutBeztData {
   /* Index of the last bez triple before the cut. */
-  int bezt_index;
+  int bezt_index, bp_index;
   /* Nurb to which the cut belongs to. */
   Nurb *nurb;
   /* Minimum distance to curve from mouse location. */
@@ -59,7 +59,7 @@ typedef struct CutBeztData {
   float prev_loc[3], cut_loc[3], next_loc[3];
   /* Mouse location as floats. */
   float mval[2];
-} CutBeztData;
+} CutData;
 
 /* Data required segment altering functionality. */
 typedef struct MoveSegmentData {
@@ -220,7 +220,8 @@ static float get_view_zoom(const float depth[3], const ViewContext *vc)
   return 15.0f / len_v2v2(p1_3d, p2_3d);
 }
 
-/* Get the closest point on an edge to a given point based on perpendicular distance. */
+/* Get the closest point on an edge to a given point based on perpendicular distance. Return true
+ * if closest point on curve.  */
 static bool get_closest_point_on_edge(float point[3],
                                       const float pos[2],
                                       const float pos1[3],
@@ -344,7 +345,7 @@ static void update_data_if_nearest_point_in_segment(BezTriple *bezt1,
                                                     void *op_data)
 {
 
-  CutBeztData *data = op_data;
+  CutData *data = op_data;
 
   float resolu = nu->resolu;
   float *points = MEM_mallocN(sizeof(float[3]) * (resolu + 1), "makeCut_bezier");
@@ -396,7 +397,7 @@ static void update_data_if_nearest_point_in_segment(BezTriple *bezt1,
 /* Update the closest point in the data structure. */
 static void update_closest_point_in_data(void *op_data, int resolution, ViewContext *vc)
 {
-  CutBeztData *data = op_data;
+  CutData *data = op_data;
   bool found_min = false;
   float point[3];
   float factor;
@@ -467,10 +468,10 @@ static void calculate_new_bezier_point(const float point_prev[3],
 /* Update the nearest point data for all nurbs. */
 static void update_data_for_all_nurbs(ListBase *nurbs, ViewContext *vc, void *op_data)
 {
-  CutBeztData *data = op_data;
+  CutData *data = op_data;
 
   for (Nurb *nu = nurbs->first; nu; nu = nu->next) {
-    if (nu->type == CU_BEZIER) {
+    if (nu->bezt) {
       float screen_co[2];
       if (data->nurb == NULL) {
         ED_view3d_project_float_object(
@@ -493,6 +494,36 @@ static void update_data_for_all_nurbs(ListBase *nurbs, ViewContext *vc, void *op
         update_data_if_nearest_point_in_segment(bezt + 1, nu->bezt, nu, i, vc, screen_co, data);
       }
     }
+    else if (nu->bp) {
+      float screen_co[2];
+      ED_view3d_project_float_object(
+          vc->region, nu->bp->vec, screen_co, V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN);
+      if (data->nurb == NULL) {
+        data->nurb = nu;
+        data->bp_index = 0;
+        data->min_dist = len_manhattan_v2v2(screen_co, data->mval);
+        copy_v3_v3(data->cut_loc, nu->bp->vec);
+      }
+
+      for (int i = 0; i < nu->pntsu - 1; i++) {
+        float point[3], factor;
+        bool found_min = get_closest_point_on_edge(
+            point, data->mval, (nu->bp + i)->vec, (nu->bp + i + 1)->vec, vc, &factor);
+        if (found_min) {
+          float point_2d[2];
+          ED_view3d_project_float_object(
+              vc->region, point, point_2d, V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN);
+          float dist = len_manhattan_v2v2(point_2d, data->mval);
+          if (dist < data->min_dist) {
+            data->min_dist = dist;
+            data->nurb = nu;
+            data->bp_index = i;
+            data->parameter = factor;
+            copy_v3_v3(data->cut_loc, point);
+          }
+        }
+      }
+    }
   }
 }
 
@@ -500,7 +531,7 @@ static void update_data_for_all_nurbs(ListBase *nurbs, ViewContext *vc, void *op
 static void add_bezt_to_nurb(Nurb *nu, void *op_data, Curve *cu)
 {
   EditNurb *editnurb = cu->editnurb;
-  CutBeztData *data = op_data;
+  CutData *data = op_data;
 
   BezTriple *bezt1 = (BezTriple *)MEM_mallocN((nu->pntsu + 1) * sizeof(BezTriple),
                                               "new_bezt_nurb");
@@ -553,16 +584,60 @@ static void add_bezt_to_nurb(Nurb *nu, void *op_data, Curve *cu)
   new_bezt->f1 = new_bezt->f2 = new_bezt->f3 = 1;
 }
 
+/* Insert a bezt to a nurb at the location specified by op_data. */
+static void add_bp_to_nurb(Nurb *nu, void *op_data, Curve *cu)
+{
+  EditNurb *editnurb = cu->editnurb;
+  CutData *data = op_data;
+
+  BPoint *bp1 = (BPoint *)MEM_mallocN((nu->pntsu + 1) * sizeof(BPoint), "new_bp_nurb");
+  int index = data->bp_index + 1;
+  /* Copy all control points before the cut to the new memory. */
+  memcpy(bp1, nu->bp, index * sizeof(BPoint));
+  BPoint *new_bp = bp1 + index;
+
+  /* Duplicate control point after the cut. */
+  memcpy(new_bp, new_bp - 1, sizeof(BPoint));
+  copy_v3_v3(new_bp->vec, data->cut_loc);
+
+  if (index < nu->pntsu) {
+    /* Copy all control points after the cut to the new memory. */
+    memcpy(bp1 + index + 1, nu->bp + index, (nu->pntsu - index) * sizeof(BPoint));
+  }
+
+  nu->pntsu += 1;
+  cu->actvert = CU_ACT_NONE;
+
+  BPoint *next_bp;
+  if ((nu->flagu & CU_NURB_CYCLIC) && (index == nu->pntsu - 1)) {
+    next_bp = bp1;
+  }
+  else {
+    next_bp = new_bp + 1;
+  }
+
+  /* Interpolate radius, tilt, weight */
+  new_bp->tilt = interpf(next_bp->tilt, (new_bp - 1)->tilt, data->parameter);
+  new_bp->radius = interpf(next_bp->radius, (new_bp - 1)->radius, data->parameter);
+  new_bp->weight = interpf(next_bp->weight, (new_bp - 1)->weight, data->parameter);
+
+  MEM_freeN(nu->bp);
+  nu->bp = bp1;
+  ED_curve_deselect_all(editnurb);
+  BKE_nurb_knot_calc_u(nu);
+}
+
 /* Make a cut on the nearest nurb at the closest point. */
 static void make_cut(const wmEvent *event, Curve *cu, Nurb **r_nu, ViewContext *vc)
 {
-  CutBeztData data = {.bezt_index = 0,
-                      .min_dist = 10000,
-                      .parameter = 0.5f,
-                      .has_prev = false,
-                      .has_next = false,
-                      .mval[0] = event->mval[0],
-                      .mval[1] = event->mval[1]};
+  CutData data = {.bezt_index = 0,
+                  .bp_index = 0,
+                  .min_dist = 10000,
+                  .parameter = 0.5f,
+                  .has_prev = false,
+                  .has_next = false,
+                  .mval[0] = event->mval[0],
+                  .mval[1] = event->mval[1]};
 
   ListBase *nurbs = BKE_curve_editNurbs_get(cu);
 
@@ -572,10 +647,15 @@ static void make_cut(const wmEvent *event, Curve *cu, Nurb **r_nu, ViewContext *
   /* If the minimum distance found < threshold distance, make cut. */
   if (data.min_dist < threshold_distance) {
     Nurb *nu = data.nurb;
-    if (nu && nu->type == CU_BEZIER) {
-      update_closest_point_in_data(&data, nu->resolu, vc);
-      add_bezt_to_nurb(nu, &data, cu);
-      *r_nu = nu;
+    if (nu) {
+      if (nu->bezt) {
+        update_closest_point_in_data(&data, nu->resolu, vc);
+        add_bezt_to_nurb(nu, &data, cu);
+        *r_nu = nu;
+      }
+      else if (nu->bp) {
+        add_bp_to_nurb(nu, &data, cu);
+      }
     }
   }
 }
@@ -625,13 +705,13 @@ static bool is_curve_nearby(ViewContext *vc, wmOperator *op, const wmEvent *even
   Curve *cu = vc->obedit->data;
   ListBase *nurbs = BKE_curve_editNurbs_get(cu);
 
-  CutBeztData data = {.bezt_index = 0,
-                      .min_dist = 10000,
-                      .parameter = 0.5f,
-                      .has_prev = false,
-                      .has_next = false,
-                      .mval[0] = event->mval[0],
-                      .mval[1] = event->mval[1]};
+  CutData data = {.bezt_index = 0,
+                  .min_dist = 10000,
+                  .parameter = 0.5f,
+                  .has_prev = false,
+                  .has_next = false,
+                  .mval[0] = event->mval[0],
+                  .mval[1] = event->mval[1]};
 
   update_data_for_all_nurbs(nurbs, vc, &data);
 
@@ -870,7 +950,7 @@ static int curve_pen_modal(bContext *C, wmOperator *op, const wmEvent *event)
           make_cut(event, cu, &nu, &vc);
         }
 
-        if (nu) {
+        if (nu && nu->bezt) {
           BKE_nurb_handles_calc(nu);
         }
       }



More information about the Bf-blender-cvs mailing list