]> git.donarmstrong.com Git - lilypond.git/commitdiff
* input/regression/tie-chord.ly: use generateTiePattern to
authorHan-Wen Nienhuys <hanwen@xs4all.nl>
Fri, 20 Jan 2006 17:38:34 +0000 (17:38 +0000)
committerHan-Wen Nienhuys <hanwen@xs4all.nl>
Fri, 20 Jan 2006 17:38:34 +0000 (17:38 +0000)
simplify file.

* lily/tie-formatting-problem.cc (peak_around): new function.
(score_configuration): use sliding criterion for staff line collisions.
(score_configuration): idem for dot collisions.
(generate_configuration): use separate stem_gap for gap to stem.

* lily/include/tie-formatting-problem.hh (struct Tie_details):
separate penalty factors for x and y distance.
(struct Tie_details): separate penalties for tip and center line collisions.

ChangeLog
input/regression/tie-chord.ly
lily/include/tie-formatting-problem.hh
lily/tie-formatting-problem.cc
lily/tie-helper.cc
scm/define-grobs.scm

index 31fa0c1a720b3e89986f47b8a05e0eb61a099538..2d481225fb1e2295c9972f30d4fc5d932d772fd8 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,17 @@
-<<<<<<< ChangeLog
+2006-01-20  Han-Wen Nienhuys  <hanwen@xs4all.nl>
+
+       * input/regression/tie-chord.ly: use generateTiePattern to
+       simplify file.
+
+       * lily/tie-formatting-problem.cc (peak_around): new function.
+       (score_configuration): use sliding criterion for staff line collisions. 
+       (score_configuration): idem for dot collisions.
+       (generate_configuration): use separate stem_gap for gap to stem.
+
+       * lily/include/tie-formatting-problem.hh (struct Tie_details):
+       separate penalty factors for x and y distance.
+       (struct Tie_details): separate penalties for tip and center line collisions.
+
 2006-01-19 Han-Wen Nienhuys  <hanwen@xs4all.nl>
 
        * lily/tie-formatting-problem.cc (generate_configuration): make
        * lily/staff-symbol-referencer.cc (on_line): rename from
        on_staffline 
 
-=======
 2006-01-18  Han-Wen Nienhuys  <hanwen@xs4all.nl>
 
        * ly/music-functions-init.ly: remove duplicate tag.
 
        * lily/include/*.hh: GCC 4.1 fixes.
 
->>>>>>> 1.4455
 006-01-16  Erlend Aasland  <erlenda@gmail.com>
 
        * Documentation/user/global.itely: fix typos; @bugs -> @refbugs
index 74b448a0273270e659a77c566217007ac6581365..d6035a0ea61c3256b332e8a8eebef11c9f386780 100644 (file)
@@ -20,54 +20,84 @@ each system.  "
   raggedright = ##t
 }
 
+
+
+generateTiePattern
+= #(def-music-function (parser location is-long chords) (boolean? ly:music?)
+
+    "
+
+translate x y z to x~x y~y z~z
+
+" 
+    
+  (define (chord->tied-chord chord)
+    (let*
+       ((ch1 (ly:music-deep-copy chord))
+        (ch2 (ly:music-deep-copy chord))
+        (dur1 (ly:make-duration
+               (if is-long
+                   1 2)))
+        (dur2 (ly:make-duration
+               (if is-long
+                   3 2))))
+
+      (for-each (lambda (e)
+                 (ly:music-set-property! e 'duration dur1))
+               (ly:music-property ch1 'elements))
+
+      (for-each (lambda (e)
+                 (ly:music-set-property! e 'duration dur2))
+               (ly:music-property ch2 'elements))
+      
+      (set! (ly:music-property ch1 'elements)
+           (cons
+            (make-music 'TieEvent)
+            (ly:music-property ch1 'elements)))
+
+      (list ch1 ch2)))
+
+  (make-music 'SequentialMusic 'elements (apply append
+                                               (map chord->tied-chord (ly:music-property  chords 'elements)))))
+
+baseChords =
+\applyMusic #(lambda (mus)
+             (ly:music-property mus 'element))
+\relative c'' {
+  <c e>  
+  <b c e>
+  <a c e>
+  <a b e>
+  <a b e f>
+  <a c d f>
+  <a c e f>
+  <f a e f>
+  <c e f a> 
+  <c e g a>
+  <f b e a>
+}
+
 testShort =
 {
-   \time 4/4
   \key c \major
-  \relative c'' {
-                               %  c ~ c
-    <c e> ~ <c e>
-    <b c e> ~ <b c e>
-    <a c e> ~ <a c e>
-    <a b e> ~ <a b e>
-    <a b e f> ~ <a b e f> 
-  }
-
-  \relative c' {
-    <c e f a> ~ <c e f a>
-    <c e g a> ~ <c e g a>
-    
-    <a' c d f> ~ <a c d f>  
-    <a c e f> ~ <a c e f>
-    <f b e a>4 ~ <f b e a>
-  }
+  \generateTiePattern ##f \baseChords
 }  
 
 testLong =
 {
-  \time 5/8
   \key c \major
-  \relative c'' {
-    <c e>2 ~ <c e>8
-    <b c e>2 ~ <b c e>8
-    <a c e>2 ~ <a c e>8
-    <a b e>2 ~ <a b e>8
-    <a b e f>2 ~ <a b e f>8
-  }
-
-  \relative c' {
-    <c e f a>2 ~ <c e f a>8
-    <c e g a>2 ~ <c e g a>8
-    <a' c d f>2  ~ <a c d f>8  
-    <a c e f>2  ~ <a c e f>8  
-    <f b e a>2 ~ <f b e a>8
-  }
+  \generateTiePattern ##t \baseChords
 }  
 
 \new Voice
-{ \testShort \break
+{
+  \time 2/4
+
+  \testShort \break
   \transpose c d \testShort \break
+  \time 5/8
   \testLong \break
   \transpose c d \testLong \break
 }
 
+
index 3325d5338043c44914c7190289b5bbed800f8d79..f311ef682cf9674d57aa00ff8571cb18cd9846ec 100644 (file)
@@ -25,18 +25,22 @@ struct Tie_details
   Real ratio_;
   Real staff_space_;
   Real x_gap_;
+  Real stem_gap_; 
   Real between_length_limit_;
   Real wrong_direction_offset_penalty_;
-  Real distance_penalty_factor_;
   Real length_penalty_factor_;
   Real min_length_;
-  Real staff_line_clearance_;
+  Real tip_staff_line_clearance_;
+  Real center_staff_line_clearance_;
   Real staff_line_collision_penalty_;
   Real dot_collision_clearance_;
   Real dot_collision_penalty_;
   Real tie_column_monotonicity_penalty_;
   Real tie_tie_collision_penalty_;
   Real tie_tie_collision_distance_;
+  Real horizontal_distance_penalty_factor_;
+  Real vertical_distance_penalty_factor_;
+  Real intra_space_threshold_;
   
   Grob *staff_symbol_referencer_;
   
@@ -71,6 +75,7 @@ struct Tie_configuration_variation
 class Tie_formatting_problem
 {
   Drul_array< Array<Skyline_entry> > chord_outlines_;
+  Drul_array< Box > stem_extents_;
   set<int> dot_positions_;
   Interval dot_x_;
   Array<Tie_specification> specifications_;
index 03293c564b221cba7d79bab2e920ff18be951b66..91a96d48b12cd86a4df6da1dd6eb3e66b6c89db2 100644 (file)
 #include "tie.hh"
 #include "warn.hh"
 
+/*
+   0 at threshold,  1 at 0, with 1/x falloff.
+ */
+Real peak_around (Real epsilon,  Real threshold, Real x)
+{
+  if (x < 0)
+    return 1.0;
+  return max (- epsilon * (x - threshold) / ((x + epsilon)  * threshold), 0.0);
+}
+
 Interval
 Tie_formatting_problem::get_attachment (Real y) const
 {
@@ -116,7 +126,7 @@ Tie_formatting_problem::set_chord_outline (Link_array<Item> bounds,
          
       insert_extent_into_skyline (&chord_outlines_[d], Box (x,y), Y_AXIS, -d);
 
-
+      stem_extents_[d].unite (Box (x,y));
 
       if (d == LEFT)
        {
@@ -155,7 +165,6 @@ Tie_formatting_problem::from_tie (Grob *tie)
 {
   Link_array<Grob> ties;
   ties.push (tie);
-
   from_ties (ties);
 
   details_.from_grob (tie);
@@ -313,15 +322,20 @@ Tie_formatting_problem::generate_configuration (int pos, Direction dir) const
   Real h =  conf->height (details_);
   if (!conf->delta_y_)
     {
-      if (h < 0.5 * details_.staff_space_)
+      /*
+       TODO: make sliding criterion?  
+       */
+      if (h < details_.intra_space_threshold_ * 0.5 * details_.staff_space_)
        {
-         if (!Staff_symbol_referencer::on_line (details_.staff_symbol_referencer_, pos))
+         if (!Staff_symbol_referencer::on_line (details_.staff_symbol_referencer_, pos)
+             && fabs (pos) < 2 * Staff_symbol_referencer::staff_radius (details_.staff_symbol_referencer_))
            {
              conf->center_tie_vertically (details_);
            }
          else if (Staff_symbol_referencer::on_line (details_.staff_symbol_referencer_, pos))
            {
-             conf->delta_y_ += dir * 0.2 * details_.staff_space_;
+             conf->delta_y_ += dir *
+               details_.tip_staff_line_clearance_ * 0.5 *  details_.staff_space_;
            }
        }
       else 
@@ -331,7 +345,7 @@ Tie_formatting_problem::generate_configuration (int pos, Direction dir) const
          int round_pos = int (my_round (top_pos));
 
          /* TODO: should use other variable? */
-         Real clearance = details_.staff_line_clearance_;
+         Real clearance = details_.center_staff_line_clearance_;
          if (fabs (top_pos - round_pos) < clearance
              && Staff_symbol_referencer::on_staff_line (details_.staff_symbol_referencer_,
                                                         round_pos))
@@ -342,7 +356,22 @@ Tie_formatting_problem::generate_configuration (int pos, Direction dir) const
        }
     }
   
+  conf->attachment_x_ = get_attachment (y + conf->delta_y_);
   conf->attachment_x_.widen ( - details_.x_gap_);
+
+  Direction d = LEFT;
+  do
+    {
+      Real y = conf->position_ * details_.staff_space_ * 0.5 + conf->delta_y_;
+      if (stem_extents_[d][X_AXIS].is_empty ()
+         || !stem_extents_[d][Y_AXIS].contains (y))
+       continue;
+
+      conf->attachment_x_[d] =
+       d* min (d * conf->attachment_x_[d],
+               d * (stem_extents_[d][X_AXIS][-d] - d * details_.stem_gap_));
+    }
+  while (flip (&d) != LEFT);
   return conf;
 }
 
@@ -356,7 +385,21 @@ Tie_formatting_problem::score_aptitude (Tie_configuration const &conf,
   if (sign (curve_y - tie_y) != conf.dir_)
     penalty += details_.wrong_direction_offset_penalty_;
 
-  penalty += details_.distance_penalty_factor_ * fabs (curve_y - tie_y);
+  penalty += details_.vertical_distance_penalty_factor_ * fabs (curve_y - tie_y);
+
+
+  Direction d = LEFT;
+  do
+    {
+      if (!spec.note_head_drul_[d])
+       continue;
+      
+      Interval head_x = spec.note_head_drul_[d]->extent (x_refpoint_, X_AXIS);
+      Real dist = head_x.distance (conf.attachment_x_[d]);
+      penalty += details_.horizontal_distance_penalty_factor_ * dist;
+    }
+  while  (flip (&d) != LEFT);
+
   return penalty;
 }
 
@@ -375,19 +418,24 @@ Tie_formatting_problem::score_configuration (Tie_configuration const &conf) cons
   Real top_y = tip_y + conf.dir_ * height;
   Real top_pos = 2 * top_y / details_.staff_space_;
   Real round_top_pos = rint (top_pos);
-  if (fabs (top_pos - round_top_pos) < details_.staff_line_clearance_
-      && Staff_symbol_referencer::on_line (details_.staff_symbol_referencer_,
+  if (Staff_symbol_referencer::on_line (details_.staff_symbol_referencer_,
                                                int (round_top_pos))
       && Staff_symbol_referencer::staff_radius (details_.staff_symbol_referencer_) > top_y)
     {
-      penalty += details_.staff_line_collision_penalty_;
+      penalty +=
+       details_.staff_line_collision_penalty_
+       * peak_around (0.1 * details_.center_staff_line_clearance_,
+                    details_.center_staff_line_clearance_,
+                    fabs (top_pos - round_top_pos));
     }
   
-  if (fabs (tip_pos - rint (tip_pos)) < details_.staff_line_clearance_
-      && Staff_symbol_referencer::on_line (details_.staff_symbol_referencer_,
-                                          int (rint (tip_pos))))
+  if (Staff_symbol_referencer::on_line (details_.staff_symbol_referencer_,
+                                       int (rint (tip_pos))))
     {
-      penalty += details_.staff_line_collision_penalty_;
+      penalty += details_.staff_line_collision_penalty_
+       * peak_around (0.1 * details_.tip_staff_line_clearance_,
+                      details_.tip_staff_line_clearance_,
+                      fabs (tip_pos - rint (tip_pos)));
     }
 
   if (!dot_x_.is_empty ())
@@ -404,10 +452,11 @@ Tie_formatting_problem::score_configuration (Tie_configuration const &conf) cons
               i != dot_positions_.end (); i ++)
            {
              int dot_pos = (*i);
-             if (fabs (dot_pos * details_.staff_space_ * 0.5 - y) < details_.dot_collision_clearance_)
-               {
-                 penalty += details_.dot_collision_penalty_;
-               }
+             penalty +=
+               details_.dot_collision_penalty_
+               * peak_around (.1 * details_.dot_collision_clearance_,
+                              details_.dot_collision_clearance_,
+                              fabs (dot_pos * details_.staff_space_ * 0.5 - y)); 
            }
        }
     }
@@ -512,16 +561,18 @@ Tie_formatting_problem::score_ties_configuration (Ties_configuration const &ties
          if (edge <= last_edge)
            score += details_.tie_column_monotonicity_penalty_;
          if (center <= last_center)
-           score +=details_. tie_column_monotonicity_penalty_;
+           score += details_.tie_column_monotonicity_penalty_;
 
          score +=
-           details_.tie_tie_collision_penalty_
-           * max (details_.tie_tie_collision_distance_ - fabs (center - last_center), 0.0)
-           / details_.tie_tie_collision_distance_;
+           details_.tie_tie_collision_penalty_ *
+           peak_around (0.1 * details_.tie_tie_collision_distance_,
+                        details_.tie_tie_collision_distance_,
+                        fabs (center - last_center));
          score +=
-           details_.tie_tie_collision_penalty_
-           * max (details_.tie_tie_collision_distance_ - fabs (edge - last_edge), 0.0)
-           / details_.tie_tie_collision_distance_;
+           details_.tie_tie_collision_penalty_ *
+           peak_around (0.1 * details_.tie_tie_collision_distance_,
+                        details_.tie_tie_collision_distance_,
+                        fabs (edge - last_edge));
        }
 
       last_edge = edge;
@@ -570,12 +621,16 @@ Tie_formatting_problem::generate_base_chord_configuration ()
            * 0.5 * details_.staff_space_;
        }
       else
-       conf.position_ = specifications_[i].position_;
-      
+       {
+         conf.position_ = specifications_[i].position_;
+       }
       ties_config.push (conf);
     }
 
   set_ties_config_standard_directions (&ties_config);
+  for (int i = 0; i < ties_config.size (); i++)
+    if (!specifications_[i].manual_position_)
+      ties_config[i].position_ += ties_config[i].dir_;
 
   ties_config = generate_ties_configuration (ties_config);
   
@@ -589,7 +644,7 @@ Tie_formatting_problem::generate_optimal_chord_configuration ()
   Array<Tie_configuration_variation> vars = get_variations (base);
 
   Ties_configuration best = base;
-  Real best_score = score_ties_configuration (best);
+  Real best_score = score_ties (best);
 
   /*
     This simply is 1-opt: we have K substitions, and we try applying
@@ -600,8 +655,7 @@ Tie_formatting_problem::generate_optimal_chord_configuration ()
       Ties_configuration variant = base;
       variant[vars[i].index_] = *vars[i].suggestion_;
 
-      Real score = (score_ties_configuration (variant)
-                   + score_ties_aptitude (variant));
+      Real score = score_ties (variant);
       if (score < best_score)
        {
          best = variant;
@@ -682,7 +736,8 @@ Tie_formatting_problem::get_variations (Ties_configuration const &ties)
                {
                  Tie_configuration_variation var;
                  var.index_ = i;
-                 var.suggestion_ = get_configuration (ties[i].position_,
+                 var.suggestion_ = get_configuration (specifications_[i].position_
+                                                      - ties[i].dir_,
                                                       -ties[i].dir_);
 
                  vars.push (var);
@@ -692,8 +747,9 @@ Tie_formatting_problem::get_variations (Ties_configuration const &ties)
                {
                  Tie_configuration_variation var;
                  var.index_ = i-1;
-                 var.suggestion_ = get_configuration (ties[i-1].position_,
-                                                      -ties[i-1].dir_);
+                 var.suggestion_ = get_configuration (specifications_[i-1].position_
+                                                      - ties[i-1].dir_,
+                                                      - ties[i-1].dir_);
 
                  vars.push (var);
                }
@@ -703,8 +759,22 @@ Tie_formatting_problem::get_variations (Ties_configuration const &ties)
       last_center = center;
     }
 
+  /*  TODO: switch off? */
+  Direction d = DOWN;
+  do
+    {
+      if (ties.boundary (d, 0).dir_ == d)
+       {
+         Tie_configuration_variation var;
+         var.index_ = (d == DOWN) ? 0 : ties.size () - 1;
+         var.suggestion_ = get_configuration (ties.boundary (d, 0).position_ + d,
+                                              d);
+         vars.push (var);
+       }
+    }
+  while (flip (&d) !=  DOWN);
+
   return vars;
-  
 }
 
 void
index 6da15c0c3c221fc10fdcab316e3d8993fdfeb89f..2e3f4b826cfefa7f2afca6de29a1fdf9ca771c4d 100644 (file)
 #include "tie-formatting-problem.hh"
 
 
-#define get_real_detail(src, defvalue) robust_scm2double(ly_assoc_get (ly_symbol2scm (src), details, SCM_EOL), defvalue)
+/*
+  this is a macro because we want ly_symbol2scm() 
+ */
+#define get_real_detail(src, defvalue) \
+  robust_scm2double(ly_assoc_get (ly_symbol2scm (src), details, SCM_EOL), defvalue)
 
 void
 Tie_details::from_grob (Grob *me)
 {
   staff_symbol_referencer_ = me;
   staff_space_ = Staff_symbol_referencer::staff_space (me);
-  x_gap_ = robust_scm2double (me->get_property ("x-gap"), 0.2);
 
   SCM details = me->get_property ("details");
 
@@ -31,19 +34,24 @@ Tie_details::from_grob (Grob *me)
   between_length_limit_ = get_real_detail ("between-length-limit", 1.0);
   
   wrong_direction_offset_penalty_ = get_real_detail("wrong-direction-offset-penalty", 10);
-  distance_penalty_factor_ = get_real_detail("distance-penalty-factor", 5);
+  
   length_penalty_factor_ = get_real_detail("length-penalty-factor", 1.0);
   min_length_ = get_real_detail("min-length", 0.333);
 
   // in half-space
-  staff_line_clearance_ = get_real_detail ("staff-line-clearance", 0.4);
+  center_staff_line_clearance_ = get_real_detail ("center-staff-line-clearance", 0.4);
+  tip_staff_line_clearance_ = get_real_detail ("tip-staff-line-clearance", 0.4);
   staff_line_collision_penalty_ = get_real_detail("staff-line-collision-penalty", 5);
   dot_collision_clearance_ = get_real_detail ( "dot-collision-clearance", 0.25);
   dot_collision_penalty_ = get_real_detail ( "dot-collision-penalty", 0.25);
-
+  x_gap_ = get_real_detail ("note-head-gap", 0.2);
+  stem_gap_ = get_real_detail ("stem-gap", 0.3);
   tie_column_monotonicity_penalty_ = get_real_detail ("tie-column-monotonicity-penalty", 100);
   tie_tie_collision_penalty_ = get_real_detail ("tie-tie-collision-penalty", 30);
   tie_tie_collision_distance_ = get_real_detail ("tie-tie-collision-distance", .25);
+  horizontal_distance_penalty_factor_ = get_real_detail ("horizontal-distance-penalty-factor", 5);
+  vertical_distance_penalty_factor_ = get_real_detail ("vertical-distance-penalty-factor", 5);
+  intra_space_threshold_ = get_real_detail ("intra-space-threshold", 1.0);
 }
 
 Tie_details::Tie_details ()
index 0d3cab0815f40e473ea1473b2334f21304e5ac39..4eba1d8e238224cd3d41a62878c390f5c9887186 100644 (file)
        (direction . ,Tie::calc_direction)
        (stencil . ,Tie::print)
        (details . ((ratio . 0.333)
-                   (staff-line-clearance . 0.6)
+                   (center-staff-line-clearance . 0.6)
+                   (tip-staff-line-clearance . 0.45)
+                   (note-head-gap . 0.2)
+                   (stem-gap . 0.35)
                    (height-limit . 1.0)
+                   (horizontal-distance-penalty-factor . 10)
+                   (tie-tie-collision-distance . 0.45) 
+                   (tie-tie-collision-penalty . 25.0)
+                   (intra-space-threshold . 1.25)
                    (between-length-limit . 1.0)))
        (thickness . 1.0)
        (meta . ((class . Spanner)