G+Smo  25.01.0
Geometry + Simulation Modules
 
Loading...
Searching...
No Matches
gsKdNode.h
Go to the documentation of this file.
1
14# pragma once
15
16#include <gsHSplines/gsAABB.h>
17
18namespace gismo {
19
33template<short_t d, class Z = index_t>
35{
36 // Defines the type of the box
37 typedef gsAABB<d, Z> kdBox;
38 typedef typename kdBox::point point;
39
42 int axis;
43
45 Z pos;
46
49 int level ;
50
55
58
61
64
66 gsKdNode() : axis(-2) ,level(0), box(0),
67 parent(0), left(0), right(0)
68 { }
69
71 gsKdNode(point const & upp) : axis(-1) , level(0),
72 parent(0), left(0) , right(0)
73 {
74 // Initial box, upp is expected to be indexed in finest level
75 box = new kdBox( point::Zero(), upp);
76 }
77
79 gsKdNode(point const & low, point const & upp) : axis(-1) , level(0),
80 parent(0), left(0) , right(0)
81 {
82 // Initial box, upp is expected to be indexed in finest level
83 box = new kdBox( low, upp);
84 }
85
87 gsKdNode(kdBox const & bb) : axis(-1) , level(0),
88 parent(0), left(0) , right(0)
89 {
90 // ..
91 }
92
95 gsKdNode(const gsKdNode & o, gsKdNode * parentNode = NULL) : axis(o.axis), level(o.level)
96 {
97 parent = parentNode;
98 if ( axis == -1 )
99 {
100 GISMO_ASSERT( (o.left == 0) && (o.right == 0),
101 "Problem: leaf with children." );
102 box = new kdBox(*o.box);
103 left = right = NULL;
104 }
105 else
106 {
107 GISMO_ASSERT( o.box == 0,
108 "Problem: split node with box." );
109 pos = o.pos;
110 left = new gsKdNode(*o.left , this);
111 right = new gsKdNode(*o.right, this);
112 box = NULL;
113 }
114 }
115
118 {
119 // TODO: non-recursive
120
121 if ( isLeaf() )
122 {
123 delete box;
124 }
125 else
126 {
127 delete left;
128 delete right;
129 }
130 }
131
132 // Box Accessors
133 const point & lowCorner() const
134 {
135 GISMO_ASSERT(box, "Asked for lowCorner at node without box data.");
136 return box->first ;
137 }
138
139 const point & uppCorner() const
140 {
141 GISMO_ASSERT(box, "Asked for uppCorner at node without box data.");
142 return box->second;
143 }
144
145 bool isLeaf() const { return axis == -1; }
146
147 bool isRoot() const { return parent == NULL; }
148
149 bool isTerminal() const
150 { return (axis!=-1) && (left->axis==-1) && (right->axis==-1); }
151
152 bool isLeftChild() const { return parent!=NULL && this==parent->left; }
153
154 bool isRightChild() const { return parent!=NULL && this==parent->right; }
155
156 bool isDegenerate() const
157 { return (box->first.array() >= box->second.array()).any(); }
158
159 gsKdNode * sibling() const
160 {
161 GISMO_ASSERT( parent != 0, "Root does not have a sibling.");
162 return (parent->left == this ? parent->right : parent->left );
163 }
164
165 void multiplyByTwo()
166 {
167 if ( isLeaf() )
168 {
169 box->first .array() *= 2;
170 box->second.array() *= 2;
171 }
172 else
173 {
174 pos *= 2;
175 }
176 }
177
178 void divideByTwo()
179 {
180 if ( isLeaf() )
181 {
182 box->first .array() /= 2;
183 box->second.array() /= 2;
184 }
185 else
186 {
187 pos /= 2;
188 }
189 }
190
192 inline void split()
193 {
194 GISMO_ASSERT( (left == 0) && (right == 0),
195 "Can only split leaf nodes.");
196 GISMO_ASSERT( axis > -1, "Split axis not prescribed.");
197
198 // Make new left and right children
199 left = new gsKdNode;
200 right = new gsKdNode;
201 // Set axis to -1 (since they are leaves)
202 left ->axis =
203 right->axis = -1;
204 // Set parent to this node
205 left ->parent =
206 right->parent = this;
207 // Set level
208 left ->level =
209 right->level = level;
210 // Set box
211 left ->box = box;
212 right->box = new kdBox(*box);
213 // Detach box from parent (is now at left child)
214 box = NULL;
215 // Resize properly the box coordinates
216 left ->box->second[axis] =
217 right->box->first [axis] = pos;
218 }
219
221 inline void merge()
222 {
223 GISMO_ASSERT( (left->isLeaf()) && (right->isLeaf()),
224 "Can only merge terminal nodes.");
225
226 // Recover box
227 box = left->box;
228 left->box = NULL;
229 box->second[axis] = right->box->second[axis];
230 axis = - 1;
231 level = left->level;
232
233 // Delete children
234 delete left;
235 left = NULL;
236 delete right;
237 right = NULL;
238 }
239
240
242 void split(int splitAxis, Z splitPos)
243 {
244 GISMO_ASSERT( box->second[splitAxis] != splitPos, "Degenerate split " << box->second[splitAxis] <<" != "<<splitPos);
245 GISMO_ASSERT( box->first [splitAxis] != splitPos, "Degenerate split " << box->first[splitAxis] <<" != "<<splitPos);
246 axis = splitAxis;
247 pos = splitPos;
248 split();
249 }
250
252 // TODO: remove
254 {
255 axis = ( parent == 0 ? 0 : (parent->axis+1)%d );
256 pos = box->first [axis] +
257 (box->second[axis] - box->first[axis])/2 ;
258 split(); // Can be degenerate
259 }
260
263 void anyMidSplit(int index_level)
264 {
265 const unsigned h = 1 << (index_level - level) ;
266 const unsigned mask = ~(h - 1);
267 for ( unsigned i = 0; i < d; ++i )
268 {
269 const unsigned c =
270 (box->first [i] + (box->second[i] - box->first[i])/2) & mask ;
271 if ( c != box->first [i] ) // avoid degenerate split
272 {
273 split(i, c);
274 return;
275 }
276 }
277 }
278
279
285 gsKdNode * adaptiveAlignedSplit(kdBox const & insBox, int index_level)
286 {
287 const unsigned h = 1 << (index_level - level) ;
288
289 for (short_t i = 0; i < d; ++i)
290 {
291 const Z c1 = insBox. first[i] - insBox. first[i] % h; //floor
292 const Z cc = insBox.second[i] % h;
293 const Z c2 = insBox.second[i] + (cc ? h-cc : 0 ); // ceil
294
295 if ( c1 > box->first[i] )
296 {
297 // right child intersects insBox
298 split(i, c1 );
299 return right;
300 }
301 else if ( c2 < box->second[i] )
302 {
303 // left child intersects insBox
304 split(i, c2 );
305 return left;
306 }
307 }
308 return NULL;
309 }
310
314 // TODO: remove
315 gsKdNode * adaptiveSplit(kdBox const & insBox)
316 {
317 // assumption: insBox intersects box
318 for ( unsigned i = 0; i < d; ++i )
319 {
320 // TODO: strategy: Try to split as close to the middle as possible.
321 if ( insBox.first[i] > box->first[i] )
322 {
323 axis = i;
324 pos = insBox.first[i];
325 split();
326 return right;
327 }
328 else if ( insBox.second[i] < box->second[i] )
329 {
330 axis = i;
331 pos = insBox.second[i];
332 split();
333 return left ;
334 }
335 }
336 // insBox is equal to this->box or they do not overlap
337 return NULL;
338 }
339
340 friend std::ostream & operator<<(std::ostream & os, const gsKdNode & n)
341 {
342 if ( n.isLeaf() )
343 {
344 os << "Leaf node ("<< n.box->first.transpose() <<"), ("
345 << n.box->second.transpose() <<"). level="<<n.level<<" \n";
346 }
347 else
348 {
349 os << "Split node, axis= "<< n.axis <<", pos="<< n.pos <<"\n";
350 }
351
352 return os;
353 }
354
355};
356
357
358}// namespace gismo
Declarations of the class gsAABB, i.e., the axis-aligned bounding box.
#define short_t
Definition gsConfig.h:35
#define GISMO_ASSERT(cond, message)
Definition gsDebug.h:89
The G+Smo namespace, containing all definitions for the library.
Struct of for an Axis-aligned bounding box.
Definition gsAABB.h:31
Struct representing a kd-tree node.
Definition gsKdNode.h:35
void nextMidSplit()
Splits the node in the middle (ie. two children are added)
Definition gsKdNode.h:253
gsKdNode * adaptiveAlignedSplit(kdBox const &insBox, int index_level)
Definition gsKdNode.h:285
~gsKdNode()
Recursively deletes the whole subtree under this node.
Definition gsKdNode.h:117
kdBox * box
Definition gsKdNode.h:54
void split(int splitAxis, Z splitPos)
Splits the node (i.e., two children are added)
Definition gsKdNode.h:242
Z pos
Split coordinate (meaningfull only for split nodes)
Definition gsKdNode.h:45
gsKdNode * left
Pointer to the left child of this split node (if it is one)
Definition gsKdNode.h:60
void split()
Splits the node (i.e., two children are added)
Definition gsKdNode.h:192
int axis
Definition gsKdNode.h:42
gsKdNode * right
Pointer to the right child of this split node (if it is one)
Definition gsKdNode.h:63
gsKdNode(point const &low, point const &upp)
Constructor (root node)
Definition gsKdNode.h:79
gsKdNode()
Constructor (empty node)
Definition gsKdNode.h:66
gsKdNode * parent
Pointer to the parent node.
Definition gsKdNode.h:57
gsKdNode(point const &upp)
Constructor (root node)
Definition gsKdNode.h:71
void anyMidSplit(int index_level)
Definition gsKdNode.h:263
gsKdNode * adaptiveSplit(kdBox const &insBox)
Definition gsKdNode.h:315
int level
Definition gsKdNode.h:49
gsKdNode(const gsKdNode &o, gsKdNode *parentNode=NULL)
Definition gsKdNode.h:95
gsKdNode(kdBox const &bb)
Constructor (leaf node)
Definition gsKdNode.h:87
void merge()
Merges terminal node (i.e., two children are joined)
Definition gsKdNode.h:221