]> git.donarmstrong.com Git - lilypond.git/blob - lily/collision.cc
53c64fed95e50568ce17fdf1d9630bf81668eb28
[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     
80     for (int j =0 ; j < 4; j++) {
81         if (clash_group_arr_a[j].size()) 
82             col_l_a[j] = clash_group_arr_a[j][0];
83         else
84             col_l_a[j] = 0;
85         
86         if (col_l_a[j]) {
87             y_extent[j] = col_l_a[j]->head_positions_interval();
88         }
89
90
91         x_off [j] = 0.0;
92         y_off[j] = 0;
93     }
94     
95     do {
96         x_off[idx(d, true)] = d*0.5;
97     } while ((d *= -1) != 1);
98
99   
100
101     Interval_t<int> middle( y_extent[0].min(), y_extent[3].max());
102     Interval_t<int> open_middle( y_extent[3].max()+1, y_extent[0].min()-1);
103     do{
104         if (!open_middle.contains_b(y_extent[idx(d,true)]))
105             x_off[idx(d, true)] = d *1.0 ;
106     } while ((d *= -1) != 1);
107    
108     if (!middle.empty_b() && 
109         middle.length() <= 1 && col_l_a[idx(1,0)] && col_l_a[idx(-1,0)]) {      
110         Notehead * nu_l= col_l_a[idx(1,0)]->head_l_arr_[idx(1,0)];
111         Notehead * nd_l = col_l_a[idx(-1,0)]->head_l_arr_[idx(1,0)];
112         if (! (nu_l->balltype_i_ == nd_l->balltype_i_ && nu_l->dots_i_ == nd_l->dots_i_)) {
113             x_off[idx(1,0)] -= 0.5;
114             x_off[1] -= 0.5;
115             x_off[2] += 0.5;
116             x_off[idx(-1,0)] += 0.5;
117         }
118     }    
119     Real inter_f = paper()->internote();
120     Real wid_f = paper()->note_width();
121     for (int j=0; j < 4; j++) {
122         if (col_l_a[j])
123             col_l_a[j]->translate(Offset(x_off[j] * wid_f,
124                                          y_off[j] * inter_f));
125         
126     }
127 }
128 IMPLEMENT_STATIC_NAME(Collision);