Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenlib/intern/math_geom.c')
-rw-r--r--source/blender/blenlib/intern/math_geom.c34
1 files changed, 34 insertions, 0 deletions
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;
+ }
+}