From 659cb9affe3f4b6c29558e3b977701131d7e4c27 Mon Sep 17 00:00:00 2001 From: Guilhem Lavaux Date: Fri, 9 Jan 2009 17:42:14 -0600 Subject: [PATCH] Implemented neighbour searching in KDTree (+ BoundedQueue) --- src/bqueue.hpp | 30 ++++++++++++++++++++++ src/bqueue.tcc | 67 ++++++++++++++++++++++++++++++++++++++++++++++++ src/mykdtree.hpp | 24 +++++++++++++---- src/mykdtree.tcc | 65 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 181 insertions(+), 5 deletions(-) create mode 100644 src/bqueue.hpp create mode 100644 src/bqueue.tcc diff --git a/src/bqueue.hpp b/src/bqueue.hpp new file mode 100644 index 0000000..792d309 --- /dev/null +++ b/src/bqueue.hpp @@ -0,0 +1,30 @@ +#ifndef __COSMO_QUEUE_HPP +#define __COSMO_QUEUE_HPP + +#include + +namespace CosmoTool { + + template + class BoundedQueue + { + public: + BoundedQueue(int maxSize, QType defaultMax); + BoundedQueue(T *pQueue, int maxSize, QType defaultMax); + ~BoundedQueue(); + + void push(T a, QType v); + T *getQueue() { return m_queue; } + QType *getPriorities() { return priority; } + QType getMaxPriority() { return priority[maxQueueSize-1]; } + private: + int maxQueueSize; + T *m_queue; + QType *priority; + bool autoFree; + }; +}; + +#include "bqueue.tcc" + +#endif diff --git a/src/bqueue.tcc b/src/bqueue.tcc new file mode 100644 index 0000000..892317f --- /dev/null +++ b/src/bqueue.tcc @@ -0,0 +1,67 @@ +namespace CosmoTool +{ + + template + BoundedQueue::BoundedQueue(int maxSize, QType defaultVal) + { + maxQueueSize = maxSize; + m_queue = new T[maxSize]; + priority = new QType[maxSize]; + autoFree = true; + + for (int i = 0; i < maxSize; i++) + priority[i] = defaultVal; + } + + template + BoundedQueue::BoundedQueue(T *pQueue, int maxSize, QType defaultVal) + { + maxQueueSize = maxSize; + m_queue = pQueue; + priority = new QType[maxSize]; + autoFree = false; + + for (int i = 0; i < maxSize; i++) + priority[i] = defaultVal; + + + } + + template + BoundedQueue::~BoundedQueue() + { + if (autoFree) + delete[] m_queue; + delete[] priority; + } + + + template + void BoundedQueue::push(T a, QType v) + { + if (v > priority[maxQueueSize-1]) + return; + + int i; + for (i = maxQueueSize-2; i >= 0; i--) + { + if (v > priority[i]) + { + priority[i+1] = v; + m_queue[i+1] = a; + return; + } + else + { + priority[i+1] = priority[i]; + m_queue[i+1] = m_queue[i]; + } + } + if (i < 0) + { + priority[0] = v; + m_queue[0] = a; + } + } + +}; diff --git a/src/mykdtree.hpp b/src/mykdtree.hpp index 5734a57..56a9898 100644 --- a/src/mykdtree.hpp +++ b/src/mykdtree.hpp @@ -3,6 +3,7 @@ #include #include "config.hpp" +#include "bqueue.hpp" namespace CosmoTool { @@ -49,6 +50,22 @@ namespace CosmoTool { uint32_t numCells; }; + template + class RecursionMultipleInfo + { + public: + const typename NGBDef::NGBCoordinates& x; + BoundedQueue< NGBCell *, float> queue; + int traversed; + + RecursionMultipleInfo(const typename NGBDef::NGBCoordinates& rx, + NGBCell **cells, + uint32_t numCells) + : x(rx), queue(cells, numCells, INFINITY),traversed(0) + { + } + }; + template class NGBTree { @@ -58,7 +75,6 @@ namespace CosmoTool { public: typedef typename NGBDef::CoordType CoordType; typedef typename NGBDef::NGBCoordinates coords; - typedef typename CosmoQueue*> NGBQueue; NGBTree(NGBCell *cells, uint32_t Ncells); ~NGBTree(); @@ -106,10 +122,8 @@ namespace CosmoTool { const coords& x, CoordType& R2, NGBCell*& cell); - void recursiveMultiNearest(NGBTreeNode *node, - int level, - const coords& x, - NGBQueue& q); + void recursiveMultipleNearest(RecursionMultipleInfo& info, NGBTreeNode *node, + int level); }; template diff --git a/src/mykdtree.tcc b/src/mykdtree.tcc index feb7a42..924e933 100644 --- a/src/mykdtree.tcc +++ b/src/mykdtree.tcc @@ -298,10 +298,75 @@ namespace CosmoTool { return best; } + template + void + NGBTree::recursiveMultipleNearest(RecursionMultipleInfo& info, NGBTreeNode *node, + int level) + { + CoordType d2 = 0; + int axis = level % N; + NGBTreeNode *other, *go; + + if (info.x[axis] < node->value->coord[axis]) + { + // The best is potentially in 0. + go = node->children[0]; + other = node->children[1]; + } + else + { + // If not it is in 1. + go = node->children[1]; + other = node->children[0]; + if (go == 0) + { + go = other; + other = 0; + } + } + + if (go != 0) + { + recursiveMultipleNearest(info, go, level+1); + } + + // Check if current node is not the nearest + CoordType thisR2 = + computeDistance(node->value, info.x); + info.queue.push(node->value, thisR2); + info.traversed++; + if (go == 0) + return; + + // Now we found the best. We check whether the hypersphere + // intersect the hyperplane of the other branch + + CoordType delta1; + + delta1 = info.x[axis]-node->value->coord[axis]; + if (delta1*delta1 < info.queue.getMaxPriority()) + { + // The hypersphere intersects the hyperplane. Try the + // other branch + if (other != 0) + { + recursiveMultipleNearest(info, other, level+1); + } + } + } + template void NGBTree::getNearestNeighbours(const coords& x, uint32_t N2, NGBCell **cells) { + RecursionMultipleInfo info(x, cells, N2); + + for (int i = 0; i < N2; i++) + cells[i] = 0; + + recursiveMultipleNearest(info, root, 0); + + std::cout << "Traversed = " << info.traversed << std::endl; } };