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];
80 for (int j =0 ; j < 4; j++) {
81 if (clash_group_arr_a[j].size())
82 col_l_a[j] = clash_group_arr_a[j][0];
87 y_extent[j] = col_l_a[j]->head_positions_interval();
96 x_off[idx(d, true)] = d*0.5;
97 } while ((d *= -1) != 1);
101 Interval_t<int> middle( y_extent[0].min(), y_extent[3].max());
102 Interval_t<int> open_middle( y_extent[3].max()+1, y_extent[0].min()-1);
104 if (!open_middle.contains_b(y_extent[idx(d,true)]))
105 x_off[idx(d, true)] = d *1.0 ;
106 } while ((d *= -1) != 1);
108 if (!middle.empty_b() &&
109 middle.length() <= 1 && col_l_a[idx(1,0)] && col_l_a[idx(-1,0)]) {
110 Notehead * nu_l= col_l_a[idx(1,0)]->head_l_arr_[idx(1,0)];
111 Notehead * nd_l = col_l_a[idx(-1,0)]->head_l_arr_[idx(1,0)];
112 if (! (nu_l->balltype_i_ == nd_l->balltype_i_ && nu_l->dots_i_ == nd_l->dots_i_)) {
113 x_off[idx(1,0)] -= 0.5;
116 x_off[idx(-1,0)] += 0.5;
119 Real inter_f = paper()->internote();
120 Real wid_f = paper()->note_width();
121 for (int j=0; j < 4; j++) {
123 col_l_a[j]->translate(Offset(x_off[j] * wid_f,
124 y_off[j] * inter_f));
128 IMPLEMENT_STATIC_NAME(Collision);