2 collision.cc -- implement Collision
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--1999 Han-Wen Nienhuys <hanwen@cs.uu.nl>
9 #include "collision.hh"
10 #include "note-column.hh"
11 #include "note-head.hh"
12 #include "paper-def.hh"
16 Collision::Collision()
18 set_axes (X_AXIS, Y_AXIS);
22 Collision::add_column (Note_column* ncol_l)
24 clash_l_arr_.push (ncol_l);
26 add_dependency (ncol_l);
30 Collision::do_pre_processing()
32 Array<Shift_tup> autos (automatic_shift ());
33 Array<Shift_tup> hand (forced_shift ());
34 Link_array<Note_column> done;
36 Real wid = paper_l ()->get_var ("collision_note_width");
37 for (int i=0; i < hand.size (); i++)
39 hand[i].e1_->translate_axis (hand[i].e2_ *wid, X_AXIS);
40 done.push (hand[i].e1_);
43 for (int i=0; i < autos.size (); i++)
45 if (!done.find_l (autos[i].e1_))
46 autos[i].e1_->translate_axis (autos[i].e2_ * wid, X_AXIS);
50 /** This complicated routine moves note columns around horizontally to
51 ensure that notes don't clash.
53 This should be done better, probably.
57 Collision::automatic_shift ()
59 Drul_array<Link_array<Note_column> > clash_groups;
60 Drul_array<Array<int> > shifts;
61 Array<Shift_tup> tups;
64 for (int i=0; i < clash_l_arr_.size(); i++)
66 clash_groups[clash_l_arr_[i]->dir ()].push (clash_l_arr_[i]);
73 Array<int> & shift (shifts[d]);
74 Link_array<Note_column> & clashes (clash_groups[d]);
76 clashes.sort (Note_column::shift_compare);
78 for (int i=0; i < clashes.size (); i++)
81 = clashes[i]->remove_elt_property ("horizontal-shift");
84 shift.push (gh_scm2int (sh));
89 for (int i=1; i < shift.size (); i++)
91 if (shift[i-1] == shift[i])
93 warning (_ ("Too many clashing notecolumns. Ignoring them."));
98 while ((flip (&d))!= UP);
100 Drul_array< Array < Slice > > extents;
101 Drul_array< Array < Real > > offsets;
105 for (int i=0; i < clash_groups[d].size (); i++)
107 Slice s(clash_groups[d][i]->head_positions_interval ());
111 offsets[d].push (d * 0.5 * i);
114 while ((flip (&d))!= UP);
118 for (int i=1; i < clash_groups[d].size (); i++)
120 Slice prev =extents[d][i-1];
121 prev.intersect (extents[d][i]);
122 if (prev.length ()> 0 ||
123 (extents[-d].size () && d * (extents[d][i][-d] - extents[-d][0][d]) < 0))
124 for (int j = i; j < clash_groups[d].size (); j++)
125 offsets[d][j] += d * 0.5;
128 while ((flip (&d))!= UP);
131 if the up and down version are close, and can not be merged, move
132 all of them again. */
133 if (extents[UP].size () && extents[DOWN].size ())
135 Note_column *cu_l =clash_groups[UP][0];
136 Note_column *cd_l =clash_groups[DOWN][0];
137 Note_head * nu_l= cu_l->head_l_arr_[0];
138 Note_head * nd_l = cd_l->head_l_arr_.top();
139 int downpos = cd_l->head_positions_interval ()[BIGGER];
140 int uppos = cu_l->head_positions_interval ()[SMALLER];
144 && nu_l->balltype_i_ == nd_l->balltype_i_
145 && nu_l->dots_i () == nd_l->dots_i ();
148 notes are close, but can not be merged. Shift
150 if (abs(uppos - downpos) < 2 && !merge)
153 for (int i=0; i < clash_groups[d].size (); i++)
155 offsets[d][i] -= d * 0.5;
158 while ((flip (&d))!= UP);
164 for (int i=0; i < clash_groups[d].size (); i++)
165 tups.push (Shift_tup (clash_groups[d][i], offsets[d][i]));
167 while (flip (&d) != UP);
173 Collision::forced_shift ()
175 Array<Shift_tup> tups;
177 for (int i=0; i < clash_l_arr_.size (); i++)
179 SCM force = clash_l_arr_[i]->remove_elt_property ("force-hshift");
180 if (force != SCM_UNDEFINED)
182 tups. push (Shift_tup (clash_l_arr_[i], gh_scm2double (force)));
190 Collision::do_substitute_element_pointer (Score_element*o_l,Score_element*n_l)
194 clash_l_arr_.substitute (dynamic_cast<Note_column *> (o_l),
195 dynamic_cast <Note_column *> (n_l));