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