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"
13 #include "ly-symbols.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 ()->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.
59 Collision::automatic_shift ()
61 Drul_array<Link_array<Note_column> > clash_groups;
62 Drul_array<Array<int> > shifts;
63 Array<Shift_tup> tups;
66 for (int i=0; i < clash_l_arr_.size(); i++)
68 clash_groups[clash_l_arr_[i]->dir ()].push (clash_l_arr_[i]);
75 Array<int> & shift (shifts[d]);
76 Link_array<Note_column> & clashes (clash_groups[d]);
78 clashes.sort (Note_column::shift_compare);
80 for (int i=0; i < clashes.size (); i++)
83 = clashes[i]->remove_elt_property (horizontal_shift_scm_sym);
88 shift.push (gh_scm2int (SCM_CDR (sh)));
91 for (int i=1; i < shift.size (); i++)
93 if (shift[i-1] == shift[i])
95 warning (_ ("Too many clashing notecolumns. Ignoring them."));
100 while ((flip (&d))!= UP);
102 Drul_array< Array < Slice > > extents;
103 Drul_array< Array < Real > > offsets;
107 for (int i=0; i < clash_groups[d].size (); i++)
109 Slice s(clash_groups[d][i]->head_positions_interval ());
113 offsets[d].push (d * 0.5 * i);
116 while ((flip (&d))!= UP);
120 for (int i=1; i < clash_groups[d].size (); i++)
122 Slice prev =extents[d][i-1];
123 prev.intersect (extents[d][i]);
124 if (prev.length ()> 0 ||
125 (extents[-d].size () && d * (extents[d][i][-d] - extents[-d][0][d]) < 0))
126 for (int j = i; j < clash_groups[d].size (); j++)
127 offsets[d][j] += d * 0.5;
130 while ((flip (&d))!= UP);
133 if the up and down version are close, and can not be merged, move
134 all of them again. */
135 if (extents[UP].size () && extents[DOWN].size ())
137 Note_column *cu_l =clash_groups[UP][0];
138 Note_column *cd_l =clash_groups[DOWN][0];
139 Note_head * nu_l= cu_l->head_l_arr_[0];
140 Note_head * nd_l = cd_l->head_l_arr_.top();
141 int downpos = cd_l->head_positions_interval ()[BIGGER];
142 int uppos = cu_l->head_positions_interval ()[SMALLER];
146 && nu_l->balltype_i_ == nd_l->balltype_i_
147 && nu_l->dots_i () == nd_l->dots_i ();
150 notes are close, but can not be merged. Shift
152 if (abs(uppos - downpos) < 2 && !merge)
155 for (int i=0; i < clash_groups[d].size (); i++)
157 offsets[d][i] -= d * 0.5;
160 while ((flip (&d))!= UP);
166 for (int i=0; i < clash_groups[d].size (); i++)
167 tups.push (Shift_tup (clash_groups[d][i], offsets[d][i]));
169 while (flip (&d) != UP);
175 Collision::forced_shift ()
177 Array<Shift_tup> tups;
179 for (int i=0; i < clash_l_arr_.size (); i++)
181 SCM force = clash_l_arr_[i]->remove_elt_property (force_hshift_scm_sym);
182 if (force != SCM_BOOL_F)
184 force = SCM_CDR (force);
185 tups. push (Shift_tup (clash_l_arr_[i],
186 gh_scm2double (force)));
194 Collision::do_substitute_element_pointer (Score_element*o_l,Score_element*n_l)
198 clash_l_arr_.substitute (dynamic_cast<Note_column *> (o_l),
199 dynamic_cast <Note_column *> (n_l));