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"
15 Collision::Collision()
17 set_axes (X_AXIS, Y_AXIS);
21 Collision::add_column (Note_column* ncol_l)
23 clash_l_arr_.push (ncol_l);
25 add_dependency (ncol_l);
29 /** This complicated routine moves note columns around horizontally to
30 ensure that notes don't clash.
32 This should be done better, probably.
38 Collision::do_pre_processing()
40 Drul_array<Link_array<Note_column> > clash_groups;
41 Drul_array<Array<int> > shifts;
43 for (int i=0; i < clash_l_arr_.size(); i++)
45 clash_groups[clash_l_arr_[i]->dir ()].push (clash_l_arr_[i]);
52 Array<int> & shift (shifts[d]);
53 Link_array<Note_column> & clashes (clash_groups[d]);
55 clashes.sort (Note_column::shift_compare);
57 for (int i=0; i < clashes.size (); i++)
60 = clashes[i]->remove_elt_property (horizontal_shift_scm_sym);
65 shift.push (gh_scm2int (SCM_CDR (sh)));
68 for (int i=1; i < shift.size (); i++)
70 if (shift[i-1] == shift[i])
72 warning (_ ("Too many clashing notecolumns. Ignoring them."));
77 while ((flip (&d))!= UP);
79 Drul_array< Array < Slice > > extents;
80 Drul_array< Array < Real > > offsets;
84 for (int i=0; i < clash_groups[d].size (); i++)
86 Slice s(clash_groups[d][i]->head_positions_interval ());
90 offsets[d].push (d * 0.5 * i);
93 while ((flip (&d))!= UP);
97 for (int i=1; i < clash_groups[d].size (); i++)
99 Slice prev =extents[d][i-1];
100 prev.intersect (extents[d][i]);
101 if (prev.length ()> 0 ||
102 (extents[-d].size () && d * (extents[d][i][-d] - extents[-d][0][d]) < 0))
103 for (int j = i; j < clash_groups[d].size (); j++)
104 offsets[d][j] += d * 0.5;
107 while ((flip (&d))!= UP);
110 if the up and down version are close, and can not be merged, move
111 all of them again. */
112 if (extents[UP].size () && extents[DOWN].size ())
114 Note_column *cu_l =clash_groups[UP][0];
115 Note_column *cd_l =clash_groups[DOWN][0];
116 Note_head * nu_l= cu_l->head_l_arr_[0];
117 Note_head * nd_l = cd_l->head_l_arr_.top();
118 int downpos = cd_l->head_positions_interval ()[BIGGER];
119 int uppos = cu_l->head_positions_interval ()[SMALLER];
123 && nu_l->balltype_i_ == nd_l->balltype_i_
124 && nu_l->dots_i_ == nd_l->dots_i_;
127 notes are close, but can not be merged. Shift
129 if (abs(uppos - downpos) < 2 && !merge)
132 for (int i=0; i < clash_groups[d].size (); i++)
134 offsets[d][i] -= d * 0.5;
137 while ((flip (&d))!= UP);
141 for (int i=0; i < clash_groups[d].size (); i++)
143 SCM force = clash_groups[d][i]->remove_elt_property (force_hshift_scm_sym);
144 if (force != SCM_BOOL_F)
146 force = SCM_CDR (force);
147 offsets[d][i] = gh_scm2double (force);
151 while ((flip (&d))!= UP);
153 Real wid_f = paper_l ()->note_width ();
156 for (int i=0; i < clash_groups[d].size (); i++)
158 clash_groups[d][i]->translate_axis (offsets[d][i]*wid_f, X_AXIS);
161 while (flip (&d) != UP);
166 Collision::do_substitute_element_pointer (Score_element*o_l,Score_element*n_l)
170 clash_l_arr_.substitute (dynamic_cast<Note_column *> (o_l),
171 dynamic_cast <Note_column *> (n_l));