Mesh Oriented datABase  (version 5.6.0)
An array-based unstructured mesh library
ContinentsOnGlobe.cpp File Reference

Example demonstrating continent boundary detection on spherical meshes. More...

#include "moab/Core.hpp"
#include "moab/ReadUtilIface.hpp"
#include <cmath>
#include "moab/CartVect.hpp"
#include <iostream>
#include <fstream>
+ Include dependency graph for ContinentsOnGlobe.cpp:

Go to the source code of this file.

Functions

double getLat (CartVect p)
 
double getLon (CartVect p)
 
bool interior_point (vector< double > &coords, int &startLoop, int &endLoop, double lat, double lon)
 
int main (int argc, char **argv)
 

Variables

string bd_name = string( MESH_DIR ) + string( "/../examples/earth/boundary_points.dat" )
 
string loops = string( MESH_DIR ) + string( "/../examples/earth/SaveLoopCounts" )
 
string input_file = string( MESH_DIR ) + string( "/../examples/earth/poly2000.h5m" )
 

Detailed Description

Example demonstrating continent boundary detection on spherical meshes.

This example shows how to:

  • Load spherical mesh files and continent boundary data
  • Convert 3D spherical coordinates to 2D lat-lon coordinates
  • Perform point-in-polygon tests for continent detection
  • Create mesh sets for different continents and islands
  • Tag mesh elements with continent information
  • Handle complex boundary loops for major landmasses
  • Write continent-mapped mesh files

This tool is useful for climate and geophysical applications where continent boundaries need to be identified on spherical meshes.

Author
MOAB Development Team
Date
2024

Definition in file ContinentsOnGlobe.cpp.

Function Documentation

◆ getLat()

double getLat ( CartVect  p)
Examples
ContinentsOnGlobe.cpp.

Definition at line 49 of file ContinentsOnGlobe.cpp.

50 {
51  p.normalize();
52  return asin( p[2] );
53 }

References moab::CartVect::normalize().

Referenced by main().

◆ getLon()

double getLon ( CartVect  p)
Examples
ContinentsOnGlobe.cpp.

Definition at line 54 of file ContinentsOnGlobe.cpp.

55 {
56  p.normalize();
57  double lon;
58 
59  lon = atan2( p[1], p[0] );
60 
61  if( lon < -2.95 )
62  { // separate Asia/Europe from Americas
63  return 2.0 * M_PI + lon;
64  }
65  else
66  {
67  return lon;
68  }
69 }

References moab::CartVect::normalize().

Referenced by main().

◆ interior_point()

bool interior_point ( vector< double > &  coords,
int &  startLoop,
int &  endLoop,
double  lat,
double  lon 
)
Examples
ContinentsOnGlobe.cpp.

Definition at line 74 of file ContinentsOnGlobe.cpp.

75 {
76  // compute oriented angle between point and edges in the loop
77  // if angle ~ +/-2Pi, it is in the interior
78  double totalAngle = 0;
79  for( int i = startLoop; i <= endLoop; i++ )
80  {
81  double x1 = coords[2 * i], y1 = coords[2 * i + 1];
82  int i2 = i + 1;
83  if( i == endLoop ) i2 = startLoop;
84  double x2 = coords[2 * i2], y2 = coords[2 * i2 + 1];
85  CartVect P1( x1 - lat, y1 - lon, 0. );
86  CartVect P2( x2 - lat, y2 - lon, 0. );
87  CartVect cross = P1 * P2;
88  double angle1 = angle( P1, P2 );
89  if( cross[2] < 0 ) angle1 = -angle1;
90  totalAngle += angle1;
91  }
92  if( fabs( totalAngle + 2 * M_PI ) < 0.1 || fabs( totalAngle - 2 * M_PI ) < 0.1 ) return true;
93  return false;
94 }

References moab::angle(), and moab::cross().

Referenced by main().

◆ main()

int main ( int  argc,
char **  argv 
)

get loops for boundaries

Examples
ContinentsOnGlobe.cpp.

Definition at line 96 of file ContinentsOnGlobe.cpp.

97 {
98  // Get MOAB instance
99  Interface* mb = new( std::nothrow ) Core;
100  if( NULL == mb ) return 1;
101 
102  if( argc > 1 )
103  {
104  // User has input file for mesh file
105  input_file = argv[1];
106  }
107 
108  cout << "input file : " << input_file << "\n";
109  std::vector< double > coords;
110  ifstream bdFile( bd_name.c_str() );
111  if( !bdFile )
112  {
113  cout << endl << "Failed to open file " << bd_name << endl;
114  ;
115  return 1;
116  }
117  coords.resize( 0 );
118  while( !bdFile.eof() )
119  {
120  double co;
121  bdFile >> co;
122  coords.push_back( co );
123  }
124  cout << " number of boundary points:" << coords.size() / 3 << "\n";
125  /// get loops for boundaries
126  vector< int > loopsindx;
127  ifstream loopFile( loops.c_str() );
128  while( !loopFile.eof() )
129  {
130  int indx;
131  loopFile >> indx;
132  loopsindx.push_back( indx );
133  }
134  cout << "number of loops: " << loopsindx.size() / 2 << "\n";
135  // convert loops to lat-lon loops
136  // it will be easier to determine in-out relations for points in 2d plane
137  // careful with the international time zone; ( + - Pi longitude )
138  vector< double > coords2d;
139  coords2d.resize( coords.size() / 3 * 2 );
140  for( int i = 0; i < (int)coords.size() / 3; i++ )
141  {
142  CartVect p( coords[3 * i], coords[3 * i + 1], coords[3 * i + 2] );
143  coords2d[2 * i] = getLat( p );
144  coords2d[2 * i + 1] = getLon( p );
145  }
146 
147  MB_CHK_SET_ERR( mb->load_file( input_file.c_str() ), "Can't load file" );
148  // look at the center of element, and see if it is inside the loop
149 
150  Range cells;
151  MB_CHK_SET_ERR( mb->get_entities_by_dimension( 0, 2, cells ), "Can't get cells" );
152 
153  cout << "number of cells: " << cells.size() << "\n";
154 
155  // tag for continents
156  Tag tag1;
157  int defa = -1;
158  MB_CHK_SET_ERR( mb->tag_get_handle( "continent", 1, MB_TYPE_INTEGER, tag1, MB_TAG_DENSE | MB_TAG_CREAT, &defa ),
159  "Trouble creating continent tag" );
160  EntityHandle islandSets[6];
161  for( int loop_index = 0; loop_index < 6; loop_index++ )
162  {
163  MB_CHK_SET_ERR( mb->create_meshset( MESHSET_SET, islandSets[loop_index] ), "Can't create island set" );
164  int startLoop = loopsindx[2 * loop_index];
165  int endLoop = loopsindx[2 * loop_index + 1];
166 
167  vector< EntityHandle > interiorCells;
168  for( Range::iterator cit = cells.begin(); cit != cells.end(); cit++ )
169  {
170  EntityHandle cell = *cit;
171  // see if it is in the interior of the loop
173  MB_CHK_SET_ERR( mb->get_coords( &cell, 1, &( center[0] ) ), "Can't get cell center coords" );
174  double lat = getLat( center ), lon = getLon( center );
175  // if NA, use some boxes too, for lat/lon
176  // if (NorthAmerica && (lat < 0.15 || lon < M_PI || lon > 2*M_PI - 0.5) )
177  // continue;
178 
179  if( interior_point( coords2d, startLoop, endLoop, lat, lon ) )
180  {
181  interiorCells.push_back( cell );
182  MB_CHK_SET_ERR( mb->tag_set_data( tag1, &cell, 1, &loop_index ), "Can't get tag on cell" );
183  }
184  }
185 
186  MB_CHK_SET_ERR( mb->add_entities( islandSets[loop_index], &interiorCells[0], interiorCells.size() ),
187  "Can't add entities to set" );
188  }
189 
190  std::stringstream islandFile;
191 
192  islandFile << "map.h5m";
193 
194  MB_CHK_SET_ERR( mb->write_file( islandFile.str().c_str() ), "Can't write island file" );
195  return 0;
196 }

References moab::Core::add_entities(), bd_name, moab::Range::begin(), center(), moab::Core::create_meshset(), moab::Range::end(), moab::Core::get_coords(), moab::Core::get_entities_by_dimension(), getLat(), getLon(), input_file, interior_point(), moab::Core::load_file(), loops, mb, MB_CHK_SET_ERR, MB_TAG_CREAT, MB_TAG_DENSE, MB_TYPE_INTEGER, MESHSET_SET, moab::Range::size(), moab::Core::tag_get_handle(), moab::Core::tag_set_data(), and moab::Core::write_file().

Variable Documentation

◆ bd_name

string bd_name = string( MESH_DIR ) + string( "/../examples/earth/boundary_points.dat" )
Examples
ContinentsOnGlobe.cpp.

Definition at line 45 of file ContinentsOnGlobe.cpp.

Referenced by main().

◆ input_file

◆ loops

string loops = string( MESH_DIR ) + string( "/../examples/earth/SaveLoopCounts" )
Examples
ContinentsOnGlobe.cpp.

Definition at line 46 of file ContinentsOnGlobe.cpp.

Referenced by main().