2 collision.cc -- implement Collision
4 source file of the GNU LilyPond music typesetter
6 (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
9 #include "collision.hh"
10 #include "note-column.hh"
11 #include "note-head.hh"
12 #include "paper-def.hh"
14 Collision::Collision()
19 Collision::add (Note_column
* ncol_l
)
21 clash_l_arr_
.push (ncol_l
);
23 add_dependency (ncol_l
);
26 should derive of Array.
29 int idx (int dir
, bool h_shift_b
)
31 assert (abs (dir
) == 1);
32 int j
= dir
> 0 ? 0 : 3;
38 /** This complicated routine moves note columns around horizontally
39 (and rests vertically) to ensure that notes don't clash.
41 This should be done better, probably.
43 This routine is dedicated to Stine Randmael :-)
47 Collision::do_pre_processing()
49 if (clash_l_arr_
.size() <= 1)
53 [stem up, stem up shifted, stem down shifted, stem down]
55 Array
<Note_column
*> clash_group_arr_a
[4];
57 for (int i
=0; i
< clash_l_arr_
.size(); i
++)
59 Note_column
* c_l
= clash_l_arr_
[i
];
62 warning (_("No stem direction set. Ignoring column in clash. "));
67 clash_group_arr_a
[idx (d
, c_l
->h_shift_b_
)].push (c_l
);
71 for (int j
=0; j
< 4; j
++)
73 if (clash_group_arr_a
[j
].size() > 1)
75 warning (_("Too many clashing notecolumns. Ignoring them."));
82 if (!clash_group_arr_a
[idx (d
, false)].size())
84 clash_group_arr_a
[idx (d
, false)] = clash_group_arr_a
[idx (d
, true)];
85 clash_group_arr_a
[idx (d
, true)].clear();
88 while ((d
*= -1) != 1);
91 Interval_t
<int> y_extent
[4];
92 Note_column
* col_l_a
[4];
96 for (int j
=0 ; j
< 4; j
++)
98 if (clash_group_arr_a
[j
].size())
99 col_l_a
[j
] = clash_group_arr_a
[j
][0];
105 y_extent
[j
] = col_l_a
[j
]->head_positions_interval();
115 x_off
[idx (d
, true)] = d
*0.5;
117 while ((d
*= -1) != 1);
120 // y_extent: smallest y-pos noteball interval containing all balls
121 // 4 (0..3) groups: stem up/down; shift on/off;
122 Interval_t
<int> middle (y_extent
[idx (-1,0)].max(),
123 y_extent
[idx (1,0)].min());
124 Interval_t
<int> open_middle (y_extent
[idx (-1,0)].max()+1, y_extent
[idx (1,0)].min ()-1);
127 if (!open_middle
.contains_b (y_extent
[idx (d
,true)]))
128 x_off
[idx (d
, true)] = d
*1.0 ;
129 } while ((d
*= -1) != 1);
131 if (!middle
.empty_b()
132 && middle
.length() < 2 && col_l_a
[idx (1,0)] && col_l_a
[idx (-1,0)]) {
133 // reproduction of bugfix at 3am ?
134 Note_head
* nu_l
= col_l_a
[idx (1,0)]->head_l_arr_
[0];
135 Note_head
* nd_l
= col_l_a
[idx (-1,0)]->head_l_arr_
.top();
136 if (! (nu_l
->balltype_i_
== nd_l
->balltype_i_
137 && nu_l
->dots_i_
== nd_l
->dots_i_
&& middle
.length() == 0))
139 x_off
[idx (1,0)] -= 0.5;
140 x_off
[idx (1,1)] -= 0.5;
141 x_off
[idx (-1,1)] += 0.5;
142 x_off
[idx (-1,0)] += 0.5;
146 Real inter_f
= paper()->internote_f ();
147 Real wid_f
= paper()->note_width ();
148 for (int j
=0; j
< 4; j
++)
152 /* collision.cc:138: request for method `translate' is ambiguous
156 Offset
o (x_off
[j
] * wid_f
, y_off
[j
] * inter_f
);
157 ((Score_elem
*)col_l_a
[j
])->translate (o
);
163 IMPLEMENT_IS_TYPE_B1(Collision
, Item
);
166 Collision::do_substitute_dependency (Score_elem
*o_l
,Score_elem
*n_l
)
168 clash_l_arr_
.substitute ((Note_column
*)o_l
->item(),
169 (Note_column
*)(n_l
?n_l
->item():0));