This example demonstrates how to skin triangular meshes to recover boundary edges. It shows how to load a mesh file, remove existing edges, get surface sets, and call a fast skinning function that creates edges for triangles that are not paired. The skinner is optimized and assumes no edges exist in the MOAB instance initially.
#include <iostream>
#include <cstdlib>
#include "MBCore.hpp"
#include "MBRange.hpp"
{
};
{
{
return (
int)( 100.f * ia->
v1 - 100.f * ib->
v1 );
}
else
{
return (
int)( 100.f * ia->
v0 - 100.f * ib->
v0 );
}
}
MBErrorCode
skin_tris( MBInterface*
mb, MBRange tris, MBRange& skin_edges )
{
skin_edges.clear();
if( !tris.all_of_type(
MBTRI ) )
return MB_FAILURE;
int n_edges;
MBErrorCode rval =
mb->get_number_entities_by_type( 0,
MBEDGE, n_edges );
if( 0 != n_edges )
{
std::cerr << "skin_tris: failed because " << n_edges << " edges exist in the MOAB instance" << std::endl;
return MB_FAILURE;
}
edge* edges =
new edge[3 * tris.size()];
int n_verts;
int ii = 0;
for( MBRange::iterator i = tris.begin(); i != tris.end(); ++i )
{
const MBEntityHandle* conn;
rval =
mb->get_connectivity( *i, conn, n_verts );
if( 3 != n_verts ) return MB_FAILURE;
if( conn[0] == conn[1] || conn[1] == conn[2] || conn[2] == conn[0] )
{
std::cerr << "skin_tris: degenerate triangle" << std::endl;
return MB_FAILURE;
}
edges[3 * ii + 0].
v0 = conn[0];
edges[3 * ii + 0].
v1 = conn[1];
edges[3 * ii + 1].
v0 = conn[1];
edges[3 * ii + 1].
v1 = conn[2];
edges[3 * ii + 2].
v0 = conn[2];
edges[3 * ii + 2].
v1 = conn[0];
ii++;
}
for( unsigned int i = 0; i < 3 * tris.size(); ++i )
{
if( edges[i].
v0 > edges[i].
v1 )
{
MBEntityHandle temp = edges[i].
v0;
edges[i].
v0 = edges[i].
v1;
}
}
for( unsigned int i = 0; i < 3 * tris.size(); i++ )
{
if( 3 * tris.size() - 1 == i )
{
const MBEntityHandle conn[2] = { edges[i].
v0, edges[i].
v1 };
skin_edges.insert(
edge );
}
else if( edges[i].
v0 == edges[i + 1].
v0 && edges[i].
v1 == edges[i + 1].
v1 )
{
i++;
while( edges[i].
v0 == edges[i + 1].
v0 && edges[i].
v1 == edges[i + 1].
v1 )
{
std::cout << "find_skin WARNING: non-manifold edge" << std::endl;
mb->list_entity( edges[i].
v0 );
mb->list_entity( edges[i].
v1 );
++i;
}
}
else
{
const MBEntityHandle conn[2] = { edges[i].
v0, edges[i].
v1 };
skin_edges.insert(
edge );
}
}
delete[] edges;
}
int main(
int argc,
char** argv )
{
if( 1 == argc )
{
std::cout << "Usage: " << argv[0] << " <filename>" << std::endl;
return 0;
}
MBCore*
mb =
new MBCore();
MBErrorCode rval =
mb->load_file( argv[1] );
MBRange edges;
rval =
mb->get_entities_by_type( 0,
MBEDGE, edges );
if( !edges.empty() ) std::cout << "Warning: deleting all MBEdges" << std::endl;
rval =
mb->delete_entities( edges );
MBTag geom_tag;
MBRange surf_sets;
int two = 2;
void* dim[] = { &two };
rval =
mb->get_entities_by_type_and_tag( 0,
MBENTITYSET, &geom_tag, dim, 1, surf_sets );
for( MBRange::iterator i = surf_sets.begin(); i != surf_sets.end(); ++i )
{
MBRange tris;
rval =
mb->get_entities_by_type( *i,
MBTRI, tris );
MBRange skin_edges;
std::cout << "surface has " << skin_edges.size() << " skin edges" << std::endl;
rval =
mb->delete_entities( skin_edges );
}
}