moab
SkinMesh.cpp
Go to the documentation of this file.
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 }  
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines