]> git.donarmstrong.com Git - lilypond.git/blob - lily/collision.cc
release: 1.3.10
[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   add_element (ncol_l);
23   add_dependency (ncol_l);
24 }
25
26 /*
27   UGH.  junk Shift_tup .
28  */
29
30 void
31 Collision::do_pre_processing()
32 {
33   Array<Shift_tup> autos (automatic_shift ());
34   Array<Shift_tup> hand (forced_shift ());
35   Link_array<Score_element> done;
36   
37   Real wid = paper_l ()->get_var ("collision_note_width");
38   for (int i=0; i < hand.size (); i++)
39     {
40       hand[i].e1_->translate_axis (hand[i].e2_ *wid, X_AXIS);
41       done.push (hand[i].e1_);
42     }
43
44   for (int i=0; i < autos.size (); i++)
45     {
46       if (!done.find_l (autos[i].e1_))
47         autos[i].e1_->translate_axis (autos[i].e2_ * wid, X_AXIS);
48     }
49 }
50
51 /** This complicated routine moves note columns around horizontally to
52   ensure that notes don't clash.
53
54   This should be done better, probably.
55
56   */
57 Array< Shift_tup >
58 Collision::automatic_shift ()
59 {
60   Drul_array<Link_array<Note_column> > clash_groups;
61   Drul_array<Array<int> > shifts;
62   Array<Shift_tup>  tups;
63
64
65   SCM s = get_elt_property ("elements");
66   for (; gh_pair_p (s); s = gh_cdr (s))
67     {
68       SCM car = gh_car (s);
69
70       Score_element * se = unsmob_element (car);
71       if (Note_column * col = dynamic_cast<Note_column*> (se))
72         clash_groups[col->dir ()].push (col);
73     }
74
75   
76   Direction d = UP;
77   do
78     {
79       Array<int> & shift (shifts[d]);
80       Link_array<Note_column> & clashes (clash_groups[d]);
81
82       clashes.sort (Note_column::shift_compare);
83
84       for (int i=0; i < clashes.size (); i++)
85         {
86           SCM sh
87             = clashes[i]->remove_elt_property ("horizontal-shift");
88
89           if (gh_number_p (sh))
90             shift.push (gh_scm2int (sh));
91           else
92             shift.push (0);
93         }
94       
95       for (int i=1; i < shift.size (); i++)
96         {
97           if (shift[i-1] == shift[i])
98             {
99               warning (_ ("Too many clashing notecolumns.  Ignoring them."));
100               return tups;
101             }
102         }
103     }
104   while ((flip (&d))!= UP);
105
106   Drul_array< Array < Slice > > extents;
107   Drul_array< Array < Real > > offsets;
108   d = UP;
109   do
110     {
111       for (int i=0; i < clash_groups[d].size (); i++)
112         {
113           Slice s(clash_groups[d][i]->head_positions_interval ());
114           s[LEFT] --;
115           s[RIGHT]++;
116           extents[d].push (s);
117           offsets[d].push (d * 0.5 * i);
118         }
119     }
120   while ((flip (&d))!= UP);
121   
122   do
123     {
124       for (int i=1; i < clash_groups[d].size (); i++)
125         {
126           Slice prev =extents[d][i-1];
127           prev.intersect (extents[d][i]);
128           if (prev.length ()> 0 ||
129               (extents[-d].size () && d * (extents[d][i][-d] - extents[-d][0][d]) < 0))
130             for (int j = i; j <  clash_groups[d].size (); j++)
131               offsets[d][j] += d * 0.5;
132         }
133     }   
134   while ((flip (&d))!= UP);
135
136   /*
137     if the up and down version are close, and can not be merged, move
138     all of them again. */
139   if (extents[UP].size () && extents[DOWN].size ())
140     {
141       Note_column *cu_l =clash_groups[UP][0];
142       Note_column *cd_l =clash_groups[DOWN][0];
143
144
145       /*
146         TODO.
147        */
148       Note_head * nu_l= cu_l->first_head();  // cu_l->head_l_arr_[0];
149       Note_head * nd_l = cd_l->first_head(); // cd_l->head_l_arr_.top();
150
151
152       
153       int downpos =     cd_l->head_positions_interval ()[BIGGER];
154       int uppos =       cu_l->head_positions_interval ()[SMALLER];      
155       
156       bool merge  =
157         downpos == uppos
158         && nu_l->balltype_i_ == nd_l->balltype_i_
159         && nu_l->dots_i () == nd_l->dots_i ();
160
161       /*
162         notes are close, but can not be merged.  Shift
163        */
164       if (abs(uppos - downpos) < 2 && !merge)
165           do
166           {
167             for (int i=0; i < clash_groups[d].size (); i++)
168               {
169                 offsets[d][i] -= d * 0.5;
170               }
171           }
172           while ((flip (&d))!= UP);
173     }
174
175
176   do
177     {
178       for (int i=0; i < clash_groups[d].size (); i++)
179         tups.push (Shift_tup (clash_groups[d][i], offsets[d][i]));
180     }
181   while (flip (&d) != UP);
182   return tups;
183 }
184
185
186 Array <Shift_tup>
187 Collision::forced_shift ()
188 {
189   Array<Shift_tup> tups;
190   
191   SCM s = get_elt_property ("elements");
192   for (; gh_pair_p (s); s = gh_cdr (s))
193     {
194       Score_element * se = unsmob_element ( gh_car (s));
195
196       SCM force =  se->remove_elt_property ("force-hshift");
197       if (force != SCM_UNDEFINED)
198         {
199           tups. push (Shift_tup (se, gh_scm2double (force)));
200         }
201     }
202   return tups;
203 }
204
205
206