]> git.donarmstrong.com Git - lilypond.git/blob - lily/collision.cc
release: 0.0.58
[lilypond.git] / lily / collision.cc
1 /*
2   collision.cc -- implement Collision
3
4   source file of the LilyPond music typesetter
5
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 "notehead.hh"
12 #include "paper-def.hh"
13
14 Collision::Collision()
15 {
16 }
17
18 void
19 Collision::add(Note_column* ncol_l)
20 {
21     clash_l_arr_.push(ncol_l);
22     add_dependency(ncol_l);
23 }
24
25 static 
26 int idx(int dir, bool h_shift_b)
27 {
28     assert(abs (dir) == 1);
29     int j = dir > 0 ? 0 : 3;
30     if ( h_shift_b ) 
31         j += dir;
32     return j;
33 }
34
35 /** This complicated routine moves note columns around horizontally
36   (and rests vertically) to ensure that notes don't clash. 
37
38   This should be done better, probably.  
39
40   This routine is dedicated to Stine Randmael :-)
41
42   */
43 void
44 Collision::do_pre_processing()
45 {
46     if (clash_l_arr_.size() <= 1)
47         return;
48     
49     /*
50       [stem up, stem up shifted, stem down shifted, stem down]
51      */
52     Array<Note_column*> clash_group_arr_a[4];
53     
54     for (int i=0; i < clash_l_arr_.size(); i++) {
55         Note_column* c_l = clash_l_arr_[i];
56         if (! c_l->dir_i_) {
57             warning ("No stem direction set. Ignoring column in clash. ");
58             continue;
59         }
60         int d = (c_l->dir_i_);
61         
62         clash_group_arr_a[idx(d, c_l->h_shift_b_)].push(c_l);
63     }
64     
65     
66     for (int j=0; j < 4; j++) {
67         if (clash_group_arr_a[j].size() > 1) {
68             warning("Too many clashing notecolumns. Ignoring them.");
69             return;
70         }
71     }
72     int d = 1;
73     do {
74         if (!clash_group_arr_a[idx(d, false)].size()){
75             clash_group_arr_a[idx(d,  false)] = clash_group_arr_a[idx(d, true)];
76             clash_group_arr_a[idx(d, true)].set_size(0);
77         }
78     } while ((d *= -1) != 1);
79                                   
80
81     Interval_t<int> y_extent[4];
82     Note_column * col_l_a[4];
83     Real x_off [4];
84     int y_off[4];
85     
86     for (int j =0 ; j < 4; j++) {
87         if (clash_group_arr_a[j].size()) 
88             col_l_a[j] = clash_group_arr_a[j][0];
89         else
90             col_l_a[j] = 0;
91         
92         if (col_l_a[j]) {
93             y_extent[j] = col_l_a[j]->head_positions_interval();
94         }
95
96
97         x_off [j] = 0.0;
98         y_off[j] = 0;
99     }
100     
101     do {
102         x_off[idx(d, true)] = d*0.5;
103     } while ((d *= -1) != 1);
104
105   
106     // y_extent: smallest y-pos noteball interval containing all balls
107     // 4 (0..3) groups: stem up/down; shift on/off; 
108     Interval_t<int> middle( y_extent[0].min(), y_extent[3].max());
109     Interval_t<int> open_middle( y_extent[3].max()+1, y_extent[0].min()-1);
110     do{
111         if (!open_middle.contains_b(y_extent[idx(d,true)]))
112             x_off[idx(d, true)] = d *1.0 ;
113     } while ((d *= -1) != 1);
114    
115     if (!middle.empty_b() && 
116         middle.length() <= 2 && col_l_a[idx(1,0)] && col_l_a[idx(-1,0)]) {      
117 // reproduction of bugfix at 3am ?
118         Notehead * nu_l= col_l_a[idx(1,0)]->head_l_arr_[0];
119         Notehead * nd_l = col_l_a[idx(-1,0)]->head_l_arr_.top();
120         if (! (nu_l->balltype_i_ == nd_l->balltype_i_ && nu_l->dots_i_ == nd_l->dots_i_)) {
121             x_off[idx(1,0)] -= 0.5;
122             x_off[1] -= 0.5;
123             x_off[2] += 0.5;
124             x_off[idx(-1,0)] += 0.5;
125         }
126     }    
127     Real inter_f = paper()->internote();
128     Real wid_f = paper()->note_width();
129     for (int j=0; j < 4; j++) {
130         if (col_l_a[j])
131             col_l_a[j]->translate(Offset(x_off[j] * wid_f,
132                                          y_off[j] * inter_f));
133         
134     }
135 }
136
137 IMPLEMENT_STATIC_NAME(Collision);