moab
SkinMesh.cpp File Reference
#include <iostream>
#include <stdlib.h>
#include "MBCore.hpp"
#include "MBRange.hpp"
#include "MBTagConventions.hpp"

Go to the source code of this file.

Classes

struct  edge

Functions

int compare_edge (const void *a, const void *b)
MBErrorCode skin_tris (MBInterface *mb, MBRange tris, MBRange &skin_edges)
int main (int argc, char **argv)

Function Documentation

int compare_edge ( const void *  a,
const void *  b 
)

Definition at line 15 of file SkinMesh.cpp.

                                               {
  struct edge *ia = (struct edge *)a;
  struct edge *ib = (struct edge *)b;
  if(ia->v0 == ib->v0) {
    return (int)(100.f*ia->v1 - 100.f*ib->v1);
  } else {
    return (int)(100.f*ia->v0 - 100.f*ib->v0);
  }
}
int main ( int  argc,
char **  argv 
)

Definition at line 118 of file SkinMesh.cpp.

                                {
  if (1 == argc) {
  std::cout << "Usage: " << argv[0] << " <filename>" << std::endl;
    return 0;
  }     

  // get MOAB instance and read the file                                                                                                  
  MBCore *mb = new MBCore();
  MBErrorCode rval = mb->load_file(argv[1]);
  if(MB_SUCCESS != rval) return 0;

  // this optimized skinner requires removing all MBEdges from the MOAB instance
  MBRange edges;
  rval = mb->get_entities_by_type( 0, MBEDGE, edges );
  if(MB_SUCCESS != rval) return 0;
  if( !edges.empty() ) std::cout << "Warning: deleting all MBEdges" << std::endl;
  rval = mb->delete_entities( edges );
  if(MB_SUCCESS != rval) return 0;

  // get surface sets
  MBTag geom_tag;
  rval = mb->tag_get_handle( GEOM_DIMENSION_TAG_NAME, 1, MB_TYPE_INTEGER, geom_tag );
  if(MB_SUCCESS != rval) return 0;
  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 );
  if(MB_SUCCESS != rval) return 0;

  // skin each surface
  for(MBRange::iterator i=surf_sets.begin(); i!=surf_sets.end(); ++i) {

    // get triangles in the surface set
    MBRange tris;
    rval = mb->get_entities_by_type( *i, MBTRI, tris );
    if(MB_SUCCESS != rval) return 0;

    // call the skinning function
    MBRange skin_edges;
    rval = skin_tris( mb, tris, skin_edges );
    if(MB_SUCCESS != rval) return 0;

    // do something with the result
    std::cout << "surface has " << skin_edges.size() << " skin edges" << std::endl;

    // remove the edges for the optimized skinner
    rval = mb->delete_entities( skin_edges );
    if(MB_SUCCESS != rval) return 0;    
  }
}  
MBErrorCode skin_tris ( MBInterface mb,
MBRange  tris,
MBRange skin_edges 
)

Definition at line 27 of file SkinMesh.cpp.

                                                                            {    
  
  // Empty the output range and make sure that the input range is only tris
  skin_edges.clear(); 
  if(tris.empty()) return MB_ENTITY_NOT_FOUND;
  if(!tris.all_of_type(MBTRI)) return MB_FAILURE;

  // Remove edges from the instance.
  int n_edges;
  MBErrorCode rval = mb->get_number_entities_by_type( 0, MBEDGE, n_edges );
  if(MB_SUCCESS != rval) return rval;
  if(0 != n_edges) {
    std::cerr << "skin_tris: failed because " << n_edges 
              << " edges exist in the MOAB instance" << std::endl;
    return MB_FAILURE;
  }      

  // Get connectivity. Do not create MBEdges.
  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(MB_SUCCESS != rval) return rval;
    if(3 != n_verts) return MB_FAILURE;
    // points should not be degenerate
    if(conn[0]==conn[1] || conn[1]==conn[2] || conn[2]==conn[0]) {
      std::cerr << "skin_tris: degenerate triangle" << std::endl;
      return MB_FAILURE;
    }

    // make edges
    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++;
  }

  // Ensure that the first vertex handle is the lowest
  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;
      edges[i].v1 = temp;
    }
  }

  // Sort by first handle, then second handle.
  qsort(edges, 3*tris.size(), sizeof(struct edge), compare_edge);    

  // Go through array, saving edges that are not paired.
  for(unsigned int i=0; i<3*tris.size(); i++) {
    // If the last edge has not been paired, create it. This avoids overrunning
    // the edges array with i+1.
    if(3*tris.size()-1 == i) {
      const MBEntityHandle conn[2] = {edges[i].v0, edges[i].v1};
      MBEntityHandle edge;
      rval = mb->create_element( MBEDGE, conn, 2, edge );
      if(MB_SUCCESS != rval) return rval;
      skin_edges.insert(edge);
    
    // If a match exists, skip ahead
    } else if(edges[i].v0==edges[i+1].v0 && edges[i].v1==edges[i+1].v1) {
      i++;
      // test to make sure surface is manifold
      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;
      }
    // otherwise a skin edge has been found
    } else {
      const MBEntityHandle conn[2] = {edges[i].v0, edges[i].v1};
      MBEntityHandle edge;
      rval = mb->create_element( MBEDGE, conn, 2, edge );
      if(MB_SUCCESS != rval) return rval;
      skin_edges.insert( edge );
    } 
  }
  delete[] edges;
  return MB_SUCCESS;
}
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines