aboutsummaryrefslogtreecommitdiff
path: root/3rdparty/imgui-node-editor/imgui_bezier_math.inl
diff options
context:
space:
mode:
authorrtk0c <[email protected]>2022-06-27 18:27:13 -0700
committerrtk0c <[email protected]>2022-06-27 18:27:13 -0700
commit8f0dda5eab181b0f14f2652b4e984aaaae3f258c (patch)
tree4b825dc642cb6eb9a060e54bf8d69288fbee4904 /3rdparty/imgui-node-editor/imgui_bezier_math.inl
parentfad6a88a13ab1f888ab25ad0aae19c1d63aa0623 (diff)
Start from a clean slate
Diffstat (limited to '3rdparty/imgui-node-editor/imgui_bezier_math.inl')
-rw-r--r--3rdparty/imgui-node-editor/imgui_bezier_math.inl675
1 files changed, 0 insertions, 675 deletions
diff --git a/3rdparty/imgui-node-editor/imgui_bezier_math.inl b/3rdparty/imgui-node-editor/imgui_bezier_math.inl
deleted file mode 100644
index 3020bdb..0000000
--- a/3rdparty/imgui-node-editor/imgui_bezier_math.inl
+++ /dev/null
@@ -1,675 +0,0 @@
-//------------------------------------------------------------------------------
-// VERSION 0.1
-//
-// LICENSE
-// This software is dual-licensed to the public domain and under the following
-// license: you are granted a perpetual, irrevocable license to copy, modify,
-// publish, and distribute this file as you see fit.
-//
-// CREDITS
-// Written by Michal Cichon
-//------------------------------------------------------------------------------
-# ifndef __IMGUI_BEZIER_MATH_INL__
-# define __IMGUI_BEZIER_MATH_INL__
-# pragma once
-
-
-//------------------------------------------------------------------------------
-# include "imgui_bezier_math.h"
-# include <map> // used in ImCubicBezierFixedStep
-
-
-//------------------------------------------------------------------------------
-template <typename T>
-inline T ImLinearBezier(const T& p0, const T& p1, float t)
-{
- return p0 + t * (p1 - p0);
-}
-
-template <typename T>
-inline T ImLinearBezierDt(const T& p0, const T& p1, float t)
-{
- IM_UNUSED(t);
-
- return p1 - p0;
-}
-
-template <typename T>
-inline T ImQuadraticBezier(const T& p0, const T& p1, const T& p2, float t)
-{
- const auto a = 1 - t;
-
- return a * a * p0 + 2 * t * a * p1 + t * t * p2;
-}
-
-template <typename T>
-inline T ImQuadraticBezierDt(const T& p0, const T& p1, const T& p2, float t)
-{
- return 2 * (1 - t) * (p1 - p0) + 2 * t * (p2 - p1);
-}
-
-template <typename T>
-inline T ImCubicBezier(const T& p0, const T& p1, const T& p2, const T& p3, float t)
-{
- const auto a = 1 - t;
- const auto b = a * a * a;
- const auto c = t * t * t;
-
- return b * p0 + 3 * t * a * a * p1 + 3 * t * t * a * p2 + c * p3;
-}
-
-template <typename T>
-inline T ImCubicBezierDt(const T& p0, const T& p1, const T& p2, const T& p3, float t)
-{
- const auto a = 1 - t;
- const auto b = a * a;
- const auto c = t * t;
- const auto d = 2 * t * a;
-
- return -3 * p0 * b + 3 * p1 * (b - d) + 3 * p2 * (d - c) + 3 * p3 * c;
-}
-
-template <typename T>
-inline T ImCubicBezierSample(const T& p0, const T& p1, const T& p2, const T& p3, float t)
-{
- const auto cp0_zero = ImLengthSqr(p1 - p0) < 1e-5f;
- const auto cp1_zero = ImLengthSqr(p3 - p2) < 1e-5f;
-
- if (cp0_zero && cp1_zero)
- return ImLinearBezier(p0, p3, t);
- else if (cp0_zero)
- return ImQuadraticBezier(p0, p2, p3, t);
- else if (cp1_zero)
- return ImQuadraticBezier(p0, p1, p3, t);
- else
- return ImCubicBezier(p0, p1, p2, p3, t);
-}
-
-template <typename T>
-inline T ImCubicBezierSample(const ImCubicBezierPointsT<T>& curve, float t)
-{
- return ImCubicBezierSample(curve.P0, curve.P1, curve.P2, curve.P3, t);
-}
-
-template <typename T>
-inline T ImCubicBezierTangent(const T& p0, const T& p1, const T& p2, const T& p3, float t)
-{
- const auto cp0_zero = ImLengthSqr(p1 - p0) < 1e-5f;
- const auto cp1_zero = ImLengthSqr(p3 - p2) < 1e-5f;
-
- if (cp0_zero && cp1_zero)
- return ImLinearBezierDt(p0, p3, t);
- else if (cp0_zero)
- return ImQuadraticBezierDt(p0, p2, p3, t);
- else if (cp1_zero)
- return ImQuadraticBezierDt(p0, p1, p3, t);
- else
- return ImCubicBezierDt(p0, p1, p2, p3, t);
-}
-
-template <typename T>
-inline T ImCubicBezierTangent(const ImCubicBezierPointsT<T>& curve, float t)
-{
- return ImCubicBezierTangent(curve.P0, curve.P1, curve.P2, curve.P3, t);
-}
-
-template <typename T>
-inline float ImCubicBezierLength(const T& p0, const T& p1, const T& p2, const T& p3)
-{
- // Legendre-Gauss abscissae with n=24 (x_i values, defined at i=n as the roots of the nth order Legendre polynomial Pn(x))
- static const float t_values[] =
- {
- -0.0640568928626056260850430826247450385909f,
- 0.0640568928626056260850430826247450385909f,
- -0.1911188674736163091586398207570696318404f,
- 0.1911188674736163091586398207570696318404f,
- -0.3150426796961633743867932913198102407864f,
- 0.3150426796961633743867932913198102407864f,
- -0.4337935076260451384870842319133497124524f,
- 0.4337935076260451384870842319133497124524f,
- -0.5454214713888395356583756172183723700107f,
- 0.5454214713888395356583756172183723700107f,
- -0.6480936519369755692524957869107476266696f,
- 0.6480936519369755692524957869107476266696f,
- -0.7401241915785543642438281030999784255232f,
- 0.7401241915785543642438281030999784255232f,
- -0.8200019859739029219539498726697452080761f,
- 0.8200019859739029219539498726697452080761f,
- -0.8864155270044010342131543419821967550873f,
- 0.8864155270044010342131543419821967550873f,
- -0.9382745520027327585236490017087214496548f,
- 0.9382745520027327585236490017087214496548f,
- -0.9747285559713094981983919930081690617411f,
- 0.9747285559713094981983919930081690617411f,
- -0.9951872199970213601799974097007368118745f,
- 0.9951872199970213601799974097007368118745f
- };
-
- // Legendre-Gauss weights with n=24 (w_i values, defined by a function linked to in the Bezier primer article)
- static const float c_values[] =
- {
- 0.1279381953467521569740561652246953718517f,
- 0.1279381953467521569740561652246953718517f,
- 0.1258374563468282961213753825111836887264f,
- 0.1258374563468282961213753825111836887264f,
- 0.1216704729278033912044631534762624256070f,
- 0.1216704729278033912044631534762624256070f,
- 0.1155056680537256013533444839067835598622f,
- 0.1155056680537256013533444839067835598622f,
- 0.1074442701159656347825773424466062227946f,
- 0.1074442701159656347825773424466062227946f,
- 0.0976186521041138882698806644642471544279f,
- 0.0976186521041138882698806644642471544279f,
- 0.0861901615319532759171852029837426671850f,
- 0.0861901615319532759171852029837426671850f,
- 0.0733464814110803057340336152531165181193f,
- 0.0733464814110803057340336152531165181193f,
- 0.0592985849154367807463677585001085845412f,
- 0.0592985849154367807463677585001085845412f,
- 0.0442774388174198061686027482113382288593f,
- 0.0442774388174198061686027482113382288593f,
- 0.0285313886289336631813078159518782864491f,
- 0.0285313886289336631813078159518782864491f,
- 0.0123412297999871995468056670700372915759f,
- 0.0123412297999871995468056670700372915759f
- };
-
- static_assert(sizeof(t_values) / sizeof(*t_values) == sizeof(c_values) / sizeof(*c_values), "");
-
- auto arc = [p0, p1, p2, p3](float t)
- {
- const auto p = ImCubicBezierDt(p0, p1, p2, p3, t);
- const auto l = ImLength(p);
- return l;
- };
-
- const auto z = 0.5f;
- const auto n = sizeof(t_values) / sizeof(*t_values);
-
- auto accumulator = 0.0f;
- for (size_t i = 0; i < n; ++i)
- {
- const auto t = z * t_values[i] + z;
- accumulator += c_values[i] * arc(t);
- }
-
- return z * accumulator;
-}
-
-template <typename T>
-inline float ImCubicBezierLength(const ImCubicBezierPointsT<T>& curve)
-{
- return ImCubicBezierLength(curve.P0, curve.P1, curve.P2, curve.P3);
-}
-
-template <typename T>
-inline ImCubicBezierSplitResultT<T> ImCubicBezierSplit(const T& p0, const T& p1, const T& p2, const T& p3, float t)
-{
- const auto z1 = t;
- const auto z2 = z1 * z1;
- const auto z3 = z1 * z1 * z1;
- const auto s1 = z1 - 1;
- const auto s2 = s1 * s1;
- const auto s3 = s1 * s1 * s1;
-
- return ImCubicBezierSplitResultT<T>
- {
- ImCubicBezierPointsT<T>
- {
- p0,
- z1 * p1 - s1 * p0,
- z2 * p2 - 2 * z1 * s1 * p1 + s2 * p0,
- z3 * p3 - 3 * z2 * s1 * p2 + 3 * z1 * s2 * p1 - s3 * p0
- },
- ImCubicBezierPointsT<T>
- {
- z3 * p0 - 3 * z2 * s1 * p1 + 3 * z1 * s2 * p2 - s3 * p3,
- z2 * p1 - 2 * z1 * s1 * p2 + s2 * p3,
- z1 * p2 - s1 * p3,
- p3,
- }
- };
-}
-
-template <typename T>
-inline ImCubicBezierSplitResultT<T> ImCubicBezierSplit(const ImCubicBezierPointsT<T>& curve, float t)
-{
- return ImCubicBezierSplit(curve.P0, curve.P1, curve.P2, curve.P3, t);
-}
-
-inline ImRect ImCubicBezierBoundingRect(const ImVec2& p0, const ImVec2& p1, const ImVec2& p2, const ImVec2& p3)
-{
- auto a = 3 * p3 - 9 * p2 + 9 * p1 - 3 * p0;
- auto b = 6 * p0 - 12 * p1 + 6 * p2;
- auto c = 3 * p1 - 3 * p0;
- auto delta_squared = ImMul(b, b) - 4 * ImMul(a, c);
-
- auto tl = ImMin(p0, p3);
- auto rb = ImMax(p0, p3);
-
-# define IM_VEC2_INDEX(v, i) *(&v.x + i)
-
- for (int i = 0; i < 2; ++i)
- {
- if (IM_VEC2_INDEX(a, i) == 0.0f)
- continue;
-
- if (IM_VEC2_INDEX(delta_squared, i) >= 0)
- {
- auto delta = ImSqrt(IM_VEC2_INDEX(delta_squared, i));
-
- auto t0 = (-IM_VEC2_INDEX(b, i) + delta) / (2 * IM_VEC2_INDEX(a, i));
- if (t0 > 0 && t0 < 1)
- {
- auto p = ImCubicBezier(IM_VEC2_INDEX(p0, i), IM_VEC2_INDEX(p1, i), IM_VEC2_INDEX(p2, i), IM_VEC2_INDEX(p3, i), t0);
- IM_VEC2_INDEX(tl, i) = ImMin(IM_VEC2_INDEX(tl, i), p);
- IM_VEC2_INDEX(rb, i) = ImMax(IM_VEC2_INDEX(rb, i), p);
- }
-
- auto t1 = (-IM_VEC2_INDEX(b, i) - delta) / (2 * IM_VEC2_INDEX(a, i));
- if (t1 > 0 && t1 < 1)
- {
- auto p = ImCubicBezier(IM_VEC2_INDEX(p0, i), IM_VEC2_INDEX(p1, i), IM_VEC2_INDEX(p2, i), IM_VEC2_INDEX(p3, i), t1);
- IM_VEC2_INDEX(tl, i) = ImMin(IM_VEC2_INDEX(tl, i), p);
- IM_VEC2_INDEX(rb, i) = ImMax(IM_VEC2_INDEX(rb, i), p);
- }
- }
- }
-
-# undef IM_VEC2_INDEX
-
- return ImRect(tl, rb);
-}
-
-inline ImRect ImCubicBezierBoundingRect(const ImCubicBezierPoints& curve)
-{
- return ImCubicBezierBoundingRect(curve.P0, curve.P1, curve.P2, curve.P3);
-}
-
-inline ImProjectResult ImProjectOnCubicBezier(const ImVec2& point, const ImVec2& p0, const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const int subdivisions)
-{
- // http://pomax.github.io/bezierinfo/#projections
-
- const float epsilon = 1e-5f;
- const float fixed_step = 1.0f / static_cast<float>(subdivisions - 1);
-
- ImProjectResult result;
- result.Point = point;
- result.Time = 0.0f;
- result.Distance = FLT_MAX;
-
- // Step 1: Coarse check
- for (int i = 0; i < subdivisions; ++i)
- {
- auto t = i * fixed_step;
- auto p = ImCubicBezier(p0, p1, p2, p3, t);
- auto s = point - p;
- auto d = ImDot(s, s);
-
- if (d < result.Distance)
- {
- result.Point = p;
- result.Time = t;
- result.Distance = d;
- }
- }
-
- if (result.Time == 0.0f || ImFabs(result.Time - 1.0f) <= epsilon)
- {
- result.Distance = ImSqrt(result.Distance);
- return result;
- }
-
- // Step 2: Fine check
- auto left = result.Time - fixed_step;
- auto right = result.Time + fixed_step;
- auto step = fixed_step * 0.1f;
-
- for (auto t = left; t < right + step; t += step)
- {
- auto p = ImCubicBezier(p0, p1, p2, p3, t);
- auto s = point - p;
- auto d = ImDot(s, s);
-
- if (d < result.Distance)
- {
- result.Point = p;
- result.Time = t;
- result.Distance = d;
- }
- }
-
- result.Distance = ImSqrt(result.Distance);
-
- return result;
-}
-
-inline ImProjectResult ImProjectOnCubicBezier(const ImVec2& p, const ImCubicBezierPoints& curve, const int subdivisions)
-{
- return ImProjectOnCubicBezier(p, curve.P0, curve.P1, curve.P2, curve.P3, subdivisions);
-}
-
-inline ImCubicBezierIntersectResult ImCubicBezierLineIntersect(const ImVec2& p0, const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& a0, const ImVec2& a1)
-{
- auto cubic_roots = [](float a, float b, float c, float d, float* roots) -> int
- {
- int count = 0;
-
- auto sign = [](float x) -> float { return x < 0 ? -1.0f : 1.0f; };
-
- auto A = b / a;
- auto B = c / a;
- auto C = d / a;
-
- auto Q = (3 * B - ImPow(A, 2)) / 9;
- auto R = (9 * A * B - 27 * C - 2 * ImPow(A, 3)) / 54;
- auto D = ImPow(Q, 3) + ImPow(R, 2); // polynomial discriminant
-
- if (D >= 0) // complex or duplicate roots
- {
- auto S = sign(R + ImSqrt(D)) * ImPow(ImFabs(R + ImSqrt(D)), (1.0f / 3.0f));
- auto T = sign(R - ImSqrt(D)) * ImPow(ImFabs(R - ImSqrt(D)), (1.0f / 3.0f));
-
- roots[0] = -A / 3 + (S + T); // real root
- roots[1] = -A / 3 - (S + T) / 2; // real part of complex root
- roots[2] = -A / 3 - (S + T) / 2; // real part of complex root
- auto Im = ImFabs(ImSqrt(3) * (S - T) / 2); // complex part of root pair
-
- // discard complex roots
- if (Im != 0)
- count = 1;
- else
- count = 3;
- }
- else // distinct real roots
- {
- auto th = ImAcos(R / ImSqrt(-ImPow(Q, 3)));
-
- roots[0] = 2 * ImSqrt(-Q) * ImCos(th / 3) - A / 3;
- roots[1] = 2 * ImSqrt(-Q) * ImCos((th + 2 * IM_PI) / 3) - A / 3;
- roots[2] = 2 * ImSqrt(-Q) * ImCos((th + 4 * IM_PI) / 3) - A / 3;
-
- count = 3;
- }
-
- return count;
- };
-
- // https://github.com/kaishiqi/Geometric-Bezier/blob/master/GeometricBezier/src/kaishiqi/geometric/intersection/Intersection.as
- //
- // Start with Bezier using Bernstein polynomials for weighting functions:
- // (1-t^3)P0 + 3t(1-t)^2P1 + 3t^2(1-t)P2 + t^3P3
- //
- // Expand and collect terms to form linear combinations of original Bezier
- // controls. This ends up with a vector cubic in t:
- // (-P0+3P1-3P2+P3)t^3 + (3P0-6P1+3P2)t^2 + (-3P0+3P1)t + P0
- // /\ /\ /\ /\
- // || || || ||
- // c3 c2 c1 c0
-
- // Calculate the coefficients
- auto c3 = -p0 + 3 * p1 - 3 * p2 + p3;
- auto c2 = 3 * p0 - 6 * p1 + 3 * p2;
- auto c1 = -3 * p0 + 3 * p1;
- auto c0 = p0;
-
- // Convert line to normal form: ax + by + c = 0
- auto a = a1.y - a0.y;
- auto b = a0.x - a1.x;
- auto c = a0.x * (a0.y - a1.y) + a0.y * (a1.x - a0.x);
-
- // Rotate each cubic coefficient using line for new coordinate system?
- // Find roots of rotated cubic
- float roots[3];
- auto rootCount = cubic_roots(
- a * c3.x + b * c3.y,
- a * c2.x + b * c2.y,
- a * c1.x + b * c1.y,
- a * c0.x + b * c0.y + c,
- roots);
-
- // Any roots in closed interval [0,1] are intersections on Bezier, but
- // might not be on the line segment.
- // Find intersections and calculate point coordinates
-
- auto min = ImMin(a0, a1);
- auto max = ImMax(a0, a1);
-
- ImCubicBezierIntersectResult result;
- auto points = result.Points;
-
- for (int i = 0; i < rootCount; ++i)
- {
- auto root = roots[i];
-
- if (0 <= root && root <= 1)
- {
- // We're within the Bezier curve
- // Find point on Bezier
- auto p = ImCubicBezier(p0, p1, p2, p3, root);
-
- // See if point is on line segment
- // Had to make special cases for vertical and horizontal lines due
- // to slight errors in calculation of p00
- if (a0.x == a1.x)
- {
- if (min.y <= p.y && p.y <= max.y)
- *points++ = p;
- }
- else if (a0.y == a1.y)
- {
- if (min.x <= p.x && p.x <= max.x)
- *points++ = p;
- }
- else if (p.x >= min.x && p.y >= min.y && p.x <= max.x && p.y <= max.y)
- {
- *points++ = p;
- }
- }
- }
-
- result.Count = static_cast<int>(points - result.Points);
-
- return result;
-}
-
-inline ImCubicBezierIntersectResult ImCubicBezierLineIntersect(const ImCubicBezierPoints& curve, const ImLine& line)
-{
- return ImCubicBezierLineIntersect(curve.P0, curve.P1, curve.P2, curve.P3, line.A, line.B);
-}
-
-inline void ImCubicBezierSubdivide(ImCubicBezierSubdivideCallback callback, void* user_pointer, const ImVec2& p0, const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, float tess_tol, ImCubicBezierSubdivideFlags flags)
-{
- return ImCubicBezierSubdivide(callback, user_pointer, ImCubicBezierPoints{ p0, p1, p2, p3 }, tess_tol, flags);
-}
-
-inline void ImCubicBezierSubdivide(ImCubicBezierSubdivideCallback callback, void* user_pointer, const ImCubicBezierPoints& curve, float tess_tol, ImCubicBezierSubdivideFlags flags)
-{
- struct Tesselator
- {
- ImCubicBezierSubdivideCallback Callback;
- void* UserPointer;
- float TesselationTollerance;
- ImCubicBezierSubdivideFlags Flags;
-
- void Commit(const ImVec2& p, const ImVec2& t)
- {
- ImCubicBezierSubdivideSample sample;
- sample.Point = p;
- sample.Tangent = t;
- Callback(sample, UserPointer);
- }
-
- void Subdivide(const ImCubicBezierPoints& curve, int level = 0)
- {
- float dx = curve.P3.x - curve.P0.x;
- float dy = curve.P3.y - curve.P0.y;
- float d2 = ((curve.P1.x - curve.P3.x) * dy - (curve.P1.y - curve.P3.y) * dx);
- float d3 = ((curve.P2.x - curve.P3.x) * dy - (curve.P2.y - curve.P3.y) * dx);
- d2 = (d2 >= 0) ? d2 : -d2;
- d3 = (d3 >= 0) ? d3 : -d3;
- if ((d2 + d3) * (d2 + d3) < TesselationTollerance * (dx * dx + dy * dy))
- {
- Commit(curve.P3, ImCubicBezierTangent(curve, 1.0f));
- }
- else if (level < 10)
- {
- const auto p12 = (curve.P0 + curve.P1) * 0.5f;
- const auto p23 = (curve.P1 + curve.P2) * 0.5f;
- const auto p34 = (curve.P2 + curve.P3) * 0.5f;
- const auto p123 = (p12 + p23) * 0.5f;
- const auto p234 = (p23 + p34) * 0.5f;
- const auto p1234 = (p123 + p234) * 0.5f;
-
- Subdivide(ImCubicBezierPoints { curve.P0, p12, p123, p1234 }, level + 1);
- Subdivide(ImCubicBezierPoints { p1234, p234, p34, curve.P3 }, level + 1);
- }
- }
- };
-
- if (tess_tol < 0)
- tess_tol = 1.118f; // sqrtf(1.25f)
-
- Tesselator tesselator;
- tesselator.Callback = callback;
- tesselator.UserPointer = user_pointer;
- tesselator.TesselationTollerance = tess_tol * tess_tol;
- tesselator.Flags = flags;
-
- if (!(tesselator.Flags & ImCubicBezierSubdivide_SkipFirst))
- tesselator.Commit(curve.P0, ImCubicBezierTangent(curve, 0.0f));
-
- tesselator.Subdivide(curve, 0);
-}
-
-template <typename F> inline void ImCubicBezierSubdivide(F& callback, const ImVec2& p0, const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, float tess_tol, ImCubicBezierSubdivideFlags flags)
-{
- auto handler = [](const ImCubicBezierSubdivideSample& p, void* user_pointer)
- {
- auto& callback = *reinterpret_cast<F*>(user_pointer);
- callback(p);
- };
-
- ImCubicBezierSubdivide(handler, &callback, ImCubicBezierPoints{ p0, p1, p2, p3 }, tess_tol, flags);
-}
-
-template <typename F> inline void ImCubicBezierSubdivide(F& callback, const ImCubicBezierPoints& curve, float tess_tol, ImCubicBezierSubdivideFlags flags)
-{
- auto handler = [](const ImCubicBezierSubdivideSample& p, void* user_pointer)
- {
- auto& callback = *reinterpret_cast<F*>(user_pointer);
- callback(p);
- };
-
- ImCubicBezierSubdivide(handler, &callback, curve, tess_tol, flags);
-}
-
-inline void ImCubicBezierFixedStep(ImCubicBezierFixedStepCallback callback, void* user_pointer, const ImVec2& p0, const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, float step, bool overshoot, float max_value_error, float max_t_error)
-{
- if (step <= 0.0f || !callback || max_value_error <= 0 || max_t_error <= 0)
- return;
-
- ImCubicBezierFixedStepSample sample;
- sample.T = 0.0f;
- sample.Length = 0.0f;
- sample.Point = p0;
- sample.BreakSearch = false;
-
- callback(sample, user_pointer);
- if (sample.BreakSearch)
- return;
-
- const auto total_length = ImCubicBezierLength(p0, p1, p2, p3);
- const auto point_count = static_cast<int>(total_length / step) + (overshoot ? 2 : 1);
- const auto t_min = 0.0f;
- const auto t_max = step * point_count / total_length;
- const auto t_0 = (t_min + t_max) * 0.5f;
-
- // #todo: replace map with ImVector + binary search
- std::map<float, float> cache;
- for (int point_index = 1; point_index < point_count; ++point_index)
- {
- const auto targetLength = point_index * step;
-
- float t_start = t_min;
- float t_end = t_max;
- float t = t_0;
-
- float t_best = t;
- float error_best = total_length;
-
- while (true)
- {
- auto cacheIt = cache.find(t);
- if (cacheIt == cache.end())
- {
- const auto front = ImCubicBezierSplit(p0, p1, p2, p3, t).Left;
- const auto split_length = ImCubicBezierLength(front);
-
- cacheIt = cache.emplace(t, split_length).first;
- }
-
- const auto length = cacheIt->second;
- const auto error = targetLength - length;
-
- if (error < error_best)
- {
- error_best = error;
- t_best = t;
- }
-
- if (ImFabs(error) <= max_value_error || ImFabs(t_start - t_end) <= max_t_error)
- {
- sample.T = t;
- sample.Length = length;
- sample.Point = ImCubicBezier(p0, p1, p2, p3, t);
-
- callback(sample, user_pointer);
- if (sample.BreakSearch)
- return;
-
- break;
- }
- else if (error < 0.0f)
- t_end = t;
- else // if (error > 0.0f)
- t_start = t;
-
- t = (t_start + t_end) * 0.5f;
- }
- }
-}
-
-inline void ImCubicBezierFixedStep(ImCubicBezierFixedStepCallback callback, void* user_pointer, const ImCubicBezierPoints& curve, float step, bool overshoot, float max_value_error, float max_t_error)
-{
- ImCubicBezierFixedStep(callback, user_pointer, curve.P0, curve.P1, curve.P2, curve.P3, step, overshoot, max_value_error, max_t_error);
-}
-
-// F has signature void(const ImCubicBezierFixedStepSample& p)
-template <typename F>
-inline void ImCubicBezierFixedStep(F& callback, const ImVec2& p0, const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, float step, bool overshoot, float max_value_error, float max_t_error)
-{
- auto handler = [](ImCubicBezierFixedStepSample& sample, void* user_pointer)
- {
- auto& callback = *reinterpret_cast<F*>(user_pointer);
- callback(sample);
- };
-
- ImCubicBezierFixedStep(handler, &callback, p0, p1, p2, p3, step, overshoot, max_value_error, max_t_error);
-}
-
-template <typename F>
-inline void ImCubicBezierFixedStep(F& callback, const ImCubicBezierPoints& curve, float step, bool overshoot, float max_value_error, float max_t_error)
-{
- auto handler = [](ImCubicBezierFixedStepSample& sample, void* user_pointer)
- {
- auto& callback = *reinterpret_cast<F*>(user_pointer);
- callback(sample);
- };
-
- ImCubicBezierFixedStep(handler, &callback, curve.P0, curve.P1, curve.P2, curve.P3, step, overshoot, max_value_error, max_t_error);
-}
-
-
-//------------------------------------------------------------------------------
-# endif // __IMGUI_BEZIER_MATH_INL__