[Bf-blender-cvs] [1aaebb2] temp-curve-draw: Corner handle calculation could fail (for larger curves especially)

Campbell Barton noreply at git.blender.org
Wed Apr 13 21:20:06 CEST 2016


Commit: 1aaebb22a3d8cb0eb97572c2039417f0e8c6ba59
Author: Campbell Barton
Date:   Thu Apr 14 04:27:36 2016 +1000
Branches: temp-curve-draw
https://developer.blender.org/rB1aaebb22a3d8cb0eb97572c2039417f0e8c6ba59

Corner handle calculation could fail (for larger curves especially)

Replace this with an optional return array of corner indices on final output curve.

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

M	extern/curve_fit_nd/curve_fit_nd.h
M	extern/curve_fit_nd/intern/curve_fit_corners_detect.c
M	extern/curve_fit_nd/intern/curve_fit_cubic.c
M	source/blender/editors/curve/editcurve_paint.c

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

diff --git a/extern/curve_fit_nd/curve_fit_nd.h b/extern/curve_fit_nd/curve_fit_nd.h
index 3ee39c7..3e39ac1 100644
--- a/extern/curve_fit_nd/curve_fit_nd.h
+++ b/extern/curve_fit_nd/curve_fit_nd.h
@@ -36,37 +36,66 @@
 /* curve_fit_cubic.c */
 
 /**
- * Takes a flat array of points:
- * `points[dims]`
+ * Takes a flat array of points and evalues that to calculate a bezier spline.
  *
- * And calculates cubic (bezier) splines:
- * `r_cubic_array[r_cubic_array_len][3][dims]`.
+ * \param points, points_len: The array of points to calculate a cubics from.
+ * \param dims: The number of dimensions for for each element in \a points.
+ * \param error_threshold: the error threshold to allow for,
+ * the curve will be within this distance from \a points.
+ * \param corners, corners_len: indices for points which will not have aligned tangents (optional).
+ * This can use the output of #spline_fit_corners_detect_db which has been included
+ * to evaluate a line to detect corner indices.
  *
- * Where each point has 0 and 2 for the tangents and the middle index 1 for the knot.
+ * \param r_cubic_array, r_cubic_array_len: Resulting array of tangents and knots, formatted as follows:
+ * ``r_cubic_array[r_cubic_array_len][3][dims]``,
+ * where each point has 0 and 2 for the tangents and the middle index 1 for the knot.
+ * The size of the *flat* array will be ``r_cubic_array_len * 3 * dims``.
+ * \param r_corner_index_array, r_corner_index_len: Corner indices in in \a r_cubic_array (optional).
+ * This allows you to access corners on the resulting curve.
+ *
+ * \returns zero on success, nonzero is reserved for error values.
  */
 int spline_fit_cubic_to_points_db(
-        const double *points,
-        const unsigned int points_len,
-        const unsigned int    dims,
-        const double  error,
-        const unsigned int   *corners,
-        const unsigned int    corners_len,
+        const double       *points,
+        const unsigned int  points_len,
+        const unsigned int  dims,
+        const double        error_threshold,
+        const unsigned int *corners,
+        const unsigned int  corners_len,
 
-        double **r_cubic_array, unsigned int *r_cubic_array_len);
+        double **r_cubic_array, unsigned int *r_cubic_array_len,
+        unsigned int **r_corner_index_array, unsigned int *r_corner_index_len);
 
 int spline_fit_cubic_to_points_fl(
-        const float  *points,
-        const unsigned int    points_len,
-        const unsigned int    dims,
-        const float   error,
-        const unsigned int   *corners,
-        const unsigned int    corners_len,
+        const float        *points,
+        const unsigned int  points_len,
+        const unsigned int  dims,
+        const float         error_threshold,
+        const unsigned int *corners,
+        const unsigned int  corners_len,
 
-        float **r_cubic_array, unsigned int *r_cubic_array_len);
+        float **r_cubic_array, unsigned int *r_cubic_array_len,
+        unsigned int **r_corners_index_array, unsigned int *r_corners_index_len);
 
 
 /* curve_fit_corners_detect.c */
 
+/**
+ * A helper function that takes a line and outputs its corner indices.
+ *
+ * \param points, points_len: Curve to evaluate.
+ * \param dims: The number of dimensions for for each element in \a points.
+ * \param radius_min: Corners on the curve between points below this radius are ignored.
+ * \param radius_max: Corners on the curve above this radius are ignored.
+ * \param samples_max: Prevent testing corners beyond this many points
+ * (prevents a large radius taking excessive time to compute).
+ * \param angle_threshold: Angles above this value are considered corners
+ * (higher value for fewer corners).
+ *
+ * \param r_corners, r_corners_len: Resulting array of corners.
+ *
+ * \returns zero on success, nonzero is reserved for error values.
+ */
 int spline_fit_corners_detect_db(
         const double      *points,
         const unsigned int points_len,
@@ -74,7 +103,7 @@ int spline_fit_corners_detect_db(
         const double       radius_min,
         const double       radius_max,
         const unsigned int samples_max,
-        const double       angle_limit,
+        const double       angle_threshold,
 
         unsigned int **r_corners,
         unsigned int  *r_corners_len);
@@ -86,7 +115,7 @@ int spline_fit_corners_detect_fl(
         const float        radius_min,
         const float        radius_max,
         const unsigned int samples_max,
-        const float        angle_limit,
+        const float        angle_threshold,
 
         unsigned int **r_corners,
         unsigned int  *r_corners_len);
diff --git a/extern/curve_fit_nd/intern/curve_fit_corners_detect.c b/extern/curve_fit_nd/intern/curve_fit_corners_detect.c
index 7cdb3c0..72a063b 100644
--- a/extern/curve_fit_nd/intern/curve_fit_corners_detect.c
+++ b/extern/curve_fit_nd/intern/curve_fit_corners_detect.c
@@ -235,8 +235,8 @@ static double point_corner_angle(
         const uint i,
         const double radius_mid,
         const double radius_max,
-        const double angle_limit,
-        const double angle_limit_cos,
+        const double angle_threshold,
+        const double angle_threshold_cos,
         /* prevent locking up when for example `radius_min` is very large
          * (possibly larger then the curve).
          * In this case we would end up checking every point from every other point,
@@ -247,7 +247,7 @@ static double point_corner_angle(
 
         const uint dims)
 {
-	assert(angle_limit_cos == cos(angle_limit));
+	assert(angle_threshold_cos == cos(angle_threshold));
 
 	const double *p = &points[i * dims];
 
@@ -274,8 +274,8 @@ static double point_corner_angle(
 
 		/* compare as cos and flip direction */
 
-		/* if (angle_mid > angle_limit) { */
-		if (angle_mid_cos < angle_limit_cos) {
+		/* if (angle_mid > angle_threshold) { */
+		if (angle_mid_cos < angle_threshold_cos) {
 #ifdef USE_VLA
 			double p_max_prev[dims];
 			double p_max_next[dims];
@@ -297,7 +297,7 @@ static double point_corner_angle(
 			{
 				const double angle_max = angle_vnvnvn(p_max_prev, p, p_max_next, dims) / 2.0;
 				const double angle_diff = acos(angle_mid_cos) - angle_max;
-				if (angle_diff > angle_limit) {
+				if (angle_diff > angle_threshold) {
 					return angle_diff;
 				}
 			}
@@ -315,12 +315,12 @@ int spline_fit_corners_detect_db(
         const double radius_min,  /* ignore values below this */
         const double radius_max,  /* ignore values above this */
         const uint samples_max,
-        const double angle_limit,
+        const double angle_threshold,
 
         uint **r_corners,
         uint  *r_corners_len)
 {
-	const double angle_limit_cos = cos(angle_limit);
+	const double angle_threshold_cos = cos(angle_threshold);
 	uint corners_len = 0;
 
 	/* Use the difference in angle between the mid-max radii
@@ -331,11 +331,14 @@ int spline_fit_corners_detect_db(
 	double *points_angle = malloc(sizeof(double) * points_len);
 	points_angle[0] = 0.0;
 
+	*r_corners = NULL;
+	*r_corners_len = 0;
+
 	for (uint i = 0; i < points_len; i++) {
 		points_angle[i] =  point_corner_angle(
 		        points, points_len, i,
 		        radius_mid, radius_max,
-		        angle_limit, angle_limit_cos,
+		        angle_threshold, angle_threshold_cos,
 		        samples_max,
 		        dims);
 
@@ -346,7 +349,7 @@ int spline_fit_corners_detect_db(
 
 	if (corners_len == 0) {
 		free(points_angle);
-		return false;
+		return 0;
 	}
 
 	/* Clean angle limits!
@@ -415,7 +418,7 @@ int spline_fit_corners_detect_db(
 	*r_corners = corners;
 	*r_corners_len = corners_len;
 
-	return 1;
+	return 0;
 }
 
 int spline_fit_corners_detect_fl(
@@ -425,7 +428,7 @@ int spline_fit_corners_detect_fl(
         const float radius_min,  /* ignore values below this */
         const float radius_max,  /* ignore values above this */
         const uint samples_max,
-        const float angle_limit,
+        const float angle_threshold,
 
         uint **r_corners,
         uint  *r_corners_len)
@@ -437,15 +440,15 @@ int spline_fit_corners_detect_fl(
 		points_db[i] = (double)points[i];
 	}
 
-	int ok = spline_fit_corners_detect_db(
+	int result = spline_fit_corners_detect_db(
 	        points_db, points_len,
 	        dims,
 	        radius_min, radius_max,
 	        samples_max,
-	        angle_limit,
+	        angle_threshold,
 	        r_corners, r_corners_len);
 
 	free(points_db);
 
-	return ok;
+	return result;
 }
diff --git a/extern/curve_fit_nd/intern/curve_fit_cubic.c b/extern/curve_fit_nd/intern/curve_fit_cubic.c
index 54cb838..2989bb6 100644
--- a/extern/curve_fit_nd/intern/curve_fit_cubic.c
+++ b/extern/curve_fit_nd/intern/curve_fit_cubic.c
@@ -801,7 +801,8 @@ int spline_fit_cubic_to_points_db(
         const uint   *corners,
         uint          corners_len,
 
-        double **r_cubic_array, uint *r_cubic_array_len)
+        double **r_cubic_array, uint *r_cubic_array_len,
+        uint **r_corner_index_array, uint *r_corner_index_len)
 {
 	uint corners_buf[2];
 	if (corners == NULL) {
@@ -828,6 +829,13 @@ int spline_fit_cubic_to_points_db(
 	uint    points_length_cache_len_alloc = 0;
 #endif
 
+	uint *corner_index_array = NULL;
+	uint  corner_index = 0;
+	if (r_corner_index_array && (corners != corners_buf)) {
+		corner_index_array = malloc(sizeof(uint) * corners_len);
+		corner_index_array[corner_index++] = corners[0];
+	}
+
 	for (uint i = 1; i < corners_len; i++) {
 		const uint points_offset_len = corners[i] - corners[i - 1] + 1;
 		const uint first_point = corners[i - 1];
@@ -874,6 +882,10 @@ int spline_fit_cubic_to_points_db(
 			cubic_init(cubic, pt, pt, pt, pt, dims);
 			cubic_list_prepend(&clist, cubic);
 		}
+
+		if (corner_index_array) {
+			corner_index_array[corner_index++] = clist.len;
+		}
 	}
 
 #ifdef USE_LENGTH_CACHE
@@ -888,6 +900,13 @@ int spline_fit_cubic_to_points_db(
 
 	cubic_list_clear(&clist);
 
+
+	if (corner_index_array) {
+		assert(corner_index == corners_len);
+		*r_corner_index_array = corner_index_array;
+		*r_corner_index_len = corner_index;
+	}
+
 	return 0;
 }
 
@@ -902,7 +921,8 @@ int spline_fit_cubic_to_points_fl(
         const uint   *corners,
         const uint    co

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list