2 beam.cc -- implement Beam
4 source file of the GNU GNU 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]
22 #include "molecule.hh"
23 #include "leastsquares.hh"
26 #include "paper-def.hh"
28 #include "grouping.hh"
40 Stem_info(Stem const *);
43 Stem_info::Stem_info(Stem const *s)
47 idealy = dir * s->stem_end_f();
48 miny = dir * s->stem_start_f() + 2; // ugh
49 assert(miny <= idealy);
60 Real w=(paper()->note_width() + width().length())/2.0;
61 return Offset(w, (left_pos + w* slope)*paper()->internote_f());
75 s->add_dependency(this);
76 s->print_flag_b_ = false;
80 Beam::set_default_dir()
82 int dirs_single = 0, dirs_chord = 0;
83 for (int i=0; i <stems.size(); i++) {
86 dirs_chord += sl->get_default_dir();
88 dirs_single += sl->get_center_distance();
90 dirs_single = -sign(dirs_single);
91 dir_i_ = (dirs_single + dirs_chord > 0) ? 1 : -1;
93 for (int i=0; i <stems.size(); i++) {
100 should use minimum energy formulation (cf linespacing)
105 Array<Stem_info> sinfo;
106 for (int j=0; j <stems.size(); j++) {
109 i->set_default_extents();
110 if (i->invisible_b())
116 Real leftx = sinfo[0].x;
118 for (int i=0; i < sinfo.size(); i++) {
120 l.input.push(Offset(sinfo[i].x, sinfo[i].idealy));
123 l.minimise(slope, left_pos);
125 for (int i=0; i < sinfo.size(); i++) {
126 Real y = sinfo[i].x * slope + left_pos;
127 Real my = sinfo[i].miny;
137 Real sl = slope*paper()->internote_f();
138 paper()->lookup_l()->beam(sl, 20 PT);
139 slope = sl /paper()->internote_f();
145 Real x0 = stems[0]->hpos_f();
146 for (int j=0; j <stems.size(); j++) {
149 Real x = s->hpos_f()-x0;
150 s->set_stemend(left_pos + slope * x);
156 Beam::do_post_processing()
163 Beam::set_grouping(Rhythmic_grouping def, Rhythmic_grouping cur)
167 assert(cur.children.size() == stems.size());
174 for (int j=0; j <stems.size(); j++) {
177 int f = intlog2(abs(s->flag_i_))-2;
182 b= cur.generate_beams(flags, fi);
185 assert(stems.size() == b.size()/2);
188 for (int j=0, i=0; i < b.size() && j <stems.size(); i+= 2, j++) {
190 s->beams_left_i_ = b[i];
191 s->beams_right_i_ = b[i+1];
196 Beam::do_pre_processing()
198 left_col_l_ = stems[0] ->pcol_l_;
199 right_col_l_ = stems.top()->pcol_l_;
200 assert(stems.size()>1);
208 Beam::do_width() const
210 return Interval( stems[0]->hpos_f(),
211 stems.top()->hpos_f() );
215 beams to go with one stem.
218 Beam::stem_beams(Stem *here, Stem *next, Stem *prev)const
220 assert( !next || next->hpos_f() > here->hpos_f() );
221 assert( !prev || prev->hpos_f() < here->hpos_f() );
222 Real dy=paper()->internote_f()*2;
223 Real stemdx = paper()->rule_thickness();
224 Real sl = slope*paper()->internote_f();
225 paper()->lookup_l()->beam(sl, 20 PT);
230 /* half beams extending to the left. */
232 int lhalfs= lhalfs = here->beams_left_i_ - prev->beams_right_i_ ;
233 int lwholebeams= here->beams_left_i_ <? prev->beams_right_i_ ;
234 Real w = (here->hpos_f() - prev->hpos_f())/4;
237 if (lhalfs) // generates warnings if not
238 a = paper()->lookup_l()->beam(sl, w);
239 a.translate(Offset (-w, -w * sl));
240 for (int j = 0; j < lhalfs; j++) {
242 b.translate(Offset(0, -dir_i_ * dy * (lwholebeams+j)));
248 int rhalfs = here->beams_right_i_ - next->beams_left_i_;
249 int rwholebeams = here->beams_right_i_ <? next->beams_left_i_;
251 Real w = next->hpos_f() - here->hpos_f();
252 Atom a = paper()->lookup_l()->beam(sl, w + stemdx);
255 for (; j < rwholebeams; j++) {
257 b.translate(Offset(0, -dir_i_ * dy * j));
263 a = paper()->lookup_l()->beam(sl, w);
265 for (; j < rwholebeams + rhalfs; j++) {
267 b.translate(Offset(0, -dir_i_ * dy * j));
272 leftbeams.add(rightbeams);
278 Beam::brew_molecule_p() const
281 Real inter=paper()->internote_f();
283 Real x0 = stems[0]->hpos_f();
284 for (int j=0; j <stems.size(); j++) {
286 Stem * prev = (j > 0)? stems[j-1] : 0;
287 Stem * next = (j < stems.size()-1) ? stems[j+1] :0;
289 Molecule sb = stem_beams(i, next, prev);
290 Real x = i->hpos_f()-x0;
291 sb.translate(Offset(x, (x * slope + left_pos)* inter));
294 out->translate(Offset(x0 - left_col_l_->hpos,0));
298 IMPLEMENT_STATIC_NAME(Beam);
301 Beam::do_print()const
304 mtor << "slope " <<slope << "left ypos " << left_pos;
310 Beam::do_substitute_dependency(Score_elem*o,Score_elem*n)
313 while ((i=stems.find_i((Stem*)o->item())) >=0)
314 if (n) stems[i] = (Stem*) n->item();