]> git.donarmstrong.com Git - lilypond.git/blob - lily/collision.cc
4b1fb66685881bf777422191430b414611f0b5ca
[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 #include "ly-symbols.hh"
14
15 Collision::Collision()
16 {
17   set_axes (X_AXIS, Y_AXIS);
18 }
19
20 void
21 Collision::add_column (Note_column* ncol_l)
22 {
23   clash_l_arr_.push (ncol_l);
24   add_element (ncol_l);
25   add_dependency (ncol_l);
26 }
27
28
29 /** This complicated routine moves note columns around horizontally to
30   ensure that notes don't clash.
31
32   This should be done better, probably.
33
34   TODO: forced hshift
35   
36   */
37 void
38 Collision::do_pre_processing()
39 {
40   Drul_array<Link_array<Note_column> > clash_groups;
41   Drul_array<Array<int> > shifts;
42   
43   for (int i=0; i < clash_l_arr_.size(); i++)
44     {
45       clash_groups[clash_l_arr_[i]->dir ()].push (clash_l_arr_[i]);
46     }
47
48   
49   Direction d = UP;
50   do
51     {
52       Array<int> & shift (shifts[d]);
53       Link_array<Note_column> & clashes (clash_groups[d]);
54
55       clashes.sort (Note_column::shift_compare);
56
57       for (int i=0; i < clashes.size (); i++)
58         {
59           SCM sh
60             = clashes[i]->remove_elt_property (horizontal_shift_scm_sym);
61
62           if (sh == SCM_BOOL_F)
63             shift.push (0);
64           else
65             shift.push (gh_scm2int (SCM_CDR (sh)));
66         }
67       
68       for (int i=1; i < shift.size (); i++)
69         {
70           if (shift[i-1] == shift[i])
71             {
72               warning (_ ("Too many clashing notecolumns. Ignoring them."));
73               return;
74             }
75         }
76     }
77   while ((flip (&d))!= UP);
78
79   Drul_array< Array < Slice > > extents;
80   Drul_array< Array < Real > > offsets;
81   d = UP;
82   do
83     {
84       for (int i=0; i < clash_groups[d].size (); i++)
85         {
86           Slice s(clash_groups[d][i]->head_positions_interval ());
87           s[LEFT] --;
88           s[RIGHT]++;
89           extents[d].push (s);
90           offsets[d].push (d * 0.5 * i);
91         }
92     }
93   while ((flip (&d))!= UP);
94   
95   do
96     {
97       for (int i=1; i < clash_groups[d].size (); i++)
98         {
99           Slice prev =extents[d][i-1];
100           prev.intersect (extents[d][i]);
101           if (prev.length ()> 0 ||
102               (extents[-d].size () && d * (extents[d][i][-d] - extents[-d][0][d]) < 0))
103             for (int j = i; j <  clash_groups[d].size (); j++)
104               offsets[d][j] += d * 0.5;
105         }
106     }   
107   while ((flip (&d))!= UP);
108
109   /*
110     if the up and down version are close, and can not be merged, move
111     all of them again. */
112   if (extents[UP].size () && extents[DOWN].size ())
113     {
114       Note_column *cu_l =clash_groups[UP][0];
115       Note_column *cd_l =clash_groups[DOWN][0];
116       Note_head * nu_l= cu_l->head_l_arr_[0];
117       Note_head * nd_l = cd_l->head_l_arr_.top();
118       int downpos =     cd_l->head_positions_interval ()[BIGGER];
119       int uppos =       cu_l->head_positions_interval ()[SMALLER];      
120       
121       bool merge  =
122         downpos == uppos
123         && nu_l->balltype_i_ == nd_l->balltype_i_
124         && nu_l->dots_i_ == nd_l->dots_i_;
125
126       /*
127         notes are close, but can not be merged.  Shift
128        */
129       if (abs(uppos - downpos) < 2 && !merge)
130           do
131           {
132             for (int i=0; i < clash_groups[d].size (); i++)
133               {
134                 offsets[d][i] -= d * 0.5;
135               }
136           }
137           while ((flip (&d))!= UP);
138     }
139   do
140     {
141       for (int i=0; i < clash_groups[d].size (); i++)
142         {
143           SCM force =  clash_groups[d][i]->remove_elt_property (force_hshift_scm_sym);
144           if (force != SCM_BOOL_F)
145             {
146               force = SCM_CDR (force);
147               offsets[d][i] = gh_scm2double (force);
148             }
149         }
150     }
151   while ((flip (&d))!= UP);
152   
153   Real wid_f = paper_l ()->note_width ();
154   do
155     {
156       for (int i=0; i < clash_groups[d].size (); i++)
157         {
158           clash_groups[d][i]->translate_axis (offsets[d][i]*wid_f, X_AXIS);
159         }
160     }
161   while (flip (&d) != UP);
162 }
163
164
165 void
166 Collision::do_substitute_element_pointer (Score_element*o_l,Score_element*n_l)
167 {
168   if (o_l)
169     {
170       clash_l_arr_.substitute (dynamic_cast<Note_column *> (o_l),
171                                dynamic_cast <Note_column *> (n_l));
172
173     }
174 }