IntervalSet IntervalSet::And(const IntervalSet &other) const { IntervalSet intersection; size_t i = 0; size_t j = 0; // iterate down both interval lists looking for nondisjoint intervals while (i < _intervals.size() && j < other._intervals.size()) { Interval mine = _intervals[i]; Interval theirs = other._intervals[j]; if (mine.startsBeforeDisjoint(theirs)) { // move this iterator looking for interval that might overlap i++; } else if (theirs.startsBeforeDisjoint(mine)) { // move other iterator looking for interval that might overlap j++; } else if (mine.properlyContains(theirs)) { // overlap, add intersection, get next theirs intersection.add(mine.intersection(theirs)); j++; } else if (theirs.properlyContains(mine)) { // overlap, add intersection, get next mine intersection.add(mine.intersection(theirs)); i++; } else if (!mine.disjoint(theirs)) { // overlap, add intersection intersection.add(mine.intersection(theirs)); // Move the iterator of lower range [a..b], but not // the upper range as it may contain elements that will collide // with the next iterator. So, if mine=[0..115] and // theirs=[115..200], then intersection is 115 and move mine // but not theirs as theirs may collide with the next range // in thisIter. // move both iterators to next ranges if (mine.startsAfterNonDisjoint(theirs)) { j++; } else if (theirs.startsAfterNonDisjoint(mine)) { i++; } } } return intersection; }
void IntervalSet::add(const Interval &addition) { if (_readonly) { throw IllegalStateException("can't alter read only IntervalSet"); } if (addition.b < addition.a) { return; } // find position in list for (auto iterator = _intervals.begin(); iterator != _intervals.end(); ++iterator) { Interval r = *iterator; if (addition == r) { return; } if (addition.adjacent(r) || !addition.disjoint(r)) { // next to each other, make a single larger interval Interval bigger = addition.Union(r); *iterator = bigger; // make sure we didn't just create an interval that // should be merged with next interval in list while (iterator + 1 != _intervals.end()) { Interval next = *++iterator; if (!bigger.adjacent(next) && bigger.disjoint(next)) { break; } // if we bump up against or overlap next, merge iterator = _intervals.erase(iterator);// remove this one --iterator; // move backwards to what we just set *iterator = bigger.Union(next); // set to 3 merged ones // ml: no need to advance iterator, we do that in the next round anyway. ++iterator; // first call to next after previous duplicates the result } return; } if (addition.startsBeforeDisjoint(r)) { // insert before r //--iterator; _intervals.insert(iterator, addition); return; } // if disjoint and after r, a future iteration will handle it } // ok, must be after last interval (and disjoint from last interval) // just add it _intervals.push_back(addition); }