+
+
+/*
+ [TODO]
+ handle rest under beam (do_post: beams are calculated now)
+ what about combination of collisions and rest under beam.
+
+ Should lookup
+
+ rest -> stem -> beam -> interpolate_y_position ()
+*/
+MAKE_SCHEME_CALLBACK(Beam,rest_collision_callback,2);
+SCM
+Beam::rest_collision_callback (SCM element_smob, SCM axis)
+{
+ Grob *rest = unsmob_grob (element_smob);
+ Axis a = (Axis) gh_scm2int (axis);
+
+ assert (a == Y_AXIS);
+
+ Grob * st = unsmob_grob (rest->get_grob_property ("stem"));
+ Grob * stem = st;
+ if (!stem)
+ return gh_double2scm (0.0);
+ Grob * beam = unsmob_grob (stem->get_grob_property ("beam"));
+ if (!beam || !Beam::has_interface (beam) || !Beam::visible_stem_count (beam))
+ return gh_double2scm (0.0);
+
+ // make callback for rest from this.
+ Real beam_dy = 0;
+ Real beam_y = 0;
+
+
+ // todo: make sure this calced already.
+ SCM s = beam->get_grob_property ("height");
+ if (gh_number_p (s))
+ beam_dy = gh_scm2double (s);
+
+ s = beam->get_grob_property ("y-position");
+ if (gh_number_p (s))
+ beam_y = gh_scm2double (s);
+
+ // ugh -> use commonx
+ Real x0 = first_visible_stem(beam)->relative_coordinate (0, X_AXIS);
+ Real dx = last_visible_stem(beam)->relative_coordinate (0, X_AXIS) - x0;
+ Real dydx = beam_dy && dx ? beam_dy/dx : 0;
+
+ Direction d = Stem::get_direction (stem);
+ Real beamy = (stem->relative_coordinate (0, X_AXIS) - x0) * dydx + beam_y;
+
+ Real staff_space = Staff_symbol_referencer::staff_space (rest);
+
+
+ Real rest_dim = rest->extent (rest, Y_AXIS)[d]*2.0 / staff_space ; // refp??
+
+ Real minimum_dist
+ = gh_scm2double (rest->get_grob_property ("minimum-beam-collision-distance"));
+ Real dist =
+ minimum_dist + -d * (beamy - rest_dim) >? 0;
+
+ int stafflines = Staff_symbol_referencer::line_count (rest);
+
+ // move discretely by half spaces.
+ int discrete_dist = int (ceil (dist));
+
+ // move by whole spaces inside the staff.
+ if (discrete_dist < stafflines+1)
+ discrete_dist = int (ceil (discrete_dist / 2.0)* 2.0);
+
+ return gh_double2scm (-d * discrete_dist);
+}
+
+
+bool
+Beam::has_interface (Grob*me)
+{
+ return me->has_interface (ly_symbol2scm ("beam-interface"));
+}
+
+void
+Beam::set_interface (Grob*me)
+{
+ /*
+ why the init? No way to tell difference between default and user
+ override. */
+ me->set_grob_property ("height", gh_int2scm (0)); // ugh.
+ me->set_grob_property ("y-position" ,gh_int2scm (0));
+ me->set_interface (ly_symbol2scm("beam-interface"));
+}