1
3
4 #include "moab/AdaptiveKDTree.hpp"
5 #include "moab/Interface.hpp"
6 #include "moab/GeomUtil.hpp"
7 #include "moab/Range.hpp"
8 #include "moab/ElemEvaluator.hpp"
9 #include "moab/CpuTimer.hpp"
10 #include "Internals.hpp"
11 #include "moab/Util.hpp"
12 #include <cmath>
13
14 #include <cassert>
15 #include <algorithm>
16 #include <limits>
17 #include <iostream>
18 #include <cstdio>
19
20 namespace moab
21 {
22
23 const char* AdaptiveKDTree::treeName = "AKDTree";
24
25 #define MB_AD_KD_TREE_DEFAULT_TAG_NAME
26
27
28 #define MB_AD_KD_TREE_USE_SINGLE_TAG
29
30
31
32
33
34 #define MB_AD_KD_TREE_USE_TWO_DOUBLE_TAG
35
36 AdaptiveKDTree::AdaptiveKDTree( Interface* iface )
37 : Tree( iface ), planeTag( 0 ), axisTag( 0 ), splitsPerDir( 3 ), planeSet( SUBDIVISION_SNAP ), spherical( false ),
38 radius( 1.0 )
39 {
40 boxTagName = treeName;
41
42 ErrorCode rval = init();
43 if( MB_SUCCESS != rval ) throw rval;
44 }
45
46 AdaptiveKDTree::AdaptiveKDTree( Interface* iface,
47 const Range& entities,
48 EntityHandle* tree_root_set,
49 FileOptions* opts )
50 : Tree( iface ), planeTag( 0 ), axisTag( 0 ), splitsPerDir( 3 ), planeSet( SUBDIVISION_SNAP ), spherical( false ),
51 radius( 1.0 )
52 {
53 boxTagName = treeName;
54
55 ErrorCode rval;
56 if( opts )
57 {
58 rval = parse_options( *opts );
59 if( MB_SUCCESS != rval ) throw rval;
60 }
61
62 rval = init();
63 if( MB_SUCCESS != rval ) throw rval;
64
65 rval = build_tree( entities, tree_root_set, opts );
66 if( MB_SUCCESS != rval ) throw rval;
67 }
68
69 AdaptiveKDTree::~AdaptiveKDTree()
70 {
71 if( !cleanUp ) return;
72
73 if( myRoot )
74 {
75 reset_tree();
76 myRoot = 0;
77 }
78 }
79
80 ErrorCode AdaptiveKDTree::build_tree( const Range& entities, EntityHandle* tree_root_set, FileOptions* options )
81 {
82 ErrorCode rval;
83 CpuTimer cp;
84
85 if( options )
86 {
87 rval = parse_options( *options );
88 if( MB_SUCCESS != rval ) return rval;
89
90 if( !options->all_seen() ) return MB_FAILURE;
91 }
92
93
94 BoundBox box;
95 rval = box.update( *moab(), entities, spherical, radius );
96 if( MB_SUCCESS != rval ) return rval;
97
98
99 EntityHandle tmp_root;
100 if( !tree_root_set ) tree_root_set = &tmp_root;
101 rval = create_root( box.bMin.array(), box.bMax.array(), *tree_root_set );
102 if( MB_SUCCESS != rval ) return rval;
103 rval = moab()->add_entities( *tree_root_set, entities );
104 if( MB_SUCCESS != rval ) return rval;
105
106 AdaptiveKDTreeIter iter;
107 iter.initialize( this, *tree_root_set, box.bMin.array(), box.bMax.array(), AdaptiveKDTreeIter::LEFT );
108
109 std::vector< double > tmp_data;
110 std::vector< EntityHandle > tmp_data2;
111 for( ;; )
112 {
113
114 int pcount;
115 rval = moab()->get_number_entities_by_handle( iter.handle(), pcount );
116 if( MB_SUCCESS != rval ) break;
117
118 const size_t p_count = pcount;
119 Range best_left, best_right, best_both;
120 Plane best_plane = { HUGE_VAL, -1 };
121 if( (int)p_count > maxPerLeaf && (int)iter.depth() < maxDepth )
122 {
123 switch( planeSet )
124 {
125 case AdaptiveKDTree::SUBDIVISION:
126 rval = best_subdivision_plane( splitsPerDir, iter, best_left, best_right, best_both, best_plane,
127 minWidth );
128 break;
129 case AdaptiveKDTree::SUBDIVISION_SNAP:
130 rval = best_subdivision_snap_plane( splitsPerDir, iter, best_left, best_right, best_both,
131 best_plane, tmp_data, minWidth );
132 break;
133 case AdaptiveKDTree::VERTEX_MEDIAN:
134 rval = best_vertex_median_plane( splitsPerDir, iter, best_left, best_right, best_both, best_plane,
135 tmp_data, minWidth );
136 break;
137 case AdaptiveKDTree::VERTEX_SAMPLE:
138 rval = best_vertex_sample_plane( splitsPerDir, iter, best_left, best_right, best_both, best_plane,
139 tmp_data, tmp_data2, minWidth );
140 break;
141 default:
142 rval = MB_FAILURE;
143 }
144
145 if( MB_SUCCESS != rval ) return rval;
146 }
147
148 if( best_plane.norm >= 0 )
149 {
150 best_left.merge( best_both );
151 best_right.merge( best_both );
152 rval = split_leaf( iter, best_plane, best_left, best_right );
153 if( MB_SUCCESS != rval ) return rval;
154 }
155 else
156 {
157 rval = iter.step();
158 if( MB_ENTITY_NOT_FOUND == rval )
159 {
160 rval = treeStats.compute_stats( mbImpl, myRoot );
161 treeStats.initTime = cp.time_elapsed();
162 return rval;
163 }
164 else if( MB_SUCCESS != rval )
165 break;
166 }
167 }
168
169 reset_tree();
170
171 treeStats.reset();
172
173 return rval;
174 }
175
176 ErrorCode AdaptiveKDTree::parse_options( FileOptions& opts )
177 {
178 ErrorCode rval = parse_common_options( opts );
179 if( MB_SUCCESS != rval ) return rval;
180
181
182 int tmp_int;
183 rval = opts.get_int_option( "SPLITS_PER_DIR", tmp_int );
184 if( MB_SUCCESS == rval ) splitsPerDir = tmp_int;
185
186
187
188 rval = opts.get_int_option( "PLANE_SET", tmp_int );
189 if( MB_SUCCESS == rval && ( tmp_int < SUBDIVISION || tmp_int > VERTEX_SAMPLE ) )
190 return MB_FAILURE;
191 else if( MB_ENTITY_NOT_FOUND == rval )
192 planeSet = SUBDIVISION;
193 else
194 planeSet = (CandidatePlaneSet)( tmp_int );
195
196 rval = opts.get_toggle_option( "SPHERICAL", false, spherical );
197 if( MB_SUCCESS != rval ) spherical = false;
198
199 double tmp = 1.0;
200 rval = opts.get_real_option( "RADIUS", tmp );
201 if( MB_SUCCESS != rval )
202 radius = 1.0;
203 else
204 radius = tmp;
205
206 return MB_SUCCESS;
207 }
208
209 ErrorCode AdaptiveKDTree::make_tag( Interface* iface,
210 std::string name,
211 TagType storage,
212 DataType type,
213 int count,
214 void* default_val,
215 Tag& tag_handle,
216 std::vector< Tag >& created_tags )
217 {
218 ErrorCode rval =
219 iface->tag_get_handle( name.c_str(), count, type, tag_handle, MB_TAG_CREAT | storage, default_val );
220
221 if( MB_SUCCESS == rval )
222 {
223 if( std::find( created_tags.begin(), created_tags.end(), tag_handle ) == created_tags.end() )
224 created_tags.push_back( tag_handle );
225 }
226 else
227 {
228 while( !created_tags.empty() )
229 {
230 iface->tag_delete( created_tags.back() );
231 created_tags.pop_back();
232 }
233
234 planeTag = axisTag = (Tag)-1;
235 }
236
237 return rval;
238 }
239
240 ErrorCode AdaptiveKDTree::init()
241 {
242 std::vector< Tag > ctl;
243
244 #ifndef MB_AD_KD_TREE_USE_SINGLE_TAG
245
246 std::string n1( treeName ), n2( treeName );
247 n1 += "_coord";
248 n2 += "_norm";
249 ErrorCode rval = make_tag( moab(), n1, MB_TAG_DENSE, MB_TYPE_DOUBLE, 1, 0, planeTag, ctl );
250 if( MB_SUCCESS != rval ) return rval;
251 rval = make_tag( moab(), n2, MB_TAG_DENSE, MB_TYPE_INT, 1, 0, axisTag, ctl );
252 if( MB_SUCCESS != rval ) return rval;
253
254 #elif defined( MB_AD_KD_TREE_USE_TWO_DOUBLE_TAG )
255
256 std::string double_tag_name = std::string( treeName ) + std::string( "_coord_norm" );
257 ErrorCode rval = make_tag( moab(), double_tag_name, MB_TAG_DENSE, MB_TYPE_DOUBLE, 2, 0, planeTag, ctl );
258 if( MB_SUCCESS != rval ) return rval;
259 #else
260
261 ErrorCode rval = make_tag( moab(), tagname, MB_TAG_DENSE, MB_TYPE_OPAQUE, sizeof( Plane ), 0, planeTag, ctl );
262 if( MB_SUCCESS != rval ) return rval;
263
264 #ifdef MOAB_HAVE_HDF5
265
266 Tag type_tag;
267 std::string type_tag_name = "__hdf5_tag_type_";
268 type_tag_name += boxTagName;
269 rval = make_tag( moab(), type_tag_name, MB_TAG_MESH, MB_TYPE_OPAQUE, sizeof( hid_t ), 0, type_tag, ctl );
270 if( MB_SUCCESS != rval ) return rval;
271
272 Plane p;
273 hid_t handle = H5Tcreate( H5T_COMPOUND, sizeof( Plane ) );
274 H5Tinsert( handle, "coord", &( p.coord ) - &p, H5T_NATIVE_DOUBLE );
275 H5Tinsert( handle, "norm", &( p.axis ) - &p, H5T_NATIVE_INT );
276 EntityHandle root = 0;
277 rval = mbImpl->tag_set_data( type_tag, &root, 1, &handle );
278 if( MB_SUCCESS != rval ) return rval;
279 #endif
280 #endif
281
282 return rval;
283 }
284
285 ErrorCode AdaptiveKDTree::get_split_plane( EntityHandle entity, Plane& plane )
286 {
287 #ifndef MB_AD_KD_TREE_USE_SINGLE_TAG
288 ErrorCode r1, r2;
289 r1 = moab()->tag_get_data( planeTag, &entity, 1, &plane.coord );
290 r2 = moab()->tag_get_data( axisTag, &entity, 1, &plane.norm );
291 return MB_SUCCESS == r1 ? r2 : r1;
292 #elif defined( MB_AD_KD_TREE_USE_TWO_DOUBLE_TAG )
293 double values[2];
294 ErrorCode rval = moab()->tag_get_data( planeTag, &entity, 1, values );
295 plane.coord = values[0];
296 plane.norm = (int)values[1];
297 return rval;
298 #else
299 return moab()->tag_get_data( planeTag, &entity, 1, &plane );
300 #endif
301 }
302
303 ErrorCode AdaptiveKDTree::set_split_plane( EntityHandle entity, const Plane& plane )
304 {
305 #ifndef MB_AD_KD_TREE_USE_SINGLE_TAG
306 ErrorCode r1, r2;
307 r1 = moab()->tag_set_data( planeTag, &entity, 1, &plane.coord );
308 r2 = moab()->tag_set_data( axisTag, &entity, 1, &plane.norm );
309 return MB_SUCCESS == r1 ? r2 : r1;
310 #elif defined( MB_AD_KD_TREE_USE_TWO_DOUBLE_TAG )
311 double values[2] = { plane.coord, static_cast< double >( plane.norm ) };
312 return moab()->tag_set_data( planeTag, &entity, 1, values );
313 #else
314 return moab()->tag_set_data( planeTag, &entity, 1, &plane );
315 #endif
316 }
317
318 ErrorCode AdaptiveKDTree::get_tree_iterator( EntityHandle root, AdaptiveKDTreeIter& iter )
319 {
320 double box[6];
321 ErrorCode rval = moab()->tag_get_data( boxTag, &root, 1, box );
322 if( MB_SUCCESS != rval ) return rval;
323
324 return get_sub_tree_iterator( root, box, box + 3, iter );
325 }
326
327 ErrorCode AdaptiveKDTree::get_last_iterator( EntityHandle root, AdaptiveKDTreeIter& iter )
328 {
329 double box[6];
330 ErrorCode rval = moab()->tag_get_data( boxTag, &root, 1, box );
331 if( MB_SUCCESS != rval ) return rval;
332
333 return iter.initialize( this, root, box, box + 3, AdaptiveKDTreeIter::RIGHT );
334 }
335
336 ErrorCode AdaptiveKDTree::get_sub_tree_iterator( EntityHandle root,
337 const double min[3],
338 const double max[3],
339 AdaptiveKDTreeIter& result )
340 {
341 return result.initialize( this, root, min, max, AdaptiveKDTreeIter::LEFT );
342 }
343
344 ErrorCode AdaptiveKDTree::split_leaf( AdaptiveKDTreeIter& leaf, Plane plane, EntityHandle& left, EntityHandle& right )
345 {
346 ErrorCode rval;
347
348 rval = moab()->create_meshset( meshsetFlags, left );
349 if( MB_SUCCESS != rval ) return rval;
350
351 rval = moab()->create_meshset( meshsetFlags, right );
352 if( MB_SUCCESS != rval )
353 {
354 moab()->delete_entities( &left, 1 );
355 return rval;
356 }
357
358 if( MB_SUCCESS != set_split_plane( leaf.handle(), plane ) ||
359 MB_SUCCESS != moab()->add_child_meshset( leaf.handle(), left ) ||
360 MB_SUCCESS != moab()->add_child_meshset( leaf.handle(), right ) ||
361 MB_SUCCESS != leaf.step_to_first_leaf( AdaptiveKDTreeIter::LEFT ) )
362 {
363 EntityHandle children[] = { left, right };
364 moab()->delete_entities( children, 2 );
365 return MB_FAILURE;
366 }
367
368 return MB_SUCCESS;
369 }
370
371 ErrorCode AdaptiveKDTree::split_leaf( AdaptiveKDTreeIter& leaf, Plane plane )
372 {
373 EntityHandle left, right;
374 return split_leaf( leaf, plane, left, right );
375 }
376
377 ErrorCode AdaptiveKDTree::split_leaf( AdaptiveKDTreeIter& leaf,
378 Plane plane,
379 const Range& left_entities,
380 const Range& right_entities )
381 {
382 EntityHandle left, right, parent = leaf.handle();
383 ErrorCode rval = split_leaf( leaf, plane, left, right );
384 if( MB_SUCCESS != rval ) return rval;
385
386 if( MB_SUCCESS == moab()->add_entities( left, left_entities ) &&
387 MB_SUCCESS == moab()->add_entities( right, right_entities ) &&
388 MB_SUCCESS == moab()->clear_meshset( &parent, 1 ) )
389 return MB_SUCCESS;
390
391 moab()->remove_child_meshset( parent, left );
392 moab()->remove_child_meshset( parent, right );
393 EntityHandle children[] = { left, right };
394 moab()->delete_entities( children, 2 );
395 return MB_FAILURE;
396 }
397
398 ErrorCode AdaptiveKDTree::split_leaf( AdaptiveKDTreeIter& leaf,
399 Plane plane,
400 const std::vector< EntityHandle >& left_entities,
401 const std::vector< EntityHandle >& right_entities )
402 {
403 EntityHandle left, right, parent = leaf.handle();
404 ErrorCode rval = split_leaf( leaf, plane, left, right );
405 if( MB_SUCCESS != rval ) return rval;
406
407 if( MB_SUCCESS == moab()->add_entities( left, &left_entities[0], left_entities.size() ) &&
408 MB_SUCCESS == moab()->add_entities( right, &right_entities[0], right_entities.size() ) &&
409 MB_SUCCESS == moab()->clear_meshset( &parent, 1 ) )
410 return MB_SUCCESS;
411
412 moab()->remove_child_meshset( parent, left );
413 moab()->remove_child_meshset( parent, right );
414 EntityHandle children[] = { left, right };
415 moab()->delete_entities( children, 2 );
416 return MB_FAILURE;
417 }
418
419 ErrorCode AdaptiveKDTree::merge_leaf( AdaptiveKDTreeIter& iter )
420 {
421 ErrorCode rval;
422 if( iter.depth() == 1 )
423 return MB_FAILURE;
424
425
426
427 AdaptiveKDTreeIter::StackObj node = iter.mStack.back();
428 iter.mStack.pop_back();
429
430 iter.childVect.clear();
431 rval = moab()->get_child_meshsets( iter.mStack.back().entity, iter.childVect );
432 if( MB_SUCCESS != rval ) return rval;
433 Plane plane;
434 rval = get_split_plane( iter.mStack.back().entity, plane );
435 if( MB_SUCCESS != rval ) return rval;
436
437 int child_idx = iter.childVect[0] == node.entity ? 0 : 1;
438 assert( iter.childVect[child_idx] == node.entity );
439 iter.mBox[1 - child_idx][plane.norm] = node.coord;
440
441
442 EntityHandle parent = iter.handle();
443 moab()->remove_child_meshset( parent, iter.childVect[0] );
444 moab()->remove_child_meshset( parent, iter.childVect[1] );
445 std::vector< EntityHandle > stack( iter.childVect );
446
447 Range range;
448 while( !stack.empty() )
449 {
450 EntityHandle h = stack.back();
451 stack.pop_back();
452 range.clear();
453 rval = moab()->get_entities_by_handle( h, range );
454 if( MB_SUCCESS != rval ) return rval;
455 rval = moab()->add_entities( parent, range );
456 if( MB_SUCCESS != rval ) return rval;
457
458 iter.childVect.clear();
459 rval = moab()->get_child_meshsets( h, iter.childVect );MB_CHK_ERR( rval );
460 if( !iter.childVect.empty() )
461 {
462 moab()->remove_child_meshset( h, iter.childVect[0] );
463 moab()->remove_child_meshset( h, iter.childVect[1] );
464 stack.push_back( iter.childVect[0] );
465 stack.push_back( iter.childVect[1] );
466 }
467
468 rval = moab()->delete_entities( &h, 1 );
469 if( MB_SUCCESS != rval ) return rval;
470 }
471
472 return MB_SUCCESS;
473 }
474
475 ErrorCode AdaptiveKDTreeIter::initialize( AdaptiveKDTree* ttool,
476 EntityHandle root,
477 const double bmin[3],
478 const double bmax[3],
479 Direction direction )
480 {
481 mStack.clear();
482 treeTool = ttool;
483 mBox[BMIN][0] = bmin[0];
484 mBox[BMIN][1] = bmin[1];
485 mBox[BMIN][2] = bmin[2];
486 mBox[BMAX][0] = bmax[0];
487 mBox[BMAX][1] = bmax[1];
488 mBox[BMAX][2] = bmax[2];
489 mStack.push_back( StackObj( root, 0 ) );
490 return step_to_first_leaf( direction );
491 }
492
493 ErrorCode AdaptiveKDTreeIter::step_to_first_leaf( Direction direction )
494 {
495 ErrorCode rval;
496 AdaptiveKDTree::Plane plane;
497 const Direction opposite = static_cast< Direction >( 1 - direction );
498
499 for( ;; )
500 {
501 childVect.clear();
502 treeTool->treeStats.nodesVisited++;
503 rval = treeTool->moab()->get_child_meshsets( mStack.back().entity, childVect );
504 if( MB_SUCCESS != rval ) return rval;
505 if( childVect.empty() )
506 {
507 treeTool->treeStats.leavesVisited++;
508 break;
509 }
510
511 rval = treeTool->get_split_plane( mStack.back().entity, plane );
512 if( MB_SUCCESS != rval ) return rval;
513
514 mStack.push_back( StackObj( childVect[direction], mBox[opposite][plane.norm] ) );
515 mBox[opposite][plane.norm] = plane.coord;
516 }
517 return MB_SUCCESS;
518 }
519
520 ErrorCode AdaptiveKDTreeIter::step( Direction direction )
521 {
522 StackObj node, parent;
523 ErrorCode rval;
524 AdaptiveKDTree::Plane plane;
525 const Direction opposite = static_cast< Direction >( 1 - direction );
526
527
528
529
530 if( mStack.empty() ) return MB_FAILURE;
531
532
533
534
535 node = mStack.back();
536 mStack.pop_back();
537 treeTool->treeStats.nodesVisited++;
538 if( mStack.empty() ) treeTool->treeStats.leavesVisited++;
539
540 while( !mStack.empty() )
541 {
542
543 parent = mStack.back();
544 childVect.clear();
545 rval = treeTool->moab()->get_child_meshsets( parent.entity, childVect );
546 if( MB_SUCCESS != rval ) return rval;
547 rval = treeTool->get_split_plane( parent.entity, plane );
548 if( MB_SUCCESS != rval ) return rval;
549
550
551 if( childVect[opposite] == node.entity )
552 {
553
554 mBox[direction][plane.norm] = node.coord;
555
556 node.entity = childVect[direction];
557 treeTool->treeStats.nodesVisited++;
558 node.coord = mBox[opposite][plane.norm];
559 mStack.push_back( node );
560
561 mBox[opposite][plane.norm] = plane.coord;
562
563 return step_to_first_leaf( opposite );
564 }
565
566
567
568 assert( childVect[direction] == node.entity );
569 mBox[opposite][plane.norm] = node.coord;
570 node = parent;
571 treeTool->treeStats.nodesVisited++;
572 mStack.pop_back();
573 }
574
575 return MB_ENTITY_NOT_FOUND;
576 }
577
578 ErrorCode AdaptiveKDTreeIter::get_neighbors( AdaptiveKDTree::Axis norm,
579 bool neg,
580 std::vector< AdaptiveKDTreeIter >& results,
581 double epsilon ) const
582 {
583 StackObj node, parent;
584 ErrorCode rval;
585 AdaptiveKDTree::Plane plane;
586 int child_idx;
587
588
589
590 AdaptiveKDTreeIter iter( *this );
591 node = iter.mStack.back();
592 iter.mStack.pop_back();
593 for( ;; )
594 {
595
596 if( iter.mStack.empty() ) return MB_SUCCESS;
597
598
599 parent = iter.mStack.back();
600 iter.childVect.clear();
601 rval = treeTool->moab()->get_child_meshsets( parent.entity, iter.childVect );
602 if( MB_SUCCESS != rval ) return rval;
603 rval = treeTool->get_split_plane( parent.entity, plane );
604 if( MB_SUCCESS != rval ) return rval;
605
606 child_idx = iter.childVect[0] == node.entity ? 0 : 1;
607 assert( iter.childVect[child_idx] == node.entity );
608
609
610
611 if( plane.norm == norm && (int)neg == child_idx )
612 {
613
614 iter.mBox[1 - child_idx][plane.norm] = node.coord;
615
616 node.entity = iter.childVect[1 - child_idx];
617 node.coord = iter.mBox[child_idx][plane.norm];
618 iter.mStack.push_back( node );
619
620 iter.mBox[child_idx][plane.norm] = plane.coord;
621 break;
622 }
623
624
625 iter.mBox[1 - child_idx][plane.norm] = node.coord;
626 node = parent;
627 iter.mStack.pop_back();
628 }
629
630
631 std::vector< AdaptiveKDTreeIter > list;
632
633 for( ;; )
634 {
635
636
637 node = iter.mStack.back();
638 for( ;; )
639 {
640 iter.childVect.clear();
641 rval = treeTool->moab()->get_child_meshsets( node.entity, iter.childVect );
642 if( MB_SUCCESS != rval ) return rval;
643
644
645 if( iter.childVect.empty() )
646 {
647 results.push_back( iter );
648 break;
649 }
650
651 rval = treeTool->get_split_plane( node.entity, plane );
652 if( MB_SUCCESS != rval ) return rval;
653
654
655 if( plane.norm == norm )
656 {
657
658 node.entity = iter.childVect[neg];
659 node.coord = iter.mBox[1 - neg][plane.norm];
660 iter.mStack.push_back( node );
661 iter.mBox[1 - neg][plane.norm] = plane.coord;
662 }
663
664 else if( this->mBox[BMIN][plane.norm] - plane.coord <= epsilon )
665 {
666
667 if( plane.coord - this->mBox[BMAX][plane.norm] <= epsilon )
668 {
669 list.push_back( iter );
670 list.back().mStack.push_back( StackObj( iter.childVect[1], iter.mBox[BMIN][plane.norm] ) );
671 list.back().mBox[BMIN][plane.norm] = plane.coord;
672 }
673
674 node.entity = iter.childVect[0];
675 node.coord = iter.mBox[BMAX][plane.norm];
676 iter.mStack.push_back( node );
677 iter.mBox[BMAX][plane.norm] = plane.coord;
678 }
679
680 else
681 {
682
683
684 assert( plane.coord - this->mBox[BMAX][plane.norm] <= epsilon );
685
686 node.entity = iter.childVect[1];
687 node.coord = iter.mBox[BMIN][plane.norm];
688 iter.mStack.push_back( node );
689 iter.mBox[BMIN][plane.norm] = plane.coord;
690 }
691 }
692
693 if( list.empty() ) break;
694
695 iter = list.back();
696 list.pop_back();
697 }
698
699 return MB_SUCCESS;
700 }
701
702 ErrorCode AdaptiveKDTreeIter::sibling_side( AdaptiveKDTree::Axis& axis_out, bool& neg_out ) const
703 {
704 if( mStack.size() < 2 )
705 return MB_ENTITY_NOT_FOUND;
706
707 EntityHandle parent = mStack[mStack.size() - 2].entity;
708 AdaptiveKDTree::Plane plane;
709 ErrorCode rval = tool()->get_split_plane( parent, plane );
710 if( MB_SUCCESS != rval ) return MB_FAILURE;
711
712 childVect.clear();
713 rval = tool()->moab()->get_child_meshsets( parent, childVect );
714 if( MB_SUCCESS != rval || childVect.size() != 2 ) return MB_FAILURE;
715
716 axis_out = static_cast< AdaptiveKDTree::Axis >( plane.norm );
717 neg_out = ( childVect[1] == handle() );
718 assert( childVect[neg_out] == handle() );
719 return MB_SUCCESS;
720 }
721
722 ErrorCode AdaptiveKDTreeIter::get_parent_split_plane( AdaptiveKDTree::Plane& plane ) const
723 {
724 if( mStack.size() < 2 )
725 return MB_ENTITY_NOT_FOUND;
726
727 EntityHandle parent = mStack[mStack.size() - 2].entity;
728 return tool()->get_split_plane( parent, plane );
729 }
730
731 bool AdaptiveKDTreeIter::is_sibling( const AdaptiveKDTreeIter& other_leaf ) const
732 {
733 const size_t s = mStack.size();
734 return ( s > 1 ) && ( s == other_leaf.mStack.size() ) &&
735 ( other_leaf.mStack[s - 2].entity == mStack[s - 2].entity ) && other_leaf.handle() != handle();
736 }
737
738 bool AdaptiveKDTreeIter::is_sibling( EntityHandle other_leaf ) const
739 {
740 if( mStack.size() < 2 || other_leaf == handle() ) return false;
741 EntityHandle parent = mStack[mStack.size() - 2].entity;
742 childVect.clear();
743 ErrorCode rval = tool()->moab()->get_child_meshsets( parent, childVect );
744 if( MB_SUCCESS != rval || childVect.size() != 2 )
745 {
746 assert( false );
747 return false;
748 }
749 return childVect[0] == other_leaf || childVect[1] == other_leaf;
750 }
751
752 bool AdaptiveKDTreeIter::sibling_is_forward() const
753 {
754 if( mStack.size() < 2 )
755 return false;
756 EntityHandle parent = mStack[mStack.size() - 2].entity;
757 childVect.clear();
758 ErrorCode rval = tool()->moab()->get_child_meshsets( parent, childVect );
759 if( MB_SUCCESS != rval || childVect.size() != 2 )
760 {
761 assert( false );
762 return false;
763 }
764 return childVect[0] == handle();
765 }
766
767 bool AdaptiveKDTreeIter::intersect_ray( const double ray_point[3],
768 const double ray_vect[3],
769 double& t_enter,
770 double& t_exit ) const
771 {
772 treeTool->treeStats.traversalLeafObjectTests++;
773 return GeomUtil::ray_box_intersect( CartVect( box_min() ), CartVect( box_max() ), CartVect( ray_point ),
774 CartVect( ray_vect ), t_enter, t_exit );
775 }
776
777 ErrorCode AdaptiveKDTree::intersect_children_with_elems( const Range& elems,
778 AdaptiveKDTree::Plane plane,
779 double eps,
780 CartVect box_min,
781 CartVect box_max,
782 Range& left_tris,
783 Range& right_tris,
784 Range& both_tris,
785 double& metric_value )
786 {
787 left_tris.clear();
788 right_tris.clear();
789 both_tris.clear();
790 CartVect coords[16];
791
792
793 BoundBox left_box( box_min, box_max ), right_box( box_min, box_max );
794 right_box.bMin = box_min;
795 left_box.bMax = box_max;
796 right_box.bMin[plane.norm] = left_box.bMax[plane.norm] = plane.coord;
797 const CartVect left_cen = 0.5 * ( left_box.bMax + box_min );
798 const CartVect left_dim = 0.5 * ( left_box.bMax - box_min );
799 const CartVect right_cen = 0.5 * ( box_max + right_box.bMin );
800 const CartVect right_dim = 0.5 * ( box_max - right_box.bMin );
801 const CartVect dim = box_max - box_min;
802 const double max_tol = std::max( dim[0], std::max( dim[1], dim[2] ) ) / 10;
803
804
805 ErrorCode rval;
806 int count, count2;
807 const EntityHandle *conn, *conn2;
808
809 const Range::const_iterator elem_begin = elems.lower_bound( MBEDGE );
810 const Range::const_iterator poly_begin = elems.lower_bound( MBPOLYHEDRON, elem_begin );
811 const Range::const_iterator set_begin = elems.lower_bound( MBENTITYSET, poly_begin );
812 Range::iterator left_ins = left_tris.begin();
813 Range::iterator right_ins = right_tris.begin();
814 Range::iterator both_ins = both_tris.begin();
815 Range::const_iterator i;
816
817
818 for( i = elems.begin(); i != elem_begin; ++i )
819 {
820 tree_stats().constructLeafObjectTests++;
821 rval = moab()->get_coords( &*i, 1, coords[0].array() );
822 if( MB_SUCCESS != rval ) return rval;
823
824 bool lo = false, ro = false;
825 if( coords[0][plane.norm] <= plane.coord ) lo = true;
826 if( coords[0][plane.norm] >= plane.coord ) ro = true;
827
828 if( lo && ro )
829 both_ins = both_tris.insert( both_ins, *i, *i );
830 else if( lo )
831 left_ins = left_tris.insert( left_ins, *i, *i );
832 else
833 right_ins = right_tris.insert( right_ins, *i, *i );
834 }
835
836
837 std::vector< EntityHandle > dum_vector;
838 for( i = elem_begin; i != poly_begin; ++i )
839 {
840 tree_stats().constructLeafObjectTests++;
841 rval = moab()->get_connectivity( *i, conn, count, true, &dum_vector );
842 if( MB_SUCCESS != rval ) return rval;
843 if( count > (int)( sizeof( coords ) / sizeof( coords[0] ) ) ) return MB_FAILURE;
844 rval = moab()->get_coords( &conn[0], count, coords[0].array() );
845 if( MB_SUCCESS != rval ) return rval;
846
847 bool lo = false, ro = false;
848 for( int j = 0; j < count; ++j )
849 {
850 if( coords[j][plane.norm] <= plane.coord ) lo = true;
851 if( coords[j][plane.norm] >= plane.coord ) ro = true;
852 }
853
854
855
856
857
858
859
860 if( lo && ro )
861 {
862 double tol = eps;
863 lo = ro = false;
864 while( !lo && !ro && tol <= max_tol )
865 {
866 tree_stats().boxElemTests += 2;
867 lo = GeomUtil::box_elem_overlap( coords, TYPE_FROM_HANDLE( *i ), left_cen, left_dim + CartVect( tol ),
868 count );
869 ro = GeomUtil::box_elem_overlap( coords, TYPE_FROM_HANDLE( *i ), right_cen, right_dim + CartVect( tol ),
870 count );
871
872 tol *= 10.0;
873 }
874 }
875 if( lo && ro )
876 both_ins = both_tris.insert( both_ins, *i, *i );
877 else if( lo )
878 left_ins = left_tris.insert( left_ins, *i, *i );
879 else if( ro )
880 right_ins = right_tris.insert( right_ins, *i, *i );
881 }
882
883
884 for( i = poly_begin; i != set_begin; ++i )
885 {
886 tree_stats().constructLeafObjectTests++;
887 rval = moab()->get_connectivity( *i, conn, count, true );
888 if( MB_SUCCESS != rval ) return rval;
889
890
891 bool lo = false, ro = false;
892 for( int j = 0; j < count; ++j )
893 {
894 rval = moab()->get_connectivity( conn[j], conn2, count2, true );
895 if( MB_SUCCESS != rval ) return rval;
896
897 for( int k = 0; k < count2; ++k )
898 {
899 rval = moab()->get_coords( conn2 + k, 1, coords[0].array() );
900 if( MB_SUCCESS != rval ) return rval;
901 if( coords[0][plane.norm] <= plane.coord ) lo = true;
902 if( coords[0][plane.norm] >= plane.coord ) ro = true;
903 }
904 }
905
906 if( lo && ro )
907 both_ins = both_tris.insert( both_ins, *i, *i );
908 else if( lo )
909 left_ins = left_tris.insert( left_ins, *i, *i );
910 else if( ro )
911 right_ins = right_tris.insert( right_ins, *i, *i );
912 }
913
914
915 BoundBox tbox;
916 for( i = set_begin; i != elems.end(); ++i )
917 {
918 tree_stats().constructLeafObjectTests++;
919 rval = tbox.update( *moab(), *i, spherical, radius );
920 if( MB_SUCCESS != rval ) return rval;
921
922 bool lo = false, ro = false;
923 if( tbox.bMin[plane.norm] <= plane.coord ) lo = true;
924 if( tbox.bMax[plane.norm] >= plane.coord ) ro = true;
925
926 if( lo && ro )
927 both_ins = both_tris.insert( both_ins, *i, *i );
928 else if( lo )
929 left_ins = left_tris.insert( left_ins, *i, *i );
930 else
931 right_ins = right_tris.insert( right_ins, *i, *i );
932 }
933
934 CartVect box_dim = box_max - box_min;
935 double area_left = left_dim[0] * left_dim[1] + left_dim[1] * left_dim[2] + left_dim[2] * left_dim[0];
936 double area_right = right_dim[0] * right_dim[1] + right_dim[1] * right_dim[2] + right_dim[2] * right_dim[0];
937 double area_both = box_dim[0] * box_dim[1] + box_dim[1] * box_dim[2] + box_dim[2] * box_dim[0];
938 metric_value = ( area_left * left_tris.size() + area_right * right_tris.size() ) / area_both + both_tris.size();
939 return MB_SUCCESS;
940 }
941
942 ErrorCode AdaptiveKDTree::best_subdivision_plane( int num_planes,
943 const AdaptiveKDTreeIter& iter,
944 Range& best_left,
945 Range& best_right,
946 Range& best_both,
947 AdaptiveKDTree::Plane& best_plane,
948 double eps )
949 {
950 double metric_val = std::numeric_limits< unsigned >::max();
951
952 ErrorCode r;
953 const CartVect box_min( iter.box_min() );
954 const CartVect box_max( iter.box_max() );
955 const CartVect diff( box_max - box_min );
956
957 Range entities;
958 r = iter.tool()->moab()->get_entities_by_handle( iter.handle(), entities );
959 if( MB_SUCCESS != r ) return r;
960 const size_t p_count = entities.size();
961
962 for( int axis = 0; axis < 3; ++axis )
963 {
964 int plane_count = num_planes;
965 if( ( num_planes + 1 ) * eps >= diff[axis] ) plane_count = (int)( diff[axis] / eps ) - 1;
966
967 for( int p = 1; p <= plane_count; ++p )
968 {
969 AdaptiveKDTree::Plane plane = { box_min[axis] + ( p / ( 1.0 + plane_count ) ) * diff[axis], axis };
970 Range left, right, both;
971 double val;
972 r = intersect_children_with_elems( entities, plane, eps, box_min, box_max, left, right, both, val );
973 if( MB_SUCCESS != r ) return r;
974 const size_t sdiff = p_count - both.size();
975 if( left.size() == sdiff || right.size() == sdiff ) continue;
976
977 if( val >= metric_val ) continue;
978
979 metric_val = val;
980 best_plane = plane;
981 best_left.swap( left );
982 best_right.swap( right );
983 best_both.swap( both );
984 }
985 }
986
987 return MB_SUCCESS;
988 }
989
990 ErrorCode AdaptiveKDTree::best_subdivision_snap_plane( int num_planes,
991 const AdaptiveKDTreeIter& iter,
992 Range& best_left,
993 Range& best_right,
994 Range& best_both,
995 AdaptiveKDTree::Plane& best_plane,
996 std::vector< double >& tmp_data,
997 double eps )
998 {
999 double metric_val = std::numeric_limits< unsigned >::max();
1000
1001 ErrorCode r;
1002
1003
1004 Range entities, vertices;
1005 r = iter.tool()->moab()->get_entities_by_handle( iter.handle(), entities );
1006 if( MB_SUCCESS != r ) return r;
1007 const size_t p_count = entities.size();
1008 r = iter.tool()->moab()->get_adjacencies( entities, 0, false, vertices, Interface::UNION );
1009 if( MB_SUCCESS != r ) return r;
1010
1011 unsigned int nverts = vertices.size();
1012 tmp_data.resize( 3 * nverts );
1013 r = iter.tool()->moab()->get_coords( vertices, &tmp_data[0], &tmp_data[nverts], &tmp_data[2 * nverts] );
1014 if( MB_SUCCESS != r ) return r;
1015
1016
1017
1018
1019
1020
1021
1022 CartVect box_min;
1023 CartVect box_max;
1024 for( int dir = 0; dir < 3; dir++ )
1025 {
1026 double amin = tmp_data[dir * nverts];
1027 double amax = amin;
1028 double* p = &tmp_data[dir * nverts + 1];
1029 for( unsigned int i = 1; i < nverts; i++ )
1030 {
1031 if( *p < amin ) amin = *p;
1032 if( *p > amax ) amax = *p;
1033 p++;
1034 }
1035 box_min[dir] = amin;
1036 box_max[dir] = amax;
1037 }
1038 CartVect diff( box_max - box_min );
1039
1040 for( int axis = 0; axis < 3; ++axis )
1041 {
1042 int plane_count = num_planes;
1043
1044
1045 if( ( num_planes + 1 ) * eps >= diff[axis] ) plane_count = (int)( diff[axis] / eps ) - 1;
1046
1047 for( int p = 1; p <= plane_count; ++p )
1048 {
1049
1050
1051 double coord = box_min[axis] + ( p / ( 1.0 + plane_count ) ) * diff[axis];
1052
1053
1054 unsigned int istrt = axis * nverts;
1055 double closest_coord = tmp_data[istrt];
1056 for( unsigned i = 1; i < nverts; ++i )
1057 if( fabs( coord - tmp_data[istrt + i] ) < fabs( coord - closest_coord ) )
1058 closest_coord = tmp_data[istrt + i];
1059 if( closest_coord - box_min[axis] <= eps || box_max[axis] - closest_coord <= eps ) continue;
1060
1061
1062 AdaptiveKDTree::Plane plane = { closest_coord, axis };
1063 Range left, right, both;
1064 double val;
1065 r = intersect_children_with_elems( entities, plane, eps, box_min, box_max, left, right, both, val );
1066 if( MB_SUCCESS != r ) return r;
1067 const size_t d = p_count - both.size();
1068 if( left.size() == d || right.size() == d ) continue;
1069
1070 if( val >= metric_val ) continue;
1071
1072 metric_val = val;
1073 best_plane = plane;
1074 best_left.swap( left );
1075 best_right.swap( right );
1076 best_both.swap( both );
1077 }
1078 }
1079
1080 return MB_SUCCESS;
1081 }
1082
1083 ErrorCode AdaptiveKDTree::best_vertex_median_plane( int num_planes,
1084 const AdaptiveKDTreeIter& iter,
1085 Range& best_left,
1086 Range& best_right,
1087 Range& best_both,
1088 AdaptiveKDTree::Plane& best_plane,
1089 std::vector< double >& coords,
1090 double eps )
1091 {
1092 double metric_val = std::numeric_limits< unsigned >::max();
1093
1094 ErrorCode r;
1095 const CartVect box_min( iter.box_min() );
1096 const CartVect box_max( iter.box_max() );
1097
1098 Range entities, vertices;
1099 r = iter.tool()->moab()->get_entities_by_handle( iter.handle(), entities );
1100 if( MB_SUCCESS != r ) return r;
1101 const size_t p_count = entities.size();
1102 r = iter.tool()->moab()->get_adjacencies( entities, 0, false, vertices, Interface::UNION );
1103 if( MB_SUCCESS != r ) return r;
1104
1105 coords.resize( vertices.size() );
1106 for( int axis = 0; axis < 3; ++axis )
1107 {
1108 if( box_max[axis] - box_min[axis] <= 2 * eps ) continue;
1109
1110 double* ptrs[] = { 0, 0, 0 };
1111 ptrs[axis] = &coords[0];
1112 r = iter.tool()->moab()->get_coords( vertices, ptrs[0], ptrs[1], ptrs[2] );
1113 if( MB_SUCCESS != r ) return r;
1114
1115 std::sort( coords.begin(), coords.end() );
1116 std::vector< double >::iterator citer;
1117 citer = std::upper_bound( coords.begin(), coords.end(), box_min[axis] + eps );
1118 const size_t count = std::upper_bound( citer, coords.end(), box_max[axis] - eps ) - citer;
1119 size_t step;
1120 int np = num_planes;
1121 if( count < 2 * (size_t)num_planes )
1122 {
1123 step = 1;
1124 np = count - 1;
1125 }
1126 else
1127 {
1128 step = count / ( num_planes + 1 );
1129 }
1130
1131 for( int p = 1; p <= np; ++p )
1132 {
1133
1134 citer += step;
1135 AdaptiveKDTree::Plane plane = { *citer, axis };
1136 Range left, right, both;
1137 double val;
1138 r = intersect_children_with_elems( entities, plane, eps, box_min, box_max, left, right, both, val );
1139 if( MB_SUCCESS != r ) return r;
1140 const size_t diff = p_count - both.size();
1141 if( left.size() == diff || right.size() == diff ) continue;
1142
1143 if( val >= metric_val ) continue;
1144
1145 metric_val = val;
1146 best_plane = plane;
1147 best_left.swap( left );
1148 best_right.swap( right );
1149 best_both.swap( both );
1150 }
1151 }
1152
1153 return MB_SUCCESS;
1154 }
1155
1156 ErrorCode AdaptiveKDTree::best_vertex_sample_plane( int num_planes,
1157 const AdaptiveKDTreeIter& iter,
1158 Range& best_left,
1159 Range& best_right,
1160 Range& best_both,
1161 AdaptiveKDTree::Plane& best_plane,
1162 std::vector< double >& coords,
1163 std::vector< EntityHandle >& indices,
1164 double eps )
1165 {
1166 const size_t random_elem_threshold = 20 * num_planes;
1167 double metric_val = std::numeric_limits< unsigned >::max();
1168
1169 ErrorCode r;
1170 const CartVect box_min( iter.box_min() );
1171 const CartVect box_max( iter.box_max() );
1172
1173 Range entities, vertices;
1174 r = iter.tool()->moab()->get_entities_by_handle( iter.handle(), entities );
1175 if( MB_SUCCESS != r ) return r;
1176
1177
1178
1179 const size_t p_count = entities.size();
1180 coords.resize( 3 * num_planes );
1181 if( p_count < random_elem_threshold )
1182 {
1183 r = iter.tool()->moab()->get_adjacencies( entities, 0, false, vertices, Interface::UNION );
1184 if( MB_SUCCESS != r ) return r;
1185 }
1186 else
1187 {
1188 indices.resize( random_elem_threshold );
1189 const int num_rand = p_count / RAND_MAX + 1;
1190 for( size_t j = 0; j < random_elem_threshold; ++j )
1191 {
1192 size_t rnd = rand();
1193 for( int i = num_rand; i > 1; --i )
1194 rnd *= rand();
1195 rnd %= p_count;
1196 indices[j] = entities[rnd];
1197 }
1198 r = iter.tool()->moab()->get_adjacencies( &indices[0], random_elem_threshold, 0, false, vertices,
1199 Interface::UNION );
1200 if( MB_SUCCESS != r ) return r;
1201 }
1202
1203 coords.resize( vertices.size() );
1204 for( int axis = 0; axis < 3; ++axis )
1205 {
1206 if( box_max[axis] - box_min[axis] <= 2 * eps ) continue;
1207
1208 double* ptrs[] = { 0, 0, 0 };
1209 ptrs[axis] = &coords[0];
1210 r = iter.tool()->moab()->get_coords( vertices, ptrs[0], ptrs[1], ptrs[2] );
1211 if( MB_SUCCESS != r ) return r;
1212
1213 size_t num_valid_coords = 0;
1214 for( size_t i = 0; i < coords.size(); ++i )
1215 if( coords[i] > box_min[axis] + eps && coords[i] < box_max[axis] - eps ) ++num_valid_coords;
1216
1217 if( 2 * (size_t)num_planes > num_valid_coords )
1218 {
1219 indices.clear();
1220 for( size_t i = 0; i < coords.size(); ++i )
1221 if( coords[i] > box_min[axis] + eps && coords[i] < box_max[axis] - eps ) indices.push_back( i );
1222 }
1223 else
1224 {
1225 indices.resize( num_planes );
1226
1227 const int num_rand = coords.size() / RAND_MAX + 1;
1228 for( int j = 0; j < num_planes; ++j )
1229 {
1230 size_t rnd;
1231 do
1232 {
1233 rnd = rand();
1234 for( int i = num_rand; i > 1; --i )
1235 rnd *= rand();
1236 rnd %= coords.size();
1237 } while( coords[rnd] <= box_min[axis] + eps || coords[rnd] >= box_max[axis] - eps );
1238 indices[j] = rnd;
1239 }
1240 }
1241
1242 for( unsigned p = 0; p < indices.size(); ++p )
1243 {
1244
1245 AdaptiveKDTree::Plane plane = { coords[indices[p]], axis };
1246 Range left, right, both;
1247 double val;
1248 r = intersect_children_with_elems( entities, plane, eps, box_min, box_max, left, right, both, val );
1249 if( MB_SUCCESS != r ) return r;
1250 const size_t diff = p_count - both.size();
1251 if( left.size() == diff || right.size() == diff ) continue;
1252
1253 if( val >= metric_val ) continue;
1254
1255 metric_val = val;
1256 best_plane = plane;
1257 best_left.swap( left );
1258 best_right.swap( right );
1259 best_both.swap( both );
1260 }
1261 }
1262
1263 return MB_SUCCESS;
1264 }
1265
1266 ErrorCode AdaptiveKDTree::point_search( const double* point,
1267 EntityHandle& leaf_out,
1268 const double iter_tol,
1269 const double inside_tol,
1270 bool* multiple_leaves,
1271 EntityHandle* start_node,
1272 CartVect* params )
1273 {
1274 std::vector< EntityHandle > children;
1275 Plane plane;
1276
1277 treeStats.numTraversals++;
1278 leaf_out = 0;
1279 BoundBox box;
1280
1281 if( multiple_leaves ) *multiple_leaves = false;
1282
1283 EntityHandle node = ( start_node ? *start_node : myRoot );
1284
1285 treeStats.nodesVisited++;
1286 ErrorCode rval = get_bounding_box( box, &node );
1287 if( MB_SUCCESS != rval ) return rval;
1288 if( !box.contains_point( point, iter_tol ) ) return MB_SUCCESS;
1289
1290 rval = moab()->get_child_meshsets( node, children );
1291 if( MB_SUCCESS != rval ) return rval;
1292
1293 while( !children.empty() )
1294 {
1295 treeStats.nodesVisited++;
1296
1297 rval = get_split_plane( node, plane );
1298 if( MB_SUCCESS != rval ) return rval;
1299
1300 const double d = point[plane.norm] - plane.coord;
1301 node = children[( d > 0.0 )];
1302
1303 children.clear();
1304 rval = moab()->get_child_meshsets( node, children );
1305 if( MB_SUCCESS != rval ) return rval;
1306 }
1307
1308 treeStats.leavesVisited++;
1309 if( myEval && params )
1310 {
1311 rval = myEval->find_containing_entity( node, point, iter_tol, inside_tol, leaf_out, params->array(),
1312 &treeStats.traversalLeafObjectTests );
1313 if( MB_SUCCESS != rval ) return rval;
1314 }
1315 else
1316 leaf_out = node;
1317
1318 return MB_SUCCESS;
1319 }
1320
1321 ErrorCode AdaptiveKDTree::point_search( const double* point,
1322 AdaptiveKDTreeIter& leaf_it,
1323 const double iter_tol,
1324 const double ,
1325 bool* multiple_leaves,
1326 EntityHandle* start_node )
1327 {
1328 ErrorCode rval;
1329 treeStats.numTraversals++;
1330
1331
1332 if( multiple_leaves ) *multiple_leaves = false;
1333
1334 leaf_it.mBox[0] = boundBox.bMin;
1335 leaf_it.mBox[1] = boundBox.bMax;
1336
1337
1338 if( !boundBox.contains_point( point, iter_tol ) )
1339 {
1340 treeStats.nodesVisited++;
1341 return MB_ENTITY_NOT_FOUND;
1342 }
1343
1344
1345 leaf_it.treeTool = this;
1346 leaf_it.mStack.clear();
1347 leaf_it.mStack.push_back( AdaptiveKDTreeIter::StackObj( ( start_node ? *start_node : myRoot ), 0 ) );
1348
1349
1350 AdaptiveKDTree::Plane plane;
1351 for( ;; )
1352 {
1353 treeStats.nodesVisited++;
1354
1355
1356 leaf_it.childVect.clear();
1357 rval = moab()->get_child_meshsets( leaf_it.handle(), leaf_it.childVect );
1358 if( MB_SUCCESS != rval ) return rval;
1359
1360
1361 if( leaf_it.childVect.empty() )
1362 {
1363 treeStats.leavesVisited++;
1364 break;
1365 }
1366
1367
1368 rval = get_split_plane( leaf_it.handle(), plane );
1369 if( MB_SUCCESS != rval ) return rval;
1370
1371
1372
1373 const int idx = ( point[plane.norm] > plane.coord );
1374 leaf_it.mStack.push_back(
1375 AdaptiveKDTreeIter::StackObj( leaf_it.childVect[idx], leaf_it.mBox[1 - idx][plane.norm] ) );
1376 leaf_it.mBox[1 - idx][plane.norm] = plane.coord;
1377 }
1378
1379 return MB_SUCCESS;
1380 }
1381
1382 struct NodeDistance
1383 {
1384 EntityHandle handle;
1385 CartVect dist;
1386 };
1387
1388 ErrorCode AdaptiveKDTree::distance_search( const double from_point[3],
1389 const double distance,
1390 std::vector< EntityHandle >& result_list,
1391 const double iter_tol,
1392 const double inside_tol,
1393 std::vector< double >* result_dists,
1394 std::vector< CartVect >* result_params,
1395 EntityHandle* tree_root )
1396 {
1397 treeStats.numTraversals++;
1398 const double dist_sqr = distance * distance;
1399 const CartVect from( from_point );
1400 std::vector< NodeDistance > list,
1401 result_list_nodes;
1402
1403 list.reserve( maxDepth );
1404
1405
1406 Plane plane;
1407 NodeDistance node;
1408 ErrorCode rval;
1409 std::vector< EntityHandle > children;
1410
1411
1412
1413 BoundBox box;
1414 rval = get_bounding_box( box );
1415 if( MB_SUCCESS == rval && !box.contains_point( from_point, iter_tol ) )
1416 {
1417 treeStats.nodesVisited++;
1418 return MB_SUCCESS;
1419 }
1420
1421
1422
1423 node.dist = CartVect( 0.0 );
1424 if( MB_SUCCESS == rval )
1425 {
1426 for( int i = 0; i < 3; ++i )
1427 {
1428 if( from_point[i] < box.bMin[i] )
1429 node.dist[i] = box.bMin[i] - from_point[i];
1430 else if( from_point[i] > box.bMax[i] )
1431 node.dist[i] = from_point[i] - box.bMax[i];
1432 }
1433 if( node.dist % node.dist > dist_sqr )
1434 {
1435 treeStats.nodesVisited++;
1436 return MB_SUCCESS;
1437 }
1438 }
1439
1440
1441 node.handle = ( tree_root ? *tree_root : myRoot );
1442 list.push_back( node );
1443
1444 while( !list.empty() )
1445 {
1446
1447 node = list.back();
1448 list.pop_back();
1449 treeStats.nodesVisited++;
1450
1451
1452 children.clear();
1453 rval = moab()->get_child_meshsets( node.handle, children );
1454 if( children.empty() )
1455 {
1456 treeStats.leavesVisited++;
1457 if( myEval && result_params )
1458 {
1459 EntityHandle ent;
1460 CartVect params;
1461 rval = myEval->find_containing_entity( node.handle, from_point, iter_tol, inside_tol, ent,
1462 params.array(), &treeStats.traversalLeafObjectTests );
1463 if( MB_SUCCESS != rval )
1464 return rval;
1465 else if( ent )
1466 {
1467 result_list.push_back( ent );
1468 result_params->push_back( params );
1469 if( result_dists ) result_dists->push_back( 0.0 );
1470 }
1471 }
1472 else
1473 {
1474 result_list_nodes.push_back( node );
1475 continue;
1476 }
1477 }
1478
1479
1480 rval = get_split_plane( node.handle, plane );
1481 if( MB_SUCCESS != rval ) return rval;
1482
1483 const double d = from[plane.norm] - plane.coord;
1484
1485
1486 if( d > 0 )
1487 {
1488 node.handle = children[1];
1489 list.push_back( node );
1490
1491
1492
1493 if( d <= distance )
1494 {
1495 node.dist[plane.norm] = d;
1496 if( node.dist % node.dist <= dist_sqr )
1497 {
1498 node.handle = children[0];
1499 list.push_back( node );
1500 }
1501 }
1502 }
1503
1504 else
1505 {
1506 node.handle = children[0];
1507 list.push_back( node );
1508
1509
1510
1511 if( -d <= distance )
1512 {
1513 node.dist[plane.norm] = -d;
1514 if( node.dist % node.dist <= dist_sqr )
1515 {
1516 node.handle = children[1];
1517 list.push_back( node );
1518 }
1519 }
1520 }
1521 }
1522
1523 if( myEval && result_params ) return MB_SUCCESS;
1524
1525
1526
1527 result_list.reserve( result_list_nodes.size() );
1528 for( std::vector< NodeDistance >::iterator vit = result_list_nodes.begin(); vit != result_list_nodes.end(); ++vit )
1529 result_list.push_back( ( *vit ).handle );
1530
1531 if( result_dists && distance > 0.0 )
1532 {
1533 result_dists->reserve( result_list_nodes.size() );
1534 for( std::vector< NodeDistance >::iterator vit = result_list_nodes.begin(); vit != result_list_nodes.end();
1535 ++vit )
1536 result_dists->push_back( ( *vit ).dist.length() );
1537 }
1538
1539 return MB_SUCCESS;
1540 }
1541
1542 static ErrorCode closest_to_triangles( Interface* moab,
1543 const Range& tris,
1544 const CartVect& from,
1545 double& shortest_dist_sqr,
1546 CartVect& closest_pt,
1547 EntityHandle& closest_tri )
1548 {
1549 ErrorCode rval;
1550 CartVect pos, diff, verts[3];
1551 const EntityHandle* conn = NULL;
1552 int len = 0;
1553
1554 for( Range::iterator i = tris.begin(); i != tris.end(); ++i )
1555 {
1556 rval = moab->get_connectivity( *i, conn, len );
1557 if( MB_SUCCESS != rval ) return rval;
1558
1559 rval = moab->get_coords( conn, 3, verts[0].array() );
1560 if( MB_SUCCESS != rval ) return rval;
1561
1562 GeomUtil::closest_location_on_tri( from, verts, pos );
1563 diff = pos - from;
1564 double dist_sqr = diff % diff;
1565 if( dist_sqr < shortest_dist_sqr )
1566 {
1567
1568 shortest_dist_sqr = dist_sqr;
1569 closest_pt = pos;
1570 closest_tri = *i;
1571 }
1572 }
1573
1574 return MB_SUCCESS;
1575 }
1576
1577 static ErrorCode closest_to_triangles( Interface* moab,
1578 EntityHandle set_handle,
1579 const CartVect& from,
1580 double& shortest_dist_sqr,
1581 CartVect& closest_pt,
1582 EntityHandle& closest_tri )
1583 {
1584 ErrorCode rval;
1585 Range tris;
1586
1587 rval = moab->get_entities_by_type( set_handle, MBTRI, tris );
1588 if( MB_SUCCESS != rval ) return rval;
1589
1590 return closest_to_triangles( moab, tris, from, shortest_dist_sqr, closest_pt, closest_tri );
1591 }
1592
1593 ErrorCode AdaptiveKDTree::find_close_triangle( EntityHandle root,
1594 const double from[3],
1595 double pt[3],
1596 EntityHandle& triangle )
1597 {
1598 ErrorCode rval;
1599 Range tris;
1600 Plane split;
1601 std::vector< EntityHandle > stack;
1602 std::vector< EntityHandle > children( 2 );
1603 stack.reserve( 30 );
1604 assert( root );
1605 stack.push_back( root );
1606
1607 while( !stack.empty() )
1608 {
1609 EntityHandle node = stack.back();
1610 stack.pop_back();
1611
1612 for( ;; )
1613 {
1614
1615 children.clear();
1616 rval = moab()->get_child_meshsets( node, children );
1617 if( MB_SUCCESS != rval ) return rval;
1618
1619
1620 if( children.empty() ) break;
1621
1622
1623 rval = get_split_plane( node, split );
1624 if( MB_SUCCESS != rval ) return rval;
1625
1626
1627
1628
1629 int rs = split.right_side( from );
1630 node = children[rs];
1631 stack.push_back( children[1 - rs] );
1632 }
1633
1634
1635
1636
1637 tris.clear();
1638 rval = moab()->get_entities_by_type( node, MBTRI, tris );
1639 if( !tris.empty() )
1640 {
1641 double dist_sqr = HUGE_VAL;
1642 CartVect point( pt );
1643 rval = closest_to_triangles( moab(), tris, CartVect( from ), dist_sqr, point, triangle );
1644 point.get( pt );
1645 return rval;
1646 }
1647 }
1648
1649
1650
1651 return MB_ENTITY_NOT_FOUND;
1652 }
1653
1654
1668
1762
1763 ErrorCode AdaptiveKDTree::closest_triangle( EntityHandle tree_root,
1764 const double from_coords[3],
1765 double closest_point_out[3],
1766 EntityHandle& triangle_out )
1767 {
1768 ErrorCode rval;
1769 double shortest_dist_sqr = HUGE_VAL;
1770 std::vector< EntityHandle > leaves;
1771 const CartVect from( from_coords );
1772 CartVect closest_pt;
1773
1774
1775
1776
1777 assert( tree_root );
1778 rval = find_close_triangle( tree_root, from_coords, closest_pt.array(), triangle_out );
1779 if( MB_SUCCESS != rval ) return rval;
1780
1781
1782
1783
1784 CartVect diff = closest_pt - from;
1785 rval = distance_search( from_coords, sqrt( diff % diff ), leaves, 1.0e-10, 1.0e-6, NULL, NULL, &tree_root );
1786 if( MB_SUCCESS != rval ) return rval;
1787
1788
1789
1790 for( unsigned i = 0; i < leaves.size(); ++i )
1791 {
1792 rval = closest_to_triangles( moab(), leaves[i], from, shortest_dist_sqr, closest_pt, triangle_out );
1793 if( MB_SUCCESS != rval ) return rval;
1794 }
1795
1796
1797 closest_pt.get( closest_point_out );
1798 return MB_SUCCESS;
1799 }
1800
1801 ErrorCode AdaptiveKDTree::sphere_intersect_triangles( EntityHandle tree_root,
1802 const double center[3],
1803 double rad,
1804 std::vector< EntityHandle >& triangles )
1805 {
1806 ErrorCode rval;
1807 std::vector< EntityHandle > leaves;
1808 const CartVect from( center );
1809 CartVect closest_pt;
1810 const EntityHandle* conn;
1811 CartVect coords[3];
1812 int conn_len;
1813
1814
1815 assert( tree_root );
1816 rval = distance_search( center, rad, leaves, 1.0e-10, 1.0e-6, NULL, NULL, &tree_root );
1817 if( MB_SUCCESS != rval ) return rval;
1818
1819
1820 for( unsigned i = 0; i < leaves.size(); ++i )
1821 {
1822 Range tris;
1823 rval = moab()->get_entities_by_type( leaves[i], MBTRI, tris );
1824 if( MB_SUCCESS != rval ) return rval;
1825
1826 for( Range::iterator j = tris.begin(); j != tris.end(); ++j )
1827 {
1828 rval = moab()->get_connectivity( *j, conn, conn_len );
1829 if( MB_SUCCESS != rval ) return rval;
1830 rval = moab()->get_coords( conn, 3, coords[0].array() );
1831 if( MB_SUCCESS != rval ) return rval;
1832 GeomUtil::closest_location_on_tri( from, coords, closest_pt );
1833 closest_pt -= from;
1834 if( ( closest_pt % closest_pt ) <= ( rad * rad ) ) triangles.push_back( *j );
1835 }
1836 }
1837
1838
1839 std::sort( triangles.begin(), triangles.end() );
1840 triangles.erase( std::unique( triangles.begin(), triangles.end() ), triangles.end() );
1841 return MB_SUCCESS;
1842 }
1843
1844 struct NodeSeg
1845 {
1846 NodeSeg( EntityHandle h, double b, double e ) : handle( h ), beg( b ), end( e ) {}
1847 EntityHandle handle;
1848 double beg, end;
1849 };
1850
1851 ErrorCode AdaptiveKDTree::ray_intersect_triangles( EntityHandle root,
1852 const double tol,
1853 const double ray_dir_in[3],
1854 const double ray_pt_in[3],
1855 std::vector< EntityHandle >& tris_out,
1856 std::vector< double >& dists_out,
1857 int max_ints,
1858 double ray_end )
1859 {
1860 ErrorCode rval;
1861 double ray_beg = 0.0;
1862 if( ray_end < 0.0 ) ray_end = HUGE_VAL;
1863
1864
1865 CartVect tvec( tol );
1866 BoundBox box;
1867 const CartVect ray_pt( ray_pt_in ), ray_dir( ray_dir_in );
1868 rval = get_bounding_box( box );
1869 if( MB_SUCCESS == rval )
1870 {
1871 if( !GeomUtil::segment_box_intersect( box.bMin - tvec, box.bMax + tvec, ray_pt, ray_dir, ray_beg, ray_end ) )
1872 return MB_SUCCESS;
1873 }
1874
1875 Range tris;
1876 Range::iterator iter;
1877 CartVect tri_coords[3];
1878 const EntityHandle* tri_conn;
1879 int conn_len;
1880 double tri_t;
1881
1882 Plane plane;
1883 std::vector< EntityHandle > children;
1884 std::vector< NodeSeg > list;
1885 NodeSeg seg( root, ray_beg, ray_end );
1886 list.push_back( seg );
1887
1888 while( !list.empty() )
1889 {
1890 seg = list.back();
1891 list.pop_back();
1892
1893
1894
1895
1896
1897 if( seg.beg > ray_end ) continue;
1898
1899
1900 children.clear();
1901 rval = moab()->get_child_meshsets( seg.handle, children );
1902 if( MB_SUCCESS != rval ) return rval;
1903 if( children.empty() )
1904 {
1905
1906 tris.clear();
1907 rval = moab()->get_entities_by_type( seg.handle, MBTRI, tris );
1908 if( MB_SUCCESS != rval ) return rval;
1909
1910 for( iter = tris.begin(); iter != tris.end(); ++iter )
1911 {
1912 rval = moab()->get_connectivity( *iter, tri_conn, conn_len );
1913 if( MB_SUCCESS != rval ) return rval;
1914 rval = moab()->get_coords( tri_conn, 3, tri_coords[0].array() );
1915 if( MB_SUCCESS != rval ) return rval;
1916
1917 if( GeomUtil::ray_tri_intersect( tri_coords, ray_pt, ray_dir, tri_t, &ray_end ) )
1918 {
1919 if( !max_ints )
1920 {
1921 if( std::find( tris_out.begin(), tris_out.end(), *iter ) == tris_out.end() )
1922 {
1923 tris_out.push_back( *iter );
1924 dists_out.push_back( tri_t );
1925 }
1926 }
1927 else if( tri_t < ray_end )
1928 {
1929 if( std::find( tris_out.begin(), tris_out.end(), *iter ) == tris_out.end() )
1930 {
1931 if( tris_out.size() < (unsigned)max_ints )
1932 {
1933 tris_out.resize( tris_out.size() + 1 );
1934 dists_out.resize( dists_out.size() + 1 );
1935 }
1936 int w = tris_out.size() - 1;
1937 for( ; w > 0 && tri_t < dists_out[w - 1]; --w )
1938 {
1939 tris_out[w] = tris_out[w - 1];
1940 dists_out[w] = dists_out[w - 1];
1941 }
1942 tris_out[w] = *iter;
1943 dists_out[w] = tri_t;
1944 if( tris_out.size() >= (unsigned)max_ints )
1945
1946
1947
1948 ray_end = dists_out.back();
1949 }
1950 }
1951 }
1952 }
1953
1954 continue;
1955 }
1956
1957 rval = get_split_plane( seg.handle, plane );
1958 if( MB_SUCCESS != rval ) return rval;
1959
1960
1961
1962
1963
1964 const double inv_dir = 1.0 / ray_dir[plane.norm];
1965 const double t = ( plane.coord - ray_pt[plane.norm] ) * inv_dir;
1966 const double diff = tol * inv_dir;
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976 const int fwd_child = ( ray_dir[plane.norm] > 0.0 );
1977
1978
1979
1980
1981 if( !Util::is_finite( t ) )
1982 {
1983 if( ray_pt[plane.norm] - tol <= plane.coord ) list.push_back( NodeSeg( children[0], seg.beg, seg.end ) );
1984 if( ray_pt[plane.norm] + tol >= plane.coord ) list.push_back( NodeSeg( children[1], seg.beg, seg.end ) );
1985 }
1986
1987
1988 else if( seg.end + diff < t )
1989 {
1990
1991
1992
1993
1994 list.push_back( NodeSeg( children[1 - fwd_child], seg.beg, seg.end ) );
1995 }
1996
1997
1998
1999 else if( seg.beg - diff > t )
2000 {
2001
2002
2003
2004
2005 list.push_back( NodeSeg( children[fwd_child], seg.beg, seg.end ) );
2006 }
2007
2008
2009
2010
2011 else if( t <= seg.beg )
2012 {
2013 list.push_back( NodeSeg( children[1 - fwd_child], seg.beg, seg.beg ) );
2014 list.push_back( NodeSeg( children[fwd_child], seg.beg, seg.end ) );
2015 }
2016 else if( t >= seg.end )
2017 {
2018 list.push_back( NodeSeg( children[1 - fwd_child], seg.beg, seg.end ) );
2019 list.push_back( NodeSeg( children[fwd_child], seg.end, seg.end ) );
2020 }
2021 else
2022 {
2023 list.push_back( NodeSeg( children[1 - fwd_child], seg.beg, t ) );
2024 list.push_back( NodeSeg( children[fwd_child], t, seg.end ) );
2025 }
2026 }
2027
2028 return MB_SUCCESS;
2029 }
2030
2031 ErrorCode AdaptiveKDTree::compute_depth( EntityHandle root, unsigned int& min_depth, unsigned int& max_depth )
2032 {
2033 AdaptiveKDTreeIter iter;
2034 get_tree_iterator( root, iter );
2035 iter.step_to_first_leaf( AdaptiveKDTreeIter::LEFT );
2036 min_depth = max_depth = iter.depth();
2037
2038 int num_of_elements = 0, max, min;
2039 moab()->get_number_entities_by_handle( iter.handle(), num_of_elements );
2040 max = min = num_of_elements;
2041 while( MB_SUCCESS == iter.step() )
2042 {
2043 int temp = 0;
2044 moab()->get_number_entities_by_handle( iter.handle(), temp );
2045 max = std::max( max, temp );
2046 min = std::min( min, temp );
2047 if( iter.depth() > max_depth )
2048 max_depth = iter.depth();
2049 else if( iter.depth() < min_depth )
2050 min_depth = iter.depth();
2051 }
2052 return MB_SUCCESS;
2053 }
2054
2055 ErrorCode AdaptiveKDTree::get_info( EntityHandle root, double bmin[3], double bmax[3], unsigned int& dep )
2056 {
2057 BoundBox box;
2058 ErrorCode result = get_bounding_box( box, &root );
2059 if( MB_SUCCESS != result ) return result;
2060 box.bMin.get( bmin );
2061 box.bMax.get( bmax );
2062
2063 unsigned min_depth;
2064 return compute_depth( root, min_depth, dep );
2065 }
2066
2067 static std::string mem_to_string( unsigned long mem )
2068 {
2069 char unit[3] = "B";
2070 if( mem > 9 * 1024 )
2071 {
2072 mem = ( mem + 512 ) / 1024;
2073 strcpy( unit, "kB" );
2074 }
2075 if( mem > 9 * 1024 )
2076 {
2077 mem = ( mem + 512 ) / 1024;
2078 strcpy( unit, "MB" );
2079 }
2080 if( mem > 9 * 1024 )
2081 {
2082 mem = ( mem + 512 ) / 1024;
2083 strcpy( unit, "GB" );
2084 }
2085 char buffer[256];
2086 snprintf( buffer, 256, "%lu %s", mem, unit );
2087 return buffer;
2088 }
2089
2090 template < typename T >
2091 struct SimpleStat
2092 {
2093 T min, max, sum, sqr;
2094 size_t count;
2095 SimpleStat();
2096 void add( T value );
2097 double avg() const
2098 {
2099 return (double)sum / count;
2100 }
2101 double rms() const
2102 {
2103 return sqrt( (double)sqr / count );
2104 }
2105 double dev() const
2106 {
2107 return ( count > 1
2108 ? sqrt( ( count * (double)sqr - (double)sum * (double)sum ) / ( (double)count * ( count - 1 ) ) )
2109 : 0.0 );
2110 }
2111 };
2112
2113 template < typename T >
2114 SimpleStat< T >::SimpleStat()
2115 : min( std::numeric_limits< T >::max() ), max( std::numeric_limits< T >::min() ), sum( 0 ), sqr( 0 ), count( 0 )
2116 {
2117 }
2118
2119 template < typename T >
2120 void SimpleStat< T >::add( T value )
2121 {
2122 if( value < min ) min = value;
2123 if( value > max ) max = value;
2124 sum += value;
2125 sqr += value * value;
2126 ++count;
2127 }
2128
2129 ErrorCode AdaptiveKDTree::print()
2130 {
2131 Range range;
2132
2133 Range tree_sets, elem2d, elem3d, verts, all;
2134 moab()->get_child_meshsets( myRoot, tree_sets, 0 );
2135
2136 {
2137 std::vector<EntityHandle> elem2d_vec, elem3d_vec, verts_vec;
2138 for( Range::iterator rit = tree_sets.begin(); rit != tree_sets.end(); ++rit )
2139 {
2140 moab()->get_entities_by_dimension( *rit, 2, elem2d_vec );
2141 moab()->get_entities_by_dimension( *rit, 3, elem3d_vec );
2142 moab()->get_entities_by_type( *rit, MBVERTEX, verts_vec );
2143 }
2144 std::sort(elem2d_vec.begin(), elem2d_vec.end());
2145 std::copy( elem2d_vec.rbegin(), elem2d_vec.rend(), range_inserter( elem2d ) );
2146 std::sort(elem3d_vec.begin(), elem3d_vec.end());
2147 std::copy( elem3d_vec.rbegin(), elem3d_vec.rend(), range_inserter( elem3d ) );
2148 std::sort(verts_vec.begin(), verts_vec.end());
2149 std::copy( verts_vec.rbegin(), verts_vec.rend(), range_inserter( verts ) );
2150 }
2151
2152 all.merge( verts );
2153 all.merge( elem2d );
2154 all.merge( elem3d );
2155 tree_sets.insert( myRoot );
2156 unsigned long long set_used, set_amortized, set_store_used, set_store_amortized, set_tag_used, set_tag_amortized,
2157 elem_used, elem_amortized;
2158 moab()->estimated_memory_use( tree_sets, &set_used, &set_amortized, &set_store_used, &set_store_amortized, 0, 0, 0,
2159 0, &set_tag_used, &set_tag_amortized );
2160 moab()->estimated_memory_use( all, &elem_used, &elem_amortized );
2161
2162 int num_2d = 0, num_3d = 0;
2163 ;
2164 moab()->get_number_entities_by_dimension( 0, 2, num_2d );
2165 moab()->get_number_entities_by_dimension( 0, 3, num_3d );
2166
2167 BoundBox box;
2168 ErrorCode rval = get_bounding_box( box, &myRoot );
2169 if( MB_SUCCESS != rval || box == BoundBox() ) throw rval;
2170 double diff[3] = { box.bMax[0] - box.bMin[0], box.bMax[1] - box.bMin[1], box.bMax[2] - box.bMin[2] };
2171 double tree_vol = diff[0] * diff[1] * diff[2];
2172 double tree_surf_area = 2 * ( diff[0] * diff[1] + diff[1] * diff[2] + diff[2] * diff[0] );
2173
2174 SimpleStat< unsigned > depth, size;
2175 SimpleStat< double > vol, surf;
2176
2177 AdaptiveKDTreeIter iter;
2178 get_tree_iterator( myRoot, iter );
2179 do
2180 {
2181 depth.add( iter.depth() );
2182
2183 int num_leaf_elem;
2184 moab()->get_number_entities_by_handle( iter.handle(), num_leaf_elem );
2185 size.add( num_leaf_elem );
2186
2187 const double* n = iter.box_min();
2188 const double* x = iter.box_max();
2189 double dims[3] = { x[0] - n[0], x[1] - n[1], x[2] - n[2] };
2190
2191 double leaf_vol = dims[0] * dims[1] * dims[2];
2192 vol.add( leaf_vol );
2193
2194 double area = 2.0 * ( dims[0] * dims[1] + dims[1] * dims[2] + dims[2] * dims[0] );
2195 surf.add( area );
2196
2197 } while( MB_SUCCESS == iter.step() );
2198
2199 printf( "------------------------------------------------------------------\n" );
2200 printf( "tree volume: %f\n", tree_vol );
2201 printf( "total elements: %d\n", num_2d + num_3d );
2202 printf( "number of leaves: %lu\n", (unsigned long)depth.count );
2203 printf( "number of nodes: %lu\n", (unsigned long)tree_sets.size() );
2204 printf( "volume ratio: %0.2f%%\n", 100 * ( vol.sum / tree_vol ) );
2205 printf( "surface ratio: %0.2f%%\n", 100 * ( surf.sum / tree_surf_area ) );
2206 printf( "\nmemory: used amortized\n" );
2207 printf( " ---------- ----------\n" );
2208 printf( "elements %10s %10s\n", mem_to_string( elem_used ).c_str(), mem_to_string( elem_amortized ).c_str() );
2209 printf( "sets (total)%10s %10s\n", mem_to_string( set_used ).c_str(), mem_to_string( set_amortized ).c_str() );
2210 printf( "sets %10s %10s\n", mem_to_string( set_store_used ).c_str(),
2211 mem_to_string( set_store_amortized ).c_str() );
2212 printf( "set tags %10s %10s\n", mem_to_string( set_tag_used ).c_str(),
2213 mem_to_string( set_tag_amortized ).c_str() );
2214 printf( "\nleaf stats: min avg rms max std.dev\n" );
2215 printf( " ---------- ---------- ---------- ---------- ----------\n" );
2216 printf( "depth %10u %10.1f %10.1f %10u %10.2f\n", depth.min, depth.avg(), depth.rms(), depth.max,
2217 depth.dev() );
2218 printf( "triangles %10u %10.1f %10.1f %10u %10.2f\n", size.min, size.avg(), size.rms(), size.max, size.dev() );
2219 printf( "volume %10.2g %10.2g %10.2g %10.2g %10.2g\n", vol.min, vol.avg(), vol.rms(), vol.max, vol.dev() );
2220 printf( "surf. area %10.2g %10.2g %10.2g %10.2g %10.2g\n", surf.min, surf.avg(), surf.rms(), surf.max,
2221 surf.dev() );
2222 printf( "------------------------------------------------------------------\n" );
2223
2224 return MB_SUCCESS;
2225 }
2226
2227 }