forked from bartvdbraak/blender
Curve Fitting: add high-quality flag
When this flag is set - even when the curve error is under the threshold, keep attempting a better fit. Enable this for freehand drawing, since it gives nicer results and isn't noticeably slower.
This commit is contained in:
parent
b0985b393c
commit
abb9d0b0ad
6
extern/curve_fit_nd/curve_fit_nd.h
vendored
6
extern/curve_fit_nd/curve_fit_nd.h
vendored
@ -60,6 +60,7 @@ int curve_fit_cubic_to_points_db(
|
|||||||
const unsigned int points_len,
|
const unsigned int points_len,
|
||||||
const unsigned int dims,
|
const unsigned int dims,
|
||||||
const double error_threshold,
|
const double error_threshold,
|
||||||
|
const unsigned int calc_flag,
|
||||||
const unsigned int *corners,
|
const unsigned int *corners,
|
||||||
unsigned int corners_len,
|
unsigned int corners_len,
|
||||||
|
|
||||||
@ -72,6 +73,7 @@ int curve_fit_cubic_to_points_fl(
|
|||||||
const unsigned int points_len,
|
const unsigned int points_len,
|
||||||
const unsigned int dims,
|
const unsigned int dims,
|
||||||
const float error_threshold,
|
const float error_threshold,
|
||||||
|
const unsigned int calc_flag,
|
||||||
const unsigned int *corners,
|
const unsigned int *corners,
|
||||||
const unsigned int corners_len,
|
const unsigned int corners_len,
|
||||||
|
|
||||||
@ -117,6 +119,10 @@ int curve_fit_cubic_to_points_single_fl(
|
|||||||
float r_handle_r[],
|
float r_handle_r[],
|
||||||
float *r_error_sq);
|
float *r_error_sq);
|
||||||
|
|
||||||
|
enum {
|
||||||
|
CURVE_FIT_CALC_HIGH_QUALIY = (1 << 0),
|
||||||
|
};
|
||||||
|
|
||||||
/* curve_fit_corners_detect.c */
|
/* curve_fit_corners_detect.c */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
53
extern/curve_fit_nd/intern/curve_fit_cubic.c
vendored
53
extern/curve_fit_nd/intern/curve_fit_cubic.c
vendored
@ -1086,11 +1086,7 @@ static bool fit_cubic_to_points(
|
|||||||
*r_error_max_sq = error_max_sq;
|
*r_error_max_sq = error_max_sq;
|
||||||
*r_split_index = split_index;
|
*r_split_index = split_index;
|
||||||
|
|
||||||
if (error_max_sq < error_threshold_sq) {
|
if (!(error_max_sq < error_threshold_sq)) {
|
||||||
free(u);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
cubic_copy(cubic_test, r_cubic, dims);
|
cubic_copy(cubic_test, r_cubic, dims);
|
||||||
|
|
||||||
/* If error not too large, try some reparameterization and iteration */
|
/* If error not too large, try some reparameterization and iteration */
|
||||||
@ -1108,25 +1104,28 @@ static bool fit_cubic_to_points(
|
|||||||
points_offset_coords_length,
|
points_offset_coords_length,
|
||||||
#endif
|
#endif
|
||||||
u_prime, tan_l, tan_r, dims, cubic_test);
|
u_prime, tan_l, tan_r, dims, cubic_test);
|
||||||
error_max_sq = cubic_calc_error(
|
|
||||||
|
const double error_max_sq_test = cubic_calc_error(
|
||||||
cubic_test, points_offset, points_offset_len, u_prime, dims,
|
cubic_test, points_offset, points_offset_len, u_prime, dims,
|
||||||
&split_index);
|
&split_index);
|
||||||
|
|
||||||
if (error_max_sq < error_threshold_sq) {
|
if (error_max_sq > error_max_sq_test) {
|
||||||
free(u_prime);
|
error_max_sq = error_max_sq_test;
|
||||||
free(u);
|
|
||||||
|
|
||||||
cubic_copy(r_cubic, cubic_test, dims);
|
|
||||||
*r_error_max_sq = error_max_sq;
|
|
||||||
*r_split_index = split_index;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (error_max_sq < *r_error_max_sq) {
|
|
||||||
cubic_copy(r_cubic, cubic_test, dims);
|
cubic_copy(r_cubic, cubic_test, dims);
|
||||||
*r_error_max_sq = error_max_sq;
|
*r_error_max_sq = error_max_sq;
|
||||||
*r_split_index = split_index;
|
*r_split_index = split_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(error_max_sq < error_threshold_sq)) {
|
||||||
|
/* continue */
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert((error_max_sq < error_threshold_sq));
|
||||||
|
free(u_prime);
|
||||||
|
free(u);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
SWAP(double *, u, u_prime);
|
SWAP(double *, u, u_prime);
|
||||||
}
|
}
|
||||||
free(u_prime);
|
free(u_prime);
|
||||||
@ -1134,6 +1133,10 @@ static bool fit_cubic_to_points(
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
free(u);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fit_cubic_to_points_recursive(
|
static void fit_cubic_to_points_recursive(
|
||||||
@ -1145,6 +1148,7 @@ static void fit_cubic_to_points_recursive(
|
|||||||
const double tan_l[],
|
const double tan_l[],
|
||||||
const double tan_r[],
|
const double tan_r[],
|
||||||
const double error_threshold_sq,
|
const double error_threshold_sq,
|
||||||
|
const uint calc_flag,
|
||||||
const uint dims,
|
const uint dims,
|
||||||
/* fill in the list */
|
/* fill in the list */
|
||||||
CubicList *clist)
|
CubicList *clist)
|
||||||
@ -1158,8 +1162,11 @@ static void fit_cubic_to_points_recursive(
|
|||||||
#ifdef USE_LENGTH_CACHE
|
#ifdef USE_LENGTH_CACHE
|
||||||
points_length_cache,
|
points_length_cache,
|
||||||
#endif
|
#endif
|
||||||
tan_l, tan_r, error_threshold_sq, dims,
|
tan_l, tan_r,
|
||||||
cubic, &error_max_sq, &split_index))
|
(calc_flag & CURVE_FIT_CALC_HIGH_QUALIY) ? DBL_EPSILON : error_threshold_sq,
|
||||||
|
dims,
|
||||||
|
cubic, &error_max_sq, &split_index) ||
|
||||||
|
(error_max_sq < error_threshold_sq))
|
||||||
{
|
{
|
||||||
cubic_list_prepend(clist, cubic);
|
cubic_list_prepend(clist, cubic);
|
||||||
return;
|
return;
|
||||||
@ -1211,13 +1218,13 @@ static void fit_cubic_to_points_recursive(
|
|||||||
#ifdef USE_LENGTH_CACHE
|
#ifdef USE_LENGTH_CACHE
|
||||||
points_length_cache,
|
points_length_cache,
|
||||||
#endif
|
#endif
|
||||||
tan_l, tan_center, error_threshold_sq, dims, clist);
|
tan_l, tan_center, error_threshold_sq, calc_flag, dims, clist);
|
||||||
fit_cubic_to_points_recursive(
|
fit_cubic_to_points_recursive(
|
||||||
&points_offset[split_index * dims], points_offset_len - split_index,
|
&points_offset[split_index * dims], points_offset_len - split_index,
|
||||||
#ifdef USE_LENGTH_CACHE
|
#ifdef USE_LENGTH_CACHE
|
||||||
points_length_cache + split_index,
|
points_length_cache + split_index,
|
||||||
#endif
|
#endif
|
||||||
tan_center, tan_r, error_threshold_sq, dims, clist);
|
tan_center, tan_r, error_threshold_sq, calc_flag, dims, clist);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1240,6 +1247,7 @@ int curve_fit_cubic_to_points_db(
|
|||||||
const uint points_len,
|
const uint points_len,
|
||||||
const uint dims,
|
const uint dims,
|
||||||
const double error_threshold,
|
const double error_threshold,
|
||||||
|
const uint calc_flag,
|
||||||
const uint *corners,
|
const uint *corners,
|
||||||
uint corners_len,
|
uint corners_len,
|
||||||
|
|
||||||
@ -1315,7 +1323,7 @@ int curve_fit_cubic_to_points_db(
|
|||||||
#ifdef USE_LENGTH_CACHE
|
#ifdef USE_LENGTH_CACHE
|
||||||
points_length_cache,
|
points_length_cache,
|
||||||
#endif
|
#endif
|
||||||
tan_l, tan_r, error_threshold_sq, dims, &clist);
|
tan_l, tan_r, error_threshold_sq, calc_flag, dims, &clist);
|
||||||
}
|
}
|
||||||
else if (points_len == 1) {
|
else if (points_len == 1) {
|
||||||
assert(points_offset_len == 1);
|
assert(points_offset_len == 1);
|
||||||
@ -1382,6 +1390,7 @@ int curve_fit_cubic_to_points_fl(
|
|||||||
const uint points_len,
|
const uint points_len,
|
||||||
const uint dims,
|
const uint dims,
|
||||||
const float error_threshold,
|
const float error_threshold,
|
||||||
|
const uint calc_flag,
|
||||||
const uint *corners,
|
const uint *corners,
|
||||||
const uint corners_len,
|
const uint corners_len,
|
||||||
|
|
||||||
@ -1399,7 +1408,7 @@ int curve_fit_cubic_to_points_fl(
|
|||||||
uint cubic_array_len = 0;
|
uint cubic_array_len = 0;
|
||||||
|
|
||||||
int result = curve_fit_cubic_to_points_db(
|
int result = curve_fit_cubic_to_points_db(
|
||||||
points_db, points_len, dims, error_threshold, corners, corners_len,
|
points_db, points_len, dims, error_threshold, calc_flag, corners, corners_len,
|
||||||
&cubic_array_db, &cubic_array_len,
|
&cubic_array_db, &cubic_array_len,
|
||||||
r_cubic_orig_index,
|
r_cubic_orig_index,
|
||||||
r_corner_index_array, r_corner_index_len);
|
r_corner_index_array, r_corner_index_len);
|
||||||
|
@ -911,7 +911,7 @@ static int curve_draw_exec(bContext *C, wmOperator *op)
|
|||||||
unsigned int corners_index_len = 0;
|
unsigned int corners_index_len = 0;
|
||||||
|
|
||||||
const int result = curve_fit_cubic_to_points_fl(
|
const int result = curve_fit_cubic_to_points_fl(
|
||||||
coords, stroke_len, dims, error_threshold,
|
coords, stroke_len, dims, error_threshold, CURVE_FIT_CALC_HIGH_QUALIY,
|
||||||
corners, corners_len,
|
corners, corners_len,
|
||||||
&cubic_spline, &cubic_spline_len,
|
&cubic_spline, &cubic_spline_len,
|
||||||
NULL,
|
NULL,
|
||||||
|
Loading…
Reference in New Issue
Block a user