[MOAB-dev] r3600 - in MOAB/trunk/examples: . SkinMesh
bmsmith6 at wisc.edu
bmsmith6 at wisc.edu
Fri Mar 12 12:12:30 CST 2010
Author: bmsmith
Date: 2010-03-12 12:12:29 -0600 (Fri, 12 Mar 2010)
New Revision: 3600
Added:
MOAB/trunk/examples/SkinMesh/
MOAB/trunk/examples/SkinMesh/Makefile
MOAB/trunk/examples/SkinMesh/SkinMesh.cpp
Log:
A simple example of skinning triangles to recover edges.
Added: MOAB/trunk/examples/SkinMesh/Makefile
===================================================================
--- MOAB/trunk/examples/SkinMesh/Makefile (rev 0)
+++ MOAB/trunk/examples/SkinMesh/Makefile 2010-03-12 18:12:29 UTC (rev 3600)
@@ -0,0 +1,8 @@
+include ${MOAB_LIB_DIR}/moab.make
+
+SkinMesh : SkinMesh.o
+ ${CXX} $< ${MOAB_LIBS_LINK} -o $@
+
+.cpp.o :
+ ${CXX} ${MOAB_INCLUDES} -c $<
+
Added: MOAB/trunk/examples/SkinMesh/SkinMesh.cpp
===================================================================
--- MOAB/trunk/examples/SkinMesh/SkinMesh.cpp (rev 0)
+++ MOAB/trunk/examples/SkinMesh/SkinMesh.cpp 2010-03-12 18:12:29 UTC (rev 3600)
@@ -0,0 +1,169 @@
+#include <iostream>
+#include <stdlib.h>
+#include "MBCore.hpp"
+#include "MBRange.hpp"
+#include "MBTagConventions.hpp"
+
+// Hold edges in an array of vertex handles.
+struct edge {
+ MBEntityHandle v0;
+ MBEntityHandle v1;
+};
+
+// edge structure comparision function for qsort
+// If the first vertex handle is the same, compare the second.
+int compare_edge(const void *a, const void *b) {
+ 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);
+ }
+}
+
+// This skinner is fast partly because it assumes that no edges exist in the MOAB
+// instance. Checking to see if an edge exists before creating a new one is slow.
+MBErrorCode skin_tris( MBInterface *mb, MBRange tris, MBRange &skin_edges ) {
+
+ // 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;
+}
+
+
+// Skin triangles to recover edges.
+// Triangles are contained in surface sets.
+int main(int argc, char **argv) {
+ 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_create( GEOM_DIMENSION_TAG_NAME, sizeof(int), MB_TAG_DENSE,
+ MB_TYPE_INTEGER, geom_tag, 0, true );
+ 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;
+ }
+}
More information about the moab-dev
mailing list