MOAB: Mesh Oriented datABase  (version 5.2.1)
obb_test.cpp File Reference
#include "moab/Core.hpp"
#include "moab/Range.hpp"
#include "moab/OrientedBoxTreeTool.hpp"
#include "moab/OrientedBox.hpp"
#include "MBTagConventions.hpp"
#include "moab/GeomUtil.hpp"
#include "moab/CN.hpp"
#include "../TestUtil.hpp"
#include <iostream>
#include <sstream>
#include <cstdlib>
#include <limits>
#include <cstdio>
#include <set>
#include <map>
+ Include dependency graph for obb_test.cpp:

Go to the source code of this file.

Classes

struct  RayTest
class  TreeValidator
class  CubitWriter
class  VtkWriter

Typedefs

typedef std::map< std::string,
std::vector< RayTest >
>::iterator 
ray_test_itr

Enumerations

enum  TriOption { DISABLE, ENABLE, AUTO }

Functions

void initialize_default_files ()
static void usage (const char *error, const char *opt)
static const char * get_option (int &i, int argc, char *argv[])
static int get_int_option (int &i, int argc, char *argv[])
static double get_double_option (int &i, int argc, char *argv[])
static bool do_file (const char *filename)
static void parse_ray (int &i, int argc, char *argv[])
int main (int argc, char *argv[])
static bool do_ray_fire_test (OrientedBoxTreeTool &tool, EntityHandle root_set, const char *filename, bool have_surface_tree)
static bool do_closest_point_test (OrientedBoxTreeTool &tool, EntityHandle root_set, bool have_surface_tree)
static ErrorCode save_tree (Interface *instance, const char *filename, EntityHandle tree_root)
static void count_non_tol (std::vector< double > intersections, int &non_tol_count, double &non_tol_dist)
static bool check_ray_intersect_tris (OrientedBoxTreeTool &tool, EntityHandle root_set, RayTest &test, int &non_tol_count, double &non_tol_dist, OrientedBoxTreeTool::TrvStats &stats)
static bool check_ray_intersect_sets (OrientedBoxTreeTool &tool, EntityHandle root_set, RayTest &test, int &non_tol_count, double &non_tol_dist, OrientedBoxTreeTool::TrvStats &stats)
static ErrorCode tri_coords (Interface *moab, EntityHandle tri, CartVect coords[3])
static ErrorCode closest_point_in_triangles (Interface *moab, const CartVect &to_pos, CartVect &result_pos, EntityHandle &result_tri)
static bool tri_in_set (Interface *moab, EntityHandle set, EntityHandle tri)

Variables

static const char * NAME = "obb_test"
std::map< std::string,
std::vector< RayTest > > 
default_files_tests
static int verbosity = 1
static
OrientedBoxTreeTool::Settings 
settings
static double tolerance = 1e-6
static bool write_cubit = false
static bool write_vtk = false
static bool write_ray_vtk = false
static std::vector< CartVectrays
static const char * save_file_name = 0
static TriOption surfTree = AUTO

Typedef Documentation

typedef std::map< std::string, std::vector< RayTest > >::iterator ray_test_itr

Definition at line 34 of file obb_test.cpp.


Enumeration Type Documentation

enum TriOption
Enumerator:
DISABLE 
ENABLE 
AUTO 

Definition at line 149 of file obb_test.cpp.


Function Documentation

static bool check_ray_intersect_sets ( OrientedBoxTreeTool tool,
EntityHandle  root_set,
RayTest test,
int &  non_tol_count,
double &  non_tol_dist,
OrientedBoxTreeTool::TrvStats stats 
) [static]

Definition at line 1005 of file obb_test.cpp.

References moab::CartVect::array(), count_non_tol(), RayTest::direction, MB_SUCCESS, RayTest::point, moab::OrientedBoxTreeTool::ray_intersect_sets(), moab::tolerance, and verbosity.

Referenced by do_ray_fire_test().

{

    ErrorCode rval;
    bool result = true;

    non_tol_dist  = std::numeric_limits< double >::max();
    non_tol_count = 0;

    const int NUM_NON_TOL_INT = 1;

    std::vector< double > intersections;
    std::vector< EntityHandle > surfs;
    std::vector< EntityHandle > facets;

    OrientedBoxTreeTool::IntersectSearchWindow search_win;
    OrientedBoxTreeTool::IntRegCtxt int_reg_ctxt;
    rval = tool.ray_intersect_sets( intersections, surfs, facets, root_set, tolerance, test.point.array(),
                                    test.direction.array(), search_win, int_reg_ctxt, &stats );

    if( MB_SUCCESS != rval )
    {
        if( verbosity ) std::cout << "  Call to OrientedBoxTreeTool::ray_intersect_sets failed." << std::endl;
        result = false;
    }
    else
    {

        if( surfs.size() != intersections.size() )
        {
            if( verbosity ) std::cout << "  ray_intersect_sets did not return sets for all intersections." << std::endl;
            result = false;
        }

        count_non_tol( intersections, non_tol_count, non_tol_dist );

        if( non_tol_count > NUM_NON_TOL_INT )
        {
            if( verbosity )
                std::cout << "  Requested " << NUM_NON_TOL_INT << "intersections "
                          << "  beyond tolerance.  Got " << non_tol_count << std::endl;
            result = false;
        }
    }

    return result;
}
static bool check_ray_intersect_tris ( OrientedBoxTreeTool tool,
EntityHandle  root_set,
RayTest test,
int &  non_tol_count,
double &  non_tol_dist,
OrientedBoxTreeTool::TrvStats stats 
) [static]

Definition at line 965 of file obb_test.cpp.

References moab::CartVect::array(), count_non_tol(), RayTest::description, RayTest::direction, RayTest::expected_hits, MB_SUCCESS, RayTest::point, moab::OrientedBoxTreeTool::ray_intersect_triangles(), moab::tolerance, and verbosity.

Referenced by do_ray_fire_test().

{
    ErrorCode rval;
    bool result = true;

    non_tol_dist  = std::numeric_limits< double >::max();
    non_tol_count = 0;

    std::vector< double > intersections;
    std::vector< EntityHandle > facets;
    rval = tool.ray_intersect_triangles( intersections, facets, root_set, tolerance, test.point.array(),
                                         test.direction.array(), 0, &stats );
    if( MB_SUCCESS != rval )
    {
        if( verbosity ) std::cout << "  Call to OrientedBoxTreeTool::ray_intersect_triangles failed." << std::endl;
        result = false;
    }
    else
    {

        if( intersections.size() != test.expected_hits )
        {
            if( verbosity > 2 )
                std::cout << "  Expected " << test.expected_hits << " and got " << intersections.size()
                          << " hits for ray fire of " << test.description << std::endl;
            if( verbosity > 3 )
            {
                for( unsigned j = 0; j < intersections.size(); ++j )
                    std::cout << "  " << intersections[j];
                std::cout << std::endl;
            }
            result = false;
        }

        count_non_tol( intersections, non_tol_count, non_tol_dist );
    }
    return result;
}
static ErrorCode closest_point_in_triangles ( Interface *  moab,
const CartVect to_pos,
CartVect result_pos,
EntityHandle result_tri 
) [static]

Definition at line 1316 of file obb_test.cpp.

References moab::Range::begin(), moab::GeomUtil::closest_location_on_tri(), moab::Range::empty(), moab::Range::end(), MB_FAILURE, MB_SUCCESS, MBTRI, and tri_coords().

Referenced by do_closest_point_test().

{
    ErrorCode rval;

    Range triangles;
    rval = moab->get_entities_by_type( 0, MBTRI, triangles );
    if( MB_SUCCESS != rval ) return rval;

    if( triangles.empty() ) return MB_FAILURE;

    Range::iterator i = triangles.begin();
    CartVect coords[3];
    rval = tri_coords( moab, *i, coords );
    if( MB_SUCCESS != rval ) return rval;
    result_tri = *i;
    GeomUtil::closest_location_on_tri( to_pos, coords, result_pos );
    CartVect diff            = to_pos - result_pos;
    double shortest_dist_sqr = diff % diff;

    for( ++i; i != triangles.end(); ++i )
    {
        rval = tri_coords( moab, *i, coords );
        if( MB_SUCCESS != rval ) return rval;
        CartVect pos;
        GeomUtil::closest_location_on_tri( to_pos, coords, pos );
        diff        = to_pos - pos;
        double dsqr = diff % diff;
        if( dsqr < shortest_dist_sqr )
        {
            shortest_dist_sqr = dsqr;
            result_pos        = pos;
            result_tri        = *i;
        }
    }

    return MB_SUCCESS;
}
static void count_non_tol ( std::vector< double >  intersections,
int &  non_tol_count,
double &  non_tol_dist 
) [static]

Definition at line 952 of file obb_test.cpp.

References moab::tolerance.

Referenced by check_ray_intersect_sets(), and check_ray_intersect_tris().

{

    for( size_t i = 0; i < intersections.size(); ++i )
    {
        if( intersections[i] > tolerance )
        {
            ++non_tol_count;
            if( intersections[i] < non_tol_dist ) non_tol_dist = intersections[i];
        }
    }
}
static bool do_closest_point_test ( OrientedBoxTreeTool tool,
EntityHandle  root_set,
bool  have_surface_tree 
) [static]

Definition at line 1364 of file obb_test.cpp.

References moab::CartVect::array(), moab::OrientedBoxTreeTool::box(), box(), moab::OrientedBox::center, moab::GeomUtil::closest_location_on_tri(), closest_point_in_triangles(), moab::OrientedBoxTreeTool::closest_to_location(), moab::OrientedBoxTreeTool::get_moab_instance(), moab::CartVect::length(), MB_SUCCESS, moab::OrientedBoxTreeTool::TrvStats::print(), moab::OrientedBox::scaled_axis(), moab::tolerance, tri_coords(), tri_in_set(), and verbosity.

Referenced by do_file().

{
    if( verbosity > 1 ) std::cout << "beginning closest point tests" << std::endl;

    ErrorCode rval;
    Interface* moab = tool.get_moab_instance();
    EntityHandle set;
    EntityHandle* set_ptr = have_surface_tree ? &set : 0;
    bool result           = true;

    // get root box
    OrientedBox box;
    rval = tool.box( root_set, box );
    if( MB_SUCCESS != rval )
    {
        if( verbosity ) std::cerr << "Invalid tree in do_closest_point_test\n";
        return false;
    }

    OrientedBoxTreeTool::TrvStats stats;

    // chose some points to test
    CartVect points[] = { box.center + box.scaled_axis( 0 ), box.center + 2 * box.scaled_axis( 1 ),
                          box.center + 0.5 * box.scaled_axis( 2 ),
                          box.center + -2 * box.scaled_axis( 0 ) + -2 * box.scaled_axis( 1 ) +
                              -2 * box.scaled_axis( 2 ),
                          CartVect( 100, 100, 100 ) };
    const int num_pts = sizeof( points ) / sizeof( points[0] );

    // test each point
    for( int i = 0; i < num_pts; ++i )
    {
        if( verbosity >= 3 ) std::cout << "Evaluating closest point to " << points[i] << std::endl;

        CartVect n_result, t_result;
        EntityHandle n_tri = 0, t_tri;

        // find closest point the slow way
        rval = closest_point_in_triangles( moab, points[i], n_result, n_tri );
        if( MB_SUCCESS != rval )
        {
            std::cerr << "Internal MOAB error in do_closest_point_test" << std::endl;
            result = false;
            continue;
        }

        // find closest point using tree
        rval = tool.closest_to_location( points[i].array(), root_set, t_result.array(), t_tri, set_ptr, &stats );
        if( MB_SUCCESS != rval )
        {
            if( verbosity )
                std::cout << "OrientedBoxTreeTool:: closest_to_location( " << points[i] << " ) FAILED!" << std::endl;
            result = false;
            continue;
        }

        CartVect diff = t_result - n_result;
        if( diff.length() > tolerance )
        {
            if( verbosity )
                std::cout << "Closest point to " << points[i] << " INCORRECT! (" << t_result << " != " << n_result
                          << ")" << std::endl;
            result = false;
            continue;
        }

        if( t_tri != n_tri )
        {
            // if result point is triangle, then OK because
            // already tested that it is the same location
            // as the expected value.  We just have a case where
            // the point was on an edge or vertex.
            CartVect coords[3];
            CartVect diff1( 1, 1, 1 );
            rval = tri_coords( moab, t_tri, coords );
            if( MB_SUCCESS == rval )
            {
                GeomUtil::closest_location_on_tri( points[i], coords, n_result );
                diff1 = n_result - t_result;
            }
            if( ( diff1 % diff1 ) > tolerance )
            {
                if( verbosity )
                    std::cout << "Triangle closest to " << points[i] << " INCORRECT! (" << t_tri << " != " << n_tri
                              << ")" << std::endl;
                result = false;
                continue;
            }
        }

        if( set_ptr && !tri_in_set( moab, *set_ptr, t_tri ) )
        {
            if( verbosity ) std::cout << "Surface closest to " << points[i] << " INCORRECT!" << std::endl;
            result = false;
            continue;
        }
    }

    if( verbosity > 1 )
    {
        std::cout << "Traversal statistics for closest point tests: " << std::endl;
        stats.print( std::cout );
    }

    return result;
}
static bool do_file ( const char *  filename) [static]

Definition at line 721 of file obb_test.cpp.

References TreeValidator::bad_outer_radius_count, moab::Range::begin(), moab::OrientedBoxTreeTool::build(), TreeValidator::child_outside_count, moab::Range::clear(), moab::OrientedBoxTreeTool::delete_tree(), dim, DISABLE, do_closest_point_test(), do_ray_fire_test(), TreeValidator::duplicate_entity_count, moab::Range::empty(), TreeValidator::empty_leaf_count, ENABLE, moab::Range::end(), entities, TreeValidator::entity_count, TreeValidator::entity_invalid_count, TreeValidator::entity_outside_count, TreeValidator::error_count, filename, GEOM_DIMENSION_TAG_NAME, iface, moab::Range::insert(), TreeValidator::is_valid(), moab::OrientedBoxTreeTool::join_trees(), TreeValidator::loose_box_count, MB_ENTITY_NOT_FOUND, MB_SUCCESS, MB_TAG_NOT_FOUND, MB_TYPE_INTEGER, MBENTITYSET, moab::Range::merge(), TreeValidator::missing_surface_count, TreeValidator::multiple_surface_count, TreeValidator::non_empty_non_leaf_count, TreeValidator::non_ortho_count, TreeValidator::non_unit_count, TreeValidator::num_entities_outside, moab::OrientedBoxTreeTool::preorder_traverse(), moab::OrientedBoxTreeTool::print(), save_file_name, save_tree(), settings, moab::Range::size(), moab::OrientedBoxTreeTool::stats(), surfTree, moab::tolerance, TreeValidator::unsorted_axis_count, verbosity, write_cubit, and write_vtk.

Referenced by main().

{
    ErrorCode rval;
    Core instance;
    Interface* const iface = &instance;
    OrientedBoxTreeTool tool( iface );
    bool haveSurfTree = false;

    if( verbosity ) std::cout << filename << std::endl << "------" << std::endl;

    rval = iface->load_mesh( filename );
    if( MB_SUCCESS != rval )
    {
        if( verbosity ) std::cout << "Failed to read file: \"" << filename << '"' << std::endl;
        return false;
    }

    // IF building from surfaces, get surfaces.
    // If AUTO and less than two surfaces, don't build from surfaces.
    Range surfaces;
    if( surfTree != DISABLE )
    {
        Tag surftag;
        rval = iface->tag_get_handle( GEOM_DIMENSION_TAG_NAME, 1, MB_TYPE_INTEGER, surftag );
        if( MB_SUCCESS == rval )
        {
            int dim                 = 2;
            const void* tagvalues[] = { &dim };
            rval = iface->get_entities_by_type_and_tag( 0, MBENTITYSET, &surftag, tagvalues, 1, surfaces );
            if( MB_SUCCESS != rval && MB_ENTITY_NOT_FOUND != rval ) return false;
        }
        else if( MB_TAG_NOT_FOUND != rval )
            return false;

        if( ENABLE == surfTree && surfaces.empty() )
        {
            std::cerr << "No Surfaces found." << std::endl;
            return false;
        }

        haveSurfTree = ( ENABLE == surfTree ) || ( surfaces.size() > 1 );
    }

    EntityHandle root;
    Range entities;
    if( !haveSurfTree )
    {
        rval = iface->get_entities_by_dimension( 0, 2, entities );
        if( MB_SUCCESS != rval )
        {
            std::cerr << "get_entities_by_dimension( 2 ) failed." << std::endl;
            return false;
        }

        if( entities.empty() )
        {
            if( verbosity ) std::cout << "File \"" << filename << "\" contains no 2D elements" << std::endl;
            return false;
        }

        if( verbosity ) std::cout << "Building tree from " << entities.size() << " 2D elements" << std::endl;

        rval = tool.build( entities, root, &settings );
        if( MB_SUCCESS != rval )
        {
            if( verbosity ) std::cout << "Failed to build tree." << std::endl;
            return false;
        }
    }
    else
    {

        if( verbosity ) std::cout << "Building tree from " << surfaces.size() << " surfaces" << std::endl;

        // Build subtree for each surface, get list of all entities to use later
        Range surf_trees, surf_tris;
        EntityHandle surf_root;
        for( Range::iterator s = surfaces.begin(); s != surfaces.end(); ++s )
        {
            surf_tris.clear();
            rval = iface->get_entities_by_dimension( *s, 2, surf_tris );
            if( MB_SUCCESS != rval ) return false;
            rval = tool.build( surf_tris, surf_root, &settings );
            if( MB_SUCCESS != rval )
            {
                if( verbosity ) std::cout << "Failed to build tree for surface." << std::endl;
                return false;
            }
            surf_trees.insert( surf_root );
            entities.merge( surf_tris );
            rval = iface->add_entities( surf_root, &*s, 1 );
            if( MB_SUCCESS != rval ) return false;
        }

        rval = tool.join_trees( surf_trees, root, &settings );
        if( MB_SUCCESS != rval )
        {
            if( verbosity ) std::cout << "Failed to build tree." << std::endl;
            return false;
        }

        if( verbosity )
            std::cout << "Built tree from " << surfaces.size() << " surfaces"
                      << " (" << entities.size() - surfaces.size() << " elements)" << std::endl;

        entities.merge( surfaces );
    }

    if( write_cubit )
    {
        std::string name = filename;
        name += ".boxes.jou";
        FILE* ptr = fopen( name.c_str(), "w+" );
        if( !ptr ) { perror( name.c_str() ); }
        else
        {
            if( verbosity ) std::cout << "Writing: " << name << std::endl;
            fprintf( ptr, "graphics off\n" );
            CubitWriter op( ptr, &tool );
            tool.preorder_traverse( root, op );
            fprintf( ptr, "graphics on\n" );
            fclose( ptr );
        }
    }

    if( write_vtk )
    {
        VtkWriter op( filename, iface );
        if( verbosity )
            std::cout << "Writing leaf contents as : " << filename << ".xxx.vtk where 'xxx' is the set id" << std::endl;
        tool.preorder_traverse( root, op );
    }

    bool print_errors = false, print_contents = false;
    switch( verbosity )
    {
        default:
            print_contents = true;
        case 4:
            tool.print( root, std::cout, print_contents );
        case 3:
            print_errors = true;
        case 2:
            rval = tool.stats( root, std::cout );
            if( MB_SUCCESS != rval ) std::cout << "****** Failed to get tree statistics ******" << std::endl;
        case 1:
        case 0:;
    }

    TreeValidator op( iface, &tool, print_errors, std::cout, tolerance, haveSurfTree, settings );
    rval        = tool.preorder_traverse( root, op );
    bool result = op.is_valid();
    if( MB_SUCCESS != rval )
    {
        result = false;
        if( verbosity ) std::cout << "Errors traversing tree.  Corrupt tree?" << std::endl;
    }

    bool missing = ( op.entity_count != entities.size() );
    if( missing ) result = false;

    if( verbosity )
    {
        if( result )
            std::cout << std::endl << "No errors detected." << std::endl;
        else
            std::cout << std::endl << "*********************** ERROR SUMMARY **********************" << std::endl;
        if( op.child_outside_count )
            std::cout << "* " << op.child_outside_count << " child boxes not contained in parent." << std::endl;
        if( op.entity_outside_count )
            std::cout << "* " << op.entity_outside_count << " nodes containing entities outside of box." << std::endl;
        if( op.num_entities_outside )
            std::cout << "* " << op.num_entities_outside << " entities outside boxes." << std::endl;
        if( op.empty_leaf_count ) std::cout << "* " << op.empty_leaf_count << " empty leaf nodes." << std::endl;
        if( op.non_empty_non_leaf_count )
            std::cout << "* " << op.non_empty_non_leaf_count << " non-leaf nodes containing entities." << std::endl;
        if( op.duplicate_entity_count )
            std::cout << "* " << op.duplicate_entity_count << " duplicate entities in leaves." << std::endl;
        if( op.missing_surface_count )
            std::cout << "* " << op.missing_surface_count << " leaves outside surface subtrees." << std::endl;
        if( op.multiple_surface_count )
            std::cout << "* " << op.multiple_surface_count << " surfaces within other surface subtrees." << std::endl;
        if( op.non_ortho_count )
            std::cout << "* " << op.non_ortho_count << " boxes with non-orthononal axes." << std::endl;
        if( op.non_unit_count ) std::cout << "* " << op.non_unit_count << " boxes with non-unit axes." << std::endl;
        if( op.bad_outer_radius_count )
            std::cout << "* " << op.bad_outer_radius_count << " boxes incorrect outer radius." << std::endl;
        if( op.unsorted_axis_count )
            std::cout << "* " << op.unsorted_axis_count << " boxes axes in unsorted order." << std::endl;
        if( op.loose_box_count )
            std::cout << "* " << op.loose_box_count << " boxes that do not fit the contained entities tightly."
                      << std::endl;
        if( op.error_count + op.entity_invalid_count )
            std::cout << "* " << op.error_count + op.entity_invalid_count << " other errors while traversing tree."
                      << std::endl;
        if( missing )
            std::cout << "* tree built from " << entities.size() << " entities contains " << op.entity_count
                      << " entities." << std::endl;
        if( !result ) std::cout << "************************************************************" << std::endl;
    }

    if( result && save_file_name )
    {
        if( MB_SUCCESS == save_tree( iface, save_file_name, root ) )
            std::cerr << "Wrote '" << save_file_name << "'" << std::endl;
        else
            std::cerr << "FAILED TO WRITE '" << save_file_name << "'" << std::endl;
    }

    if( !do_ray_fire_test( tool, root, filename, haveSurfTree ) )
    {
        if( verbosity ) std::cout << "Ray fire test failed." << std::endl;
        result = false;
    }

    if( !do_closest_point_test( tool, root, haveSurfTree ) )
    {
        if( verbosity ) std::cout << "Closest point test failed" << std::endl;
        result = false;
    }

    rval = tool.delete_tree( root );
    if( MB_SUCCESS != rval )
    {
        if( verbosity ) std::cout << "delete_tree failed." << std::endl;
        result = false;
    }

    return result;
}
static bool do_ray_fire_test ( OrientedBoxTreeTool tool,
EntityHandle  root_set,
const char *  filename,
bool  have_surface_tree 
) [static]

Definition at line 1054 of file obb_test.cpp.

References moab::OrientedBox::axis(), moab::Range::begin(), moab::OrientedBoxTreeTool::box(), box(), moab::OrientedBox::center, check_ray_intersect_sets(), check_ray_intersect_tris(), default_files_tests, moab::OrientedBox::dimensions(), moab::Range::empty(), moab::Range::end(), filename, moab::OrientedBoxTreeTool::get_moab_instance(), MB_SUCCESS, origin, moab::OrientedBoxTreeTool::TrvStats::print(), moab::OrientedBoxTreeTool::ray_intersect_boxes(), moab::OrientedBoxTreeTool::ray_intersect_sets(), moab::OrientedBoxTreeTool::ray_intersect_triangles(), rays, moab::OrientedBox::scaled_axis(), moab::Range::size(), moab::tolerance, verbosity, write_cubit, and write_ray_vtk.

Referenced by do_file().

{
    if( verbosity > 1 ) std::cout << "beginning ray fire tests" << std::endl;

    OrientedBox box;
    ErrorCode rval = tool.box( root_set, box );
    if( MB_SUCCESS != rval )
    {
        if( verbosity ) std::cerr << "Error getting box for tree root set" << std::endl;
        return false;
    }

    /* Do standard ray fire tests */
    std::cout << box << std::endl;

    CartVect origin( 0., 0., 0. );
    CartVect unitDiag( 1., 1., 1. );
    std::vector< RayTest > tests;
    RayTest default_tests[] = { { "large axis through box", 2, box.center - 1.2 * box.scaled_axis( 2 ), box.axis( 2 ) },
                                { "small axis through box", 2, box.center - 1.2 * box.scaled_axis( 0 ), box.axis( 0 ) },
                                { "parallel miss", 0, box.center + 2.0 * box.scaled_axis( 1 ), box.axis( 2 ) },
                                { "skew miss", 0, box.center + box.dimensions(), box.dimensions() * box.axis( 2 ) } };
    const size_t num_def_test = sizeof( default_tests ) / sizeof( default_tests[0] );
    tests.insert( tests.begin(), &default_tests[0], &default_tests[0] + num_def_test );
    tests.insert( tests.end(), default_files_tests[filename].begin(), default_files_tests[filename].end() );

    OrientedBoxTreeTool::TrvStats stats;

    bool result           = true;
    const size_t num_test = tests.size();
    for( size_t i = 0; i < num_test; ++i )
    {
        tests[i].direction.normalize();
        if( verbosity > 2 )
        {
            std::cout << ( 0 == i ? "** Common tests\n" : ( num_def_test == i ? "** File-specific tests\n" : "" ) );
            std::cout << "  " << tests[i].description << " " << tests[i].point << " " << tests[i].direction
                      << std::endl;
        }

        int rit_non_tol_count   = 0;
        double rit_non_tol_dist = std::numeric_limits< double >::max();
        if( !check_ray_intersect_tris( tool, root_set, tests[i], rit_non_tol_count, rit_non_tol_dist, stats ) )
        {
            result = false;
            continue;
        }

        if( !haveSurfTree ) continue;

        int ris_non_tol_count   = 0;
        double ris_non_tol_dist = std::numeric_limits< double >::max();
        if( !check_ray_intersect_sets( tool, root_set, tests[i], ris_non_tol_count, ris_non_tol_dist, stats ) )
        {
            result = false;
            continue;
        }

        if( !rit_non_tol_count && ris_non_tol_count )
        {
            if( verbosity )
                std::cout << "  ray_intersect_sets returned intersection not found by "
                             "ray_intersect_triangles"
                          << std::endl;
            result = false;
            continue;
        }
        else if( rit_non_tol_count && !ris_non_tol_count )
        {
            if( verbosity )
                std::cout << "  ray_intersect_sets missed intersection found by ray_intersect_triangles" << std::endl;
            result = false;
            continue;
        }
        else if( rit_non_tol_count && ris_non_tol_count && fabs( rit_non_tol_dist - ris_non_tol_dist ) > tolerance )
        {
            if( verbosity )
                std::cout << "  ray_intersect_sets and ray_intersect_triangles did not find same "
                             "closest intersection"
                          << std::endl;
            result = false;
        }
    }

    /* Do ray fire for any user-specified rays */

    for( size_t i = 0; i < rays.size(); i += 2 )
    {
        std::cout << rays[i] << "+" << rays[i + 1] << " : ";

        if( !haveSurfTree )
        {
            Range leaves;
            std::vector< double > intersections;
            std::vector< EntityHandle > intersection_facets;
            rval = tool.ray_intersect_boxes( leaves, root_set, tolerance, rays[i].array(), rays[i + 1].array(), 0,
                                             &stats );
            if( MB_SUCCESS != rval )
            {
                std::cout << "FAILED" << std::endl;
                result = false;
                continue;
            }

            if( !leaves.empty() && write_ray_vtk )
            {
                std::string num, name( filename );
                std::stringstream s;
                s << ( i / 2 );
                s >> num;
                name += "-ray";
                name += num;
                name += ".vtk";

                std::vector< EntityHandle > sets( leaves.size() );
                std::copy( leaves.begin(), leaves.end(), sets.begin() );
                tool.get_moab_instance()->write_mesh( name.c_str(), &sets[0], sets.size() );
                if( verbosity ) std::cout << "(Wrote " << name << ") ";
            }

            rval = tool.ray_intersect_triangles( intersections, intersection_facets, leaves, tolerance, rays[i].array(),
                                                 rays[i + 1].array(), 0 );
            if( MB_SUCCESS != rval )
            {
                std::cout << "FAILED" << std::endl;
                result = false;
                continue;
            }

            if( intersections.empty() )
            {
                std::cout << "(none)" << std::endl;
                continue;
            }

            std::cout << intersections[0];
            for( unsigned j = 1; j < intersections.size(); ++j )
                std::cout << ", " << intersections[j];
            std::cout << std::endl;

            if( !leaves.empty() && write_cubit && verbosity > 2 )
            {
                std::cout << "  intersected boxes:";
                for( Range::iterator i2 = leaves.begin(); i2 != leaves.end(); ++i2 )
                    std::cout << " " << tool.get_moab_instance()->id_from_handle( *i2 );
                std::cout << std::endl;
            }
        }
        else
        {
            std::vector< double > intersections;
            std::vector< EntityHandle > surfaces;
            std::vector< EntityHandle > facets;

            OrientedBoxTreeTool::IntersectSearchWindow search_win;
            OrientedBoxTreeTool::IntRegCtxt int_reg_ctxt;
            rval = tool.ray_intersect_sets( intersections, surfaces, facets, root_set, tolerance, rays[i].array(),
                                            rays[i + 1].array(), search_win, int_reg_ctxt, &stats );

            if( MB_SUCCESS != rval )
            {
                if( verbosity ) std::cout << "  Call to OrientedBoxTreeTool::ray_intersect_sets failed." << std::endl;
                result = false;
                continue;
            }

            if( !surfaces.empty() && write_ray_vtk )
            {
                std::string num, name( filename );
                std::stringstream s;
                s << ( i / 2 );
                s >> num;
                name += "-ray";
                name += num;
                name += ".vtk";

                tool.get_moab_instance()->write_mesh( name.c_str(), &surfaces[0], surfaces.size() );
                if( verbosity ) std::cout << "(Wrote " << name << ") ";
            }

            if( intersections.size() != surfaces.size() )
            {
                std::cout << "Mismatched output lists." << std::endl;
                result = false;
                continue;
            }

            if( intersections.empty() )
            {
                std::cout << "(none)" << std::endl;
                continue;
            }

            Tag idtag = tool.get_moab_instance()->globalId_tag();
            std::vector< int > ids( surfaces.size() );
            rval = tool.get_moab_instance()->tag_get_data( idtag, &surfaces[0], surfaces.size(), &ids[0] );
            if( MB_SUCCESS != rval )
            {
                std::cout << "NO GLOBAL_ID TAG ON SURFACE." << std::endl;
                continue;
            }

            // group by surfaces
            std::map< int, double > intmap;
            for( unsigned j = 0; j < intersections.size(); ++j )
                intmap[ids[j]] = intersections[j];

            std::map< int, double >::iterator it = intmap.begin();
            int prevsurf                         = it->first;
            std::cout << "Surf" << it->first << " " << it->second;
            for( ++it; it != intmap.end(); ++it )
            {
                std::cout << ", ";
                if( it->first != prevsurf )
                {
                    prevsurf = it->first;
                    std::cout << "Surf" << it->first << " ";
                }
                std::cout << it->second;
            }
            std::cout << std::endl;
        }
    }

    if( verbosity > 1 )
    {
        std::cout << "Traversal statistics for ray fire tests: " << std::endl;
        stats.print( std::cout );
    }

    return result;
}
static double get_double_option ( int &  i,
int  argc,
char *  argv[] 
) [static]

Definition at line 138 of file obb_test.cpp.

References get_option(), and usage.

Referenced by main().

{
    const char* str = get_option( i, argc, argv );
    char* end_ptr;
    double val = strtod( str, &end_ptr );
    if( !*str || *end_ptr ) usage( "Expected real number following option", argv[i - 1] );
    return val;
}
static int get_int_option ( int &  i,
int  argc,
char *  argv[] 
) [static]

Definition at line 129 of file obb_test.cpp.

References get_option(), and usage.

Referenced by main().

{
    const char* str = get_option( i, argc, argv );
    char* end_ptr;
    long val = strtol( str, &end_ptr, 0 );
    if( !*str || *end_ptr ) usage( "Expected integer following option", argv[i - 1] );
    return val;
}
static const char* get_option ( int &  i,
int  argc,
char *  argv[] 
) [static]

Definition at line 122 of file obb_test.cpp.

References usage.

Referenced by get_double_option(), get_int_option(), main(), and parse_ray().

{
    ++i;
    if( i == argc ) usage( "Expected argument following option", argv[i - 1] );
    return argv[i];
}

Definition at line 36 of file obb_test.cpp.

References default_files_tests, num_tests, and STRINGIFY.

Referenced by main().

{
    size_t num_tests;
    std::vector< RayTest > tests;
    std::string file = STRINGIFY( MESHDIR ) "/3k-tri-sphere.vtk";
    RayTest set1[]   = { { "triangle interior ", 1, CartVect( 0, 0, 0 ), CartVect( 99.8792, -5, 0.121729 ) },
                       { "triangle edge ", 2, CartVect( 0, 0, 0 ), CartVect( 4.99167, 0, 99.7502 ) },
                       { "triangle node ", 6, CartVect( 0, 0, 0 ), CartVect( 0, 0, 100 ) } };

    num_tests = sizeof( set1 ) / sizeof( set1[0] );
    tests.insert( tests.begin(), &set1[0], &set1[num_tests] );
    default_files_tests[file] = tests;
    tests.clear();

#ifdef MOAB_HAVE_HDF5
    file = STRINGIFY( MESHDIR ) "/3k-tri-cube.h5m";
#else
    file = STRINGIFY( MESHDIR ) "/3k-tri-cube.vtk";
#endif

    RayTest set2[] = { { "interior triangle interior ", 1, CartVect( 0, 0, 0 ), CartVect( 0, 0, 5 ) },
                       { "interior triangle edge ", 2, CartVect( 0, 0, 0 ), CartVect( -0.25, -0.05, 5 ) },
                       { "interior triangle node ", 5, CartVect( 0, 0, 0 ), CartVect( -0.3, -0.3, 5 ) },
                       { "edge triangle interior ", 1, CartVect( 0, 0, 0 ), CartVect( 5, 2.9, 2.9 ) },
                       { "edge triangle edge ", 2, CartVect( 0, 0, 0 ), CartVect( 5, 5, 2.9 ) },
                       { "edge triangle node ", 6, CartVect( 0, 0, 0 ), CartVect( 5, 5, 3 ) },
                       { "corner triangle interior ", 1, CartVect( 0, 0, 0 ), CartVect( 5, 4.9, 4.9 ) },
                       { "corner triangle edge ", 2, CartVect( 0, 0, 0 ), CartVect( 5, 5, 4.9 ) },
                       { "corner triangle node ", 3, CartVect( 0, 0, 0 ), CartVect( 5, 5, 5 ) } };

    num_tests = sizeof( set2 ) / sizeof( set2[0] );
    tests.insert( tests.begin(), &set2[0], &set2[num_tests] );
    default_files_tests[file] = tests;
    tests.clear();
}
int main ( int  argc,
char *  argv[] 
)

Definition at line 168 of file obb_test.cpp.

References moab::OrientedBoxTreeTool::Settings::best_split_ratio, default_files_tests, DISABLE, do_file(), ENABLE, moab::fail(), get_double_option(), get_int_option(), get_option(), moab::Core::impl_version(), initialize_default_files(), moab::OrientedBoxTreeTool::Settings::max_depth, moab::OrientedBoxTreeTool::Settings::max_leaf_entities, MESHSET_ORDERED, MESHSET_SET, parse_ray(), save_file_name, moab::OrientedBoxTreeTool::Settings::set_options, settings, surfTree, moab::tolerance, usage, moab::OrientedBoxTreeTool::Settings::valid(), verbosity, moab::OrientedBoxTreeTool::Settings::worst_split_ratio, write_cubit, write_ray_vtk, and write_vtk.

{
#ifdef MOAB_HAVE_MPI
    int fail = MPI_Init( &argc, &argv );
    if( fail ) return fail;
#endif

    initialize_default_files();

    std::vector< const char* > file_names;
    bool flags = true;
    for( int i = 1; i < argc; ++i )
    {
        if( flags && argv[i][0] == '-' )
        {
            if( !argv[i][1] || argv[i][2] ) usage( 0, argv[i] );
            switch( argv[i][1] )
            {
                default:
                    usage( 0, argv[i] );
                    break;
                case '-':
                    flags = false;
                    break;
                case 'v':
                    ++verbosity;
                    break;
                case 'q':
                    verbosity = 0;
                    break;
                case 'h':
                    usage( 0, 0 );
                    break;
                case 'c':
                    write_cubit = true;
                    break;
                case 'k':
                    write_vtk = true;
                    break;
                case 'K':
                    write_ray_vtk = true;
                    break;
                case 's':
                    surfTree = ENABLE;
                    break;
                case 'S':
                    surfTree = DISABLE;
                    break;
                case 'u':
                    settings.set_options = MESHSET_SET;
                    break;
                case 'U':
                    settings.set_options = MESHSET_ORDERED;
                    break;
                case 'o':
                    save_file_name = get_option( i, argc, argv );
                    break;
                case 'n':
                    settings.max_leaf_entities = get_int_option( i, argc, argv );
                    break;
                case 'l':
                    settings.max_depth = get_int_option( i, argc, argv );
                    break;
                case 'r':
                    settings.worst_split_ratio = get_double_option( i, argc, argv );
                    break;
                case 'R':
                    settings.best_split_ratio = get_double_option( i, argc, argv );
                    break;
                case 't':
                    tolerance = get_double_option( i, argc, argv );
                    break;
                case 'f':
                    parse_ray( i, argc, argv );
                    break;
            }
        }
        else
        {
            file_names.push_back( argv[i] );
        }
    }

    if( verbosity )
    {
        Core core;
        std::string version;
        core.impl_version( &version );
        std::cout << version << std::endl;
        if( verbosity > 1 )
            std::cout << "max_leaf_entities:      " << settings.max_leaf_entities << std::endl
                      << "max_depth:              " << settings.max_depth << std::endl
                      << "worst_split_ratio:      " << settings.worst_split_ratio << std::endl
                      << "best_split_ratio:       " << settings.best_split_ratio << std::endl
                      << "tolerance:              " << tolerance << std::endl
                      << "set type:               "
                      << ( ( settings.set_options & MESHSET_ORDERED ) ? "ordered" : "set" ) << std::endl
                      << std::endl;
    }

    if( !settings.valid() || tolerance < 0.0 )
    {
        std::cerr << "Invalid settings specified." << std::endl;
        return 2;
    }

    if( file_names.empty() )
    {
        std::cerr << "No file(s) specified." << std::endl;
        for( ray_test_itr file = default_files_tests.begin(); file != default_files_tests.end(); file++ )
        {
            std::cerr << "Using default file \"" << file->first << '"' << std::endl;
            file_names.push_back( file->first.c_str() );
        }
    }

    if( save_file_name && file_names.size() != 1 )
    {
        std::cout << "Only one input file allowed if \"-o\" option is specified." << std::endl;
        std::cout << "Only testing with single file " << file_names[0] << std::endl;
        file_names.erase( ++file_names.begin(), file_names.end() );
    }

    int exit_val = 0;
    for( unsigned j = 0; j < file_names.size(); ++j )
        if( !do_file( file_names[j] ) ) ++exit_val;

#ifdef MOAB_HAVE_MPI
    fail = MPI_Finalize();
    if( fail ) return fail;
#endif

    return exit_val ? exit_val + 2 : 0;
}
static void parse_ray ( int &  i,
int  argc,
char *  argv[] 
) [static]

Definition at line 303 of file obb_test.cpp.

References get_option(), moab::CartVect::normalize(), rays, and usage.

Referenced by main().

{
    CartVect point, direction;
    if( 6 != sscanf( get_option( i, argc, argv ), "%lf:%lf:%lf:%lf:%lf:%lf", &point[0], &point[1], &point[2],
                     &direction[0], &direction[1], &direction[2] ) )
        usage( "Expected ray specified as <x>:<y>:<z>:<i>:<j>:<k>", 0 );
    direction.normalize();
    rays.push_back( point );
    rays.push_back( direction );
}
static ErrorCode save_tree ( Interface *  instance,
const char *  filename,
EntityHandle  tree_root 
) [static]

Definition at line 1288 of file obb_test.cpp.

References MB_SUCCESS, MB_TAG_CREAT, MB_TAG_SPARSE, and MB_TYPE_HANDLE.

Referenced by do_file().

{
    ErrorCode rval;
    Tag tag;

    rval = instance->tag_get_handle( "OBB_ROOT", 1, MB_TYPE_HANDLE, tag, MB_TAG_SPARSE | MB_TAG_CREAT );
    if( MB_SUCCESS != rval ) return rval;

    const EntityHandle root = 0;
    rval                    = instance->tag_set_data( tag, &root, 1, &tree_root );
    if( MB_SUCCESS != rval ) return rval;

    return instance->write_mesh( filename );
}
static ErrorCode tri_coords ( Interface *  moab,
EntityHandle  tri,
CartVect  coords[3] 
) [static]

Definition at line 1303 of file obb_test.cpp.

References conn, MB_FAILURE, and MB_SUCCESS.

Referenced by check_common_vertex(), check_point_in_triangles(), closest_point_in_triangles(), do_closest_point_test(), moab::AdaptiveKDTree::ray_intersect_triangles(), MeshInterfaceTest::test_element_get_attached_vertex_indices(), TargetCalculatorTest::test_get_refmesh_Jacobian_2D(), and TargetCalculatorTest::test_jacobian_2D().

{
    ErrorCode rval;
    const EntityHandle* conn;
    int len;

    rval = moab->get_connectivity( tri, conn, len, true );
    if( MB_SUCCESS != rval ) return rval;
    if( len != 3 ) return MB_FAILURE;
    rval = moab->get_coords( conn, 3, coords[0].array() );
    return rval;
}
static bool tri_in_set ( Interface *  moab,
EntityHandle  set,
EntityHandle  tri 
) [static]

Definition at line 1355 of file obb_test.cpp.

References moab::Range::end(), moab::Range::find(), MB_SUCCESS, and MBTRI.

Referenced by do_closest_point_test().

{
    Range tris;
    ErrorCode rval = moab->get_entities_by_type( set, MBTRI, tris );
    if( MB_SUCCESS != rval ) return false;
    Range::iterator i = tris.find( tri );
    return i != tris.end();
}
static void usage ( const char *  error,
const char *  opt 
) [static]

Definition at line 75 of file obb_test.cpp.

References moab::error(), and NAME.

{
    const char* default_message = "Invalid option";
    if( opt && !error ) error = default_message;

    std::ostream& str = error ? std::cerr : std::cout;
    if( error )
    {
        str << error;
        if( opt ) str << ": " << opt;
        str << std::endl;
    }

    str << "Usage: " << NAME << " [output opts.] [settings] [file ...]" << std::endl;
    str << "       " << NAME << " -h" << std::endl;
    if( !error )
        str << " If no file is specified the defautl test files will be used" << std::endl
            << " -h  print help text. " << std::endl
            << " -v  verbose output (may be specified multiple times) " << std::endl
            << " -q  quiet (minimal output) " << std::endl
            << " -f <x>:<y>:<z>:<i>:<j>:<k> Do ray fire" << std::endl
            << " -c  write box geometry to Cubit journal file." << std::endl
            << " -k  write leaf contents to vtk files." << std::endl
            << " -K  write contents of leaf boxes intersected by rays to vtk file." << std::endl
            << " -o <name> Save file containing tree and triangles.  Mesh tag \"OBB_ROOT\"." << std::endl
            << " -t <real> specify tolerance" << std::endl
            << " -n <int>  specify max entities per leaf node " << std::endl
            << " -l <int>  specify max tree levels" << std::endl
            << " -r <real> specify worst cell split ratio" << std::endl
            << " -R <real> specify best cell split ratio" << std::endl
            << " -s force construction of surface tree" << std::endl
            << " -S do not build surface tree." << std::endl
            << "    (Default: surface tree if file contains multiple surfaces" << std::endl
            << " -u  use unordered (Range) meshsets for tree nodes" << std::endl
            << " -U  use ordered (vector) meshsets for tree nodes" << std::endl
            << " Verbosity (-q sets to 0, each -v increments, default is 1):" << std::endl
            << "  0 - no output" << std::endl
            << "  1 - status messages and error summary" << std::endl
            << "  2 - print tree statistics " << std::endl
            << "  3 - output errors for each node" << std::endl
            << "  4 - print tree" << std::endl
            << "  5 - print tree w/ contents of each node" << std::endl
            << " See documentation for OrientedBoxTreeTool::Settings for " << std::endl
            << " a description of tree generation settings." << std::endl;
    exit( !!error );
}

Variable Documentation

std::map< std::string, std::vector< RayTest > > default_files_tests

Definition at line 33 of file obb_test.cpp.

Referenced by do_ray_fire_test(), initialize_default_files(), and main().

const char* NAME = "obb_test" [static]
std::vector< CartVect > rays [static]

Definition at line 162 of file obb_test.cpp.

Referenced by do_ray_fire_test(), and parse_ray().

const char* save_file_name = 0 [static]

Definition at line 163 of file obb_test.cpp.

Referenced by do_file(), and main().

TriOption surfTree = AUTO [static]

Definition at line 164 of file obb_test.cpp.

Referenced by do_file(), and main().

bool write_cubit = false [static]

Definition at line 159 of file obb_test.cpp.

Referenced by do_file(), do_ray_fire_test(), and main().

bool write_ray_vtk = false [static]

Definition at line 161 of file obb_test.cpp.

Referenced by do_ray_fire_test(), and main().

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines