QCAD
Open Source 2D CAD
Loading...
Searching...
No Matches
opennurbs_rtree.h
Go to the documentation of this file.
1/* $NoKeywords: $ */
2/*
3//
4// Copyright (c) 1993-2009 Robert McNeel & Associates. All rights reserved.
5// Rhinoceros is a registered trademark of Robert McNeel & Assoicates.
6//
7// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
8// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
9// MERCHANTABILITY ARE HEREBY DISCLAIMED.
10//
11// For complete openNURBS copyright information see <http://www.opennurbs.org>.
12//
14*/
15
16#if !defined(OPENNURBS_RTREE_INC_)
17#define OPENNURBS_RTREE_INC_
18
19/*
20The opennurbs rtree code is a modifed version of the
21free and unrestricted R-tree implementation obtianed from
22http://www.superliminal.com/sources/sources.htm
23
24The first lines on the website indicate the code is free and unrestricted:
25
26 Free Source Code
27 Here are a few useful bits of free source code.
28 You're completely free to use them for any purpose whatsoever.
29 All I ask is that if you find one to be particularly valuable,
30 then consider sending feedback. Please send bugs and suggestions too.
31 Enjoy
32
33The readme.txt file included with the R-tree source says
34
35 LICENSE:
36 Entirely free for all uses. Enjoy!
37
38The original authors are
39
40AUTHORS
41 * 1983 Original algorithm and test code by Antonin Guttman and Michael Stonebraker, UC Berkely
42 * 1994 ANCI C ported from original test code by Melinda Green - [email protected]
43 * 1995 Sphere volume fix for degeneracy problem submitted by Paul Brook
44 * 2004 Templated C++ port by Greg Douglas
45
46The opennurbs version adds some custom memory allocation and replaces
47the leaf iterator. The rest of the changes are cosmetic.
48
49*/
50
51
52
53// Minimum and maximum number of elements
54// in ON_RTreeNode::m_branch[].
55// must have ON_RTree_MAX_NODE_COUNT > ON_RTree_MIN_NODE_COUNT
56#define ON_RTree_MIN_NODE_COUNT 2
57#define ON_RTree_MAX_NODE_COUNT 6
58
59/*
60In a test of a sphere mesh with mesh: 8385 vertices, 8192 polygons
61and ON_RTree_MAX_NODE_COUNT = 3, 4, 5, and 6, the memory use was
62most efficient with ON_RTree_MAX_NODE_COUNT=6
63
64Memory Usage MAX_NODE_COUNT = 3
65 ON_RTree: 1212 KB (1241136) (352 wasted)
66 ON_RTree: 7036 nodes, 5881 unused branches (321 KB) 0.835844 per node
67
68Memory Usage MAX_NODE_COUNT = 4
69 ON_RTree: 1152 KB (1179720) (5568 wasted)
70 ON_RTree: 5051 nodes, 6962 unused branches (380 KB) 1.37834 per node
71
72Memory Usage MAX_NODE_COUNT = 5
73 ON_RTree: 1040 KB (1065504) (11808 wasted)
74 ON_RTree: 3655 nodes, 6429 unused branches (351 KB) 1.75896 per node
75
76Memory Usage MAX_NODE_COUNT = 6
77 ON_RTree: 995 KB (1019592) (3440 wasted)
78 ON_RTree: 2951 nodes, 6564 unused branches (358 KB) 2.22433 per node
79*/
80
81// This struct is used instead of ON_BoundingBox to avoid calling
82// constructors.
84{
85 double m_min[3];
86 double m_max[3];
87};
88
90{
92
93 // If ON_RTreeNode.m_level > 0, then m_child points to a child node.
94 // If ON_RTreeNode.m_level == 0, then m_id identifies the leaf element.
95 union
96 {
99 };
100};
101
107
108// The ON_RTreeNode is used at root, branch and leaf nodes.
109// When m_level > 0, the node is a branch.
110// When m_level = 0, the node is a leaf.
112{
113 inline bool IsInternalNode() const
114 { return (m_level > 0); } // internal nodes have m_level > 0
115 inline bool IsLeaf() const
116 { return (m_level == 0); } // branch nodes have m_level = 0
117
118 // m_level must be a signed int to insure signed compares work correctly
119 int m_level; // =0 at leaf nodes, > 0 at branch nodes
120
121 // The m_branch[] array contains m_count elements
122 // 0 <= m_count <= ON_RTree_MAX_NODE_COUNT
123 // m_count must be a signed int to insure signed compares work correctly
126};
127
129{
130 int m_capacity; // m_id[] array capacity (search terminates when m_count == m_capacity)
131 int m_count; // number of elements in m_id[]
132 ON__INT_PTR* m_id; // m_id[] = array of search results.
133};
134
136{
137public:
138 ON_RTreeMemPool( ON_MEMORY_POOL* heap, size_t leaf_count );
140
141 ON_RTreeNode* AllocNode();
142 void FreeNode(ON_RTreeNode* node);
143
144 struct ON_RTreeListNode* AllocListNode();
145 void FreeListNode(struct ON_RTreeListNode* list_node);
146
147 void DeallocateAll();
148
149 /*
150 Returns:
151 Total number of bytes of heap memory allocated.
152 */
153 size_t SizeOf() const;
154
155 /*
156 Returns:
157 Number of bytes of heap memory not currently in use.
158 */
159 size_t SizeOfUnusedBuffer() const;
160
161private:
162 void GrowBuffer();
163
164 struct Blk
165 {
166 struct Blk* m_next;
167 };
168
169 // linked list of unused ON_RTreeNode
170 struct Blk* m_nodes;
171 // linked list of unused ON_RTreeListNode
173
174 // buffer for new allocations
175 unsigned char* m_buffer;
177
178 struct Blk* m_blk_list; // linked list used to free all allocated memory
179 size_t m_sizeof_blk; // total amount of memory in each block.
180
182 size_t m_sizeof_heap; // total amount of heap memory in this rtree
183};
184
186//
187// ON_RTreeIterator
188//
189// The ON_RTreeIterator class can be used to iterate each leaf
190// in an ON_RTree.
191//
193{
194public:
195 /*
196 Description:
197 Construct an empty iterator. Call Initialize() to attach
198 the iterator to an R-tree.
199 Remark:
200 Any calls to ON_RTree::Insert() or ON_RTree::Remove() that modify
201 an R-tree being iterated invalidate the iterator. The iterator
202 must be re-initialized before being used again.
203
204 There is no connection between the order elements are inserted
205 in an R-tree and the order the elements are iterated by an
206 iterator.
207 */
209 ON_RTreeIterator(const class ON_RTree& a_rtree);
210
212
213 /*
214 Description:
215 Initialize an iterator to iterate every leaf in the rtree.
216 Parameters:
217 a_rtree - [in]
218 R-tree to iterate
219 Example:
220 See the comment for ON_RTreeIterator::First().
221 Returns:
222 True if a_rtree has at least one element.
223 Remarks:
224 Any calls to ON_RTree::Insert() or ON_RTree::Remove() that modify
225 this node or its children will invalidate this iterator and it
226 must be re-initialized.
227
228 There is no connection between the order elements are inserted
229 in an R-tree and the order the elements are iterated by an
230 iterator.
231 */
232 bool Initialize(const class ON_RTree& a_rtree);
233
234 /*
235 Description:
236 Initialize an iterator to iterate every leaf on or below a_node.
237 Parameters:
238 a_node - [in]
239 R-tree node to iterate
240 Example:
241 See the comment for ON_RTreeIterator::First().
242 Returns:
243 True if a_node has at least one element.
244 Remarks:
245 Any calls to ON_RTree::Insert() or ON_RTree::Remove() that modify
246 this node or its children will invalidate this iterator and it
247 must be re-initialized.
248
249 There is no connection between the order elements are inserted
250 in an R-tree and the order the elements are iterated by an
251 iterator.
252 */
253 bool Initialize(const struct ON_RTreeNode* a_node);
254
255 /*
256 Description:
257 Get the value of the current leaf element. Calling Value()
258 does not increment or decrement the iterator.
259 Example:
260 See the comment for ON_RTreeIterator::First().
261 Return:
262 Null pointer if there are no more leaves to iterate
263 A pointer to the current R-tree leaf. When there are no more leaves,
264 the returned pointer is null.
265 */
266 const ON_RTreeBranch* Value() const;
267
268 /*
269 Description:
270 Reset the iterator so the current leaf is the first leaf in
271 the R-tree. The Initialize() functions automatically do
272 this, but First() can be called if an iterator needs to be
273 used more than once or to make code easy to read and understand.
274 Example:
275 Iterate every leaf in an R-tree.
276
277 ON_RTree rtree;
278 ...
279 ON_RtreeIterator rit(rtree);
280 const ON_RTreeBranch* rtree_leaf;
281 for ( rit.First(); 0 != (rtree_leaf = rit.Value()); rit.Next() )
282 {
283 // leaf id = rtree_leaf->m_id
284 // leaf bounding box = rtree->m_rect
285 }
286
287 Returns:
288 True if a call to Value() will return a non-null pointer.
289 See Also:
290 ON_RTreeIterator::Last();
291 */
292 bool First();
293
294 /*
295 Description:
296 Increment the iterator to the next leaf in the R-tree.
297 Example:
298 See the comment for ON_RTreeIterator::First()
299 Returns:
300 True if a call to Value() will return a non-null pointer.
301 False if there is not a next leaf and all susequent calls to
302 Value() will return null.
303 See Also:
304 ON_RTreeIterator::Prev();
305 */
306 bool Next();
307
308
309 /*
310 Description:
311 Set the iterator so the current leaf is the last leaf in the R-tree.
312
313 Example:
314 Iterate an R-tree in reverse order.
315
316 ON_RTree rtree;
317 ...
318 ON_RTreeIterator rit(rtree);
319 const ON_RTreeBranch* rtree_leaf;
320 for ( rit.Last(); 0 != (rtree_leaf = rit.Value()); rit.Prev() )
321 {
322 // leaf id = rtree_leaf->m_id
323 // leaf bounding box = rtree->m_rect
324 }
325
326 Returns:
327 True if a call to Value() will return a non-null pointer.
328 See Also:
329 ON_RTreeIterator::First();
330 */
331 bool Last();
332
333 /*
334 Description:
335 Decrement the iterator to the previous leaf in the R-tree.
336 Example:
337 See the comment for ON_RTreeIterator::Last()
338 Returns:
339 True if a call to Value() will return a non-null pointer.
340 False if there is not a previous leaf and all susequent calls to
341 Value() will return null.
342 See Also:
343 ON_RTreeIterator::Next();
344 */
345 bool Prev();
346
347private:
348 enum { MAX_STACK = 32 }; // Max stack size. Allows almost n^32 where n is number of branches in node
349
351 {
352 const struct ON_RTreeNode* m_node;
353 int m_branchIndex; // must be a signed int to insure signed compares work correctly
354 };
355
356 bool PushChildren(struct StackElement* sp, bool bFirstChild);
357
358 StackElement m_stack[MAX_STACK]; // stack
359 StackElement* m_sp; // stack pointer (null or points into m_stack[])
360 const ON_RTreeNode* m_root; // root of tree being iterated
361};
362
363
365{
366public:
367 ON_RTree( ON_MEMORY_POOL* heap = 0, size_t leaf_count = 0 );
368 ~ON_RTree();
369
370 /*
371 Description:
372 Create an R-tree with an element for each face in the mesh.
373 The element id is set to the index of the face.
374 Parameters:
375 mesh - [in]
376 Returns:
377 True if successful.
378 */
379 bool CreateMeshFaceTree( const class ON_Mesh* mesh );
380
381 /*
382 Description:
383 Insert an element into the RTree.
384 Parameters:
385 a_min - [in]
386 a_max - [in]
387 3d bounding box of the element. The values in a_min[3] and a_max[3]
388 must satisfy
389 a_min[0] <= a_max[0],
390 a_min[1] <= a_max[1], and
391 a_min[1] <= a_max[1].
392 a_dataId - [in]
393 id of the element. This can be either a pointer or an integer id.
394 Returns:
395 True if element was successfully inserted.
396 Remarks:
397 Calling Insert() or Remove() invalidates any ON_RTreeIterator
398 used to iterate this rtree.
399 */
400 bool Insert(const double a_min[3], const double a_max[3], void* a_element_id);
401 bool Insert(const double a_min[3], const double a_max[3], int a_element_id);
402 bool Insert2d(const double a_min[2], const double a_max[2], void* a_element_id);
403 bool Insert2d(const double a_min[2], const double a_max[2], int a_element_id);
404
405 /*
406 Description:
407 Remove an element from the RTree.
408 Parameters:
409 a_min - [in]
410 a_max - [in]
411 3d bounding box of the element. The values in a_min[3] and a_max[3]
412 must satisfy
413 a_min[0] <= a_max[0],
414 a_min[1] <= a_max[1], and
415 a_min[2] <= a_max[2].
416 a_dataId - [in]
417 id of the element. This can be either a pointer or an integer id.
418 Returns:
419 True if element was successfully removed.
420 Remarks:
421 Calling Insert() or Remove() invalidates any ON_RTreeIterator
422 used to iterate this rtree.
423 */
424 bool Remove(const double a_min[3], const double a_max[3], void* a_elementId);
425 bool Remove(const double a_min[3], const double a_max[3], int a_elementId);
426 bool Remove2d(const double a_min[2], const double a_max[2], void* a_elementId);
427 bool Remove2d(const double a_min[2], const double a_max[2], int a_elementId);
428
429 /*
430 Description:
431 Remove all elements from the R-tree.
432 */
433 void RemoveAll();
434
435
436 /*
437 Description:
438 Search the R-tree for all elements whose bounding boxes overlap
439 (a_min, a_max).
440 Parameters:
441 a_min - [in]
442 a_max - [in]
443 (a_min,a_max) is the bounding box of the search region.
444 a_results - [out]
445 The ids of elements that overlaps the search region.
446 Returns:
447 True if entire tree was searched. It is possible no results were found.
448 */
449 bool Search(const double a_min[3], const double a_max[3],
450 bool ON_MSC_CDECL resultCallback(void* a_context, ON__INT_PTR a_id), void* a_context ) const;
451
452 bool Search(const double a_min[3], const double a_max[3],
453 ON_RTreeSearchResult& a_result ) const;
454
455 bool Search(const double a_min[3], const double a_max[3],
456 ON_SimpleArray<ON_RTreeLeaf>& a_result ) const;
457
458 bool Search(const double a_min[3], const double a_max[3],
459 ON_SimpleArray<void*>& a_result ) const;
460
461 bool Search(const double a_min[3], const double a_max[3],
462 ON_SimpleArray<int>& a_result ) const;
463
464 bool Search2d(const double a_min[2], const double a_max[2],
465 bool ON_MSC_CDECL resultCallback(void* a_context, ON__INT_PTR a_id), void* a_context ) const;
466
467 bool Search2d(const double a_min[2], const double a_max[2],
468 ON_RTreeSearchResult& a_result ) const;
469
470 bool Search2d(const double a_min[2], const double a_max[2],
471 ON_SimpleArray<ON_RTreeLeaf>& a_result ) const;
472
473 bool Search2d(const double a_min[2], const double a_max[2],
474 ON_SimpleArray<void*>& a_result ) const;
475
476 bool Search2d(const double a_min[2], const double a_max[2],
477 ON_SimpleArray<int>& a_result ) const;
478
479 /*
480 Description:
481 Search two R-trees for all pairs elements whose bounding boxes overlap.
482 Parameters:
483 a_rtreeA - [in]
484 a_rtreeB - [in]
485 tolerance - [in]
486 If the distance between a pair of bounding boxes is <= tolerance,
487 then the pair is added to a_result[].
488 a_result - [out]
489 Pairs of ids of elements who bounding boxes overlap.
490 Returns:
491 True if entire tree was searched. It is possible no results were found.
492 */
493 static bool Search(
494 const ON_RTree& a_rtreeA,
495 const ON_RTree& a_rtreeB,
496 double tolerance,
498 );
499
500 /*
501 Description:
502 Search two R-trees for all pairs elements whose bounding boxes overlap.
503 Parameters:
504 a_rtreeA - [in]
505 a_rtreeB - [in]
506 tolerance - [in]
507 If the distance between a pair of bounding boxes is <= tolerance,
508 then resultCallback() is called.
509 resultCallback - [out]
510 callback function
511 a_context - [in] argument passed through to resultCallback().
512 Returns:
513 True if entire tree was searched. It is possible no results were found.
514 */
515 static bool Search(
516 const ON_RTree& a_rtreeA,
517 const ON_RTree& a_rtreeB,
518 double tolerance,
519 void ON_MSC_CDECL resultCallback(void* a_context, ON__INT_PTR a_idA, ON__INT_PTR a_idB),
520 void* a_context
521 );
522
523 /*
524 Returns:
525 Number of elements (leaves).
526 Remark:
527 No internal count is maintained, so this function traverses the
528 tree to count the leaves. If efficiency is important, save the
529 result.
530 */
531 int ElementCount();
532
533 /*
534 Returns:
535 Pointer to the root node.
536 */
537 const ON_RTreeNode* Root() const;
538
539 /*
540 Returns:
541 Number of bytes of heap memory used by this R-tree.
542 */
543 size_t SizeOf() const;
544
545private:
546 void SplitNode(ON_RTreeNode*, ON_RTreeBranch*, ON_RTreeNode**);
547 bool AddBranch(ON_RTreeBranch*, ON_RTreeNode*, ON_RTreeNode**);
548 bool InsertRectRec(ON_RTreeBBox*, ON__INT_PTR, ON_RTreeNode*, ON_RTreeNode**, int);
549 bool InsertRect(ON_RTreeBBox*, ON__INT_PTR, ON_RTreeNode**, int);
550 void LoadNodes(ON_RTreeNode*, ON_RTreeNode*, struct ON_RTreePartitionVars*);
551 bool RemoveRect(ON_RTreeBBox*, ON__INT_PTR, ON_RTreeNode**);
552 bool RemoveRectRec(ON_RTreeBBox*, ON__INT_PTR, ON_RTreeNode*, struct ON_RTreeListNode**);
553 void ReInsert(ON_RTreeNode*, struct ON_RTreeListNode**);
554 void RemoveAllRec(ON_RTreeNode*);
558};
559
560#endif
Definition opennurbs_mesh.h:795
Definition opennurbs_rtree.h:365
bool Search2d(const double a_min[2], const double a_max[2], bool ON_MSC_CDECL resultCallback(void *a_context, ON__INT_PTR a_id), void *a_context) const
bool Search(const double a_min[3], const double a_max[3], ON_RTreeSearchResult &a_result) const
bool Search(const double a_min[3], const double a_max[3], ON_SimpleArray< void * > &a_result) const
bool Search(const double a_min[3], const double a_max[3], bool ON_MSC_CDECL resultCallback(void *a_context, ON__INT_PTR a_id), void *a_context) const
bool Insert(const double a_min[3], const double a_max[3], int a_element_id)
ON_RTreeMemPool m_mem_pool
Definition opennurbs_rtree.h:557
bool Insert(const double a_min[3], const double a_max[3], void *a_element_id)
size_t m_reserved
Definition opennurbs_rtree.h:556
ON_RTreeNode * m_root
Definition opennurbs_rtree.h:555
bool Remove(const double a_min[3], const double a_max[3], void *a_elementId)
bool Search(const double a_min[3], const double a_max[3], ON_SimpleArray< ON_RTreeLeaf > &a_result) const
bool Search(const double a_min[3], const double a_max[3], ON_SimpleArray< int > &a_result) const
bool Remove(const double a_min[3], const double a_max[3], int a_elementId)
Definition opennurbs_rtree.h:193
bool Initialize(const struct ON_RTreeNode *a_node)
StackElement * m_sp
Definition opennurbs_rtree.h:359
bool Initialize(const class ON_RTree &a_rtree)
const ON_RTreeNode * m_root
Definition opennurbs_rtree.h:360
Definition opennurbs_rtree.h:136
size_t m_sizeof_heap
Definition opennurbs_rtree.h:182
ON_MEMORY_POOL * m_heap
Definition opennurbs_rtree.h:181
struct Blk * m_blk_list
Definition opennurbs_rtree.h:178
struct Blk * m_nodes
Definition opennurbs_rtree.h:170
size_t m_buffer_capacity
Definition opennurbs_rtree.h:176
size_t m_sizeof_blk
Definition opennurbs_rtree.h:179
unsigned char * m_buffer
Definition opennurbs_rtree.h:175
struct Blk * m_list_nodes
Definition opennurbs_rtree.h:172
Definition opennurbs_array.h:46
#define ON_CLASS
Definition opennurbs_defines.h:91
#define ON_RTree_MAX_NODE_COUNT
Definition opennurbs_rtree.h:57
int ON__INT_PTR
Definition opennurbs_system.h:377
#define ON_MSC_CDECL
Definition opennurbs_system.h:240
Definition opennurbs_rtree.h:84
double m_min[3]
Definition opennurbs_rtree.h:85
double m_max[3]
Definition opennurbs_rtree.h:86
Definition opennurbs_rtree.h:90
struct ON_RTreeNode * m_child
Definition opennurbs_rtree.h:97
ON_RTreeBBox m_rect
Definition opennurbs_rtree.h:91
ON__INT_PTR m_id
Definition opennurbs_rtree.h:98
Definition opennurbs_rtree.h:351
int m_branchIndex
Definition opennurbs_rtree.h:353
const struct ON_RTreeNode * m_node
Definition opennurbs_rtree.h:352
Definition opennurbs_rtree.h:103
ON__INT_PTR m_id
Definition opennurbs_rtree.h:105
ON_RTreeBBox m_rect
Definition opennurbs_rtree.h:104
A link list of nodes for reinsertion after a delete operation.
Definition opennurbs_rtree.cpp:23
Definition opennurbs_rtree.h:165
struct Blk * m_next
Definition opennurbs_rtree.h:166
Definition opennurbs_rtree.h:112
bool IsLeaf() const
Definition opennurbs_rtree.h:115
int m_level
Definition opennurbs_rtree.h:119
int m_count
Definition opennurbs_rtree.h:124
ON_RTreeBranch m_branch[ON_RTree_MAX_NODE_COUNT]
Definition opennurbs_rtree.h:125
bool IsInternalNode() const
Definition opennurbs_rtree.h:113
Variables for finding a split partition.
Definition opennurbs_rtree.cpp:30
Definition opennurbs_rtree.h:129
int m_capacity
Definition opennurbs_rtree.h:130
ON__INT_PTR * m_id
Definition opennurbs_rtree.h:132
int m_count
Definition opennurbs_rtree.h:131
Definition opennurbs_memory.h:207