public Point2D nearest(Point2D p) { // a nearest neighbor in the set to p; null if set is empty
    Stack<Point2D> stack = new Stack<Point2D>();

    nearestNode(root, p, stack, 2.0);

    return stack.pop();
  }
  private void nearestNode(Node2d node, Point2D queryP, Stack<Point2D> stack, double distance) {
    if (node == null) return;

    if (distance < node.rect.distanceSquaredTo(queryP)) return;

    if (queryP.distanceSquaredTo(node.p) < distance) {
      stack.push(node.p);
      distance = queryP.distanceSquaredTo(node.p);
    }

    if (node.depth % 2 == 0) {
      if (queryP.x() < node.p.x()) {
        distance = queryP.distanceSquaredTo(stack.peek());
        nearestNode(node.left, queryP, stack, distance);
        distance = queryP.distanceSquaredTo(stack.peek());
        nearestNode(node.right, queryP, stack, distance);
      } else {
        distance = queryP.distanceSquaredTo(stack.peek());
        nearestNode(node.right, queryP, stack, distance);
        distance = queryP.distanceSquaredTo(stack.peek());
        nearestNode(node.left, queryP, stack, distance);
      }
    } else {
      if (queryP.y() < node.p.y()) {
        distance = queryP.distanceSquaredTo(stack.peek());
        nearestNode(node.left, queryP, stack, distance);
        distance = queryP.distanceSquaredTo(stack.peek());
        nearestNode(node.right, queryP, stack, distance);
      } else {
        distance = queryP.distanceSquaredTo(stack.peek());
        nearestNode(node.right, queryP, stack, distance);
        distance = queryP.distanceSquaredTo(stack.peek());
        nearestNode(node.left, queryP, stack, distance);
      }
    }
  }