2 bezier.cc -- implement Bezier and Bezier_bow
4 source file of the GNU LilyPond music typesetter
6 (c) 1998--2000 Jan Nieuwenhuizen <janneke@gnu.org>
12 #include "libc-extension.hh"
14 #include "polynomial.hh"
17 binomial_coefficient (Real over
, int under
)
23 x
*= over
/ Real (under
);
32 scale (Array
<Offset
>* arr_p
, Real x
, Real y
)
34 for (int i
= 0; i
< arr_p
->size (); i
++)
36 (*arr_p
)[i
][X_AXIS
] = x
* (*arr_p
)[i
][X_AXIS
];
37 (*arr_p
)[i
][Y_AXIS
] = y
* (*arr_p
)[i
][Y_AXIS
];
42 rotate (Array
<Offset
>* arr_p
, Real phi
)
44 Offset
rot (complex_exp (Offset (0, phi
)));
45 for (int i
= 0; i
< arr_p
->size (); i
++)
46 (*arr_p
)[i
] = complex_multiply (rot
, (*arr_p
)[i
]);
50 translate (Array
<Offset
>* arr_p
, Offset o
)
52 for (int i
= 0; i
< arr_p
->size (); i
++)
58 Formula of the bezier 3-spline
60 sum_{j=0}^3 (3 over j) z_j (1-t)^(3-j) t^j
64 Bezier::get_other_coordinate (Axis a
, Real x
) const
66 Axis other
= Axis ((a
+1)%NO_AXES
);
67 Array
<Real
> ts
= solve_point (a
, x
);
69 Offset c
= curve_point (ts
[0]);
70 assert (fabs (c
[a
] - x
) < 1e-8);
77 Bezier::curve_point (Real t
)const
80 Real one_min_tj
= (1-t
)*(1-t
)*(1-t
);
83 for (int j
=0 ; j
< 4; j
++)
85 o
+= control_
[j
] * binomial_coefficient (3, j
)
86 * pow (t
,j
) * pow (1-t
, 3-j
);
94 assert (fabs (o
[X_AXIS
] - polynomial (X_AXIS
).eval (t
))< 1e-8);
95 assert (fabs (o
[Y_AXIS
] - polynomial (Y_AXIS
).eval (t
))< 1e-8);
103 Bezier::polynomial (Axis a
)const
106 for (int j
=0; j
<= 3; j
++)
109 * Polynomial::power (j
, Polynomial (0,1))*
110 Polynomial::power (3 - j
, Polynomial (1,-1))*
111 binomial_coefficient(3, j
);
118 Remove all numbers outside [0,1] from SOL
121 filter_solutions (Array
<Real
> sol
)
123 for (int i
= sol
.size (); i
--;)
124 if (sol
[i
] < 0 || sol
[i
] >1)
130 find t such that derivative is proportional to DERIV
133 Bezier::solve_derivative (Offset deriv
)const
135 Polynomial xp
=polynomial (X_AXIS
);
136 Polynomial yp
=polynomial (Y_AXIS
);
140 Polynomial combine
= xp
* deriv
[Y_AXIS
] - yp
* deriv
[X_AXIS
];
142 return filter_solutions (combine
.solve ());
147 Find t such that curve_point (t)[AX] == COORDINATE
150 Bezier::solve_point (Axis ax
, Real coordinate
) const
152 Polynomial
p(polynomial (ax
));
153 p
.coefs_
[0] -= coordinate
;
155 Array
<Real
> sol (p
.solve ());
156 return filter_solutions (sol
);
160 Compute the bounding box dimensions in direction of A.
163 Bezier::extent (Axis a
)const
165 int o
= (a
+1)%NO_AXES
;
169 Array
<Real
> sols (solve_derivative (d
));
172 for (int i
= sols
.size (); i
--;)
174 Offset
o (curve_point (sols
[i
]));
175 iv
.unite (Interval (o
[a
],o
[a
]));
185 Bezier::scale (Real x
, Real y
)
187 for (int i
= CONTROL_COUNT
; i
--;)
189 control_
[i
][X_AXIS
] = x
* control_
[i
][X_AXIS
];
190 control_
[i
][Y_AXIS
] = y
* control_
[i
][Y_AXIS
];
195 Bezier::rotate (Real phi
)
197 Offset
rot (complex_exp (Offset (0, phi
)));
198 for (int i
= 0; i
< CONTROL_COUNT
; i
++)
199 control_
[i
] = complex_multiply (rot
, control_
[i
]);
203 Bezier::translate (Offset o
)
205 for (int i
= 0; i
< CONTROL_COUNT
; i
++)
210 Bezier::assert_sanity () const
212 for (int i
=0; i
< CONTROL_COUNT
; i
++)
213 assert (!isnan (control_
[i
].length ())
214 && !isinf (control_
[i
].length ()));
221 for (int i
=0; i
< CONTROL_COUNT
; i
++)
222 b2
.control_
[CONTROL_COUNT
-i
-1] = control_
[i
];