27#define PROF_TABLE_MAX 512
93 profile->
table =
nullptr;
113 const float delta[2])
115 short handle_type = (handle_1) ? point->
h1 : point->
h2;
116 float *handle_location = (handle_1) ? &point->
h1_loc[0] : &point->
h2_loc[0];
118 float start_position[2];
127 handle_location[0] += delta ? delta[0] : 0.0f;
128 handle_location[1] += delta ? delta[1] : 0.0f;
130 handle_location[0] = 0.125f *
roundf(8.0f * handle_location[0]);
131 handle_location[1] = 0.125f *
roundf(8.0f * handle_location[1]);
136 short other_handle_type = (handle_1) ? point->
h2 : point->
h1;
137 if (other_handle_type ==
HD_ALIGN) {
138 float *other_handle_location = (handle_1) ? &point->
h2_loc[0] : &point->
h1_loc[0];
139 other_handle_location[0] = 2.0f * point->
x - handle_location[0];
140 other_handle_location[1] = 2.0f * point->
y - handle_location[1];
144 if (!
equals_v2v2(handle_location, start_position)) {
153 const float delta[2])
160 if (point == profile->
path) {
163 float origx = point->
x;
164 float origy = point->
y;
166 point->
x += delta[0];
167 point->
y += delta[1];
169 point->
x = 0.125f *
roundf(8.0f * point->
x);
170 point->
y = 0.125f *
roundf(8.0f * point->
y);
183 point->
h1_loc[0] += point->
x - origx;
184 point->
h1_loc[1] += point->
y - origy;
187 point->
h2_loc[0] += point->
x - origx;
188 point->
h2_loc[1] += point->
y - origy;
191 if (point->
x != origx || point->
y != origy) {
205 if (!(point > profile->
path && point < profile->path + profile->
path_len)) {
212 int i_delete = int(point - profile->
path);
217 memcpy(new_path + i_delete,
218 profile->
path + i_delete + 1,
222 profile->
path = new_path;
237 new_path[0] = profile->
path[0];
238 for (; i_old < profile->
path_len - 1; i_old++) {
240 new_path[i_new] = profile->
path[i_old];
247 new_path[i_new] = profile->
path[i_old];
250 profile->
path = new_path;
268 const float new_loc[2] = {
x,
y};
279 const float loc1[2] = {profile->
path[
i].
x, profile->
path[
i].
y};
280 const float loc2[2] = {profile->
path[
i + 1].
x, profile->
path[
i + 1].
y};
294 for (
int i_new = 0, i_old = 0; i_new < profile->
path_len; i_new++) {
295 if (i_new != i_insert) {
297 new_path[i_new] = profile->
path[i_old];
304 char new_handle_type = (new_path[i_new - 1].
h2 ==
HD_VECT &&
309 new_pt = &new_path[i_new];
317 profile->
path = new_path;
353 int i_reversed = profile->
path_len -
i - 1;
356 new_path[i_reversed].
profile = profile;
371 profile->
path = new_path;
383 for (
int i = 1;
i < n - 2;
i++) {
384 const float x = 1.0f - (0.5f * (1.0f -
cosf(
float(
i /
float(n - 3)) *
M_PI_2)));
385 const float y = 0.5f + 0.5f *
sinf(
float((
i /
float(n - 3)) *
M_PI_2));
407 float n_steps_x = (n % 2 == 0) ? n : (n - 1);
408 float n_steps_y = (n % 2 == 0) ? (n - 2) : (n - 1);
410 for (
int i = 0;
i < n;
i++) {
411 int step_x = (
i + 1) / 2;
413 const float x = 1.0f - (
float(2 * step_x) / n_steps_x);
414 const float y =
float(2 * step_y) / n_steps_y;
512 profile->
table =
nullptr;
524 const int resolution = 16;
551 float *point_loc = &point->
x;
554 const float *prev_loc, *next_loc;
555 if (prev ==
nullptr) {
557 pt[0] = 2.0f * point_loc[0] - next_loc[0];
558 pt[1] = 2.0f * point_loc[1] - next_loc[1];
565 if (
next ==
nullptr) {
567 pt[0] = 2.0f * point_loc[0] - prev_loc[0];
568 pt[1] = 2.0f * point_loc[1] - prev_loc[1];
575 float dvec_a[2], dvec_b[2];
579 float len_a =
len_v2(dvec_a);
580 float len_b =
len_v2(dvec_b);
590 tvec[0] = dvec_b[0] / len_b + dvec_a[0] / len_a;
591 tvec[1] = dvec_b[1] / len_b + dvec_a[1] / len_a;
617 for (
int i = 1;
i < path_len - 1;
i++) {
632 float start_handle_direction[2], end_handle_direction[2];
634 sub_v2_v2v2(start_handle_direction, path[i_edge].h2_loc, &path[i_edge].
x);
636 sub_v2_v2v2(end_handle_direction, &path[i_edge + 1].
x, path[i_edge + 1].h1_loc);
638 return angle_v2v2(start_handle_direction, end_handle_direction);
679 bool sample_straight_edges,
686 int totedges = totpoints - 1;
692 for (
int i = 0;
i < totedges;
i++) {
703 if (n_segments >= totedges) {
704 if (sample_straight_edges) {
707 int n_common = n_segments / totedges;
708 n_left = n_segments % totedges;
713 for (
int i = 0;
i < totedges;
i++) {
714 n_samples[
i] = n_common;
721 int n_curved_edges = 0;
722 for (
int i = 0;
i < totedges;
i++) {
728 n_curved_edges = (n_curved_edges == 0) ? totedges : n_curved_edges;
731 n_left = n_segments - (totedges - n_curved_edges);
732 int n_common = n_left / n_curved_edges;
734 for (
int i = 0;
i < totedges;
i++) {
738 n_samples[
i] += n_common;
747 n_left -= n_common * n_curved_edges;
756 for (
int i = 0;
i < n_left;
i++) {
766 for (
int i_sample = 0,
i = 0;
i < totedges;
i++) {
767 if (n_samples[
i] > 0) {
769 r_samples[i_sample].
h1 = path[
i].
h1;
770 r_samples[i_sample].
h2 = path[
i].
h2;
772 for (
int j = i_sample + 1; j < i_sample + n_samples[
i]; j++) {
773 r_samples[j].
flag = 0;
782 path[
i + 1].h1_loc[0],
784 &r_samples[i_sample].
x,
789 path[
i + 1].h1_loc[1],
791 &r_samples[i_sample].
y,
795 i_sample += n_samples[
i];
813 profile->
path[0].
x = 1.0f;
814 profile->
path[0].
y = 0.0f;
816 profile->
path[1].
x = 1.0f;
817 profile->
path[1].
y = 1.0f;
854 float total_length = 0;
874 const float segment_length = total_length / n_segments;
876 float distance_to_previous_table_point = 0.0f;
880 r_samples[0].
x = profile->
table[0].
x;
881 r_samples[0].
y = profile->
table[0].
y;
884 float segment_left = segment_length;
885 for (
int i = 1;
i < n_segments;
i++) {
887 while (distance_to_next_table_point < segment_left) {
888 segment_left -= distance_to_next_table_point;
891 distance_to_previous_table_point = 0.0f;
894 float factor = (distance_to_previous_table_point + segment_left) /
895 (distance_to_previous_table_point + distance_to_next_table_point);
899#ifdef DEBUG_CURVEPROFILE_EVALUATE
900 printf(
"segment_left: %.3f\n", segment_left);
901 printf(
"i_table: %d\n", i_table);
902 printf(
"distance_to_previous_table_point: %.3f\n", distance_to_previous_table_point);
903 printf(
"distance_to_next_table_point: %.3f\n", distance_to_next_table_point);
904 printf(
"Interpolating with factor %.3f from (%.3f, %.3f) to (%.3f, %.3f)\n\n",
906 profile->
table[i_table].
x,
907 profile->
table[i_table].
y,
908 profile->
table[i_table + 1].
x,
909 profile->
table[i_table + 1].
y);
913 distance_to_next_table_point -= segment_left;
914 distance_to_previous_table_point += segment_left;
915 segment_left = segment_length;
934 new_table[n_samples - 1].
x = 0.0f;
935 new_table[n_samples - 1].
y = 1.0f;
938 profile->
table = new_table;
948 if (n_samples <= 0) {
1022 float length_portion,
1027 const float requested_length = length_portion * total_length;
1031 float length_traveled = 0.0f;
1032 while (length_traveled < requested_length) {
1038 if (length_traveled + new_length >= requested_length) {
1041 length_traveled += new_length;
1048 float lerp_factor = (requested_length - length_traveled) / distance_to_next_point;
1050#ifdef DEBUG_CURVEPROFILE_EVALUATE
1051 printf(
"CURVEPROFILE EVALUATE\n");
1052 printf(
" length portion input: %f\n",
double(length_portion));
1053 printf(
" requested path length: %f\n",
double(requested_length));
1054 printf(
" distance to next point: %f\n",
double(distance_to_next_point));
1055 printf(
" length traveled: %f\n",
double(length_traveled));
1056 printf(
" lerp-factor: %f\n",
double(lerp_factor));
1057 printf(
" ith point (%f, %f)\n",
double(profile->
path[
i].
x),
double(profile->
path[
i].
y));
1058 printf(
" next point(%f, %f)\n",
double(profile->
path[
i + 1].
x),
double(profile->
path[
i + 1].
y));
void BKE_curve_forward_diff_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride)
@ PROF_UPDATE_REMOVE_DOUBLES
MINLINE float max_ff(float a, float b)
MINLINE float pow2f(float x)
MINLINE float clamp_f(float value, float min, float max)
MINLINE float min_ff(float a, float b)
MINLINE float interpf(float target, float origin, float t)
float dist_squared_to_line_segment_v2(const float p[2], const float l1[2], const float l2[2])
MINLINE float len_v2(const float v[2]) ATTR_WARN_UNUSED_RESULT
MINLINE float len_squared_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void madd_v2_v2v2fl(float r[2], const float a[2], const float b[2], float f)
float angle_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE float len_v2v2(const float v1[2], const float v2[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE bool equals_v2v2(const float v1[2], const float v2[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2])
void BLI_rctf_init(struct rctf *rect, float xmin, float xmax, float ymin, float ymax)
BLI_INLINE float BLI_rctf_size_x(const struct rctf *rct)
BLI_INLINE float BLI_rctf_size_y(const struct rctf *rct)
#define UNUSED_VARS_NDEBUG(...)
#define BLO_write_struct(writer, struct_name, data_ptr)
#define BLO_write_struct_array(writer, struct_name, array_size, data_ptr)
#define BLO_read_struct_array(reader, struct_name, array_size, ptr_p)
@ PROF_SAMPLE_EVEN_LENGTHS
@ PROF_SAMPLE_STRAIGHT_EDGES
Read Guarded memory(de)allocation.
static float bezt_edge_handle_angle(const CurveProfilePoint *path, int i_edge)
static float curveprofile_total_length(const CurveProfile *profile)
void BKE_curveprofile_init(CurveProfile *profile, short segments_len)
static void create_samples_even_spacing(CurveProfile *profile, int n_segments, CurveProfilePoint *r_samples)
void BKE_curveprofile_evaluate_length_portion(const CurveProfile *profile, float length_portion, float *x_out, float *y_out)
bool BKE_curveprofile_remove_point(CurveProfile *profile, CurveProfilePoint *point)
CurveProfilePoint * BKE_curveprofile_insert(CurveProfile *profile, float x, float y)
void BKE_curveprofile_copy_data(CurveProfile *target, const CurveProfile *profile)
void BKE_curveprofile_selected_handle_set(CurveProfile *profile, int type_1, int type_2)
static void curveprofile_build_steps(CurveProfile *profile)
bool BKE_curveprofile_move_handle(CurveProfilePoint *point, const bool handle_1, const bool snap, const float delta[2])
bool BKE_curveprofile_move_point(CurveProfile *profile, CurveProfilePoint *point, const bool snap, const float delta[2])
static void curveprofile_build_supports(CurveProfile *profile)
static void curveprofile_make_table(CurveProfile *profile)
void BKE_curveprofile_reset(CurveProfile *profile)
static void calculate_path_handles(CurveProfilePoint *path, int path_len)
static CurveProfilePoint mirror_point(const CurveProfilePoint *point)
static bool is_curved_edge(CurveProfilePoint *path, int i)
int BKE_curveprofile_table_size(const CurveProfile *profile)
void BKE_curveprofile_free_data(CurveProfile *profile)
void BKE_curveprofile_blend_write(BlendWriter *writer, const CurveProfile *profile)
void BKE_curveprofile_blend_read(BlendDataReader *reader, CurveProfile *profile)
void BKE_curveprofile_remove_by_flag(CurveProfile *profile, const short flag)
void BKE_curveprofile_reset_view(CurveProfile *profile)
static void point_calculate_handle(CurveProfilePoint *point, const CurveProfilePoint *prev, const CurveProfilePoint *next)
CurveProfile * BKE_curveprofile_add(eCurveProfilePresets preset)
void BKE_curveprofile_reverse(CurveProfile *profile)
static void point_init(CurveProfilePoint *point, float x, float y, short flag, char h1, char h2)
CurveProfile * BKE_curveprofile_copy(const CurveProfile *profile)
static void create_samples(CurveProfile *profile, int n_segments, bool sample_straight_edges, CurveProfilePoint *r_samples)
void BKE_curveprofile_free(CurveProfile *profile)
static float curveprofile_distance_to_next_table_point(const CurveProfile *profile, int i)
void BKE_curveprofile_update(CurveProfile *profile, const int update_flags)
static int sort_points_curvature(const void *in_a, const void *in_b)
static void curveprofile_make_segments_table(CurveProfile *profile)
void BKE_curveprofile_set_defaults(CurveProfile *profile)
float distance(VecOp< float, D >, VecOp< float, D >) RET
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
void * MEM_callocN(size_t len, const char *str)
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
void * MEM_dupallocN(const void *vmemh)
void MEM_freeN(void *vmemh)
vector snap(vector a, vector b)
struct CurveProfile * profile
CurveProfilePoint * table
CurveProfilePoint * segments