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