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()
16 empty_b_ = transparent_b_ =true;
20 Collision::add(Note_column* ncol_l)
22 clash_l_arr_.push(ncol_l);
23 add_element( ncol_l );
24 add_dependency(ncol_l);
27 should derive of Array.
30 int idx(int dir, bool h_shift_b)
32 assert(abs (dir) == 1);
33 int j = dir > 0 ? 0 : 3;
39 /** This complicated routine moves note columns around horizontally
40 (and rests vertically) to ensure that notes don't clash.
42 This should be done better, probably.
44 This routine is dedicated to Stine Randmael :-)
48 Collision::do_pre_processing()
50 if (clash_l_arr_.size() <= 1)
54 [stem up, stem up shifted, stem down shifted, stem down]
56 Array<Note_column*> clash_group_arr_a[4];
58 for (int i=0; i < clash_l_arr_.size(); i++) {
59 Note_column* c_l = clash_l_arr_[i];
61 warning ("No stem direction set. Ignoring column in clash. ");
64 int d = (c_l->dir_i_);
66 clash_group_arr_a[idx(d, c_l->h_shift_b_)].push(c_l);
70 for (int j=0; j < 4; j++) {
71 if (clash_group_arr_a[j].size() > 1) {
72 warning("Too many clashing notecolumns. Ignoring them.");
78 if (!clash_group_arr_a[idx(d, false)].size()){
79 clash_group_arr_a[idx(d, false)] = clash_group_arr_a[idx(d, true)];
80 clash_group_arr_a[idx(d, true)].clear();
82 } while ((d *= -1) != 1);
85 Interval_t<int> y_extent[4];
86 Note_column * col_l_a[4];
90 for (int j =0 ; j < 4; j++) {
91 if (clash_group_arr_a[j].size())
92 col_l_a[j] = clash_group_arr_a[j][0];
97 y_extent[j] = col_l_a[j]->head_positions_interval();
106 x_off[idx(d, true)] = d*0.5;
107 } while ((d *= -1) != 1);
110 // y_extent: smallest y-pos noteball interval containing all balls
111 // 4 (0..3) groups: stem up/down; shift on/off;
112 Interval_t<int> middle( y_extent[idx(-1,0)].max(),
113 y_extent[idx(1,0)].min() );
114 Interval_t<int> open_middle( y_extent[idx(-1,0)].max()+1, y_extent[idx(1,0)].min()-1);
116 if (!open_middle.contains_b(y_extent[idx(d,true)]))
117 x_off[idx(d, true)] = d *1.0 ;
118 } while ((d *= -1) != 1);
120 if (!middle.empty_b()
121 && middle.length() < 2 && col_l_a[idx(1,0)] && col_l_a[idx(-1,0)]) {
122 // reproduction of bugfix at 3am ?
123 Note_head * nu_l= col_l_a[idx(1,0)]->head_l_arr_[0];
124 Note_head * nd_l = col_l_a[idx(-1,0)]->head_l_arr_.top();
125 if (! (nu_l->balltype_i_ == nd_l->balltype_i_
126 && nu_l->dots_i_ == nd_l->dots_i_ && middle.length() == 0 )) {
127 x_off[idx(1,0)] -= 0.5;
128 x_off[idx(1,1)] -= 0.5;
129 x_off[idx(-1,1)] += 0.5;
130 x_off[idx(-1,0)] += 0.5;
134 Real inter_f = paper()->internote_f();
135 Real wid_f = paper()->note_width();
136 for (int j=0; j < 4; j++) {
138 /* collision.cc:138: request for method `translate' is ambiguous
142 Offset o(x_off[j] * wid_f, y_off[j] * inter_f);
143 ((Score_elem*)col_l_a[j])->translate(o);
149 IMPLEMENT_IS_TYPE_B1(Collision, Item);
152 Collision::do_substitute_dependency(Score_elem*o_l,Score_elem*n_l)
154 clash_l_arr_.substitute((Note_column*)o_l->item(),
155 (Note_column*)(n_l?n_l->item():0));