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 to
40 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));