2 collision.cc -- implement Collision
4 source file of the GNU LilyPond music typesetter
6 (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
9 #include "collision.hh"
10 #include "note-column.hh"
11 #include "note-head.hh"
12 #include "paper-def.hh"
14 Collision::Collision()
19 Collision::add(Note_column* ncol_l)
21 clash_l_arr_.push(ncol_l);
22 add_dependency(ncol_l);
25 should derive of Array.
28 int idx(int dir, bool h_shift_b)
30 assert(abs (dir) == 1);
31 int j = dir > 0 ? 0 : 3;
37 /** This complicated routine moves note columns around horizontally
38 (and rests vertically) to ensure that notes don't clash.
40 This should be done better, probably.
42 This routine is dedicated to Stine Randmael :-)
46 Collision::do_pre_processing()
48 if (clash_l_arr_.size() <= 1)
52 [stem up, stem up shifted, stem down shifted, stem down]
54 Array<Note_column*> clash_group_arr_a[4];
56 for (int i=0; i < clash_l_arr_.size(); i++) {
57 Note_column* c_l = clash_l_arr_[i];
59 warning ("No stem direction set. Ignoring column in clash. ");
62 int d = (c_l->dir_i_);
64 clash_group_arr_a[idx(d, c_l->h_shift_b_)].push(c_l);
68 for (int j=0; j < 4; j++) {
69 if (clash_group_arr_a[j].size() > 1) {
70 warning("Too many clashing notecolumns. Ignoring them.");
76 if (!clash_group_arr_a[idx(d, false)].size()){
77 clash_group_arr_a[idx(d, false)] = clash_group_arr_a[idx(d, true)];
78 clash_group_arr_a[idx(d, true)].set_size(0);
80 } while ((d *= -1) != 1);
83 Interval_t<int> y_extent[4];
84 Note_column * col_l_a[4];
88 for (int j =0 ; j < 4; j++) {
89 if (clash_group_arr_a[j].size())
90 col_l_a[j] = clash_group_arr_a[j][0];
95 y_extent[j] = col_l_a[j]->head_positions_interval();
104 x_off[idx(d, true)] = d*0.5;
105 } while ((d *= -1) != 1);
108 // y_extent: smallest y-pos noteball interval containing all balls
109 // 4 (0..3) groups: stem up/down; shift on/off;
110 Interval_t<int> middle( y_extent[idx(-1,0)].max(),
111 y_extent[idx(1,0)].min() );
112 Interval_t<int> open_middle( y_extent[idx(-1,0)].max()+1, y_extent[idx(1,0)].min()-1);
114 if (!open_middle.contains_b(y_extent[idx(d,true)]))
115 x_off[idx(d, true)] = d *1.0 ;
116 } while ((d *= -1) != 1);
118 if (!middle.empty_b()
119 && middle.length() < 2 && col_l_a[idx(1,0)] && col_l_a[idx(-1,0)]) {
120 // reproduction of bugfix at 3am ?
121 Note_head * nu_l= col_l_a[idx(1,0)]->head_l_arr_[0];
122 Note_head * nd_l = col_l_a[idx(-1,0)]->head_l_arr_.top();
123 if (! (nu_l->balltype_i_ == nd_l->balltype_i_
124 && nu_l->dots_i_ == nd_l->dots_i_ && middle.length() == 0 )) {
125 x_off[idx(1,0)] -= 0.5;
126 x_off[idx(1,1)] -= 0.5;
127 x_off[idx(-1,1)] += 0.5;
128 x_off[idx(-1,0)] += 0.5;
132 Real inter_f = paper()->internote_f();
133 Real wid_f = paper()->note_width();
134 for (int j=0; j < 4; j++) {
136 col_l_a[j]->translate(Offset(x_off[j] * wid_f,
137 y_off[j] * inter_f));
142 IMPLEMENT_STATIC_NAME(Collision);
143 IMPLEMENT_IS_TYPE_B1(Collision, Item);
146 Collision::do_substitute_dependency(Score_elem*o_l,Score_elem*n_l)
148 clash_l_arr_.substitute((Note_column*)o_l->item(),
149 (Note_column*)(n_l?n_l->item():0));