[Bf-blender-cvs] [2ac3bc6] gsoc2016-improved_extrusion: Curves: Extend tool

João Araújo noreply at git.blender.org
Wed Jun 22 22:12:06 CEST 2016


Commit: 2ac3bc6b1b312f70555e9f24c78ca49080ee069b
Author: João Araújo
Date:   Wed Jun 22 21:10:46 2016 +0100
Branches: gsoc2016-improved_extrusion
https://developer.blender.org/rB2ac3bc6b1b312f70555e9f24c78ca49080ee069b

Curves: Extend tool

Fixed a bug with memory that was generating wrong results.
This commit also contains some of the code for the Trim tool, though most of it is commented out.

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

M	source/blender/editors/curve/curve_intern.h
M	source/blender/editors/curve/curve_ops.c
M	source/blender/editors/curve/editcurve.c

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

diff --git a/source/blender/editors/curve/curve_intern.h b/source/blender/editors/curve/curve_intern.h
index 2fb7fc7..882af34 100644
--- a/source/blender/editors/curve/curve_intern.h
+++ b/source/blender/editors/curve/curve_intern.h
@@ -129,6 +129,7 @@ void CURVE_OT_cyclic_toggle(struct wmOperatorType *ot);
 void CURVE_OT_match_texture_space(struct wmOperatorType *ot);
 
 void CURVE_OT_extend_curve(struct wmOperatorType *ot);
+void CURVE_OT_trim_curve(struct wmOperatorType *ot);
 
 bool ED_curve_pick_vert(
         struct ViewContext *vc, short sel, const int mval[2],
diff --git a/source/blender/editors/curve/curve_ops.c b/source/blender/editors/curve/curve_ops.c
index e158ba4..e3b2096 100644
--- a/source/blender/editors/curve/curve_ops.c
+++ b/source/blender/editors/curve/curve_ops.c
@@ -140,6 +140,7 @@ void ED_operatortypes_curve(void)
 	WM_operatortype_append(CURVE_OT_extrude);
 	WM_operatortype_append(CURVE_OT_cyclic_toggle);
 	WM_operatortype_append(CURVE_OT_extend_curve);
+	WM_operatortype_append(CURVE_OT_trim_curve);
 
 	WM_operatortype_append(CURVE_OT_match_texture_space);
 }
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index a96b188..4dd4c6e 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -6469,7 +6469,7 @@ static ListBase *interpolate_all_segments(Nurb *nu)
 	int bezier_points = nu->pntsu;
 
 	while (i < bezier_points-1+nu->flagu) {
-		coord_array = MEM_callocN(dims * (nu->resolu) * sizeof(float), "interpolate_bezier2");
+		coord_array = MEM_callocN(dims * (nu->resolu + 1) * sizeof(float), "interpolate_bezier2");
 		link = MEM_callocN(sizeof(LinkData), "interpolate_bezier3");
 		link->data = coord_array;
 		for (int j = 0; j < dims; j++) {
@@ -6477,7 +6477,7 @@ static ListBase *interpolate_all_segments(Nurb *nu)
 										  nu->bezt[i%bezier_points].vec[2][j],
 										  nu->bezt[(i+1)%bezier_points].vec[0][j],
 										  nu->bezt[(i+1)%bezier_points].vec[1][j],
-										  coord_array + j, nu->resolu - 1, sizeof(float) * dims);
+										  coord_array + j, nu->resolu, sizeof(float) * dims);
 		}
 		BLI_addtail(pl, link);
 		i++;
@@ -6506,7 +6506,7 @@ static ListBase *get_intersections(float *p1, float *p2, ListBase *nubase)
 {
 	/* return a list with all the intersection points of the segment p1p2 with the curve object */
 	ListBase *spline_list, *points_list;
-	ListBase *il = (ListBase *)MEM_callocN(sizeof(ListBase), "get_intersections1");;
+	ListBase *il = (ListBase *)MEM_callocN(sizeof(ListBase), "get_intersections1");
 	LinkData *intersection, *link, *spl;
 	float *coord_array, *vi, p3[2], p4[2];
 	Nurb *nu = nubase->first;
@@ -6518,14 +6518,14 @@ static ListBase *get_intersections(float *p1, float *p2, ListBase *nubase)
 		points_list = spl->data;        /* output of interpolate_all_segments */
 		for (link = points_list->first; link; link=link->next) {
 			coord_array = (float *)link->data;
-			for (int i = 0; i < nu->resolu - 1; i++) {
+			for (int i = 0; i < nu->resolu; i++) {
 				vi = (float *) MEM_callocN(3 * sizeof(float), "get_intersections2");
 				p3[0] = coord_array[i * dims];
 				p3[1] = coord_array[i * dims + 1];
 				p4[0] = coord_array[(i + 1) * dims];
 				p4[1] = coord_array[(i + 1) * dims + 1];
 				result = isect_seg_seg_v2_point(p2, p1, p3, p4, vi);
-				if (result == 1 && len_v2v2(vi, p1) > PRECISION) {
+				if (result == 1 && len_v2v2(vi, p1) > PRECISION && len_v2v2(vi, p2) > PRECISION) {
 					intersection = MEM_callocN(sizeof(LinkData), "get_intersections4");
 					intersection->data = vi;
 					BLI_addtail(il, intersection);
@@ -6681,3 +6681,478 @@ void CURVE_OT_extend_curve(wmOperatorType *ot)
 	/* flags */
 	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
+
+/******************** Trim curve operator ********************/
+
+/*import bpy
+from mathutils import Vector
+from mathutils.geometry import intersect_line_line_2d, intersect_line_line, interpolate_bezier
+
+
+PRECISION = 1.0e-5
+
+
+def active_spline_id(shape_ob):
+    '''
+    returns integer of active spline
+    '''
+    return [i for i,s in enumerate(shape_ob.data.splines) if s == shape_ob.data.splines.active][0]
+
+
+def sel_point_id(spline_ob):
+    '''
+    > spline_ob:     bezier spline object
+    < returns integer of selected points
+    '''
+    return [i for i,bp in enumerate(spline_ob.bezier_points) if bp.select_control_point]
+
+
+def interpolate_all_segments(spline_ob):
+    '''
+    > spline_ob:     bezier spline object
+    < returns interpolated splinepoints
+    '''
+    point_range = len(spline_ob.bezier_points)
+    pl = []
+
+    for i in range (0, point_range-1+spline_ob.use_cyclic_u):
+        if len(pl) > 0:
+            pl.pop()
+        seg = (interpolate_bezier(spline_ob.bezier_points[i%point_range].co,
+                                  spline_ob.bezier_points[i%point_range].handle_right,
+                                  spline_ob.bezier_points[(i+1)%point_range].handle_left,
+                                  spline_ob.bezier_points[(i+1)%point_range].co,
+                                  spline_ob.resolution_u+1))
+        pl += seg
+    return pl
+
+
+def interpolate_spline(spline_ob):
+    '''
+    > spline_ob:     bezier spline object
+    < returns segments as lists of vectors
+    '''
+    point_range = len(spline_ob.bezier_points)
+    segments = []
+
+    for i in range (0, point_range-1+spline_ob.use_cyclic_u):
+        segments.append(interpolate_bezier(spline_ob.bezier_points[i%point_range].co,
+                                           spline_ob.bezier_points[i%point_range].handle_right,
+                                           spline_ob.bezier_points[(i+1)%point_range].handle_left,
+                                           spline_ob.bezier_points[(i+1)%point_range].co,
+                                           spline_ob.resolution_u+1))
+    return segments
+
+
+def linear_spline_list(shape_ob):
+    '''
+    > shape_ob:     bezier shape object
+    < returns list of linear interpolated splinepoints
+    '''
+    return [interpolate_spline(spl) for spl in shape_ob.data.splines]
+
+
+
+
+
+def is_between(x, a, b):
+    '''
+    > x, a, b = point
+    < True if x lies between a and b
+    '''
+    cross = (x[1] - a[1]) * (b[0] - a[0]) - (x[0] - a[0]) * (b[1] - a[1])
+    if abs(cross) > PRECISION: return False
+    dot = (x[0] - a[0]) * (b[0] - a[0]) + (x[1] - a[1])*(b[1] - a[1])
+    if dot < 0 : return False
+    squaredlengthba = (b[0] - a[0])*(b[0] - a[0]) + (b[1] - a[1])*(b[1] - a[1])
+    if dot > squaredlengthba: return False
+
+    return True
+
+
+def ratio_to_segment(x, p1, p2, p3, p4, res):
+    '''
+    > x:            intersection point
+    > p1,p2,p3,p4:  cubic bezier control points
+    < ratio of x to length of the segment
+    '''
+    seg = interpolate_bezier(p1, p2, p3, p4, res+1)
+    seg_length = length = ratio = 0
+
+    for i in range (len(seg)-1):
+        seg_length += (seg[i+1] - seg[i]).length
+
+    for i in range (len(seg)-1):
+        if is_between(x, seg[i], seg[i+1]):
+            length += (x - seg[i].to_2d()).length
+            return length/seg_length
+        else:
+            length += (seg[i+1] - seg[i]).length
+
+
+def split_segment(t,p1,p2,p3,p4):
+    '''
+    > t:            ratio
+    > p1,p2,p3,p4:  cubic bezier control points
+    < two lists of 4 control points using de Casteljau's algorithm
+    '''
+    q1 = p1 + (p2-p1)*t
+    q2 = p2 + (p3-p2)*t
+    q3 = p3 + (p4-p3)*t
+
+    r1 = q1 + (q2-q1)*t
+    r2 = q2 + (q3-q2)*t
+    r3 = r1 + (r2-r1)*t
+
+    return ([p1,q1,r1,r3], [r3,r2,q3,p4])
+
+
+def chop(x, p1, p2, p3, p4, res):
+    '''
+    > x:            intersection point
+    > p1,p2,p3,p4:  cubic bezier control points
+    > res:          spline resolution
+    < both chopped segment's cubic bezier control points
+    '''
+
+    ratio = ratio_to_segment(x, p1, p2, p3, p4, res)
+
+    if ratio != None:
+        return split_segment(ratio, p1, p2, p3, p4)
+    else:
+        return None
+
+
+def main(context):
+
+    shape_ob = context.active_object
+    spline_ob = shape_ob.data.splines.active
+    spline_id = active_spline_id(shape_ob)
+
+    # gather all intersections of the active spline
+    spl_int = spline_X_shape(shape_ob, spline_id)
+    point_id = sel_point_id(shape_ob.data.splines[spline_id])
+
+    if len(point_id) > 1: return
+    else: point_id = point_id[0]
+
+    low = [x for x in spl_int if x[1] <  point_id]
+    high = spl_int[len(low):]
+
+    # case of cyclic spline
+    if spline_ob.use_cyclic_u:
+
+        if len(low) + len(high) <= 1:
+            print ("cyclic spline needs at least 2 intersections")
+            return
+
+        elif len(low) + len(high) > 1:
+            print ("breaking up cyclic spline")
+            if len(low) == 0:
+                low = high
+                npoints = high[-1][1] - high[0][1] + 2
+            elif len(high) == 0:
+                high = low
+                npoints = low[-1][1] - low[0][1] + 2
+            else:
+                npoints = len(spline_ob.bezier_points) - high[0][1] + low[-1][1] + 2
+
+            spline_ob_data = [[[bp.co, bp.handle_left_type, bp.handle_right_type, bp.handle_left, bp.handle_right] for bp in spline_ob.bezier_points], spline_ob.resolution_u, spline_ob.use_cyclic_u]
+
+            shape_ob.data.splines.new('BEZIER')
+            new_spl = shape_ob.data.splines[-1]
+            new_spl.bezier_points.add(npoints-1)
+
+            print (len(spline_ob_data[0]), len(new_spl.bezier_points), npoints)
+
+            for i, bp in enumerate(new_spl.bezier_points):
+                print((i+high[0][1])%npoints)
+                bp.co, bp.handle_left_type, bp.handle_right_type, bp.handle_left, bp.handle_right = spline_ob_data[0][(i+high[0][1])%(len(spline_ob_data[0]))]
+            new_spl.resolution_u = spline_ob_data[1]
+
+            s1, s2 = chop(low[-1][0],
+                  spline_ob.bezier_points[low[-1][1]].co,
+                  spline_ob.bezier_points[low[-1][1]].handle_right,
+                  spline_ob.bezier_points[(low[-1][1]+1)%(len(spline_ob_data[0]))].handle_left,
+                  spline_ob.bezier_points[(low[-1][1]+1)%(len(

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list