Converting Code that Traverses Facet Vertices and Polygons in an INDEXED_MESH into Code that Traverses Facets in a LINKED_MESH


The following examples illustrate reading facet data from an INDEXED_MESH, and taking advantage of a higher performance faceter class. The newer class LINKED_MESH is a super-set of data that is contained in the older class INDEXED_MESH. When api_facet_entity uses LINKED_MESH_MANAGER instead of INDEXED_MESH_MANAGER, it performs significantly faster but results in a slightly larger memory footprint. A base class, SEQUENTIAL_MESH, was created to provide a common access to both classes. These examples are not only for those who wish to convert data using the faster LINKED_MESH class, but also serves as examples for those unfamiliar with the LINKED_MESH and the INDEXED_MESH classes.

This section contains snippets of C++ code to illustrate how to traverse facets in an INDEXED_MESH. These snippets are designed to be very simple starting points for developing your own code - they are not complete, compiling and runtime programs.

INDEXED_MESH code converted to LINKED_MESH code Example -2

The following function is an example of one of the ways to traverse facets in an INDEXED_MESH. This shows how to traverse the vertices first, then the polygons.

Note: To see how to traverse only the polygons, see Linked Mesh Example - 1.

void writeIndicesOfINDEXED_MESH(ENTITY * inEntity, FILE* fp)
{
  // Get the transform on the body, if any.
  SPAtransf xform;
  ENTITY * owner;
  api_get_owner( inEntity, owner );
  if ( is_BODY( owner ) )
  {
    BODY * body;
    body = (BODY*)owner;
    if ( body->transform() )
      xform = body->transform()->transform();
  }
  ENTITY_LIST faceList;
  api_get_faces( inEntity, faceList );
  
  // Loop through each face and print facet data
  for ( int faceIndex = 0; faceIndex < faceList.count(); faceIndex++ )
  {
    FACE * face = (FACE*)faceList[faceIndex];
 
    // Find the attribute for facets attached to the face. This is the mesh.
    MESH * face_mesh = NULL;
    af_query( (ENTITY*)face, IDX_MESH_APP, IDX_MESH_ID, face_mesh );
    INDEXED_MESH *mesh = (INDEXED_MESH*)face_mesh;
    if (mesh && mesh->get_type_of_mesh() != INDEXED_MESH_TYPE)
      mesh = 0;
    if ( mesh == NULL )
    {
      printf( "No indexed mesh available for face\n" );
      continue;
    }
    // Get the number of nodes of the whole face
    int nodeCount = mesh->get_num_vertex();
    fprintf( fp, "Face index: %d.  Number of nodes for the whole face = %d\n",
      faceIndex, nodeCount);
 
    // Loop through each facet node and print its data
    for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
    {
      SPAposition pos (mesh->get_position( nodeIndex ));
      SPAunit_vector vec (mesh->get_normal( nodeIndex ));
      SPApar_pos uv (mesh->get_uv_as_entered( nodeIndex ));
      pos *= xform;
      vec *= xform;
      fprintf(fp, "      %d: (%g %g) (%g %g %g) (%g %g %g)\n",
        nodeIndex, (double)uv.u, (double)uv.v,
        pos.x(), pos.y(), pos.z(), vec.x(), vec.y(), vec.z());
    }
    
    // Print the number of facets for this face
    int polygonCount = mesh->get_num_polygon();
    fprintf( fp, "Face index: %d.  Number of facets = %d\n",
      faceIndex, polygonCount );
 
    // Loop through each facet and print its data (node indices)
    for ( int polygonIndex = 0; polygonIndex < polygonCount; polygonIndex++ )
    {
      // Get the facet's data as an indexed_polygon
      indexed_polygon *poly = mesh->get_polygon( polygonIndex );
      if (poly)
      {
        // Print the number of nodes in this facet
        int nodeCount = poly->num_vertex();
        fprintf( fp, "      %d: %d:", polygonIndex, nodeCount );
 
        // Print the node indices of this facet
        for ( int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++ )
        {
          polygon_vertex* vert = poly->get_vertex( nodeIndex );
          int index = mesh->get_vertex_index( vert );
          fprintf( fp," %d", index );
        }
 
        // Print which edge is shared with the next facet
        int ishare_edge = poly->get_share_info();
        fprintf( fp," %d", ishare_edge );
        fprintf( fp, "\n");
      }
    }
  } // End braces for Loop through each face
}

The following example performs the same operation as the one above, but uses a SEQUENTIAL_MESH. This is the base class for both INDEXED_MESH and LINKED_MESH. Using a LINKED_MESH improves faceting performance.

void writeIndicesOfSEQUENTIAL_MESH( ENTITY * inEntity, FILE* fp )
{
  // Get the transform on the body, if any.
  SPAtransf xform;
  ENTITY * owner;
  api_get_owner( inEntity, owner );
  if ( is_BODY( owner ) )
  {
    BODY * body;
    body = (BODY *)owner;
    if (body->transform())
      xform = body->transform()->transform();
  }
  ENTITY_LIST faceList;
  api_get_faces( inEntity, faceList );
  
  // Loop through each face and print facet data
  for ( int faceIndex = 0; faceIndex < faceList.count(); faceIndex++ )
  {
    FACE * face = (FACE*)faceList[faceIndex];
 
    // Find the attribute for facets attached to the face. This is the mesh.
    MESH * face_mesh = NULL;
    af_query( (ENTITY*)face, IDX_MESH_APP, IDX_MESH_ID, face_mesh );
    if ( face_mesh == NULL )
    {
      printf( "No indexed mesh or linked mesh available for a face\n" );
      continue;
    }
    SEQUENTIAL_MESH *mesh = (SEQUENTIAL_MESH*)face_mesh;
    if ( !mesh )
      continue;
    // Get the number of nodes of the whole face
    int nodeCount = mesh->get_num_node();
    fprintf( fp, "Face index: %d.  Number of nodes for the whole face = %d\n",
      faceIndex, nodeCount);
    
    // Loop through each facet node and print its data
    MESH_NODE meshNode;
    // Get the first node of the whole face
    if ( !mesh->get_first_node( meshNode ) )
      continue;
    for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
    {
      SPAposition pos ( mesh->get_position( meshNode ) );
      SPAunit_vector vec ( mesh->get_normal( meshNode ) );
      SPApar_pos uv;
      mesh->get_par_pos_surface( mesh->get_par_pos( meshNode ), uv );
      pos *= xform;
      vec *= xform;
      fprintf( fp, "      %d: (%g %g) (%g %g %g) (%g %g %g)\n",
        nodeIndex, (double)uv.u, (double)uv.v,
        pos.x(), pos.y(), pos.z(), vec.x(), vec.y(), vec.z() );
      // Setup for the next loop by getting the next node of the whole face
      mesh->get_next_node( meshNode );
    }
    
    // Print the number of facets for this face
    int polygonCount = mesh->get_num_polygon();
    fprintf( fp, "Face index: %d.  Number of facets = %d\n",
      faceIndex, polygonCount );
 
    // Loop through each facet and print its data (node indices)
    MESH_POLYGON meshPolygon;
    // Get the handle of the first facet
    if ( !mesh->get_first_polygon( meshPolygon ) )
      continue;
    for ( int polygonIndex = 0; polygonIndex < polygonCount; polygonIndex++ )
    {
      // Print the number of nodes in this facet
      int nodeCount = mesh->get_num_polynode( meshPolygon );
      fprintf( fp, "      %d: %d:", polygonIndex, nodeCount );
 
      // Print the node indices of this facet
      MESH_POLYNODE meshPolynode;
      // Get the handle of the first node of this facet
      if ( !mesh->get_first_polynode( meshPolygon, meshPolynode ) )
        continue;
      for ( int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++ )
      {
        int index = mesh->get_node_index( meshPolynode );
        fprintf( fp," %d", index );
        // Setup for the next loop by getting the next node of the facet
        mesh->get_next_polynode( meshPolynode );
      }
      
      // Print which edge is shared with the next facet
      int ishare_edge = mesh->get_share_info( meshPolygon );
      fprintf( fp," %d", ishare_edge );
      fprintf( fp, "\n" );
 
      // Setup for the next loop by getting the next facet
      mesh->get_next_polygon( meshPolygon );
    }
  } // End braces for Loop through each face
}

Related topics:

Refinements
Mesh Managers
Step-by-Step Faceting
Discarding or Keeping Facet Data
Faceting Functions and Classes
Faceting Using Scheme

[Top]