MOAB: Mesh Oriented datABase  (version 5.4.1)
obb_time.cpp
Go to the documentation of this file.
00001 #include "moab/Core.hpp"
00002 #include "moab/CartVect.hpp"
00003 #include "moab/OrientedBox.hpp"
00004 #include "moab/OrientedBoxTreeTool.hpp"
00005 #include <cstdlib>
00006 #include <iostream>
00007 #include <cmath>
00008 #include <ctime>
00009 #include <csignal>
00010 #include <cassert>
00011 
00012 const int NUM_RAYS = 40000;
00013 const int NUM_XSCT = 20000;
00014 
00015 using namespace moab;
00016 
00017 static void usage()
00018 {
00019     std::cerr << "obb_time [-r <int>] [-i <int>] <filename>" << std::endl
00020               << "  -r - Specify total rays to fire." << std::endl
00021               << "       Zero implies unbounded. Default: " << NUM_RAYS << std::endl
00022               << "  -i - Specify total intersecting rays to fire." << std::endl
00023               << "       Zero implies unbounded. Default: " << NUM_XSCT << std::endl
00024               << "  -s - Use set-based tree." << std::endl
00025               << "  -p - Measure and report traversal performance statistics" << std::endl
00026               << "  The input file should be generated using the '-s'" << std::endl
00027               << "  option with 'obb_test'" << std::endl;
00028     exit( 1 );
00029 }
00030 
00031 void generate_ray( const CartVect& sphere_center, double sphere_radius, CartVect& point, CartVect& dir )
00032 {
00033     const int H = RAND_MAX / 2;
00034     point[0]    = (double)rand() / H - 1;
00035     point[1]    = (double)rand() / H - 1;
00036     point[2]    = (double)rand() / H - 1;
00037     point *= sphere_radius;
00038 
00039     dir[0] = (double)rand() * -point[0];
00040     dir[1] = (double)rand() * -point[1];
00041     dir[2] = (double)rand() * -point[2];
00042     dir.normalize();
00043 
00044     point += sphere_center;
00045 }
00046 
00047 ErrorCode read_tree( Interface* instance, const char* filename, EntityHandle& tree_root_out )
00048 {
00049     ErrorCode rval = instance->load_mesh( filename );
00050     if( MB_SUCCESS != rval ) return rval;
00051 
00052     Tag tag;
00053     rval = instance->tag_get_handle( "OBB_ROOT", 1, MB_TYPE_HANDLE, tag );
00054     if( MB_SUCCESS != rval ) return rval;
00055 
00056     const EntityHandle root = 0;
00057     return instance->tag_get_data( tag, &root, 1, &tree_root_out );
00058 }
00059 
00060 // global variables for CLI options
00061 int num_rays         = NUM_RAYS;
00062 int num_xsct         = NUM_XSCT;
00063 const char* filename = 0;
00064 bool do_sets         = false;
00065 bool do_trv_stats    = false;
00066 
00067 // global to make accessable to signal handler
00068 int rays = 0, xsct = 0, gen = 0;
00069 clock_t ttimer;
00070 
00071 extern "C" {
00072 void signal_handler( int )
00073 {
00074     ttimer = clock() - ttimer;
00075     std::cout << filename << ":" << std::endl
00076               << rays << " of " << num_rays << " ray fires done" << std::endl
00077               << xsct << " of " << num_xsct << " intersecting fires" << std::endl
00078               << gen << " unique rays used" << std::endl
00079               << (double)ttimer / CLOCKS_PER_SEC << " seconds" << std::endl;
00080     exit( 1 );
00081 }
00082 }
00083 
00084 int main( int argc, char* argv[] )
00085 {
00086     signal( SIGINT, &signal_handler );
00087 
00088     for( int i = 1; i < argc; ++i )
00089     {
00090         if( !strcmp( argv[i], "-r" ) )
00091         {
00092             ++i;
00093             if( i == argc || !argv[i][0] )
00094             {
00095                 std::cerr << "Expected value following '-r'" << std::endl;
00096                 usage();
00097             }
00098             char* end;
00099             long t1  = strtol( argv[i], &end, 0 );
00100             num_rays = (int)t1;
00101             if( *end || t1 < 0 || num_rays != t1 )
00102             {
00103                 std::cerr << "Expected positive integer following '-r'" << std::endl;
00104                 usage();
00105             }
00106         }
00107         else if( !strcmp( argv[i], "-i" ) )
00108         {
00109             ++i;
00110             if( i == argc || !argv[i][0] )
00111             {
00112                 std::cerr << "Expected value following '-i'" << std::endl;
00113                 usage();
00114             }
00115             char* end;
00116             long t1  = strtol( argv[i], &end, 0 );
00117             num_xsct = (int)t1;
00118             if( *end || t1 < 0 || num_xsct != t1 )
00119             {
00120                 std::cerr << "Expected positive integer following '-i'" << std::endl;
00121                 usage();
00122             }
00123         }
00124         else if( !strcmp( argv[i], "-s" ) )
00125         {
00126             do_sets = true;
00127         }
00128         else if( !strcmp( argv[i], "-p" ) )
00129         {
00130             do_trv_stats = true;
00131         }
00132         else if( filename )
00133         {
00134             std::cerr << "Invalid options or multiple file names specified." << std::endl;
00135             usage();
00136         }
00137         else
00138         {
00139             filename = argv[i];
00140         }
00141     }
00142     if( !filename )
00143     {
00144         std::cerr << "No file name specified." << std::endl;
00145         usage();
00146     }
00147 
00148     Core instance;
00149     Interface* iface = &instance;
00150     EntityHandle root;
00151     ErrorCode rval = read_tree( iface, filename, root );
00152     if( MB_SUCCESS != rval )
00153     {
00154         std::cerr << "Failed to read \"" << filename << '"' << std::endl;
00155         return 2;
00156     }
00157 
00158     OrientedBoxTreeTool tool( iface );
00159     OrientedBox box;
00160     rval = tool.box( root, box );
00161     if( MB_SUCCESS != rval )
00162     {
00163         std::cerr << "Corrupt tree.  Cannot get box for root node." << std::endl;
00164         return 3;
00165     }
00166 
00167     OrientedBoxTreeTool::TrvStats* stats = NULL;
00168     if( do_trv_stats )
00169     {
00170         stats = new OrientedBoxTreeTool::TrvStats;
00171     }
00172 
00173     const unsigned cached = 1000;
00174     std::vector< double > intersections;
00175     std::vector< EntityHandle > sets, facets;
00176     CartVect point, dir;
00177     std::vector< CartVect > randrays;
00178     randrays.reserve( cached );
00179     int cached_idx = 0;
00180 
00181     ttimer = clock();
00182     for( ;; )
00183     {
00184         if( !num_rays )
00185         {
00186             if( xsct >= num_xsct ) break;
00187         }
00188         else if( !num_xsct )
00189         {
00190             if( rays >= num_rays ) break;
00191         }
00192         else if( rays >= num_rays && xsct >= num_xsct )
00193             break;
00194 
00195         ++rays;
00196         if( randrays.size() < cached )
00197         {
00198             generate_ray( box.center, box.outer_radius(), point, dir );
00199             ++gen;
00200         }
00201         else
00202         {
00203             point      = randrays[cached_idx++];
00204             dir        = randrays[cached_idx++];
00205             cached_idx = cached_idx % randrays.size();
00206         }
00207 
00208         intersections.clear();
00209         if( do_sets )
00210         {
00211             sets.clear();
00212             facets.clear();
00213 
00214             OrientedBoxTreeTool::IntersectSearchWindow search_win;
00215             OrientedBoxTreeTool::IntRegCtxt int_reg_ctxt;
00216             rval = tool.ray_intersect_sets( intersections, sets, facets, root, 1e-6, point.array(), dir.array(),
00217                                             search_win, int_reg_ctxt, stats );
00218         }
00219         else
00220         {
00221             rval =
00222                 tool.ray_intersect_triangles( intersections, facets, root, 1e-6, point.array(), dir.array(), 0, stats );
00223         }
00224         if( MB_SUCCESS != rval )
00225         {
00226             std::cerr << "Rayfire #" << rays << " failed." << std::endl;
00227             return 4;
00228         }
00229 
00230         if( !intersections.empty() )
00231         {
00232             ++xsct;
00233         }
00234 
00235         if( randrays.size() < cached && ( !intersections.empty() || !num_xsct || xsct >= num_xsct ) )
00236         {
00237             randrays.push_back( point );
00238             randrays.push_back( dir );
00239         }
00240     }
00241 
00242     ttimer = clock() - ttimer;
00243     std::cout << rays << " ray fires done" << std::endl
00244               << gen << " unique rays used" << std::endl
00245               << xsct << " intersecting fires" << std::endl
00246               << (double)ttimer / CLOCKS_PER_SEC << " seconds" << std::endl;
00247 
00248     if( do_trv_stats )
00249     {
00250         std::cout << "Traversal statistics: " << std::endl;
00251         stats->print( std::cout );
00252     }
00253 
00254     return 0;
00255 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines