Mesh Oriented datABase  (version 5.6.0)
An array-based unstructured mesh library
BoundaryContinents.cpp
Go to the documentation of this file.
1 /**
2  * @file BoundaryContinents.cpp
3  * @brief Example demonstrating creation of continent boundary edge meshes
4  *
5  * This example shows how to:
6  * - Load continent boundary point data and loop information
7  * - Create edge meshes from boundary point sequences
8  * - Convert 3D spherical coordinates to 2D lat-lon coordinates
9  * - Handle periodic boundary conditions for longitude wrapping
10  * - Remove long edges that cross the date line
11  * - Create mesh sets for boundary visualization
12  * - Write boundary meshes in VTK format
13  *
14  * This tool is useful for creating continent boundary meshes
15  * for climate and geophysical applications.
16  *
17  * @author MOAB Development Team
18  * @date 2024
19  *
20  * @example BoundaryContinents.cpp
21  * Description: read boundary points and loops that form islands and continents
22  and create an edge mesh file \n
23  *
24  * BoundaryContinents <boundary_points.dat> \c SaveLoopCounts
25  * (default values can run if users don't specify input files)
26  *
27  * @param argc Number of command line arguments
28  * @param argv Command line arguments array
29  * @return 0 on success, 1 on failure
30  */
31 
32 #include "moab/Core.hpp"
33 #include "moab/ReadUtilIface.hpp"
34 #include "moab/CartVect.hpp"
35 #include <iostream>
36 #include <fstream>
37 
38 using namespace moab;
39 using namespace std;
40 
41 string bd_name = string( MESH_DIR ) + string( "/../examples/earth/boundary_points.dat" );
42 string loops = string( MESH_DIR ) + string( "/../examples/earth/SaveLoopCounts" );
43 
44 double getLat( CartVect p )
45 {
46  p.normalize();
47  return asin( p[2] );
48 }
49 double getLon( CartVect p )
50 {
51  p.normalize();
52  double lon;
53 
54  lon = atan2( p[1], p[0] );
55  if( lon < -2.95 )
56  { // this is Behring Strait :)
57  return 2.0 * M_PI + lon;
58  }
59  else
60  {
61  return lon;
62  }
63 }
64 
65 int main( int argc, char** argv )
66 {
67  // Get MOAB instance
68  Interface* mb = new( std::nothrow ) Core;
69  if( NULL == mb ) return 1;
70 
71  if( argc > 1 )
72  {
73  // User has input file for boundary describing continents
74  bd_name = argv[1];
75  }
76  if( argc > 2 )
77  {
78  // User has input file for loops for continents/islands
79  loops = argv[2];
80  }
81 
82  std::vector< double > coords;
83  ifstream bdFile( bd_name.c_str() );
84  if( !bdFile )
85  {
86  cout << endl << "Failed to open file " << bd_name << endl;
87  ;
88  return 1;
89  }
90  coords.resize( 0 );
91  while( !bdFile.eof() )
92  {
93  double co;
94  bdFile >> co;
95  coords.push_back( co );
96  }
97  cout << " number of boundary points:" << coords.size() / 3 << "\n";
98  /// get loops for boundaries
99  vector< int > loopsindx;
100  ifstream loopFile( loops.c_str() );
101  while( !loopFile.eof() )
102  {
103  int indx;
104  loopFile >> indx;
105  loopsindx.push_back( indx );
106  }
107  cout << "number of loops: " << loopsindx.size() / 2 << "\n";
108  ReadUtilIface* readMeshIface;
109  mb->query_interface( readMeshIface );
110  Range verts;
111 
112  MB_CHK_SET_ERR( mb->create_vertices( &coords[0], coords.size() / 3, verts ), "do not create boundary vertices" );
113 
114  Tag gid = mb->globalId_tag();
115 
116  int num_edges = 0;
117  for( size_t i = 0; i < loopsindx.size() / 2; i++ )
118  {
119  num_edges += ( loopsindx[2 * i + 1] - loopsindx[2 * i] + 1 );
120  }
121  EntityHandle handle;
122  EntityHandle* conn_array;
123  MB_CHK_SET_ERR( readMeshIface->get_element_connect( num_edges, 2, MBEDGE, 1, handle, conn_array ), "do not elems" );
124  int i1 = 0; // index in edge connectivity
125  for( size_t i = 0; i < loopsindx.size() / 2; i++ )
126  {
127  for( int j = loopsindx[2 * i]; j <= loopsindx[2 * i + 1]; j++ )
128  {
129  int j2;
130  j2 = j;
131  if( j == loopsindx[2 * i + 1] ) j2 = loopsindx[2 * i] - 1; // close the loop
132  conn_array[2 * i1] = verts[j - 1]; // vertices for sure start at 1
133  conn_array[2 * i1 + 1] = verts[j2]; // vertices for sure start at 1
134  i1++;
135  }
136  // the last vertex is first one in the loop
137  }
138 
139  Range bedges( handle, handle + num_edges - 1 );
140  EntityHandle bound_set;
141  MB_CHK_SET_ERR( mb->create_meshset( MESHSET_SET, bound_set ), "Can't create boundary edges set" );
142 
143  MB_CHK_SET_ERR( mb->add_entities( bound_set, bedges ), "Can't add edges to boundary set" );
144 
145  // set global ids for vertices and edges
146  vector< int > gids;
147  gids.resize( verts.size() );
148  for( int j = 0; j < (int)verts.size(); j++ )
149  {
150  gids[j] = j + 1;
151  }
152  MB_CHK_SET_ERR( mb->tag_set_data( gid, verts, &gids[0] ), "Can't set global ids on verts" );
153  // we have less edges than vertices, we can reuse the array for edges too
154  MB_CHK_SET_ERR( mb->tag_set_data( gid, bedges, &gids[0] ), "Can't set global ids on edges" );
155 
156  mb->write_file( "bound.vtk", 0, 0, &bound_set, 1 );
157 
158  // now project the mesh in 2d plane
159  // get all the vertices coordinates
160  std::vector< CartVect > co3;
161  co3.resize( verts.size() );
162  MB_CHK_SET_ERR( mb->get_coords( verts, &( co3[0][0] ) ), "Can't get vertex coords" );
163  for( size_t i = 0; i < verts.size(); i++ )
164  {
165  CartVect p = co3[i];
166  double lat1 = getLat( p );
167  double lon1 = getLon( p );
168  co3[i] = CartVect( lon1, lat1, 0. );
169  }
170  MB_CHK_SET_ERR( mb->set_coords( verts, &( co3[0][0] ) ), "Can't set new vertex coords" );
171  // remove edges in 2d that are too long (longer than 6; they are on the other side..., periodic)
172 
173  Range longEdges;
174  for( Range::iterator eit = bedges.begin(); eit != bedges.end(); ++eit )
175  {
176  EntityHandle eh = *eit;
177  const EntityHandle* conn;
178  int nconn;
179  MB_CHK_ERR( mb->get_connectivity( eh, conn, nconn ) );
180  // get coordinates of nodes
181  CartVect c2[2];
182  MB_CHK_ERR( mb->get_coords( conn, 2, &( c2[0][0] ) ) );
183  double dist = ( c2[1] - c2[0] ).length_squared();
184  if( dist > 36. ) // too long edge in 2d, remove it
185  longEdges.insert( eh );
186  }
187  MB_CHK_ERR( mb->delete_entities( longEdges ) );
188 
189  mb->write_file( "bound2d.vtk" );
190  delete mb;
191 
192  return 0;
193 }