Loading [MathJax]/extensions/tex2jax.js
Mesh Oriented datABase  (version 5.5.1)
An array-based unstructured mesh library
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
SkinMesh.cpp
Go to the documentation of this file.
1 #include <iostream> 2 #include <cstdlib> 3 #include "MBCore.hpp" 4 #include "MBRange.hpp" 5 #include "MBTagConventions.hpp" 6  7 // Hold edges in an array of vertex handles. 8 struct edge 9 { 10  MBEntityHandle v0; 11  MBEntityHandle v1; 12 }; 13  14 // edge structure comparision function for qsort 15 // If the first vertex handle is the same, compare the second. 16 int compare_edge( const void* a, const void* b ) 17 { 18  struct edge* ia = (struct edge*)a; 19  struct edge* ib = (struct edge*)b; 20  if( ia->v0 == ib->v0 ) 21  { 22  return (int)( 100.f * ia->v1 - 100.f * ib->v1 ); 23  } 24  else 25  { 26  return (int)( 100.f * ia->v0 - 100.f * ib->v0 ); 27  } 28 } 29  30 // This skinner is fast partly because it assumes that no edges exist in the MOAB 31 // instance. Checking to see if an edge exists before creating a new one is slow. 32 MBErrorCode skin_tris( MBInterface* mb, MBRange tris, MBRange& skin_edges ) 33 { 34  35  // Empty the output range and make sure that the input range is only tris 36  skin_edges.clear(); 37  if( tris.empty() ) return MB_ENTITY_NOT_FOUND; 38  if( !tris.all_of_type( MBTRI ) ) return MB_FAILURE; 39  40  // Remove edges from the instance. 41  int n_edges; 42  MBErrorCode rval = mb->get_number_entities_by_type( 0, MBEDGE, n_edges ); 43  if( MB_SUCCESS != rval ) return rval; 44  if( 0 != n_edges ) 45  { 46  std::cerr << "skin_tris: failed because " << n_edges << " edges exist in the MOAB instance" << std::endl; 47  return MB_FAILURE; 48  } 49  50  // Get connectivity. Do not create MBEdges. 51  edge* edges = new edge[3 * tris.size()]; 52  int n_verts; 53  int ii = 0; 54  for( MBRange::iterator i = tris.begin(); i != tris.end(); ++i ) 55  { 56  const MBEntityHandle* conn; 57  rval = mb->get_connectivity( *i, conn, n_verts ); 58  if( MB_SUCCESS != rval ) return rval; 59  if( 3 != n_verts ) return MB_FAILURE; 60  // points should not be degenerate 61  if( conn[0] == conn[1] || conn[1] == conn[2] || conn[2] == conn[0] ) 62  { 63  std::cerr << "skin_tris: degenerate triangle" << std::endl; 64  return MB_FAILURE; 65  } 66  67  // make edges 68  edges[3 * ii + 0].v0 = conn[0]; 69  edges[3 * ii + 0].v1 = conn[1]; 70  edges[3 * ii + 1].v0 = conn[1]; 71  edges[3 * ii + 1].v1 = conn[2]; 72  edges[3 * ii + 2].v0 = conn[2]; 73  edges[3 * ii + 2].v1 = conn[0]; 74  ii++; 75  } 76  77  // Ensure that the first vertex handle is the lowest 78  for( unsigned int i = 0; i < 3 * tris.size(); ++i ) 79  { 80  if( edges[i].v0 > edges[i].v1 ) 81  { 82  MBEntityHandle temp = edges[i].v0; 83  edges[i].v0 = edges[i].v1; 84  edges[i].v1 = temp; 85  } 86  } 87  88  // Sort by first handle, then second handle. 89  qsort( edges, 3 * tris.size(), sizeof( struct edge ), compare_edge ); 90  91  // Go through array, saving edges that are not paired. 92  for( unsigned int i = 0; i < 3 * tris.size(); i++ ) 93  { 94  // If the last edge has not been paired, create it. This avoids overrunning 95  // the edges array with i+1. 96  if( 3 * tris.size() - 1 == i ) 97  { 98  const MBEntityHandle conn[2] = { edges[i].v0, edges[i].v1 }; 99  MBEntityHandle edge; 100  rval = mb->create_element( MBEDGE, conn, 2, edge ); 101  if( MB_SUCCESS != rval ) return rval; 102  skin_edges.insert( edge ); 103  104  // If a match exists, skip ahead 105  } 106  else if( edges[i].v0 == edges[i + 1].v0 && edges[i].v1 == edges[i + 1].v1 ) 107  { 108  i++; 109  // test to make sure surface is manifold 110  while( edges[i].v0 == edges[i + 1].v0 && edges[i].v1 == edges[i + 1].v1 ) 111  { 112  std::cout << "find_skin WARNING: non-manifold edge" << std::endl; 113  mb->list_entity( edges[i].v0 ); 114  mb->list_entity( edges[i].v1 ); 115  ++i; 116  } 117  // otherwise a skin edge has been found 118  } 119  else 120  { 121  const MBEntityHandle conn[2] = { edges[i].v0, edges[i].v1 }; 122  MBEntityHandle edge; 123  rval = mb->create_element( MBEDGE, conn, 2, edge ); 124  if( MB_SUCCESS != rval ) return rval; 125  skin_edges.insert( edge ); 126  } 127  } 128  delete[] edges; 129  return MB_SUCCESS; 130 } 131  132 // Skin triangles to recover edges. 133 // Triangles are contained in surface sets. 134 int main( int argc, char** argv ) 135 { 136  if( 1 == argc ) 137  { 138  std::cout << "Usage: " << argv[0] << " <filename>" << std::endl; 139  return 0; 140  } 141  142  // get MOAB instance and read the file 143  MBCore* mb = new MBCore(); 144  MBErrorCode rval = mb->load_file( argv[1] ); 145  if( MB_SUCCESS != rval ) return 0; 146  147  // this optimized skinner requires removing all MBEdges from the MOAB instance 148  MBRange edges; 149  rval = mb->get_entities_by_type( 0, MBEDGE, edges ); 150  if( MB_SUCCESS != rval ) return 0; 151  if( !edges.empty() ) std::cout << "Warning: deleting all MBEdges" << std::endl; 152  rval = mb->delete_entities( edges ); 153  if( MB_SUCCESS != rval ) return 0; 154  155  // get surface sets 156  MBTag geom_tag; 157  rval = mb->tag_get_handle( GEOM_DIMENSION_TAG_NAME, 1, MB_TYPE_INTEGER, geom_tag ); 158  if( MB_SUCCESS != rval ) return 0; 159  MBRange surf_sets; 160  int two = 2; 161  void* dim[] = { &two }; 162  rval = mb->get_entities_by_type_and_tag( 0, MBENTITYSET, &geom_tag, dim, 1, surf_sets ); 163  if( MB_SUCCESS != rval ) return 0; 164  165  // skin each surface 166  for( MBRange::iterator i = surf_sets.begin(); i != surf_sets.end(); ++i ) 167  { 168  169  // get triangles in the surface set 170  MBRange tris; 171  rval = mb->get_entities_by_type( *i, MBTRI, tris ); 172  if( MB_SUCCESS != rval ) return 0; 173  174  // call the skinning function 175  MBRange skin_edges; 176  rval = skin_tris( mb, tris, skin_edges ); 177  if( MB_SUCCESS != rval ) return 0; 178  179  // do something with the result 180  std::cout << "surface has " << skin_edges.size() << " skin edges" << std::endl; 181  182  // remove the edges for the optimized skinner 183  rval = mb->delete_entities( skin_edges ); 184  if( MB_SUCCESS != rval ) return 0; 185  } 186 }