source file of the GNU LilyPond music typesetter
- (c) 1996, 1997--1998, 1998 Han-Wen Nienhuys <hanwen@cs.uu.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 "score-column.hh"
#include "paper-def.hh"
#include "colhpos.hh"
+#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;
{
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_b())
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_;
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;
Spring_spacer::Spring_spacer ()
{
+ ideal_p_list_ =0;
energy_normalisation_f_ = 1.0;
}
void
Spring_spacer::solve (Column_x_positions*positions) const
{
-
DOUT << "Spring_spacer::solve ()...";
- Vector solution_try;
+ Vector solution_try;
+
bool constraint_satisfaction = try_initial_solution_and_tell (solution_try);
if (constraint_satisfaction)
{
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_)
{
{
positions->set_stupid_solution (solution_try);
}
+
DOUT << "Finished Spring_spacer::solve ()...";
}
Line_of_cols
Spring_spacer::error_pcol_l_arr() const
{
- Array<Paper_column*> retval;
+ Link_array<Paper_column> retval;
for (int i=0; i< cols_.size(); i++)
if (cols_[i].ugh_b_)
retval.push (cols_[i].pcol_l_);
}
return retval;
}
-
+/*
+ Ugh. Should junk this.
+ */
void
-Spring_spacer::loosen_column (int i)
+Spring_spacer::loosen_column (int idx)
{
- Column_info 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;
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
}
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_);
}
for (int i=0; i < cols_.size(); i++)
{
+ Score_column * sc = scol_l(i);
Moment now = scol_l (i)->when();
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.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
/*
TODO: take out the refs to width
+
*/
/**
generate springs between columns.
- TODO: This needs rethinking.
+ TODO: This needs rethinking.......
* Spacing should take optical
effects into account
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_;
+ 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);
+ ideal_arr.push (-1.0);
+ hooke_arr.push (1.0);
}
/*
{
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 () ;
-
/*
ugh should use shortest_playing distance
*/
if (delta_t)
{
Real k= paper_l()->arithmetic_constant (context_shortest_arr[i]);
- durational_distance = paper_l()->duration_to_dist (delta_t,k);
+ 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] = 1; //2.0;
+ ideal_arr[i] = symbol_distance >? durational_distance;
+ hooke_arr[i] = 1; //2.0;
}
}
}
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);
+ Real dist = paper_l()->length_mom_to_dist (shortest_playing_len, k);
dist *= (double)(delta_t / shortest_playing_len);
/*
* 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
* 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
+ 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)->breakable_b_)
+ if (i && !scol_l (i - 1)->musical_b ())
{
- // fixed: probably should set minimum (rod/spring)?
- cols_[i-1].width_[RIGHT] += interline_f;
+ // 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);
+ 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)->breakable_b_)
+ if (i + 1 < cols_.size () && !scol_l(i+1)->musical_b ())
{
- // hmm, how bout?
- dist = dist >? interline_f;
+ // two interline minimum ok for last column?
+ dist = dist >? 2 * interline_f;
+ // set minimum rod
/*
- uhuh, this code looks fine, already?
- someone was junking this last "hinterfleisch" whitespace?!
+ urg: simply *adding* an interline leaves big gaps at
+ end of measure in star-spangled-banner (after lyrics
+ at eom).
- but this seems to be fixed now :-)
- */
- // set minimum rod
- cols_[i].width_[RIGHT] += interline_f;
+ 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
+ */
+
+ cols_[i].width_[RIGHT] = cols_[i].width_[RIGHT] >? 2 * interline_f;
}
// ugh, do we need this?
+ interline_f / 2;
dist = dist >? minimum;
}
- ideal_arr_[i] = dist;
+ ideal_arr[i] = dist;
}
}
- for (int i=0; i < ideal_arr_.size(); 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]);
}
}