2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 2004--2012 Han-Wen Nienhuys <hanwen@xs4all.nl>
6 LilyPond is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 LilyPond is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
20 #include "interval-set.hh"
23 A union of intervals in the real line.
25 This class gives good performance for finding the union of
26 a collection of intervals (n log n) and for testing if a point
27 belongs to the union (log n). It does not give an efficient way to
28 update the set (ie. by adding more intervals); to do this
29 efficiently would require a self-balancing tree, and it would not
30 be currently useful in lilypond anyway.
33 Interval_set::Interval_set ()
38 Interval_set::interval_union (vector<Interval> ivs)
40 vector_sort (ivs, Interval::left_less);
47 ret.intervals_.push_back (ivs.front ());
49 // Go over the intervals from left to right. If the current interval
50 // overlaps with the last one, merge them. Otherwise, append the
51 // current interval to the list.
52 for (vsize i = 1; i < ivs.size (); ++i)
55 Interval &last = ret.intervals_.back ();
57 if (last[RIGHT] >= iv[LEFT])
58 // overlapping intervals: merge them
59 last[RIGHT] = max (last[RIGHT], iv[RIGHT]);
60 else if (!iv.is_empty ())
61 ret.intervals_.push_back (iv);
67 // Returns an iterator pointing to the first interval whose left
68 // endpoint is at least x. That interval may or may not contain x.
69 vector<Interval>::const_iterator
70 Interval_set::upper_bound (Real x) const
73 return std::upper_bound (intervals_.begin (), intervals_.end (), xx, Interval::left_less);
77 Interval_set::nearest_point (Real x, Direction d) const
79 Real left = -infinity_f; // The closest point to the left of x.
80 Real right = infinity_f; // The closest point to the right of x.
82 vector<Interval>::const_iterator i = upper_bound (x);
83 if (i != intervals_.end ())
86 if (i != intervals_.begin ())
88 Interval left_iv = *(i - 1);
89 // left_iv[LEFT] is guaranteed to be less than x. So if
90 // left_iv[RIGHT] >= x then left_iv contains x, which must then
91 // be the nearest point to x.
92 if (left_iv[RIGHT] >= x)
95 left = left_iv[RIGHT];
103 return (right - x) < (x - left) ? right : left;
107 Interval_set::complement () const
111 if (intervals_.empty ())
113 ret.intervals_.push_back (Interval (-infinity_f, infinity_f));
117 if (intervals_[0][LEFT] > -infinity_f)
118 ret.intervals_.push_back (Interval (-infinity_f, intervals_[0][LEFT]));
120 for (vsize i = 1; i < intervals_.size (); ++i)
121 ret.intervals_.push_back (Interval (intervals_[i - 1][RIGHT], intervals_[i][LEFT]));
123 if (intervals_.back ()[RIGHT] < infinity_f)
124 ret.intervals_.push_back (Interval (intervals_.back ()[RIGHT], infinity_f));