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>
10 #include "grouping.hh"
11 #include "interval.hh"
14 Rhythmic_grouping::init()
21 Rhythmic_grouping::OK() const
24 assert (bool (children
.size()) != bool (interval_
));
26 for (int i
= 0; i
< children
.size(); i
++)
30 assert (children
[i
-1]->interval().right
==
31 children
[i
]->interval().left
);
37 Rhythmic_grouping::length() const
39 return interval().length ();
43 Rhythmic_grouping::interval() const
49 MInterval (children
[0]->interval().left
,
50 children
.top()->interval ().right
);
54 Rhythmic_grouping::split (Rhythmic_grouping r
)
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
);
74 Rhythmic_grouping::intervals()
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
);
86 for (int i
=0; i
< children
.size(); i
++)
87 r
.push (children
[i
]->interval());
93 Rhythmic_grouping::intersect (MInterval t
)
97 interval_
->intersect (t
);
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))
111 children
[i
]->intersect (t
);
114 for (int i
=0; i
< children
.size();)
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.
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
;
141 if (i
>= children
.size() || j
>= splitpoints
.size ())
145 children
[starti
]->interval().left
== splitpoints
[startj
].left
);
146 if (children
[i
]->interval().right
< splitpoints
[j
].right
)
150 else if (children
[i
]->interval().right
> splitpoints
[j
].right
)
159 ch
.push (children
[i
]);
163 Rhythmic_grouping
*newchild
=new Rhythmic_grouping (
164 children
.slice (starti
, i
+1));
181 Rhythmic_grouping::Rhythmic_grouping (MInterval t
, int n
)
186 interval_
= new MInterval (t
);
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
)
202 Rhythmic_grouping::~Rhythmic_grouping()
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
]));
216 Rhythmic_grouping::operator=(Rhythmic_grouping
const &s
)
222 Rhythmic_grouping::Rhythmic_grouping (Rhythmic_grouping
const&s
)
229 Rhythmic_grouping::junk()
232 for (int i
=0; i
< children
.size(); i
++)
238 Rhythmic_grouping::print() const
243 DOUT
<<" Interval "<< interval_
->str();
244 for (int i
=0; i
< children
.size(); i
++)
246 children
[i
]->print();
253 Rhythmic_grouping::child_fit_b (Moment start
)
256 return (children
.top()->interval ().right
== start
);
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()
275 min_elt (Array
<int> v
)
278 for (int j
= 0 ; j
< v
.size(); j
++)
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
);
299 child_beams
= children
[i
]->
300 generate_beams (flags
, flagidx
);
302 children_beams
.push (child_beams
);
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);
312 m
= min_elt (children_beams
[i
]);
314 nextm
= min_elt (children_beams
[i
+1]);
316 if (children_beams
[i
].size() == 1)
326 beams
.push (lastm
<? m
);
327 beams
.concat (children_beams
[i
]);
329 beams
.push (m
<? nextm
);
334 assert (!(beams
.size()%2));
339 Rhythmic_grouping::translate (Moment m
)
344 for (int i
=0; i
< children
.size(); i
++)
345 children
[i
]->translate (m
);
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
);
367 parse_grouping (Array
<int> beat_i_arr
, Array
<Moment
> elt_length_arr
)
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
++)
376 here
+= elt_length_arr
[i
] * Moment (beat_i_arr
[i
]);
378 new Rhythmic_grouping (MInterval (last
, here
),
381 return Rhythmic_grouping (children
);