2 grouping.cc -- implement Rhythmic_grouping
4 source file of the LilyPond music typesetter
6 (c) 1997 Han-Wen Nienhuys <hanwen@stack.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
++) {
29 assert(children
[i
-1]->interval().right
==
30 children
[i
]->interval().left
);
36 Rhythmic_grouping::length() const
38 return interval().length();
42 Rhythmic_grouping::interval()const
48 MInterval(children
[0]->interval().left
,
49 children
.top()->interval().right
);
53 Rhythmic_grouping::split(Rhythmic_grouping r
)
58 r
.intersect(interval());
61 for (int i
= 0; i
< children
.size(); i
++) {
62 if (!children
[i
]->interval_
) {
63 Rhythmic_grouping
here(r
);
64 children
[i
]->split(here
);
71 Rhythmic_grouping::intervals()
74 if (interval_
|| children
.size() == 1) {
75 MInterval
i(interval());
76 MInterval
r1(i
), r2(i
);
77 r1
.right
= r2
.left
= i
.center();
78 r
.push(r1
); r
.push(r2
);
80 for (int i
=0; i
< children
.size(); i
++)
81 r
.push(children
[i
]->interval());
87 Rhythmic_grouping::intersect(MInterval t
)
90 interval_
->intersect(t
);
94 for (int i
=0; i
< children
.size(); i
++) {
95 MInterval inter
= intersection(t
, children
[i
]->interval());
96 if (inter
.empty() || inter
.length() <= Rational( 0 )) {
100 children
[i
]->intersect(t
);
103 for (int i
=0; i
< children
.size(); ) {
113 Put our children in branches of #this#.
114 The min and max time intervals coincide with elements of #splitpoints#
116 I really should be documenting what is happening here, but I find
117 that difficult, since I don't really understand what's going on here.
121 Rhythmic_grouping::split(Array
<MInterval
> splitpoints
)
123 //check on splitpoints..
124 int j
= 0, i
= 0, starti
= 0, startj
= 0;
126 Array
<Rhythmic_grouping
*> ch
;
128 if ( i
>= children
.size() || j
>= splitpoints
.size())
132 children
[starti
]->interval().left
== splitpoints
[startj
].left
);
133 if (children
[i
]->interval().right
< splitpoints
[j
].right
) {
135 } else if (children
[i
]->interval().right
> splitpoints
[j
].right
) {
140 ch
.push(children
[i
]);
142 Rhythmic_grouping
*newchild
=new Rhythmic_grouping(
143 children
.subvec(starti
, i
+1));
160 Rhythmic_grouping::Rhythmic_grouping(MInterval t
, int n
)
164 interval_
= new MInterval(t
);
167 Moment dt
= t
.length()/Rational(n
);
168 MInterval basic
= MInterval(t
.left
, t
.left
+dt
);
169 for (int i
= 0; i
< n
; i
++)
170 children
.push(new Rhythmic_grouping( dt
*Rational(i
) + basic
));
174 Rhythmic_grouping::Rhythmic_grouping(Array
<Rhythmic_grouping
*> r
)
180 Rhythmic_grouping::~Rhythmic_grouping()
186 Rhythmic_grouping::copy(Rhythmic_grouping
const&s
)
188 interval_
= (s
.interval_
)? new MInterval(*s
.interval_
) : 0;
189 for (int i
=0; i
< s
.children
.size(); i
++)
190 children
.push(new Rhythmic_grouping(*s
.children
[i
]));
194 Rhythmic_grouping::operator=(Rhythmic_grouping
const &s
)
200 Rhythmic_grouping::Rhythmic_grouping(Rhythmic_grouping
const&s
)
207 Rhythmic_grouping::junk()
210 for (int i
=0; i
< children
.size(); i
++)
216 Rhythmic_grouping::print()const
221 mtor
<<" Interval "<< interval_
->str();
222 for (int i
=0; i
< children
.size(); i
++) {
223 children
[i
]->print();
230 Rhythmic_grouping::child_fit_query(Moment start
)
233 return ( children
.top()->interval().right
== start
);
239 Rhythmic_grouping::add_child(Moment start
, Moment len
)
241 Moment stop
= start
+len
;
243 assert(child_fit_query(start
));
244 children
.push(new Rhythmic_grouping(MInterval(start
, stop
)));
247 Rhythmic_grouping::Rhythmic_grouping()
253 min_elt(Array
<int> v
)
256 for (int j
= 0 ; j
< v
.size(); j
++)
262 Rhythmic_grouping::generate_beams(Array
<int> flags
, int &flagidx
)
264 assert (!interval_
) ;
266 Array
< Array
<int> > children_beams
;
267 for (int i
=0; i
< children
.size(); i
++) {
268 Array
<int> child_beams
;
269 if (children
[i
]->interval_
) {
270 int f
= flags
[flagidx
++];
273 child_beams
= children
[i
]->
274 generate_beams(flags
, flagidx
);
276 children_beams
.push(child_beams
);
280 for (int i
=0; i
< children_beams
.size(); i
++) {
281 bool add_left
= (i
>0);
282 bool add_right
= (i
< children_beams
.size() -1);
285 m
= min_elt(children_beams
[i
]);
287 nextm
= min_elt(children_beams
[i
+1]);
289 if (children_beams
[i
].size() == 1) {
296 beams
.push(lastm
<? m
);
297 beams
.concat(children_beams
[i
]);
299 beams
.push(m
<? nextm
);
304 assert(!(beams
.size()%2));
309 Rhythmic_grouping::translate(Moment m
)
314 for (int i
=0; i
< children
.size(); i
++)
315 children
[i
]->translate(m
);
319 Rhythmic_grouping::extend(MInterval m
)const
321 assert(m
.left
>= interval().left
);
322 while (m
.right
>interval().right
) {
323 Array
<Rhythmic_grouping
*> a(children
);
324 for (int i
=0; i
< a
.size(); i
++) {
325 a
[i
] =new Rhythmic_grouping(*children
[i
]);
326 a
[i
]->translate(children
.top()->interval().right
);
328 ((Rhythmic_grouping
*)this)->children
.concat(a
);
330 assert(m
.right
<= interval().right
);
335 parse_grouping(Array
<int> beat_i_arr
, Array
<Moment
> elt_length_arr
)
338 assert(beat_i_arr
.size() == elt_length_arr
.size());
340 Array
<Rhythmic_grouping
*> children
;
341 for (int i
=0; i
< beat_i_arr
.size(); i
++) {
343 here
+= elt_length_arr
[i
] * Moment(beat_i_arr
[i
]);
345 new Rhythmic_grouping(MInterval(last
, here
),
348 return Rhythmic_grouping(children
);