protected virtual void Add(Interval addition) { //[email protected]("add "+addition+" to "+intervals.toString()); if (addition.b < addition.a) { return; } // find position in list //for (ListIterator iter = intervals.listIterator(); iter.hasNext();) { int n = intervals.Count; for (int i = 0; i < n; i++) { Interval r = (Interval)intervals[i]; if (addition.Equals(r)) { return; } if (addition.adjacent(r) || !addition.disjoint(r)) { // next to each other, make a single larger interval Interval bigger = addition.union(r); intervals[i] = bigger; // make sure we didn't just create an interval that // should be merged with next interval in list if ((i + 1) < n) { i++; Interval next = (Interval)intervals[i]; if (bigger.adjacent(next) || !bigger.disjoint(next)) { // if we bump up against or overlap next, merge intervals.RemoveAt(i); // remove next one i--; intervals[i] = bigger.union(next); // set to 3 merged ones } } return; } if (addition.startsBeforeDisjoint(r)) { // insert before r intervals.Insert(i, 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.Add(addition); }
/** return a new set containing all elements in this but not in other. * Intervals may have to be broken up when ranges in this overlap * with ranges in other. other is assumed to be a subset of this; * anything that is in other but not in this will be ignored. * * Keep around, but 10-20-2005, I decided to make complement work w/o * subtract and so then subtract can simply be a&~b */ public IIntSet Subtract(IIntSet other) { if (other == null || !(other is IntervalSet)) { return(null); // nothing in common with null set } IntervalSet diff = new IntervalSet(); // iterate down both interval lists var thisIter = this.intervals.GetEnumerator(); var otherIter = ((IntervalSet)other).intervals.GetEnumerator(); Interval mine = null; Interval theirs = null; if (thisIter.MoveNext()) { mine = (Interval)thisIter.Current; } if (otherIter.MoveNext()) { theirs = (Interval)otherIter.Current; } while (mine != null) { //[email protected]("mine="+mine+", theirs="+theirs); // CASE 1: nothing in theirs removes a chunk from mine if (theirs == null || mine.disjoint(theirs)) { // SUBCASE 1a: finished traversing theirs; keep adding mine now if (theirs == null) { // add everything in mine to difference since theirs done diff.add(mine); mine = null; if (thisIter.MoveNext()) { mine = (Interval)thisIter.Current; } } else { // SUBCASE 1b: mine is completely to the left of theirs // so we can add to difference; move mine, but not theirs if (mine.startsBeforeDisjoint(theirs)) { diff.add(mine); mine = null; if (thisIter.MoveNext()) { mine = (Interval)thisIter.Current; } } // SUBCASE 1c: theirs is completely to the left of mine else { // keep looking in theirs theirs = null; if (otherIter.MoveNext()) { theirs = (Interval)otherIter.Current; } } } } else { // CASE 2: theirs breaks mine into two chunks if (mine.properlyContains(theirs)) { // must add two intervals: stuff to left and stuff to right diff.add(mine.a, theirs.a - 1); // don't actually add stuff to right yet as next 'theirs' // might overlap with it // The stuff to the right might overlap with next "theirs". // so it is considered next Interval right = new Interval(theirs.b + 1, mine.b); mine = right; // move theirs forward theirs = null; if (otherIter.MoveNext()) { theirs = (Interval)otherIter.Current; } } // CASE 3: theirs covers mine; nothing to add to diff else if (theirs.properlyContains(mine)) { // nothing to add, theirs forces removal totally of mine // just move mine looking for an overlapping interval mine = null; if (thisIter.MoveNext()) { mine = (Interval)thisIter.Current; } } // CASE 4: non proper overlap else { // overlap, but not properly contained diff.add(mine.differenceNotProperlyContained(theirs)); // update iterators bool moveTheirs = true; if (mine.startsBeforeNonDisjoint(theirs) || theirs.b > mine.b) { // uh oh, right of theirs extends past right of mine // therefore could overlap with next of mine so don't // move theirs iterator yet moveTheirs = false; } // always move mine mine = null; if (thisIter.MoveNext()) { mine = (Interval)thisIter.Current; } if (moveTheirs) { theirs = null; if (otherIter.MoveNext()) { theirs = (Interval)otherIter.Current; } } } } } return(diff); }