2009-10-09 Chris Toshok <toshok@ximian.com>
[moon.git] / src / moon-curves.c
blob7204302f99a0861794b82aac4344489462e84489
1 /*
2 * moon-curves.c: A set of primitives + alghos for solving Y at X problmem
3 * for cubic curves. This is used ONLY for KeySpline animation,
4 * not used in any way for drawing.
6 * Author:
7 * Michael Dominic K. <mdk@mdk.am>
9 * Copyright 2007 Novell, Inc. (http://www.novell.com)
11 * See the LICENSE file included with the distribution for details.
15 #include "moon-curves.h"
17 static void
18 point_half_lerp (moon_point *dest, moon_point a, moon_point b)
20 dest->x = a.x + (b.x - a.x) * 0.5;
21 dest->y = a.y + (b.y - a.y) * 0.5;
24 void
25 moon_quadratic_from_cubic (moon_quadratic *dest, moon_cubic *src)
27 dest->c0.x = src->c0.x; dest->c0.y = src->c0.y;
29 dest->c1.x = (src->c1.x + src->c2.x) / 2.0;
30 dest->c1.y = (src->c1.y + src->c2.y) / 2.0;
32 dest->c2.x = src->c3.x; dest->c2.y = src->c3.y;
35 double
36 moon_quadratic_y_for_x (double x, moon_quadratic *src)
38 double l = src->c2.x - src->c0.x;
39 if (l <= 0)
40 return 0.0;
41 else {
42 x = (x - src->c0.x) / l;
43 return ((1 - x) * (1 - x)) * src->c0.y + ((2 * x) * (1 - x) * src->c1.y) + ((x * x) * src->c2.y);
47 double
48 moon_quadratic_array_y_for_x (moon_quadratic *qarr, double x, int count)
50 int i;
52 for (i = 0; i < count; i++) {
53 if (x < qarr [i].c2.x)
54 return moon_quadratic_y_for_x (x, &qarr [i]);
57 g_warning ("Failed to find a matching quadratic segment for %.5f", x);
58 return 0.0;
61 void
62 moon_convert_cubics_to_quadratics (moon_quadratic *dest_array, moon_cubic *src_array, int count)
64 int i = 0;
65 for (i = 0; i < count; i++)
66 moon_quadratic_from_cubic (&dest_array [i], &src_array [i]);
69 void
70 moon_subdivide_cubic (moon_cubic *dest1, moon_cubic *dest2, moon_cubic *src)
72 moon_point p01, p012, p0123;
73 moon_point p12, p23, p123;
75 point_half_lerp (&p01, src->c0, src->c1);
76 point_half_lerp (&p12, src->c1, src->c2);
77 point_half_lerp (&p23, src->c2, src->c3);
79 point_half_lerp (&p012, p01, p12);
81 point_half_lerp (&p123, p12, p23);
82 point_half_lerp (&p0123, p012, p123);
84 dest1->c0 = src->c0;
85 dest1->c1 = p01;
86 dest1->c2 = p012;
87 dest1->c3 = p0123;
89 dest2->c0 = p0123;
90 dest2->c1 = p123;
91 dest2->c2 = p23;
92 dest2->c3 = src->c3;
95 static void
96 recursive_subdivide_func (moon_cubic *b, int lvl, int current_lvl, int *current_pos, moon_cubic *src)
98 moon_cubic b1, b2;
99 moon_subdivide_cubic (&b1, &b2, src);
101 if (current_lvl == lvl) {
102 b [*current_pos] = b1;
103 b [*current_pos + 1] = b2;
104 *current_pos += 2;
105 } else {
106 recursive_subdivide_func (b, lvl, current_lvl + 1, current_pos, &b1);
107 recursive_subdivide_func (b, lvl, current_lvl + 1, current_pos, &b2);
111 void
112 moon_subdivide_cubic_at_level (moon_cubic *b, int lvl, moon_cubic *src)
114 int pos = 0;
115 recursive_subdivide_func (b, lvl, 1, &pos, src);