lilypond-0.1.56
[lilypond.git] / lily / collision.cc
blob17c57cf3384a34cad2efcf5b44c3c5ac893af2e6
1 /*
2 collision.cc -- implement Collision
4 source file of the GNU LilyPond music typesetter
6 (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
7 */
8 #include "debug.hh"
9 #include "collision.hh"
10 #include "note-column.hh"
11 #include "note-head.hh"
12 #include "paper-def.hh"
14 Collision::Collision()
18 void
19 Collision::add (Note_column* ncol_l)
21 clash_l_arr_.push (ncol_l);
22 add_element (ncol_l);
23 add_dependency (ncol_l);
25 /**
26 should derive of Array.
28 static
29 int idx (int dir, bool h_shift_b)
31 assert (abs (dir) == 1);
32 int j = dir > 0 ? 0 : 3;
33 if (h_shift_b)
34 j += dir;
35 return j;
38 /** This complicated routine moves note columns around horizontally
39 (and rests vertically) to ensure that notes don't clash.
41 This should be done better, probably.
43 This routine is dedicated to Stine Randmael :-)
46 void
47 Collision::do_pre_processing()
49 if (clash_l_arr_.size() <= 1)
50 return;
53 [stem up, stem up shifted, stem down shifted, stem down]
55 Array<Note_column*> clash_group_arr_a[4];
57 for (int i=0; i < clash_l_arr_.size(); i++)
59 Note_column* c_l = clash_l_arr_[i];
60 if (! c_l->dir_)
62 warning (_("No stem direction set. Ignoring column in clash. "));
63 continue;
65 int d = (c_l->dir_);
67 clash_group_arr_a[idx (d, c_l->h_shift_b_)].push (c_l);
71 for (int j=0; j < 4; j++)
73 if (clash_group_arr_a[j].size() > 1)
75 warning (_("Too many clashing notecolumns. Ignoring them."));
76 return;
79 int d = 1;
82 if (!clash_group_arr_a[idx (d, false)].size())
84 clash_group_arr_a[idx (d, false)] = clash_group_arr_a[idx (d, true)];
85 clash_group_arr_a[idx (d, true)].clear();
88 while ((d *= -1) != 1);
91 Interval_t<int> y_extent[4];
92 Note_column * col_l_a[4];
93 Real x_off [4];
94 int y_off[4];
96 for (int j =0 ; j < 4; j++)
98 if (clash_group_arr_a[j].size())
99 col_l_a[j] = clash_group_arr_a[j][0];
100 else
101 col_l_a[j] = 0;
103 if (col_l_a[j])
105 y_extent[j] = col_l_a[j]->head_positions_interval();
109 x_off [j] = 0.0;
110 y_off[j] = 0;
115 x_off[idx (d, true)] = d*0.5;
117 while ((d *= -1) != 1);
120 // y_extent: smallest y-pos noteball interval containing all balls
121 // 4 (0..3) groups: stem up/down; shift on/off;
122 Interval_t<int> middle (y_extent[idx (-1,0)].max(),
123 y_extent[idx (1,0)].min());
124 Interval_t<int> open_middle (y_extent[idx (-1,0)].max()+1, y_extent[idx (1,0)].min ()-1);
127 if (!open_middle.contains_b (y_extent[idx (d,true)]))
128 x_off[idx (d, true)] = d *1.0 ;
129 } while ((d *= -1) != 1);
131 if (!middle.empty_b()
132 && middle.length() < 2 && col_l_a[idx (1,0)] && col_l_a[idx (-1,0)]) {
133 // reproduction of bugfix at 3am ?
134 Note_head * nu_l= col_l_a[idx (1,0)]->head_l_arr_[0];
135 Note_head * nd_l = col_l_a[idx (-1,0)]->head_l_arr_.top();
136 if (! (nu_l->balltype_i_ == nd_l->balltype_i_
137 && nu_l->dots_i_ == nd_l->dots_i_ && middle.length() == 0))
139 x_off[idx (1,0)] -= 0.5;
140 x_off[idx (1,1)] -= 0.5;
141 x_off[idx (-1,1)] += 0.5;
142 x_off[idx (-1,0)] += 0.5;
146 Real inter_f = paper()->internote_f ();
147 Real wid_f = paper()->note_width ();
148 for (int j=0; j < 4; j++)
150 if (col_l_a[j])
152 /* collision.cc:138: request for method `translate' is ambiguous
154 (shaddup)
156 Offset o (x_off[j] * wid_f, y_off[j] * inter_f);
157 ((Score_elem*)col_l_a[j])->translate (o);
163 IMPLEMENT_IS_TYPE_B1(Collision, Item);
165 void
166 Collision::do_substitute_dependency (Score_elem*o_l,Score_elem*n_l)
168 clash_l_arr_.substitute ((Note_column*)o_l->item(),
169 (Note_column*)(n_l?n_l->item():0));