#pragma once
#include "manifold/common.h"
#include "manifold/optional_assert.h"
#include "manifold/polygon.h"
#include "manifold/vec_view.h"
namespace manifold {
void BuildTwoDTreeImpl(VecView<PolyVert> points, bool sortX);
void BuildTwoDTree(VecView<PolyVert> points);
template <typename F>
void QueryTwoDTree(VecView<PolyVert> points, Rect r, F f) {
if (points.size() <= 8) {
for (const auto& p : points)
if (r.Contains(p.pos)) f(p);
return;
}
Rect current;
current.min = vec2(-std::numeric_limits<double>::infinity());
current.max = vec2(std::numeric_limits<double>::infinity());
int level = 0;
VecView<PolyVert> currentView = points;
std::array<Rect, 64> rectStack;
std::array<VecView<PolyVert>, 64> viewStack;
std::array<int, 64> levelStack;
int stackPointer = 0;
while (1) {
if (currentView.size() <= 8) {
for (const auto& p : currentView)
if (r.Contains(p.pos)) f(p);
if (--stackPointer < 0) break;
level = levelStack[stackPointer];
currentView = viewStack[stackPointer];
current = rectStack[stackPointer];
continue;
}
Rect left = current;
Rect right = current;
const PolyVert middle = currentView[currentView.size() / 2];
if (level % 2 == 0)
left.max.x = right.min.x = middle.pos.x;
else
left.max.y = right.min.y = middle.pos.y;
if (r.Contains(middle.pos)) f(middle);
if (left.DoesOverlap(r)) {
if (right.DoesOverlap(r)) {
DEBUG_ASSERT(stackPointer < 64, logicErr, "Stack overflow");
rectStack[stackPointer] = right;
viewStack[stackPointer] = currentView.view(currentView.size() / 2 + 1);
levelStack[stackPointer] = level + 1;
stackPointer++;
}
current = left;
currentView = currentView.view(0, currentView.size() / 2);
level++;
} else {
current = right;
currentView = currentView.view(currentView.size() / 2 + 1);
level++;
}
}
}
}