MOAB: Mesh Oriented datABase
(version 5.4.1)
|
00001 #include "moab/Core.hpp" 00002 #include "moab/AdaptiveKDTree.hpp" 00003 #include "moab/CartVect.hpp" 00004 #include "moab/GeomUtil.hpp" 00005 #include "moab/Range.hpp" 00006 #include "TestUtil.hpp" 00007 00008 using namespace moab; 00009 00010 #include <iostream> 00011 #include <algorithm> 00012 #include <sstream> 00013 00014 #ifdef MOAB_HAVE_MPI 00015 #include "moab_mpi.h" 00016 #endif 00017 00018 /* Utility method - compare two range boxes */ 00019 bool box_equal( const AdaptiveKDTreeIter& iter, 00020 double x_min, 00021 double y_min, 00022 double z_min, 00023 double x_max, 00024 double y_max, 00025 double z_max ) 00026 { 00027 return iter.box_min()[0] == x_min && iter.box_min()[1] == y_min && iter.box_min()[2] == z_min && 00028 iter.box_max()[0] == x_max && iter.box_max()[1] == y_max && iter.box_max()[2] == z_max; 00029 } 00030 00031 void build_triangles( Interface* moab, 00032 Range& tris, 00033 int num_vert, 00034 const double* coords, 00035 int num_tri, 00036 const unsigned* conn ) 00037 { 00038 std::vector< EntityHandle > verts( num_vert ); 00039 for( int i = 0; i < num_vert; ++i ) 00040 moab->create_vertex( coords + 3 * i, verts[i] ); 00041 00042 EntityHandle tri, tri_verts[3]; 00043 for( int i = 0; i < num_tri; ++i ) 00044 { 00045 tri_verts[0] = verts[conn[3 * i]]; 00046 tri_verts[1] = verts[conn[3 * i + 1]]; 00047 tri_verts[2] = verts[conn[3 * i + 2]]; 00048 moab->create_element( MBTRI, tri_verts, 3, tri ); 00049 tris.insert( tri ); 00050 } 00051 } 00052 00053 /* Utility method - build a 2x2x2 box composed of two triagles on a side */ 00054 void build_triangle_box_small( Interface* moab, Range& tris ) 00055 { 00056 const double coords[] = { -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1 }; 00057 00058 const unsigned conn[] = { 0, 1, 5, 0, 5, 4, 2, 6, 7, 2, 7, 3, 1, 2, 6, 1, 6, 5, 00059 0, 3, 4, 3, 7, 4, 0, 1, 3, 1, 2, 3, 4, 5, 6, 4, 6, 7 }; 00060 00061 build_triangles( moab, tris, 8, coords, 12, conn ); 00062 } 00063 00064 /* build 6x6x6 box centered at origin and composed of 18 triangles per side, 00065 Each side of the box is composed of a 3x3 grid of quads, where each 00066 quad is split diagonally to form two triangles. */ 00067 void build_triangle_box_large( Interface* moab, Range& tris ) 00068 { 00069 const double coords[] = { // corners 00070 -3, -3, -3, 3, -3, -3, 3, 3, -3, -3, 3, -3, -3, -3, 3, 3, -3, 3, 3, 3, 3, -3, 3, 3, 00071 00072 // edges 00073 -1, -3, -3, 1, -3, -3, 3, -1, -3, 3, 1, -3, 1, 3, -3, -1, 3, -3, -3, 1, -3, -3, -1, -3, 00074 00075 -1, -3, 3, 1, -3, 3, 3, -1, 3, 3, 1, 3, 1, 3, 3, -1, 3, 3, -3, 1, 3, -3, -1, 3, 00076 00077 -3, -3, -1, -3, -3, 1, 3, -3, -1, 3, -3, 1, 3, 3, -1, 3, 3, 1, -3, 3, -1, -3, 3, 1, 00078 00079 // faces 00080 -1, -3, -1, 1, -3, -1, 1, -3, 1, -1, -3, 1, 00081 00082 3, -1, -1, 3, 1, -1, 3, 1, 1, 3, -1, 1, 00083 00084 1, 3, -1, -1, 3, -1, -1, 3, 1, 1, 3, 1, 00085 00086 -3, 1, -1, -3, -1, -1, -3, -1, 1, -3, 1, 1, 00087 00088 -1, -1, -3, 1, -1, -3, 1, 1, -3, -1, 1, -3, 00089 00090 -1, -1, 3, 1, -1, 3, 1, 1, 3, -1, 1, 3 }; 00091 const unsigned conn[] = { 00092 // face 0 00093 0, 8, 24, 8, 32, 24, 8, 33, 32, 8, 9, 33, 9, 1, 33, 1, 26, 33, 24, 35, 25, 24, 32, 35, 32, 33, 35, 33, 34, 35, 00094 33, 27, 34, 33, 26, 27, 35, 4, 25, 35, 16, 4, 35, 17, 16, 35, 34, 17, 27, 17, 34, 27, 5, 17, 00095 // face 1 00096 36, 26, 1, 36, 1, 10, 36, 10, 11, 36, 11, 37, 11, 28, 37, 11, 2, 28, 36, 27, 26, 36, 39, 27, 36, 38, 39, 36, 37, 00097 38, 37, 28, 38, 28, 29, 38, 18, 5, 27, 18, 27, 39, 18, 39, 38, 18, 38, 19, 6, 19, 38, 6, 38, 29, 00098 // face 2 00099 12, 28, 2, 12, 40, 28, 12, 41, 40, 12, 13, 41, 3, 41, 13, 3, 30, 41, 43, 29, 28, 43, 28, 40, 43, 40, 41, 43, 41, 00100 42, 41, 31, 42, 41, 30, 31, 43, 6, 29, 43, 20, 6, 43, 21, 20, 43, 42, 21, 21, 42, 31, 21, 31, 7, 00101 // face 3 00102 44, 30, 3, 44, 3, 14, 44, 14, 15, 44, 15, 45, 15, 24, 45, 15, 0, 24, 44, 31, 30, 44, 47, 31, 44, 46, 47, 44, 45, 00103 46, 46, 45, 24, 46, 24, 25, 31, 22, 7, 31, 47, 22, 46, 22, 47, 46, 23, 22, 46, 4, 23, 46, 25, 4, 00104 // face 4 00105 8, 15, 0, 8, 48, 15, 8, 49, 48, 8, 9, 49, 1, 49, 9, 1, 10, 49, 51, 14, 15, 51, 15, 48, 51, 48, 49, 51, 49, 50, 00106 11, 50, 49, 11, 49, 10, 51, 3, 14, 51, 13, 3, 51, 12, 13, 51, 50, 12, 11, 12, 50, 11, 2, 12, 00107 // face 5 00108 4, 52, 16, 4, 23, 52, 22, 52, 23, 22, 55, 52, 22, 21, 55, 22, 7, 21, 17, 16, 52, 17, 52, 53, 54, 53, 52, 54, 52, 00109 55, 54, 55, 21, 54, 21, 20, 18, 5, 17, 18, 17, 53, 18, 53, 54, 18, 54, 19, 6, 19, 54, 6, 54, 20 }; 00110 00111 build_triangles( moab, tris, 56, coords, 108, conn ); 00112 } 00113 00114 /* Utility method - build 2x2x2 octahedron (3D diamond)*/ 00115 void build_triangle_octahedron( Interface* moab, Range& tris ) 00116 { 00117 const double coords[] = { 1, 0, 0, 0, 1, 0, -1, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, -1 }; 00118 const unsigned conn[] = { 0, 1, 4, 1, 2, 4, 2, 3, 4, 3, 0, 4, 1, 0, 5, 2, 1, 5, 3, 2, 5, 0, 3, 5 }; 00119 00120 build_triangles( moab, tris, 6, coords, 8, conn ); 00121 } 00122 00123 void test_valid_tree( AdaptiveKDTree* tool, EntityHandle root, FileOptions& options, const Range& expected_tris ) 00124 { 00125 Range all_tris; 00126 ErrorCode rval; 00127 AdaptiveKDTreeIter iter; 00128 CHECK( MB_SUCCESS == tool->get_tree_iterator( root, iter ) ); 00129 do 00130 { 00131 double dep; 00132 rval = options.get_real_option( "MAX_DEPTH", dep ); 00133 CHECK( MB_ENTITY_NOT_FOUND == rval || iter.depth() <= tool->get_max_depth() ); 00134 00135 Range tris; 00136 CHECK( tool->moab()->get_entities_by_type( iter.handle(), MBTRI, tris ) == MB_SUCCESS ); 00137 // CHECK( !tris.empty() ); 00138 all_tris.merge( tris ); 00139 00140 const CartVect min( iter.box_min() ), max( iter.box_max() ); 00141 const CartVect cen( 0.5 * ( min + max ) ), hdim( 0.5 * ( max - min ) ); 00142 00143 for( Range::iterator i = tris.begin(); i != tris.end(); ++i ) 00144 { 00145 EntityHandle tri = *i; 00146 const EntityHandle* conn; 00147 int conn_len; 00148 CHECK( tool->moab()->get_connectivity( tri, conn, conn_len ) == MB_SUCCESS ); 00149 CHECK( conn_len == 3 ); 00150 CartVect coords[3]; 00151 CHECK( tool->moab()->get_coords( conn, 3, coords[0].array() ) == MB_SUCCESS ); 00152 CHECK( GeomUtil::box_tri_overlap( coords, cen, hdim ) ); 00153 } 00154 } while( MB_SUCCESS == ( rval = iter.step() ) ); 00155 00156 CHECK( MB_ENTITY_NOT_FOUND == rval ); 00157 CHECK( expected_tris == all_tris ); 00158 } 00159 00160 /* utility method - check that all tris share a vertex */ 00161 void check_common_vertex( Interface* moab, const EntityHandle* tris, unsigned num_tri, CartVect point ) 00162 { 00163 for( unsigned i = 0; i < num_tri; ++i ) 00164 CHECK( MBTRI == moab->type_from_handle( tris[i] ) ); 00165 00166 ErrorCode rval; 00167 CartVect tri_coords[3]; 00168 const EntityHandle* conn; 00169 int conn_len; 00170 rval = moab->get_connectivity( tris[0], conn, conn_len ); 00171 CHECK( MB_SUCCESS == rval ); 00172 rval = moab->get_coords( conn, 3, tri_coords[0].array() ); 00173 CHECK( MB_SUCCESS == rval ); 00174 tri_coords[0] -= point; 00175 tri_coords[1] -= point; 00176 tri_coords[2] -= point; 00177 EntityHandle vertex = 0; 00178 if( tri_coords[0] % tri_coords[0] < 1e-6 ) 00179 vertex = conn[0]; 00180 else if( tri_coords[1] % tri_coords[1] < 1e-6 ) 00181 vertex = conn[1]; 00182 else if( tri_coords[2] % tri_coords[2] < 1e-6 ) 00183 vertex = conn[2]; 00184 else 00185 CHECK( false ); 00186 for( unsigned j = 1; j < num_tri; ++j ) 00187 { 00188 rval = moab->get_connectivity( tris[j], conn, conn_len ); 00189 CHECK( conn[0] == vertex || conn[1] == vertex || conn[2] == vertex ); 00190 } 00191 } 00192 00193 /* utility method - check that all tris share a vertex */ 00194 void check_point_in_triangles( Interface* moab, const EntityHandle* tris, unsigned num_tris, CartVect point ) 00195 { 00196 ErrorCode rval; 00197 CartVect tri_coords[3], tript; 00198 const EntityHandle* conn; 00199 int conn_len; 00200 00201 for( unsigned i = 0; i < num_tris; ++i ) 00202 { 00203 CHECK( MBTRI == moab->type_from_handle( tris[i] ) ); 00204 00205 rval = moab->get_connectivity( tris[i], conn, conn_len ); 00206 CHECK( MB_SUCCESS == rval ); 00207 rval = moab->get_coords( conn, 3, tri_coords[0].array() ); 00208 CHECK( MB_SUCCESS == rval ); 00209 00210 GeomUtil::closest_location_on_tri( point, tri_coords, tript ); 00211 tript -= point; 00212 CHECK( fabs( tript[0] ) < 1e-6 ); 00213 CHECK( fabs( tript[1] ) < 1e-6 ); 00214 CHECK( fabs( tript[2] ) < 1e-6 ); 00215 } 00216 } 00217 00218 /* Create the following 2D tree (no Z splits) 00219 00220 (6) X = -3 (5) X = 0 00221 / | 00222 / | [8] 00223 / |---------------- (7) Y = 3 00224 [5] / [6] | 00225 / | [7] 00226 / | 00227 / | 00228 -------------------------------------- (1) Y = 0 00229 | | 00230 [2] | | 00231 (3)----------------| | 00232 Y = -2 | [3] | [4] 00233 | | 00234 [1] | | 00235 | | 00236 (2) X = -1 (4) X = 4 00237 */ 00238 void create_simple_2d_tree( AdaptiveKDTree& tool, EntityHandle& root, EntityHandle leaves[9] = 0 ) 00239 { 00240 ErrorCode rval; 00241 AdaptiveKDTree::Plane plane; 00242 00243 // create a single-node tree 00244 double min[3] = { -5, -4, -1 }; 00245 double max[3] = { 5, 4, 1 }; 00246 rval = tool.create_root( min, max, root ); 00247 CHECK( MB_SUCCESS == rval ); 00248 00249 // get iterator for tree 00250 AdaptiveKDTreeIter iter; 00251 rval = tool.get_tree_iterator( root, iter ); 00252 CHECK( MB_SUCCESS == rval ); 00253 CHECK( box_equal( iter, -5, -4, -1, 5, 4, 1 ) ); 00254 00255 // split plane (1) 00256 plane.norm = AdaptiveKDTree::Y; 00257 plane.coord = 0.0; 00258 rval = tool.split_leaf( iter, plane ); 00259 CHECK( MB_SUCCESS == rval ); 00260 CHECK( box_equal( iter, -5, -4, -1, 5, 0, 1 ) ); 00261 00262 // split plane (2) 00263 plane.norm = AdaptiveKDTree::X; 00264 plane.coord = -1.0; 00265 rval = tool.split_leaf( iter, plane ); 00266 CHECK( MB_SUCCESS == rval ); 00267 CHECK( box_equal( iter, -5, -4, -1, -1, 0, 1 ) ); 00268 00269 // split plane (3), leaf [1] 00270 plane.norm = AdaptiveKDTree::Y; 00271 plane.coord = -2.0; 00272 rval = tool.split_leaf( iter, plane ); 00273 CHECK( MB_SUCCESS == rval ); 00274 CHECK( box_equal( iter, -5, -4, -1, -1, -2, 1 ) ); 00275 if( leaves ) leaves[1] = iter.handle(); 00276 00277 // leaf [2] 00278 rval = iter.step(); 00279 CHECK( MB_SUCCESS == rval ); 00280 CHECK( box_equal( iter, -5, -2, -1, -1, 0, 1 ) ); 00281 if( leaves ) leaves[2] = iter.handle(); 00282 00283 // non-leaf right of split plane (2) 00284 rval = iter.step(); 00285 CHECK( MB_SUCCESS == rval ); 00286 CHECK( box_equal( iter, -1, -4, -1, 5, 0, 1 ) ); 00287 00288 // split plane (4) and leaf [3] 00289 plane.norm = AdaptiveKDTree::X; 00290 plane.coord = 4.0; 00291 rval = tool.split_leaf( iter, plane ); 00292 CHECK( MB_SUCCESS == rval ); 00293 CHECK( box_equal( iter, -1, -4, -1, 4, 0, 1 ) ); 00294 if( leaves ) leaves[3] = iter.handle(); 00295 00296 // leaf [4] 00297 rval = iter.step(); 00298 CHECK( MB_SUCCESS == rval ); 00299 CHECK( box_equal( iter, 4, -4, -1, 5, 0, 1 ) ); 00300 if( leaves ) leaves[4] = iter.handle(); 00301 00302 // non-leaf above split plane (1) 00303 rval = iter.step(); 00304 CHECK( MB_SUCCESS == rval ); 00305 CHECK( box_equal( iter, -5, 0, -1, 5, 4, 1 ) ); 00306 00307 // split plane (5) 00308 plane.norm = AdaptiveKDTree::X; 00309 plane.coord = 0.0; 00310 rval = tool.split_leaf( iter, plane ); 00311 CHECK( MB_SUCCESS == rval ); 00312 CHECK( box_equal( iter, -5, 0, -1, 0, 4, 1 ) ); 00313 00314 // split plane (6) and leaf [5] 00315 plane.norm = AdaptiveKDTree::X; 00316 plane.coord = -3.0; 00317 rval = tool.split_leaf( iter, plane ); 00318 CHECK( MB_SUCCESS == rval ); 00319 CHECK( box_equal( iter, -5, 0, -1, -3, 4, 1 ) ); 00320 if( leaves ) leaves[5] = iter.handle(); 00321 00322 // leaf [6]; 00323 rval = iter.step(); 00324 CHECK( MB_SUCCESS == rval ); 00325 CHECK( box_equal( iter, -3, 0, -1, 0, 4, 1 ) ); 00326 if( leaves ) leaves[6] = iter.handle(); 00327 00328 // non-leaf right of split plane (5) 00329 rval = iter.step(); 00330 CHECK( MB_SUCCESS == rval ); 00331 CHECK( box_equal( iter, 0, 0, -1, 5, 4, 1 ) ); 00332 00333 // split plane (7) and leaf [7] 00334 plane.norm = AdaptiveKDTree::Y; 00335 plane.coord = 3.0; 00336 rval = tool.split_leaf( iter, plane ); 00337 CHECK( MB_SUCCESS == rval ); 00338 CHECK( box_equal( iter, 0, 0, -1, 5, 3, 1 ) ); 00339 if( leaves ) leaves[7] = iter.handle(); 00340 00341 // leaf [8]; 00342 rval = iter.step(); 00343 CHECK( MB_SUCCESS == rval ); 00344 CHECK( box_equal( iter, 0, 3, -1, 5, 4, 1 ) ); 00345 if( leaves ) leaves[8] = iter.handle(); 00346 00347 // the end 00348 rval = iter.step(); 00349 CHECK( MB_ENTITY_NOT_FOUND == rval ); 00350 } 00351 00352 void leaf_iterator_test() 00353 { 00354 ErrorCode rval; 00355 Core moab; 00356 Interface* mb = &moab; 00357 AdaptiveKDTree tool( mb ); 00358 00359 // create a single-node tree 00360 EntityHandle root; 00361 double min[3] = { -3, -2, -1 }; 00362 double max[3] = { 1, 2, 3 }; 00363 rval = tool.create_root( min, max, root ); 00364 CHECK( MB_SUCCESS == rval ); 00365 00366 // get iterator for tree 00367 AdaptiveKDTreeIter iter; 00368 rval = tool.get_tree_iterator( root, iter ); 00369 CHECK( MB_SUCCESS == rval ); 00370 CHECK( box_equal( iter, -3, -2, -1, 1, 2, 3 ) ); 00371 00372 // check that steping the iterator fails correctly. 00373 rval = iter.step(); 00374 CHECK( MB_ENTITY_NOT_FOUND == rval ); 00375 rval = iter.step(); 00376 CHECK( MB_SUCCESS != rval ); 00377 00378 rval = tool.reset_tree(); 00379 CHECK( MB_SUCCESS == rval ); 00380 root = 0; 00381 00382 // construct a simple 2D tree for remaining tests 00383 EntityHandle leaves[9]; 00384 create_simple_2d_tree( tool, root, leaves ); 00385 00386 /**** Now traverse tree again, and check neighbors of each leaf *****/ 00387 std::vector< AdaptiveKDTreeIter > list; 00388 00389 // leaf [1] 00390 00391 rval = tool.get_tree_iterator( root, iter ); 00392 CHECK( MB_SUCCESS == rval ); 00393 CHECK( box_equal( iter, -5, -4, -1, -1, -2, 1 ) ); 00394 CHECK( iter.handle() == leaves[1] ); 00395 00396 list.clear(); 00397 rval = iter.get_neighbors( AdaptiveKDTree::X, true, list ); 00398 CHECK( MB_SUCCESS == rval ); 00399 CHECK( list.empty() ); 00400 00401 list.clear(); 00402 rval = iter.get_neighbors( AdaptiveKDTree::X, false, list ); 00403 CHECK( MB_SUCCESS == rval ); 00404 CHECK( list.size() == 1 ); 00405 // should be leaf [3] 00406 CHECK( box_equal( list.front(), -1, -4, -1, 4, 0, 1 ) ); 00407 CHECK( list.front().handle() == leaves[3] ); 00408 00409 list.clear(); 00410 rval = iter.get_neighbors( AdaptiveKDTree::Y, true, list ); 00411 CHECK( MB_SUCCESS == rval ); 00412 CHECK( list.empty() ); 00413 00414 list.clear(); 00415 rval = iter.get_neighbors( AdaptiveKDTree::Y, false, list ); 00416 CHECK( MB_SUCCESS == rval ); 00417 CHECK( list.size() == 1 ); 00418 // should be leaf [2] 00419 CHECK( box_equal( list.front(), -5, -2, -1, -1, 0, 1 ) ); 00420 CHECK( list.front().handle() == leaves[2] ); 00421 00422 list.clear(); 00423 rval = iter.get_neighbors( AdaptiveKDTree::Z, true, list ); 00424 CHECK( MB_SUCCESS == rval ); 00425 CHECK( list.empty() ); 00426 00427 list.clear(); 00428 rval = iter.get_neighbors( AdaptiveKDTree::Z, false, list ); 00429 CHECK( MB_SUCCESS == rval ); 00430 CHECK( list.empty() ); 00431 00432 // leaf [2] 00433 00434 rval = iter.step(); 00435 CHECK( MB_SUCCESS == rval ); 00436 CHECK( box_equal( iter, -5, -2, -1, -1, 0, 1 ) ); 00437 CHECK( iter.handle() == leaves[2] ); 00438 00439 list.clear(); 00440 rval = iter.get_neighbors( AdaptiveKDTree::X, true, list ); 00441 CHECK( MB_SUCCESS == rval ); 00442 CHECK( list.empty() ); 00443 00444 list.clear(); 00445 rval = iter.get_neighbors( AdaptiveKDTree::X, false, list ); 00446 CHECK( MB_SUCCESS == rval ); 00447 CHECK( list.size() == 1 ); 00448 // should be leaf [3] 00449 CHECK( box_equal( list.front(), -1, -4, -1, 4, 0, 1 ) ); 00450 CHECK( list.front().handle() == leaves[3] ); 00451 00452 list.clear(); 00453 rval = iter.get_neighbors( AdaptiveKDTree::Y, true, list ); 00454 CHECK( MB_SUCCESS == rval ); 00455 // should be leaf [1] 00456 CHECK( list.size() == 1 ); 00457 CHECK( box_equal( list.front(), -5, -4, -1, -1, -2, 1 ) ); 00458 CHECK( list.front().handle() == leaves[1] ); 00459 00460 list.clear(); 00461 rval = iter.get_neighbors( AdaptiveKDTree::Y, false, list ); 00462 CHECK( MB_SUCCESS == rval ); 00463 CHECK( list.size() == 2 ); 00464 // should be leaf [5] and leaf[6] 00465 if( list[0].handle() == leaves[6] ) std::swap( list[0], list[1] ); 00466 CHECK( list[0].handle() == leaves[5] ); 00467 CHECK( list[1].handle() == leaves[6] ); 00468 CHECK( box_equal( list[0], -5, 0, -1, -3, 4, 1 ) ); 00469 CHECK( box_equal( list[1], -3, 0, -1, 0, 4, 1 ) ); 00470 00471 list.clear(); 00472 rval = iter.get_neighbors( AdaptiveKDTree::Z, true, list ); 00473 CHECK( MB_SUCCESS == rval ); 00474 CHECK( list.empty() ); 00475 00476 list.clear(); 00477 rval = iter.get_neighbors( AdaptiveKDTree::Z, false, list ); 00478 CHECK( MB_SUCCESS == rval ); 00479 CHECK( list.empty() ); 00480 00481 // leaf [3] 00482 rval = iter.step(); 00483 CHECK( MB_SUCCESS == rval ); 00484 CHECK( box_equal( iter, -1, -4, -1, 4, 0, 1 ) ); 00485 CHECK( iter.handle() == leaves[3] ); 00486 00487 // leaf [4] 00488 rval = iter.step(); 00489 CHECK( MB_SUCCESS == rval ); 00490 CHECK( box_equal( iter, 4, -4, -1, 5, 0, 1 ) ); 00491 CHECK( iter.handle() == leaves[4] ); 00492 00493 // leaf [5] 00494 rval = iter.step(); 00495 CHECK( MB_SUCCESS == rval ); 00496 CHECK( box_equal( iter, -5, 0, -1, -3, 4, 1 ) ); 00497 CHECK( iter.handle() == leaves[5] ); 00498 00499 // leaf [6] 00500 rval = iter.step(); 00501 CHECK( MB_SUCCESS == rval ); 00502 CHECK( box_equal( iter, -3, 0, -1, 0, 4, 1 ) ); 00503 CHECK( iter.handle() == leaves[6] ); 00504 00505 // leaf [7] 00506 rval = iter.step(); 00507 CHECK( MB_SUCCESS == rval ); 00508 CHECK( box_equal( iter, 0, 0, -1, 5, 3, 1 ) ); 00509 CHECK( iter.handle() == leaves[7] ); 00510 00511 // leaf [8] 00512 rval = iter.step(); 00513 CHECK( MB_SUCCESS == rval ); 00514 CHECK( box_equal( iter, 0, 3, -1, 5, 4, 1 ) ); 00515 CHECK( iter.handle() == leaves[8] ); 00516 } 00517 00518 void test_tree_merge_nodes() 00519 { 00520 // build simple tree for tests 00521 ErrorCode rval; 00522 Core moab; 00523 Interface* mb = &moab; 00524 AdaptiveKDTree tool( mb ); 00525 EntityHandle root; 00526 EntityHandle leaves[9]; 00527 create_simple_2d_tree( tool, root, leaves ); 00528 00529 // get iterator for tree 00530 AdaptiveKDTreeIter iter; 00531 rval = tool.get_tree_iterator( root, iter ); 00532 CHECK( MB_SUCCESS == rval ); 00533 00534 // merge leaves 1 and 2 00535 rval = tool.merge_leaf( iter ); 00536 CHECK( MB_SUCCESS == rval ); 00537 CHECK( box_equal( iter, -5, -4, -1, -1, 0, 1 ) ); 00538 00539 // merge leaf 1,2 with 3,4 (implicity merges 3 and 4) 00540 rval = tool.merge_leaf( iter ); 00541 CHECK( MB_SUCCESS == rval ); 00542 CHECK( box_equal( iter, -5, -4, -1, 5, 0, 1 ) ); 00543 00544 // make sure iterator remains valid 00545 rval = iter.step(); 00546 CHECK( MB_SUCCESS == rval ); 00547 // leaf 5 00548 CHECK( box_equal( iter, -5, 0, -1, -3, 4, 1 ) ); 00549 CHECK( iter.handle() == leaves[5] ); 00550 } 00551 00552 void test_build_tree_bisect_triangles() 00553 { 00554 Core moab; 00555 AdaptiveKDTree tool( &moab ); 00556 Range box_tris; 00557 00558 std::ostringstream options; 00559 options << "MAX_PER_LEAF=1;SPLITS_PER_DIR=1;PLANE_SET=0;"; 00560 FileOptions opts( options.str().c_str() ); 00561 EntityHandle root; 00562 ErrorCode rval; 00563 00564 moab.delete_mesh(); 00565 box_tris.clear(); 00566 build_triangle_box_small( &moab, box_tris ); 00567 rval = tool.build_tree( box_tris, &root, &opts ); 00568 CHECK( MB_SUCCESS == rval ); 00569 test_valid_tree( &tool, root, opts, box_tris ); 00570 tool.reset_tree(); 00571 00572 moab.delete_mesh(); 00573 box_tris.clear(); 00574 build_triangle_octahedron( &moab, box_tris ); 00575 rval = tool.build_tree( box_tris, &root, &opts ); 00576 CHECK( MB_SUCCESS == rval ); 00577 test_valid_tree( &tool, root, opts, box_tris ); 00578 tool.reset_tree(); 00579 00580 moab.delete_mesh(); 00581 box_tris.clear(); 00582 build_triangle_box_large( &moab, box_tris ); 00583 rval = tool.build_tree( box_tris, &root, &opts ); 00584 CHECK( MB_SUCCESS == rval ); 00585 test_valid_tree( &tool, root, opts, box_tris ); 00586 tool.reset_tree(); 00587 00588 options << "MAX_DEPTH=2;"; 00589 opts = FileOptions( options.str().c_str() ); 00590 build_triangle_box_large( &moab, box_tris ); 00591 rval = tool.build_tree( box_tris, &root, &opts ); 00592 CHECK( MB_SUCCESS == rval ); 00593 test_valid_tree( &tool, root, opts, box_tris ); 00594 tool.reset_tree(); 00595 } 00596 00597 void test_closest_triangle() 00598 { 00599 Core moab; 00600 AdaptiveKDTree tool( &moab ); 00601 Range box_tris; 00602 00603 std::ostringstream options; 00604 options << "MAX_PER_LEAF=1;SPLITS_PER_DIR=1;PLANE_SET=0;"; 00605 FileOptions opts( options.str().c_str() ); 00606 EntityHandle root; 00607 ErrorCode rval; 00608 EntityHandle tri; 00609 00610 moab.delete_mesh(); 00611 box_tris.clear(); 00612 build_triangle_box_small( &moab, box_tris ); 00613 rval = tool.build_tree( box_tris, &root, &opts ); 00614 CHECK( MB_SUCCESS == rval ); 00615 test_valid_tree( &tool, root, opts, box_tris ); 00616 00617 // test closest to each corner of the box. 00618 for( unsigned i = 0; i < 8; ++i ) 00619 { 00620 int x = i & 1 ? 1 : -1; 00621 int y = i & 2 ? 1 : -1; 00622 int z = i & 4 ? 1 : -1; 00623 double coords[] = { 2.0 * x, 2.0 * y, 2.0 * z }; 00624 CartVect point; 00625 rval = tool.closest_triangle( root, coords, point.array(), tri ); 00626 CHECK( MB_SUCCESS == rval ); 00627 // check result position 00628 CHECK( fabs( x - point[0] ) < 1e-6 ); 00629 CHECK( fabs( y - point[1] ) < 1e-6 ); 00630 CHECK( fabs( z - point[2] ) < 1e-6 ); 00631 // check point is at triangle vertex 00632 check_common_vertex( tool.moab(), &tri, 1, point ); 00633 } 00634 00635 // test location on each face 00636 const CartVect facepts[] = { CartVect( -1.0, 0.5, 0.5 ), CartVect( 1.0, 0.5, 0.5 ), CartVect( 0.5, -1.0, 0.5 ), 00637 CartVect( 0.5, 1.0, 0.5 ), CartVect( 0.5, 0.5, -1.0 ), CartVect( 0.5, 0.5, 1.0 ) }; 00638 for( unsigned i = 0; i < 6; ++i ) 00639 { 00640 CartVect point; 00641 rval = tool.closest_triangle( root, facepts[i].array(), point.array(), tri ); 00642 CHECK( MB_SUCCESS == rval ); 00643 // check result position 00644 const CartVect diff = facepts[i] - point; 00645 CHECK( fabs( diff[0] ) < 1e-6 ); 00646 CHECK( fabs( diff[1] ) < 1e-6 ); 00647 CHECK( fabs( diff[2] ) < 1e-6 ); 00648 // check that point is contained within triangle 00649 check_point_in_triangles( tool.moab(), &tri, 1, point ); 00650 } 00651 00652 // test a location really far from the tree 00653 { 00654 const double far[] = { 0.75, 0.75, 200 }; 00655 CartVect point; 00656 rval = tool.closest_triangle( root, far, point.array(), tri ); 00657 CHECK( MB_SUCCESS == rval ); 00658 CHECK( fabs( point[0] - 0.75 ) < 1e-6 ); 00659 CHECK( fabs( point[1] - 0.75 ) < 1e-6 ); 00660 CHECK( fabs( point[2] - 1.00 ) < 1e-6 ); 00661 // check that point is contained within triangle 00662 check_point_in_triangles( tool.moab(), &tri, 1, point ); 00663 } 00664 00665 // now do it all again with a lot more triangles 00666 tool.reset_tree(); 00667 moab.delete_mesh(); 00668 box_tris.clear(); 00669 00670 build_triangle_box_large( &moab, box_tris ); 00671 rval = tool.build_tree( box_tris, &root, &opts ); 00672 CHECK( MB_SUCCESS == rval ); 00673 test_valid_tree( &tool, root, opts, box_tris ); 00674 00675 // test closest to each corner of the box. 00676 for( unsigned i = 0; i < 8; ++i ) 00677 { 00678 int x = i & 1 ? 1 : -1; 00679 int y = i & 2 ? 1 : -1; 00680 int z = i & 4 ? 1 : -1; 00681 double coords[] = { 4.0 * x, 4.0 * y, 4.0 * z }; 00682 CartVect point; 00683 rval = tool.closest_triangle( root, coords, point.array(), tri ); 00684 CHECK( MB_SUCCESS == rval ); 00685 // check result position 00686 CHECK( fabs( 3.0 * x - point[0] ) < 1e-6 ); 00687 CHECK( fabs( 3.0 * y - point[1] ) < 1e-6 ); 00688 CHECK( fabs( 3.0 * z - point[2] ) < 1e-6 ); 00689 // check point is at triangle vertex 00690 check_common_vertex( tool.moab(), &tri, 1, point ); 00691 } 00692 00693 // test location on each face 00694 const CartVect facepts2[] = { CartVect( -3.0, 0.5, 0.5 ), CartVect( 3.0, 0.5, 0.5 ), CartVect( 0.5, -3.0, 0.5 ), 00695 CartVect( 0.5, 3.0, 0.5 ), CartVect( 0.5, 0.5, -3.0 ), CartVect( 0.5, 0.5, 3.0 ) }; 00696 for( unsigned i = 0; i < 6; ++i ) 00697 { 00698 CartVect point; 00699 rval = tool.closest_triangle( root, facepts2[i].array(), point.array(), tri ); 00700 CHECK( MB_SUCCESS == rval ); 00701 // check result position 00702 const CartVect diff = facepts2[i] - point; 00703 CHECK( fabs( diff[0] ) < 1e-6 ); 00704 CHECK( fabs( diff[1] ) < 1e-6 ); 00705 CHECK( fabs( diff[2] ) < 1e-6 ); 00706 // check that point is contained within triangle 00707 check_point_in_triangles( tool.moab(), &tri, 1, point ); 00708 } 00709 00710 // test a location really far from the tree 00711 { 00712 const double far[] = { 2.75, 2.75, 200 }; 00713 CartVect point; 00714 rval = tool.closest_triangle( root, far, point.array(), tri ); 00715 CHECK( MB_SUCCESS == rval ); 00716 CHECK( fabs( point[0] - 2.75 ) < 1e-6 ); 00717 CHECK( fabs( point[1] - 2.75 ) < 1e-6 ); 00718 CHECK( fabs( point[2] - 3.00 ) < 1e-6 ); 00719 // check that point is contained within triangle 00720 check_point_in_triangles( tool.moab(), &tri, 1, point ); 00721 } 00722 } 00723 00724 void test_sphere_intersect_triangles() 00725 { 00726 Core moab; 00727 AdaptiveKDTree tool( &moab ); 00728 Range box_tris; 00729 00730 std::ostringstream options; 00731 options << "MAX_PER_LEAF=1;SPLITS_PER_DIR=1;PLANE_SET=0;"; 00732 FileOptions opts( options.str().c_str() ); 00733 EntityHandle root; 00734 ErrorCode rval; 00735 std::vector< EntityHandle > triangles; 00736 00737 moab.delete_mesh(); 00738 box_tris.clear(); 00739 build_triangle_box_small( &moab, box_tris ); 00740 rval = tool.build_tree( box_tris, &root, &opts ); 00741 CHECK( MB_SUCCESS == rval ); 00742 test_valid_tree( &tool, root, opts, box_tris ); 00743 00744 // test closest to each corner of the box. 00745 for( unsigned i = 0; i < 8; ++i ) 00746 { 00747 double x = i & 1 ? 1 : -1; 00748 double y = i & 2 ? 1 : -1; 00749 double z = i & 4 ? 1 : -1; 00750 double center[] = { x, y, z }; 00751 triangles.clear(); 00752 rval = tool.sphere_intersect_triangles( root, center, 0.26, triangles ); 00753 CHECK( MB_SUCCESS == rval ); 00754 // expect 3 to 6 triangles, depending on the corner 00755 CHECK( triangles.size() >= 3 ); 00756 CHECK( triangles.size() <= 6 ); 00757 // check point is at the same vertex for each triangle 00758 check_common_vertex( tool.moab(), &triangles[0], triangles.size(), CartVect( center ) ); 00759 } 00760 00761 // now do it all again with a lot more triangles 00762 00763 tool.reset_tree(); 00764 moab.delete_mesh(); 00765 box_tris.clear(); 00766 build_triangle_box_large( &moab, box_tris ); 00767 00768 rval = tool.build_tree( box_tris, &root, &opts ); 00769 CHECK( MB_SUCCESS == rval ); 00770 test_valid_tree( &tool, root, opts, box_tris ); 00771 00772 // test closest to each corner of the box. 00773 for( unsigned i = 0; i < 8; ++i ) 00774 { 00775 int x = i & 1 ? 1 : -1; 00776 int y = i & 2 ? 1 : -1; 00777 int z = i & 4 ? 1 : -1; 00778 double center[] = { 3.0 * x, 3.0 * y, 3.0 * z }; 00779 triangles.clear(); 00780 rval = tool.sphere_intersect_triangles( root, center, 0.26, triangles ); 00781 CHECK( MB_SUCCESS == rval ); 00782 // expect 3 to 6 triangles, depending on the corner 00783 CHECK( triangles.size() >= 3 ); 00784 CHECK( triangles.size() <= 6 ); 00785 // check point is at the same vertex for each triangle 00786 check_common_vertex( tool.moab(), &triangles[0], triangles.size(), CartVect( center ) ); 00787 } 00788 } 00789 00790 void test_ray_intersect_triangles() 00791 { 00792 Core moab; 00793 AdaptiveKDTree tool( &moab ); 00794 Range box_tris; 00795 00796 std::ostringstream options; 00797 options << "MAX_PER_LEAF=1;SPLITS_PER_DIR=1;PLANE_SET=0;"; 00798 FileOptions opts( options.str().c_str() ); 00799 EntityHandle root; 00800 ErrorCode rval; 00801 std::vector< EntityHandle > tris; 00802 std::vector< double > dists; 00803 00804 moab.delete_mesh(); 00805 box_tris.clear(); 00806 build_triangle_box_small( &moab, box_tris ); 00807 rval = tool.build_tree( box_tris, &root, &opts ); 00808 CHECK( MB_SUCCESS == rval ); 00809 test_valid_tree( &tool, root, opts, box_tris ); 00810 00811 // test ray through box parallel to X axis 00812 CartVect dir( 1, 0, 0 ); 00813 CartVect pt( -2, 0.75, 0.75 ); 00814 tris.clear(); 00815 dists.clear(); 00816 rval = tool.ray_intersect_triangles( root, 1e-6, dir.array(), pt.array(), tris, dists ); 00817 CHECK( MB_SUCCESS == rval ); 00818 CHECK( tris.size() == 3 ); 00819 CHECK( dists.size() == tris.size() ); 00820 for( unsigned i = 0; i < dists.size(); ++i ) 00821 { 00822 CHECK( fabs( dists[i] - 1 ) < 1e-6 || fabs( dists[i] - 3 ) < 1e-6 ); 00823 CartVect tript = pt + dists[i] * dir; 00824 check_point_in_triangles( &moab, &tris[i], 1, tript ); 00825 } 00826 00827 // test ray through box parallel to X axis, closest tri only 00828 tris.clear(); 00829 dists.clear(); 00830 rval = tool.ray_intersect_triangles( root, 1e-6, dir.array(), pt.array(), tris, dists, 1 ); 00831 CHECK( MB_SUCCESS == rval ); 00832 CHECK( tris.size() == 1 ); 00833 CHECK( dists.size() == tris.size() ); 00834 CHECK( fabs( dists[0] - 1 ) < 1e-6 ); 00835 check_point_in_triangles( &moab, &tris[0], 1, pt + dists[0] * dir ); 00836 00837 // test ray ending within box, parallel to X axis 00838 tris.clear(); 00839 dists.clear(); 00840 rval = tool.ray_intersect_triangles( root, 1e-6, dir.array(), pt.array(), tris, dists, 0, 2.0 ); 00841 CHECK( MB_SUCCESS == rval ); 00842 CHECK( tris.size() == 1 ); 00843 CHECK( dists.size() == tris.size() ); 00844 CHECK( fabs( dists[0] - 1 ) < 1e-6 ); 00845 check_point_in_triangles( &moab, &tris[0], 1, pt + dists[0] * dir ); 00846 00847 // test ray starting within box parallel to X axis 00848 tris.clear(); 00849 dists.clear(); 00850 pt = CartVect( 0, .75, .75 ); 00851 rval = tool.ray_intersect_triangles( root, 1e-6, dir.array(), pt.array(), tris, dists ); 00852 CHECK( MB_SUCCESS == rval ); 00853 CHECK( tris.size() == 2 ); 00854 CHECK( dists.size() == tris.size() ); 00855 for( unsigned i = 0; i < dists.size(); ++i ) 00856 { 00857 CHECK( fabs( dists[i] - 1 ) < 1e-6 ); 00858 CartVect tript = pt + dists[i] * dir; 00859 check_point_in_triangles( &moab, &tris[i], 1, tript ); 00860 } 00861 00862 // test skew ray through box 00863 dir = CartVect( 0.5 * sqrt( 2.0 ), 0.5 * sqrt( 2.0 ), 0.0 ); 00864 pt = CartVect( 0, -1.5, 0 ); 00865 tris.clear(); 00866 dists.clear(); 00867 rval = tool.ray_intersect_triangles( root, 1e-6, dir.array(), pt.array(), tris, dists ); 00868 CHECK( MB_SUCCESS == rval ); 00869 CHECK( tris.size() == 2 ); 00870 CHECK( dists.size() == tris.size() ); 00871 if( dists[0] < dists[1] ) 00872 { 00873 CHECK( fabs( dists[0] - 0.5 * sqrt( 2.0 ) ) < 1e-6 ); 00874 CHECK( fabs( dists[1] - sqrt( 2.0 ) ) < 1e-6 ); 00875 } 00876 check_point_in_triangles( &moab, &tris[0], 1, pt + dists[0] * dir ); 00877 check_point_in_triangles( &moab, &tris[1], 1, pt + dists[1] * dir ); 00878 00879 // test ray through box parallel to -Y axis 00880 dir = CartVect( 0, -1, 0 ); 00881 pt = CartVect( 0, 2, 0 ); 00882 tris.clear(); 00883 dists.clear(); 00884 rval = tool.ray_intersect_triangles( root, 1e-6, dir.array(), pt.array(), tris, dists ); 00885 CHECK( MB_SUCCESS == rval ); 00886 CHECK( tris.size() == 4 ); 00887 CHECK( dists.size() == tris.size() ); 00888 for( unsigned i = 0; i < dists.size(); ++i ) 00889 { 00890 CHECK( fabs( dists[i] - 1 ) < 1e-6 || fabs( dists[i] - 3 ) < 1e-6 ); 00891 CartVect tript = pt + dists[i] * dir; 00892 check_point_in_triangles( &moab, &tris[i], 1, tript ); 00893 } 00894 00895 // test ray through box parallel to Z axis 00896 dir = CartVect( 0, 0, 1 ); 00897 pt = CartVect( 0, 0, -2 ); 00898 tris.clear(); 00899 dists.clear(); 00900 rval = tool.ray_intersect_triangles( root, 1e-6, dir.array(), pt.array(), tris, dists ); 00901 CHECK( MB_SUCCESS == rval ); 00902 CHECK( tris.size() == 4 ); 00903 CHECK( dists.size() == tris.size() ); 00904 for( unsigned i = 0; i < dists.size(); ++i ) 00905 { 00906 CHECK( fabs( dists[i] - 1 ) < 1e-6 || fabs( dists[i] - 3 ) < 1e-6 ); 00907 CartVect tript = pt + dists[i] * dir; 00908 check_point_in_triangles( &moab, &tris[i], 1, tript ); 00909 } 00910 00911 // test ray through box parallel to Z axis, limit 2 first 2 intersections 00912 tris.clear(); 00913 dists.clear(); 00914 rval = tool.ray_intersect_triangles( root, 1e-6, dir.array(), pt.array(), tris, dists, 2 ); 00915 CHECK( MB_SUCCESS == rval ); 00916 CHECK( tris.size() == 2 ); 00917 CHECK( dists.size() == tris.size() ); 00918 for( unsigned i = 0; i < dists.size(); ++i ) 00919 { 00920 CHECK( fabs( dists[i] - 1 ) < 1e-6 ); 00921 CartVect tript = pt + dists[i] * dir; 00922 check_point_in_triangles( &moab, &tris[i], 1, tript ); 00923 } 00924 } 00925 00926 void test_leaf_volume() 00927 { 00928 Core moab; 00929 AdaptiveKDTree tool( &moab ); 00930 EntityHandle root; 00931 00932 create_simple_2d_tree( tool, root ); 00933 AdaptiveKDTreeIter iter; 00934 ErrorCode rval = tool.get_tree_iterator( root, iter );CHECK_ERR( rval ); 00935 00936 CHECK_REAL_EQUAL( 16.0, iter.volume(), 1e-12 ); // 1 00937 CHECK_ERR( iter.step() ); 00938 CHECK_REAL_EQUAL( 16.0, iter.volume(), 1e-12 ); // 2 00939 CHECK_ERR( iter.step() ); 00940 CHECK_REAL_EQUAL( 40.0, iter.volume(), 1e-12 ); // 3 00941 CHECK_ERR( iter.step() ); 00942 CHECK_REAL_EQUAL( 8.0, iter.volume(), 1e-12 ); // 4 00943 CHECK_ERR( iter.step() ); 00944 CHECK_REAL_EQUAL( 16.0, iter.volume(), 1e-12 ); // 5 00945 CHECK_ERR( iter.step() ); 00946 CHECK_REAL_EQUAL( 24.0, iter.volume(), 1e-12 ); // 6 00947 CHECK_ERR( iter.step() ); 00948 CHECK_REAL_EQUAL( 30.0, iter.volume(), 1e-12 ); // 7 00949 CHECK_ERR( iter.step() ); 00950 CHECK_REAL_EQUAL( 10.0, iter.volume(), 1e-12 ); // 8 00951 } 00952 00953 void test_leaf_sibling() 00954 { 00955 ErrorCode rval; 00956 Core moab; 00957 AdaptiveKDTree tool( &moab ); 00958 EntityHandle root; 00959 00960 create_simple_2d_tree( tool, root ); 00961 AdaptiveKDTreeIter iter1, iter2; 00962 rval = tool.get_tree_iterator( root, iter1 );CHECK_ERR( rval ); 00963 rval = tool.get_tree_iterator( root, iter2 );CHECK_ERR( rval ); 00964 00965 // iter1 == 1, iter2 == 1 00966 CHECK( !iter1.is_sibling( iter1 ) ); 00967 CHECK( !iter1.is_sibling( iter1.handle() ) ); 00968 CHECK( !iter1.is_sibling( iter2 ) ); 00969 CHECK( iter1.sibling_is_forward() ); 00970 00971 // iter1 == 1, iter2 == 2 00972 rval = iter2.step();CHECK_ERR( rval ); 00973 CHECK( iter1.is_sibling( iter2 ) ); 00974 CHECK( iter1.is_sibling( iter2.handle() ) ); 00975 CHECK( iter2.is_sibling( iter1 ) ); 00976 CHECK( iter2.is_sibling( iter1.handle() ) ); 00977 CHECK( !iter2.sibling_is_forward() ); 00978 00979 // iter1 == 1, iter2 == 3 00980 rval = iter2.step();CHECK_ERR( rval ); 00981 CHECK( !iter1.is_sibling( iter2 ) ); 00982 CHECK( !iter1.is_sibling( iter2.handle() ) ); 00983 CHECK( !iter2.is_sibling( iter1 ) ); 00984 CHECK( !iter2.is_sibling( iter1.handle() ) ); 00985 CHECK( iter2.sibling_is_forward() ); 00986 00987 // iter1 == 2, iter2 == 3 00988 rval = iter1.step();CHECK_ERR( rval ); 00989 CHECK( !iter1.is_sibling( iter2 ) ); 00990 CHECK( !iter1.is_sibling( iter2.handle() ) ); 00991 CHECK( !iter2.is_sibling( iter1 ) ); 00992 CHECK( !iter2.is_sibling( iter1.handle() ) ); 00993 CHECK( !iter1.sibling_is_forward() ); 00994 00995 // iter1 == 4, iter2 == 3 00996 rval = iter1.step();CHECK_ERR( rval ); 00997 CHECK_EQUAL( iter1.handle(), iter2.handle() ); 00998 rval = iter1.step();CHECK_ERR( rval ); 00999 CHECK( iter1.is_sibling( iter2 ) ); 01000 CHECK( iter1.is_sibling( iter2.handle() ) ); 01001 CHECK( iter2.is_sibling( iter1 ) ); 01002 CHECK( iter2.is_sibling( iter1.handle() ) ); 01003 CHECK( !iter1.sibling_is_forward() ); 01004 } 01005 01006 void test_leaf_intersects_plane() 01007 { 01008 ErrorCode rval; 01009 Core moab; 01010 AdaptiveKDTree tool( &moab ); 01011 01012 EntityHandle root; 01013 const double min[3] = { -5, -4, -1 }; 01014 const double max[3] = { 1, 2, 3 }; 01015 rval = tool.create_root( min, max, root );CHECK_ERR( rval ); 01016 01017 AdaptiveKDTreeIter iter; 01018 rval = tool.get_tree_iterator( root, iter );CHECK_ERR( rval ); 01019 01020 AdaptiveKDTree::Plane x1 = { min[0] - 1, AdaptiveKDTree::X }; 01021 CHECK( !iter.intersects( x1 ) ); 01022 AdaptiveKDTree::Plane x2 = { min[0], AdaptiveKDTree::X }; 01023 CHECK( iter.intersects( x2 ) ); 01024 AdaptiveKDTree::Plane x3 = { min[0] + 1, AdaptiveKDTree::X }; 01025 CHECK( iter.intersects( x3 ) ); 01026 AdaptiveKDTree::Plane x4 = { max[0] - 1, AdaptiveKDTree::X }; 01027 CHECK( iter.intersects( x4 ) ); 01028 AdaptiveKDTree::Plane x5 = { max[0], AdaptiveKDTree::X }; 01029 CHECK( iter.intersects( x5 ) ); 01030 AdaptiveKDTree::Plane x6 = { max[0] + 1, AdaptiveKDTree::X }; 01031 CHECK( !iter.intersects( x6 ) ); 01032 01033 AdaptiveKDTree::Plane y1 = { min[1] - 1, AdaptiveKDTree::Y }; 01034 CHECK( !iter.intersects( y1 ) ); 01035 AdaptiveKDTree::Plane y2 = { min[1], AdaptiveKDTree::Y }; 01036 CHECK( iter.intersects( y2 ) ); 01037 AdaptiveKDTree::Plane y3 = { min[1] + 1, AdaptiveKDTree::Y }; 01038 CHECK( iter.intersects( y3 ) ); 01039 AdaptiveKDTree::Plane y4 = { max[1] - 1, AdaptiveKDTree::Y }; 01040 CHECK( iter.intersects( y4 ) ); 01041 AdaptiveKDTree::Plane y5 = { max[1], AdaptiveKDTree::Y }; 01042 CHECK( iter.intersects( y5 ) ); 01043 AdaptiveKDTree::Plane y6 = { max[1] + 1, AdaptiveKDTree::Y }; 01044 CHECK( !iter.intersects( y6 ) ); 01045 01046 AdaptiveKDTree::Plane z1 = { min[2] - 1, AdaptiveKDTree::Z }; 01047 CHECK( !iter.intersects( z1 ) ); 01048 AdaptiveKDTree::Plane z2 = { min[2], AdaptiveKDTree::Z }; 01049 CHECK( iter.intersects( z2 ) ); 01050 AdaptiveKDTree::Plane z3 = { min[2] + 1, AdaptiveKDTree::Z }; 01051 CHECK( iter.intersects( z3 ) ); 01052 AdaptiveKDTree::Plane z4 = { max[2] - 1, AdaptiveKDTree::Z }; 01053 CHECK( iter.intersects( z4 ) ); 01054 AdaptiveKDTree::Plane z5 = { max[2], AdaptiveKDTree::Z }; 01055 CHECK( iter.intersects( z5 ) ); 01056 AdaptiveKDTree::Plane z6 = { max[2] + 1, AdaptiveKDTree::Z }; 01057 CHECK( !iter.intersects( z6 ) ); 01058 } 01059 01060 #define CHECK_RAY_XSECTS( PT, DIR, T_IN, T_OUT ) \ 01061 do \ 01062 { \ 01063 CHECK( iter.intersect_ray( ( PT ), ( DIR ), t_in, t_out ) ); \ 01064 CHECK_REAL_EQUAL( ( T_IN ), t_in, 1e-6 ); \ 01065 CHECK_REAL_EQUAL( ( T_OUT ), t_out, 1e-6 ); \ 01066 } while( false ) 01067 01068 void test_leaf_intersects_ray() 01069 { 01070 ErrorCode rval; 01071 Core moab; 01072 AdaptiveKDTree tool( &moab ); 01073 double t_in, t_out; 01074 01075 EntityHandle root; 01076 const double min[3] = { -5, -4, -1 }; 01077 const double max[3] = { 1, 2, 3 }; 01078 rval = tool.create_root( min, max, root );CHECK_ERR( rval ); 01079 01080 AdaptiveKDTreeIter iter; 01081 rval = tool.get_tree_iterator( root, iter );CHECK_ERR( rval ); 01082 01083 // start with point inside box 01084 const double pt1[] = { 0, 0, 0 }; 01085 const double dir1[] = { 0.1, 0.1, 0.1 }; 01086 CHECK_RAY_XSECTS( pt1, dir1, 0, 10 ); 01087 const double dir2[] = { 5, 5, 5 }; 01088 CHECK_RAY_XSECTS( pt1, dir2, 0, 0.2 ); 01089 const double pxdir[] = { 1, 0, 0 }; 01090 CHECK_RAY_XSECTS( pt1, pxdir, 0, 1 ); 01091 const double nxdir[] = { -1, 0, 0 }; 01092 CHECK_RAY_XSECTS( pt1, nxdir, 0, 5 ); 01093 const double pydir[] = { 0, 1, 0 }; 01094 CHECK_RAY_XSECTS( pt1, pydir, 0, 2 ); 01095 const double nydir[] = { 0, -1, 0 }; 01096 CHECK_RAY_XSECTS( pt1, nydir, 0, 4 ); 01097 const double pzdir[] = { 0, 0, 1 }; 01098 CHECK_RAY_XSECTS( pt1, pzdir, 0, 3 ); 01099 const double nzdir[] = { 0, 0, -1 }; 01100 CHECK_RAY_XSECTS( pt1, nzdir, 0, 1 ); 01101 01102 // point below box 01103 const double pt2[] = { 0, 0, -2 }; 01104 CHECK_RAY_XSECTS( pt2, dir1, 10, 10 ); 01105 CHECK_RAY_XSECTS( pt2, dir2, 0.2, 0.2 ); 01106 CHECK( !iter.intersect_ray( pt2, pxdir, t_in, t_out ) ); 01107 CHECK( !iter.intersect_ray( pt2, nxdir, t_in, t_out ) ); 01108 CHECK( !iter.intersect_ray( pt2, pydir, t_in, t_out ) ); 01109 CHECK( !iter.intersect_ray( pt2, nydir, t_in, t_out ) ); 01110 CHECK_RAY_XSECTS( pt2, pzdir, 1, 5 ); 01111 CHECK( !iter.intersect_ray( pt2, nzdir, t_in, t_out ) ); 01112 01113 // point right of box 01114 const double pt3[] = { 3, 0, 0 }; 01115 CHECK( !iter.intersect_ray( pt3, dir1, t_in, t_out ) ); 01116 CHECK( !iter.intersect_ray( pt3, dir2, t_in, t_out ) ); 01117 CHECK( !iter.intersect_ray( pt3, pxdir, t_in, t_out ) ); 01118 CHECK_RAY_XSECTS( pt3, nxdir, 2, 8 ); 01119 CHECK( !iter.intersect_ray( pt3, pydir, t_in, t_out ) ); 01120 CHECK( !iter.intersect_ray( pt3, nydir, t_in, t_out ) ); 01121 CHECK( !iter.intersect_ray( pt3, pzdir, t_in, t_out ) ); 01122 CHECK( !iter.intersect_ray( pt3, nzdir, t_in, t_out ) ); 01123 01124 // a few more complex test cases 01125 const double dira[] = { -3, 0, 3 }; 01126 CHECK_RAY_XSECTS( pt3, dira, 2. / 3., 1.0 ); 01127 const double dirb[] = { -2, 0, 3.1 }; 01128 CHECK( !iter.intersect_ray( pt3, dirb, t_in, t_out ) ); 01129 } 01130 01131 int main() 01132 { 01133 #ifdef MOAB_HAVE_MPI 01134 int fail = MPI_Init( 0, 0 ); 01135 if( fail ) return fail; 01136 #endif 01137 01138 int error_count = 0; 01139 01140 error_count += RUN_TEST( leaf_iterator_test ); 01141 error_count += RUN_TEST( test_build_tree_bisect_triangles ); 01142 error_count += RUN_TEST( test_closest_triangle ); 01143 error_count += RUN_TEST( test_sphere_intersect_triangles ); 01144 error_count += RUN_TEST( test_ray_intersect_triangles ); 01145 error_count += RUN_TEST( test_tree_merge_nodes ); 01146 error_count += RUN_TEST( test_leaf_volume ); 01147 error_count += RUN_TEST( test_leaf_sibling ); 01148 error_count += RUN_TEST( test_leaf_intersects_plane ); 01149 error_count += RUN_TEST( test_leaf_intersects_ray ); 01150 01151 #ifdef MOAB_HAVE_MPI 01152 fail = MPI_Finalize(); 01153 if( fail ) return fail; 01154 #endif 01155 01156 return error_count; 01157 }