]> git.donarmstrong.com Git - lilypond.git/blob - lily/collision.cc
release: 0.0.57
[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         if (! c_l->dir_i_) {
56             warning ("No stem direction set. Ignoring column in clash. ");
57             continue;
58         }
59         int d = (c_l->dir_i_);
60         
61         clash_group_arr_a[idx(d, c_l->h_shift_b_)].push(c_l);
62     }
63     
64     
65     for (int j=0; j < 4; j++) {
66         if (clash_group_arr_a[j].size() > 1) {
67             warning("Too many clashing notecolumns. Ignoring them.");
68             return;
69         }
70     }
71     int d = 1;
72     do {
73         if (!clash_group_arr_a[idx(d, false)].size()){
74             clash_group_arr_a[idx(d,  false)] = clash_group_arr_a[idx(d, true)];
75             clash_group_arr_a[idx(d, true)].set_size(0);
76         }
77     } while ((d *= -1) != 1);
78                                   
79
80     Interval_t<int> y_extent[4];
81     Note_column * col_l_a[4];
82     Real x_off [4];
83     int y_off[4];
84     
85     for (int j =0 ; j < 4; j++) {
86         if (clash_group_arr_a[j].size()) 
87             col_l_a[j] = clash_group_arr_a[j][0];
88         else
89             col_l_a[j] = 0;
90         
91         if (col_l_a[j]) {
92             y_extent[j] = col_l_a[j]->head_positions_interval();
93         }
94
95
96         x_off [j] = 0.0;
97         y_off[j] = 0;
98     }
99     
100     do {
101         x_off[idx(d, true)] = d*0.5;
102     } while ((d *= -1) != 1);
103
104   
105
106     Interval_t<int> middle( y_extent[0].min(), y_extent[3].max());
107     Interval_t<int> open_middle( y_extent[3].max()+1, y_extent[0].min()-1);
108     do{
109         if (!open_middle.contains_b(y_extent[idx(d,true)]))
110             x_off[idx(d, true)] = d *1.0 ;
111     } while ((d *= -1) != 1);
112    
113     if (!middle.empty_b() && 
114         middle.length() <= 1 && col_l_a[idx(1,0)] && col_l_a[idx(-1,0)]) {      
115         Notehead * nu_l= col_l_a[idx(1,0)]->head_l_arr_[idx(1,0)];
116         Notehead * nd_l = col_l_a[idx(-1,0)]->head_l_arr_[idx(1,0)];
117         if (! (nu_l->balltype_i_ == nd_l->balltype_i_ && nu_l->dots_i_ == nd_l->dots_i_)) {
118             x_off[idx(1,0)] -= 0.5;
119             x_off[1] -= 0.5;
120             x_off[2] += 0.5;
121             x_off[idx(-1,0)] += 0.5;
122         }
123     }    
124     Real inter_f = paper()->internote();
125     Real wid_f = paper()->note_width();
126     for (int j=0; j < 4; j++) {
127         if (col_l_a[j])
128             col_l_a[j]->translate(Offset(x_off[j] * wid_f,
129                                          y_off[j] * inter_f));
130         
131     }
132 }
133 IMPLEMENT_STATIC_NAME(Collision);