Mesh Oriented datABase  (version 5.4.1)
Array-based unstructured mesh datastructure
Tree.hpp
Go to the documentation of this file.
00001 /**\file Tree.hpp
00002  * \class moab::Tree
00003  * \brief Parent class of various tree types in MOAB
00004  */
00005 
00006 #ifndef MOAB_TREE_HPP
00007 #define MOAB_TREE_HPP
00008 
00009 #include "moab/Interface.hpp"
00010 #include "moab/BoundBox.hpp"
00011 #include "moab/CartVect.hpp"
00012 #include "moab/FileOptions.hpp"
00013 #include "moab/TreeStats.hpp"
00014 
00015 #include <string>
00016 #include <vector>
00017 #include <cmath>
00018 #include <cassert>
00019 
00020 namespace moab
00021 {
00022 
00023 class Interface;
00024 class Range;
00025 class ElemEvaluator;
00026 
00027 class Tree
00028 {
00029   public:
00030     /** \brief Constructor (bare)
00031      * \param iface MOAB instance
00032      */
00033     Tree( Interface* iface );
00034 
00035     /** \brief Destructor
00036      */
00037     virtual ~Tree();
00038 
00039     /** \brief Destroy the tree maintained by this object, optionally checking we have the right
00040      * root. \param root If non-NULL, check that this is the root, return failure if not
00041      */
00042     virtual ErrorCode reset_tree() = 0;
00043 
00044     /** \brief Delete the entity sets associated with the tree, starting with the root and
00045      * traversing children
00046      */
00047     ErrorCode delete_tree_sets();
00048 
00049     /** Build the tree
00050      * Build a tree with the entities input.  If a non-NULL tree_root_set pointer is input,
00051      * use the pointed-to set as the root of this tree (*tree_root_set!=0) otherwise construct
00052      * a new root set and pass its handle back in *tree_root_set.  Options vary by tree type,
00053      * with a few common to all types of trees.  Common options:
00054      * MAX_PER_LEAF: max entities per leaf; default = 6
00055      * MAX_DEPTH: max depth of the tree; default = 30
00056      * MIN_WIDTH: minimum width of box, used like a tolerance; default = 1.0e-10
00057      * MESHSET_FLAGS: flags passed into meshset creation for tree nodes; should be a value from
00058      *          ENTITY_SET_PROPERTY (see Types.hpp); default = MESHSET_SET
00059      * CLEAN_UP: if false, do not delete tree sets upon tree class destruction; default = true
00060      * TAG_NAME: tag name to store tree information on tree nodes; default determined by tree type
00061      * \param entities Entities with which to build the tree
00062      * \param tree_root Root set for tree (see function description)
00063      * \param opts Options for tree (see function description)
00064      * \return Error is returned only on build failure
00065      */
00066     virtual ErrorCode build_tree( const Range& entities,
00067                                   EntityHandle* tree_root_set = NULL,
00068                                   FileOptions* options        = NULL ) = 0;
00069 
00070     /** \brief Get bounding box for tree below tree_node, or entire tree
00071      * If no tree has been built yet, returns +/- DBL_MAX for all dimensions.  Note for some tree
00072      * types, boxes are not available for non-root nodes, and this function will return failure if
00073      * non-root is passed in \param box The box for this tree \param tree_node If non-NULL, node for
00074      * which box is requested, tree root if NULL \return Only returns error on fatal condition
00075      */
00076     virtual ErrorCode get_bounding_box( BoundBox& box, EntityHandle* tree_node = NULL ) const;
00077 
00078     /** \brief Return some basic information about the tree
00079      * Stats are returned for tree starting from input node or tree root (root = 0)
00080      * \param root If non-0, give stats below and including root
00081      * \param min Minimum corner of bounding box
00082      * \param max Maximum corner of bounding box
00083      * \param max_dep Maximum depth of tree below root
00084      */
00085     virtual ErrorCode get_info( EntityHandle root, double min[3], double max[3], unsigned int& max_dep );
00086 
00087     /** \brief Find all trees, by bounding box tag
00088      */
00089     ErrorCode find_all_trees( Range& results );
00090 
00091     /** \brief Get leaf containing input position.
00092      *
00093      * Does not take into account global bounding box of tree.
00094      * - Therefore there is always one leaf containing the point.
00095      * - If caller wants to account for global bounding box, then
00096      * caller can test against that box and not call this method
00097      * at all if the point is outside the box, as there is no leaf
00098      * containing the point in that case.
00099      * \param point Point to be located in tree
00100      * \param leaf_out Leaf containing point
00101      * \param iter_tol Tolerance for convergence of point search
00102      * \param inside_tol Tolerance for inside element calculation
00103      * \param multiple_leaves Some tree types can have multiple leaves containing a point;
00104      *          if non-NULL, this parameter is returned true if multiple leaves contain
00105      *          the input point
00106      * \param start_node Start from this tree node (non-NULL) instead of tree root (NULL)
00107      * \return Non-success returned only in case of failure; not-found indicated by leaf_out=0
00108      */
00109     virtual ErrorCode point_search( const double* point,
00110                                     EntityHandle& leaf_out,
00111                                     const double iter_tol    = 1.0e-10,
00112                                     const double inside_tol  = 1.0e-6,
00113                                     bool* multiple_leaves    = NULL,
00114                                     EntityHandle* start_node = NULL,
00115                                     CartVect* params         = NULL ) = 0;
00116 
00117     /** \brief Find all leaves within a given distance from point
00118      * If dists_out input non-NULL, also returns distances from each leaf; if
00119      * point i is inside leaf, 0 is given as dists_out[i].
00120      * If params_out is non-NULL and myEval is non-NULL, will evaluate individual entities
00121      * in tree nodes and return containing entities in leaves_out.  In those cases, if params_out
00122      * is also non-NULL, will return parameters in those elements in that vector.
00123      * \param point Point to be located in tree
00124      * \param distance Distance within which to query
00125      * \param leaves_out Leaves within distance or containing point
00126      * \param iter_tol Tolerance for convergence of point search
00127      * \param inside_tol Tolerance for inside element calculation
00128      * \param dists_out If non-NULL, will contain distsances to leaves
00129      * \param params_out If non-NULL, will contain parameters of the point in the ents in leaves_out
00130      * \param start_node Start from this tree node (non-NULL) instead of tree root (NULL)
00131      */
00132     virtual ErrorCode distance_search( const double* point,
00133                                        const double distance,
00134                                        std::vector< EntityHandle >& leaves_out,
00135                                        const double iter_tol               = 1.0e-10,
00136                                        const double inside_tol             = 1.0e-6,
00137                                        std::vector< double >* dists_out    = NULL,
00138                                        std::vector< CartVect >* params_out = NULL,
00139                                        EntityHandle* start_node            = NULL ) = 0;
00140 
00141     /** \brief Return the MOAB interface associated with this tree
00142      */
00143     Interface* moab()
00144     {
00145         return mbImpl;
00146     }
00147 
00148     /** \brief Return the MOAB interface associated with this tree
00149      */
00150     const Interface* moab() const
00151     {
00152         return mbImpl;
00153     }
00154 
00155     /** \brief Get max depth set on tree */
00156     double get_max_depth()
00157     {
00158         return maxDepth;
00159     }
00160 
00161     /** \brief Get max entities per leaf set on tree */
00162     double get_max_per_leaf()
00163     {
00164         return maxPerLeaf;
00165     }
00166 
00167     /** \brief Get tree traversal stats object */
00168     TreeStats& tree_stats()
00169     {
00170         return treeStats;
00171     }
00172 
00173     /** \brief Get tree traversal stats object */
00174     const TreeStats& tree_stats() const
00175     {
00176         return treeStats;
00177     }
00178 
00179     /** \brief Create tree root and tag with bounding box
00180      */
00181     ErrorCode create_root( const double box_min[3], const double box_max[3], EntityHandle& root_handle );
00182 
00183     //! print various things about this tree
00184     virtual ErrorCode print() = 0;
00185 
00186     //! get/set the ElemEvaluator
00187     inline ElemEvaluator* get_eval()
00188     {
00189         return myEval;
00190     }
00191 
00192     //! get/set the ElemEvaluator
00193     inline void set_eval( ElemEvaluator* eval )
00194     {
00195         myEval = eval;
00196     }
00197 
00198     /** \brief Parse options for this tree, including common options for all trees
00199      * \param opts Options
00200      */
00201     virtual ErrorCode parse_options( FileOptions& opts ) = 0;
00202 
00203   protected:
00204     /** \brief Parse options common to all trees
00205      * \param options Options for representing tree; see Tree::build_tree() and subclass
00206      * build_tree() functions for allowed options \return Non-success returned from base class
00207      * function only under catastrophic circumstances; derived classes also can recognize
00208      * subclass-specific options
00209      */
00210     ErrorCode parse_common_options( FileOptions& options );
00211 
00212     /** \brief Get the box tag, possibly constructing it first
00213      * \param create_if_missing If true and it has not been made yet, make it
00214      */
00215     Tag get_box_tag( bool create_if_missing = true );
00216 
00217     // moab instance
00218     Interface* mbImpl;
00219 
00220     // bounding box for entire tree
00221     BoundBox boundBox;
00222 
00223     // max entities per leaf
00224     int maxPerLeaf;
00225 
00226     // max depth of tree
00227     int maxDepth;
00228 
00229     // tree depth, set by build_tree
00230     int treeDepth;
00231 
00232     // min width of box, handled like tolerance
00233     double minWidth;
00234 
00235     // meshset creation flags
00236     unsigned int meshsetFlags;
00237 
00238     // clean up flag
00239     bool cleanUp;
00240 
00241     // tree root
00242     EntityHandle myRoot;
00243 
00244     // tag used to mark bounding box of nodes
00245     Tag boxTag;
00246 
00247     // tag name used for boxTag
00248     std::string boxTagName;
00249 
00250     // tree traversal stats
00251     TreeStats treeStats;
00252 
00253     // element evaluator
00254     ElemEvaluator* myEval;
00255 };
00256 
00257 inline Tree::Tree( Interface* iface )
00258     : mbImpl( iface ), maxPerLeaf( 6 ), maxDepth( 30 ), treeDepth( -1 ), minWidth( 1.0e-10 ), meshsetFlags( 0 ),
00259       cleanUp( true ), myRoot( 0 ), boxTag( 0 ), myEval( 0 )
00260 {
00261 }
00262 
00263 inline Tree::~Tree() {}
00264 
00265 inline ErrorCode Tree::get_bounding_box( BoundBox& box, EntityHandle* tree_node ) const
00266 {
00267     if( ( tree_node && *tree_node == myRoot ) || !tree_node )
00268     {
00269         box = boundBox;
00270         return MB_SUCCESS;
00271     }
00272     else
00273         return MB_FAILURE;
00274 }
00275 
00276 inline ErrorCode Tree::get_info( EntityHandle /* root */,
00277                                  double* /*min[3]*/,
00278                                  double* /* max[3]*/,
00279                                  unsigned int& /*dep*/ )
00280 {
00281     return MB_NOT_IMPLEMENTED;
00282 }
00283 
00284 inline Tag Tree::get_box_tag( bool create_if_missing )
00285 {
00286     if( !boxTag && create_if_missing )
00287     {
00288         assert( boxTagName.length() > 0 );
00289         ErrorCode rval =
00290             moab()->tag_get_handle( boxTagName.c_str(), 6, MB_TYPE_DOUBLE, boxTag, MB_TAG_CREAT | MB_TAG_SPARSE );
00291         if( MB_INVALID_SIZE == rval )
00292         {
00293             // delete the tag and get it again, legacy file...
00294             rval = moab()->tag_delete( boxTag );
00295             if( MB_SUCCESS != rval ) return 0;
00296             boxTag = 0;
00297             return get_box_tag( true );
00298         }
00299 
00300         if( MB_SUCCESS != rval ) return 0;
00301     }
00302 
00303     return boxTag;
00304 }
00305 
00306 }  // namespace moab
00307 
00308 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines