Example #1
0
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;
}
Example #2
0
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);
}