Warning: session_start(): open(/var/lib/php/sessions/sess_il1a2spqkho7q9el1qljau8km1, O_RDWR) failed: No space left on device (28) in /var/www/tb-usercake/models/config.php on line 51
Warning: session_start(): Failed to read session data: files (path: /var/lib/php/sessions) in /var/www/tb-usercake/models/config.php on line 51
sclass PtTree {
Node root = new Leaf(null);
abstract class Node {
Node parent;
abstract bool add(Pt p);
abstract void collectPointsIn(Rect r, L out);
abstract void replaceChild(Node from, Node to);
void addAll(Iterable l) {
fOr (Pt p : l) add(p);
}
}
class Leaf extends Node {
Cl points;
*(Node *parent) {}
bool add(Pt p) {
if (contains(points, p)) false;
if (l(points) >= maxPointsPerNode)
ret split().add(p);
if (points == null) points = new L;
points.add(p);
true;
}
void collectPointsIn(Rect r, L out) {
addAll(out, points);
}
record noeq ProposedSplit(int dimension, int splitPoint, int count) {
int error() { ret abs(count-half(l(points))); }
}
Split split() {
int n = l(points), half = n/2;
ProposedSplit xSplit = checkSplit(0);
ProposedSplit ySplit = checkSplit(1);
var best = xSplit.error() < ySplit.error() ? xSplit : ySplit;
new Split split;
split.dimension = (byte) best.dimension;
split.splitPoint = best.splitPoint;
Leaf a = new Leaf(split);
IPred pred = p -> ptCoord(split.dimension, p) >= split.splitPoint;
a.addAll(antiFilter(pred, points));
split.a = a;
Leaf b = new Leaf(split);
b.addAll(filter(pred, points));
split.b = b;
ret replaceMeWith(split);
}
A replaceMeWith(A node) {
node.parent = parent;
if (parent != null) parent.replaceChild(this, node);
else if (root == this) root = node;
ret node;
}
ProposedSplit checkSplit(int dimension) {
L lx = sortedBy(points, p -> ptCoord(dimension, p));
new ProposedSplit ps;
ps.dimension = dimension;
int n = l(points), half = n/2;
int i = 0;
int splitPoint = Int.MIN_VALUE;
while true {
int lastSplitpoint = splitPoint;
splitPoint = ptCoord(lx.get(i++), dimension)+1;
int lastI = i;
while (i < n && ptCoord(lx.get(i), dimension) < splitPoint) ++i;
if (i >= half) {
if (abs(lastI-half) < abs(i-half)) {
ps.splitPoint = lastSplitPoint;
ps.count = lastI;
} else {
ps.splitPoint = splitPoint;
ps.count = i;
}
ret ps;
}
}
}
void replaceChild(Node from, Node to) { unimplemented(); } // doesn't need
}
class Split extends Node {
byte dimension; // 0 for X, 1 for Y
int splitPoint;
Node a, b;
void collectPointsIn(Rect r, L out) {
a.collectPointsIn(r, out);
b.collectPointsIn(r, out);
}
void replaceChild(Node from, Node to) {
if (a == from) a = to;
if (b == from) b = to;
}
}
int maxPointsPerNode = 4;
bool add(Pt p) {
ret root.add(p);
}
L pointsIn(Rect r) {
new L out;
root.collectPointsIn(r, out);
ret out;
}
}