2 rest-collision.cc -- implement Rest_collision
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>
8 #include <math.h> // ceil.
12 #include "rest-collision.hh"
13 #include "note-column.hh"
15 #include "note-head.hh"
16 #include "collision.hh"
17 #include "paper-def.hh"
19 #include "group-interface.hh"
20 #include "staff-symbol-referencer.hh"
21 #include "duration.hh"
24 Rest_collision::add_column (Note_column
*nc_l
)
26 add_dependency (nc_l
);
27 Pointer_group_interface
gi (this);
33 gi
.add_element (nc_l
);
37 to_duration (int type
, int dots
)
46 rhythmic_head2mom (Rhythmic_head
* r
)
48 return to_duration (r
->balltype_i (), r
->dot_count ()).length_mom ();
55 col2rhythmic_head (Note_column
* c
)
57 SCM s
= c
->get_elt_pointer ("rests");
58 assert (gh_pair_p (s
));
59 Score_element
* e
= unsmob_element (gh_car (s
));
60 return dynamic_cast<Rhythmic_head
*> (e
);
63 GLUE_SCORE_ELEMENT(Rest_collision
,after_line_breaking
);
66 Rest_collision::member_after_line_breaking ()
68 Link_array
<Note_column
> rest_l_arr
=
69 Pointer_group_interface__extract_elements (this, (Note_column
*) 0, "rests");
70 Link_array
<Note_column
> ncol_l_arr
=
71 Pointer_group_interface__extract_elements (this, (Note_column
*) 0, "notes");
75 handle rest-rest and rest-note collisions
78 * decide not to print rest if too crowded?
80 * ignore rests under beams.
83 // no rests to collide
84 if (!rest_l_arr
.size())
87 // no partners to collide with
88 if (rest_l_arr
.size() + ncol_l_arr
.size () < 2)
91 // meisjes met meisjes
92 if (!ncol_l_arr
.size())
94 Moment m
= rhythmic_head2mom (col2rhythmic_head (rest_l_arr
[0]));
96 for (; i
< rest_l_arr
.size (); i
++)
98 Moment me
= rhythmic_head2mom (col2rhythmic_head (rest_l_arr
[i
]));
104 If all durations are the same, we'll check if there are more
105 rests than maximum-rest-count.
106 Otherwise (different durations), we'll try to display them all
107 (urg: all 3 of them, currently).
110 SCM s
= get_elt_property ("maximum-rest-count");
111 if (i
== rest_l_arr
.size ()
112 && gh_number_p (s
) && gh_scm2int (s
) < rest_l_arr
.size ())
114 display_count
= gh_scm2int (s
);
115 for (; i
> display_count
; i
--)
116 col2rhythmic_head (rest_l_arr
[i
-1])
117 ->set_elt_property ("molecule-callback", SCM_BOOL_T
);
120 display_count
= rest_l_arr
.size ();
123 UGH. Should get dims from table. Should have minimum dist.
125 int dy
= display_count
> 2 ? 6 : 4;
126 if (display_count
> 1)
128 rest_l_arr
[0]->translate_rests (dy
);
129 rest_l_arr
[1]->translate_rests (-dy
);
132 // meisjes met jongetjes
135 if (rest_l_arr
.size () > 1)
137 warning (_("too many colliding rests"));
139 if (ncol_l_arr
.size () > 1)
141 warning (_("too many notes for rest collision"));
143 Note_column
* rcol
= rest_l_arr
[0];
145 // try to be opposite of noteheads.
146 Direction dir
= - ncol_l_arr
[0]->dir();
148 Interval restdim
= rcol
->rest_dim ();
149 if (restdim
.empty_b ())
150 return SCM_UNDEFINED
;
153 Real staff_space
= paper_l()->get_var ("interline");
156 staff_space = rcol->rest_l_arr[0]->staff_space ();
158 Real half_staff_space_f
= staff_space
/2;
159 Real minimum_dist
= paper_l ()->get_var ("restcollision_minimum_dist")
160 * half_staff_space_f
;
163 assumption: ref points are the same.
166 for (int i
= 0; i
< ncol_l_arr
.size(); i
++)
168 notedim
.unite (ncol_l_arr
[i
]->extent (Y_AXIS
));
171 Interval
inter (notedim
);
172 inter
.intersect (restdim
);
175 minimum_dist
+ dir
* (notedim
[dir
] - restdim
[-dir
]) >? 0;
179 //int stafflines = 5; // rcol->rest_l_arr[0]->line_count;
180 int stafflines
= Staff_symbol_referencer_interface (this).line_count ();
182 stafflines
= stafflines
!= 0 ? stafflines
: 5;
184 // move discretely by half spaces.
185 int discrete_dist
= int (ceil (dist
/ (0.5 *staff_space
)));
187 // move by whole spaces inside the staff.
188 if (discrete_dist
< stafflines
+1)
189 discrete_dist
= int (ceil (discrete_dist
/ 2.0)* 2.0);
191 rcol
->translate_rests (dir
* discrete_dist
);
193 return SCM_UNDEFINED
;
197 Rest_collision::Rest_collision(SCM s
)
200 set_elt_pointer ("rests", SCM_EOL
);
201 set_elt_pointer ("notes", SCM_EOL
);
202 set_extent_callback (0, X_AXIS
);
203 set_extent_callback (0, Y_AXIS
);