[Bf-blender-cvs] [5d403a6] gsoc2016-improved_extrusion: Merge remote-tracking branch 'origin/master' into gsoc2016-improved_extrusion
João Araújo
noreply at git.blender.org
Sat Jul 30 21:59:28 CEST 2016
Commit: 5d403a6dc3376932967398ac0f8a103e08badbee
Author: João Araújo
Date: Sat Jul 30 15:41:24 2016 +0100
Branches: gsoc2016-improved_extrusion
https://developer.blender.org/rB5d403a6dc3376932967398ac0f8a103e08badbee
Merge remote-tracking branch 'origin/master' into gsoc2016-improved_extrusion
===================================================================
===================================================================
diff --cc source/blender/editors/curve/editcurve.c
index 482ba72,e40dde2..571bf01
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@@ -6302,1567 -6302,3 +6302,1567 @@@ void CURVE_OT_match_texture_space(wmOpe
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+
+
+
+/******************** Extend curve operator ********************/
+
+static void get_selected_splines(ListBase* spline_list, ListBase *nubase, int *r_number_splines, bool return_cyclic)
+{
+ /* receives a list with all Bezier splines in a "curve" object
+ * returns the first spline of a linked list with all the selected splines,
+ * along with the number of selected splines
+ * if "return_cyclic" is false, it ignores cyclic splines */
+
+ Nurb *nu, *nu_copy;
+ BezTriple *bezt;
+ int handles;
+
+ for(nu=nubase->first; nu; nu = nu->next)
+ {
+ handles = nu->pntsu;
+ bezt = nu->bezt;
+ while (handles--)
+ { /* cycle through all the handles. see if any is selected */
+ if (BEZT_ISSEL_ANY(bezt) && (!(nu->flagu & CU_NURB_CYCLIC) || return_cyclic))
+ { /* this expression was deduced using truth tables */
+ *r_number_splines += 1;
+ nu_copy = BKE_nurb_duplicate(nu);
+ nu_copy->next = NULL;
+ nu_copy->prev = NULL;
+ BLI_addtail(spline_list, nu_copy);
+ break;
+ }
+ bezt++;
+ }
+ }
+}
+
+static ListBase *get_selected_handles(Nurb* nu, int *r_num_sel_handles)
+{
+ /* Takes in the first element of a linked list of nurbs
+ * and returns a ListBase with the BezTriple of the selected handles. */
+ BezTriple *bezt;
+ LinkData *link;
+ ListBase *sel_handles = (ListBase *)MEM_callocN(sizeof(ListBase), "get_selected_handles1");
+ int a;
+
+ *r_num_sel_handles = 0;
+ while (nu) {
+ a = nu->pntsu;
+ bezt = nu->bezt;
+ while (a--) {
+ if (BEZT_ISSEL_ANY(bezt)) {
+ link = MEM_callocN(sizeof(LinkData), "get_selected_handles2");
+ link->data = bezt;
+ BLI_addtail(sel_handles, link);
+ *r_num_sel_handles = *r_num_sel_handles + 1;
+ }
+ bezt++;
+ }
+ nu = nu->next;
+ }
+
+ return sel_handles;
+}
+
+static void get_selected_endpoints(Nurb* nu, BezTriple **r_handle_list)
+{
+ /* Takes in a nurb and returns an array with the selected endpoints BezTriple */
+ BezTriple *first_bezt, *last_bezt;
+ int a;
+ r_handle_list[0] = r_handle_list[1] = NULL;
+
+ a = nu->pntsu - 1;
+ first_bezt = last_bezt = nu->bezt;
+
+ while (a--) {
+ last_bezt++;
+ }
+
+ if (BEZT_ISSEL_ANY(first_bezt) && BEZT_ISSEL_ANY(last_bezt))
+ {
+ r_handle_list[0] = first_bezt;
+ r_handle_list[1] = last_bezt;
+ }
+ else if (BEZT_ISSEL_ANY(first_bezt))
+ {
+ r_handle_list[0] = first_bezt;
+ r_handle_list[1] = NULL;
+ }
+ else if (BEZT_ISSEL_ANY(last_bezt))
+ {
+ r_handle_list[0] = NULL;
+ r_handle_list[1] = last_bezt;
+ }
+}
+
+static void get_nurb_shape_bounds(Object *obedit, float r_bound_box[4])
+{
+ /* returns the coordinates of the XY-bounding box of obedit */
+ r_bound_box[0] = obedit->bb->vec[0][0]; /* min X */
+ r_bound_box[1] = obedit->bb->vec[4][0]; /* max X */
+ r_bound_box[2] = obedit->bb->vec[0][1]; /* min Y */
+ r_bound_box[3] = obedit->bb->vec[3][1]; /* max Y */
+}
+
+static void get_max_extent_2d(float p1[2], float p2[2], float bb[4], float r_result[2])
+{
+ /* TODO: Find out what this actually does */
+ if (fabsf(p1[0]-p2[0])) {
+ if (p1[0] < p2[0]) {
+ r_result[0] = bb[0];
+ r_result[1] = (p2[1]-p1[1])/(p2[0]-p1[0])*(bb[0]-p1[0])+p1[1];
+ }
+ else {
+ r_result[0] = bb[1];
+ r_result[1] = (p2[1]-p1[1])/(p2[0]-p1[0])*(bb[1]-p1[0])+p1[1];
+ }
+ }
+ else {
+ if (p1[1] < p2[1]) {
+ r_result[0] = (p2[0]-p1[0])/(p2[1]-p1[1])*(bb[2]-p1[1])+p1[0];
+ r_result[1] = bb[2];
+ }
+ else {
+ r_result[0] = (p2[0]-p1[0])/(p2[1]-p1[1])*(bb[3]-p1[1])+p1[0];
+ r_result[1] = bb[3];
+ }
+ }
+}
+
+static void nearest_point(float p[2], ListBase *p_list, float r_near[2], int *r_result)
+{
+ LinkData *link;
+ int p_list_size = BLI_listbase_count(p_list);
+ *r_result = 1;
+ /* return the point from p_list nearer to p */
+ if (p_list_size == 0) {
+ r_near = NULL;
+ *r_result = 0;
+ }
+ else if (p_list_size == 1) {
+ link = p_list->first;
+ copy_v2_v2(r_near, link->data);
+ }
+ else {
+ int pos = 0, i = 0;
+ float distance = len_v2v2(p, ((LinkData *)p_list->first)->data), smallest_distance = distance;
+ for (link = p_list->first; link; link = link->next) {
+ distance = len_v2v2(p, link->data);
+ if (distance <= smallest_distance) {
+ distance = smallest_distance;
+ copy_v2_v2(r_near, link->data);
+ pos = i;
+ }
+ i++;
+ }
+ }
+}
+
+static ListBase *interpolate_all_segments(Nurb *nu)
+{
+ /* return a listbase with all the points in the Bezier curve. Each element
+ * of the ListBase is a segment between two handles.
+ * If the cuve only has two handles, the final result is only on list
+ * Otherwise, there is an overlap between the last element of a list and
+ * the first of the next one */
+ int i = 0, dims = 3;
+ float *coord_array;
+ ListBase *pl = (ListBase *)MEM_callocN(sizeof(ListBase), "interpolate_all_segments1");
+ LinkData *link;
+
+ /* number of BezTriples */
+ int bezier_points = nu->pntsu;
+
+ while (i < bezier_points-1+nu->flagu) {
+ coord_array = MEM_callocN(dims * (nu->resolu + 1) * sizeof(float), "interpolate_all_segments2");
+ link = MEM_callocN(sizeof(LinkData), "interpolate_all_segments3");
+ link->data = coord_array;
+ for (int j = 0; j < dims; j++) {
+ BKE_curve_forward_diff_bezier(nu->bezt[i%bezier_points].vec[1][j],
+ 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, sizeof(float) * dims);
+ }
+ BLI_addtail(pl, link);
+ i++;
+ }
+
+ return pl;
+}
+
+static void linear_spline_list(ListBase *nubase, ListBase *spline_list)
+{
+ /* return a list with all the points of a curve object */
+ LinkData *link;
+ Nurb *nu;
+
+ for (nu=nubase->first; nu; nu=nu->next) {
+ link = MEM_callocN(sizeof(LinkData), "linearspllist1");
+ link->data = interpolate_all_segments(nu);
+ BLI_addtail(spline_list, link);
+ }
+}
+
+static void get_intersections(ListBase* il, 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 = {NULL}, *points_list;
+ LinkData *intersection, *link, *spl;
+ float *coord_array, *vi, p3[2], p4[2];
+ Nurb *nu = nubase->first;
+ int dims = 3, result;
+ const float PRECISION = 1e-05;
+
+ linear_spline_list(nubase, &spline_list); /* all the points in a curve object */
+ for (spl=spline_list.first; spl; spl=spl->next) { /* selecting the points of a given spline */
+ 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; 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) {
+ /* a hit, lets add it. */
+ intersection = MEM_callocN(sizeof(LinkData), "get_intersections4");
+ intersection->data = vi;
+ BLI_addtail(il, intersection);
+ }
+ else {
+ /* not going to add, so free the memory we reserved, not used. */
+ MEM_freeN(vi);
+ }
+ }
+ MEM_freeN(link->data); /* commenting either does not free the memory */
+ MEM_freeN(coord_array); /* running both gives an error, but seems to free the memory */
+ }
+ BLI_freelistN(spl->data);
+ BLI_freelistN(points_list);
+ MEM_freeN(points_list);
+ }
+ BLI_freelistN(&spline_list);
+ MEM_freeN(&spline_list);
+}
+
+static int extend_curve_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ Nurb *first_spline, *second_spline;
+ Curve *cu = obedit->data;
+ Nurb *nu;
+ EditNurb *editnurb = cu->editnurb;
+ ListBase spline_list = {NULL};
+ ListBase intersections_list = {NULL};
+ ListBase *nubase = object_editcurve_get(obedit);
+ BezTriple **selected_endpoints = NULL, **first_selected_endpoints = NULL, **second_selected_endpoints = NULL, *bezt;
+ int n_selected_splines = 0, result = 0, a = 0;
+ float p1[3], p2[3] = {0.0, 0.0, 0.0}, p1_handle[3], bound_box[4], p1_extend[2];
+
+ for (nu = nubase->first; nu; nu = nu->next)
+ {
+ if (!(nu->type & CU_BEZIER))
+ {
+ BKE_report(op->reports, RPT_ERROR, "Only Bezier curves can be extended");
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ get_selected_splines(&spline_list, nubase, &n_selected_splines, false);
+
+ /* the user can only select one or two splines */
+ if ((n_selected_splines == 0 || n_selected_splines > 2)) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot extend current selection");
+ return OPERATOR_CANCELLED;
+ }
+
+ first_spline = (Nurb *)spline_list.first;
+ second_spline = (Nurb *)spline_list.last;
+
+ if (n_selected_splines == 1) { /* one spline selected */
+ selected_endpoints = MEM_callocN(2 * sizeof(BezTriple*), "extendcurve1");
+ get_selected_endpoints(first_spline, selected_endpoints);
+
+ if (selected_endpoints[0] && selected_endpoints[1]) { /* both endpoints are selected */
+ result = isect_line_line_v3(selected_endpoints[0]->vec[1], selected_endpoints[0]->vec[0],
+ selected_endpoints[1]->vec[1], selected_endpoints[1]->vec[2],
+ p1, p2); /* result serves to check the existence of the intersection;
+ * the intersection point is on variables p1 and p2 */
+ }
+ else if (selected_endpoints[0] || selected_endpoints[1]) { /* only one endpoint selected */
+ if (selected_endpoints[0])
+ {
+ copy_v3_v3(p1, selected_endpoints[0]->vec[1]);
+ copy_v3_v3(p1_handle
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list