2 beam.cc -- implement Beam
4 source file of the LilyPond music typesetter
6 (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
10 Less hairy code. Better slope calculations.
11 knee ([\stem 1; c8 \stem -1; c8]
23 #include "molecule.hh"
24 #include "leastsquares.hh"
27 #include "paper-def.hh"
29 #include "grouping.hh"
41 Stem_info(Stem const *);
44 Stem_info::Stem_info(Stem const *s)
48 idealy = dir * s->stem_end_f();
49 miny = dir * s->stem_start_f();
50 assert(miny <= idealy);
58 assert(status >= POSTCALCED);
60 Real w=(paper()->note_width() + width().length())/2.0;
61 return Offset(w, (left_pos + w* slope)*paper()->internote());
74 stems.bottom().add(s);
75 s->add_dependency(this);
76 s->print_flag_b_ = false;
80 Beam::set_default_dir()
83 dirs[0]=0; dirs[1] =0;
84 for (iter_top(stems,i); i.ok(); i++) {
85 int d = i->get_default_dir();
88 dir_i_ = (dirs[0] > dirs[1]) ? -1 : 1;
89 for (iter_top(stems,i); i.ok(); i++) {
95 should use minimum energy formulation (cf linespacing)
100 Array<Stem_info> sinfo;
101 for (iter_top(stems,i); i.ok(); i++) {
102 i->set_default_extents();
103 if (i->invisible_b())
109 Real leftx = sinfo[0].x;
111 for (int i=0; i < sinfo.size(); i++) {
113 l.input.push(Offset(sinfo[i].x, sinfo[i].idealy));
116 l.minimise(slope, left_pos);
118 for (int i=0; i < sinfo.size(); i++) {
119 Real y = sinfo[i].x * slope + left_pos;
120 Real my = sinfo[i].miny;
130 Real sl = slope*paper()->internote();
131 paper()->lookup_l()->beam(sl, 20 PT);
132 slope = sl /paper()->internote();
139 Real x0 = s->hpos_f();
140 for (; s.ok() ; s++) {
141 Real x = s->hpos_f()-x0;
142 s->set_stemend(left_pos + slope * x);
148 Beam::do_post_processing()
155 Beam::set_grouping(Rhythmic_grouping def, Rhythmic_grouping cur)
159 assert(cur.children.size() == stems.size());
167 for (; s.ok(); s++) {
168 int f = intlog2(abs(s->flag_i_))-2;
173 b= cur.generate_beams(flags, fi);
176 assert(stems.size() == b.size()/2);
180 for (int i=0; i < b.size() && s.ok(); i+=2, s++) {
181 s->beams_left_i_ = b[i];
182 s->beams_right_i_ = b[i+1];
189 Beam::do_break_at( PCol *, PCol *) const
191 Beam *beam_p= new Beam(*this);
197 Beam::do_pre_processing()
199 left_col_l_ = (*stems.top()) ->pcol_l_;
200 right_col_l_ = (*stems.bottom())->pcol_l_;
201 assert(stems.size()>1);
209 Beam::do_width() const
211 Beam * me = (Beam*) this; // ugh
212 return Interval( (*me->stems.top()) ->hpos_f(),
213 (*me->stems.bottom()) ->hpos_f() );
217 beams to go with one stem.
220 Beam::stem_beams(Stem *here, Stem *next, Stem *prev)const
222 assert( !next || next->hpos_f() > here->hpos_f() );
223 assert( !prev || prev->hpos_f() < here->hpos_f() );
224 Real dy=paper()->internote()*2;
225 Real stemdx = paper()->rule_thickness();
226 Real sl = slope*paper()->internote();
227 paper()->lookup_l()->beam(sl, 20 PT);
232 /* half beams extending to the left. */
234 int lhalfs= lhalfs = here->beams_left_i_ - prev->beams_right_i_ ;
235 int lwholebeams= here->beams_left_i_ <? prev->beams_right_i_ ;
236 Real w = (here->hpos_f() - prev->hpos_f())/4;
239 if (lhalfs) // generates warnings if not
240 a = paper()->lookup_l()->beam(sl, w);
241 a.translate(Offset (-w, -w * sl));
242 for (int j = 0; j < lhalfs; j++) {
244 b.translate(Offset(0, -dir_i_ * dy * (lwholebeams+j)));
250 int rhalfs = here->beams_right_i_ - next->beams_left_i_;
251 int rwholebeams = here->beams_right_i_ <? next->beams_left_i_;
253 Real w = next->hpos_f() - here->hpos_f();
254 Atom a = paper()->lookup_l()->beam(sl, w + stemdx);
257 for (; j < rwholebeams; j++) {
259 b.translate(Offset(0, -dir_i_ * dy * j));
265 a = paper()->lookup_l()->beam(sl, w);
267 for (; j < rwholebeams + rhalfs; j++) {
269 b.translate(Offset(0, -dir_i_ * dy * j));
274 leftbeams.add(rightbeams);
280 Beam::brew_molecule_p() const
283 Real inter=paper()->internote();
285 Real x0 = stems.top()->hpos_f();
287 for (iter_top(stems,i); i.ok(); i++) {
288 PCursor<Stem*> p(i-1);
289 PCursor<Stem*> n(i+1);
290 Stem * prev = p.ok() ? p.ptr() : 0;
291 Stem * next = n.ok() ? n.ptr() : 0;
293 Molecule sb = stem_beams(i, next, prev);
294 Real x = i->hpos_f()-x0;
295 sb.translate(Offset(x, (x * slope + left_pos)* inter));
298 out->translate(Offset(x0 - left_col_l_->hpos,0));
302 IMPLEMENT_STATIC_NAME(Beam);
305 Beam::do_print()const
308 mtor << "slope " <<slope << "left ypos " << left_pos;