2 collision.cc -- implement Collision
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--1999 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()
16 set_axes (X_AXIS, Y_AXIS);
20 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]; // TODO: use drul.
58 for (int i=0; i < clash_l_arr_.size(); i++)
60 Note_column* c_l = clash_l_arr_[i];
61 Direction d = c_l->dir ();
64 warning (_ ("No stem direction set. Ignoring column in clash."));
68 SCM shift = c_l->remove_elt_property (horizontal_shift_scm_sym);
69 bool shift_b = (shift != SCM_BOOL_F);
70 clash_group_arr_a[idx (d, shift_b)].push (c_l);
74 for (int j=0; j < 4; j++)
76 if (clash_group_arr_a[j].size() > 1)
78 warning (_ ("Too many clashing notecolumns. Ignoring them."));
85 if (!clash_group_arr_a[idx (d, false)].size())
87 clash_group_arr_a[idx (d, false)] = clash_group_arr_a[idx (d, true)];
88 clash_group_arr_a[idx (d, true)].clear();
91 while (flip (&d) != UP);
94 Interval_t<int> y_extent[4];
95 Note_column * col_l_a[4];
98 for (int j =0 ; j < 4; j++)
100 if (clash_group_arr_a[j].size())
101 col_l_a[j] = clash_group_arr_a[j][0];
107 y_extent[j] = col_l_a[j]->head_positions_interval();
116 x_off[idx (d, true)] = d*0.5;
118 while (flip (&d) != UP);
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)][BIGGER],
124 y_extent[idx (1,0)][SMALLER]);
125 Interval_t<int> open_middle (y_extent[idx (-1,0)][BIGGER]+1, y_extent[idx (1,0)][SMALLER]-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);
133 if (!middle.empty_b()
134 && middle.length() < 2 && col_l_a[idx (1,0)] && col_l_a[idx (-1,0)])
136 // reproduction of bugfix at 3am ?
137 Note_head * nu_l= col_l_a[idx (1,0)]->head_l_arr_[0];
138 Note_head * nd_l = col_l_a[idx (-1,0)]->head_l_arr_.top();
139 if (! (nu_l->balltype_i_ == nd_l->balltype_i_
140 && nu_l->dots_i_ == nd_l->dots_i_ && middle.length() == 0))
144 x_off[idx (d, false)] -= d*0.5;
145 x_off[idx (d, true)] -= d*0.5;
147 while (flip (&d) != UP);
151 Real wid_f = paper_l ()->note_width ();
152 for (int j=0; j < 4; j++)
156 Offset o (x_off[j] * wid_f, 0);
157 col_l_a[j]->translate (o);
166 Collision::do_substitute_element_pointer (Score_element*o_l,Score_element*n_l)
170 clash_l_arr_.substitute (dynamic_cast<Note_column *> (o_l),
171 dynamic_cast <Note_column *> (n_l));