9 #include "leastsquares.hh"
12 #include "paperdef.hh"
14 #include "grouping.hh"
26 Stem_info(const Stem*);
29 Stem_info::Stem_info(const Stem*s)
33 idealy = max(dir*s->top, dir*s->bot);
34 miny = max(dir*s->minnote, dir*s-> maxnote);
35 assert(miny <= idealy);
44 assert(status >= POSTCALCED);
46 Real w=(paper()->note_width() + width().length())/2.0;
47 return Offset(w, (left_pos + w* slope)*paper()->internote());
60 stems.bottom().add(s);
61 s->add_depedency(this);
62 s->print_flag = false;
66 Beam::set_default_dir()
69 dirs[0]=0; dirs[1] =0;
70 for (iter_top(stems,i); i.ok(); i++) {
71 int d = i->get_default_dir();
74 dir_i_ = (dirs[0] > dirs[1]) ? -1 : 1;
75 for (iter_top(stems,i); i.ok(); i++) {
81 should use minimum energy formulation (cf linespacing)
86 Array<Stem_info> sinfo;
87 for (iter_top(stems,i); i.ok(); i++) {
88 i->set_default_extents();
92 Real leftx = sinfo[0].x;
94 for (int i=0; i < sinfo.size(); i++) {
96 l.input.push(Offset(sinfo[i].x, sinfo[i].idealy));
99 l.minimise(slope, left_pos);
101 for (int i=0; i < sinfo.size(); i++) {
102 Real y = sinfo[i].x * slope + left_pos;
103 Real my = sinfo[i].miny;
113 Real sl = slope*paper()->internote();
114 paper()->lookup_p_->beam(sl, 20 PT);
115 slope = sl /paper()->internote();
122 Real x0 = s->hindex();
123 for (; s.ok() ; s++) {
124 Real x = s->hindex()-x0;
125 s->set_stemend(left_pos + slope * x);
131 Beam::do_post_processing()
138 Beam::set_grouping(Rhythmic_grouping def, Rhythmic_grouping cur)
142 assert(cur.children.size() == stems.size());
150 for (; s.ok(); s++) {
151 int f = intlog2(abs(s->flag))-2;
156 b= cur.generate_beams(flags, fi);
159 assert(stems.size() == b.size()/2);
163 for (int i=0; i < b.size() && s.ok(); i+=2, s++) {
164 s->beams_left = b[i];
165 s->beams_right = b[i+1];
172 Beam::do_break_at( PCol *, PCol *) const
174 Beam *beam_p= new Beam(*this);
180 Beam::do_pre_processing()
182 left = (*stems.top()) ->pcol_l_;
183 right = (*stems.bottom())->pcol_l_;
184 assert(stems.size()>1);
194 Beam * me = (Beam*) this; // ugh
195 return Interval( (*me->stems.top()) ->hindex(),
196 (*me->stems.bottom()) ->hindex() );
200 beams to go with one stem.
203 Beam::stem_beams(Stem *here, Stem *next, Stem *prev)const
205 assert( !next || next->hindex() > here->hindex() );
206 assert( !prev || prev->hindex() < here->hindex() );
207 Real dy=paper()->internote()*2;
208 Real stemdx = paper()->rule_thickness();
209 Real sl = slope*paper()->internote();
210 paper()->lookup_p_->beam(sl, 20 PT);
215 /* half beams extending to the left. */
217 int lhalfs= lhalfs = here->beams_left - prev->beams_right ;
218 int lwholebeams= here->beams_left <? prev->beams_right ;
219 Real w = (here->hindex() - prev->hindex())/4;
222 if (lhalfs) // generates warnings if not
223 a = paper()->lookup_p_->beam(sl, w);
224 a.translate(Offset (-w, -w * sl));
225 for (int j = 0; j < lhalfs; j++) {
227 b.translate(Offset(0, -dir_i_ * dy * (lwholebeams+j)));
233 int rhalfs = here->beams_right - next->beams_left;
234 int rwholebeams = here->beams_right <? next->beams_left;
236 Real w = next->hindex() - here->hindex();
237 Atom a = paper()->lookup_p_->beam(sl, w + stemdx);
240 for (; j < rwholebeams; j++) {
242 b.translate(Offset(0, -dir_i_ * dy * j));
248 a = paper()->lookup_p_->beam(sl, w);
250 for (; j < rwholebeams + rhalfs; j++) {
252 b.translate(Offset(0, -dir_i_ * dy * j));
257 leftbeams.add(rightbeams);
263 Beam::brew_molecule_p() const return out;
265 Real inter=paper()->internote();
267 Real x0 = stems.top()->hindex();
269 for (iter_top(stems,i); i.ok(); i++) {
270 PCursor<Stem*> p(i-1);
271 PCursor<Stem*> n(i+1);
272 Stem * prev = p.ok() ? p.ptr() : 0;
273 Stem * next = n.ok() ? n.ptr() : 0;
275 Molecule sb = stem_beams(i, next, prev);
276 Real x = i->hindex()-x0;
277 sb.translate(Offset(x, (x * slope + left_pos)* inter));
280 out->translate(Offset(x0 - left->hpos,0));
284 Beam::do_print()const
287 mtor << "slope " <<slope << "left ypos " << left_pos;