lilypond-1.1.67
[lilypond.git] / lily / rhythmic-grouping.cc
blob487d03a5b981628441c08d682244c99b1f7b10b5
1 /*
2 rhythmic-grouping.cc -- implement Rhythmic_grouping
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--1999 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
9 #include "debug.hh"
10 #include "rhythmic-grouping.hh"
11 #include "interval.hh"
13 void
14 Rhythmic_grouping::init()
16 interval_ = 0;
17 children.clear();
20 void
21 Rhythmic_grouping::OK() const
23 #ifndef NDEBUG
24 assert (bool (children.size()) != bool (interval_));
26 for (int i= 0; i < children.size(); i++)
28 children[i]->OK();
29 if (i>0)
30 assert (children[i-1]->interval()[RIGHT] ==
31 children[i]->interval()[LEFT]);
33 #endif
36 Moment
37 Rhythmic_grouping::length_mom () const
39 return interval().length ();
42 MInterval
43 Rhythmic_grouping::interval() const
45 if (interval_)
46 return *interval_;
47 else
48 return
49 MInterval (children[0]->interval()[LEFT],
50 children.top()->interval ()[RIGHT]);
53 void
54 Rhythmic_grouping::split (Rhythmic_grouping r)
56 if (interval_)
57 return ;
59 r.intersect (interval());
60 split (r.intervals());
62 for (int i= 0; i < children.size(); i++)
64 if (!children[i]->interval_)
66 Rhythmic_grouping here (r);
67 children[i]->split (here);
73 Array<MInterval>
74 Rhythmic_grouping::intervals()
76 Array<MInterval> r;
77 if (interval_ || children.size() == 1)
79 MInterval i (interval());
80 MInterval r1(i), r2(i);
81 r1[RIGHT] = r2[LEFT] = i.center();
82 r.push (r1); r.push (r2);
84 else
86 for (int i=0; i < children.size(); i++)
87 r.push (children[i]->interval());
89 return r;
92 void
93 Rhythmic_grouping::intersect (MInterval t)
95 if (interval_)
97 interval_->intersect (t);
98 return;
101 for (int i=0; i < children.size(); i++)
103 MInterval inter = intersection (t, children[i]->interval());
104 if (inter.empty_b() || inter.length () <= Moment (0))
106 delete children[i];
107 children[i] =0;
109 else
111 children[i]->intersect (t);
114 for (int i=0; i < children.size();)
116 if (!children[i])
117 children.del (i);
118 else
119 i++;
125 Put our children in branches of #this#.
126 The min and max time intervals coincide with elements of #splitpoints#
128 I really should be documenting what is happening here, but I find
129 that difficult, since I don't really understand what's going on here.
132 void
133 Rhythmic_grouping::split (Array<MInterval> splitpoints)
135 //check on splitpoints..
136 int j = 0, i = 0, starti = 0, startj = 0;
138 Link_array<Rhythmic_grouping> ch;
139 while (1)
141 if (i >= children.size() || j >= splitpoints.size ())
142 break;
144 assert (
145 children[starti]->interval()[LEFT]== splitpoints[startj][LEFT]);
146 if (children[i]->interval()[RIGHT] < splitpoints[j][RIGHT])
148 i ++;
150 else if (children[i]->interval()[RIGHT] > splitpoints[j][RIGHT])
152 j ++;
154 else
157 if (i == starti)
159 ch.push (children[i]);
161 else
163 Link_array<Rhythmic_grouping> slice = children.slice (starti, i+1);
164 Rhythmic_grouping *newchild=new Rhythmic_grouping (slice);
166 ch.push (newchild);
168 i ++;
169 j++;
170 starti = i;
171 startj = j;
176 if (ch.size() != 1)
177 children = ch;
181 Rhythmic_grouping::Rhythmic_grouping (MInterval t, int n)
183 init();
184 if (n == 1 || !n)
186 interval_ = new MInterval (t);
187 return;
189 Moment dt = t.length ()/Moment (n);
190 MInterval basic = MInterval (t[LEFT], t[LEFT]+dt);
191 for (int i= 0; i < n; i++)
192 children.push (new Rhythmic_grouping (dt*Moment (i) + basic));
196 Rhythmic_grouping::Rhythmic_grouping (Link_array<Rhythmic_grouping> r)
197 :children (r)
199 interval_ =0;
202 Rhythmic_grouping::~Rhythmic_grouping()
204 junk();
207 void
208 Rhythmic_grouping::copy (Rhythmic_grouping const&s)
210 interval_ = (s.interval_)? new MInterval (*s.interval_) : 0;
211 for (int i=0; i < s.children.size(); i++)
212 children.push (new Rhythmic_grouping (*s.children[i]));
215 void
216 Rhythmic_grouping::operator=(Rhythmic_grouping const &s)
218 junk();
219 copy (s);
222 Rhythmic_grouping::Rhythmic_grouping (Rhythmic_grouping const&s)
224 init();
225 copy (s);
228 void
229 Rhythmic_grouping::junk()
231 delete interval_;
232 junk_pointer_array (children);
233 init();
236 void
237 Rhythmic_grouping::print() const
239 #ifndef NPRINT
240 DOUT << "{ \n";
241 if (interval_)
242 DOUT <<" Interval "<< interval_->str();
243 for (int i=0; i < children.size(); i++)
245 children[i]->print();
247 DOUT << "}\n";
248 #endif
251 bool
252 Rhythmic_grouping::child_fit_b (Moment start)
254 if (children.size())
255 return (children.top()->interval ()[RIGHT]== start);
257 return true;
260 void
261 Rhythmic_grouping::add_child (Moment start, Moment len)
263 Moment stop = start+len;
264 assert (child_fit_b (start));
265 children.push (new Rhythmic_grouping (MInterval (start, stop)));
268 Rhythmic_grouping::Rhythmic_grouping()
270 interval_ =0;
274 min_elt (Array<int> v)
276 int i = 1000; // ugh
277 for (int j = 0 ; j < v.size(); j++)
278 i = i <? v[j];
279 return i;
282 Array<int>
283 Rhythmic_grouping::generate_beams (Array<int> flags, int &flagidx)
285 assert (!interval_) ;
287 Array< Array<int> > children_beams;
288 for (int i=0; i < children.size(); i++)
290 Array<int> child_beams;
291 if (children[i]->interval_)
293 int f = flags[flagidx++];
294 child_beams.push (f);
296 else
298 child_beams = children[i]->
299 generate_beams (flags, flagidx);
301 children_beams.push (child_beams);
303 Array<int> beams;
304 int lastm, m, nextm;
305 for (int i=0; i < children_beams.size(); i++)
307 bool add_left = (i >0);
308 bool add_right = (i < children_beams.size() -1);
310 if (!i)
311 m = min_elt (children_beams[i]);
312 if (add_right)
313 nextm = min_elt (children_beams[i+1]);
315 if (children_beams[i].size() == 1)
317 if (add_right)
318 beams.push (m);
319 if (add_left)
320 beams.push (m);
322 else
324 if (add_left)
325 beams.push (lastm <? m);
326 beams.concat (children_beams[i]);
327 if (add_right)
328 beams.push (m <? nextm);
330 lastm = m;
331 m = nextm;
333 assert (!(beams.size()%2));
334 return beams;
337 void
338 Rhythmic_grouping::translate (Moment m)
340 if (interval_)
341 *interval_ += m;
342 else
343 for (int i=0; i < children.size(); i++)
344 children[i]->translate (m);
347 void
348 Rhythmic_grouping::extend (MInterval m) const
350 assert (m[LEFT] >= interval()[LEFT]);
351 while (m[RIGHT] >interval()[RIGHT])
353 Link_array<Rhythmic_grouping> a (children);
354 for (int i=0; i < a.size(); i++)
356 a[i] =new Rhythmic_grouping (*children[i]);
357 a[i]->translate (children.top()->interval ()[RIGHT]);
359 ((Rhythmic_grouping*)this)->children.concat (a);
361 assert (m[RIGHT] <= interval()[RIGHT]);
362 OK();
365 Rhythmic_grouping
366 parse_grouping (Array<int> beat_i_arr, Array<Moment> elt_length_arr)
368 Moment here =0;
369 assert (beat_i_arr.size() == elt_length_arr.size ());
371 Link_array<Rhythmic_grouping> children;
372 for (int i=0; i < beat_i_arr.size(); i++)
374 Moment last = here;
375 here += elt_length_arr[i] * Moment (beat_i_arr[i]);
376 children.push (
377 new Rhythmic_grouping (MInterval (last, here),
378 beat_i_arr[i]));
380 return Rhythmic_grouping (children);