10 #include "leastsquares.hh"
13 #include "paper-def.hh"
15 #include "grouping.hh"
27 Stem_info(const Stem*);
30 Stem_info::Stem_info(const Stem*s)
34 idealy = max(dir*s->top, dir*s->bot);
35 miny = max(dir*s->minnote, dir*s-> maxnote);
36 assert(miny <= idealy);
45 assert(status >= POSTCALCED);
47 Real w=(paper()->note_width() + width().length())/2.0;
48 return Offset(w, (left_pos + w* slope)*paper()->internote());
61 stems.bottom().add(s);
62 s->add_dependency(this);
63 s->print_flag = false;
67 Beam::set_default_dir()
70 dirs[0]=0; dirs[1] =0;
71 for (iter_top(stems,i); i.ok(); i++) {
72 int d = i->get_default_dir();
75 dir_i_ = (dirs[0] > dirs[1]) ? -1 : 1;
76 for (iter_top(stems,i); i.ok(); i++) {
82 should use minimum energy formulation (cf linespacing)
87 Array<Stem_info> sinfo;
88 for (iter_top(stems,i); i.ok(); i++) {
89 i->set_default_extents();
93 Real leftx = sinfo[0].x;
95 for (int i=0; i < sinfo.size(); i++) {
97 l.input.push(Offset(sinfo[i].x, sinfo[i].idealy));
100 l.minimise(slope, left_pos);
102 for (int i=0; i < sinfo.size(); i++) {
103 Real y = sinfo[i].x * slope + left_pos;
104 Real my = sinfo[i].miny;
114 Real sl = slope*paper()->internote();
115 paper()->lookup_l()->beam(sl, 20 PT);
116 slope = sl /paper()->internote();
123 Real x0 = s->hindex();
124 for (; s.ok() ; s++) {
125 Real x = s->hindex()-x0;
126 s->set_stemend(left_pos + slope * x);
132 Beam::do_post_processing()
139 Beam::set_grouping(Rhythmic_grouping def, Rhythmic_grouping cur)
143 assert(cur.children.size() == stems.size());
151 for (; s.ok(); s++) {
152 int f = intlog2(abs(s->flag))-2;
157 b= cur.generate_beams(flags, fi);
160 assert(stems.size() == b.size()/2);
164 for (int i=0; i < b.size() && s.ok(); i+=2, s++) {
165 s->beams_left = b[i];
166 s->beams_right = b[i+1];
173 Beam::do_break_at( PCol *, PCol *) const
175 Beam *beam_p= new Beam(*this);
181 Beam::do_pre_processing()
183 left = (*stems.top()) ->pcol_l_;
184 right = (*stems.bottom())->pcol_l_;
185 assert(stems.size()>1);
195 Beam * me = (Beam*) this; // ugh
196 return Interval( (*me->stems.top()) ->hindex(),
197 (*me->stems.bottom()) ->hindex() );
201 beams to go with one stem.
204 Beam::stem_beams(Stem *here, Stem *next, Stem *prev)const
206 assert( !next || next->hindex() > here->hindex() );
207 assert( !prev || prev->hindex() < here->hindex() );
208 Real dy=paper()->internote()*2;
209 Real stemdx = paper()->rule_thickness();
210 Real sl = slope*paper()->internote();
211 paper()->lookup_l()->beam(sl, 20 PT);
216 /* half beams extending to the left. */
218 int lhalfs= lhalfs = here->beams_left - prev->beams_right ;
219 int lwholebeams= here->beams_left <? prev->beams_right ;
220 Real w = (here->hindex() - prev->hindex())/4;
223 if (lhalfs) // generates warnings if not
224 a = paper()->lookup_l()->beam(sl, w);
225 a.translate(Offset (-w, -w * sl));
226 for (int j = 0; j < lhalfs; j++) {
228 b.translate(Offset(0, -dir_i_ * dy * (lwholebeams+j)));
234 int rhalfs = here->beams_right - next->beams_left;
235 int rwholebeams = here->beams_right <? next->beams_left;
237 Real w = next->hindex() - here->hindex();
238 Atom a = paper()->lookup_l()->beam(sl, w + stemdx);
241 for (; j < rwholebeams; j++) {
243 b.translate(Offset(0, -dir_i_ * dy * j));
249 a = paper()->lookup_l()->beam(sl, w);
251 for (; j < rwholebeams + rhalfs; j++) {
253 b.translate(Offset(0, -dir_i_ * dy * j));
258 leftbeams.add(rightbeams);
264 Beam::brew_molecule_p() const return out;
266 Real inter=paper()->internote();
268 Real x0 = stems.top()->hindex();
270 for (iter_top(stems,i); i.ok(); i++) {
271 PCursor<Stem*> p(i-1);
272 PCursor<Stem*> n(i+1);
273 Stem * prev = p.ok() ? p.ptr() : 0;
274 Stem * next = n.ok() ? n.ptr() : 0;
276 Molecule sb = stem_beams(i, next, prev);
277 Real x = i->hindex()-x0;
278 sb.translate(Offset(x, (x * slope + left_pos)* inter));
281 out->translate(Offset(x0 - left->hpos,0));
285 Beam::do_print()const
288 mtor << "slope " <<slope << "left ypos " << left_pos;