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_dependency(ncol_l);
26 should derive of Array.
29 int idx(int dir, bool h_shift_b)
31 assert(abs (dir) == 1);
32 int j = dir > 0 ? 0 : 3;
38 /** This complicated routine moves note columns around horizontally
39 (and rests vertically) to ensure that notes don't clash.
41 This should be done better, probably.
43 This routine is dedicated to Stine Randmael :-)
47 Collision::do_pre_processing()
49 if (clash_l_arr_.size() <= 1)
53 [stem up, stem up shifted, stem down shifted, stem down]
55 Array<Note_column*> clash_group_arr_a[4];
57 for (int i=0; i < clash_l_arr_.size(); i++) {
58 Note_column* c_l = clash_l_arr_[i];
60 warning ("No stem direction set. Ignoring column in clash. ");
63 int d = (c_l->dir_i_);
65 clash_group_arr_a[idx(d, c_l->h_shift_b_)].push(c_l);
69 for (int j=0; j < 4; j++) {
70 if (clash_group_arr_a[j].size() > 1) {
71 warning("Too many clashing notecolumns. Ignoring them.");
77 if (!clash_group_arr_a[idx(d, false)].size()){
78 clash_group_arr_a[idx(d, false)] = clash_group_arr_a[idx(d, true)];
79 clash_group_arr_a[idx(d, true)].set_size(0);
81 } while ((d *= -1) != 1);
84 Interval_t<int> y_extent[4];
85 Note_column * col_l_a[4];
89 for (int j =0 ; j < 4; j++) {
90 if (clash_group_arr_a[j].size())
91 col_l_a[j] = clash_group_arr_a[j][0];
96 y_extent[j] = col_l_a[j]->head_positions_interval();
105 x_off[idx(d, true)] = d*0.5;
106 } while ((d *= -1) != 1);
109 // y_extent: smallest y-pos noteball interval containing all balls
110 // 4 (0..3) groups: stem up/down; shift on/off;
111 Interval_t<int> middle( y_extent[idx(-1,0)].max(),
112 y_extent[idx(1,0)].min() );
113 Interval_t<int> open_middle( y_extent[idx(-1,0)].max()+1, y_extent[idx(1,0)].min()-1);
115 if (!open_middle.contains_b(y_extent[idx(d,true)]))
116 x_off[idx(d, true)] = d *1.0 ;
117 } while ((d *= -1) != 1);
119 if (!middle.empty_b()
120 && middle.length() < 2 && col_l_a[idx(1,0)] && col_l_a[idx(-1,0)]) {
121 // reproduction of bugfix at 3am ?
122 Note_head * nu_l= col_l_a[idx(1,0)]->head_l_arr_[0];
123 Note_head * nd_l = col_l_a[idx(-1,0)]->head_l_arr_.top();
124 if (! (nu_l->balltype_i_ == nd_l->balltype_i_
125 && nu_l->dots_i_ == nd_l->dots_i_ && middle.length() == 0 )) {
126 x_off[idx(1,0)] -= 0.5;
127 x_off[idx(1,1)] -= 0.5;
128 x_off[idx(-1,1)] += 0.5;
129 x_off[idx(-1,0)] += 0.5;
133 Real inter_f = paper()->internote_f();
134 Real wid_f = paper()->note_width();
135 for (int j=0; j < 4; j++) {
137 col_l_a[j]->translate(Offset(x_off[j] * wid_f,
138 y_off[j] * inter_f));
143 IMPLEMENT_STATIC_NAME(Collision);
144 IMPLEMENT_IS_TYPE_B1(Collision, Item);
147 Collision::do_substitute_dependency(Score_elem*o_l,Score_elem*n_l)
149 clash_l_arr_.substitute((Note_column*)o_l->item(),
150 (Note_column*)(n_l?n_l->item():0));