MOAB: Mesh Oriented datABase
(version 5.2.1)
|
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 #ifndef MOAB_GEOM_TOPO_TOOL_HPP 00017 #define MOAB_GEOM_TOPO_TOOL_HPP 00018 00019 #include "moab/Forward.hpp" 00020 #include "moab/Range.hpp" 00021 00022 #include <map> 00023 #include <assert.h> 00024 00025 namespace moab 00026 { 00027 00028 // forward declare this class to avoid the header leaking in here 00029 class OrientedBoxTreeTool; 00030 class GeomQueryTool; 00031 00032 /** \class GeomTopoTool 00033 * \brief Tool for interpreting geometric topology sets in MOAB database 00034 * Tool for interpreting geometric topology sets in MOAB database; see MOAB metadata_info 00035 * document for information on how geometric topology sets are read and represented. 00036 */ 00037 class GeomTopoTool 00038 { 00039 public: 00040 /** \brief Constructor (creates a GTT object) \ 00041 * Construct a GeomTopoTool object and search for geometric EntitySets if they 00042 * exist in the provided moab instance. 00043 * \param impl MOAB instance the GeomTopoTool will operate on. 00044 * \param find_geoments if specified as True, geometric objects in the provided MOAB instance 00045 will be searched for and added to the GTT. 00046 \param modelRootSet the GTT will operate only on geometric EntitySets contained by this 00047 EntitySet. If unprovided, the default value for the modelRootSet is the MOAB instance's root 00048 set, which contains everything in the instance. \param p_rootSets_vector determines the storage 00049 datastructure used to relate geometric EntitySets to their OrientedBoundingBox (OBB) Tree 00050 roots. If set to true (default) a vector will be used to store the root sets along with an 00051 EntityHandle offset for fast lookup of the root sets. If set to false, then a map will be used 00052 to link geometric EntitySets (keys) to the OBB Tree root sets (values). \param restore_rootSets 00053 determines whether or not to restore the internal index that links geomSets to their 00054 corresponding OBB Root. Only relevant if find_geoments is true. (default = true) 00055 */ 00056 GeomTopoTool( Interface* impl, bool find_geoments = false, EntityHandle modelRootSet = 0, 00057 bool p_rootSets_vector = true, bool restore_rootSets = true ); 00058 00059 ~GeomTopoTool(); 00060 00061 //! Restore parent/child links between GEOM_TOPO mesh sets 00062 ErrorCode restore_topology_from_adjacency(); 00063 //! Store sense of entity relative to wrt_entity. 00064 //!\return MB_MULTIPLE_ENTITIES_FOUND if surface already has a forward volume. 00065 //! MB_SUCCESS if successful 00066 //! otherwise whatever internal error code occured. 00067 ErrorCode set_sense( EntityHandle entity, EntityHandle wrt_entity, int sense ); 00068 //! Get the sense of entity with respect to wrt_entity 00069 //! Returns MB_ENTITY_NOT_FOUND if no relationship found 00070 ErrorCode get_sense( EntityHandle entity, EntityHandle wrt_entity, int& sense ); 00071 //! Get the sense of the surface(s) with respect to the volume 00072 ErrorCode get_surface_senses( EntityHandle volume, int num_surfs, const EntityHandle* surfs, int* senses_out ); 00073 //! Get the senses of a surface with respect to its volumes 00074 ErrorCode get_surface_senses( EntityHandle surface_ent, EntityHandle& forward_vol, EntityHandle& reverse_vol ); 00075 00076 //! Set the senses of a surface with respect to its volumes 00077 ErrorCode set_surface_senses( EntityHandle surface_ent, EntityHandle forward_vol, EntityHandle reverse_vol ); 00078 //! Get the senses of the lower dimension entity handle wrt the higher dimension entities 00079 ErrorCode get_senses( EntityHandle entity, std::vector< EntityHandle >& wrt_entities, std::vector< int >& senses ); 00080 //! Set the senses of the entity wrt multiple higher dimension entities 00081 ErrorCode set_senses( EntityHandle entity, std::vector< EntityHandle >& wrt_entities, std::vector< int >& senses ); 00082 00083 /** \brief Get the volume on the other side of a surface 00084 * 00085 * @param A surface to query 00086 * @param old_volume A volume on one side of surface 00087 * @param new_volume Output parameter for volume on the other side of surface 00088 * @return MB_SUCCESS if new_volume was set successfully, error if not. 00089 */ 00090 ErrorCode next_vol( EntityHandle surface, EntityHandle old_volume, EntityHandle& new_volume ); 00091 00092 //! Retrieve geometry sets of desired dimension from model set 00093 // 0 = verts, 1 = curves, 2 = surfs, 3 = vols 00094 ErrorCode get_gsets_by_dimension( int dim, Range& gset ); 00095 00096 /** \brief Build obb tree for the entity set given; entity can be surface or volume 00097 * 00098 * @param eh EntityHandle of the volume or surface to construct the OBB tree around 00099 */ 00100 ErrorCode construct_obb_tree( EntityHandle eh ); 00101 00102 /** \brief Get the bouding points from a bounding box 00103 * 00104 * @param volume The volume for which the bounding coordinates are requested 00105 * @param minPt Location of the min xyz corner of the volume's axis-aligned bounding box 00106 * @param maxPt Location of the max xyz corner of the volume's axis-aligned bounding box 00107 */ 00108 ErrorCode get_bounding_coords( EntityHandle volume, double minPt[3], double maxPt[3] ); 00109 00110 /** \brief Get the center point and three vectors for the OBB of a given volume 00111 * 00112 * @param volume The volume for which the OBB axes will be returned 00113 * @param center coordinates of the oriented bounding box's center point 00114 * @param axis1 scaled axis one of the oriented bounding box 00115 * @param axis2 scaled axis two of the oriented bounding box 00116 * @param axis3 scaled axis three of the oriented bounding box 00117 */ 00118 ErrorCode get_obb( EntityHandle volume, double center[3], double axis1[3], double axis2[3], double axis3[3] ); 00119 00120 /** \brief Get the other (d-1)-dimensional entity bounding a set across a (d-2)-dimensional 00121 * entity 00122 * 00123 * Given a d-dimensional entity and one (d-1)-dimensional entity, return the (d-1) dimensional 00124 * entity across a specified (d-2)-dimensional entity. For example, given a surface, edge, and 00125 * vertex, returns the other edge bounding the surface sharing the vertex. In the case of 00126 * degenerate results, e.g. two loops bounding a surface and sharing a vertex, tries to step in 00127 * positively-oriented direction. This won't always work; in those cases, will return 00128 * MB_MULTIPLE_ENTITIES_FOUND. 00129 * 00130 * In the special case where bounded is a curve, then not_this can be a vertex and across zero. 00131 * This function returns the other vertex on the curve. 00132 */ 00133 ErrorCode other_entity( EntityHandle bounded, EntityHandle not_this, EntityHandle across, EntityHandle& other ); 00134 00135 /** \brief Return the dimension of the set, or -1 if it's not a geom_dimension set 00136 */ 00137 int dimension( EntityHandle this_set ); 00138 00139 /** \brief Return the global ID of a given entity set 00140 * 00141 * @param this_set EntitySet for which the global ID will be returned 00142 */ 00143 int global_id( EntityHandle this_set ); 00144 00145 //! Map from dimension & global ID to EntityHandle 00146 EntityHandle entity_by_id( int dimension, int id ); 00147 00148 ErrorCode find_geomsets( Range* ranges = NULL ); 00149 00150 //! Restore the internal cross-referencing of geometry sets and OBB roots 00151 // The EntityHandle of an OBB Root can be tagged onto the geoemtry EntitySet 00152 // that it represents so that this relationship can be recovered across 00153 // write to/read from file. Since finding the OBB Root for a given geomset 00154 // is frequent, a faster lookup capability is enabled through data structures 00155 // in GeomTopoTool (i.e. rootSets or mapRootSets). This data structure 00156 // needs to be populated upon file read. 00157 ErrorCode restore_obb_index(); 00158 00159 //! Build obb trees for all surfaces and volumes in model set. 00160 // If make_one_vol true, joins trees from all surfaces in model into single 00161 // volume obb tree. 00162 ErrorCode construct_obb_trees( bool make_one_vol = false ); 00163 00164 //! Delete the OBB tree of a volume or surface. 00165 // If the passed entity is a volume, and the bool 'vol_only' 00166 // is True, function will delete the volume OBB tree, but 00167 // OBB trees of the surfaces that compose (are children of) 00168 // the volume will remain in tact. If the entity is a volume and 00169 // 'vol_only' is False, function will delete the volume OBB tree 00170 // along with all child surface OBB trees. 00171 ErrorCode delete_obb_tree( EntityHandle gset, bool vol_only = false ); 00172 00173 ErrorCode delete_all_obb_trees(); 00174 00175 //! Delete the root of the obb tree from the set of all roots 00176 ErrorCode remove_root( EntityHandle vol_or_surf ); 00177 00178 //! Get the root of the obbtree for a given entity 00179 ErrorCode get_root( EntityHandle vol_or_surf, EntityHandle& root ); 00180 00181 //! If constructing one volume obb tree by joining all surface trees, 00182 // get the root of that tree 00183 EntityHandle get_one_vol_root(); 00184 00185 //! Pointer to Oriented Box Tree Tool class 00186 OrientedBoxTreeTool* obb_tree() 00187 { 00188 return obbTree; 00189 } 00190 00191 //! Adds a geometry set to the range of all geometry sets, the model set, and root set 00192 // Make sure the set has the proper geometry dimension tag 00193 // This could make the obb tree out of date 00194 ErrorCode add_geo_set( EntityHandle set, int dimension, int global_id = 0 ); 00195 00196 //! Will assume no geo sets are defined for this surface 00197 // Will output a mesh_set that contains everything (all sets of interest), for proper output 00198 ErrorCode geometrize_surface_set( EntityHandle surface, EntityHandle& output ); 00199 00200 //! Checks to see if the entity is part of the model set 00201 ErrorCode is_owned_set( EntityHandle eh ); 00202 00203 //! This would be a deep copy, into a new geom topo tool 00204 // sets will be duplicated, but entities not 00205 // modelSet will be a new one; 00206 // will take as input a pointer to a std::vector of gents (surfaces and volumes, usually), 00207 // which will serve to filter the gents from modelSet (only dependents will be part of the new 00208 // gtt) if the pointer is null, all gsets in the original modelSet are duplicated 00209 ErrorCode duplicate_model( GeomTopoTool*& duplicate, std::vector< EntityHandle >* pvGEnts = NULL ); 00210 00211 //! Return the model set handle (this is the full geometry) 00212 EntityHandle get_root_model_set() 00213 { 00214 return modelSet; 00215 } 00216 00217 //! Checks that all geometric entities were created properly 00218 bool check_model(); 00219 00220 //! Should be used instead of keeping multiple ranges, for example in FBEngine 00221 const Range* geoRanges() 00222 { 00223 return geomRanges; 00224 } 00225 00226 //! Return pointer to moab instance 00227 Interface* get_moab_instance() 00228 { 00229 return mdbImpl; 00230 } 00231 00232 //! Returns the sense tag (sense2Tag) from check_face_sense_tag 00233 Tag get_sense_tag(); 00234 00235 //! Returns the global ID tag (gidTag) from check_gid_tag 00236 Tag get_gid_tag(); 00237 00238 //! Returns the geometry dimension tag (geomTag) from check_geom_tag 00239 Tag get_geom_tag(); 00240 00241 //! Returns true if obb trees have been added to the rootset 00242 bool have_obb_tree(); 00243 00244 //! returns the number of entities in the modelSet with specified geometric dimension 00245 int num_ents_of_dim( int dim ); 00246 00247 //! sets the implicit complement handle for this tool 00248 ErrorCode setup_implicit_complement(); 00249 00250 //! Get (or optionally, create) the implicit complement handle 00251 ErrorCode get_implicit_complement( EntityHandle& implicit_complement ); 00252 00253 //! detection method for the implicit complement 00254 bool is_implicit_complement( EntityHandle volume ); 00255 00256 /** \brief Discover and store the topological relationships among a set of volumes 00257 * This method may be used to discover the hierarchy that exists in a range of 00258 * volumes, that have no previous sense of hierarchy, and store it according 00259 * to the conventions of GeomTopoTool. 00260 * The following requirements about the range of flat_volumes must be met: 00261 * 1. Each volume must be represented by a single, closed surface 00262 * a. The surface meshsets have triangles and vertices as members. 00263 * b. For each "flat volume", there must be two meshsets: one for the 00264 * volume and another for the surface that encloses it. These must be 00265 * linked by a parent-child relationship. 00266 * c. The SENSE_FORWARD tag on the surface meshset must be set to be 00267 * the volume meshset it encloses. 00268 * 2. The surfaces must not touch or overlap 00269 * 00270 * After the hierarchy is established, the topological relationships between 00271 * surfaces and the volumes that enclose them are set. This involves: 00272 * 1. Setting parent-child relationship between surfaces and the volumes that 00273 * enclose them. 00274 * 2. Setting the SENSE_REVERSE tag on the surfaces to be the volume that 00275 * encloses them. 00276 * 00277 */ 00278 ErrorCode restore_topology_from_geometric_inclusion( const Range& flat_volumes ); 00279 00280 private: 00281 Interface* mdbImpl; 00282 Tag sense2Tag; 00283 Tag senseNEntsTag, senseNSensesTag; 00284 Tag geomTag; 00285 Tag gidTag; 00286 Tag nameTag; 00287 Tag obbRootTag; 00288 Tag obbGsetTag; 00289 // the model set encompasses a full topological model 00290 EntityHandle modelSet; 00291 // implicit complement handle cache 00292 EntityHandle impl_compl_handle; 00293 00294 Range geomRanges[5]; // add one more dimension, for set of gentities; by default, they will 00295 // have geom_dimension 4 00296 int maxGlobalId[5]; // one max global id for each dimension 00297 bool updated; 00298 00299 OrientedBoxTreeTool* obbTree; 00300 EntityHandle setOffset; 00301 std::vector< EntityHandle > rootSets; 00302 00303 bool m_rootSets_vector; 00304 std::map< EntityHandle, EntityHandle > mapRootSets; 00305 EntityHandle oneVolRootSet; 00306 00307 //! Creates a volume for undefined space in the model 00308 // The implicit complement is composed of all surfaces that only 00309 // have one parent volume, i.e. surfaces that are in contact with the outside 00310 // world 00311 ErrorCode generate_implicit_complement( EntityHandle& implicit_complement_set ); 00312 00313 //! Compute vertices inclusive and put on tag on sets in geom_sets 00314 ErrorCode construct_vertex_ranges( const Range& geom_sets, const Tag verts_tag ); 00315 00316 //! Given a range of geom topology sets, separate by dimension 00317 ErrorCode separate_by_dimension( const Range& geom_sets ); 00318 00319 //! Verify global id tag 00320 ErrorCode check_gid_tag( bool create = false ); 00321 00322 //! Verify geometry tag 00323 ErrorCode check_geom_tag( bool create = false ); 00324 00325 //! Verify sense face tag 00326 ErrorCode check_face_sense_tag( bool create = false ); 00327 00328 //! Verify sense edge tags 00329 ErrorCode check_edge_sense_tags( bool create = false ); 00330 00331 ErrorCode resize_rootSets(); 00332 00333 ErrorCode set_root_set( EntityHandle vol_or_surf, EntityHandle root ); 00334 00335 //! Return a range of children of a desired geometric dimension 00336 Range get_ct_children_by_dimension( const EntityHandle parent, const int desired_dimension ); 00337 00338 //! Test if volume A is enclosed by volume B 00339 // This will only produce the correct result if the conventions about 00340 // volumes listed in the restore_topology_from_geometric_inclusion are 00341 // upheld 00342 bool A_is_in_B( const EntityHandle volume_A, const EntityHandle volume_B, GeomQueryTool* GQT ); 00343 00344 //! Used by restore_topology_from_geometric_inclusion to generate the 00345 // hierarchical tree of volumes 00346 ErrorCode insert_in_tree( const EntityHandle ct_root, const EntityHandle volume, GeomQueryTool* GQT ); 00347 }; 00348 00349 inline int GeomTopoTool::num_ents_of_dim( int dim ) 00350 { 00351 assert( 0 <= dim && 3 >= dim ); 00352 return geomRanges[dim].size(); 00353 } 00354 00355 // get the root of the obbtree for a given entity 00356 inline ErrorCode GeomTopoTool::get_root( EntityHandle vol_or_surf, EntityHandle& root ) 00357 { 00358 if( m_rootSets_vector ) 00359 { 00360 unsigned int index = vol_or_surf - setOffset; 00361 root = ( index < rootSets.size() ? rootSets[index] : 0 ); 00362 } 00363 else 00364 root = mapRootSets[vol_or_surf]; 00365 return ( root ? MB_SUCCESS : MB_INDEX_OUT_OF_RANGE ); 00366 } 00367 00368 inline EntityHandle GeomTopoTool::get_one_vol_root() 00369 { 00370 return oneVolRootSet; 00371 } 00372 00373 inline Tag GeomTopoTool::get_sense_tag() 00374 { 00375 check_face_sense_tag( true ); 00376 return sense2Tag; 00377 } 00378 00379 inline Tag GeomTopoTool::get_gid_tag() 00380 { 00381 check_gid_tag( true ); 00382 return gidTag; 00383 } 00384 00385 inline Tag GeomTopoTool::get_geom_tag() 00386 { 00387 check_geom_tag( true ); 00388 return geomTag; 00389 } 00390 00391 inline bool GeomTopoTool::is_implicit_complement( EntityHandle volume ) 00392 { 00393 return volume == impl_compl_handle; 00394 } 00395 00396 } // namespace moab 00397 00398 #endif