OpenWalnut  1.5.0dev
WKdTree.cpp
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #include <algorithm>
26 #include <vector>
27 
28 #include "../common/WAssert.h"
29 #include "../common/WLogger.h"
30 
31 #include "WKdTree.h"
32 
33 WKdTree::WKdTree( int size, float *pointArray ) :
34  m_size( size ), m_pointArray( pointArray )
35 {
36  // WAssert( m_size > 2, "The current kD-tree implementation works only with at least 3 vertices." );
37  m_tree.clear();
38  m_tree.resize( m_size );
39 
40  wlog::debug( "KdTree" ) << " Start building KdTree";
41 
42  for( int i = 0; i < m_size; ++i )
43  m_tree[i] = i;
44 
45  int root = ( m_size - 1 ) / 2;
46 
47  if( m_size == 0 )
48  m_root = 0;
49 
50  if( m_size > 0 )
51  {
52  m_root = root;
53  std::nth_element( m_tree.begin(), m_tree.begin() + root, m_tree.end(), lessy( m_pointArray, 0 ) );
54  }
55 
56  int rootLeft = ( root - 1 ) / 2;
57  if( m_size > 2 )
58  {
59  std::nth_element( m_tree.begin(), m_tree.begin() + rootLeft, m_tree.begin() + root - 1, lessy( m_pointArray, 1 ) );
60  }
61 
62  int rootRight = ( m_size + root ) / 2;
63  if( m_size > 1 )
64  {
65  std::nth_element( m_tree.begin() + root + 1, m_tree.begin() + rootRight, m_tree.end(), lessy( m_pointArray, 1 ) );
66  }
67 
68  if( m_size > 2 )
69  {
70  WKdTreeThread *thread1 = new WKdTreeThread( m_pointArray, &m_tree, 0, rootLeft - 1, 2 );
71  WKdTreeThread *thread2 = new WKdTreeThread( m_pointArray, &m_tree, rootLeft + 1, root - 1, 2 );
72  WKdTreeThread *thread3 = new WKdTreeThread( m_pointArray, &m_tree, root + 1, rootRight - 1, 2 );
73  WKdTreeThread *thread4 = new WKdTreeThread( m_pointArray, &m_tree, rootRight + 1, m_size - 1, 2 );
74 
75  wlog::debug( "KdTree" ) << "Start threads";
76 
77  thread1->run();
78  thread2->run();
79  thread3->run();
80  thread4->run();
81 
82  wlog::debug( "KdTree" ) << "All threads started";
83 
84  thread1->wait();
85  thread2->wait();
86  thread3->wait();
87  thread4->wait();
88 
89  wlog::debug( "KdTree" ) << "All threads finished";
90 
91  delete thread1;
92  delete thread2;
93  delete thread3;
94  delete thread4;
95  }
96 }
97 
99 {
100 }
101 
102 void WKdTree::buildTree( int left, int right, int axis )
103 {
104  if( left >= right )
105  return;
106 
107  int div = ( left + right ) / 2;
108  std::nth_element( m_tree.begin() + left, m_tree.begin() + div, m_tree.begin() + right, lessy( m_pointArray, axis ) );
109 
110  buildTree( left, div - 1, ( axis + 1 ) % 3 );
111  buildTree( div + 1, right, ( axis + 1 ) % 3 );
112 }
113 
114 WKdTreeThread::WKdTreeThread( float* pointArray, std::vector< unsigned int >* tree, int left, int right, int axis ) :
115  WThreadedRunner(), m_tree( tree ), m_pointArray( pointArray ), m_left( left ), m_right( right ), m_axis( axis )
116 {
117 }
118 
120 {
122  wlog::debug( "KdTree" ) << "thread finished";
123 }
124 
125 void WKdTreeThread::buildTree( int left, int right, int axis )
126 {
127  if( left >= right )
128  return;
129 
130  int div = ( left + right ) / 2;
131  std::nth_element( m_tree->begin() + left, m_tree->begin() + div, m_tree->begin() + right, lessy( m_pointArray, axis ) );
132 
133  buildTree( left, div - 1, ( axis + 1 ) % 3 );
134  buildTree( div + 1, right, ( axis + 1 ) % 3 );
135 }
class to provide threaded computation of parts of the kd tree
Definition: WKdTree.h:67
std::vector< unsigned int > * m_tree
stores a pointer to the tree
Definition: WKdTree.h:94
WKdTreeThread(float *pointArray, std::vector< unsigned int > *tree, int left, int right, int axis)
constructor
Definition: WKdTree.cpp:114
int m_axis
stores axis, since the threadMain method has no arguments
Definition: WKdTree.h:99
int m_left
stores left boundary, since the threadMain method has no arguments
Definition: WKdTree.h:97
float * m_pointArray
stores a pointer to the vertex array
Definition: WKdTree.h:95
void buildTree(int left, int right, int axis)
recursive function to compute a part of the kd tree
Definition: WKdTree.cpp:125
int m_right
stores left boundary, since the threadMain method has no arguments
Definition: WKdTree.h:98
virtual void threadMain()
entry for the run command
Definition: WKdTree.cpp:119
float * m_pointArray
stores a pointer to the vertex array
Definition: WKdTree.h:134
WKdTree(int size, float *pointArray)
constructor
Definition: WKdTree.cpp:33
~WKdTree()
destructor
Definition: WKdTree.cpp:98
int m_size
size of the tree
Definition: WKdTree.h:132
unsigned int m_root
index of the root point
Definition: WKdTree.h:133
std::vector< unsigned int > m_tree
stores the tree
Definition: WKdTree.h:121
void buildTree(int left, int right, int axis)
recursive function to compute a part of the kd tree
Definition: WKdTree.cpp:102
Base class for all classes needing to be executed in a separate thread.
virtual void run()
Run thread.
void wait(bool requestFinish=false)
Wait for the thread to be finished.
WStreamedLogger debug(const std::string &source)
Logging a debug message.
Definition: WLogger.h:331
implements the compare function for std::nth_element on a point array
Definition: WKdTree.h:37