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_SKINNER_HPP
17 #define MOAB_SKINNER_HPP
18
19 #include "moab/Forward.hpp"
20 #include "moab/Range.hpp"
21 #include <vector>
22
23 namespace moab
24 {
25
26 class ScdBox;
27
28 /** \class Skinner
29 * \brief Class for constructing and querying skin of a mesh
30 * Class for constructing and querying skin of a mesh, defined as the outside lower-dimensional
31 * boundary of a mesh or a given set of entities. This class provides options for finding the
32 * forward- and reverse-oriented members of the skin. Several methods are available for computing
33 * the skin, e.g. using geometric topology sets, vertex-entity adjacencies, or directly from
34 * (n-1)-dimensional entities.
35 */
36 class Skinner
37 {
38
39 enum direction
40 {
41 FORWARD = 1,
42 REVERSE = -1
43 };
44
45 protected:
46 //! the MB instance that this works with
47 Interface* thisMB;
48
49 Tag mDeletableMBTag;
50 Tag mAdjTag;
51 int mTargetDim;
52
53 public:
54 //! constructor, takes mdb instance
55 Skinner( Interface* mdb ) : thisMB( mdb ), mDeletableMBTag( 0 ), mAdjTag( 0 ), mTargetDim( 0 ) {}
56
57 //! destructor
58 ~Skinner();
59
60 ErrorCode find_geometric_skin( const EntityHandle meshset, Range& forward_target_entities );
61
62 /**\brief will accept entities all of one dimension and
63 * return entities of n-1 dimension; NOTE: get_vertices argument controls whether
64 * vertices or entities of n-1 dimension are returned, and only one of these is allowed
65 * (i.e. this function returns only vertices or (n-1)-dimensional entities, but not both)
66 * \param entities The elements for which to find the skin
67 * \param get_vertices If true, vertices on the skin are returned
68 * in the range, otherwise elements are returned
69 * \param output_handles Range holding skin entities returned
70 * \param output_reverse_handles Range holding entities on skin which
71 * are reversed wrt entities
72 * \param create_vert_elem_adjs If true, this function will cause
73 * vertex-element adjacencies to be generated
74 * \param create_skin_elements If true, this function will cause creation
75 * of skin entities, otherwise only skin entities already extant
76 * will be returned
77 */
78 ErrorCode find_skin( const EntityHandle meshset,
79 const Range& entities,
80 bool get_vertices,
81 Range& output_handles,
82 Range* output_reverse_handles = 0,
83 bool create_vert_elem_adjs = false,
84 bool create_skin_elements = true,
85 bool look_for_scd = false );
86
87 /**\brief will accept entities all of one dimension and
88 * return entities of n-1 dimension; NOTE: get_vertices argument controls whether
89 * vertices or entities of n-1 dimension are returned, and only one of these is allowed
90 * (i.e. this function returns only vertices or (n-1)-dimensional entities, but not both)
91 * \param entities Pointer to elements for which to find the skin
92 * \param num_entities Number of entities in vector
93 * \param get_vertices If true, vertices on the skin are returned
94 * in the range, otherwise elements are returned
95 * \param output_handles Range holding skin entities returned
96 * \param output_reverse_handles Range holding entities on skin which
97 * are reversed wrt entities
98 * \param create_vert_elem_adjs If true, this function will cause
99 * vertex-element adjacencies to be generated
100 * \param create_skin_elements If true, this function will cause creation
101 * of skin entities, otherwise only skin entities already extant
102 * will be returned
103 */
104 ErrorCode find_skin( const EntityHandle this_set,
105 const EntityHandle* entities,
106 int num_entities,
107 bool get_vertices,
108 Range& output_handles,
109 Range* output_reverse_handles = 0,
110 bool create_vert_elem_adjs = false,
111 bool create_skin_elements = true,
112 bool look_for_scd = false );
113
114 /**\brief get skin entities of prescribed dimension
115 * \param entities The elements for which to find the skin
116 * \param dim Dimension of skin entities requested
117 * \param skin_entities Range holding skin entities returned
118 * \param create_vert_elem_adjs If true, this function will cause
119 * vertex-element adjacencies to be generated
120 */
121 ErrorCode find_skin( const EntityHandle this_set,
122 const Range& entities,
123 int dim,
124 Range& skin_entities,
125 bool create_vert_elem_adjs = false,
126 bool create_skin_elements = true );
127
128 ErrorCode classify_2d_boundary( const Range& boundary,
129 const Range& bar_elements,
130 EntityHandle boundary_edges,
131 EntityHandle inferred_edges,
132 EntityHandle non_manifold_edges,
133 EntityHandle other_edges,
134 int& number_boundary_nodes );
135
136 //! given a skin of dimension 2, will classify and return edges
137 //! as boundary, inferred, and non-manifold, and the rest (other)
138 ErrorCode classify_2d_boundary( const Range& boundary,
139 const Range& mesh_1d_elements,
140 Range& boundary_edges,
141 Range& inferred_edges,
142 Range& non_manifold_edges,
143 Range& other_edges,
144 int& number_boundary_nodes );
145
146 protected:
147 ErrorCode initialize();
148
149 ErrorCode deinitialize();
150
151 ErrorCode find_skin_noadj( const Range& source_entities,
152 Range& forward_target_entities,
153 Range& reverse_target_entities );
154
155 ErrorCode add_adjacency( EntityHandle entity );
156
157 void add_adjacency( EntityHandle entity, const EntityHandle* conn, const int num_nodes );
158
159 ErrorCode remove_adjacency( EntityHandle entity );
160
161 bool entity_deletable( EntityHandle entity );
162
163 void find_match( EntityType type,
164 const EntityHandle* conn,
165 const int num_nodes,
166 EntityHandle& match,
167 Skinner::direction& direct );
168
169 bool connectivity_match( const EntityHandle* conn1,
170 const EntityHandle* conn2,
171 const int num_verts,
172 Skinner::direction& direct );
173
174 void find_inferred_edges( Range& skin_boundary,
175 Range& candidate_edges,
176 Range& inferred_edges,
177 double reference_angle_degrees );
178
179 bool has_larger_angle( EntityHandle& entity1, EntityHandle& entity2, double reference_angle_cosine );
180
181 /**\brief Find vertices on the skin of a set of mesh entities.
182 *\param entities The elements for which to find the skin. Range
183 * may NOT contain vertices, polyhedra, or entity sets.
184 * All elements in range must be of the same dimension.
185 *\param skin_verts Output: the vertices on the skin.
186 *\param skin_elems Optional output: elements representing sides of entities
187 * that are on the skin
188 *\param create_if_missing If skin_elemts is non-null and this is true,
189 * create new elements representing the sides of
190 * entities on the skin. If this is false, skin_elems
191 * will contain only those skin elements that already
192 * exist.
193 */
194 ErrorCode find_skin_vertices( const EntityHandle this_set,
195 const Range& entities,
196 Range* skin_verts = 0,
197 Range* skin_elems = 0,
198 Range* rev_elems = 0,
199 bool create_if_missing = true,
200 bool corners_only = false );
201
202 /**\brief Skin edges
203 *
204 * Return any vertices adjacent to exactly one of the input edges.
205 */
206 ErrorCode find_skin_vertices_1D( Tag tag, const Range& edges, Range& skin_verts );
207
208 /**\brief Skin faces
209 *
210 * For the set of face sides (logical edges), return
211 * vertices on such sides and/or edges equivalent to such sides.
212 *\param faces Set of toplogically 2D entities to skin.
213 *\param skin_verts If non-NULL, skin vertices will be added to this container.
214 *\param skin_edges If non-NULL, skin edges will be added to this container
215 *\param reverse_edges If skin_edges is not NULL and this is not NULL, then
216 * any existing skin edges that are reversed with respect
217 * to the skin side will be placed in this range instead of
218 * skin_edges. Note: this argument is ignored if skin_edges
219 * is NULL.
220 *\param create_edges If true, edges equivalent to face sides on the skin
221 * that don't already exist will be created. Note: this
222 * parameter is honored regardless of whether or not skin
223 * edges or vertices are returned.
224 *\param corners_only If true, only skin vertices that correspond to the
225 * corners of sides will be returned (i.e. no higher-order
226 * nodes.) This argument is ignored if skin_verts is NULL.
227 */
228 ErrorCode find_skin_vertices_2D( const EntityHandle this_set,
229 Tag tag,
230 const Range& faces,
231 Range* skin_verts = 0,
232 Range* skin_edges = 0,
233 Range* reverse_edges = 0,
234 bool create_edges = false,
235 bool corners_only = false );
236
237 /**\brief Skin volume mesh
238 *
239 * For the set of element sides (logical faces), return
240 * vertices on such sides and/or faces equivalent to such sides.
241 *\param entities Set of toplogically 3D entities to skin.
242 *\param skin_verts If non-NULL, skin vertices will be added to this container.
243 *\param skin_faces If non-NULL, skin faces will be added to this container
244 *\param reverse_faces If skin_faces is not NULL and this is not NULL, then
245 * any existing skin faces that are reversed with respect
246 * to the skin side will be placed in this range instead of
247 * skin_faces. Note: this argument is ignored if skin_faces
248 * is NULL.
249 *\param create_faces If true, face equivalent to sides on the skin
250 * that don't already exist will be created. Note: this
251 * parameter is honored regardless of whether or not skin
252 * faces or vertices are returned.
253 *\param corners_only If true, only skin vertices that correspond to the
254 * corners of sides will be returned (i.e. no higher-order
255 * nodes.) This argument is ignored if skin_verts is NULL.
256 */
257 ErrorCode find_skin_vertices_3D( const EntityHandle this_set,
258 Tag tag,
259 const Range& entities,
260 Range* skin_verts = 0,
261 Range* skin_faces = 0,
262 Range* reverse_faces = 0,
263 bool create_faces = false,
264 bool corners_only = false );
265
266 ErrorCode create_side( const EntityHandle this_set,
267 EntityHandle element,
268 EntityType side_type,
269 const EntityHandle* side_corners,
270 EntityHandle& side_elem_handle_out );
271
272 bool edge_reversed( EntityHandle face, const EntityHandle edge_ends[2] );
273 bool face_reversed( EntityHandle region, const EntityHandle* face_conn, EntityType face_type );
274
275 //! look for structured box comprising source_entities, and if one is found use
276 //! structured information to find the skin
277 ErrorCode find_skin_scd( const Range& source_entities,
278 bool get_vertices,
279 Range& output_handles,
280 bool create_skin_elements );
281
282 //! skin a structured box, taking advantage of structured information
283 ErrorCode skin_box( ScdBox* box, bool get_vertices, Range& output_handles, bool create_skin_elements );
284 };
285
286 inline ErrorCode Skinner::find_skin( const EntityHandle this_set,
287 const EntityHandle* entities,
288 int num_entities,
289 bool get_vertices,
290 Range& output_handles,
291 Range* output_reverse_handles,
292 bool create_vert_elem_adjs,
293 bool create_skin_elements,
294 bool look_for_scd )
295 {
296 Range ents;
297 std::copy( entities, entities + num_entities, range_inserter( ents ) );
298 return find_skin( this_set, ents, get_vertices, output_handles, output_reverse_handles, create_vert_elem_adjs,
299 create_skin_elements, look_for_scd );
300 }
301
302 } // namespace moab
303
304 #endif