in baremaps-flatgeobuf/src/main/java/org/apache/baremaps/flatgeobuf/PackedRTree.java [332:403]
public static SearchResult search(
InputStream stream,
int start,
int numItems,
int nodeSize,
Envelope rect) throws IOException {
LittleEndianDataInputStream data = new LittleEndianDataInputStream(stream);
int dataPos = 0;
int skip;
List<SearchHit> hits = new ArrayList<>();
double minX = rect.getMinX();
double minY = rect.getMinY();
double maxX = rect.getMaxX();
double maxY = rect.getMaxY();
List<Pair<Integer, Integer>> levelBounds = generateLevelBounds(numItems, nodeSize);
int leafNodesOffset = levelBounds.get(0).first;
int numNodes = levelBounds.get(0).second;
Deque<QueueItem> queue = new LinkedList<QueueItem>();
queue.add(new QueueItem(0, levelBounds.size() - 1));
while (!queue.isEmpty()) {
QueueItem stackItem = queue.pop();
int nodeIndex = (int) stackItem.nodeIndex;
int level = stackItem.level;
boolean isLeafNode = nodeIndex >= numNodes - numItems;
// find the end index of the node
int levelBound = levelBounds.get(level).second;
int end = Math.min(nodeIndex + nodeSize, levelBound);
int nodeStart = nodeIndex * NODE_ITEM_LEN;
skip = nodeStart - dataPos;
if (skip > 0) {
skipNBytes(data, skip);
dataPos += skip;
}
// search through child nodes
for (int pos = nodeIndex; pos < end; pos++) {
int offset = nodeStart + ((pos - nodeIndex) * NODE_ITEM_LEN);
skip = offset - dataPos;
if (skip > 0) {
skipNBytes(data, skip);
dataPos += skip;
}
double nodeMinX = data.readDouble();
dataPos += 8;
if (maxX < nodeMinX) {
continue;
}
double nodeMinY = data.readDouble();
dataPos += 8;
if (maxY < nodeMinY) {
continue;
}
double nodeMaxX = data.readDouble();
dataPos += 8;
if (minX > nodeMaxX) {
continue;
}
double nodeMaxY = data.readDouble();
dataPos += 8;
if (minY > nodeMaxY) {
continue;
}
long indexOffset = data.readLong();
dataPos += 8;
if (isLeafNode) {
hits.add(new SearchHit(indexOffset, (long) pos - leafNodesOffset));
} else {
queue.add(new QueueItem(indexOffset, level - 1));
}
}
}
return new SearchResult(hits, dataPos);
}