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>
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
);
20 Collision::add_column (Note_column
* ncol_l
)
23 add_dependency (ncol_l
);
31 Collision::do_pre_processing()
33 Array
<Shift_tup
> autos (automatic_shift ());
34 Array
<Shift_tup
> hand (forced_shift ());
35 Link_array
<Score_element
> done
;
37 Real wid
= paper_l ()->get_var ("collision_note_width");
38 for (int i
=0; i
< hand
.size (); i
++)
40 hand
[i
].e1_
->translate_axis (hand
[i
].e2_
*wid
, X_AXIS
);
41 done
.push (hand
[i
].e1_
);
44 for (int i
=0; i
< autos
.size (); i
++)
46 if (!done
.find_l (autos
[i
].e1_
))
47 autos
[i
].e1_
->translate_axis (autos
[i
].e2_
* wid
, X_AXIS
);
51 /** This complicated routine moves note columns around horizontally to
52 ensure that notes don't clash.
54 This should be done better, probably.
58 Collision::automatic_shift ()
60 Drul_array
<Link_array
<Note_column
> > clash_groups
;
61 Drul_array
<Array
<int> > shifts
;
62 Array
<Shift_tup
> tups
;
65 SCM s
= get_elt_property ("elements");
66 for (; gh_pair_p (s
); s
= gh_cdr (s
))
70 Score_element
* se
= unsmob_element (car
);
71 if (Note_column
* col
= dynamic_cast<Note_column
*> (se
))
72 clash_groups
[col
->dir ()].push (col
);
79 Array
<int> & shift (shifts
[d
]);
80 Link_array
<Note_column
> & clashes (clash_groups
[d
]);
82 clashes
.sort (Note_column::shift_compare
);
84 for (int i
=0; i
< clashes
.size (); i
++)
87 = clashes
[i
]->remove_elt_property ("horizontal-shift");
90 shift
.push (gh_scm2int (sh
));
95 for (int i
=1; i
< shift
.size (); i
++)
97 if (shift
[i
-1] == shift
[i
])
99 warning (_ ("Too many clashing notecolumns. Ignoring them."));
104 while ((flip (&d
))!= UP
);
106 Drul_array
< Array
< Slice
> > extents
;
107 Drul_array
< Array
< Real
> > offsets
;
111 for (int i
=0; i
< clash_groups
[d
].size (); i
++)
113 Slice
s(clash_groups
[d
][i
]->head_positions_interval ());
117 offsets
[d
].push (d
* 0.5 * i
);
120 while ((flip (&d
))!= UP
);
124 for (int i
=1; i
< clash_groups
[d
].size (); i
++)
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;
134 while ((flip (&d
))!= UP
);
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 ())
141 Note_column
*cu_l
=clash_groups
[UP
][0];
142 Note_column
*cd_l
=clash_groups
[DOWN
][0];
148 Note_head
* nu_l
= cu_l
->first_head();
149 Note_head
* nd_l
= cd_l
->first_head();
151 int downpos
= cd_l
->head_positions_interval ()[BIGGER
];
152 int uppos
= cu_l
->head_positions_interval ()[SMALLER
];
156 && nu_l
->balltype_i () == nd_l
->balltype_i ()
157 && nu_l
->dots_i () == nd_l
->dots_i ();
160 notes are close, but can not be merged. Shift
162 if (abs(uppos
- downpos
) < 2 && !merge
)
165 for (int i
=0; i
< clash_groups
[d
].size (); i
++)
167 offsets
[d
][i
] -= d
* 0.5;
170 while ((flip (&d
))!= UP
);
175 for (int i
=0; i
< clash_groups
[d
].size (); i
++)
176 tups
.push (Shift_tup (clash_groups
[d
][i
], offsets
[d
][i
]));
178 while (flip (&d
) != UP
);
184 Collision::forced_shift ()
186 Array
<Shift_tup
> tups
;
188 SCM s
= get_elt_property ("elements");
189 for (; gh_pair_p (s
); s
= gh_cdr (s
))
191 Score_element
* se
= unsmob_element ( gh_car (s
));
193 SCM force
= se
->remove_elt_property ("force-hshift");
194 if (gh_number_p (force
))
196 tups
. push (Shift_tup (se
, gh_scm2double (force
)));