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