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];
56 warning ("No stem direction set. Ignoring column in clash. ");
59 int d = (c_l->dir_i_);
61 clash_group_arr_a[idx(d, c_l->h_shift_b_)].push(c_l);
65 for (int j=0; j < 4; j++) {
66 if (clash_group_arr_a[j].size() > 1) {
67 warning("Too many clashing notecolumns. Ignoring them.");
73 if (!clash_group_arr_a[idx(d, false)].size()){
74 clash_group_arr_a[idx(d, false)] = clash_group_arr_a[idx(d, true)];
75 clash_group_arr_a[idx(d, true)].set_size(0);
77 } while ((d *= -1) != 1);
80 Interval_t<int> y_extent[4];
81 Note_column * col_l_a[4];
85 for (int j =0 ; j < 4; j++) {
86 if (clash_group_arr_a[j].size())
87 col_l_a[j] = clash_group_arr_a[j][0];
92 y_extent[j] = col_l_a[j]->head_positions_interval();
101 x_off[idx(d, true)] = d*0.5;
102 } while ((d *= -1) != 1);
106 Interval_t<int> middle( y_extent[0].min(), y_extent[3].max());
107 Interval_t<int> open_middle( y_extent[3].max()+1, y_extent[0].min()-1);
109 if (!open_middle.contains_b(y_extent[idx(d,true)]))
110 x_off[idx(d, true)] = d *1.0 ;
111 } while ((d *= -1) != 1);
113 if (!middle.empty_b() &&
114 middle.length() <= 1 && col_l_a[idx(1,0)] && col_l_a[idx(-1,0)]) {
115 Notehead * nu_l= col_l_a[idx(1,0)]->head_l_arr_[idx(1,0)];
116 Notehead * nd_l = col_l_a[idx(-1,0)]->head_l_arr_[idx(1,0)];
117 if (! (nu_l->balltype_i_ == nd_l->balltype_i_ && nu_l->dots_i_ == nd_l->dots_i_)) {
118 x_off[idx(1,0)] -= 0.5;
121 x_off[idx(-1,0)] += 0.5;
124 Real inter_f = paper()->internote();
125 Real wid_f = paper()->note_width();
126 for (int j=0; j < 4; j++) {
128 col_l_a[j]->translate(Offset(x_off[j] * wid_f,
129 y_off[j] * inter_f));
133 IMPLEMENT_STATIC_NAME(Collision);