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);
26 int idx(int dir, bool h_shift_b)
28 assert(abs (dir) == 1);
29 int j = dir > 0 ? 0 : 3;
35 /** This complicated routine moves note columns around horizontally
36 (and rests vertically) to ensure that notes don't clash.
38 This should be done better, probably.
40 This routine is dedicated to Stine Randmael :-)
44 Collision::do_pre_processing()
46 if (clash_l_arr_.size() <= 1)
50 [stem up, stem up shifted, stem down shifted, stem down]
52 Array<Note_column*> clash_group_arr_a[4];
54 for (int i=0; i < clash_l_arr_.size(); i++) {
55 Note_column* c_l = clash_l_arr_[i];
57 warning ("No stem direction set. Ignoring column in clash. ");
60 int d = (c_l->dir_i_);
62 clash_group_arr_a[idx(d, c_l->h_shift_b_)].push(c_l);
66 for (int j=0; j < 4; j++) {
67 if (clash_group_arr_a[j].size() > 1) {
68 warning("Too many clashing notecolumns. Ignoring them.");
74 if (!clash_group_arr_a[idx(d, false)].size()){
75 clash_group_arr_a[idx(d, false)] = clash_group_arr_a[idx(d, true)];
76 clash_group_arr_a[idx(d, true)].set_size(0);
78 } while ((d *= -1) != 1);
81 Interval_t<int> y_extent[4];
82 Note_column * col_l_a[4];
86 for (int j =0 ; j < 4; j++) {
87 if (clash_group_arr_a[j].size())
88 col_l_a[j] = clash_group_arr_a[j][0];
93 y_extent[j] = col_l_a[j]->head_positions_interval();
102 x_off[idx(d, true)] = d*0.5;
103 } while ((d *= -1) != 1);
106 // y_extent: smallest y-pos noteball interval containing all balls
107 // 4 (0..3) groups: stem up/down; shift on/off;
108 Interval_t<int> middle( y_extent[0].min(), y_extent[3].max());
109 Interval_t<int> open_middle( y_extent[3].max()+1, y_extent[0].min()-1);
111 if (!open_middle.contains_b(y_extent[idx(d,true)]))
112 x_off[idx(d, true)] = d *1.0 ;
113 } while ((d *= -1) != 1);
115 if (!middle.empty_b() &&
116 middle.length() <= 2 && col_l_a[idx(1,0)] && col_l_a[idx(-1,0)]) {
117 // reproduction of bugfix at 3am ?
118 Notehead * nu_l= col_l_a[idx(1,0)]->head_l_arr_[0];
119 Notehead * nd_l = col_l_a[idx(-1,0)]->head_l_arr_.top();
120 if (! (nu_l->balltype_i_ == nd_l->balltype_i_ && nu_l->dots_i_ == nd_l->dots_i_)) {
121 x_off[idx(1,0)] -= 0.5;
124 x_off[idx(-1,0)] += 0.5;
127 Real inter_f = paper()->internote();
128 Real wid_f = paper()->note_width();
129 for (int j=0; j < 4; j++) {
131 col_l_a[j]->translate(Offset(x_off[j] * wid_f,
132 y_off[j] * inter_f));
137 IMPLEMENT_STATIC_NAME(Collision);