#include "pch.h" // use stdafx.h in Visual Studio 2017 and earlier #include "KDtree.h" KDtree kdtree; bool cmp0(const point &a, const point &b) { return a.x[0] < b.x[0]; } bool cmp1(const point &a, const point &b) { return a.x[1] < b.x[1]; } bool cmp2(const point &a, const point &b) { return a.x[2] < b.x[2]; } point::point() { x[0] = x[1] = x[2] = 0; id = 0; } bool node::operator<(node b) const { return dis < b.dis || (dis == b.dis && id < b.id); } node::node() { dis = 0; id = 0; } node::node(int id1, double dis1) { dis = dis1; id = id1; } tree::tree() { ls = rs = id = 0; } KDtree::KDtree() { X = Y = Z = 0; n = tot = root = 0; } double KDtree::dis(tree &x) { double P = (x.p.x[0] - X) * (x.p.x[0] - X); double Q = (x.p.x[1] - Y) * (x.p.x[1] - Y); double O = (x.p.x[2] - Z) * (x.p.x[2] - Z); return P + Q + O; } double KDtree::mndis(tree &x) { double P = (x.mn[0] - X) * (x.mn[0] - X); double M = (x.mx[0] - X) * (x.mx[0] - X); if (X >= x.mn[0] && X <= x.mx[0]) P = M = 0; double Q = (x.mn[1] - Y) * (x.mn[1] - Y); double N = (x.mx[1] - Y) * (x.mx[1] - Y); if (Y >= x.mn[1] && Y <= x.mx[1]) Q = N = 0; double O = (x.mn[2] - Z) * (x.mn[2] - Z); double U = (x.mx[2] - Z) * (x.mx[2] - Z); if (Z >= x.mn[2] && Z <= x.mx[2]) O = U = 0; return min(P, M) + min(Q, N) + min(O, U); } void KDtree::update(int x) { if (!x) return; int l = t[x].ls, r = t[x].rs; if (l) t[x].mn[0] = min(t[x].mn[0], t[l].mn[0]), t[x].mn[1] = min(t[x].mn[1], t[l].mn[1]), t[x].mn[2] = min(t[x].mn[2], t[l].mn[2]), t[x].mx[0] = max(t[x].mx[0], t[l].mx[0]), t[x].mx[1] = max(t[x].mx[1], t[l].mx[1]), t[x].mx[2] = max(t[x].mx[2], t[l].mx[2]); if (r) t[x].mn[0] = min(t[x].mn[0], t[r].mn[0]), t[x].mn[1] = min(t[x].mn[1], t[r].mn[1]), t[x].mn[2] = min(t[x].mn[2], t[r].mn[2]), t[x].mx[0] = max(t[x].mx[0], t[r].mx[0]), t[x].mx[1] = max(t[x].mx[1], t[r].mx[1]), t[x].mx[2] = max(t[x].mx[2], t[r].mx[2]); } void KDtree::query(int x) { if (!x) return; double res = dis(t[x]); if (res < q.top().dis || (res == q.top().dis && t[x].id < q.top().id)) q.pop(), q.push(node(t[x].id, res)); int l = t[x].ls, r = t[x].rs; double ld = 0, rd = 0; if (l) ld = mndis(t[l]); if (r) rd = mndis(t[r]); // cout< r) return; x = ++tot; int mid = (l + r) >> 1; // cout<<"stage1 "< KDtree::search_by_k(P &s, int k) { X = s.x; Y = s.y; Z = s.z; while (q.size()) q.pop(); for (int j = 1; j <= k; j++) q.push(node(0, 1e9)); query(root); vector veck; while (q.size()) { if (q.top().id != 0) veck.push_back(q.top().id); q.pop(); } return veck; } // 返回距离s点d以内的所有点的编号 vector KDtree::search_by_dis(P &s, double d) { X = s.x; Y = s.y; Z = s.z; vec.clear(); queryd(root, d); return vec; }