/** @file * @brief Representation of the optimized k-d tree. MetaScan variant. * @author Andreas Nuechter. Institute of Computer Science, University of Osnabrueck, Germany. * @author Kai Lingemann. Institute of Computer Science, University of Osnabrueck, Germany. * @author Thomas Escher */ #ifndef __KD_META_H__ #define __KD_META_H__ #include "kdparams.h" #include "searchTree.h" #include "data_types.h" #include #include #ifdef _MSC_VER #if !defined _OPENMP && defined OPENMP #define _OPENMP #endif #endif #ifdef _OPENMP #include #endif class Scan; /** * @brief The optimized k-d tree. * * A kD tree for points, with limited * capabilities (find nearest point to * a given point, or to a ray). **/ class KDtreeMeta : public SearchTree { protected: class Index { public: unsigned int s, i; inline void set(unsigned int _s, unsigned int _i) { s = _s; i = _i; } }; public: KDtreeMeta(); virtual ~KDtreeMeta(); void create(const DataXYZ* const* pts, Index* indices, unsigned int n); virtual double *FindClosest(double *_p, double maxdist2, int threadNum = 0) const { return 0; } protected: /** * storing the parameters of the k-d tree, i.e., the current closest point, * the distance to the current closest point and the point itself. * These global variable are needed in this search. * * Padded in the parallel case. */ #ifdef _OPENMP #ifdef __INTEL_COMPILER __declspec (align(16)) static KDParams params[MAX_OPENMP_NUM_THREADS]; #else static KDParams params[MAX_OPENMP_NUM_THREADS]; #endif //__INTEL_COMPILER #else static KDParams params[MAX_OPENMP_NUM_THREADS]; #endif /** * number of points. If this is 0: intermediate node. If nonzero: leaf. */ int npts; /** * Cue the standard rant about anon unions but not structs in C++ */ union { /** * in case of internal node... */ struct { double center[3]; ///< storing the center of the voxel (R^3) double dx, ///< defining the voxel itself dy, ///< defining the voxel itself dz, ///< defining the voxel itself r2; ///< defining the voxel itself int splitaxis; ///< defining the kind of splitaxis KDtreeMeta *child1; ///< pointers to the childs KDtreeMeta *child2; ///< pointers to the childs } node; /** * in case of leaf node ... */ struct { //! Content is an array of indices to be put into the dynamically aquired data array Index* p; } leaf; }; inline double* point(const DataXYZ* const* pts, const Index& i) const { return (*pts[i.s])[i.i]; } void _FindClosest(const DataXYZ* const* pts, int threadNum) const; }; class KDtreeMetaManaged : public KDtreeMeta { public: KDtreeMetaManaged(const vector& scans); virtual ~KDtreeMetaManaged(); virtual void lock(); virtual void unlock(); //! Aquires cached data first to pass on to the usual KDtree to process virtual double* FindClosest(double *_p, double maxdist2, int threadNum = 0) const; private: Scan** m_scans; DataXYZ** m_data; unsigned int m_size; //! Mutex for safely reducing points just once in a multithreaded environment boost::mutex m_mutex_locking; volatile unsigned int m_count_locking; // constructor initializer list hacks Index* m_temp_indices; Index* prepareTempIndices(const vector& scans); unsigned int getPointsSize(const vector& scans); }; #endif