+MAKE_SCHEME_CALLBACK(Beam,brew_molecule,1);
+SCM
+Beam::brew_molecule (SCM smob)
+{
+ Grob * me =unsmob_element (smob);
+
+ Molecule mol;
+ if (!gh_pair_p (me->get_grob_property ("stems")))
+ return SCM_EOL;
+ Real x0,dx;
+ Link_array<Item>stems =
+ Pointer_group_interface__extract_elements (me, (Item*) 0, "stems");
+ if (visible_stem_count (me))
+ {
+ // ugh -> use commonx
+ x0 = first_visible_stem (me)->relative_coordinate (0, X_AXIS);
+ dx = last_visible_stem (me)->relative_coordinate (0, X_AXIS) - x0;
+ }
+ else
+ {
+ x0 = stems[0]->relative_coordinate (0, X_AXIS);
+ dx = stems.top()->relative_coordinate (0, X_AXIS) - x0;
+ }
+
+
+ Real dy = gh_scm2double (me->get_grob_property ("height"));
+ Real dydx = dy && dx ? dy/dx : 0;
+ Real y = gh_scm2double (me->get_grob_property ("y-position"));
+
+
+ for (int j=0; j <stems.size (); j++)
+ {
+ Item *i = stems[j];
+ Item * prev = (j > 0)? stems[j-1] : 0;
+ Item * next = (j < stems.size()-1) ? stems[j+1] :0;
+
+ Molecule sb = stem_beams (me, i, next, prev);
+ Real x = i->relative_coordinate (0, X_AXIS)-x0;
+ sb.translate (Offset (x, x * dydx + y));
+ mol.add_molecule (sb);
+ }
+ mol.translate_axis (x0
+ - dynamic_cast<Spanner*> (me)->get_bound (LEFT)->relative_coordinate (0, X_AXIS), X_AXIS);
+
+ return mol.smobbed_copy ();
+}
+
+int
+Beam::forced_stem_count (Grob*me)
+{
+ Link_array<Item>stems =
+ Pointer_group_interface__extract_elements ( me, (Item*) 0, "stems");
+ int f = 0;
+ for (int i=0; i < stems.size (); i++)
+ {
+ Item *s = stems[i];
+
+ if (Stem::invisible_b (s))
+ continue;
+
+ if (((int)Stem::chord_start_f (s))
+ && (Stem::get_direction (s ) != Stem::get_default_dir (s )))
+ f++;
+ }
+ return f;
+}
+
+
+
+
+/* TODO:
+ use filter and standard list functions.
+ */
+int
+Beam::visible_stem_count (Grob*me)
+{
+ Link_array<Item>stems =
+ Pointer_group_interface__extract_elements (me, (Item*) 0, "stems");
+ int c = 0;
+ for (int i = stems.size (); i--;)
+ {
+ if (!Stem::invisible_b (stems[i]))
+ c++;
+ }
+ return c;
+}
+
+Item*
+Beam::first_visible_stem(Grob*me)
+{
+ Link_array<Item>stems =
+ Pointer_group_interface__extract_elements ( me, (Item*) 0, "stems");
+
+ for (int i = 0; i < stems.size (); i++)
+ {
+ if (!Stem::invisible_b (stems[i]))
+ return stems[i];
+ }
+ return 0;
+}
+
+Item*
+Beam::last_visible_stem(Grob*me)
+{
+ Link_array<Item>stems =
+ Pointer_group_interface__extract_elements ( me, (Item*) 0, "stems");
+ for (int i = stems.size (); i--;)
+ {
+ if (!Stem::invisible_b (stems[i]))
+ return stems[i];
+ }
+ return 0;
+}
+
+
+/*
+ [TODO]
+ handle rest under beam (do_post: beams are calculated now)
+ what about combination of collisions and rest under beam.