@@ -39,6 +39,44 @@ namespace {
3939 bool IsPointBeforeX (Point const & p, double const x) {
4040 return p.co .X < x;
4141 }
42+
43+ double InterpolateBezierCurve (Point const & left, Point const & right, bool const needY, double const target, double const allowed_error) {
44+ double const X_diff = right.co .X - left.co .X ;
45+ double const Y_diff = right.co .Y - left.co .Y ;
46+ Coordinate const p0 = left.co ;
47+ Coordinate const p1 = Coordinate (p0.X + left.handle_right .X * X_diff, p0.Y + left.handle_right .Y * Y_diff);
48+ Coordinate const p2 = Coordinate (p0.X + right.handle_left .X * X_diff, p0.Y + right.handle_left .Y * Y_diff);
49+ Coordinate const p3 = right.co ;
50+
51+ double t = 0.5 ;
52+ double t_step = 0.25 ;
53+ do {
54+ // Bernstein polynoms
55+ double B[4 ] = {1 , 3 , 3 , 1 };
56+ double oneMinTExp = 1 ;
57+ double tExp = 1 ;
58+ for (int i = 0 ; i < 4 ; ++i, tExp *= t) {
59+ B[i] *= tExp;
60+ }
61+ for (int i = 0 ; i < 4 ; ++i, oneMinTExp *= 1 - t) {
62+ B[4 - i - 1 ] *= oneMinTExp;
63+ }
64+ double const x = p0.X * B[0 ] + p1.X * B[1 ] + p2.X * B[2 ] + p3.X * B[3 ];
65+ double const y = p0.Y * B[0 ] + p1.Y * B[1 ] + p2.Y * B[2 ] + p3.Y * B[3 ];
66+ bool const stop = abs (target - (needY ? x : y)) < allowed_error;
67+ bool const move_left = (needY ? x : y) > target;
68+ if (stop) {
69+ return needY ? y : x;
70+ }
71+ if (move_left) {
72+ t -= t_step;
73+ }
74+ else {
75+ t += t_step;
76+ }
77+ t_step /= 2 ;
78+ } while (true );
79+ }
4280}
4381
4482
@@ -231,39 +269,7 @@ double Keyframe::GetValue(int64_t index) const {
231269 // BEZIER curve!
232270 assert (candidate->interpolation == BEZIER);
233271
234- double const X_diff = candidate->co .X - predecessor->co .X ;
235- double const Y_diff = candidate->co .Y - predecessor->co .Y ;
236- Coordinate const p0 = predecessor->co ;
237- Coordinate const p1 = Coordinate (p0.X + predecessor->handle_right .X * X_diff, p0.Y + predecessor->handle_right .Y * Y_diff);
238- Coordinate const p2 = Coordinate (p0.X + candidate->handle_left .X * X_diff, p0.Y + candidate->handle_left .Y * Y_diff);
239- Coordinate const p3 = candidate->co ;
240-
241- double t = 0.5 ;
242- double t_step = 0.25 ;
243- do {
244- // Bernstein polynoms
245- double B[4 ] = {1 , 3 , 3 , 1 };
246- double oneMinTExp = 1 ;
247- double tExp = 1 ;
248- for (int i = 0 ; i < 4 ; ++i, tExp *= t) {
249- B[i] *= tExp;
250- }
251- for (int i = 0 ; i < 4 ; ++i, oneMinTExp *= 1 - t) {
252- B[4 - i - 1 ] *= oneMinTExp;
253- }
254- double const x = p0.X * B[0 ] + p1.X * B[1 ] + p2.X * B[2 ] + p3.X * B[3 ];
255- double const y = p0.Y * B[0 ] + p1.Y * B[1 ] + p2.Y * B[2 ] + p3.Y * B[3 ];
256- if (abs (index - x) < 0.01 ) {
257- return y;
258- }
259- if (x > index) {
260- t -= t_step;
261- }
262- else {
263- t += t_step;
264- }
265- t_step /= 2 ;
266- } while (true );
272+ return InterpolateBezierCurve (*predecessor, *candidate, true , index, 0.01 );
267273}
268274
269275// Get the rounded INT value at a specific index
0 commit comments