2 bezier.cc -- implement Bezier and Bezier_bow
4 source file of the GNU LilyPond music typesetter
6 (c) 1998--2003 Jan Nieuwenhuizen <janneke@gnu.org>
13 #include "libc-extension.hh"
15 #include "polynomial.hh"
18 binomial_coefficient (Real over
, int under
)
24 x
*= over
/ Real (under
);
33 scale (Array
<Offset
>* array
, Real x
, Real y
)
35 for (int i
= 0; i
< array
->size (); i
++)
37 (*array
)[i
][X_AXIS
] = x
* (*array
)[i
][X_AXIS
];
38 (*array
)[i
][Y_AXIS
] = y
* (*array
)[i
][Y_AXIS
];
43 rotate (Array
<Offset
>* array
, Real phi
)
45 Offset
rot (complex_exp (Offset (0, phi
)));
46 for (int i
= 0; i
< array
->size (); i
++)
47 (*array
)[i
] = complex_multiply (rot
, (*array
)[i
]);
51 translate (Array
<Offset
>* array
, Offset o
)
53 for (int i
= 0; i
< array
->size (); i
++)
59 Formula of the bezier 3-spline
61 sum_{j=0}^3 (3 over j) z_j (1-t)^ (3-j) t^j
65 Bezier::get_other_coordinate (Axis a
, Real x
) const
67 Axis other
= Axis ((a
+1)%NO_AXES
);
68 Array
<Real
> ts
= solve_point (a
, x
);
72 programming_error ("No solution found for Bezier intersection.");
76 Offset c
= curve_point (ts
[0]);
77 assert (fabs (c
[a
] - x
) < 1e-8);
84 Bezier::curve_point (Real t
)const
87 Real one_min_tj
= (1-t
)* (1-t
)* (1-t
);
90 for (int j
=0 ; j
< 4; j
++)
92 o
+= control_
[j
] * binomial_coefficient (3, j
)
93 * pow (t
,j
) * pow (1-t
, 3-j
);
101 assert (fabs (o
[X_AXIS
] - polynomial (X_AXIS
).eval (t
))< 1e-8);
102 assert (fabs (o
[Y_AXIS
] - polynomial (Y_AXIS
).eval (t
))< 1e-8);
110 Bezier::polynomial (Axis a
)const
113 for (int j
=0; j
<= 3; j
++)
115 p
+= (control_
[j
][a
] * binomial_coefficient (3, j
))
116 * Polynomial::power (j
, Polynomial (0,1))*
117 Polynomial::power (3 - j
, Polynomial (1,-1));
124 Remove all numbers outside [0,1] from SOL
127 filter_solutions (Array
<Real
> sol
)
129 for (int i
= sol
.size (); i
--;)
130 if (sol
[i
] < 0 || sol
[i
] >1)
136 find t such that derivative is proportional to DERIV
139 Bezier::solve_derivative (Offset deriv
)const
141 Polynomial xp
=polynomial (X_AXIS
);
142 Polynomial yp
=polynomial (Y_AXIS
);
146 Polynomial combine
= xp
* deriv
[Y_AXIS
] - yp
* deriv
[X_AXIS
];
148 return filter_solutions (combine
.solve ());
153 Find t such that curve_point (t)[AX] == COORDINATE
156 Bezier::solve_point (Axis ax
, Real coordinate
) const
158 Polynomial
p (polynomial (ax
));
159 p
.coefs_
[0] -= coordinate
;
161 Array
<Real
> sol (p
.solve ());
162 return filter_solutions (sol
);
166 Compute the bounding box dimensions in direction of A.
169 Bezier::extent (Axis a
)const
171 int o
= (a
+1)%NO_AXES
;
175 Array
<Real
> sols (solve_derivative (d
));
178 for (int i
= sols
.size (); i
--;)
180 Offset
o (curve_point (sols
[i
]));
181 iv
.unite (Interval (o
[a
],o
[a
]));
191 Bezier::scale (Real x
, Real y
)
193 for (int i
= CONTROL_COUNT
; i
--;)
195 control_
[i
][X_AXIS
] = x
* control_
[i
][X_AXIS
];
196 control_
[i
][Y_AXIS
] = y
* control_
[i
][Y_AXIS
];
201 Bezier::rotate (Real phi
)
203 Offset
rot (complex_exp (Offset (0, phi
)));
204 for (int i
= 0; i
< CONTROL_COUNT
; i
++)
205 control_
[i
] = complex_multiply (rot
, control_
[i
]);
209 Bezier::translate (Offset o
)
211 for (int i
= 0; i
< CONTROL_COUNT
; i
++)
216 Bezier::assert_sanity () const
218 for (int i
=0; i
< CONTROL_COUNT
; i
++)
219 assert (!isnan (control_
[i
].length ())
220 && !isinf (control_
[i
].length ()));
227 for (int i
=0; i
< CONTROL_COUNT
; i
++)
228 b2
.control_
[CONTROL_COUNT
-i
-1] = control_
[i
];