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);
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++)
59 Note_column* c_l = clash_l_arr_[i];
62 warning ("No stem direction set. Ignoring column in clash. ");
65 int d = (c_l->dir_i_);
67 clash_group_arr_a[idx (d, c_l->h_shift_b_)].push (c_l);
71 for (int j=0; j < 4; j++)
73 if (clash_group_arr_a[j].size() > 1)
75 warning ("Too many clashing notecolumns. Ignoring them.");
82 if (!clash_group_arr_a[idx (d, false)].size())
84 clash_group_arr_a[idx (d, false)] = clash_group_arr_a[idx (d, true)];
85 clash_group_arr_a[idx (d, true)].clear();
87 } while ((d *= -1) != 1);
90 Interval_t<int> y_extent[4];
91 Note_column * col_l_a[4];
95 for (int j =0 ; j < 4; j++)
97 if (clash_group_arr_a[j].size())
98 col_l_a[j] = clash_group_arr_a[j][0];
104 y_extent[j] = col_l_a[j]->head_positions_interval();
114 x_off[idx (d, true)] = d*0.5;
115 } while ((d *= -1) != 1);
118 // y_extent: smallest y-pos noteball interval containing all balls
119 // 4 (0..3) groups: stem up/down; shift on/off;
120 Interval_t<int> middle (y_extent[idx (-1,0)].max(),
121 y_extent[idx (1,0)].min());
122 Interval_t<int> open_middle (y_extent[idx (-1,0)].max()+1, y_extent[idx (1,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() < 2 && col_l_a[idx (1,0)] && col_l_a[idx (-1,0)]) {
131 // reproduction of bugfix at 3am ?
132 Note_head * nu_l= col_l_a[idx (1,0)]->head_l_arr_[0];
133 Note_head * nd_l = col_l_a[idx (-1,0)]->head_l_arr_.top();
134 if (! (nu_l->balltype_i_ == nd_l->balltype_i_
135 && nu_l->dots_i_ == nd_l->dots_i_ && middle.length() == 0))
137 x_off[idx (1,0)] -= 0.5;
138 x_off[idx (1,1)] -= 0.5;
139 x_off[idx (-1,1)] += 0.5;
140 x_off[idx (-1,0)] += 0.5;
144 Real inter_f = paper()->internote_f ();
145 Real wid_f = paper()->note_width ();
146 for (int j=0; j < 4; j++)
150 /* collision.cc:138: request for method `translate' is ambiguous
154 Offset o (x_off[j] * wid_f, y_off[j] * inter_f);
155 ((Score_elem*)col_l_a[j])->translate (o);
161 IMPLEMENT_IS_TYPE_B1(Collision, Item);
164 Collision::do_substitute_dependency (Score_elem*o_l,Score_elem*n_l)
166 clash_l_arr_.substitute ((Note_column*)o_l->item(),
167 (Note_column*)(n_l?n_l->item():0));