C++ (Qt)index = (index + 1) % m_dimensions;
C++ (Qt) node* m_best = nullptr; real_t m_best_dist = 0.0;
C++ (Qt) vec_t predict(const vec_t & data, size_t tests = 10) const { size_t N = std::min(m_kdtree.num_nodes(), (tests) ? tests : size_t(1)); vec_t output = m_kdtree.nearest(data).second; const real_t r = sqrt(3.0/m_kdtree.dimensions()) * m_kdtree.radius(); std::uniform_real_distribution<real_t> dist(-r, r); for (size_t i = 1; i < N; ++i) { vec_t p = data; for (auto & x : p) x += dist(m_gen); auto stat = m_kdtree.nearest(p).second; for (size_t j = 0; j < output.size(); ++j) { output[j] += (stat[j] - output[j])/(i+1); } } return output; }
C++ (Qt)void kd_tree::nearest( const vec_t & ip, // запросная точка double & ioRadius, // напр -1 если начального R нет int iMaxNear; // макс число ближайших (-1 если всех) std::vector<vec_t *> & outPt ); // вектор найденных ближайших
C++ (Qt)index = (index + 1) % m_dimensions; middle->m_left = make_tree(begin, middle, index); // Здесь индекс уже для следующей компоненты вектора middle->m_right = make_tree(std::next(middle, 1), end, index);
C++ (Qt) struct CFindData { vec_t mPt; double mRad; int mMaxNear; std::vector<node *> mOut; }; void nearest(node ** beg, node ** end, size_t index, CFindData & data ) { auto num = end - beg; // std::distance? if (num < 1) return; node *& mid = *(beg + dist / 2); bool scanLeft = true, scanRight = true; // пытаемся добавить точку data.AddPoint(mid); if (num < 2) return; // если радиус есть (был или появился после AddPoint),// то отсекаем точки что заведомо далеко if (data.mRad >= 0.0) { real_t dx = mid->get(index) - data.mPt[index]; scanRight = (dx < data.mRad); scanLeft = (dx > -data.mRad); } index = (index + 1) % m_dimensions; // халтура // продолжаем рекурсивно if (scanLeft) nearest(beg, &mid, index, data); if (scanLeft) nearest(&mid + 1, end, index, data); }
C++ (Qt)bool CFindData::AddPoint( node * pt ){// гонорируем точку за границами радиуса double dist = pt->distance(mPt); if ((mRad >= 0.0) && (dist >= mRad)) return false; // вставляем точку в сортированный вектор auto it = std::lower_bound(mOutPt.begin(), mOutPt.end(), pt, CompDistFunc); mOutPt.insert(it, pt); // вычисляем новый радиус if (mMaxNear > 0) { if (mOutPt.size() > mMaxNear) mOutPt.resize(mMaxNear); if (mOutPt.size() >= mMaxNear) mRad = mPt.distance(*mOutPt.back()); } else assert(mRad >= 0.0); // хотя бы 1 (mRad и mMaxNear) должен быть задан return true;}