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