]> git.donarmstrong.com Git - lilypond.git/commitdiff
* lily/tie-formatting-problem.cc (find_optimal_tie_configuration):
authorHan-Wen Nienhuys <hanwen@xs4all.nl>
Wed, 16 Nov 2005 15:54:43 +0000 (15:54 +0000)
committerHan-Wen Nienhuys <hanwen@xs4all.nl>
Wed, 16 Nov 2005 15:54:43 +0000 (15:54 +0000)
new function. Search region of 3 positions for best tie.
(score_configuration): new function.
(score_aptitude): new function.
(generate_configuration): new function.
(get_configuration): new function.
(Tie_formatting_problem): new function

* input/regression/page-top-space.ly: a6 for page-top-space demo.

* lily/include/tie-formatting-problem.hh (class
Tie_formatting_problem): add Tie_details to
Tie_formatting_problem. Update calling conventions.

ChangeLog
input/regression/page-top-space.ly
lily/include/tie-formatting-problem.hh
lily/include/tie.hh
lily/tie-formatting-problem.cc
lily/tie-helper.cc
lily/tie.cc

index a1d46bab139a52c96ad4a27a2f8aa9e9a5f3fa4f..47e2fc6435fed65b0af5d6a0462fb5738a85cc77 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,15 @@
 2005-11-16  Han-Wen Nienhuys  <hanwen@xs4all.nl>
 
+       * lily/tie-formatting-problem.cc (find_optimal_tie_configuration):
+       new function. Search region of 3 positions for best tie.
+       (score_configuration): new function.
+       (score_aptitude): new function.
+       (generate_configuration): new function.
+       (get_configuration): new function.
+       (Tie_formatting_problem): new function
+
+       * input/regression/page-top-space.ly: a6 for page-top-space demo. 
+
        * stepmake/aclocal.m4: use $(if ) for config-FOOF.make
 
        * THANKS: add Eduardo Vieira & Ralph Little
index 4e456773ce1d86993fc3f1108c51b401d3a13733..ef5db63dd1c7996b94269e410c89c304e700245b 100644 (file)
@@ -6,6 +6,8 @@ first system can be forced to be uniform."
 }
 \version "2.7.13"
 
+#(set-default-paper-size "a6")
+
 \book {
   \score {
 
index 5adda8bb6241e9ede3598dfaf912e1b907995823..c3cc58926f36474d1b0cf870cbfdd40fb8677ba7 100644 (file)
@@ -15,6 +15,8 @@
 #include "skyline.hh"
 #include "lily-proto.hh"
 
+#include <map>
+#include <set>
 
 struct Tie_details
 {
@@ -23,21 +25,37 @@ struct Tie_details
   Real staff_space_;
   Real x_gap_;
   Real between_length_limit_;
+  Grob *staff_symbol_referencer_;
   
   Tie_details ();
   void from_grob (Grob *);
 };
 
+
+typedef map< pair<int, int>, Tie_configuration *> Tie_configuration_map;
+
 class Tie_formatting_problem
 {
   Drul_array< Array<Skyline_entry> > chord_outlines_;
+  set<int> dot_positions_;
+  Tie_configuration_map possibilities_;
+
+  Tie_configuration *get_configuration (int position, Direction dir);
+  Tie_configuration *generate_configuration (int position, Direction dir);
+  Real score_configuration (Tie_configuration const&);
+  Real score_aptitude (Tie_configuration const&, int);
+  
   Grob *x_refpoint_;
+
+  
 public:
   Tie_details details_;
 
 public:
   Tie_formatting_problem ();
+  ~Tie_formatting_problem ();
 
+  Tie_configuration find_optimal_tie_configuration (int p, Direction d);
   void from_ties (Link_array<Grob> const &ties);
   void from_tie (Grob *tie);
   void from_lv_ties (Link_array<Grob> const &);
index 23c73a46c1e4baecedd63f06d391dfc62775184a..30be5796113207dfa0fcc11a93435ee0aea43263 100644 (file)
@@ -14,7 +14,6 @@
 #include "skyline.hh"
 
 
-
   
 class Tie_configuration
 {
@@ -45,10 +44,8 @@ class Ties_configuration
 {
 public:
   Array<Tie_configuration> ties_;
-
 };
 
-
 class Tie
 {
 public:
index d02593c28bc8fcfd23e1da9aab7f62c797eddd34..36c81fe0a2b1a4d25d0b42dc6e5d043814d37509 100644 (file)
@@ -34,13 +34,16 @@ Tie_formatting_problem::get_attachment (Real y) const
   return attachments;
 }
 
-
-
-
 Tie_formatting_problem::Tie_formatting_problem()
 {
   x_refpoint_ = 0;
-  
+}
+
+Tie_formatting_problem::~Tie_formatting_problem ()
+{
+  for (Tie_configuration_map::const_iterator i (possibilities_.begin ());
+       i != possibilities_.end (); i++)
+    delete (*i).second;
 }
 
 void
@@ -73,10 +76,13 @@ Tie_formatting_problem::set_chord_outline (Link_array<Item> bounds,
        {
          Interval x = dots->extent (x_refpoint_, X_AXIS);
          Interval y (-0.5, 0.5);
-         y.translate (Staff_symbol_referencer::get_position (dots));
-         y *= staff_space * 0.5;
+         int p = int (Staff_symbol_referencer::get_position (dots));
+         y.translate (p);
+
+         dot_positions_.insert (p);
          
-         boxes.push (Box (x, y));
+         y *= staff_space * 0.5;
+         // boxes.push (Box (x, y));
        }
     }
 
@@ -138,27 +144,6 @@ Tie_formatting_problem::set_chord_outline (Link_array<Item> bounds,
                                    Y_AXIS, -d);
     }
   while (flip (&updowndir) != DOWN);
-
-  for (int i = 0; i < bounds.size (); i++)
-    {
-      if (!Note_head::has_interface (bounds[i]))
-       continue;
-
-      
-      Grob *dots = unsmob_grob (bounds[i]->get_object ("dot"));
-      if (dots && d == LEFT)
-       {
-         Interval x = dots->extent (x_refpoint_, X_AXIS);
-         Real p = Staff_symbol_referencer::get_position (dots);
-             
-         Interval y (-1,1);
-         y *= (staff_space /4);
-         y.translate (p * staff_space * .5);
-
-         insert_extent_into_skyline (&chord_outlines_[d],
-                                     Box (x,y), Y_AXIS, -d);
-       }
-    }
 }
 
 
@@ -186,12 +171,13 @@ Tie_formatting_problem::from_ties (Link_array<Grob> const &ties)
     return;
   
   x_refpoint_ = ties[0];
-  details_.from_grob (ties[0]);
   for (int i = 0; i < ties.size (); i++)
     {
       x_refpoint_ = dynamic_cast<Spanner*> (ties[i])->get_bound (LEFT)->common_refpoint (x_refpoint_, X_AXIS); 
       x_refpoint_ = dynamic_cast<Spanner*> (ties[i])->get_bound (RIGHT)->common_refpoint (x_refpoint_, X_AXIS); 
     }
+
+  details_.from_grob (ties[0]);
   
   Direction d = LEFT;
   do
@@ -221,6 +207,9 @@ Tie_formatting_problem::from_lv_ties (Link_array<Grob> const &lv_ties)
   for (int i = 0; i < lv_ties.size (); i++)
     {
       Item *head = unsmob_item (lv_ties[i]->get_object ("note-head"));
+      if (!head)
+       continue;
+      
       heads.push (head);
     }
 
@@ -245,3 +234,147 @@ Tie_formatting_problem::from_lv_ties (Link_array<Grob> const &lv_ties)
   
   chord_outlines_[RIGHT].push (right_entry);
 }
+
+Tie_configuration*
+Tie_formatting_problem::get_configuration (int pos, Direction dir)
+{
+  pair<int,int> key (pos, dir);
+  Tie_configuration_map::const_iterator f = possibilities_.find (key);
+                                                             
+  if (f != possibilities_.end ())
+    {
+      return (*f).second;
+    }
+
+  
+  Tie_configuration *conf = generate_configuration (pos,dir);
+  possibilities_[key] = conf;
+  return conf;
+}
+
+Tie_configuration*
+Tie_formatting_problem::generate_configuration (int pos, Direction dir)
+{
+  Tie_configuration *conf = new Tie_configuration;
+  conf->position_ = pos;
+  conf->dir_ = dir;
+  Real y = conf->position_ * 0.5 * details_.staff_space_;
+
+  if (dot_positions_.find (pos) != dot_positions_.end ())
+    {
+      conf->delta_y_ += 0.25 * details_.staff_space_;
+    }
+  conf->attachment_x_ = get_attachment (y + conf->delta_y_);
+
+  Real h =  conf->height (details_);
+  if (!conf->delta_y_)
+    {
+      if (h < 0.5 * details_.staff_space_
+         && !Staff_symbol_referencer::on_staffline (details_.staff_symbol_referencer_, pos))
+       {
+         conf->center_tie_vertically (details_);
+       }
+      else if (h < 0.5 * details_.staff_space_
+              && Staff_symbol_referencer::on_staffline (details_.staff_symbol_referencer_, pos))
+       {
+         conf->delta_y_ += dir * 0.2 * details_.staff_space_;
+       }
+    }
+  
+  conf->attachment_x_.widen ( - details_.x_gap_);
+  return conf;
+}
+
+Real
+Tie_formatting_problem::score_aptitude (Tie_configuration const &conf,
+                                       int tie_position)
+{
+  Real wrong_direction_offset_penalty_;
+  Real distance_penalty_factor_;
+                                 
+  wrong_direction_offset_penalty_ = 10;
+  distance_penalty_factor_ = 5;
+  
+  Real penalty = 0.0;
+  Real curve_y = conf.position_ * details_.staff_space_ * 0.5 + conf.delta_y_;
+  Real tie_y = tie_position * details_.staff_space_ * 0.5;
+  if (sign (curve_y - tie_y) != conf.dir_)
+    penalty += wrong_direction_offset_penalty_;
+
+  penalty += distance_penalty_factor_ * fabs (curve_y - tie_y);
+  return penalty;
+}
+
+
+Real
+Tie_formatting_problem::score_configuration (Tie_configuration const &conf)
+{
+  Real length_penalty_factor = 1.0;
+  Real min_length = 0.333;
+  Real staff_line_clearance = 0.1;
+  Real staff_line_collision_penalty = 5;
+
+  Real penalty = 0.0;
+  Real length = conf.attachment_x_.length ();
+  if (length < min_length)
+    penalty += length_penalty_factor / max (0.01, length);
+
+  Real tip_pos = conf.position_ + conf.delta_y_ / 0.5 * details_.staff_space_;
+  Real tip_y = tip_pos * details_.staff_space_ * 0.5;
+  Real height =  conf.height (details_);
+
+  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) < staff_line_clearance
+      && Staff_symbol_referencer::on_staffline (details_.staff_symbol_referencer_,
+                                               int (round_top_pos))
+      && Staff_symbol_referencer::staff_radius (details_.staff_symbol_referencer_) > top_y)
+    {
+      penalty += staff_line_collision_penalty;      
+    }
+  
+  if (fabs (tip_pos - rint (tip_pos)) < staff_line_clearance
+      && Staff_symbol_referencer::on_staffline (details_.staff_symbol_referencer_,
+                                               int (rint (tip_pos))))
+    {
+      penalty += staff_line_collision_penalty;
+    }
+  
+  return penalty;
+}
+
+Tie_configuration
+Tie_formatting_problem::find_optimal_tie_configuration (int pos, Direction dir)
+{
+  Link_array<Tie_configuration> confs;
+
+  int region_size = 3;
+  for (int i = 0; i < region_size; i ++)
+    {
+      confs.push (generate_configuration (pos + i * dir, dir));
+    }
+
+  Array<Real> scores;
+
+  int best_idx = -1;
+  Real best_score = 1e6;
+  for (int i = 0; i < confs.size (); i ++)
+    {
+      Real score = 0.0;
+      score += score_configuration (*confs[i]);
+      score += score_aptitude (*confs[i], pos);
+
+      if (score < best_score)
+       {
+         best_score = score;
+         best_idx = i;
+       }
+    }
+
+  Tie_configuration best = *confs[best_idx];
+  for (int i = 0; i < confs.size (); i++)
+    delete confs[i];
+
+  return best;
+}
index 5410a0d94226b0239de524204cc9cd655b7057f7..23915a1d05a925c44d954da6a360f7d104625733 100644 (file)
@@ -89,6 +89,7 @@ Tie_configuration::height (Tie_details const &details) const
 void
 Tie_details::from_grob (Grob *me)
 {
+  staff_symbol_referencer_ = me;
   staff_space_ = Staff_symbol_referencer::staff_space (me);
   SCM details = me->get_property ("details");
 
index b2ae46d96635b093c23780ae5c7a97ffd6a2ca83..5c756b7686a585f2e5fe8f848bd7578f31aeb7dc 100644 (file)
@@ -192,7 +192,7 @@ Tie::get_default_attachments (Spanner *me, Grob *common, Real gap,
 
   return attachments;
 }  
-                       
+
 void
 Tie::get_configuration (Grob *me_grob, 
                        Tie_configuration *conf,
@@ -406,14 +406,13 @@ Tie::set_default_control_points (Grob *me_grob)
   common = me->get_bound (LEFT)->common_refpoint (common, X_AXIS); 
   common = me->get_bound (RIGHT)->common_refpoint (common, X_AXIS); 
   
-  Tie_configuration conf;
-  int tie_position = (int) Tie::get_position (me);
-  conf.position_ = tie_position;
-  
   Tie_formatting_problem problem;
   problem.from_tie (me);
   
-  get_configuration (me,  &conf, problem);
+  // get_configuration (me,  &conf, problem);
+  int tie_position = (int) Tie::get_position (me);
+  Tie_configuration conf
+    = problem.find_optimal_tie_configuration (tie_position, get_grob_direction (me));
   set_control_points (me, problem.common_x_refpoint (),
                      conf, problem.details_);
 }
@@ -522,3 +521,6 @@ ADD_INTERFACE (Tie,
               "direction "
               "thickness "
               "x-gap ");
+
+
+