]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/linespace.cc
release: 0.0.62
[lilypond.git] / lily / linespace.cc
index aed6c407eb3b9c490b1013aab30e3a781af8e647..c2fec09918ab6a17845111593d74e9b67f09ce42 100644 (file)
@@ -5,15 +5,16 @@
 #include "qlp.hh"
 #include "unionfind.hh"
 #include "idealspacing.hh"
+#include "pointer.tcc"
 
 const Real COLFUDGE=1e-3;
-
+template class P<Real>;                // ugh.
 
 bool
 Spacing_problem::contains(PCol const *w)
 {
     for (int i=0; i< cols.size(); i++)
-       if (cols[i].pcol_ == w)
+       if (cols[i].pcol_l_ == w)
            return true;
     return false;
 }
@@ -22,7 +23,7 @@ int
 Spacing_problem::col_id(PCol const *w)const
 {
     for (int i=0; i< cols.size(); i++)
-       if (cols[i].pcol_ == w)
+       if (cols[i].pcol_l_ == w)
            return i;
     assert(false);
     return -1;
@@ -32,6 +33,19 @@ void
 Spacing_problem::OK() const
 {
 #ifndef NDEBUG
+    for (int i = 1; i < cols.size(); i++)
+       assert(cols[i].rank_i_ > cols[i-1].rank_i_);
+    for (int i = 1; i < loose_col_arr_.size(); i++)
+       assert(loose_col_arr_[i].rank_i_ > loose_col_arr_[i-1].rank_i_);
+#endif 
+}
+
+/**
+  Make sure no unconnected columns happen. 
+ */
+void
+Spacing_problem::handle_loose_cols() 
+{
     Union_find connected(cols.size());
     Array<int> fixed;
     for (int i=0; i < ideals.size(); i++) {
@@ -43,23 +57,73 @@ Spacing_problem::OK() const
     for (int i = 0; i < cols.size(); i++)
        if (cols[i].fixed())
            fixed.push(i);
-    for (int i = 0; i < cols.size(); i++) {
-       bool c=false;
-       for (int j =0; j<fixed.size(); j++)
-           c |=  connected.equiv(fixed[j],i);
-       if (!c)
-           WARN << "You have unconnected columns. \n"
-               "Check if bars and music fit each other\n"
-               "(crashing :-)\n";
-       assert(c);
+    for (int i=1; i < fixed.size(); i++)
+       connected.connect(fixed[i-1], fixed[i]);
+
+    for (int i = cols.size(); i--; ) {
+       if (! connected.equiv(fixed[0], i)) {
+           warning("unconnected column: " + String(i));
+           loosen_column(i);
+       }
     }
-#endif    
+    OK();
 }
 
+
+/** Guess a stupid position for loose columns.  Put loose columns at
+  regular distances from enclosing calced columns */
+void
+Spacing_problem::position_loose_cols(Vector &sol_vec)const
+{
+    if (!loose_col_arr_.size())
+       return ; 
+    assert(sol_vec.dim());
+    Array<bool> fix_b_arr;
+    fix_b_arr.set_size(cols.size() + loose_col_arr_.size());
+    Real utter_right_f=-INFTY;
+    Real utter_left_f =INFTY;
+    for (int i=0; i < loose_col_arr_.size(); i++) {
+       fix_b_arr[loose_col_arr_[i].rank_i_] = false;
+    }
+    for (int i=0; i < cols.size(); i++) {
+       int r= cols[i].rank_i_;
+       fix_b_arr[r] = true;
+       utter_right_f = utter_right_f >? sol_vec(i);
+       utter_left_f = utter_left_f <? sol_vec(i);
+    }
+    Vector v(fix_b_arr.size());
+    int j =0;
+    int k =0;
+    for (int i=0; i < v.dim(); i++) {
+       if (fix_b_arr[i]) {
+           assert(cols[j].rank_i_ == i);
+           v(i) = sol_vec(j++);
+       } else {
+           Real left_pos_f = 
+               (j>0) ?sol_vec(j-1) : utter_left_f;
+           Real right_pos_f = 
+               (j < sol_vec.dim()) ? sol_vec(j) : utter_right_f;
+           int left_rank = (j>0) ? cols[j-1].rank_i_ : 0;
+           int right_rank = (j<sol_vec.dim()) ? cols[j].rank_i_ : sol_vec.dim();
+
+           int d_r = right_rank - left_rank;
+           Colinfo loose=loose_col_arr_[k++];
+           int r = loose.rank_i_ ;
+           assert(r > left_rank && r < right_rank);
+
+           v(i) =  (r - left_rank)*left_pos_f/ d_r + 
+               (right_rank - r) *right_pos_f /d_r;
+       }
+    }
+    sol_vec = v;
+}
 bool
 Spacing_problem::check_constraints(Vector v) const 
 {
     int dim=v.dim();
+    assert(dim == cols.size());
+    
     for (int i=0; i < dim; i++) {
 
        if (cols[i].fixed()&&
@@ -84,6 +148,12 @@ Spacing_problem::check_constraints(Vector v) const
     return true;
 }
 
+void
+Spacing_problem::prepare()
+{
+    handle_loose_cols();
+}
+
 bool
 Spacing_problem::check_feasible() const
 {
@@ -91,7 +161,7 @@ Spacing_problem::check_feasible() const
     return check_constraints(sol);     
 }
 
-// generate a solution which obeys the min distances and fixed positions
+/// generate a solution which obeys the min distances and fixed positions
 Vector
 Spacing_problem::try_initial_solution() const
 {
@@ -99,21 +169,30 @@ Spacing_problem::try_initial_solution() const
     Vector initsol(dim);
     for (int i=0; i < dim; i++) {
        if (cols[i].fixed()) {
-           initsol(i)=cols[i].fixed_position();            
+           initsol(i)=cols[i].fixed_position();        
+
+           if (i > 0) {
+               Real r =initsol(i-1)  + cols[i-1].minright();
+               if (initsol(i) < r ) {
+                   warning("overriding fixed position");
+                   initsol(i) =r;
+               } 
+           }
+               
        } else {
            Real mindist=cols[i-1].minright()
                +cols[i].minleft();
-           assert(mindist >= 0.0);
+           if (mindist < 0.0)
+               warning("Excentric column");
            initsol(i)=initsol(i-1)+mindist;
-
-           //nog niet 
-           //if (i>0)
-           //  assert(initsol(i) > initsol(i-1));
        }       
     }
 
     return initsol;
 }
+
+
+
 Vector
 Spacing_problem::find_initial_solution() const
 {
@@ -170,9 +249,8 @@ Spacing_problem::make_constraints(Mixed_qp& lp) const
 Array<Real>
 Spacing_problem::solve() const
 {
-    print();
-    OK();
     assert(check_feasible());
+    print();
 
     Mixed_qp lp(cols.size());
     make_matrices(lp.quad,lp.lin, lp.const_term);
@@ -182,10 +260,12 @@ Spacing_problem::solve() const
     if (!check_constraints(sol)) {
        WARN << "solution doesn't satisfy constraints.\n" ;
     }
-       
+    Real energy_f =lp.eval(sol);
+    position_loose_cols(sol);
 
     Array<Real> posns(sol);
-    posns.push(lp.eval(sol));
+
+    posns.push(energy_f);
     return posns;
 }
 
@@ -193,12 +273,50 @@ Spacing_problem::solve() const
     add one column to the problem.
 */    
 void
-Spacing_problem::add_column(PCol const *col, bool fixed, Real fixpos)
+Spacing_problem::add_column(PCol  *col, bool fixed, Real fixpos)
 {
     Colinfo c(col,(fixed)? &fixpos :  0);
+    if (cols.size())
+       c.rank_i_ = cols.top().rank_i_+1;
+    else
+       c.rank_i_ = 0;
     cols.push(c);
 }
 
+Array<PCol*>
+Spacing_problem::error_pcol_l_arr()const
+{
+    Array<PCol*> retval;
+    for (int i=0; i< cols.size(); i++)
+       if (cols[i].ugh_b_)
+           retval.push(cols[i].pcol_l_);
+    for (int i=0;  i < loose_col_arr_.size(); i++) {
+       retval.push(loose_col_arr_[i].pcol_l_);
+    }
+    return retval;
+}
+
+void
+Spacing_problem::loosen_column(int i)
+{
+    Colinfo c=cols.get(i);
+    for (int i=0; i < ideals.size(); ) {
+       Idealspacing const *i_l =ideals[i];
+       if (i_l->left == c.pcol_l_ || i_l->right == c.pcol_l_)
+           ideals.del(i);
+       else
+           i++;
+    }
+    c.ugh_b_ = true;
+    
+    int i=0;
+    for (; i < loose_col_arr_.size(); i++) {
+       if (loose_col_arr_[i].rank_i_ > c.rank_i_)
+           break;
+    }
+    loose_col_arr_.insert(c,i);
+}
+
 void
 Spacing_problem::add_ideal(Idealspacing const *i)
 {
@@ -247,41 +365,24 @@ Colinfo::print() const
     mtor << "column { ";
     if (fixed())
        mtor << "fixed at " << fixed_position()<<", ";
-    assert(pcol_);
+    assert(pcol_l_);
     mtor << "[" << minleft() << ", " << minright() << "]";
     mtor <<"}\n";
 #endif
 }
 
-Colinfo::Colinfo(Colinfo const&c)
+Colinfo::Colinfo(PCol *col_l, Real const *fixed_C)
 {
-    fixpos = (c.fixpos)?new Real(*c.fixpos):0;
-    pcol_ = c.pcol_;
-    width = c.width;
+    if (fixed_C)
+       fixpos_p_.set_l(fixed_C);
+    ugh_b_ = false;
+    pcol_l_ = col_l;
+    width = pcol_l_->width();
 }
 
-Colinfo::Colinfo(PCol const *col_p, Real const *fixed_r_p )
-{
-    fixpos = (fixed_r_p)? new Real(*fixed_r_p) : 0;
-    pcol_ = col_p;
-    width = pcol_->width();
-}
-
-Colinfo::~Colinfo()
-{
-    delete fixpos;
-}
 
 Colinfo::Colinfo()
 {
-    pcol_=0;
-    fixpos = 0;
-}
-void
-Colinfo::operator=(Colinfo const&c )
-{
-    delete fixpos;
-    fixpos = (c.fixpos)?new Real(*c.fixpos):0;
-    pcol_ = c.pcol_;
-    width = c.width;
+    ugh_b_ = false;
+    pcol_l_ =0;
 }