Mesh Oriented datABase  (version 5.6.0)
An array-based unstructured mesh library
QuadTriConv.cpp
Go to the documentation of this file.
1 /**
2  * @file QuadTriConv.cpp
3  * @brief Example demonstrating conversion of repeated-vertex cells to triangles/quads/polygons
4  *
5  * This example shows how to:
6  * - Load a mesh file with repeated vertices in 2D cells (e.g., at poles)
7  * - Merge repeated vertices in cell connectivity
8  * - Convert cells to triangles, quads, or polygons as appropriate
9  * - Preserve global ID tags during conversion
10  * - Write the modified mesh to a new file
11  *
12  * This is useful for cleaning up rll meshes or other grids with repeated
13  * vertices at the poles or other singularities.
14  *
15  * @author MOAB Development Team
16  * @date 2024
17  *
18 
19  * \brief Merge vertices in 2d cell, if they are repeated \n
20  * <b>To run</b>: QuadTriConv input_file output_file \n
21  *
22  * In this example, a mesh that has vertices repeated due to south or north pole, for
23  * example in an rll mesh, need to be converted to triangles, preserving GLOBAL_ID tag
24  *
25  * @param argc Number of command line arguments
26  * @param argv Command line arguments array
27  * @return 0 on success, 1 on failure
28  */
29 
30 #include <iostream>
31 #include <vector>
32 //#include <string>
33 
34 // Include header for MOAB instance and tag conventions for
35 #include "moab/Core.hpp"
36 #include "MBTagConventions.hpp"
37 
38 using namespace moab;
39 using namespace std;
40 
41 int main( int argc, char** argv )
42 {
43  // Get MOAB instance
44  Interface* mb = new( std::nothrow ) Core;
45  if( NULL == mb ) return 1;
46 
47  std::string filename, outfile;
48  outfile = string( "out.h5m" );
49  if( argc == 1 ) return 0;
50  if( argc > 1 ) filename = string( argv[1] );
51  if( argc > 2 ) outfile = string( argv[2] );
52 
53  // This file is in the mesh files directory
54  MB_CHK_SET_ERR( mb->load_file( filename.c_str() ), "Failed to read" );
55 
56  // get all cells of dimension 2;
57  Range cells;
58  MB_CHK_SET_ERR( mb->get_entities_by_dimension( 0, 2, cells ), "Failed to get cells" );
59 
60  cout << " number of cells : " << cells.size() << "\n";
61 
62  Tag gid; // global id tag
63  MB_CHK_SET_ERR( mb->tag_get_handle( "GLOBAL_ID", gid ), "Failed to get Global ID tag" );
64 
65  Range modifiedCells; // will be deleted at the end; keep the gid
66 
67  for( Range::iterator cit = cells.begin(); cit != cells.end(); cit++ )
68  {
69  EntityHandle cell = *cit;
70  const EntityHandle* connec = NULL;
71  int num_verts = 0;
72  MB_CHK_SET_ERR( mb->get_connectivity( cell, connec, num_verts ), "Failed to get connectivity" );
73 
74  vector< EntityHandle > newConnec;
75  newConnec.push_back( connec[0] ); // at least one vertex
76  int index = 0;
77  int new_size = 1;
78  while( index < num_verts - 2 )
79  {
80  int next_index = ( index + 1 );
81  if( connec[next_index] != newConnec[new_size - 1] )
82  {
83  newConnec.push_back( connec[next_index] );
84  new_size++;
85  }
86  index++;
87  }
88  // add the last one only if different from previous and first node
89  if( ( connec[num_verts - 1] != connec[num_verts - 2] ) && ( connec[num_verts - 1] != connec[0] ) )
90  {
91  newConnec.push_back( connec[num_verts - 1] );
92  new_size++;
93  }
94  if( new_size < num_verts )
95  {
96  // cout << "new cell from " << cell << " has only " << new_size << " vertices \n";
97  modifiedCells.insert( cell );
98  // create a new cell with type triangle, quad or polygon
99  EntityType type = MBTRI;
100  if( new_size == 3 )
101  type = MBTRI;
102  else if( new_size == 4 )
103  type = MBQUAD;
104  else if( new_size > 4 )
105  type = MBPOLYGON;
106 
107  // create new cell
108  EntityHandle newCell;
109  MB_CHK_SET_ERR( mb->create_element( type, &newConnec[0], new_size, newCell ), "Failed to create new cell" );
110  // set the old id to the new element
111  int id;
112  MB_CHK_SET_ERR( mb->tag_get_data( gid, &cell, 1, &id ), "Failed to get global id" );
113  MB_CHK_SET_ERR( mb->tag_set_data( gid, &newCell, 1, &id ), "Failed to set global id on new cell" );
114  }
115  }
116 
117  mb->delete_entities( modifiedCells );
118  // in case global ids are not set for vertices, set them, in order;
119  // they are needed for migrating later on
120  //
121  Range verts;
122  MB_CHK_SET_ERR( mb->get_entities_by_dimension( 0, 0, verts ), "Failed to get vertices" );
123 
124  vector< int > gids;
125  gids.resize( verts.size() );
126  MB_CHK_SET_ERR( mb->tag_get_data( gid, verts, &gids[0] ), "Failed to get gids on vertices" );
127  if( gids[0] <= 0 )
128  {
129  // gids were never set, assign them
130  for( size_t i = 1; i <= verts.size(); i++ )
131  gids[i - 1] = (int)i;
132  MB_CHK_SET_ERR( mb->tag_set_data( gid, verts, &gids[0] ), "Failed to set gids on vertices" );
133  }
134  MB_CHK_SET_ERR( mb->write_file( outfile.c_str() ), "Failed to write new file" );
135 
136  cout << " wrote file " << outfile << " with " << modifiedCells.size() << " modified cells\n";
137 
138  delete mb;
139  return 0;
140 }