From 165ac5f938f67e73c381c1b1b7f6e6412ce0765d Mon Sep 17 00:00:00 2001 From: fred Date: Tue, 26 Mar 2002 22:46:07 +0000 Subject: [PATCH] lilypond-1.3.28 --- lily/bezier-bow.cc | 207 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 194 insertions(+), 13 deletions(-) diff --git a/lily/bezier-bow.cc b/lily/bezier-bow.cc index 0cfd5a070e..3565cddb31 100644 --- a/lily/bezier-bow.cc +++ b/lily/bezier-bow.cc @@ -50,28 +50,206 @@ Bezier_bow::Bezier_bow (Array points, Direction dir) ratio_ = 1.0; } +static Real +default_height (Real len) +{ + // assume 20pt staff + // see fonts.doc + Real staff_space = 5.0; + Real h_inf = 2.0* staff_space; + Real r_0 = 0.33; + return h_inf * 2.0 / M_PI * atan ( M_PI * r_0 / (2.0 * h_inf) * len); +} + void Bezier_bow::blow_fit () { - Real len = curve_.control_[3][X_AXIS] ; - Real ind = curve_.control_[1][X_AXIS] / len; + Real len = curve_.control_[3][X_AXIS]; Real h = curve_.control_[1][Y_AXIS] * fit_factor () / len; + curve_.control_[1][Y_AXIS] = h * len; + curve_.control_[2][Y_AXIS] = h * len; + curve_.check_sanity (); +} + +void +Bezier_bow::de_uglyfy () +{ + Real len = curve_.control_[3][X_AXIS] ; + Real ff = fit_factor (); + for (int i = 1; i < 3; i++) + { + Real ind = abs (curve_.control_[(i-1)*3][X_AXIS] + - curve_.control_[i][X_AXIS]) / len; + Real h = curve_.control_[i][Y_AXIS] * ff / len; + + // ugh. Unhardcode this +#if 0 + // Too crude. + if (h > 4 * ind) + { + h = 4* ind; + } +#else + Real f = default_height (len) / len; + if (h > 2.0 * f) + { + h = 2.0 * f; + } +#endif + + if (h > 0.8 + -2 * ind) + { + h = 0.8 - 2 *ind; + } + + curve_.control_[i][Y_AXIS] = h * len; + } + + curve_.check_sanity (); +} + +Real +Bezier_bow::calc_enclosed_area_f () const +{ + Real a = 0; + for (int i=0; i < encompass_.size (); i++) + { + Interval x; + Interval y; + if (i == 0) + { + x = Interval (0, encompass_[1][X_AXIS] / 2); + y = Interval (0, + curve_.get_other_coordinate (X_AXIS, + encompass_[1][X_AXIS] + / 2)); + } + else if (i == encompass_.size () - 1) + { + x = Interval ((encompass_[i-1][X_AXIS] + encompass_[i][X_AXIS])/2, + encompass_[i][X_AXIS]); + y = Interval (0, + (curve_.get_other_coordinate (X_AXIS, + (x[MIN] + x[MAX]) / 2))); + } + else + { + x = Interval ((encompass_[i-1][X_AXIS] + encompass_[i][X_AXIS]) / 2, + (encompass_[i][X_AXIS] + encompass_[i+1][X_AXIS]) / 2); + y = Interval (encompass_[i][Y_AXIS], + (curve_.get_other_coordinate (X_AXIS, x[MIN]) + + curve_.get_other_coordinate (X_AXIS, + (x[MIN] + x[MAX]) / 2) + + curve_.get_other_coordinate (X_AXIS, x[MAX])) / 3); + } + + Real da = x.length () * y.length (); + a += da; + } + return a; +} - // ugh. Unhardcode this - if (h > 4 * ind) +Array +Bezier_bow::area_gradient_offset_arr () +{ + Real len = curve_.control_[3][X_AXIS]; + Real area = calc_enclosed_area_f (); + + Real grow = len / 10.0; + Array da (2); + for (int i=1; i < 3; i++) { - h = 4* ind; + for (Axis a=X_AXIS; a < NO_AXES; incr (a)) + { + Real r = curve_.control_[i][a]; + curve_.control_[i][a] += grow; + da[i-1][a] = (calc_enclosed_area_f () - area) / grow; + + curve_.control_[i][a] = r; + } } + return da; +} - if (h > 0.8 + -2 * ind) +void +Bezier_bow::minimise_enclosed_area () +{ + Real len = curve_.control_[3][X_AXIS]; + Real beautiful = len * default_height (len) / 2.0; + + DEBUG_OUT << to_str ("Beautiful: %f\n", beautiful); + DEBUG_OUT << to_str ("Length: %f\n", len); + int steps=2; + for (int i=0; i < steps; i++) { - h = 0.8 - 2 *ind; + Real ff = fit_factor (); + if (!ff) + break; + + DEBUG_OUT << to_str ("FitFac: %f\n", ff); + + // slur must be higher at every point + if (ff > 1.01) + { + blow_fit (); + DEBUG_OUT << to_str ("Blown area: %f\n", calc_enclosed_area_f ()); + } + else + DEBUG_OUT << to_str ("Init area: %f\n", calc_enclosed_area_f ()); + + Real area = calc_enclosed_area_f (); + + + if (area <= beautiful) + break; + + Array da = area_gradient_offset_arr (); + + /* + Urg: empiric cs + Small slurs are easily too asymmetric, + while big slurs are too symmetric + + This makes short slurs strictly x-bound, + long slurs become y-bound. + */ + Real ypct = 0.50; + //Real xpct = (0.07 * len * len / 1000.0) 1.5) + blow_fit (); + + DEBUG_OUT << to_str ("Exarea: %f\n", calc_enclosed_area_f ()); + Real area = calc_enclosed_area_f (); + /* + Slurs that fit beautifully are not ugly + */ + if (area > beautiful) + { + DEBUG_OUT << "DE-UGLYFY\n"; + de_uglyfy (); + } + } void @@ -81,7 +259,8 @@ Bezier_bow::calculate () if (fit_factor () > 1.0) { // calc_tangent_controls (); - blow_fit (); + // blow_fit (); + minimise_enclosed_area (); } } @@ -202,7 +381,8 @@ Bezier_bow::calc_tangent_controls () } /* - The maximum amount that the encompass points stick out above the bezier curve. + max ( encompass.y / curve.y ) + */ Real Bezier_bow::fit_factor () const @@ -210,7 +390,7 @@ Bezier_bow::fit_factor () const Real x1 = encompass_[0][X_AXIS]; Real x2 = encompass_.top ()[X_AXIS]; - Real factor = 1.0; + Real factor = 0.0; for (int i=1; i < encompass_.size ()-1; i++) { if (encompass_[i][X_AXIS] > x1 && encompass_[i][X_AXIS] < x2) @@ -288,3 +468,4 @@ Bezier_bow::calc_default () + -- 2.39.5