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