2 collision.cc -- implement Collision
4 source file of the LilyPond music typesetter
6 (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
9 #include "collision.hh"
10 #include "note-column.hh"
11 #include "notehead.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 int idx(int dir, bool h_shift_b)
27 assert(abs (dir) == 1);
28 int j = dir > 0 ? 0 : 3;
34 /** This complicated routine moves note columns around horizontally
35 (and rests vertically) to ensure that notes don't clash.
37 This should be done better, probably.
39 This routine is dedicated to Stine Randmael :-)
43 Collision::do_pre_processing()
45 if (clash_l_arr_.size() <= 1)
49 [stem up, stem up shifted, stem down shifted, stem down]
51 Array<Note_column*> clash_group_arr_a[4];
53 for (int i=0; i < clash_l_arr_.size(); i++) {
54 Note_column* c_l = clash_l_arr_[i];
55 int d = (c_l->dir_i_);
57 clash_group_arr_a[idx(d, c_l->h_shift_b_)].push(c_l);
60 for (int j=0; j < 4; j++) {
61 if (clash_group_arr_a[j].size() > 1) {
62 warning("Too many clashing notecolumns. Ignoring them.");
68 if (!clash_group_arr_a[idx(d, false)].size()){
69 clash_group_arr_a[idx(d, false)] = clash_group_arr_a[idx(d, true)];
70 clash_group_arr_a[idx(d, true)].set_size(0);
72 } while ((d *= -1) != 1);
75 Interval_t<int> y_extent[4];
76 Note_column * col_l_a[4];
81 for (int j =0 ; j < 4; j++) {
82 if (clash_group_arr_a[j].size())
83 col_l_a[j] = clash_group_arr_a[j][0];
88 y_extent[j] = col_l_a[j]->head_positions_interval();
91 rest_b_a[j] = (col_l_a[j]) ? col_l_a[j]->rest_b_ : false;
97 x_off[idx(d, true)] = d*0.5;
98 } while ((d *= -1) != 1);
101 int i1 = idx(d, false);
102 int i2 = idx(d,true);
103 if (!intersection(y_extent[i1] ,
104 y_extent[i2]).empty_b()) {
106 y_off[i1] = -y_extent[i1][-d] + y_extent[1][d] + d*4; // ugh
107 y_extent[i1] += y_off[i1];
110 } while ((d *= -1) != 1);
113 int i1 = idx(d, false);
114 int i2 = idx(-d,false);
116 if (d*(y_extent[i1][-d] - y_extent[i2][d] )< 0&& rest_b_a[i1]) {
117 y_off[i1] = -y_extent[i1][-d] + y_extent[i2][d] +d* 4; // ugh
118 y_extent[i1] += y_off[i1];
120 } while ((d *= -1) != 1);
122 Interval_t<int> middle( y_extent[0].min(), y_extent[3].max());
123 Interval_t<int> open_middle( y_extent[3].max()+1, y_extent[0].min()-1);
125 if (!open_middle.contains_b(y_extent[idx(d,true)]))
126 x_off[idx(d, true)] = d *1.0 ;
127 } while ((d *= -1) != 1);
129 if (!middle.empty_b() &&
130 middle.length() <= 1 && col_l_a[idx(1,0)] && col_l_a[idx(-1,0)]
131 && !rest_b_a[idx(1,0)] && !rest_b_a[idx(-1,0)]) {
133 Notehead * nu_l= col_l_a[idx(1,0)]->head_l_arr_[idx(1,0)];
134 Notehead * nd_l = col_l_a[idx(-1,0)]->head_l_arr_[idx(1,0)];
135 if (! (nu_l->balltype == nd_l->balltype && nu_l->dots == nd_l->dots)) {
136 x_off[idx(1,0)] -= 0.5;
139 x_off[idx(-1,0)] += 0.5;
142 Real inter_f = paper()->internote();
143 Real wid_f = paper()->note_width();
144 for (int j=0; j < 4; j++) {
146 col_l_a[j]->translate(Offset(x_off[j] * wid_f,
147 y_off[j] * inter_f));
151 IMPLEMENT_STATIC_NAME(Collision);