Line |
Branch |
Exec |
Source |
1 |
|
|
//------------------------------------------------------------------------------ |
2 |
|
|
// VERSION 0.1 |
3 |
|
|
// |
4 |
|
|
// LICENSE |
5 |
|
|
// This software is dual-licensed to the public domain and under the following |
6 |
|
|
// license: you are granted a perpetual, irrevocable license to copy, modify, |
7 |
|
|
// publish, and distribute this file as you see fit. |
8 |
|
|
// |
9 |
|
|
// CREDITS |
10 |
|
|
// Written by Michal Cichon |
11 |
|
|
//------------------------------------------------------------------------------ |
12 |
|
|
|
13 |
|
|
#define IMGUI_DEFINE_MATH_OPERATORS |
14 |
|
|
#include "imgui_extra_math.h" |
15 |
|
|
#include "bezier.h" |
16 |
|
|
|
17 |
|
|
ImProjectResult ImProjectOnCubicBezier(const ImVec2& point, const ImVec2& p0, const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const int subdivisions) |
18 |
|
|
{ |
19 |
|
|
// http://pomax.github.io/bezierinfo/#projections |
20 |
|
|
|
21 |
|
✗ |
const float epsilon = 1e-5f; |
22 |
|
✗ |
const float fixed_step = 1.0f / static_cast<float>(subdivisions - 1); |
23 |
|
|
|
24 |
|
✗ |
ImProjectResult result; |
25 |
|
✗ |
result.Point = point; |
26 |
|
✗ |
result.Time = 0.0f; |
27 |
|
✗ |
result.Distance = FLT_MAX; |
28 |
|
|
|
29 |
|
|
// Step 1: Coarse check |
30 |
|
✗ |
for (int i = 0; i < subdivisions; ++i) |
31 |
|
|
{ |
32 |
|
✗ |
auto t = i * fixed_step; |
33 |
|
✗ |
auto p = ImCubicBezier(p0, p1, p2, p3, t); |
34 |
|
✗ |
auto s = point - p; |
35 |
|
✗ |
auto d = ImDot(s, s); |
36 |
|
|
|
37 |
|
✗ |
if (d < result.Distance) |
38 |
|
|
{ |
39 |
|
✗ |
result.Point = p; |
40 |
|
✗ |
result.Time = t; |
41 |
|
✗ |
result.Distance = d; |
42 |
|
|
} |
43 |
|
|
} |
44 |
|
|
|
45 |
|
✗ |
if (result.Time == 0.0f || ImFabs(result.Time - 1.0f) <= epsilon) |
46 |
|
|
{ |
47 |
|
✗ |
result.Distance = ImSqrt(result.Distance); |
48 |
|
✗ |
return result; |
49 |
|
|
} |
50 |
|
|
|
51 |
|
|
// Step 2: Fine check |
52 |
|
✗ |
auto left = result.Time - fixed_step; |
53 |
|
✗ |
auto right = result.Time + fixed_step; |
54 |
|
✗ |
auto step = fixed_step * 0.1f; |
55 |
|
|
|
56 |
|
✗ |
for (auto t = left; t < right + step; t += step) |
57 |
|
|
{ |
58 |
|
✗ |
auto p = ImCubicBezier(p0, p1, p2, p3, t); |
59 |
|
✗ |
auto s = point - p; |
60 |
|
✗ |
auto d = ImDot(s, s); |
61 |
|
|
|
62 |
|
✗ |
if (d < result.Distance) |
63 |
|
|
{ |
64 |
|
✗ |
result.Point = p; |
65 |
|
✗ |
result.Time = t; |
66 |
|
✗ |
result.Distance = d; |
67 |
|
|
} |
68 |
|
|
} |
69 |
|
|
|
70 |
|
✗ |
result.Distance = ImSqrt(result.Distance); |
71 |
|
|
|
72 |
|
✗ |
return result; |
73 |
|
|
} |
74 |
|
|
|