MOAB: Mesh Oriented datABase  (version 5.3.1)
TreeValidator Class Reference
+ Inheritance diagram for TreeValidator:
+ Collaboration diagram for TreeValidator:

Public Member Functions

 TreeValidator (Interface *instance_ptr, OrientedBoxTreeTool *tool_ptr, bool print_errors, std::ostream &str, double tol, bool surfs, OrientedBoxTreeTool::Settings s)
bool is_valid () const
virtual ErrorCode visit (EntityHandle node, int depth, bool &descend)
 Visit a node in the tree during a traversal.
virtual ErrorCode leaf (EntityHandle)
 Process a leaf node during tree traversal.

Public Attributes

unsigned entity_count
unsigned loose_box_count
unsigned child_outside_count
unsigned entity_outside_count
unsigned num_entities_outside
unsigned non_ortho_count
unsigned error_count
unsigned empty_leaf_count
unsigned non_empty_non_leaf_count
unsigned entity_invalid_count
unsigned unsorted_axis_count
unsigned non_unit_count
unsigned duplicate_entity_count
unsigned bad_outer_radius_count
unsigned missing_surface_count
unsigned multiple_surface_count
std::set< EntityHandleseen
int surface_depth
EntityHandle surface_handle

Private Member Functions

void print (EntityHandle handle, const char *string)
ErrorCode error (EntityHandle handle, const char *string)

Private Attributes

Interface *const instance
OrientedBoxTreeTool *const tool
const bool printing
const double epsilon
bool surfaces
std::ostream & stream
OrientedBoxTreeTool::Settings settings

Detailed Description

Definition at line 314 of file obb_test.cpp.


Constructor & Destructor Documentation

TreeValidator::TreeValidator ( Interface instance_ptr,
OrientedBoxTreeTool tool_ptr,
bool  print_errors,
std::ostream &  str,
double  tol,
bool  surfs,
OrientedBoxTreeTool::Settings  s 
) [inline]

Member Function Documentation

ErrorCode TreeValidator::error ( EntityHandle  handle,
const char *  string 
) [inline, private]

Definition at line 330 of file obb_test.cpp.

References error_count, MB_SUCCESS, and MBMesquite::print().

    {
        ++error_count;
        print( handle, string );
        return MB_SUCCESS;
    }
virtual ErrorCode TreeValidator::leaf ( EntityHandle  node) [inline, virtual]

Process a leaf node during tree traversal.

Implements moab::OrientedBoxTreeTool::Op.

Definition at line 380 of file obb_test.cpp.

References MB_SUCCESS.

    {
        return MB_SUCCESS;
    }
void TreeValidator::print ( EntityHandle  handle,
const char *  string 
) [inline, private]

Definition at line 325 of file obb_test.cpp.

    {
        if( printing ) stream << instance->id_from_handle( handle ) << ": " << string << std::endl;
    }
ErrorCode TreeValidator::visit ( EntityHandle  node,
int  depth,
bool &  descend 
) [virtual]

Visit a node in the tree during a traversal.

This method is called for each node in the tree visited during a pre-order traversal.

Parameters:
nodeThe EntityHandle for the entity set for the tree node.
depthThe current depth in the tree.
descendOutput: if false, traversal will skip children of the current node, or if the current node is a leaf, the 'leaf' method will not be called.

Implements moab::OrientedBoxTreeTool::Op.

Definition at line 386 of file obb_test.cpp.

References moab::OrientedBox::area(), moab::OrientedBox::axis(), moab::Range::begin(), box(), moab::OrientedBox::center, children, conn, moab::OrientedBox::contained(), dim, moab::CN::Dimension(), moab::Range::empty(), moab::Range::end(), epsilon, moab::Range::erase(), moab::error(), error_count, ErrorCode, moab::OrientedBox::length, length(), moab::CartVect::length(), moab::Range::lower_bound(), moab::OrientedBoxTreeTool::Settings::max_depth, moab::OrientedBoxTreeTool::Settings::max_leaf_entities, MB_SUCCESS, MBENTITYSET, n, MBMesquite::print(), moab::OrientedBox::radius, settings, moab::Range::size(), moab::tolerance, and moab::OrientedBox::volume().

{
    ErrorCode rval;
    descend = true;

    Range contents;
    rval = instance->get_entities_by_handle( node, contents );
    if( MB_SUCCESS != rval ) return error( node, "Error getting contents of tree node.  Corrupt tree?" );
    entity_count += contents.size();

    if( surfaces )
    {
        // if no longer in subtree for previous surface, clear
        if( depth <= surface_depth ) surface_depth = -1;

        EntityHandle surface      = 0;
        Range::iterator surf_iter = contents.lower_bound( MBENTITYSET );
        if( surf_iter != contents.end() )
        {
            surface = *surf_iter;
            contents.erase( surf_iter );
        }

        if( surface )
        {
            if( surface_depth >= 0 )
            {
                ++multiple_surface_count;
                print( node, "Multiple surfaces in encountered in same subtree." );
            }
            else
            {
                surface_depth  = depth;
                surface_handle = surface;
            }
        }
    }

    std::vector< EntityHandle > children;
    rval = tool->get_moab_instance()->get_child_meshsets( node, children );
    if( MB_SUCCESS != rval || ( !children.empty() && children.size() != 2 ) )
        return error( node, "Error getting children.  Corrupt tree?" );

    OrientedBox box;
    rval = tool->box( node, box );
    if( MB_SUCCESS != rval ) return error( node, "Error getting oriented box from tree node.  Corrupt tree?" );

    if( children.empty() && contents.empty() )
    {
        ++empty_leaf_count;
        print( node, "Empty leaf node.\n" );
    }
    else if( !children.empty() && !contents.empty() )
    {
        ++non_empty_non_leaf_count;
        print( node, "Non-leaf node is not empty." );
    }

    if( surfaces && children.empty() && surface_depth < 0 )
    {
        ++missing_surface_count;
        print( node, "Reached leaf node w/out encountering any surface set." );
    }

    double dot_epsilon = epsilon * ( box.axis( 0 ) + box.axis( 1 ) + box.axis( 2 ) ).length();
    if( box.axis( 0 ) % box.axis( 1 ) > dot_epsilon || box.axis( 0 ) % box.axis( 2 ) > dot_epsilon ||
        box.axis( 1 ) % box.axis( 2 ) > dot_epsilon )
    {
        ++non_ortho_count;
        print( node, "Box axes are not orthogonal" );
    }

    if( !children.empty() )
    {
        for( int i = 0; i < 2; ++i )
        {
            OrientedBox other_box;
            rval = tool->box( children[i], other_box );
            if( MB_SUCCESS != rval )
                return error( children[i], " Error getting oriented box from tree node.  Corrupt tree?" );
            //      else if (!box.contained( other_box, epsilon )) {
            //        ++child_outside_count;
            //        print( children[i], "Parent box does not contain child box." );
            //        char string[64];
            //        sprintf(string, "     Volume ratio is %f", other_box.volume()/box.volume() );
            //        print( children [i], string );
            //      }
            else
            {
                double vol_ratio = other_box.volume() / box.volume();
                if( vol_ratio > 2.0 )
                {
                    char string[64];
                    sprintf( string, "child/parent volume ratio is %f", vol_ratio );
                    print( children[i], string );
                    sprintf( string, "   child/parent area ratio is %f", other_box.area() / box.area() );
                    print( children[i], string );
                }
            }
        }
    }

    bool bad_element        = false;
    bool bad_element_handle = false;
    bool bad_element_conn   = false;
    bool duplicate_element  = false;
    int num_outside         = 0;
    bool boundary[6]        = { false, false, false, false, false, false };
    for( Range::iterator it = contents.begin(); it != contents.end(); ++it )
    {
        EntityType type = instance->type_from_handle( *it );
        int dim         = CN::Dimension( type );
        if( dim != 2 )
        {
            bad_element = true;
            continue;
        }

        const EntityHandle* conn;
        int conn_len;
        rval = instance->get_connectivity( *it, conn, conn_len );
        if( MB_SUCCESS != rval )
        {
            bad_element_handle = true;
            continue;
        }

        std::vector< CartVect > coords( conn_len );
        rval = instance->get_coords( conn, conn_len, coords[0].array() );
        if( MB_SUCCESS != rval )
        {
            bad_element_conn = true;
            continue;
        }

        bool outside = false;
        for( std::vector< CartVect >::iterator j = coords.begin(); j != coords.end(); ++j )
        {
            if( !box.contained( *j, epsilon ) )
                outside = true;
            else
                for( int d = 0; d < 3; ++d )
                {
#if MB_ORIENTED_BOX_UNIT_VECTORS
                    double n = box.axis( d ) % ( *j - box.center );
                    if( fabs( n - box.length[d] ) <= epsilon ) boundary[2 * d] = true;
                    if( fabs( n + box.length[d] ) <= epsilon ) boundary[2 * d + 1] = true;
#else
                    double ln   = box.axis( d ).length();
                    CartVect v1 = *j - box.center - box.axis[d];
                    CartVect v2 = *j - box.center + box.axis[d];
                    if( fabs( v1 % box.axis[d] ) <= ln * epsilon ) boundary[2 * d] = true;
                    if( fabs( v2 % box.axis[d] ) <= ln * epsilon ) boundary[2 * d + 1] = true;
#endif
                }
        }
        if( outside ) ++num_outside;

        if( !seen.insert( *it ).second )
        {
            duplicate_element = true;
            ++duplicate_entity_count;
        }
    }

    CartVect alength( box.axis( 0 ).length(), box.axis( 1 ).length(), box.axis( 2 ).length() );
#if MB_ORIENTED_BOX_UNIT_VECTORS
    CartVect length = box.length;
#else
    CartVect length = alength;
#endif

    if( length[0] > length[1] || length[0] > length[2] || length[1] > length[2] )
    {
        ++unsorted_axis_count;
        print( node, "Box axes are not ordered from shortest to longest." );
    }

#if MB_ORIENTED_BOX_UNIT_VECTORS
    if( fabs( alength[0] - 1.0 ) > epsilon || fabs( alength[1] - 1.0 ) > epsilon || fabs( alength[2] - 1.0 ) > epsilon )
    {
        ++non_unit_count;
        print( node, "Box axes are not unit vectors." );
    }
#endif

#if MB_ORIENTED_BOX_OUTER_RADIUS
    if( fabs( length.length() - box.radius ) > tolerance )
    {
        ++bad_outer_radius_count;
        print( node, "Box has incorrect outer radius." );
    }
#endif

    if( depth + 1 < settings.max_depth && contents.size() > (unsigned)( 4 * settings.max_leaf_entities ) )
    {
        char string[64];
        sprintf( string, "leaf at depth %d with %u entities", depth, (unsigned)contents.size() );
        print( node, string );
    }

    bool all_boundaries = true;
    for( int f = 0; f < 6; ++f )
        all_boundaries = all_boundaries && boundary[f];

    if( bad_element )
    {
        ++entity_invalid_count;
        print( node, "Set contained an entity with an inappropriate dimension." );
    }
    if( bad_element_handle )
    {
        ++error_count;
        print( node, "Error querying face contained in set." );
    }
    if( bad_element_conn )
    {
        ++error_count;
        print( node, "Error querying connectivity of element." );
    }
    if( duplicate_element ) { print( node, "Elements occur in multiple leaves of tree." ); }
    if( num_outside > 0 )
    {
        ++entity_outside_count;
        num_entities_outside += num_outside;
        if( printing )
            stream << instance->id_from_handle( node ) << ": " << num_outside << " elements outside box." << std::endl;
    }
    else if( !all_boundaries && !contents.empty() )
    {
        ++loose_box_count;
        print( node, "Box does not fit contained elements tightly." );
    }

    return MB_SUCCESS;
}

Member Data Documentation

Definition at line 352 of file obb_test.cpp.

Referenced by do_file().

Definition at line 341 of file obb_test.cpp.

Referenced by do_file().

Definition at line 351 of file obb_test.cpp.

Referenced by do_file().

Definition at line 346 of file obb_test.cpp.

Referenced by do_file().

Definition at line 338 of file obb_test.cpp.

Referenced by do_file().

Definition at line 348 of file obb_test.cpp.

Referenced by do_file().

Definition at line 342 of file obb_test.cpp.

Referenced by do_file().

const double TreeValidator::epsilon [private]

Definition at line 320 of file obb_test.cpp.

Definition at line 345 of file obb_test.cpp.

Referenced by do_file().

Definition at line 317 of file obb_test.cpp.

Definition at line 340 of file obb_test.cpp.

Referenced by do_file().

Definition at line 353 of file obb_test.cpp.

Referenced by do_file().

Definition at line 354 of file obb_test.cpp.

Referenced by do_file().

Definition at line 347 of file obb_test.cpp.

Referenced by do_file().

Definition at line 344 of file obb_test.cpp.

Referenced by do_file().

Definition at line 350 of file obb_test.cpp.

Referenced by do_file().

Definition at line 343 of file obb_test.cpp.

Referenced by do_file().

const bool TreeValidator::printing [private]

Definition at line 319 of file obb_test.cpp.

Definition at line 355 of file obb_test.cpp.

std::ostream& TreeValidator::stream [private]

Definition at line 322 of file obb_test.cpp.

Definition at line 356 of file obb_test.cpp.

bool TreeValidator::surfaces [private]

Definition at line 321 of file obb_test.cpp.

Definition at line 318 of file obb_test.cpp.

Definition at line 349 of file obb_test.cpp.

Referenced by do_file().

List of all members.


The documentation for this class was generated from the following file:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines