From d4eeffef422b68e35e232a8688693d06db7c0e49 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Sat, 28 Aug 2004 13:32:37 +0000 Subject: [PATCH] * ly/engraver-init.ly (AncientRemoveEmptyStaffContext): set bassStaffProperties to \clef bass. * lily/auto-change-iterator.cc (construct_children): instantiate up/down Staff, create Voice on up staff initially. Obviates explicit instantiation of up/down contexts for \autochange. * lily/slur-quanting.cc (get_bezier): new functionality, blow up slur depending on extents of note heads. --- ChangeLog | 12 +++ lily/auto-change-iterator.cc | 30 +++++- lily/bezier-bow.cc | 21 +++- lily/include/bezier-bow.hh | 3 +- lily/new-slur.cc | 11 +- lily/slur-quanting.cc | 165 ++++++++++++++++++++++++------ ly/engraver-init.ly | 4 + scm/define-context-properties.scm | 4 + scm/define-grob-properties.scm | 4 +- scm/slur.scm | 4 +- 10 files changed, 211 insertions(+), 47 deletions(-) diff --git a/ChangeLog b/ChangeLog index 885e52087a..2929f9b3df 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2004-08-28 Han-Wen Nienhuys + + * ly/engraver-init.ly (AncientRemoveEmptyStaffContext): set + bassStaffProperties to \clef bass. + + * lily/auto-change-iterator.cc (construct_children): instantiate + up/down Staff, create Voice on up staff initially. Obviates + explicit instantiation of up/down contexts for \autochange. + + * lily/slur-quanting.cc (get_bezier): new functionality, blow up + slur depending on extents of note heads. + 2004-08-28 Graham Percival * Documentation/user/tutorial.itely: minor editing. diff --git a/lily/auto-change-iterator.cc b/lily/auto-change-iterator.cc index 7b73db03ca..e4966b9dca 100644 --- a/lily/auto-change-iterator.cc +++ b/lily/auto-change-iterator.cc @@ -21,6 +21,7 @@ public: Auto_change_iterator (); protected: + virtual void do_quit (); virtual void construct_children (); virtual void process (Moment); Array pending_pitch (Moment)const; @@ -29,6 +30,10 @@ private: Direction where_dir_; void change_to (Music_iterator* , SCM, String); Moment start_moment_; + + Interpretation_context_handle up_; + Interpretation_context_handle down_; + }; @@ -120,9 +125,32 @@ Auto_change_iterator::Auto_change_iterator () void Auto_change_iterator::construct_children () { - Music_wrapper_iterator::construct_children (); split_list_ = get_music ()->get_property ("split-list"); start_moment_ = get_outlet ()->now_mom (); + + SCM props = get_outlet()->get_property ("trebleStaffProperties"); + Context *up = get_outlet()->find_create_context (ly_symbol2scm ("Staff"), + "up", props); + + props = get_outlet()->get_property ("bassStaffProperties"); + Context *down = get_outlet()->find_create_context (ly_symbol2scm ("Staff"), + "down", props); + + up_.set_translator (up); + down_.set_translator (down); + + Context *voice = up->find_create_context (ly_symbol2scm ("Voice"), + "", SCM_EOL); + set_translator (voice); + Music_wrapper_iterator::construct_children (); + } +void +Auto_change_iterator::do_quit() +{ + up_.set_translator (0); + down_.set_translator (0); + +} IMPLEMENT_CTOR_CALLBACK (Auto_change_iterator); diff --git a/lily/bezier-bow.cc b/lily/bezier-bow.cc index 85d116e78c..7d7b640a54 100644 --- a/lily/bezier-bow.cc +++ b/lily/bezier-bow.cc @@ -83,17 +83,30 @@ height */ +void +get_slur_indent_height (Real * indent, Real *height, + Real width, Real h_inf, Real r_0) +{ + *height = slur_height (width, h_inf, r_0); + *indent = (width/(h_inf+ width)*1.5 + 0.5) * (*height); +} + + + + Bezier slur_shape (Real width, Real h_inf, Real r_0) { - Bezier curve; - Real height = slur_height (width, h_inf, r_0); - Real indent = (width/(h_inf+ width)*1.5 + 0.5) * height; + Real indent; + Real height; + + get_slur_indent_height (&indent, &height, + width, h_inf, r_0); + Bezier curve; curve.control_[0] = Offset (0, 0); curve.control_[1] = Offset (indent, height); curve.control_[2] = Offset (width - indent, height); curve.control_[3] = Offset (width, 0); return curve; } - diff --git a/lily/include/bezier-bow.hh b/lily/include/bezier-bow.hh index 26d1cd85e8..a53ad18d4c 100644 --- a/lily/include/bezier-bow.hh +++ b/lily/include/bezier-bow.hh @@ -19,7 +19,6 @@ Bezier slur_shape (Real width, Real height_limit, Real height_proportion); Real slur_height (Real width, Real height_limit, Real height_proportion); - - +void get_slur_indent_height (Real * indent, Real *height, Real width, Real h_inf, Real r_0); #endif /* BEZIER_BOW_HH */ diff --git a/lily/new-slur.cc b/lily/new-slur.cc index 78b569053e..5896714233 100644 --- a/lily/new-slur.cc +++ b/lily/new-slur.cc @@ -126,11 +126,6 @@ New_slur::add_extra_encompass (Grob*me, Grob*n) } -ADD_INTERFACE (New_slur, "new-slur-interface", - "A slur", - "encompass-objects control-points dashed details direction height-limit note-columns ratio thickness"); - - MAKE_SCHEME_CALLBACK (New_slur, outside_slur_callback, 2); SCM @@ -181,3 +176,9 @@ New_slur::outside_slur_callback (SCM grob, SCM axis) } return scm_make_real (0.0); } + + +ADD_INTERFACE (New_slur, "new-slur-interface", + "A slur", + "excentricity encompass-objects control-points dashed details direction height-limit note-columns ratio thickness"); + diff --git a/lily/slur-quanting.cc b/lily/slur-quanting.cc index a750086ccd..9f9bde87b7 100644 --- a/lily/slur-quanting.cc +++ b/lily/slur-quanting.cc @@ -51,7 +51,7 @@ struct Slur_score */ struct Slur_score_parameters { - int slur_region_size_; + int region_size_; Real head_encompass_penalty_; Real stem_encompass_penalty_; Real closeness_factor_; @@ -59,7 +59,6 @@ struct Slur_score_parameters Real same_slope_penalty_; Real steeper_slope_factor_; Real non_horizontal_penalty_; - Real head_strict_free_space_; Real max_slope_; Real max_slope_factor_; Real extra_object_collision_; @@ -116,7 +115,9 @@ struct Bound_info } }; - +/* + TODO: create one object for passing all parameters. + */ static void @@ -147,15 +148,20 @@ static Bezier avoid_staff_line (Grob *me, Grob **common, static Encompass_info get_encompass_info (Grob *me, Grob *col, Grob **common); -static Bezier get_bezier (Grob *me, Drul_array, Real, Real); +static Bezier get_bezier (Grob *me, + Grob **common, + Slur_score_parameters*, + Drul_array extremes, + Drul_array attachments, + Real r_0, Real h_inf); static Direction get_default_dir (Grob *me); static void set_end_points (Grob *); static Real broken_trend_y (Grob *me, Grob **, Direction dir); static Drul_array get_bound_info (Spanner *me, Grob **common); -static void generate_curves (Grob *me, - Grob *common[], +static void generate_curves (Grob *me, + Grob *common[],Slur_score_parameters*, Drul_array extremes, Drul_array base_attach, Array *scores); @@ -166,7 +172,9 @@ static Array enumerate_attachments static Drul_array get_base_attachments (Spanner *sp, Grob **common, Drul_array extremes); static Drul_array get_y_attachment_range -(Spanner *sp, Grob **common, Drul_array extremes, +(Spanner *sp, Grob **common, + Slur_score_parameters*, + Drul_array extremes, Drul_array base_attachment); @@ -186,8 +194,8 @@ init_score_param (Grob *me, { SCM details = me->get_property ("slur-details"); - score_param->slur_region_size_ - = (int) get_detail (details, ly_symbol2scm ("slur-region-size")); + score_param->region_size_ + = (int) get_detail (details, ly_symbol2scm ("region-size")); score_param->head_encompass_penalty_ = get_detail (details, ly_symbol2scm ("head-encompass-penalty")); score_param->stem_encompass_penalty_ @@ -202,8 +210,6 @@ init_score_param (Grob *me, = get_detail (details, ly_symbol2scm ("steeper-slope-factor")); score_param->non_horizontal_penalty_ = get_detail (details, ly_symbol2scm ("non-horizontal-penalty")); - score_param->head_strict_free_space_ - = get_detail (details, ly_symbol2scm ("head-strict-free-space")); score_param->max_slope_ = get_detail (details, ly_symbol2scm ("max-slope")); score_param->max_slope_factor_ @@ -379,19 +385,6 @@ New_slur::after_line_breaking (SCM smob) return SCM_UNSPECIFIED; } -Bezier -get_bezier (Grob *me, Drul_array extremes, Real r_0, Real h_inf) -{ - Array encompasses; - encompasses.push (extremes[LEFT]); - encompasses.push (extremes[RIGHT]); - - Slur_bezier_bow bb (encompasses, - get_grob_direction (me), h_inf, r_0); - - return bb.get_bezier (); -} - Drul_array get_bound_info (Spanner* me, Grob **common) { @@ -467,14 +460,14 @@ set_end_points (Grob *me) Drul_array extremes = get_bound_info (sp, common); Drul_array base_attachment = get_base_attachments (sp, common, extremes); - Drul_array end_ys - = get_y_attachment_range (sp, common, extremes, base_attachment); Slur_score_parameters params (me); + Drul_array end_ys + = get_y_attachment_range (sp, common, ¶ms, extremes, base_attachment); Array scores = enumerate_attachments (me, common, ¶ms, extremes, base_attachment, end_ys); - generate_curves (me, common, extremes, base_attachment, &scores); + generate_curves (me, common, ¶ms, extremes, base_attachment, &scores); score_edges (me, common, ¶ms,extremes, base_attachment, &scores); score_slopes (me, common, ¶ms,extremes, base_attachment, &scores); score_encompass (me, common, ¶ms,extremes, base_attachment, &scores); @@ -533,10 +526,14 @@ set_end_points (Grob *me) me->set_property ("control-points", controls); } +/* + TODO: should analyse encompasses to determine sensible region, and + should limit slopes available. + */ Drul_array get_y_attachment_range (Spanner*me, - Grob **common, + Grob **common, Slur_score_parameters *score_param, Drul_array extremes, Drul_array base_attachment) { @@ -548,13 +545,13 @@ get_y_attachment_range (Spanner*me, if (extremes[d].note_column_) { end_ys[d] = dir - * ((dir * (base_attachment[d][Y_AXIS] + 4.0 * dir)) + * ((dir * (base_attachment[d][Y_AXIS] + score_param->region_size_* dir)) >? (dir * (dir + extremes[d].note_column_->extent(common[Y_AXIS], Y_AXIS)[dir])) >? (dir * base_attachment[-d][Y_AXIS])); } else - end_ys[d] = extremes[d].neighbor_y_ + 4.0 * dir; + end_ys[d] = extremes[d].neighbor_y_ + score_param->region_size_ * dir; } while (flip (&d) != LEFT); @@ -648,6 +645,7 @@ get_base_attachments (Spanner *me, void generate_curves (Grob *me, Grob **common, + Slur_score_parameters *score_param, Drul_array extremes, Drul_array, Array *scores) @@ -659,7 +657,11 @@ generate_curves (Grob *me, Grob **common, Real h_inf = staff_space * ly_scm2double (me->get_property ("height-limit")); for (int i = 0; i < scores->size(); i++) { - Bezier bez= get_bezier (me, (*scores)[i].attachment_, r_0, h_inf); + Bezier bez= get_bezier (me, + common, + score_param, + extremes, + (*scores)[i].attachment_, r_0, h_inf); bez = avoid_staff_line (me, common, extremes, bez); (*scores)[i].attachment_[LEFT] = bez.control_[0]; (*scores)[i].attachment_[RIGHT] = bez.control_[3]; @@ -1140,4 +1142,105 @@ score_slopes (Grob *me, Grob *common[], } +Real +fit_factor (Offset dz_unit, Offset dz_perp, + Bezier curve, Direction d, Array const &avoid) +{ + Real fit_factor = 0.0; + Offset x0 = curve.control_[0]; + curve.translate (-x0); + curve.rotate (-dz_unit.arg ()); + curve.scale (1, d); + + Interval curve_xext; + curve_xext.add_point (curve.control_[0][X_AXIS]); + curve_xext.add_point (curve.control_[3][X_AXIS]); + + for (int i = 0; i < avoid.size (); i++) + { + Offset z = (avoid[i] - x0) ; + Offset p (dot_product (z, dz_unit), + d* dot_product (z, dz_perp)); + if (!curve_xext.contains (p[X_AXIS])) + continue; + + Real y = curve.get_other_coordinate (X_AXIS, p[X_AXIS]); + if (y) + { + fit_factor = fit_factor >? (p[Y_AXIS] / y); + } + } + return fit_factor; +} + + +Bezier +get_bezier (Grob *me, + Grob **common, + Slur_score_parameters *score_param, + Drul_array extremes, + Drul_array attachments, + Real r_0, Real h_inf) +{ + Link_array encompasses + = Pointer_group_interface__extract_grobs (me, (Grob *)0, "note-columns"); + Direction dir = get_grob_direction (me); + + Array avoid; + for (int i = 0; i < encompasses.size(); i++) + { + if (extremes[LEFT].note_column_ == encompasses[i] + ||extremes[RIGHT].note_column_ == encompasses[i]) + continue; + + Encompass_info inf (get_encompass_info (me, encompasses[i], common)); + avoid.push (Offset (inf.x_, inf.head_ + dir * score_param->free_head_distance_)); + } + + Offset dz = attachments[RIGHT]- attachments[LEFT];; + Offset dz_unit = dz; + dz_unit *= 1 / dz.length(); + Offset dz_perp = dz_unit * Offset(0,1); + + Real indent, height; + get_slur_indent_height (&indent, &height, dz.length (), h_inf, r_0); + + Real excentricity = robust_scm2double (me->get_property ("excentricity"), 0.0); + Bezier curve; + Real x1 = (excentricity + indent); + Real x2 = (excentricity - indent); + curve.control_[0] = attachments[LEFT]; + curve.control_[1] = attachments[LEFT] + dz_perp * height * dir + dz_unit * x1; + curve.control_[2] = attachments[RIGHT] + dz_perp * height * dir + dz_unit * x2; + curve.control_[3] = attachments[RIGHT]; + + + Real ff = fit_factor (dz_unit, dz_perp, curve, dir, avoid); + Real l = dz.length (); + + /* + This condition, + + l^2 > 4h^2 + 3(i 1/3l)^2 - 1/3 l^2 + + is equivalent to: + + |bez'(0)| < | bez'(.5)| + + when (control2-control1) has the same direction as (control3 - + control0). + + */ + Real max_h = sqrt (sqr (l)/3 - .75 * sqr (indent + l / 3)); + height = height >? ((height * ff)