Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
00001 #include <iostream> 00002 #include <cstdlib> 00003 #include "MBCore.hpp" 00004 #include "MBRange.hpp" 00005 #include "MBTagConventions.hpp" 00006 00007 // Hold edges in an array of vertex handles. 00008 struct edge 00009 { 00010 MBEntityHandle v0; 00011 MBEntityHandle v1; 00012 }; 00013 00014 // edge structure comparision function for qsort 00015 // If the first vertex handle is the same, compare the second. 00016 int compare_edge( const void* a, const void* b ) 00017 { 00018 struct edge* ia = (struct edge*)a; 00019 struct edge* ib = (struct edge*)b; 00020 if( ia->v0 == ib->v0 ) 00021 { 00022 return (int)( 100.f * ia->v1 - 100.f * ib->v1 ); 00023 } 00024 else 00025 { 00026 return (int)( 100.f * ia->v0 - 100.f * ib->v0 ); 00027 } 00028 } 00029 00030 // This skinner is fast partly because it assumes that no edges exist in the MOAB 00031 // instance. Checking to see if an edge exists before creating a new one is slow. 00032 MBErrorCode skin_tris( MBInterface* mb, MBRange tris, MBRange& skin_edges ) 00033 { 00034 00035 // Empty the output range and make sure that the input range is only tris 00036 skin_edges.clear(); 00037 if( tris.empty() ) return MB_ENTITY_NOT_FOUND; 00038 if( !tris.all_of_type( MBTRI ) ) return MB_FAILURE; 00039 00040 // Remove edges from the instance. 00041 int n_edges; 00042 MBErrorCode rval = mb->get_number_entities_by_type( 0, MBEDGE, n_edges ); 00043 if( MB_SUCCESS != rval ) return rval; 00044 if( 0 != n_edges ) 00045 { 00046 std::cerr << "skin_tris: failed because " << n_edges << " edges exist in the MOAB instance" << std::endl; 00047 return MB_FAILURE; 00048 } 00049 00050 // Get connectivity. Do not create MBEdges. 00051 edge* edges = new edge[3 * tris.size()]; 00052 int n_verts; 00053 int ii = 0; 00054 for( MBRange::iterator i = tris.begin(); i != tris.end(); ++i ) 00055 { 00056 const MBEntityHandle* conn; 00057 rval = mb->get_connectivity( *i, conn, n_verts ); 00058 if( MB_SUCCESS != rval ) return rval; 00059 if( 3 != n_verts ) return MB_FAILURE; 00060 // points should not be degenerate 00061 if( conn[0] == conn[1] || conn[1] == conn[2] || conn[2] == conn[0] ) 00062 { 00063 std::cerr << "skin_tris: degenerate triangle" << std::endl; 00064 return MB_FAILURE; 00065 } 00066 00067 // make edges 00068 edges[3 * ii + 0].v0 = conn[0]; 00069 edges[3 * ii + 0].v1 = conn[1]; 00070 edges[3 * ii + 1].v0 = conn[1]; 00071 edges[3 * ii + 1].v1 = conn[2]; 00072 edges[3 * ii + 2].v0 = conn[2]; 00073 edges[3 * ii + 2].v1 = conn[0]; 00074 ii++; 00075 } 00076 00077 // Ensure that the first vertex handle is the lowest 00078 for( unsigned int i = 0; i < 3 * tris.size(); ++i ) 00079 { 00080 if( edges[i].v0 > edges[i].v1 ) 00081 { 00082 MBEntityHandle temp = edges[i].v0; 00083 edges[i].v0 = edges[i].v1; 00084 edges[i].v1 = temp; 00085 } 00086 } 00087 00088 // Sort by first handle, then second handle. 00089 qsort( edges, 3 * tris.size(), sizeof( struct edge ), compare_edge ); 00090 00091 // Go through array, saving edges that are not paired. 00092 for( unsigned int i = 0; i < 3 * tris.size(); i++ ) 00093 { 00094 // If the last edge has not been paired, create it. This avoids overrunning 00095 // the edges array with i+1. 00096 if( 3 * tris.size() - 1 == i ) 00097 { 00098 const MBEntityHandle conn[2] = { edges[i].v0, edges[i].v1 }; 00099 MBEntityHandle edge; 00100 rval = mb->create_element( MBEDGE, conn, 2, edge ); 00101 if( MB_SUCCESS != rval ) return rval; 00102 skin_edges.insert( edge ); 00103 00104 // If a match exists, skip ahead 00105 } 00106 else if( edges[i].v0 == edges[i + 1].v0 && edges[i].v1 == edges[i + 1].v1 ) 00107 { 00108 i++; 00109 // test to make sure surface is manifold 00110 while( edges[i].v0 == edges[i + 1].v0 && edges[i].v1 == edges[i + 1].v1 ) 00111 { 00112 std::cout << "find_skin WARNING: non-manifold edge" << std::endl; 00113 mb->list_entity( edges[i].v0 ); 00114 mb->list_entity( edges[i].v1 ); 00115 ++i; 00116 } 00117 // otherwise a skin edge has been found 00118 } 00119 else 00120 { 00121 const MBEntityHandle conn[2] = { edges[i].v0, edges[i].v1 }; 00122 MBEntityHandle edge; 00123 rval = mb->create_element( MBEDGE, conn, 2, edge ); 00124 if( MB_SUCCESS != rval ) return rval; 00125 skin_edges.insert( edge ); 00126 } 00127 } 00128 delete[] edges; 00129 return MB_SUCCESS; 00130 } 00131 00132 // Skin triangles to recover edges. 00133 // Triangles are contained in surface sets. 00134 int main( int argc, char** argv ) 00135 { 00136 if( 1 == argc ) 00137 { 00138 std::cout << "Usage: " << argv[0] << " <filename>" << std::endl; 00139 return 0; 00140 } 00141 00142 // get MOAB instance and read the file 00143 MBCore* mb = new MBCore(); 00144 MBErrorCode rval = mb->load_file( argv[1] ); 00145 if( MB_SUCCESS != rval ) return 0; 00146 00147 // this optimized skinner requires removing all MBEdges from the MOAB instance 00148 MBRange edges; 00149 rval = mb->get_entities_by_type( 0, MBEDGE, edges ); 00150 if( MB_SUCCESS != rval ) return 0; 00151 if( !edges.empty() ) std::cout << "Warning: deleting all MBEdges" << std::endl; 00152 rval = mb->delete_entities( edges ); 00153 if( MB_SUCCESS != rval ) return 0; 00154 00155 // get surface sets 00156 MBTag geom_tag; 00157 rval = mb->tag_get_handle( GEOM_DIMENSION_TAG_NAME, 1, MB_TYPE_INTEGER, geom_tag ); 00158 if( MB_SUCCESS != rval ) return 0; 00159 MBRange surf_sets; 00160 int two = 2; 00161 void* dim[] = { &two }; 00162 rval = mb->get_entities_by_type_and_tag( 0, MBENTITYSET, &geom_tag, dim, 1, surf_sets ); 00163 if( MB_SUCCESS != rval ) return 0; 00164 00165 // skin each surface 00166 for( MBRange::iterator i = surf_sets.begin(); i != surf_sets.end(); ++i ) 00167 { 00168 00169 // get triangles in the surface set 00170 MBRange tris; 00171 rval = mb->get_entities_by_type( *i, MBTRI, tris ); 00172 if( MB_SUCCESS != rval ) return 0; 00173 00174 // call the skinning function 00175 MBRange skin_edges; 00176 rval = skin_tris( mb, tris, skin_edges ); 00177 if( MB_SUCCESS != rval ) return 0; 00178 00179 // do something with the result 00180 std::cout << "surface has " << skin_edges.size() << " skin edges" << std::endl; 00181 00182 // remove the edges for the optimized skinner 00183 rval = mb->delete_entities( skin_edges ); 00184 if( MB_SUCCESS != rval ) return 0; 00185 } 00186 }