/*
- beam.cc -- implement Beam
+ This file is part of LilyPond, the GNU music typesetter.
- source file of the GNU LilyPond music typesetter
-
- (c) 1997--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>
+ Copyright (C) 1997--2011 Han-Wen Nienhuys <hanwen@xs4all.nl>
Jan Nieuwenhuizen <janneke@gnu.org>
+
+ LilyPond is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ LilyPond is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
*/
/*
#include "beam.hh"
+#include "beam-scoring-problem.hh"
#include "beaming-pattern.hh"
#include "directional-element-interface.hh"
-#include "main.hh"
+#include "grob-array.hh"
#include "international.hh"
#include "interval-set.hh"
#include "item.hh"
#include "least-squares.hh"
#include "lookup.hh"
+#include "main.hh"
#include "misc.hh"
#include "output-def.hh"
#include "pointer-group-interface.hh"
#include "staff-symbol-referencer.hh"
#include "stem.hh"
#include "warn.hh"
-#include "grob-array.hh"
#if DEBUG_BEAM_SCORING
#include "text-interface.hh" // debug output.
Real line = Staff_symbol_referencer::line_thickness (me);
Real beam_thickness = get_beam_thickness (me);
Real fract = robust_scm2double (me->get_property ("length-fraction"), 1.0);
-
+
Real beam_translation = beam_count < 4
? (2 * staff_space + line - beam_thickness) / 2.0
: (3 * staff_space + line - beam_thickness) / 3.0;
Beam::calc_normal_stems (SCM smob)
{
Grob *me = unsmob_grob (smob);
-
+
extract_grob_set (me, "stems", stems);
SCM val = Grob_array::make_array ();
Grob_array *ga = unsmob_grob_array (val);
for (vsize i = 0; i < stems.size (); i++)
if (Stem::is_normal_stem (stems[i]))
ga->add (stems[i]);
-
- return val;
+
+ return val;
}
MAKE_SCHEME_CALLBACK (Beam, calc_direction, 1);
return SCM_UNSPECIFIED;
}
- else
+ else
{
Grob *stem = first_normal_stem (me);
*/
if (!stem)
stem = stems[0];
-
- if (is_direction (stem->get_property_data ("direction")))
+
+ if (is_direction (stem->get_property_data ("direction")))
dir = to_dir (stem->get_property_data ("direction"));
else
dir = to_dir (stem->get_property ("default-direction"));
{
if (!dir)
dir = get_default_dir (me);
-
+
consider_auto_knees (me);
}
{
set_stem_directions (me, dir);
}
-
+
return scm_from_int (dir);
}
Beam::calc_beaming (SCM smob)
{
Grob *me = unsmob_grob (smob);
-
+
extract_grob_set (me, "stems", stems);
Slice last_int;
last_int.set_empty ();
-
+
SCM last_beaming = scm_cons (SCM_EOL, scm_list_1 (scm_from_int (0)));
Direction last_dir = CENTER;
for (vsize i = 0; i < stems.size (); i++)
else
{
/*
- FIXME: what's this for?
+ FIXME: what's this for?
*/
SCM s = scm_cdr (this_beaming);
for (; scm_is_pair (s); s = scm_cdr (s))
last_int.add_point (np);
}
}
-
+
if (scm_ilength (scm_cdr (this_beaming)) > 0)
{
last_beaming = this_beaming;
return a.rank_ < b.rank_;
}
-typedef map<int, vector<Beam_stem_segment> > Position_stem_segments_map;
+typedef map<int, vector<Beam_stem_segment> > Position_stem_segments_map;
vector<Beam_segment>
Beam::get_beam_segments (Grob *me_grob, Grob **common)
commonx = me->get_bound (RIGHT)->common_refpoint (commonx, X_AXIS);
*common = commonx;
-
+
int gap_count = robust_scm2int (me->get_property ("gap-count"), 0);
Real gap_length = robust_scm2double (me->get_property ("gap"), 0.0);
int beam_rank = scm_to_int (scm_car (s));
ranks.add_point (beam_rank);
}
-
+
for (SCM s = index_get_cell (beaming, d);
scm_is_pair (s); s = scm_cdr (s))
{
if (!scm_is_integer (scm_car (s)))
continue;
-
+
int beam_rank = scm_to_int (scm_car (s));
Beam_stem_segment seg;
seg.stem_ = stem;
seg.stem_index_ = i;
seg.dir_ = d;
seg.max_connect_ = robust_scm2int (stem->get_property ("max-beam-connect"), 1000);
-
+
Direction stem_dir = get_grob_direction (stem);
-
+
seg.gapped_
= (stem_dir * beam_rank < (stem_dir * ranks[-stem_dir] + gap_count));
stem_segments[beam_rank].push_back (seg);
bool inside_stem = (event_dir == LEFT)
? seg.stem_index_ > 0
: seg.stem_index_ + 1 < stems.size () ;
-
+
bool event = on_beam_bound
|| abs (seg.rank_ - neighbor_seg.rank_) > 1
|| (abs (vertical_count) >= seg.max_connect_
|| abs (vertical_count) >= neighbor_seg.max_connect_);
-
+
if (!event)
// Then this edge of the current segment is irrelevent because it will
// be connected with the next segment in the event_dir direction.
}
while (flip (&event_dir) != LEFT);
}
-
+
}
return segments;
}
else
{
- extract_grob_set (me, "stems", stems);
+ extract_grob_set (me, "stems", stems);
span[LEFT] = stems[0]->relative_coordinate (commonx, X_AXIS);
span[RIGHT] = stems.back ()->relative_coordinate (commonx, X_AXIS);
}
Real beam_dy = get_beam_translation (me);
Direction feather_dir = to_dir (me->get_property ("grow-direction"));
-
+
Stencil the_beam;
for (vsize i = 0; i < segments.size (); i ++)
{
{
local_slope += feather_dir * segments[i].vertical_count_ * beam_dy / span.length ();
}
-
+
Stencil b = Lookup::beam (local_slope, segments[i].horizontal_.length (), beam_thickness, blot);
b.translate_axis (segments[i].horizontal_[LEFT], X_AXIS);
-
+
b.translate_axis (local_slope
* (segments[i].horizontal_[LEFT] - span.linear_combination (feather_dir))
+ pos.linear_combination (feather_dir)
+ beam_dy * segments[i].vertical_count_, Y_AXIS);
- the_beam.add_stencil (b);
+ the_beam.add_stencil (b);
}
-
+
#if (DEBUG_BEAM_SCORING)
SCM annotation = me->get_property ("annotation");
if (!scm_is_string (annotation))
if (to_boolean (debug))
annotation = me->get_property ("quant-score");
}
-
+
if (scm_is_string (annotation))
{
- extract_grob_set (me, "stems", stems);
+ extract_grob_set (me, "stems", stems);
/*
This code prints the demerits for each beam. Perhaps this
the_beam.translate_axis (-me->relative_coordinate (commonx, X_AXIS), X_AXIS);
return the_beam.smobbed_copy ();
}
-
+
Direction
Beam::get_default_dir (Grob *me)
{
else if (extremes[UP] < -extremes[DOWN])
return UP;
}
-
+
Direction dir = CENTER;
Direction d = CENTER;
if ((d = (Direction) sign (count[UP] - count[DOWN])))
dir = d;
else
dir = to_dir (me->get_property ("neutral-direction"));
-
+
return dir;
}
}
}
-
+
MAKE_SCHEME_CALLBACK (Beam, calc_stem_shorten, 1)
SCM
Beam::calc_stem_shorten (SCM smob)
{
Grob *me = unsmob_grob (smob);
-
+
/*
shortening looks silly for x staff beams
*/
shorten *= forced_fraction;
-
+
if (shorten)
return scm_from_double (shorten);
extract_grob_set (me, "stems", stems);
if (stems.empty ())
return default_value;
-
+
Interval head_positions;
Slice multiplicity;
for (vsize i = 0; i < stems.size(); i++)
if (normal_stem_count (me) <= 1)
return posns;
-
SCM s = me->get_property ("damping");
Real damping = scm_to_double (s);
Real concaveness = robust_scm2double (me->get_property ("concaveness"), 0.0);
me->set_property ("least-squares-dy", scm_from_double (0));
damping = 0;
}
-
+
if (damping)
{
scale_drul (&pos, Staff_symbol_referencer::staff_space (me));
return ly_interval2scm (pos);
}
+
+MAKE_SCHEME_CALLBACK (Beam, quanting, 2);
+SCM
+Beam::quanting (SCM smob, SCM posns)
+{
+ Grob *me = unsmob_grob (smob);
+ Drul_array<Real> ys(0, 0);
+ ys = robust_scm2drul (posns, ys);
+ Beam_scoring_problem problem (me, ys);
+
+ ys = problem.solve ();
+ return ly_interval2scm (ys);
+}
+
+
/*
Report slice containing the numbers that are both in (car BEAMING)
and (cdr BEAMING)
in POS for stem S. This Y position is relative to S. */
Real
Beam::calc_stem_y (Grob *me, Grob *stem, Grob **common,
- Real xl, Real xr, Direction feather_dir,
+ Real xl, Real xr, Direction feather_dir,
Drul_array<Real> pos, bool french)
{
Real beam_translation = get_beam_translation (me);
/*
feather dir = 1 , relx 0->1 : factor 0 -> 1
- feather dir = 0 , relx 0->1 : factor 1 -> 1
- feather dir = -1, relx 0->1 : factor 1 -> 0
+ feather dir = 0 , relx 0->1 : factor 1 -> 1
+ feather dir = -1, relx 0->1 : factor 1 -> 0
*/
Real feather_factor = 1;
if (feather_dir > 0)
feather_factor = relx;
else if (feather_dir < 0)
feather_factor = 1 - relx;
-
+
stem_y += feather_factor * beam_translation
* beam_multiplicity[Direction(((french) ? DOWN : UP)*stem_dir)];
Real id = me->relative_coordinate (common[Y_AXIS], Y_AXIS)
Hmm. At this time, beam position and slope are determined. Maybe,
stem directions and length should set to relative to the chord's
position of the beam. */
-MAKE_SCHEME_CALLBACK (Beam, set_stem_lengths, 1);
+MAKE_SCHEME_CALLBACK (Beam, set_stem_lengths, 1);
SCM
Beam::set_stem_lengths (SCM smob)
{
(void) me->get_property ("beaming");
SCM posns = me->get_property ("positions");
-
+
extract_grob_set (me, "stems", stems);
if (!stems.size ())
return posns;
/* I can imagine counting those boundaries as a half forced stem,
but let's count them full for now. */
Direction defdir = to_dir (s->get_property ("default-direction"));
-
+
if (abs (Stem::chord_start_y (s)) > 0.1
&& defdir
&& get_grob_direction (s) != defdir)
return scm_from_int (0);
Real offset = robust_scm2double (prev_offset, 0.0);
-
+
Grob *st = unsmob_grob (rest->get_object ("stem"));
Grob *stem = st;
if (!stem)
Drul_array<Grob*> visible_stems (first_normal_stem (beam),
last_normal_stem (beam));
extract_grob_set (beam, "stems", stems);
-
+
Grob *common = common_refpoint_of_array (stems, beam, X_AXIS);
-
+
Real x0 = visible_stems[LEFT]->relative_coordinate (common, X_AXIS);
Real dx = visible_stems[RIGHT]->relative_coordinate (common, X_AXIS) - x0;
Real slope = dy && dx ? dy / dx : 0;
Grob *common_y = rest->common_refpoint (beam, Y_AXIS);
- /*
- TODO: this is dubious, because this call needs the info we're
- computing right now.
- */
- Interval rest_extent = rest->extent (common_y, Y_AXIS);
- rest_extent.translate (offset);
-
+ Interval rest_extent = rest->extent (rest, Y_AXIS);
+ rest_extent.translate (offset + rest->get_parent (Y_AXIS)->relative_coordinate (common_y, Y_AXIS));
+
Real rest_dim = rest_extent[d];
Real minimum_distance
= staff_space * (robust_scm2double (stem->get_property ("stemlet-length"), 0.0)
"Damping slope which is considered zero for purposes of"
" calculating direction penalties.\n"
"@end table\n",
-
+
/* properties */
"annotation "
"auto-knee-gap "