       return
 
   delete: (id) ->
-    if @ids.has(id)
-      @ids.delete(id)
-      i = 0
-      while i < @children.length
-        @children[i].delete(id)
-        if @children[i - 1]?.shouldMergeWith(@children[i])
-          @children.splice(i - 1, 2, @children[i - 1].merge(@children[i]))
-        else
-          i++
-
-  hasEmptyRightmostLeaf: ->
-    @children[@children.length - 1].hasEmptyRightmostLeaf()
-
-  hasEmptyLeftmostLeaf: ->
-    @children[0].hasEmptyLeftmostLeaf()
+    return unless @ids.delete(id)
+    i = 0
+    while i < @children.length
+      @children[i].delete(id)
+      if @children[i - 1]?.shouldMergeWith(@children[i])
+        @children.splice(i - 1, 2, @children[i - 1].merge(@children[i]))
+      else
+        i++
 
   splice: (position, oldExtent, newExtent, excludedIds) ->
-    childStart = Point.zero()
-    oldExtentEmpty = oldExtent.isZero()
-    for child in @children
+    oldRangeIsEmpty = oldExtent.isZero()
+    childEnd = Point.zero()
+    for child in @children
+      childStart = childEnd
       childEnd = childStart.traverse(child.extent)
 
       if remainderToDelete?
-        break unless remainderToDelete.isPositive()
         remainderToDelete = child.splice(Point.zero(), remainderToDelete, Point.zero())
         continue
 
-      comparison = childEnd.compare(position)
-      if comparison > 0 or (comparison is 0 and oldExtentEmpty and child.hasEmptyRightmostLeaf())
-        remainderToDelete = child.splice(position.traversalFrom(childStart), oldExtent, newExtent, excludedIds)
-
-      childStart = childEnd
+      switch childEnd.compare(position)
+        when -1 then childPrecedesRange = true
+        when 0  then childPrecedesRange = not (child.hasEmptyRightmostLeaf() and oldRangeIsEmpty)
+        when 1  then childPrecedesRange = false
+      continue if childPrecedesRange
+
+      relativeStart = position.traversalFrom(childStart)
+      remainderToDelete = child.splice(relativeStart, oldExtent, newExtent, excludedIds)
 
     @extent = @extent
       .traverse(newExtent.traversalFrom(oldExtent))
       .traverse(remainderToDelete)
     remainderToDelete
 
-  shouldMergeWith: (other) ->
-    @children.length + other.children.length <= BRANCHING_FACTOR
-
-  merge: (other) ->
-    new Node(@children.concat(other.children))
-
   getStart: (id) ->
     return unless @ids.has(id)
-    childStart = Point.zero()
-    for child in @children
+    childEnd = Point.zero()
+    for child in @children
+      childStart = childEnd
+      childEnd = childStart.traverse(child.extent)
       if startRelativeToChild = child.getStart(id)
         return childStart.traverse(startRelativeToChild)
-      childStart = childStart.traverse(child.extent)
     return
 
   getEnd: (id) ->
     return unless @ids.has(id)
-    childStart = Point.zero()
-    for child in @children
+    childEnd = Point.zero()
+    for child in @children
+      childStart = childEnd
+      childEnd = childStart.traverse(child.extent)
       if endRelativeToChild = child.getEnd(id)
         end = childStart.traverse(endRelativeToChild)
       else if end?
         break
-      childStart = childStart.traverse(child.extent)
     end
 
   findContaining: (point, set) ->
-    childStart = Point.zero()
-    for child in @children
-      childEnd = childStart.traverse(child.extent)
-      if point.compare(childEnd) <= 0
-        child.findContaining(point.traversalFrom(childStart), set)
-      break if childEnd.compare(point) > 0
-      childStart = childEnd
+    childEnd = Point.zero()
+    for child in @children
+      childStart = childEnd
+      childEnd = childStart.traverse(child.extent)
+      continue if childEnd.compare(point) < 0
+      break if childStart.compare(point) > 0
+      child.findContaining(point.traversalFrom(childStart), set)
 
   findIntersecting: (start, end, set) ->
     if start.isZero() and end.compare(@extent) is 0
       addSet(set, @ids)
-    else
-      childEnd = Point.zero()
-      for child in @children
-        childStart = childEnd
-        childEnd = childStart.traverse(child.extent)
-        continue if childEnd.compare(start) < 0
-        break if childStart.compare(end) > 0
-        child.findIntersecting(
-          Point.max(Point.zero(), start.traversalFrom(childStart)),
-          Point.min(child.extent, end.traversalFrom(childStart)),
-          set
-        )
+      return
+
+    childEnd = Point.zero()
+    for child in @children
+      childStart = childEnd
+      childEnd = childStart.traverse(child.extent)
+      continue if childEnd.compare(start) < 0
+      break if childStart.compare(end) > 0
+      child.findIntersecting(
+        Point.max(Point.zero(), start.traversalFrom(childStart)),
+        Point.min(child.extent, end.traversalFrom(childStart)),
+        set
+      )
+
+  hasEmptyRightmostLeaf: ->
+    @children[@children.length - 1].hasEmptyRightmostLeaf()
+
+  hasEmptyLeftmostLeaf: ->
+    @children[0].hasEmptyLeftmostLeaf()
+
+  shouldMergeWith: (other) ->
+    @children.length + other.children.length <= BRANCHING_FACTOR
+
+  merge: (other) ->
+    new Node(@children.concat(other.children))
 
   toString: (indentLevel=0) ->
     indent = ""

      addSet(@ids, child.ids)

  insert: (ids, start, end) ->
    # Insert the given id into all children that intersect the given range.
    # Take the intersection of the given range and the child's range when
    # inserting into each child.
    rangeIsEmpty = start.compare(end) is 0
    childEnd = Point.zero()
    i = 0

    # shrink enough, we may need to shrink subsequent leaves.
    @extent.traversalFrom(myOldExtent).traversalFrom(spliceDelta)

  getStart: (id) ->
    Point.zero() if @ids.has(id)

  getEnd: (id) ->
    @extent if @ids.has(id)

  findContaining: (point, set) ->
    addSet(set, @ids)

  findIntersecting: (start, end, set) ->
    addSet(set, @ids)

  hasEmptyRightmostLeaf: ->
    @extent.isZero()

  hasEmptyLeftmostLeaf: ->
    @extent.isZero()

  shouldMergeWith: (other) ->
    setEqual(@ids, other.ids)

  merge: (other) ->
    new Leaf(@extent.traverse(other.extent), new Set(@ids))

  toString: (indentLevel=0) ->
    indent = ""
