7 #include "leastsquares.hh"
12 #include "grouping.hh"
23 Stem_info(const Stem*);
26 Stem_info::Stem_info(const Stem*s)
30 idealy = max(dir*s->top, dir*s->bot);
31 miny = max(dir*s->minnote, dir*s-> maxnote);
32 assert(miny <= idealy);
41 ((Beam*)this)->calculate();
42 Real w=width().length()/2;
44 (left_pos + w* slope)*paper()->interline());
59 stems.bottom().add(s);
60 s->print_flag = false;
64 Beam::set_default_dir()
67 dirs[0]=0; dirs[1] =0;
68 for (PCursor<Stem*> sc(stems); sc.ok(); sc++) {
69 sc->set_default_dir();
70 dirs[(sc->dir+1)/2] ++;
72 dir = (dirs[0] > dirs[1]) ? -1 : 1;
73 for (PCursor<Stem*> sc(stems); sc.ok(); sc++) {
79 should use minimum energy formulation (cf linespacing)
84 svec<Stem_info> sinfo;
85 for (PCursor<Stem* >sc(stems); sc.ok(); sc++) {
86 sc->set_default_extents();
90 Real leftx = sinfo[0].x;
92 for (int i=0; i < sinfo.sz(); i++) {
94 l.input.add(Offset(sinfo[i].x, sinfo[i].idealy));
97 l.minimise(slope, left_pos);
99 for (int i=0; i < sinfo.sz(); i++) {
100 Real y = sinfo[i].x * slope + left_pos;
101 Real my = sinfo[i].miny;
115 PCursor<Stem*> s(stems);
117 for (; s.ok() ; s++) {
118 Real x = s->hpos()-x0;
119 s->set_stemend(left_pos + slope * x);
126 assert(stems.size()>1);
143 Beam::set_grouping(Rhythmic_grouping def, Rhythmic_grouping cur)
147 assert(cur.children.sz() == stems.size());
150 group = new Rhythmic_grouping(cur);
153 PCursor<Stem*> s(stems);
155 for (; s.ok(); s++) {
156 int f = intlog2(abs(s->flag))-2;
161 b= group->generate_beams(flags, fi);
164 assert(stems.size() == b.sz()/2);
167 PCursor<Stem*> s(stems);
168 for (int i=0; i < b.sz() && s.ok(); i+=2, s++) {
169 s->beams_left = b[i];
170 s->beams_right = b[i+1];
177 Beam::broken_at( PCol *, PCol *) const
179 return new Beam(*this);
185 left = (*stems.top()) ->pcol_;
186 right = (*stems.bottom())->pcol_;
192 return output->extent().y;
198 Beam * me = (Beam*) this; // ugh
199 return Interval( (*me->stems.top()) ->hpos(),
200 (*me->stems.bottom()) ->hpos() );
204 beams to go with one stem.
207 Beam::stem_beams(Stem *here, Stem *next, Stem *prev)
209 assert( !next || next->hpos() > here->hpos() );
210 assert( !prev || prev->hpos() < here->hpos() );
211 Real dy=paper()->internote()*2;
212 Real stemdx = paper()->rule_thickness();
213 Real sl = slope*paper()->internote();
214 paper()->lookup_->beam(sl, convert_dimen(20,"pt"));
215 slope = sl /paper()->internote();
219 /* half beams extending to the left. */
221 int lhalfs= lhalfs = here->beams_left - prev->beams_right ;
222 int lwholebeams= here->beams_left <? prev->beams_right ;
223 Real w = (here->hpos() - prev->hpos())/4;
224 Atom a = paper()->lookup_->beam(sl, w);
225 a.translate(Offset (-w, -w * sl));
226 for (int j = 0; j < lhalfs; j++) {
228 b.translate(Offset(0, -dir * 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->hpos() - here->hpos();
238 Atom a = paper()->lookup_->beam(sl, w + stemdx);
241 for (; j < rwholebeams; j++) {
243 b.translate(Offset(0, -dir * dy * j));
247 a = paper()->lookup_->beam(sl, w);
249 for (; j < rwholebeams + rhalfs; j++) {
251 b.translate(Offset(0, -dir * dy * j));
256 leftbeams.add(rightbeams);
262 Beam::brew_molecule()
264 assert(left->line == right->line);
265 Real inter=paper()->internote();
266 output = new Molecule;
267 Real x0 = stems.top()->hpos();
269 for (PCursor<Stem*> i(stems); 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->hpos()-x0;
277 sb.translate(Offset(x, (x * slope + left_pos)* inter));
280 output->translate(Offset(x0 - left->hpos,0));
287 mtor << "{ slope " <<slope << "left ypos " << left_pos;