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