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>
10 #include "rhythmic-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_mom () 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 () <= Moment (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 Link_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 Link_array
<Rhythmic_grouping
> slice
= children
.slice (starti
, i
+1);
164 Rhythmic_grouping
*newchild
=new Rhythmic_grouping (slice
);
181 Rhythmic_grouping::Rhythmic_grouping (MInterval t
, int n
)
186 interval_
= new MInterval (t
);
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
)
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 junk_pointer_array (children
);
237 Rhythmic_grouping::print() const
242 DOUT
<<" Interval "<< interval_
->str();
243 for (int i
=0; i
< children
.size(); i
++)
245 children
[i
]->print();
252 Rhythmic_grouping::child_fit_b (Moment start
)
255 return (children
.top()->interval ()[RIGHT
]== start
);
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()
274 min_elt (Array
<int> v
)
277 for (int j
= 0 ; j
< v
.size(); j
++)
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
);
298 child_beams
= children
[i
]->
299 generate_beams (flags
, flagidx
);
301 children_beams
.push (child_beams
);
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);
311 m
= min_elt (children_beams
[i
]);
313 nextm
= min_elt (children_beams
[i
+1]);
315 if (children_beams
[i
].size() == 1)
325 beams
.push (lastm
<? m
);
326 beams
.concat (children_beams
[i
]);
328 beams
.push (m
<? nextm
);
333 assert (!(beams
.size()%2));
338 Rhythmic_grouping::translate (Moment m
)
343 for (int i
=0; i
< children
.size(); i
++)
344 children
[i
]->translate (m
);
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
]);
366 parse_grouping (Array
<int> beat_i_arr
, Array
<Moment
> elt_length_arr
)
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
++)
375 here
+= elt_length_arr
[i
] * Moment (beat_i_arr
[i
]);
377 new Rhythmic_grouping (MInterval (last
, here
),
380 return Rhythmic_grouping (children
);