]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/beam.cc
release: 0.0.73pre
[lilypond.git] / lily / beam.cc
index d0b0079692411028520408b3e82ba771d4979f9e..d4f741d78893dd82a1451ed98d0e6b8b811de791 100644 (file)
@@ -1,14 +1,13 @@
 /*
   beam.cc -- implement Beam
 
-  source file of the GNU GNU LilyPond music typesetter
+  source file of the GNU LilyPond music typesetter
 
   (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
 
   TODO
 
-  Less hairy code. Better slope calculations.
-  knee: ([\stem 1; c8 \stem -1; c8]
+  Less hairy code.  knee: ([\stem 1; c8 \stem -1; c8]
   
 */
 
@@ -69,7 +68,6 @@ Stem_info::Stem_info(Stem const *s)
     // huh? why do i need the / 2
 //    Real interbeam_f = s->paper()->interbeam_f();
     Real interbeam_f = s->paper()->interbeam_f() / 2;
-    Real interline_f = s->paper()->interline_f();
            
     /* well eh, huh?
     idealy_f_  = dir_i_ * s->stem_start_f() + beams_i_ * interbeam_f; 
@@ -149,7 +147,12 @@ Beam::set_default_dir()
 
 /*
   should use minimum energy formulation (cf linespacing)
-  */
+
+  [todo]
+  the y of the (start) of the beam should be quantisized,
+  so that no stafflines appear just in between two beam-flags
+
+*/
 void
 Beam::solve_slope()
 {
@@ -164,14 +167,23 @@ Beam::solve_slope()
        Stem_info info(i);
        sinfo.push(info);
     }
-    Real leftx = sinfo[0].x;
-    Least_squares l;
-    for (int i=0; i < sinfo.size(); i++) {
-       sinfo[i].x -= leftx;
-       l.input.push(Offset(sinfo[i].x, sinfo[i].idealy_f_));
-    }
+    if (! sinfo.size() )
+       slope = left_pos = 0;
+    else if (sinfo.size() == 1) {
+       slope = 0;
+       left_pos = sinfo[0].idealy_f_;
+    } else {
+       
+       Real leftx = sinfo[0].x;
+       Least_squares l;
+       for (int i=0; i < sinfo.size(); i++) {
+           sinfo[i].x -= leftx;
+           l.input.push(Offset(sinfo[i].x, sinfo[i].idealy_f_));
+       }
 
-    l.minimise(slope, left_pos);
+       l.minimise(slope, left_pos);
+    }
+    
     Real dy = 0.0;
     for (int i=0; i < sinfo.size(); i++) {
        Real y = sinfo[i].x * slope + left_pos;
@@ -184,7 +196,12 @@ Beam::solve_slope()
     left_pos *= dir_i_;    
 
     slope *= dir_i_;
-    slope = 0.6 * tanh(slope);  // damping
+
+    /*
+      This neat trick is by Werner Lemberg, damped = tanh(slope) corresponds
+      with some tables in [Wanske]
+     */
+    slope = 0.6 * tanh(slope);  
 
                                // ugh
     Real sl = slope*paper()->internote_f();
@@ -208,6 +225,11 @@ Beam::set_stemlens()
 void
 Beam::do_post_processing()
 {
+    if ( stems.size() < 2) {
+       warning("Beam with less than 2 stems");
+       transparent_b_ = true;
+       return ;
+    }
     solve_slope();    
     set_stemlens();
 }
@@ -248,7 +270,6 @@ Beam::set_grouping(Rhythmic_grouping def, Rhythmic_grouping cur)
 void
 Beam::do_pre_processing()
 {
-    assert(stems.size()>1);
     if (!dir_i_)
        set_default_dir();
 
@@ -329,11 +350,7 @@ Beam::stem_beams(Stem *here, Stem *next, Stem *prev)const
 Molecule*
 Beam::brew_molecule_p() const 
 {
-    /*
-      [todo]
-      the y of the (start) of the beam should be quantisized,
-      so that no stafflines appear just in between two beam-flags
-     */
     Molecule *mol_p = new Molecule;
     // huh? inter-what
 //    Real inter_f = paper()->interbeam_f();
@@ -364,12 +381,13 @@ Beam::do_print()const
     Spanner::print();
 #endif
 }
-
+/*
+  duh. The stem is not a dependency but a dependent
+ */
 void
 Beam::do_substitute_dependency(Score_elem*o,Score_elem*n)
 {
-    int i;
-    while ((i=stems.find_i((Stem*)o->item())) >=0) 
-          if (n) stems[i] = (Stem*) n->item();
-          else stems.del(i);
+    if (o->is_type_b( Stem::static_name() )) {
+       stems.substitute( (Stem*)o->item(),  n?(Stem*) n->item():0);
+    }
 }