Mesh Oriented datABase  (version 5.4.1)
Array-based unstructured mesh datastructure
SkinMesh.cpp
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines