1 /* This file is part of Evoral.
2 * Copyright (C) 2008 David Robillard <http://drobilla.net>
3 * Copyright (C) 2000-2008 Paul Davis
5 * Evoral is free software; you can redistribute it and/or modify it under the
6 * terms of the GNU General Public License as published by the Free Software
7 * Foundation; either version 2 of the License, or (at your option) any later
10 * Evoral is distributed in the hope that it will be useful, but WITHOUT ANY
11 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 #ifndef EVORAL_RANGE_HPP
20 #define EVORAL_RANGE_HPP
27 OverlapNone, // no overlap
28 OverlapInternal, // the overlap is 100% with the object
29 OverlapStart, // overlap covers start, but ends within
30 OverlapEnd, // overlap begins within and covers end
31 OverlapExternal // overlap extends to (at least) begin+end
35 OverlapType coverage (T sa, T ea, T sb, T eb) {
36 /* OverlapType returned reflects how the second (B)
37 range overlaps the first (A).
39 The diagrams show various relative placements
40 of A and B for each OverlapType.
43 Internal: the start points cannot coincide
44 External: the start and end points can coincide
45 Start: end points can coincide
46 End: start points can coincide
48 XXX Logically, Internal should disallow end
53 |--------------------| A
62 if ((sb > sa) && (eb <= ea)) {
63 return OverlapInternal;
67 |--------------------| A
69 -----------------------| B
72 "B overlaps the start of A"
76 if ((eb >= sa) && (eb <= ea)) {
80 |---------------------| A
82 |----------------------- B
85 "B overlaps the end of A"
88 if ((sb > sa) && (sb <= ea)) {
92 |--------------------| A
93 -------------------------- B
94 |----------------------- B
95 ----------------------| B
96 |--------------------| B
101 if ((sa >= sb) && (sa <= eb) && (ea <= eb)) {
102 return OverlapExternal;
108 /** Type to describe a time range */
111 Range (T f, T t) : from (f), to (t) {}
112 T from; ///< start of the range
113 T to; ///< end of the range
117 bool operator== (Range<T> a, Range<T> b) {
118 return a.from == b.from && a.to == b.to;
124 RangeList () : _dirty (false) {}
126 typedef std::list<Range<T> > List;
128 List const & get () {
133 void add (Range<T> const & range) {
135 _list.push_back (range);
138 bool empty () const {
139 return _list.empty ();
149 for (typename List::iterator i = _list.begin(); i != _list.end(); ++i) {
150 for (typename List::iterator j = _list.begin(); j != _list.end(); ++j) {
156 if (coverage (i->from, i->to, j->from, j->to) != OverlapNone) {
157 i->from = std::min (i->from, j->from);
158 i->to = std::max (i->to, j->to);
172 /** Type to describe the movement of a time range */
175 RangeMove (T f, double l, T t) : from (f), length (l), to (t) {}
176 T from; ///< start of the range
177 double length; ///< length of the range
178 T to; ///< new start of the range
182 RangeList<T> subtract (Range<T> range, RangeList<T> sub)
193 typename RangeList<T>::List s = sub.get ();
195 for (typename RangeList<T>::List::const_iterator i = s.begin(); i != s.end(); ++i) {
197 if (coverage (range.from, range.to, i->from, i->to) == OverlapNone) {
201 Range<T> clamped (std::max (range.from, i->from), std::min (range.to, i->to));
203 if (clamped.from != x) {
204 result.add (Range<T> (x, clamped.from - 1));
210 if (s.back().to < range.to) {
211 result.add (Range<T> (x, range.to));