![]() |
Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
00001 /*
00002 * MOAB, a Mesh-Oriented datABase, is a software component for creating,
00003 * storing and accessing finite element mesh data.
00004 *
00005 * Copyright 2004 Sandia Corporation. Under the terms of Contract
00006 * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
00007 * retains certain rights in this software.
00008 *
00009 * This library is free software; you can redistribute it and/or
00010 * modify it under the terms of the GNU Lesser General Public
00011 * License as published by the Free Software Foundation; either
00012 * version 2.1 of the License, or (at your option) any later version.
00013 *
00014 */
00015
00016 /**\file OrientedBoxTreeTool.hpp
00017 *\author Jason Kraftcheck (kraftche@cae.wisc.edu)
00018 *\date 2006-07-18
00019 */
00020
00021 #ifndef MOAB_ORIENTED_BOX_TREE_TOOL_HPP
00022 #define MOAB_ORIENTED_BOX_TREE_TOOL_HPP
00023
00024 #include "moab/Forward.hpp"
00025 #include "moab/GeomUtil.hpp"
00026 #include "moab/OrientedBox.hpp"
00027 #include
00028 #include
00029 #include
00030
00031 namespace moab
00032 {
00033
00034 class Range;
00035 class OrientedBox;
00036 class StatData;
00037 class CartVect;
00038
00039 /** \class OrientedBoxTreeTool
00040 * \brief Class for constructing and querying Hierarchical Oriented Bounding Box trees
00041 */
00042 class OrientedBoxTreeTool
00043 {
00044 public:
00045 /**\brief This provides the search range for ray intersections, measured
00046 relative to the origin of the ray.
00047
00048 first: nonnegative limit for search
00049 second: negative limit for search
00050
00051 These are const double* so that the window is always defined by
00052 pointing to other quantities, but it is not posible to change those
00053 quantities via the window.
00054 **/
00055 typedef std::pair< const double*, const double* > IntersectSearchWindow;
00056
00057 /**\brief Misc. knobs controlling tree subdivision
00058 *
00059 * Available settings for controlling when and how nodes in the tree
00060 * are split. The constructor will initialize to the default
00061 * settings. All settings except best_split_ratio control when
00062 * a node is subdivided. best_split_ratio influences the choice
00063 * of how the node is subdivided.
00064 *
00065 * A calculated ratio is used in the determination of when and how
00066 * to split a node. The ratio is calculated as:
00067 * - \f$max(\frac{|n_L - n_R|}{n_L+n_R}, f*\frac{n_I}{n_L+n_R})\f$
00068 * - \f$n_L\f$ : num entities to be placed in left child
00069 * - \f$n_R\f$ : num entities to be placed in right child
00070 * - \f$f\f$ : Settings::intersect_ratio_factor
00071 * - \f$n_I\f$: num entities intersecting split plane
00072 *
00073 * ALL of the following conditions must be met for a node to be further
00074 * subdivied:
00075 * - Depth must be less than max_depth
00076 * - Node must contain more than max_leaf_entities entities.
00077 * - The 'ratio' must be less than worst_split_ratio
00078 *
00079 * The node will be subdivided using a plane normal to one of the
00080 * box axis and containing the box center. The planes are tested
00081 * beginning with the one orthogonal to the longest box axis and
00082 * finishing with the one orthogonal to the shortest box axis. The
00083 * search will stop at the first plane for which the 'ratio' is
00084 * at least Settings::best_split_ratio . Giving Settings::best_split_ratio
00085 * a non-zero value gives preference to a split orthogonal to larger
00086 * box dimensions.
00087 */
00088 struct Settings
00089 {
00090 public:
00091 Settings(); //!< set defaults
00092 int max_leaf_entities; //!< Average number of entities per leaf
00093 int max_depth; //!< Maximum tree depth - 0->no limit
00094 //! Must be in [best_split_ratio,1.0]
00095 //! A tree node will not be split if the ratio of children
00096 //! in the child nodes is greater than this value.
00097 double worst_split_ratio;
00098 //! Must be in [0.0,worst_split_ratio]
00099 //! The search for an optimal split plane for splitting a node
00100 //! will stop if at least this ratio is achieved for the number of
00101 //! entities on each side of the split plane.
00102 double best_split_ratio;
00103 //! Flags used to create entity sets representing tree nodes
00104 unsigned int set_options;
00105 //! Check if settings are valid.
00106 bool valid() const;
00107 };
00108
00109 OrientedBoxTreeTool( Interface* i, const char* tag_name = 0, bool destroy_created_trees = false );
00110
00111 ~OrientedBoxTreeTool();
00112
00113 /**\brief Build oriented bounding box tree
00114 *
00115 * Build an oriented bounding box tree.
00116 *\param entities A list of either vertices or 2-D elements (not both)
00117 * for which to build a tree.
00118 *\param set_handle_out A handle for the entity set representing the
00119 * root of the tree.
00120 */
00121 ErrorCode build( const Range& entities, EntityHandle& set_handle_out, const Settings* settings = 0 );
00122
00123 /**\brief Build a tree of sets, where each set contains triangles.
00124 *
00125 * Build a tree of sets. Each set must contain at least one triangle
00126 * to define its geometry. Each passed set will become a leaf of
00127 * the OBB tree. Settings controlling tree depth are ignored by
00128 * this method. The tree will be as deep as it needs to be for each
00129 * input set to be a leaf.
00130 *
00131 * To build a tree representing the surfaces of a geometric volume,
00132 * 1) Build an OBB tree for each surface using the 'build' method
00133 * 2) Add each surface to the contents of the resulting OBB tree root set
00134 * 3) Build a tree from all the surface OBB tree root sets using this
00135 * method to get a combined tree for the volume.
00136 */
00137 ErrorCode join_trees( const Range& tree_roots, EntityHandle& root_set_out, const Settings* settings = 0 );
00138
00139 /**\brief Traversal statistics structure
00140 *
00141 * Structure to accumulate statistics on traversal performance. Passed optionally
00142 * to query functions, this structure contains the count of nodes visited at each
00143 * level in a tree, and the count of traversals that ended at each level.
00144 * One TrvStats structure can be used with multiple OBB trees or multiple queries,
00145 * or used on only a single tree or a single query.
00146 *
00147 * Note that these traversal statistics are not related to the stats() query below,
00148 * which calculates static information about a tree. These statistics relate
00149 * to a tree's dynamic behavior on particular operations.
00150 */
00151 class TrvStats
00152 {
00153 public:
00154 //! return counts of nodes visited, indexed by tree depth.
00155 //! the counts include both leaves and interior nodes
00156 const std::vector< unsigned >& nodes_visited() const
00157 {
00158 return nodes_visited_count;
00159 }
00160 //! return counts of tree leaves visited, indexed by tree depth
00161 const std::vector< unsigned >& leaves_visited() const
00162 {
00163 return leaves_visited_count;
00164 }
00165 //! return counts of traversals ended, indexed by tree depth
00166 const std::vector< unsigned >& traversals_ended() const
00167 {
00168 return traversals_ended_count;
00169 }
00170 //! return total number of ray-triangle intersection tests performed
00171 //! in calls made with this TrvStats
00172 unsigned int ray_tri_tests() const
00173 {
00174 return ray_tri_tests_count;
00175 }
00176 //! reset all counters on this structure
00177 void reset();
00178 //! print the contents of this structure to given stream
00179 void print( std::ostream& str ) const;
00180
00181 TrvStats() : ray_tri_tests_count( 0 ) {}
00182
00183 private:
00184 std::vector< unsigned > nodes_visited_count;
00185 std::vector< unsigned > leaves_visited_count;
00186 std::vector< unsigned > traversals_ended_count;
00187 unsigned int ray_tri_tests_count;
00188
00189 void increment( unsigned depth );
00190 void increment_leaf( unsigned depth );
00191 void end_traversal( unsigned depth );
00192
00193 friend class OrientedBoxTreeTool;
00194 };
00195
00196 /**\brief Default/Base class to provide a context for registering intersections
00197 *
00198 * To enable different logic for how individual intersections are
00199 * accumulated, depending on the usage of ray_intersect_sets().
00200 *
00201 * The API to this context has 3 parts:
00202 * * getDesiredOrient() during initialization of ray_intersect_sets to
00203 determine whether this context filters by context
00204 * * update_orient() updates the context to know the orientation of the
00205 current surface wrt to its volume during a traversal visit()
00206 * * register_intersection() offers an intersection to the context so that
00207 it can decide whether to accumulate it or ignore it
00208 *
00209 * This implementation also provides a default NOP version that accumulates
00210 * all intersections without logic.
00211 *
00212 * A reference implementation can be found in GeomQueryTool::GQT_IntRegCtxt.
00213 *
00214 */
00215
00216 class IntRegCtxt
00217 {
00218
00219 protected:
00220 std::vector< double > intersections;
00221 std::vector< EntityHandle > sets;
00222 std::vector< EntityHandle > facets;
00223
00224 public:
00225 /* provide a default behavior that will simply add the intersection data to the relevent
00226 lists with no logic or discrimination */
00227 virtual ErrorCode register_intersection( EntityHandle set,
00228 EntityHandle tri,
00229 double dist,
00230 IntersectSearchWindow& /* search_win */,
00231 GeomUtil::intersection_type /* int_type */ )
00232 {
00233 intersections.push_back( dist );
00234 sets.push_back( set );
00235 facets.push_back( tri );
00236
00237 return MB_SUCCESS;
00238 };
00239
00240 /* determine the orientation of the topological set with respect to any
00241 topological set in the context */
00242 virtual ErrorCode update_orient( EntityHandle /* set */, int* /* surfTriOrient */ )
00243 {
00244 return MB_SUCCESS;
00245 };
00246
00247 /* determine whether or not a preferred orientation is established */
00248 virtual const int* getDesiredOrient()
00249 {
00250 return NULL;
00251 };
00252
00253 std::vector< double > get_intersections()
00254 {
00255 return intersections;
00256 };
00257 std::vector< EntityHandle > get_facets()
00258 {
00259 return facets;
00260 };
00261 std::vector< EntityHandle > get_sets()
00262 {
00263 return sets;
00264 };
00265 };
00266
00267 /**\brief Intersect a ray with the triangles contained within the tree
00268 *
00269 * Intersect a ray with the triangles contained in the tree and return
00270 * the distance at which the intersection occured.
00271 *\param distances_out The output list of intersection points on the ray.
00272 *\param facets_out Handles of intersected triangles corresponding to distances_out
00273 *\param root_set The MBENTITYSET representing the root of the tree.
00274 *\param tolerance The tolerance to use in intersection checks.
00275 *\param ray_point The base point of the ray.
00276 *\param unit_ray_dir The ray direction vector (must be unit length)
00277 *\param ray_length Optional ray length (intersect segment instead of ray.)
00278 */
00279 ErrorCode ray_intersect_triangles( std::vector< double >& distances_out,
00280 std::vector< EntityHandle >& facets_out,
00281 EntityHandle root_set,
00282 double tolerance,
00283 const double ray_point[3],
00284 const double unit_ray_dir[3],
00285 const double* ray_length = 0,
00286 TrvStats* accum = 0 );
00287
00288 /**\brief Intersect ray with tree
00289 *
00290 * Return the tree nodes (as MBENTITYSET handles) for the leaf boxes
00291 * of the tree intersected by a ray.
00292 *\param boxes_out The boxes intersected by the ray.
00293 *\param tolerance The tolerance to use in intersection checks.
00294 *\param ray_point The base point of the ray.
00295 *\param unit_ray_dir The ray direction vector (must be unit length)
00296 *\param ray_length Optional ray length (intersect segment instead of ray.)
00297 */
00298 ErrorCode ray_intersect_boxes( Range& boxes_out,
00299 EntityHandle root_set,
00300 double tolerance,
00301 const double ray_point[3],
00302 const double unit_ray_dir[3],
00303 const double* ray_length = 0,
00304 TrvStats* accum = 0 );
00305
00306 /**\brief Intersect ray with triangles contained in passed MBENTITYSETs
00307 *
00308 * \param raytri_test_count If non-NULL, count of ray-triangle intersect tests
00309 * will be added to the value at which this points.
00310 */
00311 ErrorCode ray_intersect_triangles( std::vector< double >& intersection_distances_out,
00312 std::vector< EntityHandle >& intersection_facets_out,
00313 const Range& leaf_boxes_containing_tris,
00314 double tolerance,
00315 const double ray_point[3],
00316 const double unit_ray_dir[3],
00317 const double* ray_length = 0,
00318 unsigned int* raytri_test_count = 0 );
00319
00320 /**\brief Intersect a ray with the triangles contained within the tree
00321 *
00322 * Intersect a ray with the triangles contained in the tree and return
00323 * the distance at which the intersection occured.
00324 *\param distances_out The output list of intersection points on the ray.
00325 *\param sets_out The contained set encountered during the tree traversal
00326 * (see 'set_build'). For the most common use, this is the
00327 * set corresponding to the geometric surface containing the
00328 * intersected triangle.
00329 *\param facets_out Handles of intersected triangles corresponding to distances_out
00330 *\param root_set The MBENTITYSET representing the root of the tree.
00331 *\param tolerance The tolerance to use in intersection checks.
00332 *\param ray_point The base point of the ray.
00333 *\param unit_ray_dir The ray direction vector (must be unit length)
00334 *\param search_win An interval that defines the current window in which the
00335 * an intersection is being sought: (nonnegative, negative)
00336 *\param register_intersection A context for assessing and registering intersections
00337 * derived from IntRegCtxt
00338 *\param accum Optional class for tree traversal statistics.
00339 */
00340
00341 ErrorCode ray_intersect_sets( std::vector< double >& distances_out,
00342 std::vector< EntityHandle >& sets_out,
00343 std::vector< EntityHandle >& facets_out,
00344 EntityHandle root_set,
00345 double tolerance,
00346 const double ray_point[3],
00347 const double unit_ray_dir[3],
00348 IntersectSearchWindow& search_win,
00349 IntRegCtxt& register_intersection,
00350 TrvStats* accum = 0 );
00351
00352 /*\brief Version that doesn't require a search window or an intersection registration context
00353 *
00354 *
00355 */
00356 ErrorCode ray_intersect_sets( std::vector< double >& distances_out,
00357 std::vector< EntityHandle >& sets_out,
00358 std::vector< EntityHandle >& facets_out,
00359 EntityHandle root_set,
00360 double tolerance,
00361 const double ray_point[3],
00362 const double unit_ray_dir[3],
00363 const double* ray_length = 0,
00364 TrvStats* accum = 0 );
00365
00366 ErrorCode ray_intersect_sets( EntityHandle root_set,
00367 double tolerance,
00368 const double ray_point[3],
00369 const double unit_ray_dir[3],
00370 IntersectSearchWindow& search_win,
00371 IntRegCtxt& register_intersection,
00372 TrvStats* accum = 0 );
00373
00374 /**\brief Find closest surface, facet in surface, and location on facet
00375 *
00376 * Find the closest location in the tree to the specified location.
00377 *\param point Location to search from
00378 *\param point_out Closest location on closest facet
00379 *\param facet_out Closest 2D element to input position
00380 *\param set_out Set containing closest facet. 0 if tree was not
00381 * constructed using 'set_build'
00382 */
00383 ErrorCode closest_to_location( const double* point,
00384 EntityHandle tree_root,
00385 double* point_out,
00386 EntityHandle& facet_out,
00387 EntityHandle* set_out = 0,
00388 TrvStats* accum = 0 );
00389
00390 /**\brief Find closest facet(s) to input position.
00391 *
00392 * Find the closest location(s) in the tree to the specified location.
00393 *\param point Location to search from
00394 *\param facets_out Closest 2D elements to input position are appended to this list
00395 *\param sets_out If non-null, sets owning facets are appended to this list.
00396 */
00397 ErrorCode closest_to_location( const double* point,
00398 EntityHandle tree_root,
00399 double tolerance,
00400 std::vector< EntityHandle >& facets_out,
00401 std::vector< EntityHandle >* sets_out = 0,
00402 TrvStats* accum = 0 );
00403
00404 /**\brief Find facets intersected by a sphere
00405 *
00406 * Find facets intersected by a spherical volume.
00407 *\param center Sphere center
00408 *\param radius Sphere radius
00409 *\param tree_root Root of OBB tree
00410 *\param facets_out List of triangles intersecting sphere
00411 *\param sets_out If not null, sets owning facets are appended to this
00412 * list in an order corresponding to the entries in
00413 * facets_out.
00414 */
00415 ErrorCode sphere_intersect_triangles( const double* center,
00416 double radius,
00417 EntityHandle tree_root,
00418 std::vector< EntityHandle >& facets_out,
00419 std::vector< EntityHandle >* sets_out = 0,
00420 TrvStats* accum = 0 );
00421
00422 ErrorCode get_close_tris( CartVect int_pt,
00423 double tol,
00424 const EntityHandle* rootSet,
00425 const EntityHandle* geomVol,
00426 const Tag* senseTag,
00427 std::vector< EntityHandle >& close_tris,
00428 std::vector< int >& close_senses );
00429
00430 /**\brief Get oriented box at node in tree
00431 *
00432 * Get the oriented box for a node in an oriented bounding box tree.
00433 */
00434 ErrorCode box( EntityHandle node_set, double center[3], double axis1[3], double axis2[3], double axis3[3] );
00435
00436 ErrorCode delete_tree( EntityHandle root_set );
00437
00438 /**\brief Remove obb tree root from the Oriented Box Tree Tool data structure
00439 *
00440 * Remove obb tree root from the Oriented Box Tree Tool data structure (createdTrees)
00441 */
00442 ErrorCode remove_root( EntityHandle root_set );
00443
00444 /**\brief Print out tree
00445 *
00446 * Print the tree to an output stream in a human-readable form.
00447 *\param tree_root_set Entity set representing tree root.
00448 *\param list_contents If true, list entities in each tree node,
00449 * If false, just list number of entities.
00450 *\param id_tag_name If specified, must be the name of an existing
00451 * integer tag containing an ID for the entities.
00452 * Not used if list_contents is false.
00453 */
00454 void print( EntityHandle tree_root_set,
00455 std::ostream& stream,
00456 bool list_contents = false,
00457 const char* id_tag_name = 0 );
00458
00459 /**\brief Print tree statistics
00460 *
00461 * Print misc. stats. describing tree
00462 */
00463 ErrorCode stats( EntityHandle tree_root_set, std::ostream& stream );
00464
00465 /**\brief Get tree statistics
00466 *
00467 * Get summary stats. describing tree
00468 * \param set Root of tree for which data is requested
00469 * \param total_entities Entities in tree
00470 * \param root_volume Total volume of root box
00471 * \param tot_node_volume Total volume in all nodes
00472 * \param tot_to_root_volume Ratio of total / root volume
00473 * \param tree_height Maximum height of tree, from root to leaf
00474 * \param node_count Number of nodes in tree
00475 * \param num_leaves Number of leaf nodes in tree
00476 */
00477 ErrorCode stats( EntityHandle set,
00478 unsigned& entities_in_tree,
00479 double& root_volume,
00480 double& tot_node_volume,
00481 double& tot_to_root_volume,
00482 unsigned& tree_height,
00483 unsigned& node_count,
00484 unsigned& num_leaves );
00485
00486 /** \brief Implement this and pass instance to preorder_traverse
00487 *
00488 * This interface may be implemented and an instance passed to
00489 * preorder_traverse to define some operation to do when traversing
00490 * the tree.
00491 */
00492 class Op
00493 {
00494 public:
00495 /**\brief Visit a node in the tree during a traversal.
00496 *
00497 * This method is called for each node in the tree visited
00498 * during a pre-order traversal.
00499 *\param node The EntityHandle for the entity set for the tree node.
00500 *\param depth The current depth in the tree.
00501 *\param descend Output: if false, traversal will skip children
00502 * of the current node, or if the current node is a
00503 * leaf, the 'leaf' method will not be called.
00504 */
00505 virtual ErrorCode visit( EntityHandle node, int depth, bool& descend ) = 0;
00506
00507 /**\brief Process a leaf node during tree traversal */
00508 virtual ErrorCode leaf( EntityHandle node ) = 0;
00509
00510 virtual ~Op(); // probably isn't necessary in this case, and
00511 // does nothing, but lots of compilers warn if
00512 // virtual function but no virtual destructor.
00513 };
00514
00515 /**\brief Visitor pattern - do operation for each tree node
00516 *
00517 * Do a preorder traversal of the tree, calling the method
00518 * in the passed operation instance for each node in the tree.
00519 * Parent node is visited before either child (pre-order traversal).
00520 * If operator method passes back the 'descend' argument as false,
00521 * traversal will not descend to the children of the current node.
00522 */
00523 ErrorCode preorder_traverse( EntityHandle root_set, Op& operation, TrvStats* accum = 0 );
00524
00525 Interface* get_moab_instance() const
00526 {
00527 return instance;
00528 }
00529
00530 struct SetData;
00531
00532 /**\brief Get oriented box at node in tree
00533 *
00534 * Get the oriented box for a node in an oriented bounding box tree.
00535 *
00536 * NOTE: This function is provided for internal MOAB use only.
00537 * The definition of OrientedBox is not available as a part
00538 * of the MOAB API
00539 */
00540 ErrorCode box( EntityHandle node_set, OrientedBox& box );
00541
00542 private:
00543 ErrorCode build_tree( const Range& entities, EntityHandle& set, int depth, const Settings& settings );
00544
00545 ErrorCode build_sets( std::list< SetData >& sets, EntityHandle& node_set, int depth, const Settings& settings );
00546
00547 ErrorCode recursive_stats( OrientedBoxTreeTool* tool,
00548 Interface* instance,
00549 EntityHandle set,
00550 int depth,
00551 StatData& data,
00552 unsigned& count_out,
00553 CartVect& dimensions_out );
00554
00555 Interface* instance;
00556 Tag tagHandle;
00557
00558 bool cleanUpTrees;
00559 std::vector< EntityHandle > createdTrees;
00560 };
00561
00562 } // namespace moab
00563
00564 #endif