lilypond-1.3.7
[lilypond.git] / lily / grouping.cc
blobaf7d234bf4032d5ad41ae9b874cc3f1152f9c5a9
1 /*
2 grouping.cc -- implement Rhythmic_grouping
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--1998 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
9 #include "debug.hh"
10 #include "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() 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 () <= Rational (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 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 Rhythmic_grouping *newchild=new Rhythmic_grouping (
164 children.slice (starti, i+1));
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()/Rational (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*Rational (i) + basic));
196 Rhythmic_grouping::Rhythmic_grouping (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 for (int i=0; i < children.size(); i++)
233 delete children[i];
234 init();
237 void
238 Rhythmic_grouping::print() const
240 #ifndef NPRINT
241 DOUT << "{ \n";
242 if (interval_)
243 DOUT <<" Interval "<< interval_->str();
244 for (int i=0; i < children.size(); i++)
246 children[i]->print();
248 DOUT << "}\n";
249 #endif
252 bool
253 Rhythmic_grouping::child_fit_b (Moment start)
255 if (children.size())
256 return (children.top()->interval ().right== start);
258 return true;
261 void
262 Rhythmic_grouping::add_child (Moment start, Moment len)
264 Moment stop = start+len;
265 assert (child_fit_b (start));
266 children.push (new Rhythmic_grouping (MInterval (start, stop)));
269 Rhythmic_grouping::Rhythmic_grouping()
271 interval_ =0;
275 min_elt (Array<int> v)
277 int i = 1000; // ugh
278 for (int j = 0 ; j < v.size(); j++)
279 i = i <? v[j];
280 return i;
283 Array<int>
284 Rhythmic_grouping::generate_beams (Array<int> flags, int &flagidx)
286 assert (!interval_) ;
288 Array< Array<int> > children_beams;
289 for (int i=0; i < children.size(); i++)
291 Array<int> child_beams;
292 if (children[i]->interval_)
294 int f = flags[flagidx++];
295 child_beams.push (f);
297 else
299 child_beams = children[i]->
300 generate_beams (flags, flagidx);
302 children_beams.push (child_beams);
304 Array<int> beams;
305 int lastm, m, nextm;
306 for (int i=0; i < children_beams.size(); i++)
308 bool add_left = (i >0);
309 bool add_right = (i < children_beams.size() -1);
311 if (!i)
312 m = min_elt (children_beams[i]);
313 if (add_right)
314 nextm = min_elt (children_beams[i+1]);
316 if (children_beams[i].size() == 1)
318 if (add_right)
319 beams.push (m);
320 if (add_left)
321 beams.push (m);
323 else
325 if (add_left)
326 beams.push (lastm <? m);
327 beams.concat (children_beams[i]);
328 if (add_right)
329 beams.push (m <? nextm);
331 lastm = m;
332 m = nextm;
334 assert (!(beams.size()%2));
335 return beams;
338 void
339 Rhythmic_grouping::translate (Moment m)
341 if (interval_)
342 *interval_ += m;
343 else
344 for (int i=0; i < children.size(); i++)
345 children[i]->translate (m);
348 void
349 Rhythmic_grouping::extend (MInterval m) const
351 assert (m.left >= interval().left);
352 while (m.right >interval().right)
354 Array<Rhythmic_grouping*> a (children);
355 for (int i=0; i < a.size(); i++)
357 a[i] =new Rhythmic_grouping (*children[i]);
358 a[i]->translate (children.top()->interval ().right);
360 ((Rhythmic_grouping*)this)->children.concat (a);
362 assert (m.right <= interval().right);
363 OK();
366 Rhythmic_grouping
367 parse_grouping (Array<int> beat_i_arr, Array<Moment> elt_length_arr)
369 Moment here =0;
370 assert (beat_i_arr.size() == elt_length_arr.size ());
372 Array<Rhythmic_grouping*> children;
373 for (int i=0; i < beat_i_arr.size(); i++)
375 Moment last = here;
376 here += elt_length_arr[i] * Moment (beat_i_arr[i]);
377 children.push (
378 new Rhythmic_grouping (MInterval (last, here),
379 beat_i_arr[i]));
381 return Rhythmic_grouping (children);