lilypond-0.1.27
[lilypond.git] / lily / grouping.cc
blob2c073adc630a708759ff0a13a5ee946dfbe660a9
1 /*
2 grouping.cc -- implement Rhythmic_grouping
4 source file of the GNU LilyPond music typesetter
6 (c) 1997 Han-Wen Nienhuys <hanwen@stack.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;
266 assert (child_fit_b (start));
267 children.push (new Rhythmic_grouping (MInterval (start, stop)));
270 Rhythmic_grouping::Rhythmic_grouping()
272 interval_ =0;
276 min_elt (Array<int> v)
278 int i = 1000; // ugh
279 for (int j = 0 ; j < v.size(); j++)
280 i = i <? v[j];
281 return i;
284 Array<int>
285 Rhythmic_grouping::generate_beams (Array<int> flags, int &flagidx)
287 assert (!interval_) ;
289 Array< Array<int> > children_beams;
290 for (int i=0; i < children.size(); i++)
292 Array<int> child_beams;
293 if (children[i]->interval_)
295 int f = flags[flagidx++];
296 child_beams.push (f);
298 else
300 child_beams = children[i]->
301 generate_beams (flags, flagidx);
303 children_beams.push (child_beams);
305 Array<int> beams;
306 int lastm, m, nextm;
307 for (int i=0; i < children_beams.size(); i++)
309 bool add_left = (i >0);
310 bool add_right = (i < children_beams.size() -1);
312 if (!i)
313 m = min_elt (children_beams[i]);
314 if (add_right)
315 nextm = min_elt (children_beams[i+1]);
317 if (children_beams[i].size() == 1)
319 if (add_right)
320 beams.push (m);
321 if (add_left)
322 beams.push (m);
324 else
326 if (add_left)
327 beams.push (lastm <? m);
328 beams.concat (children_beams[i]);
329 if (add_right)
330 beams.push (m <? nextm);
332 lastm = m;
333 m = nextm;
335 assert (!(beams.size()%2));
336 return beams;
339 void
340 Rhythmic_grouping::translate (Moment m)
342 if (interval_)
343 *interval_ += m;
344 else
345 for (int i=0; i < children.size(); i++)
346 children[i]->translate (m);
349 void
350 Rhythmic_grouping::extend (MInterval m) const
352 assert (m.left >= interval().left);
353 while (m.right >interval().right)
355 Array<Rhythmic_grouping*> a (children);
356 for (int i=0; i < a.size(); i++)
358 a[i] =new Rhythmic_grouping (*children[i]);
359 a[i]->translate (children.top()->interval ().right);
361 ((Rhythmic_grouping*)this)->children.concat (a);
363 assert (m.right <= interval().right);
364 OK();
367 Rhythmic_grouping
368 parse_grouping (Array<int> beat_i_arr, Array<Moment> elt_length_arr)
370 Moment here =0;
371 assert (beat_i_arr.size() == elt_length_arr.size ());
373 Array<Rhythmic_grouping*> children;
374 for (int i=0; i < beat_i_arr.size(); i++)
376 Moment last = here;
377 here += elt_length_arr[i] * Moment (beat_i_arr[i]);
378 children.push (
379 new Rhythmic_grouping (MInterval (last, here),
380 beat_i_arr[i]));
382 return Rhythmic_grouping (children);