code: private void adjustTree(Node n, Node nn)
    {
      // special case for root
      if (n == root) {
        if (nn != null) {
          root = buildRoot(false);
          root.addChild(n);
          root.addChild(nn);
        }
        root.enclose();
        return;
      }
  
      boolean updateParent = n.enclose();
  
      if (nn != null) {
        nn.enclose();
        updateParent = true;
  
        if (splitStrategy.needToSplit(n.getParent())) {
          Node[] groups = splitStrategy.split(n.getParent());
          adjustTree(groups[0], groups[1]);
        }
      }
  
      if (n.getParent() != null && updateParent) {
        adjustTree(n.getParent(), null);
      }
    }
docs: This description is from the original paper.
  
  AT1. [Initialize]. Set N=L. If L was split previously, set NN to be the resulting second node.
  
  AT2. [Check if done]. If N is the root, stop.
  
  AT3. [Adjust covering rectangle in parent entry]. Let P be the parent node of N, and let Ev(N)I be N's entry in P.
  Adjust Ev(N)I so that it tightly encloses all entry rectangles in N.
  
  AT4. [Propagate node split upward]. If N has a partner NN resulting from an earlier split, create a new entry
  Ev(NN) with Ev(NN)p pointing to NN and Ev(NN)I enclosing all rectangles in NN. Add Ev(NN) to p is there is room.
  Otherwise, invoke {@link SplitStrategy} split to product p and pp containing Ev(NN) and all p's old entries.
  
  @param n  - first node to adjust
  @param nn - optional second node to adjust