[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