source file of the GNU LilyPond music typesetter
- (c) 1996,1997 Han-Wen Nienhuys <hanwen@stack.nl>
+ (c) 1996--1999 Han-Wen Nienhuys <hanwen@cs.uu.nl>
*/
#include <math.h>
#include <limits.h>
+#include "killing-cons.tcc"
#include "spring-spacer.hh"
#include "p-col.hh"
#include "debug.hh"
+#include "dimensions.hh"
#include "qlp.hh"
#include "unionfind.hh"
#include "idealspacing.hh"
#include "pointer.tcc"
#include "score-column.hh"
#include "paper-def.hh"
-#include "dimen.hh"
#include "colhpos.hh"
-#include "main.hh" // experimental_fietsers
+#include "main.hh"
Vector
Spring_spacer::default_solution() const
{
- return try_initial_solution() ;
+ return try_initial_solution();
}
Score_column*
Spring_spacer::scol_l (int i)
{
- return (Score_column*)cols[i].pcol_l_;
+ return dynamic_cast<Score_column*>(cols_[i].pcol_l_);
}
const Real COLFUDGE=1e-3;
template class P<Real>; // ugh.
bool
-Spring_spacer::contains (Paper_column const *w)
+Spring_spacer::contains_b (Paper_column const *w)
{
- for (int i=0; i< cols.size(); i++)
- if (cols[i].pcol_l_ == w)
+ for (int i=0; i< cols_.size(); i++)
+ if (cols_[i].pcol_l_ == w)
return true;
return false;
}
Spring_spacer::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 < 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
void
Spring_spacer::handle_loose_cols()
{
- Union_find connected (cols.size());
+ Union_find connected (cols_.size());
Array<int> fixed;
- for (PCursor<Idealspacing*> i (ideal_p_list_.top()); i.ok (); i++)
+
+ for (Cons<Idealspacing> *i = ideal_p_list_; i; i = i->next_cons_p_)
{
- connected.connect (i->left_i_,i->right_i_);
+ connected.connect (i->car_p_->cols_drul_[LEFT],i->car_p_->cols_drul_[RIGHT]);
}
- for (int i = 0; i < cols.size(); i++)
- if (cols[i].fixed())
+ for (int i = 0; i < cols_.size(); i++)
+ if (cols_[i].fixed_b())
fixed.push (i);
for (int i=1; i < fixed.size(); i++)
connected.connect (fixed[i-1], fixed[i]);
- for (int i = cols.size(); i--;)
+ for (int i = cols_.size(); i--;)
{
if (! connected.equiv (fixed[0], i))
{
- warning (_("unconnected column: ") + String (i));
+ warning (_f ("unconnected column: %d", i));
loosen_column (i);
}
}
return ;
assert (sol_vec.dim());
Array<bool> fix_b_arr;
- fix_b_arr.set_size (cols.size() + loose_col_arr_.size ());
+ fix_b_arr.set_size (cols_.size() + loose_col_arr_.size ());
Real utter_right_f=-infinity_f;
Real utter_left_f =infinity_f;
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++)
+ for (int i=0; i < cols_.size(); i++)
{
- int r= cols[i].rank_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);
{
if (fix_b_arr[i])
{
- assert (cols[j].rank_i_ == i);
+ assert (cols_[j].rank_i_ == i);
v (i) = sol_vec (j++);
}
else
(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 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++];
+ Column_info loose=loose_col_arr_[k++];
int r = loose.rank_i_ ;
assert (r > left_rank && r < right_rank);
Spring_spacer::check_constraints (Vector v) const
{
int dim=v.dim();
- assert (dim == cols.size());
-
+ assert (dim == cols_.size());
+ DOUT << "checking " << v;
for (int i=0; i < dim; i++)
{
-
- if (cols[i].fixed()&&
- abs (cols[i].fixed_position() - v (i)) > COLFUDGE)
- return false;
-
- if (!i)
- continue;
-
- Real mindist=cols[i-1].width_[RIGHT]
- -cols[i].width_[LEFT];
-
- // ugh... compares
- Real dif =v (i) - v (i-1)- mindist;
- bool b = (dif > - COLFUDGE);
-
-
- if (!b)
- return false;
+ if (cols_[i].fixed_b() &&
+ abs (cols_[i].fixed_position() - v (i)) > COLFUDGE)
+ {
+ DOUT << "Fixpos broken\n";
+ return false;
+ }
+ Array<Spacer_rod> const &rods (cols_[i].rods_[RIGHT]);
+ for (int j =0; j < rods.size (); j++)
+ {
+ int other =rods[j].other_idx_;
+ Real diff =v (other) - v (i) ;
+ if (COLFUDGE +diff < rods[j].distance_f_)
+ {
+ DOUT << "i, other_i: " << i << " " << other << '\n';
+ DOUT << "dist, minimal = " << diff << " "
+ << rods[j].distance_f_ << '\n';
+ return false;
+ }
+ }
}
return true;
}
-bool
-Spring_spacer::check_feasible() const
+/** try to generate a solution which obeys the min distances and fixed positions
+ */
+Vector
+Spring_spacer::try_initial_solution() const
{
- Vector sol (try_initial_solution());
- return check_constraints (sol);
+ Vector v;
+ if (!try_initial_solution_and_tell (v))
+ {
+ warning (_ ("I'm too fat; call Oprah"));
+ }
+ return v;
+
}
-/// generate a solution which obeys the min distances and fixed positions
-Vector
-Spring_spacer::try_initial_solution() const
+bool
+Spring_spacer::try_initial_solution_and_tell (Vector &v) const
{
- int dim=cols.size();
+ int dim=cols_.size();
+ bool succeeded = true;
Vector initsol (dim);
+
+ assert (cols_[0].fixed_b ());
+ DOUT << "fixpos 0 " << cols_[0].fixed_position ();
for (int i=0; i < dim; i++)
{
- if (cols[i].fixed())
+ Real min_x = i ? initsol (i-1) : cols_[0].fixed_position ();
+ Array<Spacer_rod> const &sr_arr(cols_[i].rods_[LEFT]);
+ for (int j=0; j < sr_arr.size (); j++)
{
- initsol (i)=cols[i].fixed_position();
-
- if (i > 0)
- {
- Real r =initsol (i-1) + cols[i-1].width_[RIGHT];
- if (initsol (i) < r)
- {
- warning (_("overriding fixed position"));
- initsol (i) =r;
- }
- }
-
+ min_x = min_x >? (initsol (sr_arr[j].other_idx_) + sr_arr[j].distance_f_);
}
- else
+ initsol (i) = min_x;
+
+ if (cols_[i].fixed_b())
{
- Real mindist=cols[i-1].width_[RIGHT]
- - cols[i].width_[LEFT];
- if (mindist < 0.0)
- warning (_("Excentric column"));
- initsol (i)=initsol (i-1)+mindist;
+ initsol (i)=cols_[i].fixed_position();
+ if (initsol (i) < min_x )
+ {
+ DOUT << "failing: init, min : " << initsol (i) << " " << min_x << '\n';
+ initsol (i) = min_x;
+ succeeded = false;
+ }
}
}
-
- return initsol;
+ v = initsol;
+
+ DOUT << "tried and told solution: " << v;
+ if (!succeeded)
+ DOUT << "(failed)\n";
+ return succeeded;
}
-Vector
-Spring_spacer::find_initial_solution() const
-{
- Vector v (try_initial_solution());
- assert (check_constraints (v));
- return v;
-}
-
// generate the matrices
void
Spring_spacer::make_matrices (Matrix &quad, Vector &lin, Real &c) const
lin.fill (0);
c = 0;
- for (PCursor<Idealspacing*> i (ideal_p_list_.top()); i.ok (); i++)
+ for (Cons<Idealspacing> *p =ideal_p_list_; p; p = p->next_cons_p_)
{
- int l = i->left_i_;
- int r = i->right_i_;
+ Idealspacing *i = p->car_p_;
+ int l = i->cols_drul_[LEFT];
+ int r = i->cols_drul_[RIGHT];
quad (r,r) += i->hooke_f_;
quad (r,l) -= i->hooke_f_;
c += sqr (i->space_f_);
}
+
+ if (quad.dim() > 10)
+ quad.set_band();
+
+
}
void
Spring_spacer::set_fixed_cols (Mixed_qp &qp) const
{
- for (int j=0; j < cols.size(); j++)
- if (cols[j].fixed())
- qp.add_fixed_var (j,cols[j].fixed_position());
-
-
-}
+ for (int j=0; j < cols_.size(); j++)
+ if (cols_[j].fixed_b())
+ qp.add_fixed_var (j,cols_[j].fixed_position());
+}
// put the constraints into the LP problem
void
Spring_spacer::make_constraints (Mixed_qp& lp) const
{
- int dim=cols.size();
- for (int j=0; j < dim; j++)
+ int dim=cols_.size();
+
+ for (int j=0; j < dim -1; j++)
{
- Colinfo c=cols[j];
- if (j > 0)
+ Array<Spacer_rod> const&rod_arr (cols_[j].rods_[RIGHT]);
+ for (int i = 0; i < rod_arr.size (); i++)
{
Vector c1(dim);
+ c1(rod_arr[i].other_idx_)=1.0 ;
+ c1(j)=-1.0 ;
- c1(j)=1.0 ;
- c1(j-1)=-1.0 ;
- lp.add_inequality_cons (c1,
- cols[j-1].width_[RIGHT] - cols[j].width_[LEFT]);
+ lp.add_inequality_cons (c1, rod_arr[i].distance_f_);
}
}
}
Spring_spacer::calculate_energy_f (Vector solution) const
{
Real e = 0.0;
- for (PCursor<Idealspacing*> i (ideal_p_list_.top()); i.ok(); i++)
+ for (Cons<Idealspacing>*p =ideal_p_list_; p; p = p->next_cons_p_)
{
- e += i->energy_f(solution(i->right_i_) - solution(i->left_i_));
+ Idealspacing * i = p->car_p_;
+ e += i->energy_f(solution(i->cols_drul_[RIGHT]) - solution(i->cols_drul_[LEFT]));
}
return e;
}
void
-Spring_spacer::lower_bound_solution (Col_hpositions*positions) const
+Spring_spacer::lower_bound_solution (Column_x_positions*positions) const
{
- Mixed_qp lp (cols.size());
- make_matrices (lp.quad,lp.lin, lp.const_term);
+ Mixed_qp lp (cols_.size());
+ make_matrices (lp.quad_,lp.lin_, lp.const_term_);
set_fixed_cols (lp);
- Vector start (cols.size());
+ Vector start (cols_.size());
start.fill (0.0);
Vector solution_vec (lp.solve (start));
+ DOUT << "Lower bound sol: " << solution_vec;
positions->energy_f_ = calculate_energy_f (solution_vec);
positions->config = solution_vec;
positions->satisfies_constraints_b_ = check_constraints (solution_vec);
}
-void
-Spring_spacer::solve (Col_hpositions*positions) const
+Spring_spacer::Spring_spacer ()
{
- assert (check_feasible());
-
- Mixed_qp lp (cols.size());
- make_matrices (lp.quad,lp.lin, lp.const_term);
- make_constraints (lp);
- set_fixed_cols (lp);
- Vector start=find_initial_solution();
- Vector solution_vec (lp.solve (start));
+ ideal_p_list_ =0;
+ energy_normalisation_f_ = 1.0;
+}
+void
+Spring_spacer::solve (Column_x_positions*positions) const
+{
+ DOUT << "Spring_spacer::solve ()...";
- positions->satisfies_constraints_b_ = check_constraints (solution_vec);
- if (!positions->satisfies_constraints_b_)
+ Vector solution_try;
+
+ bool constraint_satisfaction = try_initial_solution_and_tell (solution_try);
+ if (constraint_satisfaction)
{
- WARN << _("solution doesn't satisfy constraints.\n") ;
+ Mixed_qp lp (cols_.size());
+ make_matrices (lp.quad_,lp.lin_, lp.const_term_);
+ make_constraints (lp);
+ set_fixed_cols (lp);
+
+ Vector solution_vec (lp.solve (solution_try));
+
+ positions->satisfies_constraints_b_ = check_constraints (solution_vec);
+ if (!positions->satisfies_constraints_b_)
+ {
+ WARN << _ ("solution doesn't satisfy constraints") << '\n' ;
+ }
+ position_loose_cols (solution_vec);
+ positions->energy_f_ = calculate_energy_f (solution_vec);
+ positions->config = solution_vec;
+ positions->error_col_l_arr_ = error_pcol_l_arr();
+ }
+ else
+ {
+ positions->set_stupid_solution (solution_try);
}
- position_loose_cols (solution_vec);
- positions->energy_f_ = calculate_energy_f (solution_vec);
- positions->config = solution_vec;
- positions->error_col_l_arr_ = error_pcol_l_arr();
+ DOUT << "Finished Spring_spacer::solve ()...";
}
/**
void
Spring_spacer::add_column (Paper_column *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);
+ Column_info c (col,(fixed)? &fixpos : 0);
+ int this_rank = cols_.size();
+ c.rank_i_ = this_rank;
+
+ for (int i=0; i < col->minimal_dists_arr_drul_[LEFT].size (); i++)
+ {
+ Column_rod &cr = col->minimal_dists_arr_drul_[LEFT][i];
+ int left_idx = cr.other_l_->rank_i () - cols_[0].pcol_l_->rank_i ();
+ if (left_idx < 0)
+ continue;
+
+ if (cols_[left_idx].pcol_l_ != cr.other_l_)
+ continue;
+
+ Spacer_rod l_rod;
+ l_rod.distance_f_ = cr.distance_f_;
+ l_rod.other_idx_ = left_idx;
+ c.rods_[LEFT].push (l_rod);
+
+ Spacer_rod r_rod;
+ r_rod.distance_f_ = cr.distance_f_;
+ r_rod.other_idx_ = this_rank;
+ cols_[left_idx].rods_[RIGHT].push (r_rod);
+ }
+
+ cols_.push (c);
}
Line_of_cols
Spring_spacer::error_pcol_l_arr() const
{
- Array<Paper_column*> retval;
- for (int i=0; i< cols.size(); i++)
- if (cols[i].ugh_b_)
- retval.push (cols[i].pcol_l_);
+ Link_array<Paper_column> 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;
}
-
+/*
+ Ugh. Should junk this.
+ */
void
-Spring_spacer::loosen_column (int i)
+Spring_spacer::loosen_column (int idx)
{
- Colinfo c=cols.get (i);
- for (PCursor<Idealspacing*> j (ideal_p_list_.top()); j.ok (); j++)
+ Column_info c=cols_.get (idx);
+
+ Cons<Idealspacing> **pp = &ideal_p_list_;
+
+ while (*pp)
{
- if (j->left_i_ == i|| j->right_i_ == i)
- j.del();
+ Idealspacing *j = (*pp)->car_p_;
+ if (j->cols_drul_[LEFT] == idx|| j->cols_drul_[RIGHT] == idx)
+ {
+ delete remove_cons_p (pp);
+ }
else
- j++;
+ {
+ pp = &(*pp)->next_cons_p_;
+ }
}
c.ugh_b_ = true;
Spring_spacer::print() const
{
#ifndef NPRINT
- for (int i=0; i < cols.size(); i++)
+ for (int i=0; i < cols_.size(); i++)
{
- DOUT << "col " << i<<' ';
- cols[i].print();
+ DOUT << "col " << i << " ";
+ cols_[i].print();
}
- for (PCursor<Idealspacing*> i (ideal_p_list_.top()); i.ok (); i++)
+
+ for (Cons<Idealspacing> *p =ideal_p_list_; p; p = p->next_cons_p_)
{
- i->print();
+ p->car_p_->print();
}
#endif
}
assert(h >=0);
Idealspacing * s = new Idealspacing;
- s->left_i_ = i;
- s->right_i_ = j;
+
+ s->cols_drul_[LEFT] = i ;
+ s->cols_drul_[RIGHT] = j;
s->space_f_ = d;
s->hooke_f_ = h;
- ideal_p_list_.bottom().add (s);
+ ideal_p_list_ = new Killing_cons<Idealspacing> (s, ideal_p_list_);
}
void
Spring_spacer::prepare()
{
+ DOUT << "Preparing..";
calc_idealspacing();
handle_loose_cols();
print();
+ DOUT << "finished preparing.\n";
}
Line_spacer*
Spring_spacer::get_ruling_durations(Array<Moment> &shortest_playing_arr,
Array<Moment> &context_shortest_arr)
{
- for (int i=0; i < cols.size(); i++)
- scol_l (i)->preprocess();
-
+ for (int i=0; i < cols_.size(); i++)
+ {
+ scol_l (i)->preprocess();
+ scol_l (i)->print ();
+ }
int start_context_i=0;
- Moment context_shortest = infinity_mom;
- context_shortest_arr.set_size(cols.size());
+ Moment context_shortest;
+ context_shortest.set_infinite (1);
+ context_shortest_arr.set_size(cols_.size());
- for (int i=0; i < cols.size(); i++)
+ for (int i=0; i < cols_.size(); i++)
{
+ Score_column * sc = scol_l(i);
Moment now = scol_l (i)->when();
- Moment shortest_playing = infinity_mom;
+ Moment shortest_playing;
+ shortest_playing.set_infinite (1);
- if (scol_l (i)->breakable_b_)
+ if (!sc->musical_b ())
{
for (int ji=i; ji >= start_context_i; ji--)
context_shortest_arr[ji] = context_shortest;
start_context_i = i;
- context_shortest = infinity_mom;
+ context_shortest.set_infinite (1);
}
- if (scol_l (i)->durations.size())
+ if (sc->durations.size())
{
- context_shortest = context_shortest <? scol_l(i)->durations[0];
+ context_shortest = context_shortest <? sc->durations[0];
}
+
// ji was j, but triggered ICE
for (int ji=i+1; ji --;)
{
#endif
}
+/*
+ TODO: take out the refs to width
+
+ */
/**
generate springs between columns.
- UNDER DESTRUCTION
+ TODO: This needs rethinking.......
- TODO: This needs rethinking. Spacing should take optical
- effects into account, and should be local (measure wide)
+ * Spacing should take optical
+ effects into account
+ * Should be decentralised
+
The algorithm is taken from :
John S. Gourlay. ``Spacing a Line of Music,'' Technical Report
Array<Moment> context_shortest_arr;
get_ruling_durations(shortest_playing_arr, context_shortest_arr);
- Real interline_f = paper_l ()->interline_f ();
+ Real interline_f = paper_l ()->get_realvar (interline_scm_sym);
- Array<Real> ideal_arr_;
- Array<Real> hooke_arr_;
- for (int i=0; i < cols.size(); i++){
- ideal_arr_.push (-1.0);
- hooke_arr_.push (1.0);
+ Array<Real> ideal_arr;
+ Array<Real> hooke_arr;
+ for (int i=0; i < cols_.size() - 1; i++){
+ ideal_arr.push (-1.0);
+ hooke_arr.push (1.0);
}
- for (int i=0; i < cols.size(); i++)
+ /*
+ First do all non-musical columns
+ */
+ for (int i=0; i < cols_.size(); i++)
{
- if (!scol_l (i)->musical_b())
+ if (!scol_l (i)->musical_b() && i+1 < cols_.size())
{
- Real symbol_distance =cols[i].width_[RIGHT] + 2 PT;
+ Real symbol_distance =cols_[i].width_[RIGHT] + 2 PT;
Real durational_distance = 0;
+ Moment delta_t = scol_l (i+1)->when() - scol_l (i)->when () ;
- if (i+1 < cols.size())
+ /*
+ ugh should use shortest_playing distance
+ */
+ if (delta_t)
{
- Moment delta_t = scol_l (i+1)->when() - scol_l (i)->when () ;
-
- Real k= paper_l()->arithmetic_constant(context_shortest_arr[i]);
- /*
- ugh should use shortest_playing distance
- */
- if (delta_t)
- durational_distance = paper_l()->duration_to_dist (delta_t,k);
- symbol_distance += -cols[i+1].width_[LEFT];
+ Real k= paper_l()->arithmetic_constant (context_shortest_arr[i]);
+ durational_distance = paper_l()->length_mom_to_dist (delta_t,k);
}
+ symbol_distance += -cols_[i+1].width_[LEFT];
+
- ideal_arr_[i] = symbol_distance >? durational_distance;
- hooke_arr_[i] = 2.0;
+ ideal_arr[i] = symbol_distance >? durational_distance;
+ hooke_arr[i] = 1; //2.0;
}
}
- for (int i=0; i < cols.size(); i++)
+
+ /*
+ Then musicals
+ */
+ for (int i=0; i < cols_.size(); i++)
{
if (scol_l (i)->musical_b())
{
Moment context_shortest = context_shortest_arr[i];
if (! shortest_playing_len)
{
- warning (_("Can't find a ruling note at ")
- +String (scol_l (i)->when()));
+ warning (_f ("can't find a ruling note at %s",
+ scol_l (i)->when().str ()));
shortest_playing_len = 1;
}
if (! context_shortest)
{
- warning(_("No minimum in measure at ")
- + String (scol_l (i)->when()));
+ warning (_f ("no minimum in measure at %s",
+ scol_l (i)->when().str ()));
context_shortest = 1;
}
Moment delta_t = scol_l (i+1)->when() - scol_l (i)->when ();
Real k= paper_l()->arithmetic_constant(context_shortest);
- Real dist = paper_l()->duration_to_dist (shortest_playing_len, k);
- dist *= delta_t / shortest_playing_len;
+ Real dist = paper_l()->length_mom_to_dist (shortest_playing_len, k);
+ dist *= (double)(delta_t / shortest_playing_len);
/*
- this is an experimental try to fix the spacing
- at the beginning and end of bars.
- if -t option is not used, the old algorithm should still
- be in effect.
-
- the "old" comment below about ugliness seems to indicate that
- the code below it address the same problem? but it sounds real
- bad.
-
- According to [Ross] and [Wanske], and from what i've seen:
- * whitespace at the begin of the bar should be fixed at
- (about) two interlines.
- [Ross]:
- when spacing gets real tight, a smaller fixed value may be
- used, so that there are two discrete amounts of whitespace
- possible at the begin of a bar; but this is not implemented
- right now.
- * whitespace at the end of the bar is the normal amount of
- "hinterfleish" that would have been used, had there been
- yet another note in the bar.
- [Ross]:
- some editors argue that the bar line should not take any
- space, not to hinder the flow of music spaced around a bar
- line.
- [Ross] and [Wanske] do not suggest this, however. Further,
- it introduces some spacing problems and think that it is ugly
- too.
- */
-
- if (experimental_features_global_b)
+ According to [Ross] and [Wanske], and from what i've seen:
+
+ * whitespace at the begin of the bar should be fixed at
+ (about) one interline.
+
+ [Ross]:
+ when spacing gets real tight, a smaller fixed value may be
+ used, so that there are two discrete amounts of whitespace
+ possible at the begin of a bar; but this is not implemented
+ right now.
+
+ * whitespace at the end of the bar is the normal amount of
+ "hinterfleish" that would have been used, had there been
+ yet another note in the bar.
+
+ [Ross]:
+ some editors argue that the bar line should not take any
+ space, not to hinder the flow of music spaced around a bar
+ line.
+
+ [Ross] and [Wanske] do not suggest this, however. Further,
+ it introduces some spacing problems and I think that it is ugly
+ too.
+
+ [jcn]
+ */
+
+ /*
+ first musical column of bar
+ */
+ if (i && !scol_l (i - 1)->musical_b ())
{
- /*
- first musical column of bar?
- */
- Moment now_mom = scol_l (i)->when ();
- if (i && !scol_l (i - 1)->musical_b ()
- && ((Moment) floor (now_mom) == now_mom))
- {
- /*
- wtk1-fugue2: very nice
- standchen: fuk, koor dump in check_feasible ()
- */
- // fixed: probably should set minimum (rod/spring)?
- cols[i-1].width_[RIGHT] += 1.5 * interline_f;
- // should adjust dist too?
- ideal_arr_[i-1] += 1.5 * interline_f;
- }
-
- /*
- last musical column of bar?
+ // one interline minimum at start of bar
+
+ // cols_[i].width_[RIGHT] += interline_f;
+ cols_[i].width_[RIGHT] = cols_[i].width_[RIGHT] >? interline_f;
+
+ // should adjust dist too?
+ ideal_arr[i-1] = ideal_arr[i-1] >? (2 * interline_f);
+ }
+
+ /*
+ last musical column of bar
+ */
+ if (i + 1 < cols_.size () && !scol_l(i+1)->musical_b ())
+ {
+ // two interline minimum ok for last column?
+ dist = dist >? 2 * interline_f;
+
+ // set minimum rod
+ /*
+ urg: simply *adding* an interline leaves big gaps at
+ end of measure in star-spangled-banner (after lyrics
+ at eom).
+
+ cols_[i].width_[RIGHT] += interline_f; // before
+
+ having a minimum of one interline solves this problem
+ in most (but not all??) cases.
+
+ for music without lyrics (esp. when set very tightly),
+ adding an interline looks good: probably because this
+ hides a bug that allows the last note's "hinterfleish"
+ to be removed (e.g., see wtk1-fugue2: that's ugly now).
+ -- jcn
*/
- Moment next_mom = scol_l (i + 1)->when ();
- if ((i + 1 < cols.size ()) && !scol_l (i + 1)->musical_b ()
- && ((Moment) floor (next_mom) == next_mom))
- {
- // hmm, how bout?
- dist = dist >? interline_f;
-
- // uhuh, this looks fine, already??
- // someone is junking this last "hinterfleisch" whitespace?!
- /*
- wtk1-fugue2: very nice
- standchen: fuk, koor dump in check_feasible ()
- */
- cols[i].width_[RIGHT] = cols[i].width_[RIGHT] >? dist;
- }
-
- // ugh, do we need this?
- if (!scol_l (i + 1)->musical_b ())
- {
- Real minimum = -cols[i + 1].width_[LEFT] + cols[i].width_[RIGHT]
- + interline_f / 2;
- dist = dist >? minimum;
- }
+
+ cols_[i].width_[RIGHT] = cols_[i].width_[RIGHT] >? 2 * interline_f;
}
- /* all sorts of ugliness to avoid running into bars/clefs,
- but not taking extra space if this is not needed
- */
- else if (!scol_l (i + 1)->musical_b ())
+ // ugh, do we need this?
+ if (i < cols_.size () - 1 && !scol_l (i + 1)->musical_b ())
{
- Real minimum_dist = -cols[i + 1].width_[LEFT] + 2 PT
- + cols[i].width_[RIGHT];
- if (ideal_arr_[i + 1] + minimum_dist < dist)
- dist -= ideal_arr_[i + 1];
- else
- dist = minimum_dist;
+ Real minimum = -cols_[i + 1].width_[LEFT] + cols_[i].width_[RIGHT]
+ + interline_f / 2;
+ dist = dist >? minimum;
}
- ideal_arr_[i] = dist;
+ ideal_arr[i] = dist;
}
}
- for (int i=0; i < ideal_arr_.size()-1; i++)
+ /*
+ shorter distances should stretch less.
+
+ (and how bout
+
+ hooke[i] = 2 * max_ideal_space - ideal[i]
+
+ ?)
+ */
+ for (int i=0; i < ideal_arr.size(); i++)
+ hooke_arr[i] = 1/ideal_arr[i];
+
+ for (int i=0; i < ideal_arr.size(); i++)
{
- assert (ideal_arr_[i] >=0 && hooke_arr_[i] >=0);
- connect (i, i+1, ideal_arr_[i], hooke_arr_[i]);
+ assert (ideal_arr[i] >=0 && hooke_arr[i] >=0);
+ connect (i, i+1, ideal_arr[i], hooke_arr[i]);
}
}