public void findIntersections(Rectangle query, Consumer<T> consumer)
    {
        IntArrayList todoNodes = new IntArrayList(levelOffsets.length * degree);
        IntArrayList todoLevels = new IntArrayList(levelOffsets.length * degree);

        int rootLevel = levelOffsets.length - 1;
        int rootIndex = levelOffsets[rootLevel];
        if (doesIntersect(query, rootIndex)) {
            todoNodes.push(rootIndex);
            todoLevels.push(rootLevel);
        }

        while (!todoNodes.isEmpty()) {
            int nodeIndex = todoNodes.popInt();
            int level = todoLevels.popInt();

            if (level == 0) {
                // This is a leaf node
                consumer.accept(items[nodeIndex / ENVELOPE_SIZE]);
            }
            else {
                int childrenOffset = getChildrenOffset(nodeIndex, level);
                for (int i = 0; i < degree; i++) {
                    int childIndex = childrenOffset + ENVELOPE_SIZE * i;
                    if (doesIntersect(query, childIndex)) {
                        todoNodes.push(childIndex);
                        todoLevels.push(level - 1);
                    }
                }
            }
        }
    }
@Test
    public void testSingletonFlatbushXY()
    {
        // Because mixing up x and y is easy to do...
        List<Rectangle> items = ImmutableList.of(new Rectangle(0, 10, 1, 11));
        Flatbush<Rectangle> rtree = new Flatbush<>(items.toArray(new Rectangle[] {}));

        // hit
        assertEquals(findIntersections(rtree, new Rectangle(1, 11, 2, 12)), items);
        // miss
        assertEquals(findIntersections(rtree, new Rectangle(11, 1, 12, 2)), ImmutableList.of());
    }