]> git.donarmstrong.com Git - lilypond.git/blob - src/grouping.cc
release: 0.0.26
[lilypond.git] / src / grouping.cc
1 #include "debug.hh"
2 #include "grouping.hh"
3 #include "interval.hh"
4
5 void
6 Rhythmic_grouping::init()
7 {
8     interval_ = 0;
9     children.set_size(0);     
10 }
11
12 void
13 Rhythmic_grouping::OK()const
14 {
15 #ifndef NDEBUG
16     assert(bool(children.size()) != bool(interval_));
17
18     for (int i= 0; i < children.size(); i++) {
19         children[i]->OK();
20         if (i>0)
21             assert(children[i-1]->interval().right ==
22                    children[i]->interval().left);
23     }
24 #endif
25 }
26
27 Moment
28 Rhythmic_grouping::length() const
29 {
30     return interval().length();
31 }
32
33 MInterval
34 Rhythmic_grouping::interval()const
35 {
36     if (interval_)
37         return *interval_;
38     else
39         return
40             MInterval(children[0]->interval().left,
41                      children.last()->interval().right);
42 }
43
44 void
45 Rhythmic_grouping::split(Rhythmic_grouping r)
46 {
47     if (interval_)
48         return ;
49     
50     r.intersect(interval());
51     split(r.intervals());
52     
53     for (int i= 0; i < children.size(); i++) {
54         if (!children[i]->interval_) {
55             Rhythmic_grouping here(r);  
56             children[i]->split(here);
57         }
58     }
59 }
60
61
62 Array<MInterval>
63 Rhythmic_grouping::intervals()
64 {
65     Array<MInterval> r;
66     if (interval_ || children.size() == 1) {
67         MInterval i(interval());
68         MInterval r1(i), r2(i);
69         r1.right = r2.left = i.center();
70         r.push(r1); r.push(r2);
71     } else {
72         for (int i=0; i < children.size(); i++)
73             r.push(children[i]->interval());
74     }
75     return r;
76 }
77 void
78 Rhythmic_grouping::intersect(MInterval t)
79 {
80     if (interval_) {
81         interval_->intersect(t);
82         return;
83     }
84     
85     for (int i=0; i < children.size(); i++) {
86         MInterval inter = intersection(t, children[i]->interval());
87         if (inter.empty() || inter.length() <= 0) {
88             delete children[i];
89             children[i] =0;
90         } else {
91             children[i]->intersect(t);
92         }
93     }
94     for (int i=0; i < children.size(); ) {
95         if (!children[i])
96             children.del(i);
97         else
98             i++;
99     }
100
101 }
102
103 /* I really should be documenting what is happening here, but I find
104   that difficult, since I don't really understand what's going on here.
105
106   */
107 void
108 Rhythmic_grouping::split(Array<MInterval> splitpoints)
109 {
110     //check on splitpoints..
111     int j = 0, i = 0, starti = 0, startj = 0;
112     
113     Array<Rhythmic_grouping*> ch;
114     while (1) {
115         if  ( i >= children.size() || j >= splitpoints.size())
116             break;
117         
118         assert( 
119             children[starti]->interval().left== splitpoints[startj].left);
120                 if (children[i]->interval().right < splitpoints[j].right) {
121             i ++;
122         } else if (children[i]->interval().right > splitpoints[j].right ) {
123             j ++;
124         } else {
125
126             if (i == starti) {
127                 ch.push(children[i]);
128             } else {
129                 Rhythmic_grouping *newchild=new Rhythmic_grouping(
130                     children.subvec(starti, i+1));
131
132                 ch.push(newchild);
133             }
134             i ++;
135             j++;
136             starti = i;
137             startj = j;
138
139
140         }
141     }
142     if (ch.size() != 1)
143         children = ch;
144     }
145
146
147 Rhythmic_grouping::Rhythmic_grouping(MInterval t, int n)
148 {
149     init();
150     if (n == 1 || !n) {
151         interval_ = new MInterval(t);
152         return;
153     }
154     Moment dt = t.length()/n;
155     MInterval basic = MInterval(t.left, t.left+dt);
156     for (int i= 0; i < n; i++)
157         children.push(new Rhythmic_grouping( dt*i + basic ));
158 }
159
160
161 Rhythmic_grouping::Rhythmic_grouping(Array<Rhythmic_grouping*> r)
162     :children(r)
163 {
164     interval_ =0;
165 }
166
167 Rhythmic_grouping::~Rhythmic_grouping()
168 {
169     junk();    
170 }
171
172 void
173 Rhythmic_grouping::copy(Rhythmic_grouping const&s)
174 {
175     interval_ =  (s.interval_)? new MInterval(*s.interval_) : 0;
176     for (int i=0; i < s.children.size(); i++)
177        children.push(new Rhythmic_grouping(*s.children[i]));
178 }
179
180 void
181 Rhythmic_grouping::operator=(Rhythmic_grouping const &s)
182 {
183     junk();
184     copy(s);
185 }
186
187 Rhythmic_grouping::Rhythmic_grouping(Rhythmic_grouping const&s)
188 {
189     init();
190     copy(s);
191 }
192
193 void
194 Rhythmic_grouping::junk()
195 {
196     delete interval_;
197     for (int i=0; i < children.size(); i++)
198         delete children[i];
199     init();
200 }
201
202 void
203 Rhythmic_grouping::print()const    
204 {
205 #ifndef NPRINT
206     mtor << "{ \n";
207     if (interval_)
208         mtor<<" Interval "<< interval_->str();
209     for (int i=0; i < children.size(); i++) {
210         children[i]->print();
211     }
212     mtor << "}\n";
213 #endif
214 }
215
216 bool
217 Rhythmic_grouping::child_fit_query(Moment start)
218 {
219     if (children.size())
220         return ( children.last()->interval().right== start);
221
222     return true;
223 }  
224
225 void
226 Rhythmic_grouping::add_child(Moment start, Moment len)
227 {
228     Moment stop = start+len;
229
230     assert(child_fit_query(start));
231     children.push(new Rhythmic_grouping(MInterval(start, stop)));
232 }
233
234 Rhythmic_grouping::Rhythmic_grouping()
235 {
236     interval_ =0;
237 }
238
239 int
240 min_elt(Array<int> v)
241 {
242     int i = 1000;               // ugh
243     for (int j = 0 ; j <  v.size(); j++)
244         i = i <? v[j];
245     return i;
246 }
247
248 Array<int>
249 Rhythmic_grouping::generate_beams(Array<int> flags, int &flagidx)
250 {
251     
252     assert (!interval_) ;
253     
254     Array< Array<int> > children_beams;
255     for (int i=0; i < children.size(); i++) {
256         Array<int> child_beams;
257         if (children[i]->interval_) {
258             int f = flags[flagidx++];
259             child_beams.push(f);
260         } else {
261             child_beams = children[i]->
262                 generate_beams(flags, flagidx);
263         }
264         children_beams.push(child_beams);
265     }
266     Array<int> beams;
267     int lastm, m, nextm;
268     for (int i=0; i  < children_beams.size(); i++) {
269         bool add_left =  (i >0);
270         bool add_right = (i  < children_beams.size() -1);
271
272         if (!i)
273             m =  min_elt(children_beams[i]);
274         if (add_right)
275             nextm = min_elt(children_beams[i+1]);
276         
277         if (children_beams[i].size() == 1) {
278             if (add_right)
279                 beams.push(m);
280             if (add_left)
281                 beams.push(m);
282         } else {
283             if (add_left) 
284                 beams.push(lastm <? m);
285             beams.concat(children_beams[i]);
286             if (add_right)
287                 beams.push(m <? nextm);
288         }
289         lastm = m;
290         m = nextm;      
291     }
292     assert(!(beams.size()%2));
293     return beams;
294 }
295
296 void
297 Rhythmic_grouping::translate(Moment m)
298 {
299     if (interval_)
300         *interval_ += m;
301     else
302         for (int i=0; i < children.size(); i++)
303             children[i]->translate(m);
304 }
305
306 void
307 Rhythmic_grouping::extend(MInterval m)
308 {    
309     assert(m.left >= interval().left);
310     while (m.right  >interval().right ) {
311         Array<Rhythmic_grouping*> a(children);
312         for (int i=0; i < a.size(); i++) {
313             a[i] =new Rhythmic_grouping(*children[i]);
314             a[i]->translate(children.last()->interval().right);     
315         }
316         children.concat(a);
317     }
318     assert(m.right <= interval().right);
319     OK();
320 }