diff options
author | Campbell Barton <ideasman42@gmail.com> | 2016-05-23 14:31:22 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2016-05-23 14:35:54 +0300 |
commit | a17cba339cf6d425b44fb4953974cedaed1a8cef (patch) | |
tree | 199ebbcb9d7501dc7c95144e68b3f7c1e71cf55c /source/blender/blenlib | |
parent | abe98de63ce4ec9a80aa8fd16bf94675d3947f12 (diff) |
BLI_math: Add function to calculate circular cubic curve tangents
Diffstat (limited to 'source/blender/blenlib')
-rw-r--r-- | source/blender/blenlib/BLI_math_geom.h | 4 | ||||
-rw-r--r-- | source/blender/blenlib/intern/math_geom.c | 34 |
2 files changed, 38 insertions, 0 deletions
diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h index 45edaca544d..54b824c91ac 100644 --- a/source/blender/blenlib/BLI_math_geom.h +++ b/source/blender/blenlib/BLI_math_geom.h @@ -470,6 +470,10 @@ MINLINE float shell_v2v2_normalized_to_dist(const float a[2], const float b[2]); MINLINE float shell_v3v3_mid_normalized_to_dist(const float a[3], const float b[3]); MINLINE float shell_v2v2_mid_normalized_to_dist(const float a[2], const float b[2]); +/********************************* Cubic (Bezier) *******************************/ + +float cubic_tangent_factor_circle_v3(const float tan_l[3], const float tan_r[3]); + /**************************** Inline Definitions ******************************/ #if BLI_MATH_DO_INLINE diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index f80099bee1b..370e8bb0035 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -4988,3 +4988,37 @@ int is_quad_flip_v3(const float v1[3], const float v2[3], const float v3[3], con return ret; } + +/** + * Return the value which the distance between points will need to be scaled by, + * to define a handle, given both points are on a perfect circle. + * + * Use when we want a bezier curve to match a circle as closely as possible. + * + * \note the return value will need to be divided by 0.75 for correct results. + */ +float cubic_tangent_factor_circle_v3(const float tan_l[3], const float tan_r[3]) +{ + BLI_ASSERT_UNIT_V3(tan_l); + BLI_ASSERT_UNIT_V3(tan_r); + + const float eps = 1e-7f; + const float tan_dot = dot_v3v3(tan_l, tan_r); + if (tan_dot > 1.0f - eps) { + /* no angle difference (use fallback, length wont make any difference) */ + return (1.0f / 3.0f) * 0.75f; + } + else if (tan_dot < -1.0f + eps) { + /* parallele tangents (half-circle) */ + return (1.0f / 2.0f); + } + else { + /* non-aligned tangents, calculate handle length */ + const float angle = acosf(tan_dot) / 2.0f; + + /* could also use 'angle_sin = len_vnvn(tan_l, tan_r, dims) / 2.0' */ + const float angle_sin = sinf(angle); + const float angle_cos = cosf(angle); + return ((1.0f - angle_cos) / (angle_sin * 2.0f)) / angle_sin; + } +} |