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"
14 Collision::Collision()
16 set_axes (X_AXIS, Y_AXIS);
20 Collision::add_column (Note_column* ncol_l)
23 clash_l_arr_.push (ncol_l);
25 add_dependency (ncol_l);
28 should derive of Array.
31 int idx (int dir, bool h_shift_b)
33 assert (abs (dir) == 1);
34 int j = dir > 0 ? 0 : 3;
40 /** This complicated routine moves note columns around horizontally
41 (and rests vertically) to ensure that notes don't clash.
43 This should be done better, probably.
45 This routine is dedicated to Stine Randmael :-)
49 Collision::do_pre_processing()
51 if (clash_l_arr_.size() <= 1)
55 [stem up, stem up shifted, stem down shifted, stem down]
57 Array<Note_column*> clash_group_arr_a[4];
59 for (int i=0; i < clash_l_arr_.size(); i++)
61 Note_column* c_l = clash_l_arr_[i];
64 warning (_ ("No stem direction set. Ignoring column in clash."));
69 SCM shift = c_l->remove_elt_property (horizontal_shift_scm_sym);
70 bool shift_b = (shift != SCM_BOOL_F);
71 clash_group_arr_a[idx (d, shift_b)].push (c_l);
75 for (int j=0; j < 4; j++)
77 if (clash_group_arr_a[j].size() > 1)
79 warning (_ ("Too many clashing notecolumns. Ignoring them."));
86 if (!clash_group_arr_a[idx (d, false)].size())
88 clash_group_arr_a[idx (d, false)] = clash_group_arr_a[idx (d, true)];
89 clash_group_arr_a[idx (d, true)].clear();
92 while ((d *= -1) != 1);
95 Interval_t<int> y_extent[4];
96 Note_column * col_l_a[4];
99 for (int j =0 ; j < 4; j++)
101 if (clash_group_arr_a[j].size())
102 col_l_a[j] = clash_group_arr_a[j][0];
108 y_extent[j] = col_l_a[j]->head_positions_interval();
117 x_off[idx (d, true)] = d*0.5;
119 while ((d *= -1) != 1);
122 // y_extent: smallest y-pos noteball interval containing all balls
123 // 4 (0..3) groups: stem up/down; shift on/off;
124 Interval_t<int> middle (y_extent[idx (-1,0)].max(),
125 y_extent[idx (1,0)].min());
126 Interval_t<int> open_middle (y_extent[idx (-1,0)].max()+1, y_extent[idx (1,0)].min ()-1);
129 if (!open_middle.contains_b (y_extent[idx (d,true)]))
130 x_off[idx (d, true)] = d *1.0 ;
131 } while ((d *= -1) != 1);
133 if (!middle.empty_b()
134 && middle.length() < 2 && col_l_a[idx (1,0)] && col_l_a[idx (-1,0)]) {
135 // reproduction of bugfix at 3am ?
136 Note_head * nu_l= col_l_a[idx (1,0)]->head_l_arr_[0];
137 Note_head * nd_l = col_l_a[idx (-1,0)]->head_l_arr_.top();
138 if (! (nu_l->balltype_i_ == nd_l->balltype_i_
139 && nu_l->dots_i_ == nd_l->dots_i_ && middle.length() == 0))
141 x_off[idx (1,0)] -= 0.5;
142 x_off[idx (1,1)] -= 0.5;
143 x_off[idx (-1,1)] += 0.5;
144 x_off[idx (-1,0)] += 0.5;
149 Real wid_f = paper_l ()->note_width ();
150 for (int j=0; j < 4; j++)
154 /* collision.cc:138: request for method `translate' is ambiguous
158 Offset o (x_off[j] * wid_f, 0);
159 col_l_a[j]->translate (o);
160 // ((Score_element*)col_l_a[j])->translate (o);
169 Collision::do_substitute_element_pointer (Score_element*o_l,Score_element*n_l)
173 clash_l_arr_.substitute (dynamic_cast<Note_column *> (o_l),
174 dynamic_cast <Note_column *> (n_l));