]> git.donarmstrong.com Git - lilypond.git/blob - lily/collision.cc
c63c71747c1f300c1971ff94b6ea3acd0ce846dc
[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--1998 Han-Wen Nienhuys <hanwen@cs.uu.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_column (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_)
61         {
62           warning (_ ("No stem direction set. Ignoring column in clash."));
63           continue;
64         }
65       int d = (c_l->dir_);
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     }
88   while ((d *= -1) != 1);
89
90
91   Interval_t<int> y_extent[4];
92   Note_column * col_l_a[4];
93   Real x_off [4];
94   int y_off[4];
95
96   for (int j =0 ; j < 4; j++)
97     {
98       if (clash_group_arr_a[j].size())
99         col_l_a[j] = clash_group_arr_a[j][0];
100       else
101         col_l_a[j] = 0;
102
103       if (col_l_a[j])
104         {
105           y_extent[j] = col_l_a[j]->head_positions_interval();
106         }
107
108
109       x_off [j] = 0.0;
110       y_off[j] = 0;
111     }
112
113   do
114     {
115       x_off[idx (d, true)] = d*0.5;
116     }
117   while ((d *= -1) != 1);
118
119
120   // y_extent: smallest y-pos noteball interval containing all balls
121   // 4 (0..3) groups: stem up/down; shift on/off;
122   Interval_t<int> middle (y_extent[idx (-1,0)].max(),
123                           y_extent[idx (1,0)].min());
124   Interval_t<int> open_middle (y_extent[idx (-1,0)].max()+1, y_extent[idx (1,0)].min ()-1);
125   do
126     {
127       if (!open_middle.contains_b (y_extent[idx (d,true)]))
128         x_off[idx (d, true)] = d *1.0 ;
129     } while ((d *= -1) != 1);
130
131   if (!middle.empty_b()
132       && middle.length() < 2 && col_l_a[idx (1,0)] && col_l_a[idx (-1,0)]) {
133     // reproduction of bugfix at 3am ?
134     Note_head * nu_l= col_l_a[idx (1,0)]->head_l_arr_[0];
135     Note_head * nd_l = col_l_a[idx (-1,0)]->head_l_arr_.top();
136     if (! (nu_l->balltype_i_ == nd_l->balltype_i_
137            && nu_l->dots_i_ == nd_l->dots_i_  && middle.length() == 0))
138       {
139         x_off[idx (1,0)] -= 0.5;
140         x_off[idx (1,1)] -= 0.5;
141         x_off[idx (-1,1)] += 0.5;
142         x_off[idx (-1,0)] += 0.5;
143       }
144
145   }
146   Real inter_f = paper()->internote_f ();
147   Real wid_f = paper()->note_width ();
148   for (int j=0; j < 4; j++)
149     {
150       if (col_l_a[j])
151         {
152           /* collision.cc:138: request for method `translate' is ambiguous
153
154              (shaddup)
155              */
156           Offset o (x_off[j] * wid_f, y_off[j] * inter_f);
157           ((Score_element*)col_l_a[j])->translate (o);
158         }
159     }
160 }
161
162
163 IMPLEMENT_IS_TYPE_B1(Collision, Item);
164
165 void
166 Collision::do_substitute_dependency (Score_element*o_l,Score_element*n_l)
167 {
168   clash_l_arr_.substitute ((Note_column*)o_l->access_Item (),
169                            (Note_column*)(n_l?n_l->access_Item ():0));
170 }