2 collision.cc -- implement Collision
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--1998 Han-Wen Nienhuys <hanwen@cs.uu.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_column (Note_column* ncol_l)
22 clash_l_arr_.push (ncol_l);
24 add_dependency (ncol_l);
27 should derive of Array.
30 int idx (int dir, bool h_shift_b)
32 assert (abs (dir) == 1);
33 int j = dir > 0 ? 0 : 3;
39 /** This complicated routine moves note columns around horizontally
40 (and rests vertically) to ensure that notes don't clash.
42 This should be done better, probably.
44 This routine is dedicated to Stine Randmael :-)
48 Collision::do_pre_processing()
50 if (clash_l_arr_.size() <= 1)
54 [stem up, stem up shifted, stem down shifted, stem down]
56 Array<Note_column*> clash_group_arr_a[4];
58 for (int i=0; i < clash_l_arr_.size(); i++)
60 Note_column* c_l = clash_l_arr_[i];
63 warning (_ ("No stem direction set. Ignoring column in clash."));
68 clash_group_arr_a[idx (d, c_l->h_shift_b_)].push (c_l);
72 for (int j=0; j < 4; j++)
74 if (clash_group_arr_a[j].size() > 1)
76 warning (_ ("Too many clashing notecolumns. Ignoring them."));
83 if (!clash_group_arr_a[idx (d, false)].size())
85 clash_group_arr_a[idx (d, false)] = clash_group_arr_a[idx (d, true)];
86 clash_group_arr_a[idx (d, true)].clear();
89 while ((d *= -1) != 1);
92 Interval_t<int> y_extent[4];
93 Note_column * col_l_a[4];
97 for (int j =0 ; j < 4; j++)
99 if (clash_group_arr_a[j].size())
100 col_l_a[j] = clash_group_arr_a[j][0];
106 y_extent[j] = col_l_a[j]->head_positions_interval();
116 x_off[idx (d, true)] = d*0.5;
118 while ((d *= -1) != 1);
121 // y_extent: smallest y-pos noteball interval containing all balls
122 // 4 (0..3) groups: stem up/down; shift on/off;
123 Interval_t<int> middle (y_extent[idx (-1,0)].max(),
124 y_extent[idx (1,0)].min());
125 Interval_t<int> open_middle (y_extent[idx (-1,0)].max()+1, y_extent[idx (1,0)].min ()-1);
128 if (!open_middle.contains_b (y_extent[idx (d,true)]))
129 x_off[idx (d, true)] = d *1.0 ;
130 } while ((d *= -1) != 1);
132 if (!middle.empty_b()
133 && middle.length() < 2 && col_l_a[idx (1,0)] && col_l_a[idx (-1,0)]) {
134 // reproduction of bugfix at 3am ?
135 Note_head * nu_l= col_l_a[idx (1,0)]->head_l_arr_[0];
136 Note_head * nd_l = col_l_a[idx (-1,0)]->head_l_arr_.top();
137 if (! (nu_l->balltype_i_ == nd_l->balltype_i_
138 && nu_l->dots_i_ == nd_l->dots_i_ && middle.length() == 0))
140 x_off[idx (1,0)] -= 0.5;
141 x_off[idx (1,1)] -= 0.5;
142 x_off[idx (-1,1)] += 0.5;
143 x_off[idx (-1,0)] += 0.5;
147 Real inter_f = paper()->internote_f ();
148 Real wid_f = paper()->note_width ();
149 for (int j=0; j < 4; j++)
153 /* collision.cc:138: request for method `translate' is ambiguous
157 Offset o (x_off[j] * wid_f, y_off[j] * inter_f);
158 ((Score_element*)col_l_a[j])->translate (o);
164 IMPLEMENT_IS_TYPE_B1(Collision, Item);
167 Collision::do_substitute_dependency (Score_element*o_l,Score_element*n_l)
171 clash_l_arr_.substitute (dynamic_cast<Note_column *> (o_l),
172 dynamic_cast <Note_column *> (n_l));