Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
Class for constructing and querying skin of a mesh Class for constructing and querying skin of a mesh, defined as the outside lower-dimensional boundary of a mesh or a given set of entities. This class provides options for finding the forward- and reverse-oriented members of the skin. Several methods are available for computing the skin, e.g. using geometric topology sets, vertex-entity adjacencies, or directly from (n-1)-dimensional entities. More...
#include <Skinner.hpp>
Public Member Functions | |
Skinner (Interface *mdb) | |
constructor, takes mdb instance | |
~Skinner () | |
destructor | |
ErrorCode | find_geometric_skin (const EntityHandle meshset, Range &forward_target_entities) |
ErrorCode | find_skin (const EntityHandle meshset, const Range &entities, bool get_vertices, Range &output_handles, Range *output_reverse_handles=0, bool create_vert_elem_adjs=false, bool create_skin_elements=true, bool look_for_scd=false) |
will accept entities all of one dimension and return entities of n-1 dimension; NOTE: get_vertices argument controls whether vertices or entities of n-1 dimension are returned, and only one of these is allowed (i.e. this function returns only vertices or (n-1)-dimensional entities, but not both) | |
ErrorCode | find_skin (const EntityHandle this_set, const EntityHandle *entities, int num_entities, bool get_vertices, Range &output_handles, Range *output_reverse_handles=0, bool create_vert_elem_adjs=false, bool create_skin_elements=true, bool look_for_scd=false) |
will accept entities all of one dimension and return entities of n-1 dimension; NOTE: get_vertices argument controls whether vertices or entities of n-1 dimension are returned, and only one of these is allowed (i.e. this function returns only vertices or (n-1)-dimensional entities, but not both) | |
ErrorCode | find_skin (const EntityHandle this_set, const Range &entities, int dim, Range &skin_entities, bool create_vert_elem_adjs=false, bool create_skin_elements=true) |
get skin entities of prescribed dimension | |
ErrorCode | classify_2d_boundary (const Range &boundary, const Range &bar_elements, EntityHandle boundary_edges, EntityHandle inferred_edges, EntityHandle non_manifold_edges, EntityHandle other_edges, int &number_boundary_nodes) |
ErrorCode | classify_2d_boundary (const Range &boundary, const Range &mesh_1d_elements, Range &boundary_edges, Range &inferred_edges, Range &non_manifold_edges, Range &other_edges, int &number_boundary_nodes) |
given a skin of dimension 2, will classify and return edges as boundary, inferred, and non-manifold, and the rest (other) | |
Protected Member Functions | |
ErrorCode | initialize () |
ErrorCode | deinitialize () |
ErrorCode | find_skin_noadj (const Range &source_entities, Range &forward_target_entities, Range &reverse_target_entities) |
ErrorCode | add_adjacency (EntityHandle entity) |
void | add_adjacency (EntityHandle entity, const EntityHandle *conn, const int num_nodes) |
ErrorCode | remove_adjacency (EntityHandle entity) |
bool | entity_deletable (EntityHandle entity) |
void | find_match (EntityType type, const EntityHandle *conn, const int num_nodes, EntityHandle &match, Skinner::direction &direct) |
bool | connectivity_match (const EntityHandle *conn1, const EntityHandle *conn2, const int num_verts, Skinner::direction &direct) |
void | find_inferred_edges (Range &skin_boundary, Range &candidate_edges, Range &inferred_edges, double reference_angle_degrees) |
bool | has_larger_angle (EntityHandle &entity1, EntityHandle &entity2, double reference_angle_cosine) |
ErrorCode | find_skin_vertices (const EntityHandle this_set, const Range &entities, Range *skin_verts=0, Range *skin_elems=0, Range *rev_elems=0, bool create_if_missing=true, bool corners_only=false) |
Find vertices on the skin of a set of mesh entities. | |
ErrorCode | find_skin_vertices_1D (Tag tag, const Range &edges, Range &skin_verts) |
Skin edges. | |
ErrorCode | find_skin_vertices_2D (const EntityHandle this_set, Tag tag, const Range &faces, Range *skin_verts=0, Range *skin_edges=0, Range *reverse_edges=0, bool create_edges=false, bool corners_only=false) |
Skin faces. | |
ErrorCode | find_skin_vertices_3D (const EntityHandle this_set, Tag tag, const Range &entities, Range *skin_verts=0, Range *skin_faces=0, Range *reverse_faces=0, bool create_faces=false, bool corners_only=false) |
Skin volume mesh. | |
ErrorCode | create_side (const EntityHandle this_set, EntityHandle element, EntityType side_type, const EntityHandle *side_corners, EntityHandle &side_elem_handle_out) |
bool | edge_reversed (EntityHandle face, const EntityHandle edge_ends[2]) |
bool | face_reversed (EntityHandle region, const EntityHandle *face_conn, EntityType face_type) |
ErrorCode | find_skin_scd (const Range &source_entities, bool get_vertices, Range &output_handles, bool create_skin_elements) |
look for structured box comprising source_entities, and if one is found use structured information to find the skin | |
ErrorCode | skin_box (ScdBox *box, bool get_vertices, Range &output_handles, bool create_skin_elements) |
skin a structured box, taking advantage of structured information | |
Protected Attributes | |
Interface * | thisMB |
the MB instance that this works with | |
Tag | mDeletableMBTag |
Tag | mAdjTag |
int | mTargetDim |
Private Types | |
enum | direction { FORWARD = 1, REVERSE = -1 } |
Class for constructing and querying skin of a mesh Class for constructing and querying skin of a mesh, defined as the outside lower-dimensional boundary of a mesh or a given set of entities. This class provides options for finding the forward- and reverse-oriented members of the skin. Several methods are available for computing the skin, e.g. using geometric topology sets, vertex-entity adjacencies, or directly from (n-1)-dimensional entities.
Definition at line 36 of file Skinner.hpp.
enum moab::Skinner::direction [private] |
Definition at line 39 of file Skinner.hpp.
moab::Skinner::Skinner | ( | Interface * | mdb | ) | [inline] |
constructor, takes mdb instance
Definition at line 55 of file Skinner.hpp.
: thisMB( mdb ), mDeletableMBTag( 0 ), mAdjTag( 0 ), mTargetDim( 0 ) {}
ErrorCode moab::Skinner::add_adjacency | ( | EntityHandle | entity | ) | [protected] |
Definition at line 129 of file Skinner.cpp.
References ErrorCode, moab::Interface::get_connectivity(), mAdjTag, MB_CHK_ERR, MB_SUCCESS, moab::Interface::tag_get_data(), moab::Interface::tag_set_data(), and thisMB.
Referenced by classify_2d_boundary(), find_skin_noadj(), and initialize().
{ std::vector< EntityHandle >* adj = NULL; const EntityHandle* nodes; int num_nodes; ErrorCode result = thisMB->get_connectivity( entity, nodes, num_nodes, true );MB_CHK_ERR( result ); const EntityHandle* iter = std::min_element( nodes, nodes + num_nodes ); if( iter == nodes + num_nodes ) return MB_SUCCESS; // add this entity to the node if( thisMB->tag_get_data( mAdjTag, iter, 1, &adj ) == MB_SUCCESS && adj != NULL ) { adj->push_back( entity ); } // create a new vector and add it else { adj = new std::vector< EntityHandle >; adj->push_back( entity ); result = thisMB->tag_set_data( mAdjTag, iter, 1, &adj );MB_CHK_ERR( result ); } return MB_SUCCESS; }
void moab::Skinner::add_adjacency | ( | EntityHandle | entity, |
const EntityHandle * | conn, | ||
const int | num_nodes | ||
) | [protected] |
Definition at line 155 of file Skinner.cpp.
References mAdjTag, MB_SUCCESS, MBPOLYGON, moab::Interface::tag_get_data(), moab::Interface::tag_set_data(), thisMB, moab::TYPE_FROM_HANDLE(), and moab::CN::VerticesPerEntity().
{ std::vector< EntityHandle >* adj = NULL; const EntityHandle* iter = std::min_element( nodes, nodes + num_nodes ); if( iter == nodes + num_nodes ) return; // should not be setting adjacency lists in ho-nodes assert( TYPE_FROM_HANDLE( entity ) == MBPOLYGON || num_nodes == CN::VerticesPerEntity( TYPE_FROM_HANDLE( entity ) ) ); // add this entity to the node if( thisMB->tag_get_data( mAdjTag, iter, 1, &adj ) == MB_SUCCESS && adj != NULL ) { adj->push_back( entity ); } // create a new vector and add it else { adj = new std::vector< EntityHandle >; adj->push_back( entity ); thisMB->tag_set_data( mAdjTag, iter, 1, &adj ); } }
ErrorCode moab::Skinner::classify_2d_boundary | ( | const Range & | boundary, |
const Range & | bar_elements, | ||
EntityHandle | boundary_edges, | ||
EntityHandle | inferred_edges, | ||
EntityHandle | non_manifold_edges, | ||
EntityHandle | other_edges, | ||
int & | number_boundary_nodes | ||
) |
Definition at line 659 of file Skinner.cpp.
References moab::Interface::add_entities(), moab::Interface::clear_meshset(), ErrorCode, MB_CHK_ERR, MB_SUCCESS, and thisMB.
{ Range bedges, iedges, nmedges, oedges; ErrorCode result = classify_2d_boundary( boundary, bar_elements, bedges, iedges, nmedges, oedges, number_boundary_nodes );MB_CHK_ERR( result ); // now set the input meshsets to the output ranges result = thisMB->clear_meshset( &boundary_edges, 1 );MB_CHK_ERR( result ); result = thisMB->add_entities( boundary_edges, bedges );MB_CHK_ERR( result ); result = thisMB->clear_meshset( &inferred_edges, 1 );MB_CHK_ERR( result ); result = thisMB->add_entities( inferred_edges, iedges );MB_CHK_ERR( result ); result = thisMB->clear_meshset( &non_manifold_edges, 1 );MB_CHK_ERR( result ); result = thisMB->add_entities( non_manifold_edges, nmedges );MB_CHK_ERR( result ); result = thisMB->clear_meshset( &other_edges, 1 );MB_CHK_ERR( result ); result = thisMB->add_entities( other_edges, oedges );MB_CHK_ERR( result ); return MB_SUCCESS; }
ErrorCode moab::Skinner::classify_2d_boundary | ( | const Range & | boundary, |
const Range & | mesh_1d_elements, | ||
Range & | boundary_edges, | ||
Range & | inferred_edges, | ||
Range & | non_manifold_edges, | ||
Range & | other_edges, | ||
int & | number_boundary_nodes | ||
) |
given a skin of dimension 2, will classify and return edges as boundary, inferred, and non-manifold, and the rest (other)
Definition at line 687 of file Skinner.cpp.
References add_adjacency(), moab::Range::begin(), moab::Range::clear(), moab::Interface::create_element(), deinitialize(), moab::CN::Dimension(), moab::Range::empty(), moab::Range::end(), entity_deletable(), moab::Range::erase(), ErrorCode, moab::Range::find(), find_inferred_edges(), find_match(), moab::Interface::get_connectivity(), initialize(), moab::Range::insert(), moab::MAX_SUB_ENTITY_VERTICES, MB_CHK_ERR, MB_SUCCESS, MB_TAG_CREAT, MB_TAG_DENSE, MB_TYPE_INTEGER, MBEDGE, moab::CN::mConnectivityMap, mTargetDim, moab::CN::ConnMap::num_corners_per_sub_element, moab::CN::NumSubEntities(), moab::Range::size(), moab::CN::SubEntityNodeIndices(), moab::CN::SubEntityVertexIndices(), moab::Interface::tag_delete(), moab::Interface::tag_get_data(), moab::Interface::tag_get_handle(), moab::Interface::tag_set_data(), thisMB, moab::Interface::type_from_handle(), and moab::CN::VerticesPerEntity().
{ // clear out the edge lists boundary_edges.clear(); inferred_edges.clear(); non_manifold_edges.clear(); other_edges.clear(); number_boundary_nodes = 0; // make sure we have something to work with if( boundary.empty() ) { return MB_FAILURE; } // get our working dimensions EntityType type = thisMB->type_from_handle( *( boundary.begin() ) ); const int source_dim = CN::Dimension( type ); // make sure we can handle the working dimensions if( source_dim != 2 ) { return MB_FAILURE; } mTargetDim = source_dim - 1; // initialize initialize(); // additional initialization for this routine // define a tag for MBEDGE which counts the occurrences of the edge below // default should be 0 for existing edges, if any Tag count_tag; int default_count = 0; ErrorCode result = thisMB->tag_get_handle( 0, 1, MB_TYPE_INTEGER, count_tag, MB_TAG_DENSE | MB_TAG_CREAT, &default_count );MB_CHK_ERR( result ); Range::const_iterator iter, end_iter; end_iter = boundary.end(); std::vector< EntityHandle > conn; EntityHandle sub_conn[2]; EntityHandle match; Range edge_list; Range boundary_nodes; Skinner::direction direct; EntityType sub_type; int num_edge, num_sub_ent_vert; const short* edge_verts; // now, process each entity in the boundary for( iter = boundary.begin(); iter != end_iter; ++iter ) { // get the connectivity of this entity conn.clear(); result = thisMB->get_connectivity( &( *iter ), 1, conn, false ); assert( MB_SUCCESS == result ); // add node handles to boundary_node range std::copy( conn.begin(), conn.begin() + CN::VerticesPerEntity( type ), range_inserter( boundary_nodes ) ); type = thisMB->type_from_handle( *iter ); // get connectivity of each n-1 dimension entity (edge in this case) const struct CN::ConnMap* conn_map = &( CN::mConnectivityMap[type][0] ); num_edge = CN::NumSubEntities( type, 1 ); for( int i = 0; i < num_edge; i++ ) { edge_verts = CN::SubEntityVertexIndices( type, 1, i, sub_type, num_sub_ent_vert ); assert( sub_type == MBEDGE && num_sub_ent_vert == 2 ); sub_conn[0] = conn[edge_verts[0]]; sub_conn[1] = conn[edge_verts[1]]; int num_sub_nodes = conn_map->num_corners_per_sub_element[i]; // see if we can match this connectivity with // an existing entity find_match( MBEDGE, sub_conn, num_sub_nodes, match, direct ); // if there is no match, create a new entity if( match == 0 ) { EntityHandle tmphndl = 0; int indices[MAX_SUB_ENTITY_VERTICES]; EntityType new_type; int num_new_nodes; CN::SubEntityNodeIndices( type, conn.size(), 1, i, new_type, num_new_nodes, indices ); for( int j = 0; j < num_new_nodes; j++ ) sub_conn[j] = conn[indices[j]]; result = thisMB->create_element( new_type, sub_conn, num_new_nodes, tmphndl ); assert( MB_SUCCESS == result ); add_adjacency( tmphndl, sub_conn, num_sub_nodes ); // target_entities.insert(tmphndl); edge_list.insert( tmphndl ); int count; result = thisMB->tag_get_data( count_tag, &tmphndl, 1, &count ); assert( MB_SUCCESS == result ); count++; result = thisMB->tag_set_data( count_tag, &tmphndl, 1, &count ); assert( MB_SUCCESS == result ); } else { // We found a match, we must increment the count on the match int count; result = thisMB->tag_get_data( count_tag, &match, 1, &count ); assert( MB_SUCCESS == result ); count++; result = thisMB->tag_set_data( count_tag, &match, 1, &count ); assert( MB_SUCCESS == result ); // if the entity is not deletable, it was pre-existing in // the database. We therefore may need to add it to the // edge_list. Since it will not hurt the range, we add // whether it was added before or not if( !entity_deletable( match ) ) { edge_list.insert( match ); } } } } // Any bar elements in the model should be classified separately // If the element is in the skin edge_list, then it should be put in // the non-manifold edge list. Edges not in the edge_list are stand-alone // bars, and we make them simply boundary elements if( !bar_elements.empty() ) { Range::iterator bar_iter; for( iter = bar_elements.begin(); iter != bar_elements.end(); ++iter ) { EntityHandle handle = *iter; bar_iter = edge_list.find( handle ); if( bar_iter != edge_list.end() ) { // it is in the list, erase it and put in non-manifold list edge_list.erase( bar_iter ); non_manifold_edges.insert( handle ); } else { // not in the edge list, make it a boundary edge boundary_edges.insert( handle ); } } } // now all edges should be classified. Go through the edge_list, // and put all in the appropriate lists Range::iterator edge_iter, edge_end_iter; edge_end_iter = edge_list.end(); int count; for( edge_iter = edge_list.begin(); edge_iter != edge_end_iter; ++edge_iter ) { // check the count_tag result = thisMB->tag_get_data( count_tag, &( *edge_iter ), 1, &count ); assert( MB_SUCCESS == result ); if( count == 1 ) { boundary_edges.insert( *edge_iter ); } else if( count == 2 ) { other_edges.insert( *edge_iter ); } else { non_manifold_edges.insert( *edge_iter ); } } // find the inferred edges from the other_edge_list double min_angle_degrees = 20.0; find_inferred_edges( const_cast< Range& >( boundary ), other_edges, inferred_edges, min_angle_degrees ); // we now want to remove the inferred_edges from the other_edges Range temp_range; std::set_difference( other_edges.begin(), other_edges.end(), inferred_edges.begin(), inferred_edges.end(), range_inserter( temp_range ), std::less< EntityHandle >() ); other_edges = temp_range; // get rid of count tag and deinitialize result = thisMB->tag_delete( count_tag ); assert( MB_SUCCESS == result ); deinitialize(); // set the node count number_boundary_nodes = boundary_nodes.size(); return MB_SUCCESS; }
bool moab::Skinner::connectivity_match | ( | const EntityHandle * | conn1, |
const EntityHandle * | conn2, | ||
const int | num_verts, | ||
Skinner::direction & | direct | ||
) | [protected] |
Definition at line 582 of file Skinner.cpp.
References FORWARD, and REVERSE.
Referenced by find_match().
{ const EntityHandle* iter = std::find( conn2, conn2 + num_verts, conn1[0] ); if( iter == conn2 + num_verts ) return false; bool they_match = true; int i; unsigned int j = iter - conn2; // first compare forward for( i = 1; i < num_verts; ++i ) { if( conn1[i] != conn2[( j + i ) % num_verts] ) { they_match = false; break; } } if( they_match == true ) { // need to check for reversed edges here direct = ( num_verts == 2 && j ) ? REVERSE : FORWARD; return true; } they_match = true; // then compare reverse j += num_verts; for( i = 1; i < num_verts; ) { if( conn1[i] != conn2[( j - i ) % num_verts] ) { they_match = false; break; } ++i; } if( they_match ) { direct = REVERSE; } return they_match; }
ErrorCode moab::Skinner::create_side | ( | const EntityHandle | this_set, |
EntityHandle | element, | ||
EntityType | side_type, | ||
const EntityHandle * | side_corners, | ||
EntityHandle & | side_elem_handle_out | ||
) | [protected] |
Definition at line 1432 of file Skinner.cpp.
References moab::CN::Dimension(), ErrorCode, MB_CHK_ERR, MB_SUCCESS, MBEDGE, MBPOLYGON, moab::CN::SideNumber(), moab::CN::SubEntityNodeIndices(), moab::TYPE_FROM_HANDLE(), and moab::CN::VerticesPerEntity().
{ const int max_side = 9; const EntityHandle* conn; int len, side_len, side, sense, offset, indices[max_side]; ErrorCode rval; EntityType type = TYPE_FROM_HANDLE( elem ), tmp_type; const int ncorner = CN::VerticesPerEntity( side_type ); const int d = CN::Dimension( side_type ); std::vector< EntityHandle > storage; // Get the connectivity of the parent element rval = thisMB->get_connectivity( elem, conn, len, false, &storage ); if( MB_SUCCESS != rval ) return rval; // treat separately MBPOLYGON; we want to create the edge in the // forward sense always ; so figure out the sense first, then get out if( MBPOLYGON == type && 1 == d && MBEDGE == side_type ) { // first find the first vertex in the conn list int i = 0; for( i = 0; i < len; i++ ) { if( conn[i] == side_conn[0] ) break; } if( len == i ) return MB_FAILURE; // not found, big error // now, what if the polygon is padded? // the previous index is fine always. but the next one could be trouble :( int prevIndex = ( i + len - 1 ) % len; int nextIndex = ( i + 1 ) % len; // if the next index actually point to the same node, as current, it means it is padded if( conn[nextIndex] == conn[i] ) { // it really means we are at the end of proper nodes, the last nodes are repeated, so it // should be the first node nextIndex = 0; // this is the first node! } EntityHandle conn2[2] = { side_conn[0], side_conn[1] }; if( conn[prevIndex] == side_conn[1] ) { // reverse, so the edge will be forward conn2[0] = side_conn[1]; conn2[1] = side_conn[0]; } else if( conn[nextIndex] != side_conn[1] ) return MB_FAILURE; // it is not adjacent to the polygon rval = thisMB->create_element( MBEDGE, conn2, 2, side_elem );MB_CHK_ERR( rval ); if( this_set ) { rval = thisMB->add_entities( this_set, &side_elem, 1 );MB_CHK_ERR( rval ); } return MB_SUCCESS; } // Find which side we are creating and get indices of all nodes // (including higher-order, if any.) CN::SideNumber( type, conn, side_conn, ncorner, d, side, sense, offset ); CN::SubEntityNodeIndices( type, len, d, side, tmp_type, side_len, indices ); assert( side_len <= max_side ); assert( side_type == tmp_type ); // NOTE: re-create conn array even when no higher-order nodes // because we want it to always be forward with respect // to the side ordering. EntityHandle side_conn_full[max_side]; for( int i = 0; i < side_len; ++i ) side_conn_full[i] = conn[indices[i]]; rval = thisMB->create_element( side_type, side_conn_full, side_len, side_elem );MB_CHK_ERR( rval ); if( this_set ) { rval = thisMB->add_entities( this_set, &side_elem, 1 );MB_CHK_ERR( rval ); } return MB_SUCCESS; ; }
ErrorCode moab::Skinner::deinitialize | ( | ) | [protected] |
Definition at line 98 of file Skinner.cpp.
References entities, ErrorCode, moab::Interface::get_entities_by_type_and_tag(), mAdjTag, MB_CHK_ERR, MB_SUCCESS, MBMAXTYPE, MBVERTEX, mDeletableMBTag, moab::Range::size(), t, moab::Interface::tag_delete(), moab::Interface::tag_get_data(), and thisMB.
Referenced by classify_2d_boundary(), and find_skin_noadj().
{ ErrorCode result; if( 0 != mDeletableMBTag ) { result = thisMB->tag_delete( mDeletableMBTag ); mDeletableMBTag = 0;MB_CHK_ERR( result ); } // remove the adjacency tag std::vector< std::vector< EntityHandle >* > adj_arr; std::vector< std::vector< EntityHandle >* >::iterator i; if( 0 != mAdjTag ) { for( EntityType t = MBVERTEX; t != MBMAXTYPE; ++t ) { Range entities; result = thisMB->get_entities_by_type_and_tag( 0, t, &mAdjTag, 0, 1, entities );MB_CHK_ERR( result ); adj_arr.resize( entities.size() ); result = thisMB->tag_get_data( mAdjTag, entities, &adj_arr[0] );MB_CHK_ERR( result ); for( i = adj_arr.begin(); i != adj_arr.end(); ++i ) delete *i; } result = thisMB->tag_delete( mAdjTag ); mAdjTag = 0;MB_CHK_ERR( result ); } return MB_SUCCESS; }
bool moab::Skinner::edge_reversed | ( | EntityHandle | face, |
const EntityHandle | edge_ends[2] | ||
) | [protected] |
Definition at line 1515 of file Skinner.cpp.
References ErrorCode, and MB_SUCCESS.
{ const EntityHandle* conn; int len, idx; ErrorCode rval = thisMB->get_connectivity( face, conn, len, true ); if( MB_SUCCESS != rval ) { assert( false ); return false; } idx = std::find( conn, conn + len, edge_ends[0] ) - conn; if( idx == len ) { assert( false ); return false; } return ( edge_ends[1] == conn[( idx + len - 1 ) % len] ); }
bool moab::Skinner::entity_deletable | ( | EntityHandle | entity | ) | [protected] |
Definition at line 650 of file Skinner.cpp.
References ErrorCode, MB_SUCCESS, mDeletableMBTag, moab::Interface::tag_get_data(), and thisMB.
Referenced by classify_2d_boundary(), and find_skin_noadj().
{ unsigned char deletable = 0; ErrorCode result = thisMB->tag_get_data( mDeletableMBTag, &entity, 1, &deletable ); assert( MB_SUCCESS == result ); if( MB_SUCCESS == result && deletable == 1 ) return false; return true; }
bool moab::Skinner::face_reversed | ( | EntityHandle | region, |
const EntityHandle * | face_conn, | ||
EntityType | face_type | ||
) | [protected] |
Definition at line 1537 of file Skinner.cpp.
References moab::CN::Dimension(), ErrorCode, MB_SUCCESS, moab::CN::SideNumber(), moab::TYPE_FROM_HANDLE(), and moab::CN::VerticesPerEntity().
{ const EntityHandle* conn; int len, side, sense, offset; ErrorCode rval = thisMB->get_connectivity( region, conn, len, true ); if( MB_SUCCESS != rval ) { assert( false ); return false; } short r = CN::SideNumber( TYPE_FROM_HANDLE( region ), conn, face_corners, CN::VerticesPerEntity( face_type ), CN::Dimension( face_type ), side, sense, offset ); assert( 0 == r ); return ( !r && sense == -1 ); }
ErrorCode moab::Skinner::find_geometric_skin | ( | const EntityHandle | meshset, |
Range & | forward_target_entities | ||
) |
Definition at line 180 of file Skinner.cpp.
References moab::Range::begin(), moab::debug, moab::Range::empty(), moab::Range::end(), ErrorCode, GEOM_DIMENSION_TAG_NAME, moab::Interface::get_entities_by_handle(), moab::Interface::get_entities_by_type_and_tag(), moab::Range::insert(), MB_ENTITY_NOT_FOUND, MB_SUCCESS, MB_TAG_CREAT, MB_TAG_SPARSE, MB_TYPE_INTEGER, MBENTITYSET, moab::Interface::num_parent_meshsets(), moab::Range::size(), moab::Interface::tag_get_handle(), and thisMB.
{ // attempts to find whole model skin, using geom topo sets first then // normal find_skin function bool debug = true; // look for geom topo sets Tag geom_tag; ErrorCode result = thisMB->tag_get_handle( GEOM_DIMENSION_TAG_NAME, 1, MB_TYPE_INTEGER, geom_tag, MB_TAG_SPARSE | MB_TAG_CREAT ); if( MB_SUCCESS != result ) return result; // get face sets (dimension = 2) Range face_sets; int two = 2; const void* two_ptr = &two; result = thisMB->get_entities_by_type_and_tag( meshset, MBENTITYSET, &geom_tag, &two_ptr, 1, face_sets ); Range::iterator it; if( MB_SUCCESS != result ) return result; else if( face_sets.empty() ) return MB_ENTITY_NOT_FOUND; // ok, we have face sets; use those to determine skin Range skin_sets; if( debug ) std::cout << "Found " << face_sets.size() << " face sets total..." << std::endl; for( it = face_sets.begin(); it != face_sets.end(); ++it ) { int num_parents; result = thisMB->num_parent_meshsets( *it, &num_parents ); if( MB_SUCCESS != result ) return result; else if( num_parents == 1 ) skin_sets.insert( *it ); } if( debug ) std::cout << "Found " << skin_sets.size() << " 1-parent face sets..." << std::endl; if( skin_sets.empty() ) return MB_FAILURE; // ok, we have the shell; gather up the elements, putting them all in forward for now for( it = skin_sets.begin(); it != skin_sets.end(); ++it ) { result = thisMB->get_entities_by_handle( *it, forward_target_entities, true ); if( MB_SUCCESS != result ) return result; } return result; }
void moab::Skinner::find_inferred_edges | ( | Range & | skin_boundary, |
Range & | candidate_edges, | ||
Range & | inferred_edges, | ||
double | reference_angle_degrees | ||
) | [protected] |
Definition at line 900 of file Skinner.cpp.
References moab::Range::begin(), moab::Range::end(), ErrorCode, moab::Interface::get_adjacencies(), has_larger_angle(), moab::Range::insert(), MB_SUCCESS, MB_TAG_CREAT, MB_TYPE_BIT, SKINNER_PI, moab::Interface::tag_clear_data(), moab::Interface::tag_delete(), moab::Interface::tag_get_data(), moab::Interface::tag_get_handle(), and thisMB.
Referenced by classify_2d_boundary().
{ // mark all the entities in the skin boundary Tag mark_tag; ErrorCode result = thisMB->tag_get_handle( 0, 1, MB_TYPE_BIT, mark_tag, MB_TAG_CREAT ); assert( MB_SUCCESS == result ); unsigned char bit = true; result = thisMB->tag_clear_data( mark_tag, skin_boundary, &bit ); assert( MB_SUCCESS == result ); // find the cosine of the reference angle double reference_cosine = cos( reference_angle_degrees * SKINNER_PI / 180.0 ); // check all candidate edges for an angle greater than the minimum Range::iterator iter, end_iter = candidate_edges.end(); std::vector< EntityHandle > adjacencies; std::vector< EntityHandle >::iterator adj_iter; EntityHandle face[2]; for( iter = candidate_edges.begin(); iter != end_iter; ++iter ) { // get the 2D elements connected to this edge adjacencies.clear(); result = thisMB->get_adjacencies( &( *iter ), 1, 2, false, adjacencies ); if( MB_SUCCESS != result ) continue; // there should be exactly two, that is why the edge is classified as nonBoundary // and manifold int faces_found = 0; for( adj_iter = adjacencies.begin(); adj_iter != adjacencies.end() && faces_found < 2; ++adj_iter ) { // we need to find two of these which are in the skin unsigned char is_marked = 0; result = thisMB->tag_get_data( mark_tag, &( *adj_iter ), 1, &is_marked ); assert( MB_SUCCESS == result ); if( is_marked ) { face[faces_found] = *adj_iter; faces_found++; } } // assert(faces_found == 2 || faces_found == 0); if( 2 != faces_found ) continue; // see if the two entities have a sufficient angle if( has_larger_angle( face[0], face[1], reference_cosine ) ) { inferred_edges.insert( *iter ); } } result = thisMB->tag_delete( mark_tag ); assert( MB_SUCCESS == result ); }
void moab::Skinner::find_match | ( | EntityType | type, |
const EntityHandle * | conn, | ||
const int | num_nodes, | ||
EntityHandle & | match, | ||
Skinner::direction & | direct | ||
) | [protected] |
Definition at line 532 of file Skinner.cpp.
References connectivity_match(), ErrorCode, FORWARD, moab::Interface::get_connectivity(), mAdjTag, MB_SUCCESS, MBVERTEX, moab::Interface::tag_get_data(), thisMB, moab::Interface::type_from_handle(), and moab::CN::VerticesPerEntity().
Referenced by classify_2d_boundary(), and find_skin_noadj().
{ match = 0; if( type == MBVERTEX ) { match = *conn; direct = FORWARD; return; } const EntityHandle* iter = std::min_element( conn, conn + num_nodes ); std::vector< EntityHandle >* adj = NULL; ErrorCode result = thisMB->tag_get_data( mAdjTag, iter, 1, &adj ); if( result == MB_FAILURE || adj == NULL ) { return; } std::vector< EntityHandle >::iterator jter, end_jter; end_jter = adj->end(); const EntityHandle* tmp; int num_verts; for( jter = adj->begin(); jter != end_jter; ++jter ) { EntityType tmp_type; tmp_type = thisMB->type_from_handle( *jter ); if( type != tmp_type ) continue; result = thisMB->get_connectivity( *jter, tmp, num_verts, false ); assert( MB_SUCCESS == result && num_verts >= CN::VerticesPerEntity( type ) ); // FIXME: connectivity_match appears to work only for linear elements, // so ignore higher-order nodes. if( connectivity_match( conn, tmp, CN::VerticesPerEntity( type ), direct ) ) { match = *jter; break; } } }
ErrorCode moab::Skinner::find_skin | ( | const EntityHandle | meshset, |
const Range & | entities, | ||
bool | get_vertices, | ||
Range & | output_handles, | ||
Range * | output_reverse_handles = 0 , |
||
bool | create_vert_elem_adjs = false , |
||
bool | create_skin_elements = true , |
||
bool | look_for_scd = false |
||
) |
will accept entities all of one dimension and return entities of n-1 dimension; NOTE: get_vertices argument controls whether vertices or entities of n-1 dimension are returned, and only one of these is allowed (i.e. this function returns only vertices or (n-1)-dimensional entities, but not both)
entities | The elements for which to find the skin |
get_vertices | If true, vertices on the skin are returned in the range, otherwise elements are returned |
output_handles | Range holding skin entities returned |
output_reverse_handles | Range holding entities on skin which are reversed wrt entities |
create_vert_elem_adjs | If true, this function will cause vertex-element adjacencies to be generated |
create_skin_elements | If true, this function will cause creation of skin entities, otherwise only skin entities already extant will be returned |
Definition at line 233 of file Skinner.cpp.
References moab::Core::a_entity_factory(), moab::AEntityFactory::create_vert_elem_adjacencies(), moab::Range::empty(), ErrorCode, find_skin_scd(), find_skin_vertices(), MB_SUCCESS, thisMB, and moab::AEntityFactory::vert_elem_adjacencies().
Referenced by add_dead_elems_to_impl_compl(), MetisPartitioner::assemble_taggedsets_graph(), moab::GeomTopoTool::check_model(), moab::ParallelComm::create_interface_sets(), DeformMeshRemap::execute(), find_skin(), moab::GeomTopoTool::geometrize_surface_set(), get_imesh_mesh(), moab::LloydSmoother::initialize(), main(), moab::MergeMesh::merge_entities(), moab::MergeMesh::merge_higher_dimensions(), moab::ParallelMergeMesh::PopulateMySkinEnts(), moab::ParallelComm::resolve_shared_ents(), tag_depth(), and moab::WriteCCMIO::write_cells_and_faces().
{ if( source_entities.empty() ) return MB_SUCCESS; if( look_for_scd ) { ErrorCode rval = find_skin_scd( source_entities, get_vertices, output_handles, create_skin_elements ); // if it returns success, it's all scd, and we don't need to do anything more if( MB_SUCCESS == rval ) return rval; } Core* this_core = dynamic_cast< Core* >( thisMB ); if( this_core && create_vert_elem_adjs && !this_core->a_entity_factory()->vert_elem_adjacencies() ) this_core->a_entity_factory()->create_vert_elem_adjacencies(); return find_skin_vertices( meshset, source_entities, get_vertices ? &output_handles : 0, get_vertices ? 0 : &output_handles, output_reverse_handles, create_skin_elements ); }
ErrorCode moab::Skinner::find_skin | ( | const EntityHandle | this_set, |
const EntityHandle * | entities, | ||
int | num_entities, | ||
bool | get_vertices, | ||
Range & | output_handles, | ||
Range * | output_reverse_handles = 0 , |
||
bool | create_vert_elem_adjs = false , |
||
bool | create_skin_elements = true , |
||
bool | look_for_scd = false |
||
) | [inline] |
will accept entities all of one dimension and return entities of n-1 dimension; NOTE: get_vertices argument controls whether vertices or entities of n-1 dimension are returned, and only one of these is allowed (i.e. this function returns only vertices or (n-1)-dimensional entities, but not both)
entities | Pointer to elements for which to find the skin |
num_entities | Number of entities in vector |
get_vertices | If true, vertices on the skin are returned in the range, otherwise elements are returned |
output_handles | Range holding skin entities returned |
output_reverse_handles | Range holding entities on skin which are reversed wrt entities |
create_vert_elem_adjs | If true, this function will cause vertex-element adjacencies to be generated |
create_skin_elements | If true, this function will cause creation of skin entities, otherwise only skin entities already extant will be returned |
Definition at line 286 of file Skinner.hpp.
References find_skin().
ErrorCode moab::Skinner::find_skin | ( | const EntityHandle | this_set, |
const Range & | entities, | ||
int | dim, | ||
Range & | skin_entities, | ||
bool | create_vert_elem_adjs = false , |
||
bool | create_skin_elements = true |
||
) |
get skin entities of prescribed dimension
entities | The elements for which to find the skin |
dim | Dimension of skin entities requested |
skin_entities | Range holding skin entities returned |
create_vert_elem_adjs | If true, this function will cause vertex-element adjacencies to be generated |
Definition at line 985 of file Skinner.cpp.
References moab::Interface::add_entities(), moab::Range::all_of_dimension(), moab::Range::empty(), ErrorCode, find_skin(), moab::Interface::get_adjacencies(), MB_CHK_ERR, MB_SUCCESS, moab::Range::merge(), moab::Range::swap(), thisMB, and moab::Interface::UNION.
{ Range tmp_skin; ErrorCode result = find_skin( this_set, entities, ( dim == 0 ), tmp_skin, 0, create_vert_elem_adjs, create_skin_elements ); if( MB_SUCCESS != result || tmp_skin.empty() ) return result; if( tmp_skin.all_of_dimension( dim ) ) { if( skin_entities.empty() ) skin_entities.swap( tmp_skin ); else skin_entities.merge( tmp_skin ); } else { result = thisMB->get_adjacencies( tmp_skin, dim, create_skin_elements, skin_entities, Interface::UNION );MB_CHK_ERR( result ); if( this_set ) result = thisMB->add_entities( this_set, skin_entities ); } return result; }
ErrorCode moab::Skinner::find_skin_noadj | ( | const Range & | source_entities, |
Range & | forward_target_entities, | ||
Range & | reverse_target_entities | ||
) | [protected] |
use_adjs &&
use_adjs &&
Definition at line 386 of file Skinner.cpp.
References add_adjacency(), moab::Range::begin(), moab::Interface::create_element(), deinitialize(), moab::Interface::delete_entities(), moab::CN::Dimension(), moab::Range::empty(), moab::Range::end(), entity_deletable(), moab::Range::erase(), ErrorCode, moab::Range::find(), find_match(), FORWARD, moab::Interface::get_connectivity(), initialize(), moab::Range::insert(), moab::MAX_SUB_ENTITY_VERTICES, MB_SUCCESS, MBEDGE, MBPOLYGON, mTargetDim, moab::CN::NumSubEntities(), remove_adjacency(), moab::CN::SubEntityNodeIndices(), thisMB, moab::Interface::type_from_handle(), and moab::CN::VerticesPerEntity().
{ if( source_entities.empty() ) return MB_FAILURE; // get our working dimensions EntityType type = thisMB->type_from_handle( *( source_entities.begin() ) ); const int source_dim = CN::Dimension( type ); mTargetDim = source_dim - 1; // make sure we can handle the working dimensions if( mTargetDim < 0 || source_dim > 3 ) return MB_FAILURE; initialize(); Range::const_iterator iter, end_iter; end_iter = source_entities.end(); const EntityHandle* conn; EntityHandle match; direction direct; ErrorCode result; // assume we'll never have more than 32 vertices on a facet (checked // with assert later) EntityHandle sub_conn[32]; std::vector< EntityHandle > tmp_conn_vec; int num_nodes, num_sub_nodes, num_sides; int sub_indices[32]; // Also, assume that no polygon has more than 32 nodes // we could increase that, but we will not display it right in visit moab h5m , anyway EntityType sub_type; // for each source entity for( iter = source_entities.begin(); iter != end_iter; ++iter ) { // get the connectivity of this entity int actual_num_nodes_polygon = 0; result = thisMB->get_connectivity( *iter, conn, num_nodes, false, &tmp_conn_vec ); if( MB_SUCCESS != result ) return result; type = thisMB->type_from_handle( *iter ); Range::iterator seek_iter; // treat separately polygons (also, polyhedra will need special handling) if( MBPOLYGON == type ) { // treat padded polygons, if existing; count backwards, see how many of the last nodes // are repeated assume connectivity is fine, otherwise we could be in trouble actual_num_nodes_polygon = num_nodes; while( actual_num_nodes_polygon >= 3 && conn[actual_num_nodes_polygon - 1] == conn[actual_num_nodes_polygon - 2] ) actual_num_nodes_polygon--; num_sides = actual_num_nodes_polygon; sub_type = MBEDGE; num_sub_nodes = 2; } else // get connectivity of each n-1 dimension entity num_sides = CN::NumSubEntities( type, mTargetDim ); for( int i = 0; i < num_sides; i++ ) { if( MBPOLYGON == type ) { sub_conn[0] = conn[i]; sub_conn[1] = conn[i + 1]; if( i + 1 == actual_num_nodes_polygon ) sub_conn[1] = conn[0]; } else { CN::SubEntityNodeIndices( type, num_nodes, mTargetDim, i, sub_type, num_sub_nodes, sub_indices ); assert( (size_t)num_sub_nodes <= sizeof( sub_indices ) / sizeof( sub_indices[0] ) ); for( int j = 0; j < num_sub_nodes; j++ ) sub_conn[j] = conn[sub_indices[j]]; } // see if we can match this connectivity with // an existing entity find_match( sub_type, sub_conn, num_sub_nodes, match, direct ); // if there is no match, create a new entity if( match == 0 ) { EntityHandle tmphndl = 0; int indices[MAX_SUB_ENTITY_VERTICES]; EntityType new_type; int num_new_nodes; if( MBPOLYGON == type ) { new_type = MBEDGE; num_new_nodes = 2; } else { CN::SubEntityNodeIndices( type, num_nodes, mTargetDim, i, new_type, num_new_nodes, indices ); for( int j = 0; j < num_new_nodes; j++ ) sub_conn[j] = conn[indices[j]]; } result = thisMB->create_element( new_type, sub_conn, num_new_nodes, tmphndl ); assert( MB_SUCCESS == result ); add_adjacency( tmphndl, sub_conn, CN::VerticesPerEntity( new_type ) ); forward_target_entities.insert( tmphndl ); } // if there is a match, delete the matching entity // if we can. else { if( ( seek_iter = forward_target_entities.find( match ) ) != forward_target_entities.end() ) { forward_target_entities.erase( seek_iter ); remove_adjacency( match ); if( /*!use_adjs &&*/ entity_deletable( match ) ) { result = thisMB->delete_entities( &match, 1 ); assert( MB_SUCCESS == result ); } } else if( ( seek_iter = reverse_target_entities.find( match ) ) != reverse_target_entities.end() ) { reverse_target_entities.erase( seek_iter ); remove_adjacency( match ); if( /*!use_adjs &&*/ entity_deletable( match ) ) { result = thisMB->delete_entities( &match, 1 ); assert( MB_SUCCESS == result ); } } else { if( direct == FORWARD ) { forward_target_entities.insert( match ); } else { reverse_target_entities.insert( match ); } } } } } deinitialize(); return MB_SUCCESS; }
ErrorCode moab::Skinner::find_skin_scd | ( | const Range & | source_entities, |
bool | get_vertices, | ||
Range & | output_handles, | ||
bool | create_skin_elements | ||
) | [protected] |
look for structured box comprising source_entities, and if one is found use structured information to find the skin
Definition at line 259 of file Skinner.cpp.
References moab::Range::contains(), ErrorCode, moab::ScdInterface::find_boxes(), MB_SUCCESS, moab::Range::merge(), moab::Interface::query_interface(), moab::Range::size(), skin_box(), and thisMB.
Referenced by find_skin().
{ // get the scd interface and check if it's been initialized ScdInterface* scdi = NULL; ErrorCode rval = thisMB->query_interface( scdi ); if( !scdi ) return MB_FAILURE; // ok, there's scd mesh; see if the entities passed in are all in a scd box // a box needs to be wholly included in entities for this to work std::vector< ScdBox* > boxes, myboxes; Range myrange; rval = scdi->find_boxes( boxes ); if( MB_SUCCESS != rval ) return rval; for( std::vector< ScdBox* >::iterator bit = boxes.begin(); bit != boxes.end(); ++bit ) { Range belems( ( *bit )->start_element(), ( *bit )->start_element() + ( *bit )->num_elements() - 1 ); if( source_entities.contains( belems ) ) { myboxes.push_back( *bit ); myrange.merge( belems ); } } if( myboxes.empty() || myrange.size() != source_entities.size() ) return MB_FAILURE; // ok, we're all structured; get the skin for each box for( std::vector< ScdBox* >::iterator bit = boxes.begin(); bit != boxes.end(); ++bit ) { rval = skin_box( *bit, get_vertices, output_handles, create_skin_elements ); if( MB_SUCCESS != rval ) return rval; } return MB_SUCCESS; }
ErrorCode moab::Skinner::find_skin_vertices | ( | const EntityHandle | this_set, |
const Range & | entities, | ||
Range * | skin_verts = 0 , |
||
Range * | skin_elems = 0 , |
||
Range * | rev_elems = 0 , |
||
bool | create_if_missing = true , |
||
bool | corners_only = false |
||
) | [protected] |
Find vertices on the skin of a set of mesh entities.
entities | The elements for which to find the skin. Range may NOT contain vertices, polyhedra, or entity sets. All elements in range must be of the same dimension. |
skin_verts | Output: the vertices on the skin. |
skin_elems | Optional output: elements representing sides of entities that are on the skin |
create_if_missing | If skin_elemts is non-null and this is true, create new elements representing the sides of entities on the skin. If this is false, skin_elems will contain only those skin elements that already exist. |
Definition at line 1013 of file Skinner.cpp.
References moab::Range::all_of_dimension(), dim, moab::CN::Dimension(), moab::Range::empty(), ErrorCode, find_skin_vertices_1D(), find_skin_vertices_2D(), find_skin_vertices_3D(), moab::Range::front(), moab::Interface::get_number_entities_by_dimension(), MB_SUCCESS, MB_TAG_CREAT, MB_TYPE_BIT, MB_TYPE_OUT_OF_RANGE, moab::Range::size(), moab::Interface::tag_delete(), moab::Interface::tag_get_handle(), moab::Interface::tag_set_data(), thisMB, and moab::TYPE_FROM_HANDLE().
Referenced by find_skin().
{ ErrorCode rval; if( entities.empty() ) return MB_SUCCESS; const int dim = CN::Dimension( TYPE_FROM_HANDLE( entities.front() ) ); if( dim < 1 || dim > 3 || !entities.all_of_dimension( dim ) ) return MB_TYPE_OUT_OF_RANGE; // are we skinning all entities size_t count = entities.size(); int num_total; rval = thisMB->get_number_entities_by_dimension( this_set, dim, num_total ); if( MB_SUCCESS != rval ) return rval; bool all = ( count == (size_t)num_total ); // Create a bit tag for fast intersection with input entities range. // If we're skinning all the entities in the mesh, we really don't // need the tag. To save memory, just create it with a default value // of one and don't set it. That way MOAB will return 1 for all // entities. Tag tag; char bit = all ? 1 : 0; rval = thisMB->tag_get_handle( NULL, 1, MB_TYPE_BIT, tag, MB_TAG_CREAT, &bit ); if( MB_SUCCESS != rval ) return rval; // tag all entities in input range if( !all ) { std::vector< unsigned char > vect( count, 1 ); rval = thisMB->tag_set_data( tag, entities, &vect[0] ); if( MB_SUCCESS != rval ) { thisMB->tag_delete( tag ); return rval; } } switch( dim ) { case 1: if( skin_verts ) rval = find_skin_vertices_1D( tag, entities, *skin_verts ); else if( skin_elems ) rval = find_skin_vertices_1D( tag, entities, *skin_elems ); else rval = MB_SUCCESS; break; case 2: rval = find_skin_vertices_2D( this_set, tag, entities, skin_verts, skin_elems, skin_rev_elems, create_skin_elems, corners_only ); break; case 3: rval = find_skin_vertices_3D( this_set, tag, entities, skin_verts, skin_elems, skin_rev_elems, create_skin_elems, corners_only ); break; default: rval = MB_TYPE_OUT_OF_RANGE; break; } thisMB->tag_delete( tag ); return rval; }
ErrorCode moab::Skinner::find_skin_vertices_1D | ( | Tag | tag, |
const Range & | edges, | ||
Range & | skin_verts | ||
) | [protected] |
Skin edges.
Return any vertices adjacent to exactly one of the input edges.
Definition at line 1083 of file Skinner.cpp.
References moab::Range::all_of_dimension(), moab::Range::begin(), moab::Range::end(), ErrorCode, moab::Interface::get_adjacencies(), moab::Interface::get_connectivity(), moab::Range::insert(), MB_SUCCESS, MB_TYPE_OUT_OF_RANGE, moab::Interface::tag_get_data(), and thisMB.
Referenced by find_skin_vertices().
{ // This rather simple algorithm is provided for completeness // (not sure how often one really wants the 'skin' of a chain // or tangle of edges.) // // A vertex is on the skin of the edges if it is contained in exactly // one of the edges *in the input range*. // // This function expects the caller to have tagged all edges in the // input range with a value of one for the passed bit tag, and all // other edges with a value of zero. This allows us to do a faster // intersection with the input range and the edges adjacent to a vertex. ErrorCode rval; Range::iterator hint = skin_verts.begin(); // All input entities must be edges. if( !edges.all_of_dimension( 1 ) ) return MB_TYPE_OUT_OF_RANGE; // get all the vertices Range verts; rval = thisMB->get_connectivity( edges, verts, true ); if( MB_SUCCESS != rval ) return rval; // Test how many edges each input vertex is adjacent to. std::vector< char > tag_vals; std::vector< EntityHandle > adj; int n; for( Range::const_iterator it = verts.begin(); it != verts.end(); ++it ) { // get edges adjacent to vertex adj.clear(); rval = thisMB->get_adjacencies( &*it, 1, 1, false, adj ); if( MB_SUCCESS != rval ) return rval; if( adj.empty() ) continue; // Intersect adjacent edges with the input list of edges tag_vals.resize( adj.size() ); rval = thisMB->tag_get_data( tag, &adj[0], adj.size(), &tag_vals[0] ); if( MB_SUCCESS != rval ) return rval; #ifdef MOAB_OLD_STD_COUNT n = 0; std::count( tag_vals.begin(), tag_vals.end(), '\001' ); #else n = std::count( tag_vals.begin(), tag_vals.end(), '\001' ); #endif // If adjacent to only one input edge, then vertex is on skin if( n == 1 ) { hint = skin_verts.insert( hint, *it ); } } return MB_SUCCESS; }
ErrorCode moab::Skinner::find_skin_vertices_2D | ( | const EntityHandle | this_set, |
Tag | tag, | ||
const Range & | faces, | ||
Range * | skin_verts = 0 , |
||
Range * | skin_edges = 0 , |
||
Range * | reverse_edges = 0 , |
||
bool | create_edges = false , |
||
bool | corners_only = false |
||
) | [protected] |
Skin faces.
For the set of face sides (logical edges), return vertices on such sides and/or edges equivalent to such sides.
faces | Set of toplogically 2D entities to skin. |
skin_verts | If non-NULL, skin vertices will be added to this container. |
skin_edges | If non-NULL, skin edges will be added to this container |
reverse_edges | If skin_edges is not NULL and this is not NULL, then any existing skin edges that are reversed with respect to the skin side will be placed in this range instead of skin_edges. Note: this argument is ignored if skin_edges is NULL. |
create_edges | If true, edges equivalent to face sides on the skin that don't already exist will be created. Note: this parameter is honored regardless of whether or not skin edges or vertices are returned. |
corners_only | If true, only skin vertices that correspond to the corners of sides will be returned (i.e. no higher-order nodes.) This argument is ignored if skin_verts is NULL. |
Definition at line 1553 of file Skinner.cpp.
References moab::Range::all_of_dimension(), moab::Range::begin(), moab::AdjSides< CORNERS >::begin(), moab::AdjSides< CORNERS >::clear(), moab::Range::end(), moab::AdjSides< CORNERS >::end(), ErrorCode, moab::AdjSides< CORNERS >::find_and_unmark(), moab::CN::HasMidEdgeNodes(), moab::CN::HONodeIndex(), moab::ID_FROM_HANDLE(), moab::Range::insert(), moab::AdjSides< CORNERS >::insert(), MB_SUCCESS, MB_TYPE_OUT_OF_RANGE, MBEDGE, MBQUAD, MBTRI, moab::AdjSides< CORNERS >::num_skin(), moab::CN::SideNumber(), and moab::TYPE_FROM_HANDLE().
Referenced by find_skin_vertices().
{ // This function iterates over all the vertices contained in the // input face list. For each such vertex, it then iterates over // all of the sides of the face elements adjacent to the vertex. // If an adjacent side is the side of only one of the input // faces, then that side is on the skin. // // This algorithm will visit each skin vertex exactly once. It // will visit each skin side once for each vertex in the side. // // This function expects the caller to have created the passed bit // tag and set it to one only for the faces in the passed range. This // tag is used to do a fast intersection of the faces adjacent to a // vertex with the faces in the input range (discard any for which the // tag is not set to one.) ErrorCode rval; std::vector< EntityHandle >::iterator i, j; Range::iterator hint; if( skin_verts ) hint = skin_verts->begin(); std::vector< EntityHandle > storage; const EntityHandle* conn; int len; bool find_edges = skin_edges || create_edges; bool printed_nonconformal_ho_warning = false; EntityHandle face; if( !faces.all_of_dimension( 2 ) ) return MB_TYPE_OUT_OF_RANGE; // get all the vertices Range verts; rval = thisMB->get_connectivity( faces, verts, true ); if( MB_SUCCESS != rval ) return rval; std::vector< char > tag_vals; std::vector< EntityHandle > adj; AdjSides< 2 > adj_edges; for( Range::const_iterator it = verts.begin(); it != verts.end(); ++it ) { bool higher_order = false; // get all adjacent faces adj.clear(); rval = thisMB->get_adjacencies( &*it, 1, 2, false, adj ); if( MB_SUCCESS != rval ) return rval; if( adj.empty() ) continue; // remove those not in the input list (intersect with input list) i = j = adj.begin(); tag_vals.resize( adj.size() ); rval = thisMB->tag_get_data( tag, &adj[0], adj.size(), &tag_vals[0] ); if( MB_SUCCESS != rval ) return rval; // remove non-tagged entries i = j = adj.begin(); for( ; i != adj.end(); ++i ) if( tag_vals[i - adj.begin()] ) *( j++ ) = *i; adj.erase( j, adj.end() ); // For each adjacent face, check the edges adjacent to the current vertex adj_edges.clear(); // other vertex for adjacent edges for( i = adj.begin(); i != adj.end(); ++i ) { rval = thisMB->get_connectivity( *i, conn, len, false, &storage ); if( MB_SUCCESS != rval ) return rval; // For a single face element adjacent to this vertex, there // will be exactly two sides (edges) adjacent to the vertex. // Find the other vertex for each of the two edges. EntityHandle prev, next; // vertices of two adjacent edge-sides const int idx = std::find( conn, conn + len, *it ) - conn; assert( idx != len ); if( TYPE_FROM_HANDLE( *i ) == MBTRI && len > 3 ) { len = 3; higher_order = true; if( idx > 2 ) { // skip higher-order nodes for now if( !printed_nonconformal_ho_warning ) { printed_nonconformal_ho_warning = true; std::cerr << "Non-conformal higher-order mesh detected in skinner: " << "vertex " << ID_FROM_HANDLE( *it ) << " is a corner in " << "some elements and a higher-order node in others" << std::endl; } continue; } } else if( TYPE_FROM_HANDLE( *i ) == MBQUAD && len > 4 ) { len = 4; higher_order = true; if( idx > 3 ) { // skip higher-order nodes for now if( !printed_nonconformal_ho_warning ) { printed_nonconformal_ho_warning = true; std::cerr << "Non-conformal higher-order mesh detected in skinner: " << "vertex " << ID_FROM_HANDLE( *it ) << " is a corner in " << "some elements and a higher-order node in others" << std::endl; } continue; } } // so it must be a MBPOLYGON const int prev_idx = ( idx + len - 1 ) % len; // this should be fine, always, even for padded case prev = conn[prev_idx]; next = conn[( idx + 1 ) % len]; if( next == conn[idx] ) // it must be the padded case, so roll to the beginning next = conn[0]; // Insert sides (edges) in our list of candidate skin sides adj_edges.insert( &prev, 1, *i, prev_idx ); adj_edges.insert( &next, 1, *i, idx ); } // If vertex is not on skin, advance to next vertex. // adj_edges handled checking for duplicates on insertion. // If every candidate skin edge occurred more than once (was // not in fact on the skin), then we're done with this vertex. if( 0 == adj_edges.num_skin() ) continue; // If user requested Range of *vertices* on the skin... if( skin_verts ) { // Put skin vertex in output list hint = skin_verts->insert( hint, *it ); // Add mid edge nodes to vertex list if( !corners_only && higher_order ) { for( AdjSides< 2 >::const_iterator p = adj_edges.begin(); p != adj_edges.end(); ++p ) { if( p->skin() ) { face = p->adj_elem; EntityType type = TYPE_FROM_HANDLE( face ); rval = thisMB->get_connectivity( face, conn, len, false ); if( MB_SUCCESS != rval ) return rval; if( !CN::HasMidEdgeNodes( type, len ) ) continue; EntityHandle ec[2] = { *it, p->handles[0] }; int side, sense, offset; CN::SideNumber( type, conn, ec, 2, 1, side, sense, offset ); offset = CN::HONodeIndex( type, len, 1, side ); assert( offset >= 0 && offset < len ); skin_verts->insert( conn[offset] ); } } } } // If user requested Range of *edges* on the skin... if( find_edges ) { // Search list of existing adjacent edges for any that are on the skin adj.clear(); rval = thisMB->get_adjacencies( &*it, 1, 1, false, adj ); if( MB_SUCCESS != rval ) return rval; for( i = adj.begin(); i != adj.end(); ++i ) { rval = thisMB->get_connectivity( *i, conn, len, true ); if( MB_SUCCESS != rval ) return rval; // bool equality expression within find_and_unmark call // will be evaluate to the index of *it in the conn array. // // Note that the order of the terms in the if statement is important. // We want to unmark any existing skin edges even if we aren't // returning them. Otherwise we'll end up creating duplicates // if create_edges is true and skin_edges is not. if( adj_edges.find_and_unmark( conn, ( conn[1] == *it ), face ) && skin_edges ) { if( reversed_edges && edge_reversed( face, conn ) ) reversed_edges->insert( *i ); else skin_edges->insert( *i ); } } } // If the user requested that we create new edges for sides // on the skin for which there is no existing edge, and there // are still skin sides for which no corresponding edge was found... if( create_edges && adj_edges.num_skin() ) { // Create any skin edges that don't exist for( AdjSides< 2 >::const_iterator p = adj_edges.begin(); p != adj_edges.end(); ++p ) { if( p->skin() ) { EntityHandle edge, ec[] = { *it, p->handles[0] }; rval = create_side( this_set, p->adj_elem, MBEDGE, ec, edge ); if( MB_SUCCESS != rval ) return rval; if( skin_edges ) skin_edges->insert( edge ); } } } } // end for each vertex return MB_SUCCESS; }
ErrorCode moab::Skinner::find_skin_vertices_3D | ( | const EntityHandle | this_set, |
Tag | tag, | ||
const Range & | entities, | ||
Range * | skin_verts = 0 , |
||
Range * | skin_faces = 0 , |
||
Range * | reverse_faces = 0 , |
||
bool | create_faces = false , |
||
bool | corners_only = false |
||
) | [protected] |
Skin volume mesh.
For the set of element sides (logical faces), return vertices on such sides and/or faces equivalent to such sides.
entities | Set of toplogically 3D entities to skin. |
skin_verts | If non-NULL, skin vertices will be added to this container. |
skin_faces | If non-NULL, skin faces will be added to this container |
reverse_faces | If skin_faces is not NULL and this is not NULL, then any existing skin faces that are reversed with respect to the skin side will be placed in this range instead of skin_faces. Note: this argument is ignored if skin_faces is NULL. |
create_faces | If true, face equivalent to sides on the skin that don't already exist will be created. Note: this parameter is honored regardless of whether or not skin faces or vertices are returned. |
corners_only | If true, only skin vertices that correspond to the corners of sides will be returned (i.e. no higher-order nodes.) This argument is ignored if skin_verts is NULL. |
Definition at line 1768 of file Skinner.cpp.
References moab::Range::all_of_dimension(), moab::Range::begin(), moab::AdjSides< CORNERS >::begin(), moab::AdjSides< CORNERS >::clear(), moab::Range::end(), moab::AdjSides< CORNERS >::end(), moab::Range::erase(), ErrorCode, moab::AdjSides< CORNERS >::find_and_unmark(), moab::CN::HasMidNodes(), moab::ID_FROM_HANDLE(), moab::Range::insert(), moab::AdjSides< CORNERS >::insert(), MB_SUCCESS, MB_TYPE_OUT_OF_RANGE, MBPOLYHEDRON, MBQUAD, MBTRI, MBVERTEX, moab::Range::merge(), moab::AdjSides< CORNERS >::num_skin(), moab::CN::NumSubEntities(), moab::CN::SideNumber(), moab::CN::SubEntityNodeIndices(), moab::CN::SubEntityVertexIndices(), t, moab::TYPE_FROM_HANDLE(), moab::Range::upper_bound(), and moab::CN::VerticesPerEntity().
Referenced by find_skin_vertices().
{ // This function iterates over all the vertices contained in the // input vol elem list. For each such vertex, it then iterates over // all of the sides of the vol elements adjacent to the vertex. // If an adjacent side is the side of only one of the input // elements, then that side is on the skin. // // This algorithm will visit each skin vertex exactly once. It // will visit each skin side once for each vertex in the side. // // This function expects the caller to have created the passed bit // tag and set it to one only for the elements in the passed range. This // tag is used to do a fast intersection of the elements adjacent to a // vertex with the elements in the input range (discard any for which the // tag is not set to one.) // // For each vertex, iterate over each adjacent element. Construct // lists of the sides of each adjacent element that contain the vertex. // // A list of three-vertex sides is kept for all triangular faces, // included three-vertex faces of type MBPOLYGON. Putting polygons // in the same list ensures that we find polyhedron and non-polyhedron // elements that are adjacent. // // A list of four-vertex sides is kept for all quadrilateral faces, // including four-vertex faces of type MBPOLYGON. // // Sides with more than four vertices must have an explicit MBPOLYGON // element representing them because MBPOLYHEDRON connectivity is a // list of faces rather than vertices. So the third list (vertices>=5), // need contain only the handle of the face rather than the vertex handles. ErrorCode rval; std::vector< EntityHandle >::iterator i, j; Range::iterator hint; if( skin_verts ) hint = skin_verts->begin(); std::vector< EntityHandle > storage, storage2; // temp storage for conn lists const EntityHandle *conn, *conn2; int len, len2; bool find_faces = skin_faces || create_faces; int clen, side, sense, offset, indices[9]; EntityType face_type; EntityHandle elem; bool printed_nonconformal_ho_warning = false; if( !entities.all_of_dimension( 3 ) ) return MB_TYPE_OUT_OF_RANGE; // get all the vertices Range verts; rval = thisMB->get_connectivity( entities, verts, true ); if( MB_SUCCESS != rval ) return rval; // if there are polyhedra in the input list, need to make another // call to get vertices from faces if( !verts.all_of_dimension( 0 ) ) { Range::iterator it = verts.upper_bound( MBVERTEX ); Range pfaces; pfaces.merge( it, verts.end() ); verts.erase( it, verts.end() ); rval = thisMB->get_connectivity( pfaces, verts, true ); if( MB_SUCCESS != rval ) return rval; assert( verts.all_of_dimension( 0 ) ); } AdjSides< 4 > adj_quads; // 4-node sides adjacent to a vertex AdjSides< 3 > adj_tris; // 3-node sides adjacent to a vertex AdjSides< 2 > adj_poly; // n-node sides (n>5) adjacent to vertex // (must have an explicit polygon, so store // polygon handle rather than vertices.) std::vector< char > tag_vals; std::vector< EntityHandle > adj; for( Range::const_iterator it = verts.begin(); it != verts.end(); ++it ) { bool higher_order = false; // get all adjacent elements adj.clear(); rval = thisMB->get_adjacencies( &*it, 1, 3, false, adj ); if( MB_SUCCESS != rval ) return rval; if( adj.empty() ) continue; // remove those not tagged (intersect with input range) i = j = adj.begin(); tag_vals.resize( adj.size() ); rval = thisMB->tag_get_data( tag, &adj[0], adj.size(), &tag_vals[0] ); if( MB_SUCCESS != rval ) return rval; for( ; i != adj.end(); ++i ) if( tag_vals[i - adj.begin()] ) *( j++ ) = *i; adj.erase( j, adj.end() ); // Build lists of sides of 3D element adjacent to the current vertex adj_quads.clear(); // store three other vertices for each adjacent quad face adj_tris.clear(); // store two other vertices for each adjacent tri face adj_poly.clear(); // store handle of each adjacent polygonal face int idx; for( i = adj.begin(); i != adj.end(); ++i ) { const EntityType type = TYPE_FROM_HANDLE( *i ); // Special case for POLYHEDRA if( type == MBPOLYHEDRON ) { rval = thisMB->get_connectivity( *i, conn, len ); if( MB_SUCCESS != rval ) return rval; for( int k = 0; k < len; ++k ) { rval = thisMB->get_connectivity( conn[k], conn2, len2, true, &storage2 ); if( MB_SUCCESS != rval ) return rval; idx = std::find( conn2, conn2 + len2, *it ) - conn2; if( idx == len2 ) // vertex not in this face continue; // Treat 3- and 4-vertex faces specially, so that // if the mesh contains both elements and polyhedra, // we don't miss one type adjacent to the other. switch( len2 ) { case 3: adj_tris.insert( conn2, idx, *i, k ); break; case 4: adj_quads.insert( conn2, idx, *i, k ); break; default: adj_poly.insert( conn + k, 1, *i, k ); break; } } } else { rval = thisMB->get_connectivity( *i, conn, len, false, &storage ); if( MB_SUCCESS != rval ) return rval; idx = std::find( conn, conn + len, *it ) - conn; assert( idx != len ); if( len > CN::VerticesPerEntity( type ) ) { higher_order = true; // skip higher-order nodes for now if( idx >= CN::VerticesPerEntity( type ) ) { if( !printed_nonconformal_ho_warning ) { printed_nonconformal_ho_warning = true; std::cerr << "Non-conformal higher-order mesh detected in skinner: " << "vertex " << ID_FROM_HANDLE( *it ) << " is a corner in " << "some elements and a higher-order node in others" << std::endl; } continue; } } // For each side of the element... const int num_faces = CN::NumSubEntities( type, 2 ); for( int f = 0; f < num_faces; ++f ) { int num_vtx; const short* face_indices = CN::SubEntityVertexIndices( type, 2, f, face_type, num_vtx ); const short face_idx = std::find( face_indices, face_indices + num_vtx, (short)idx ) - face_indices; // skip sides that do not contain vertex from outer loop if( face_idx == num_vtx ) continue; // current vertex not in this face assert( num_vtx <= 4 ); // polyhedra handled above switch( face_type ) { case MBTRI: adj_tris.insert( conn, face_idx, *i, f, face_indices ); break; case MBQUAD: adj_quads.insert( conn, face_idx, *i, f, face_indices ); break; default: return MB_TYPE_OUT_OF_RANGE; } } } } // end for (adj[3]) // If vertex is not on skin, advance to next vertex if( 0 == ( adj_tris.num_skin() + adj_quads.num_skin() + adj_poly.num_skin() ) ) continue; // If user requested that skin *vertices* be passed back... if( skin_verts ) { // Put skin vertex in output list hint = skin_verts->insert( hint, *it ); // Add mid-edge and mid-face nodes to vertex list if( !corners_only && higher_order ) { for( AdjSides< 3 >::const_iterator t = adj_tris.begin(); t != adj_tris.end(); ++t ) { if( t->skin() ) { elem = t->adj_elem; EntityType type = TYPE_FROM_HANDLE( elem ); rval = thisMB->get_connectivity( elem, conn, len, false ); if( MB_SUCCESS != rval ) return rval; if( !CN::HasMidNodes( type, len ) ) continue; EntityHandle ec[3] = { *it, t->handles[0], t->handles[1] }; CN::SideNumber( type, conn, ec, 3, 2, side, sense, offset ); CN::SubEntityNodeIndices( type, len, 2, side, face_type, clen, indices ); assert( MBTRI == face_type ); for( int k = 3; k < clen; ++k ) skin_verts->insert( conn[indices[k]] ); } } for( AdjSides< 4 >::const_iterator q = adj_quads.begin(); q != adj_quads.end(); ++q ) { if( q->skin() ) { elem = q->adj_elem; EntityType type = TYPE_FROM_HANDLE( elem ); rval = thisMB->get_connectivity( elem, conn, len, false ); if( MB_SUCCESS != rval ) return rval; if( !CN::HasMidNodes( type, len ) ) continue; EntityHandle ec[4] = { *it, q->handles[0], q->handles[1], q->handles[2] }; CN::SideNumber( type, conn, ec, 4, 2, side, sense, offset ); CN::SubEntityNodeIndices( type, len, 2, side, face_type, clen, indices ); assert( MBQUAD == face_type ); for( int k = 4; k < clen; ++k ) skin_verts->insert( conn[indices[k]] ); } } } } // If user requested that we pass back the list of 2D elements // representing the skin of the mesh... if( find_faces ) { // Search list of adjacent faces for any that are on the skin adj.clear(); rval = thisMB->get_adjacencies( &*it, 1, 2, false, adj ); if( MB_SUCCESS != rval ) return rval; for( i = adj.begin(); i != adj.end(); ++i ) { rval = thisMB->get_connectivity( *i, conn, len, true ); if( MB_SUCCESS != rval ) return rval; const int idx2 = std::find( conn, conn + len, *it ) - conn; if( idx2 >= len ) { assert( printed_nonconformal_ho_warning ); continue; } // Note that the order of the terms in the if statements below // is important. We want to unmark any existing skin faces even // if we aren't returning them. Otherwise we'll end up creating // duplicates if create_faces is true. if( 3 == len ) { if( adj_tris.find_and_unmark( conn, idx2, elem ) && skin_faces ) { if( reversed_faces && face_reversed( elem, conn, MBTRI ) ) reversed_faces->insert( *i ); else skin_faces->insert( *i ); } } else if( 4 == len ) { if( adj_quads.find_and_unmark( conn, idx2, elem ) && skin_faces ) { if( reversed_faces && face_reversed( elem, conn, MBQUAD ) ) reversed_faces->insert( *i ); else skin_faces->insert( *i ); } } else { if( adj_poly.find_and_unmark( &*i, 1, elem ) && skin_faces ) skin_faces->insert( *i ); } } } // If user does not want use to create new faces representing // sides for which there is currently no explicit element, // skip the remaining code and advance the outer loop to the // next vertex. if( !create_faces ) continue; // Polyhedra always have explicitly defined faces, so // there is no way we could need to create such a face. assert( 0 == adj_poly.num_skin() ); // Create any skin tris that don't exist if( adj_tris.num_skin() ) { for( AdjSides< 3 >::const_iterator t = adj_tris.begin(); t != adj_tris.end(); ++t ) { if( t->skin() ) { EntityHandle tri, c[3] = { *it, t->handles[0], t->handles[1] }; rval = create_side( this_set, t->adj_elem, MBTRI, c, tri ); if( MB_SUCCESS != rval ) return rval; if( skin_faces ) skin_faces->insert( tri ); } } } // Create any skin quads that don't exist if( adj_quads.num_skin() ) { for( AdjSides< 4 >::const_iterator q = adj_quads.begin(); q != adj_quads.end(); ++q ) { if( q->skin() ) { EntityHandle quad, c[4] = { *it, q->handles[0], q->handles[1], q->handles[2] }; rval = create_side( this_set, q->adj_elem, MBQUAD, c, quad ); if( MB_SUCCESS != rval ) return rval; if( skin_faces ) skin_faces->insert( quad ); } } } } // end for each vertex return MB_SUCCESS; }
bool moab::Skinner::has_larger_angle | ( | EntityHandle & | entity1, |
EntityHandle & | entity2, | ||
double | reference_angle_cosine | ||
) | [protected] |
Definition at line 965 of file Skinner.cpp.
References moab::Util::normal(), and thisMB.
Referenced by find_inferred_edges().
{ // compare normals to get angle. We assume that the surface quads // which we test here will be approximately planar double norm[2][3]; Util::normal( thisMB, entity1, norm[0][0], norm[0][1], norm[0][2] ); Util::normal( thisMB, entity2, norm[1][0], norm[1][1], norm[1][2] ); double cosine = norm[0][0] * norm[1][0] + norm[0][1] * norm[1][1] + norm[0][2] * norm[1][2]; if( cosine < reference_angle_cosine ) { return true; } return false; }
ErrorCode moab::Skinner::initialize | ( | ) | [protected] |
Definition at line 53 of file Skinner.cpp.
References add_adjacency(), moab::Range::begin(), moab::Range::end(), entities, ErrorCode, moab::Interface::get_entities_by_type(), mAdjTag, MB_CHK_ERR, MB_SUCCESS, MB_TAG_BIT, MB_TAG_CREAT, MB_TAG_DENSE, MB_TYPE_BIT, MB_TYPE_OPAQUE, MBVERTEX, mDeletableMBTag, mTargetDim, moab::Interface::tag_get_handle(), moab::Interface::tag_set_data(), thisMB, moab::TYPE_FROM_HANDLE(), and moab::CN::TypeDimensionMap.
Referenced by classify_2d_boundary(), and find_skin_noadj().
{ // go through and mark all the target dimension entities // that already exist as not deleteable // also get the connectivity tags for each type // also populate adjacency information EntityType type; DimensionPair target_ent_types = CN::TypeDimensionMap[mTargetDim]; void* null_ptr = NULL; ErrorCode result = thisMB->tag_get_handle( "skinner adj", sizeof( void* ), MB_TYPE_OPAQUE, mAdjTag, MB_TAG_DENSE | MB_TAG_CREAT, &null_ptr );MB_CHK_ERR( result ); if( mDeletableMBTag == 0 ) { result = thisMB->tag_get_handle( "skinner deletable", 1, MB_TYPE_BIT, mDeletableMBTag, MB_TAG_BIT | MB_TAG_CREAT );MB_CHK_ERR( result ); } Range entities; // go through each type at this dimension for( type = target_ent_types.first; type <= target_ent_types.second; ++type ) { // get the entities of this type in the MB thisMB->get_entities_by_type( 0, type, entities ); // go through each entity of this type in the MB // and set its deletable tag to NO Range::iterator iter, end_iter; end_iter = entities.end(); for( iter = entities.begin(); iter != end_iter; ++iter ) { unsigned char bit = 0x1; result = thisMB->tag_set_data( mDeletableMBTag, &( *iter ), 1, &bit ); assert( MB_SUCCESS == result ); // add adjacency information too if( TYPE_FROM_HANDLE( *iter ) != MBVERTEX ) add_adjacency( *iter ); } } return MB_SUCCESS; }
ErrorCode moab::Skinner::remove_adjacency | ( | EntityHandle | entity | ) | [protected] |
Definition at line 632 of file Skinner.cpp.
References ErrorCode, moab::Interface::get_connectivity(), mAdjTag, MB_CHK_ERR, MB_SUCCESS, moab::Interface::tag_get_data(), and thisMB.
Referenced by find_skin_noadj().
{ std::vector< EntityHandle > nodes, *adj = NULL; ErrorCode result = thisMB->get_connectivity( &entity, 1, nodes );MB_CHK_ERR( result ); std::vector< EntityHandle >::iterator iter = std::min_element( nodes.begin(), nodes.end() ); if( iter == nodes.end() ) return MB_FAILURE; // remove this entity from the node if( thisMB->tag_get_data( mAdjTag, &( *iter ), 1, &adj ) == MB_SUCCESS && adj != NULL ) { iter = std::find( adj->begin(), adj->end(), entity ); if( iter != adj->end() ) adj->erase( iter ); } return result; }
ErrorCode moab::Skinner::skin_box | ( | ScdBox * | box, |
bool | get_vertices, | ||
Range & | output_handles, | ||
bool | create_skin_elements | ||
) | [protected] |
skin a structured box, taking advantage of structured information
Definition at line 296 of file Skinner.cpp.
References moab::ScdBox::box_max(), moab::ScdBox::box_min(), dim, ErrorCode, moab::ScdBox::get_adj_edge_or_face(), moab::Interface::get_adjacencies(), moab::HomCoord::i(), moab::Range::insert(), moab::HomCoord::j(), moab::HomCoord::k(), MB_SUCCESS, moab::Range::merge(), thisMB, and moab::Interface::UNION.
Referenced by find_skin_scd().
{ HomCoord bmin = box->box_min(), bmax = box->box_max(); // don't support 1d boxes if( bmin.j() == bmax.j() && bmin.k() == bmax.k() ) return MB_FAILURE; int dim = ( bmin.k() == bmax.k() ? 1 : 2 ); ErrorCode rval; EntityHandle ent; // i=min for( int k = bmin.k(); k < bmax.k(); k++ ) { for( int j = bmin.j(); j < bmax.j(); j++ ) { ent = 0; rval = box->get_adj_edge_or_face( dim, bmin.i(), j, k, 0, ent, create_skin_elements ); if( MB_SUCCESS != rval ) return rval; if( ent ) output_handles.insert( ent ); } } // i=max for( int k = bmin.k(); k < bmax.k(); k++ ) { for( int j = bmin.j(); j < bmax.j(); j++ ) { ent = 0; rval = box->get_adj_edge_or_face( dim, bmax.i(), j, k, 0, ent, create_skin_elements ); if( MB_SUCCESS != rval ) return rval; if( ent ) output_handles.insert( ent ); } } // j=min for( int k = bmin.k(); k < bmax.k(); k++ ) { for( int i = bmin.i(); i < bmax.i(); i++ ) { ent = 0; rval = box->get_adj_edge_or_face( dim, i, bmin.j(), k, 1, ent, create_skin_elements ); if( MB_SUCCESS != rval ) return rval; if( ent ) output_handles.insert( ent ); } } // j=max for( int k = bmin.k(); k < bmax.k(); k++ ) { for( int i = bmin.i(); i < bmax.i(); i++ ) { ent = 0; rval = box->get_adj_edge_or_face( dim, i, bmax.j(), k, 1, ent, create_skin_elements ); if( MB_SUCCESS != rval ) return rval; if( ent ) output_handles.insert( ent ); } } // k=min for( int j = bmin.j(); j < bmax.j(); j++ ) { for( int i = bmin.i(); i < bmax.i(); i++ ) { ent = 0; rval = box->get_adj_edge_or_face( dim, i, j, bmin.k(), 2, ent, create_skin_elements ); if( MB_SUCCESS != rval ) return rval; if( ent ) output_handles.insert( ent ); } } // k=max for( int j = bmin.j(); j < bmax.j(); j++ ) { for( int i = bmin.i(); i < bmax.i(); i++ ) { ent = 0; rval = box->get_adj_edge_or_face( dim, i, j, bmax.k(), 2, ent, create_skin_elements ); if( MB_SUCCESS != rval ) return rval; if( ent ) output_handles.insert( ent ); } } if( get_vertices ) { Range verts; rval = thisMB->get_adjacencies( output_handles, 0, true, verts, Interface::UNION ); if( MB_SUCCESS != rval ) return rval; output_handles.merge( verts ); } return MB_SUCCESS; }
Tag moab::Skinner::mAdjTag [protected] |
Definition at line 50 of file Skinner.hpp.
Referenced by add_adjacency(), deinitialize(), find_match(), initialize(), and remove_adjacency().
Tag moab::Skinner::mDeletableMBTag [protected] |
Definition at line 49 of file Skinner.hpp.
Referenced by deinitialize(), entity_deletable(), and initialize().
int moab::Skinner::mTargetDim [protected] |
Definition at line 51 of file Skinner.hpp.
Referenced by classify_2d_boundary(), find_skin_noadj(), and initialize().
Interface* moab::Skinner::thisMB [protected] |
the MB instance that this works with
Definition at line 47 of file Skinner.hpp.
Referenced by add_adjacency(), classify_2d_boundary(), deinitialize(), entity_deletable(), find_geometric_skin(), find_inferred_edges(), find_match(), find_skin(), find_skin_noadj(), find_skin_scd(), find_skin_vertices(), find_skin_vertices_1D(), has_larger_angle(), initialize(), remove_adjacency(), and skin_box().