lilypond-1.1.49
[lilypond.git] / lily / collision.cc
blob1ddff7d2f7cc3f880b3edcc1dc967453e8b52dbf
1 /*
2 collision.cc -- implement Collision
4 source file of the GNU LilyPond music typesetter
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"
14 Collision::Collision()
16 set_axes (X_AXIS, Y_AXIS);
19 void
20 Collision::add_column (Note_column* ncol_l)
22 clash_l_arr_.push (ncol_l);
23 add_element (ncol_l);
24 add_dependency (ncol_l);
28 /** This complicated routine moves note columns around horizontally to
29 ensure that notes don't clash.
31 This should be done better, probably.
33 TODO: forced hshift
36 void
37 Collision::do_pre_processing()
39 Drul_array<Link_array<Note_column> > clash_groups;
40 Drul_array<Array<int> > shifts;
42 for (int i=0; i < clash_l_arr_.size(); i++)
44 clash_groups[clash_l_arr_[i]->dir ()].push (clash_l_arr_[i]);
48 Direction d = UP;
51 Array<int> & shift (shifts[d]);
52 Link_array<Note_column> & clashes (clash_groups[d]);
54 clashes.sort (Note_column::shift_compare);
56 for (int i=0; i < clashes.size (); i++)
58 SCM sh
59 = clashes[i]->remove_elt_property (horizontal_shift_scm_sym);
61 if (sh == SCM_BOOL_F)
62 shift.push (0);
63 else
64 shift.push (gh_scm2int (SCM_CDR (sh)));
67 for (int i=1; i < shift.size (); i++)
69 if (shift[i-1] == shift[i])
71 warning (_ ("Too many clashing notecolumns. Ignoring them."));
72 return;
76 while ((flip (&d))!= UP);
78 Drul_array< Array < Slice > > extents;
79 Drul_array< Array < Real > > offsets;
80 d = UP;
83 for (int i=0; i < clash_groups[d].size (); i++)
85 Slice s(clash_groups[d][i]->head_positions_interval ());
86 s[LEFT] --;
87 s[RIGHT]++;
88 extents[d].push (s);
89 offsets[d].push (d * 0.5 * i);
92 while ((flip (&d))!= UP);
96 for (int i=1; i < clash_groups[d].size (); i++)
98 Slice prev =extents[d][i-1];
99 prev.intersect (extents[d][i]);
100 if (prev.length ()> 0 ||
101 (extents[-d].size () && d * (extents[d][i][-d] - extents[-d][0][d]) < 0))
102 for (int j = i; j < clash_groups[d].size (); j++)
103 offsets[d][j] += d * 0.5;
106 while ((flip (&d))!= UP);
109 if the up and down version are close, and can not be merged, move
110 all of them again. */
111 if (extents[UP].size () && extents[DOWN].size ())
113 Note_column *cu_l =clash_groups[UP][0];
114 Note_column *cd_l =clash_groups[DOWN][0];
115 Note_head * nu_l= cu_l->head_l_arr_[0];
116 Note_head * nd_l = cd_l->head_l_arr_.top();
117 int downpos = cd_l->head_positions_interval ()[SMALLER];
118 int uppos = cu_l->head_positions_interval ()[BIGGER];
120 bool merge =
121 downpos == uppos
122 && nu_l->balltype_i_ == nd_l->balltype_i_
123 && nu_l->dots_i_ == nd_l->dots_i_;
126 notes are close, but can not be merged. Shift
128 if (abs(uppos - downpos) < 2 && !merge)
131 for (int i=0; i < clash_groups[d].size (); i++)
133 offsets[d][i] -= d * 0.5;
136 while ((flip (&d))!= UP);
139 Real wid_f = paper_l ()->note_width ();
142 for (int i=0; i < clash_groups[d].size (); i++)
144 clash_groups[d][i]->translate_axis (offsets[d][i]*wid_f, X_AXIS);
147 while (flip (&d) != UP);
151 void
152 Collision::do_substitute_element_pointer (Score_element*o_l,Score_element*n_l)
154 if (o_l)
156 clash_l_arr_.substitute (dynamic_cast<Note_column *> (o_l),
157 dynamic_cast <Note_column *> (n_l));