Branch data Line data Source code
1 : : /**
2 : : * MOAB, a Mesh-Oriented datABase, is a software component for creating,
3 : : * storing and accessing finite element mesh data.
4 : : *
5 : : * Copyright 2004 Sandia Corporation. Under the terms of Contract
6 : : * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
7 : : * retains certain rights in this software.
8 : : *
9 : : * This library is free software; you can redistribute it and/or
10 : : * modify it under the terms of the GNU Lesser General Public
11 : : * License as published by the Free Software Foundation; either
12 : : * version 2.1 of the License, or (at your option) any later version.
13 : : *
14 : : */
15 : :
16 : : #ifndef MOAB_GEOM_TOPO_TOOL_HPP
17 : : #define MOAB_GEOM_TOPO_TOOL_HPP
18 : :
19 : : #include "moab/Forward.hpp"
20 : : #include "moab/Range.hpp"
21 : :
22 : : #include <map>
23 : : #include <assert.h>
24 : :
25 : : namespace moab
26 : : {
27 : :
28 : : // forward declare this class to avoid the header leaking in here
29 : : class OrientedBoxTreeTool;
30 : : class GeomQueryTool;
31 : :
32 : : /** \class GeomTopoTool
33 : : * \brief Tool for interpreting geometric topology sets in MOAB database
34 : : * Tool for interpreting geometric topology sets in MOAB database; see MOAB metadata_info
35 : : * document for information on how geometric topology sets are read and represented.
36 : : */
37 : : class GeomTopoTool
38 : : {
39 : : public:
40 : : /** \brief Constructor (creates a GTT object) \
41 : : * Construct a GeomTopoTool object and search for geometric EntitySets if they
42 : : * exist in the provided moab instance.
43 : : * \param impl MOAB instance the GeomTopoTool will operate on.
44 : : * \param find_geoments if specified as True, geometric objects in the provided MOAB instance
45 : : will be searched for and added to the GTT.
46 : : \param modelRootSet the GTT will operate only on geometric EntitySets contained by this
47 : : EntitySet. If unprovided, the default value for the modelRootSet is the MOAB instance's root
48 : : set, which contains everything in the instance. \param p_rootSets_vector determines the storage
49 : : datastructure used to relate geometric EntitySets to their OrientedBoundingBox (OBB) Tree
50 : : roots. If set to true (default) a vector will be used to store the root sets along with an
51 : : EntityHandle offset for fast lookup of the root sets. If set to false, then a map will be used
52 : : to link geometric EntitySets (keys) to the OBB Tree root sets (values). \param restore_rootSets
53 : : determines whether or not to restore the internal index that links geomSets to their
54 : : corresponding OBB Root. Only relevant if find_geoments is true. (default = true)
55 : : */
56 : : GeomTopoTool( Interface* impl, bool find_geoments = false, EntityHandle modelRootSet = 0,
57 : : bool p_rootSets_vector = true, bool restore_rootSets = true );
58 : :
59 : : ~GeomTopoTool();
60 : :
61 : : //! Restore parent/child links between GEOM_TOPO mesh sets
62 : : ErrorCode restore_topology_from_adjacency();
63 : : //! Store sense of entity relative to wrt_entity.
64 : : //!\return MB_MULTIPLE_ENTITIES_FOUND if surface already has a forward volume.
65 : : //! MB_SUCCESS if successful
66 : : //! otherwise whatever internal error code occured.
67 : : ErrorCode set_sense( EntityHandle entity, EntityHandle wrt_entity, int sense );
68 : : //! Get the sense of entity with respect to wrt_entity
69 : : //! Returns MB_ENTITY_NOT_FOUND if no relationship found
70 : : ErrorCode get_sense( EntityHandle entity, EntityHandle wrt_entity, int& sense );
71 : : //! Get the sense of the surface(s) with respect to the volume
72 : : ErrorCode get_surface_senses( EntityHandle volume, int num_surfs, const EntityHandle* surfs, int* senses_out );
73 : : //! Get the senses of a surface with respect to its volumes
74 : : ErrorCode get_surface_senses( EntityHandle surface_ent, EntityHandle& forward_vol, EntityHandle& reverse_vol );
75 : :
76 : : //! Set the senses of a surface with respect to its volumes
77 : : ErrorCode set_surface_senses( EntityHandle surface_ent, EntityHandle forward_vol, EntityHandle reverse_vol );
78 : : //! Get the senses of the lower dimension entity handle wrt the higher dimension entities
79 : : ErrorCode get_senses( EntityHandle entity, std::vector< EntityHandle >& wrt_entities, std::vector< int >& senses );
80 : : //! Set the senses of the entity wrt multiple higher dimension entities
81 : : ErrorCode set_senses( EntityHandle entity, std::vector< EntityHandle >& wrt_entities, std::vector< int >& senses );
82 : :
83 : : /** \brief Get the volume on the other side of a surface
84 : : *
85 : : * @param A surface to query
86 : : * @param old_volume A volume on one side of surface
87 : : * @param new_volume Output parameter for volume on the other side of surface
88 : : * @return MB_SUCCESS if new_volume was set successfully, error if not.
89 : : */
90 : : ErrorCode next_vol( EntityHandle surface, EntityHandle old_volume, EntityHandle& new_volume );
91 : :
92 : : //! Retrieve geometry sets of desired dimension from model set
93 : : // 0 = verts, 1 = curves, 2 = surfs, 3 = vols
94 : : ErrorCode get_gsets_by_dimension( int dim, Range& gset );
95 : :
96 : : /** \brief Build obb tree for the entity set given; entity can be surface or volume
97 : : *
98 : : * @param eh EntityHandle of the volume or surface to construct the OBB tree around
99 : : */
100 : : ErrorCode construct_obb_tree( EntityHandle eh );
101 : :
102 : : /** \brief Get the bouding points from a bounding box
103 : : *
104 : : * @param volume The volume for which the bounding coordinates are requested
105 : : * @param minPt Location of the min xyz corner of the volume's axis-aligned bounding box
106 : : * @param maxPt Location of the max xyz corner of the volume's axis-aligned bounding box
107 : : */
108 : : ErrorCode get_bounding_coords( EntityHandle volume, double minPt[3], double maxPt[3] );
109 : :
110 : : /** \brief Get the center point and three vectors for the OBB of a given volume
111 : : *
112 : : * @param volume The volume for which the OBB axes will be returned
113 : : * @param center coordinates of the oriented bounding box's center point
114 : : * @param axis1 scaled axis one of the oriented bounding box
115 : : * @param axis2 scaled axis two of the oriented bounding box
116 : : * @param axis3 scaled axis three of the oriented bounding box
117 : : */
118 : : ErrorCode get_obb( EntityHandle volume, double center[3], double axis1[3], double axis2[3], double axis3[3] );
119 : :
120 : : /** \brief Get the other (d-1)-dimensional entity bounding a set across a (d-2)-dimensional
121 : : * entity
122 : : *
123 : : * Given a d-dimensional entity and one (d-1)-dimensional entity, return the (d-1) dimensional
124 : : * entity across a specified (d-2)-dimensional entity. For example, given a surface, edge, and
125 : : * vertex, returns the other edge bounding the surface sharing the vertex. In the case of
126 : : * degenerate results, e.g. two loops bounding a surface and sharing a vertex, tries to step in
127 : : * positively-oriented direction. This won't always work; in those cases, will return
128 : : * MB_MULTIPLE_ENTITIES_FOUND.
129 : : *
130 : : * In the special case where bounded is a curve, then not_this can be a vertex and across zero.
131 : : * This function returns the other vertex on the curve.
132 : : */
133 : : ErrorCode other_entity( EntityHandle bounded, EntityHandle not_this, EntityHandle across, EntityHandle& other );
134 : :
135 : : /** \brief Return the dimension of the set, or -1 if it's not a geom_dimension set
136 : : */
137 : : int dimension( EntityHandle this_set );
138 : :
139 : : /** \brief Return the global ID of a given entity set
140 : : *
141 : : * @param this_set EntitySet for which the global ID will be returned
142 : : */
143 : : int global_id( EntityHandle this_set );
144 : :
145 : : //! Map from dimension & global ID to EntityHandle
146 : : EntityHandle entity_by_id( int dimension, int id );
147 : :
148 : : ErrorCode find_geomsets( Range* ranges = NULL );
149 : :
150 : : //! Restore the internal cross-referencing of geometry sets and OBB roots
151 : : // The EntityHandle of an OBB Root can be tagged onto the geoemtry EntitySet
152 : : // that it represents so that this relationship can be recovered across
153 : : // write to/read from file. Since finding the OBB Root for a given geomset
154 : : // is frequent, a faster lookup capability is enabled through data structures
155 : : // in GeomTopoTool (i.e. rootSets or mapRootSets). This data structure
156 : : // needs to be populated upon file read.
157 : : ErrorCode restore_obb_index();
158 : :
159 : : //! Build obb trees for all surfaces and volumes in model set.
160 : : // If make_one_vol true, joins trees from all surfaces in model into single
161 : : // volume obb tree.
162 : : ErrorCode construct_obb_trees( bool make_one_vol = false );
163 : :
164 : : //! Delete the OBB tree of a volume or surface.
165 : : // If the passed entity is a volume, and the bool 'vol_only'
166 : : // is True, function will delete the volume OBB tree, but
167 : : // OBB trees of the surfaces that compose (are children of)
168 : : // the volume will remain in tact. If the entity is a volume and
169 : : // 'vol_only' is False, function will delete the volume OBB tree
170 : : // along with all child surface OBB trees.
171 : : ErrorCode delete_obb_tree( EntityHandle gset, bool vol_only = false );
172 : :
173 : : ErrorCode delete_all_obb_trees();
174 : :
175 : : //! Delete the root of the obb tree from the set of all roots
176 : : ErrorCode remove_root( EntityHandle vol_or_surf );
177 : :
178 : : //! Get the root of the obbtree for a given entity
179 : : ErrorCode get_root( EntityHandle vol_or_surf, EntityHandle& root );
180 : :
181 : : //! If constructing one volume obb tree by joining all surface trees,
182 : : // get the root of that tree
183 : : EntityHandle get_one_vol_root();
184 : :
185 : : //! Pointer to Oriented Box Tree Tool class
186 : 4597 : OrientedBoxTreeTool* obb_tree()
187 : : {
188 : 4597 : return obbTree;
189 : : }
190 : :
191 : : //! Adds a geometry set to the range of all geometry sets, the model set, and root set
192 : : // Make sure the set has the proper geometry dimension tag
193 : : // This could make the obb tree out of date
194 : : ErrorCode add_geo_set( EntityHandle set, int dimension, int global_id = 0 );
195 : :
196 : : //! Will assume no geo sets are defined for this surface
197 : : // Will output a mesh_set that contains everything (all sets of interest), for proper output
198 : : ErrorCode geometrize_surface_set( EntityHandle surface, EntityHandle& output );
199 : :
200 : : //! Checks to see if the entity is part of the model set
201 : : ErrorCode is_owned_set( EntityHandle eh );
202 : :
203 : : //! This would be a deep copy, into a new geom topo tool
204 : : // sets will be duplicated, but entities not
205 : : // modelSet will be a new one;
206 : : // will take as input a pointer to a std::vector of gents (surfaces and volumes, usually),
207 : : // which will serve to filter the gents from modelSet (only dependents will be part of the new
208 : : // gtt) if the pointer is null, all gsets in the original modelSet are duplicated
209 : : ErrorCode duplicate_model( GeomTopoTool*& duplicate, std::vector< EntityHandle >* pvGEnts = NULL );
210 : :
211 : : //! Return the model set handle (this is the full geometry)
212 : 40 : EntityHandle get_root_model_set()
213 : : {
214 : 40 : return modelSet;
215 : : }
216 : :
217 : : //! Checks that all geometric entities were created properly
218 : : bool check_model();
219 : :
220 : : //! Should be used instead of keeping multiple ranges, for example in FBEngine
221 : 1312 : const Range* geoRanges()
222 : : {
223 : 1312 : return geomRanges;
224 : : }
225 : :
226 : : //! Return pointer to moab instance
227 : 49 : Interface* get_moab_instance()
228 : : {
229 : 49 : return mdbImpl;
230 : : }
231 : :
232 : : //! Returns the sense tag (sense2Tag) from check_face_sense_tag
233 : : Tag get_sense_tag();
234 : :
235 : : //! Returns the global ID tag (gidTag) from check_gid_tag
236 : : Tag get_gid_tag();
237 : :
238 : : //! Returns the geometry dimension tag (geomTag) from check_geom_tag
239 : : Tag get_geom_tag();
240 : :
241 : : //! Returns true if obb trees have been added to the rootset
242 : : bool have_obb_tree();
243 : :
244 : : //! returns the number of entities in the modelSet with specified geometric dimension
245 : : int num_ents_of_dim( int dim );
246 : :
247 : : //! sets the implicit complement handle for this tool
248 : : ErrorCode setup_implicit_complement();
249 : :
250 : : //! Get (or optionally, create) the implicit complement handle
251 : : ErrorCode get_implicit_complement( EntityHandle& implicit_complement );
252 : :
253 : : //! detection method for the implicit complement
254 : : bool is_implicit_complement( EntityHandle volume );
255 : :
256 : : /** \brief Discover and store the topological relationships among a set of volumes
257 : : * This method may be used to discover the hierarchy that exists in a range of
258 : : * volumes, that have no previous sense of hierarchy, and store it according
259 : : * to the conventions of GeomTopoTool.
260 : : * The following requirements about the range of flat_volumes must be met:
261 : : * 1. Each volume must be represented by a single, closed surface
262 : : * a. The surface meshsets have triangles and vertices as members.
263 : : * b. For each "flat volume", there must be two meshsets: one for the
264 : : * volume and another for the surface that encloses it. These must be
265 : : * linked by a parent-child relationship.
266 : : * c. The SENSE_FORWARD tag on the surface meshset must be set to be
267 : : * the volume meshset it encloses.
268 : : * 2. The surfaces must not touch or overlap
269 : : *
270 : : * After the hierarchy is established, the topological relationships between
271 : : * surfaces and the volumes that enclose them are set. This involves:
272 : : * 1. Setting parent-child relationship between surfaces and the volumes that
273 : : * enclose them.
274 : : * 2. Setting the SENSE_REVERSE tag on the surfaces to be the volume that
275 : : * encloses them.
276 : : *
277 : : */
278 : : ErrorCode restore_topology_from_geometric_inclusion( const Range& flat_volumes );
279 : :
280 : : private:
281 : : Interface* mdbImpl;
282 : : Tag sense2Tag;
283 : : Tag senseNEntsTag, senseNSensesTag;
284 : : Tag geomTag;
285 : : Tag gidTag;
286 : : Tag nameTag;
287 : : Tag obbRootTag;
288 : : Tag obbGsetTag;
289 : : // the model set encompasses a full topological model
290 : : EntityHandle modelSet;
291 : : // implicit complement handle cache
292 : : EntityHandle impl_compl_handle;
293 : :
294 : : Range geomRanges[5]; // add one more dimension, for set of gentities; by default, they will
295 : : // have geom_dimension 4
296 : : int maxGlobalId[5]; // one max global id for each dimension
297 : : bool updated;
298 : :
299 : : OrientedBoxTreeTool* obbTree;
300 : : EntityHandle setOffset;
301 : : std::vector< EntityHandle > rootSets;
302 : :
303 : : bool m_rootSets_vector;
304 : : std::map< EntityHandle, EntityHandle > mapRootSets;
305 : : EntityHandle oneVolRootSet;
306 : :
307 : : //! Creates a volume for undefined space in the model
308 : : // The implicit complement is composed of all surfaces that only
309 : : // have one parent volume, i.e. surfaces that are in contact with the outside
310 : : // world
311 : : ErrorCode generate_implicit_complement( EntityHandle& implicit_complement_set );
312 : :
313 : : //! Compute vertices inclusive and put on tag on sets in geom_sets
314 : : ErrorCode construct_vertex_ranges( const Range& geom_sets, const Tag verts_tag );
315 : :
316 : : //! Given a range of geom topology sets, separate by dimension
317 : : ErrorCode separate_by_dimension( const Range& geom_sets );
318 : :
319 : : //! Verify global id tag
320 : : ErrorCode check_gid_tag( bool create = false );
321 : :
322 : : //! Verify geometry tag
323 : : ErrorCode check_geom_tag( bool create = false );
324 : :
325 : : //! Verify sense face tag
326 : : ErrorCode check_face_sense_tag( bool create = false );
327 : :
328 : : //! Verify sense edge tags
329 : : ErrorCode check_edge_sense_tags( bool create = false );
330 : :
331 : : ErrorCode resize_rootSets();
332 : :
333 : : ErrorCode set_root_set( EntityHandle vol_or_surf, EntityHandle root );
334 : :
335 : : //! Return a range of children of a desired geometric dimension
336 : : Range get_ct_children_by_dimension( const EntityHandle parent, const int desired_dimension );
337 : :
338 : : //! Test if volume A is enclosed by volume B
339 : : // This will only produce the correct result if the conventions about
340 : : // volumes listed in the restore_topology_from_geometric_inclusion are
341 : : // upheld
342 : : bool A_is_in_B( const EntityHandle volume_A, const EntityHandle volume_B, GeomQueryTool* GQT );
343 : :
344 : : //! Used by restore_topology_from_geometric_inclusion to generate the
345 : : // hierarchical tree of volumes
346 : : ErrorCode insert_in_tree( const EntityHandle ct_root, const EntityHandle volume, GeomQueryTool* GQT );
347 : : };
348 : :
349 : 1 : inline int GeomTopoTool::num_ents_of_dim( int dim )
350 : : {
351 [ + - ][ - + ]: 1 : assert( 0 <= dim && 3 >= dim );
352 : 1 : return geomRanges[dim].size();
353 : : }
354 : :
355 : : // get the root of the obbtree for a given entity
356 : 5975 : inline ErrorCode GeomTopoTool::get_root( EntityHandle vol_or_surf, EntityHandle& root )
357 : : {
358 [ + + ]: 5975 : if( m_rootSets_vector )
359 : : {
360 : 5963 : unsigned int index = vol_or_surf - setOffset;
361 [ + + ]: 5963 : root = ( index < rootSets.size() ? rootSets[index] : 0 );
362 : : }
363 : : else
364 : 12 : root = mapRootSets[vol_or_surf];
365 : 5975 : return ( root ? MB_SUCCESS : MB_INDEX_OUT_OF_RANGE );
366 : : }
367 : :
368 : 1836 : inline EntityHandle GeomTopoTool::get_one_vol_root()
369 : : {
370 : 1836 : return oneVolRootSet;
371 : : }
372 : :
373 : 49 : inline Tag GeomTopoTool::get_sense_tag()
374 : : {
375 : 49 : check_face_sense_tag( true );
376 : 49 : return sense2Tag;
377 : : }
378 : :
379 : 10 : inline Tag GeomTopoTool::get_gid_tag()
380 : : {
381 : 10 : check_gid_tag( true );
382 : 10 : return gidTag;
383 : : }
384 : :
385 : 28 : inline Tag GeomTopoTool::get_geom_tag()
386 : : {
387 : 28 : check_geom_tag( true );
388 : 28 : return geomTag;
389 : : }
390 : :
391 : 6 : inline bool GeomTopoTool::is_implicit_complement( EntityHandle volume )
392 : : {
393 : 6 : return volume == impl_compl_handle;
394 : : }
395 : :
396 : : } // namespace moab
397 : :
398 : : #endif
|