Mesh Oriented datABase  (version 5.5.0)
An array-based unstructured mesh library
moab::IntxUtils Class Reference

#include <IntxUtils.hpp>

Classes

struct  SphereCoords
 

Static Public Member Functions

static double dist2 (double *a, double *b)
 
static double area2D (double *a, double *b, double *c)
 
static int borderPointsOfXinY2 (double *X, int nX, double *Y, int nY, double *P, int *side, double epsilon_area)
 
static int SortAndRemoveDoubles2 (double *P, int &nP, double epsilon)
 
static ErrorCode EdgeIntersections2 (double *blue, int nsBlue, double *red, int nsRed, int *markb, int *markr, double *points, int &nPoints)
 
static ErrorCode EdgeIntxRllCs (double *blue, CartVect *bluec, int *blueEdgeType, int nsBlue, double *red, CartVect *redc, int nsRed, int *markb, int *markr, int plane, double Radius, double *points, int &nPoints)
 
static void decide_gnomonic_plane (const CartVect &pos, int &oPlane)
 
static ErrorCode gnomonic_projection (const CartVect &pos, double R, int plane, double &c1, double &c2)
 
static ErrorCode reverse_gnomonic_projection (const double &c1, const double &c2, double R, int plane, CartVect &pos)
 
static void gnomonic_unroll (double &c1, double &c2, double R, int plane)
 
static ErrorCode global_gnomonic_projection (Interface *mb, EntityHandle inSet, double R, bool centers_only, EntityHandle &outSet)
 
static void transform_coordinates (double *avg_position, int projection_type)
 
static SphereCoords cart_to_spherical (CartVect &)
 
static CartVect spherical_to_cart (SphereCoords &)
 
static ErrorCode ScaleToRadius (Interface *mb, EntityHandle set, double R)
 
static double distance_on_great_circle (CartVect &p1, CartVect &p2)
 
static ErrorCode enforce_convexity (Interface *mb, EntityHandle set, int rank=0)
 
static double oriented_spherical_angle (double *A, double *B, double *C)
 
static ErrorCode fix_degenerate_quads (Interface *mb, EntityHandle set)
 
static double distance_on_sphere (double la1, double te1, double la2, double te2)
 
static ErrorCode intersect_great_circle_arcs (double *A, double *B, double *C, double *D, double R, double *E)
 
static ErrorCode intersect_great_circle_arc_with_clat_arc (double *A, double *B, double *C, double *D, double R, double *E, int &np)
 
static int borderPointsOfCSinRLL (CartVect *redc, double *red2dc, int nsRed, CartVect *bluec, int nsBlue, int *blueEdgeType, double *P, int *side, double epsil)
 
static ErrorCode deep_copy_set_with_quads (Interface *mb, EntityHandle source_set, EntityHandle dest_set)
 
static ErrorCode remove_duplicate_vertices (Interface *mb, EntityHandle file_set, double merge_tol, std::vector< Tag > &tagList)
 
static ErrorCode remove_padded_vertices (Interface *mb, EntityHandle file_set, std::vector< Tag > &tagList)
 

Detailed Description

Definition at line 16 of file IntxUtils.hpp.

Member Function Documentation

◆ area2D()

◆ borderPointsOfCSinRLL()

int moab::IntxUtils::borderPointsOfCSinRLL ( CartVect redc,
double *  red2dc,
int  nsRed,
CartVect bluec,
int  nsBlue,
int *  blueEdgeType,
double *  P,
int *  side,
double  epsil 
)
static

Definition at line 1733 of file IntxUtils.cpp.

1742 {
1743  int extraPoints = 0;
1744  // first decide the blue z coordinates
1745  CartVect A( 0. ), B( 0. ), C( 0. ), D( 0. );
1746  for( int i = 0; i < nsBlue; i++ )
1747  {
1748  if( blueEdgeType[i] == 0 )
1749  {
1750  int iP1 = ( i + 1 ) % nsBlue;
1751  if( bluec[i][2] > bluec[iP1][2] )
1752  {
1753  A = bluec[i];
1754  B = bluec[iP1];
1755  C = bluec[( i + 2 ) % nsBlue];
1756  D = bluec[( i + 3 ) % nsBlue]; // it could be back to A, if triangle on top
1757  break;
1758  }
1759  }
1760  }
1761  if( nsBlue == 3 && B[2] < 0 )
1762  {
1763  // select D to be C
1764  D = C;
1765  C = B; // B is the south pole then
1766  }
1767  // so we have A, B, C, D, with A at the top, b going down, then C, D, D > C, A > B
1768  // AB is const longitude, BC and DA constant latitude
1769  // check now each of the red points if they are inside this rectangle
1770  for( int i = 0; i < nsRed; i++ )
1771  {
1772  CartVect& X = redc[i];
1773  if( X[2] > A[2] || X[2] < B[2] ) continue; // it is above or below the rectangle
1774  // now decide if it is between the planes OAB and OCD
1775  if( ( ( A * B ) % X >= -epsil ) && ( ( C * D ) % X >= -epsil ) )
1776  {
1777  side[i] = 1; //
1778  // it means point X is in the rectangle that we want , on the sphere
1779  // pass the coords 2d
1780  P[extraPoints * 2] = red2dc[2 * i];
1781  P[extraPoints * 2 + 1] = red2dc[2 * i + 1];
1782  extraPoints++;
1783  }
1784  }
1785  return extraPoints;
1786 }

Referenced by moab::IntxRllCssphere::computeIntersectionBetweenTgtAndSrc().

◆ borderPointsOfXinY2()

int moab::IntxUtils::borderPointsOfXinY2 ( double *  X,
int  nX,
double *  Y,
int  nY,
double *  P,
int *  side,
double  epsilon_area 
)
static

Definition at line 44 of file IntxUtils.cpp.

45 {
46  // 2 triangles, 3 corners, is the corner of X in Y?
47  // Y must have a positive area
48  /*
49  */
50  int extraPoint = 0;
51  for( int i = 0; i < nX; i++ )
52  {
53  // compute double the area of all nY triangles formed by a side of Y and a corner of X; if
54  // one is negative, stop (negative means it is outside; X and Y are all oriented such that
55  // they are positive oriented;
56  // if one area is negative, it means it is outside the convex region, for sure)
57  double* A = X + 2 * i;
58 
59  int inside = 1;
60  for( int j = 0; j < nY; j++ )
61  {
62  double* B = Y + 2 * j;
63  int j1 = ( j + 1 ) % nY;
64  double* C = Y + 2 * j1; // no copy of data
65 
66  double area2 = ( B[0] - A[0] ) * ( C[1] - A[1] ) - ( C[0] - A[0] ) * ( B[1] - A[1] );
67  if( area2 < -epsilon_area )
68  {
69  inside = 0;
70  break;
71  }
72  }
73  if( inside )
74  {
75  side[i] = 1; // so vertex i of X is inside the convex region formed by Y
76  // so side has nX dimension (first array)
77  P[extraPoint * 2] = A[0];
78  P[extraPoint * 2 + 1] = A[1];
79  extraPoint++;
80  }
81  }
82  return extraPoint;
83 }

Referenced by moab::Intx2MeshInPlane::computeIntersectionBetweenTgtAndSrc(), moab::Intx2MeshOnSphere::computeIntersectionBetweenTgtAndSrc(), and moab::IntxRllCssphere::computeIntersectionBetweenTgtAndSrc().

◆ cart_to_spherical()

IntxUtils::SphereCoords moab::IntxUtils::cart_to_spherical ( CartVect cart3d)
static

Definition at line 726 of file IntxUtils.cpp.

727 {
728  SphereCoords res;
729  res.R = cart3d.length();
730  if( res.R < 0 )
731  {
732  res.lon = res.lat = 0.;
733  return res;
734  }
735  res.lat = asin( cart3d[2] / res.R );
736  res.lon = atan2( cart3d[1], cart3d[0] );
737  if( res.lon < 0 ) res.lon += 2 * M_PI; // M_PI is defined in math.h? it seems to be true, although
738  // there are some defines it depends on :(
739  // #if defined __USE_BSD || defined __USE_XOPEN ???
740 
741  return res;
742 }

References moab::IntxUtils::SphereCoords::lat, moab::CartVect::length(), moab::IntxUtils::SphereCoords::lon, and moab::IntxUtils::SphereCoords::R.

Referenced by add_field_value(), IntxUtilsCSLAM::departure_point_case1(), departure_point_swirl(), departure_point_swirl_rot(), distance_on_great_circle(), set_density(), and IntxUtilsCSLAM::velocity_case1().

◆ decide_gnomonic_plane()

void moab::IntxUtils::decide_gnomonic_plane ( const CartVect pos,
int &  oPlane 
)
static

Definition at line 349 of file IntxUtils.cpp.

350 {
351  // decide plane, based on max x, y, z
352  if( fabs( pos[0] ) < fabs( pos[1] ) )
353  {
354  if( fabs( pos[2] ) < fabs( pos[1] ) )
355  {
356  // pos[1] is biggest
357  if( pos[1] > 0 )
358  plane = 2;
359  else
360  plane = 4;
361  }
362  else
363  {
364  // pos[2] is biggest
365  if( pos[2] < 0 )
366  plane = 5;
367  else
368  plane = 6;
369  }
370  }
371  else
372  {
373  if( fabs( pos[2] ) < fabs( pos[0] ) )
374  {
375  // pos[0] is the greatest
376  if( pos[0] > 0 )
377  plane = 1;
378  else
379  plane = 3;
380  }
381  else
382  {
383  // pos[2] is biggest
384  if( pos[2] < 0 )
385  plane = 5;
386  else
387  plane = 6;
388  }
389  }
390  return;
391 }

Referenced by moab::Intx2MeshOnSphere::computeIntersectionBetweenTgtAndSrc(), get_gnomonic_plane(), global_gnomonic_projection(), moab::Intx2MeshOnSphere::setup_tgt_cell(), moab::IntxRllCssphere::setup_tgt_cell(), transform_coordinates(), and moab::BoundBox::update_box_spherical_elem().

◆ deep_copy_set_with_quads()

ErrorCode moab::IntxUtils::deep_copy_set_with_quads ( Interface mb,
EntityHandle  source_set,
EntityHandle  dest_set 
)
static

Definition at line 1788 of file IntxUtils.cpp.

1789 {
1790  ReadUtilIface* read_iface;
1791  ErrorCode rval = mb->query_interface( read_iface );MB_CHK_ERR( rval );
1792  // create the handle tag for the corresponding element / vertex
1793 
1794  EntityHandle dum = 0;
1795  Tag corrTag = 0; // it will be created here
1796  rval = mb->tag_get_handle( CORRTAGNAME, 1, MB_TYPE_HANDLE, corrTag, MB_TAG_DENSE | MB_TAG_CREAT, &dum );MB_CHK_ERR( rval );
1797 
1798  // give the same global id to new verts and cells created in the lagr(departure) mesh
1799  Tag gid = mb->globalId_tag();
1800 
1801  Range quads;
1802  rval = mb->get_entities_by_type( source_set, MBQUAD, quads );MB_CHK_ERR( rval );
1803 
1804  Range connecVerts;
1805  rval = mb->get_connectivity( quads, connecVerts );MB_CHK_ERR( rval );
1806 
1807  std::map< EntityHandle, EntityHandle > newNodes;
1808 
1809  std::vector< double* > coords;
1810  EntityHandle start_vert, start_elem, *connect;
1811  int num_verts = connecVerts.size();
1812  rval = read_iface->get_node_coords( 3, num_verts, 0, start_vert, coords );
1813  if( MB_SUCCESS != rval ) return rval;
1814  // fill it up
1815  int i = 0;
1816  for( Range::iterator vit = connecVerts.begin(); vit != connecVerts.end(); ++vit, i++ )
1817  {
1818  EntityHandle oldV = *vit;
1819  CartVect posi;
1820  rval = mb->get_coords( &oldV, 1, &( posi[0] ) );MB_CHK_ERR( rval );
1821 
1822  int global_id;
1823  rval = mb->tag_get_data( gid, &oldV, 1, &global_id );MB_CHK_ERR( rval );
1824  EntityHandle new_vert = start_vert + i;
1825  // Cppcheck warning (false positive): variable coords is assigned a value that is never used
1826  coords[0][i] = posi[0];
1827  coords[1][i] = posi[1];
1828  coords[2][i] = posi[2];
1829 
1830  newNodes[oldV] = new_vert;
1831  // set also the correspondent tag :)
1832  rval = mb->tag_set_data( corrTag, &oldV, 1, &new_vert );MB_CHK_ERR( rval );
1833 
1834  // also the other side
1835  // need to check if we really need this; the new vertex will never need the old vertex
1836  // we have the global id which is the same
1837  rval = mb->tag_set_data( corrTag, &new_vert, 1, &oldV );MB_CHK_ERR( rval );
1838  // set the global id on the corresponding vertex the same as the initial vertex
1839  rval = mb->tag_set_data( gid, &new_vert, 1, &global_id );MB_CHK_ERR( rval );
1840  }
1841  // now create new quads in order (in a sequence)
1842 
1843  rval = read_iface->get_element_connect( quads.size(), 4, MBQUAD, 0, start_elem, connect );
1844  if( MB_SUCCESS != rval ) return rval;
1845  int ie = 0;
1846  for( Range::iterator it = quads.begin(); it != quads.end(); ++it, ie++ )
1847  {
1848  EntityHandle q = *it;
1849  int nnodes;
1850  const EntityHandle* conn;
1851  rval = mb->get_connectivity( q, conn, nnodes );MB_CHK_ERR( rval );
1852  int global_id;
1853  rval = mb->tag_get_data( gid, &q, 1, &global_id );MB_CHK_ERR( rval );
1854 
1855  for( int ii = 0; ii < nnodes; ii++ )
1856  {
1857  EntityHandle v1 = conn[ii];
1858  connect[4 * ie + ii] = newNodes[v1];
1859  }
1860  EntityHandle newElement = start_elem + ie;
1861 
1862  // set the corresponding tag; not sure we need this one, from old to new
1863  rval = mb->tag_set_data( corrTag, &q, 1, &newElement );MB_CHK_ERR( rval );
1864  rval = mb->tag_set_data( corrTag, &newElement, 1, &q );MB_CHK_ERR( rval );
1865 
1866  // set the global id
1867  rval = mb->tag_set_data( gid, &newElement, 1, &global_id );MB_CHK_ERR( rval );
1868 
1869  rval = mb->add_entities( dest_set, &newElement, 1 );MB_CHK_ERR( rval );
1870  }
1871 
1872  rval = read_iface->update_adjacencies( start_elem, quads.size(), 4, connect );MB_CHK_ERR( rval );
1873 
1874  return MB_SUCCESS;
1875 }

References moab::Range::begin(), CORRTAGNAME, moab::dum, moab::Range::end(), ErrorCode, moab::ReadUtilIface::get_element_connect(), moab::ReadUtilIface::get_node_coords(), mb, MB_CHK_ERR, MB_SUCCESS, MB_TAG_CREAT, MB_TAG_DENSE, MB_TYPE_HANDLE, MBQUAD, moab::Range::size(), and moab::ReadUtilIface::update_adjacencies().

◆ dist2()

static double moab::IntxUtils::dist2 ( double *  a,
double *  b 
)
inlinestatic

Definition at line 20 of file IntxUtils.hpp.

21  {
22  double abx = b[0] - a[0], aby = b[1] - a[1];
23  return sqrt( abx * abx + aby * aby );
24  }

Referenced by moab::Intx2MeshInPlane::findNodes(), moab::Intx2MeshOnSphere::findNodes(), moab::IntxRllCssphere::findNodes(), and SortAndRemoveDoubles2().

◆ distance_on_great_circle()

double moab::IntxUtils::distance_on_great_circle ( CartVect p1,
CartVect p2 
)
static

Definition at line 1075 of file IntxUtils.cpp.

1076 {
1077  SphereCoords sph1 = cart_to_spherical( p1 );
1078  SphereCoords sph2 = cart_to_spherical( p2 );
1079  // radius should be the same
1080  return sph1.R *
1081  acos( sin( sph1.lon ) * sin( sph2.lon ) + cos( sph1.lat ) * cos( sph2.lat ) * cos( sph2.lon - sph2.lon ) );
1082 }

References cart_to_spherical(), moab::IntxUtils::SphereCoords::lat, moab::IntxUtils::SphereCoords::lon, and moab::IntxUtils::SphereCoords::R.

◆ distance_on_sphere()

double moab::IntxUtils::distance_on_sphere ( double  la1,
double  te1,
double  la2,
double  te2 
)
static

Definition at line 1324 of file IntxUtils.cpp.

1325 {
1326  return acos( sin( te1 ) * sin( te2 ) + cos( te1 ) * cos( te2 ) * cos( la1 - la2 ) );
1327 }

Referenced by IntxUtilsCSLAM::quasi_smooth_field(), and IntxUtilsCSLAM::slotted_cylinder_field().

◆ EdgeIntersections2()

ErrorCode moab::IntxUtils::EdgeIntersections2 ( double *  blue,
int  nsBlue,
double *  red,
int  nsRed,
int *  markb,
int *  markr,
double *  points,
int &  nPoints 
)
static

Definition at line 179 of file IntxUtils.cpp.

187 {
188  /* EDGEINTERSECTIONS computes edge intersections of two elements
189  [P,n]=EdgeIntersections(X,Y) computes for the two given elements * red
190  and blue ( stored column wise )
191  (point coordinates are stored column-wise, in counter clock
192  order) the points P where their edges intersect. In addition,
193  in n the indices of which neighbors of red are also intersecting
194  with blue are given.
195  */
196 
197  // points is an array with enough slots (24 * 2 doubles)
198  nPoints = 0;
199  for( int i = 0; i < MAXEDGES; i++ )
200  {
201  markb[i] = markr[i] = 0;
202  }
203 
204  for( int i = 0; i < nsBlue; i++ )
205  {
206  for( int j = 0; j < nsRed; j++ )
207  {
208  double b[2];
209  double a[2][2]; // 2*2
210  int iPlus1 = ( i + 1 ) % nsBlue;
211  int jPlus1 = ( j + 1 ) % nsRed;
212  for( int k = 0; k < 2; k++ )
213  {
214  b[k] = red[2 * j + k] - blue[2 * i + k];
215  // row k of a: a(k, 0), a(k, 1)
216  a[k][0] = blue[2 * iPlus1 + k] - blue[2 * i + k];
217  a[k][1] = red[2 * j + k] - red[2 * jPlus1 + k];
218  }
219  double delta = a[0][0] * a[1][1] - a[0][1] * a[1][0];
220  if( fabs( delta ) > 1.e-14 ) // this is close to machine epsilon
221  {
222  // not parallel
223  double alfa = ( b[0] * a[1][1] - a[0][1] * b[1] ) / delta;
224  double beta = ( -b[0] * a[1][0] + b[1] * a[0][0] ) / delta;
225  if( 0 <= alfa && alfa <= 1. && 0 <= beta && beta <= 1. )
226  {
227  // the intersection is good
228  for( int k = 0; k < 2; k++ )
229  {
230  points[2 * nPoints + k] = blue[2 * i + k] + alfa * ( blue[2 * iPlus1 + k] - blue[2 * i + k] );
231  }
232  markb[i] = 1; // so neighbor number i of blue will be considered too.
233  markr[j] = 1; // this will be used in advancing red around blue quad
234  nPoints++;
235  }
236  }
237  // the case delta ~ 0. will be considered by the interior points logic
238  }
239  }
240  return MB_SUCCESS;
241 }

References MAXEDGES, and MB_SUCCESS.

Referenced by moab::Intx2MeshInPlane::computeIntersectionBetweenTgtAndSrc(), and moab::Intx2MeshOnSphere::computeIntersectionBetweenTgtAndSrc().

◆ EdgeIntxRllCs()

ErrorCode moab::IntxUtils::EdgeIntxRllCs ( double *  blue,
CartVect bluec,
int *  blueEdgeType,
int  nsBlue,
double *  red,
CartVect redc,
int  nsRed,
int *  markb,
int *  markr,
int  plane,
double  Radius,
double *  points,
int &  nPoints 
)
static

Definition at line 244 of file IntxUtils.cpp.

257 {
258  // if blue edge type is 1, intersect in 3d then project to 2d by gnomonic projection
259  // everything else the same (except if there are 2 points resulting, which is rare)
260  for( int i = 0; i < 4; i++ )
261  { // always at most 4 , so maybe don't bother
262  markb[i] = markr[i] = 0;
263  }
264 
265  for( int i = 0; i < nsBlue; i++ )
266  {
267  int iPlus1 = ( i + 1 ) % nsBlue;
268  if( blueEdgeType[i] == 0 ) // old style, just 2d
269  {
270  for( int j = 0; j < nsRed; j++ )
271  {
272  double b[2];
273  double a[2][2]; // 2*2
274 
275  int jPlus1 = ( j + 1 ) % nsRed;
276  for( int k = 0; k < 2; k++ )
277  {
278  b[k] = red[2 * j + k] - blue[2 * i + k];
279  // row k of a: a(k, 0), a(k, 1)
280  a[k][0] = blue[2 * iPlus1 + k] - blue[2 * i + k];
281  a[k][1] = red[2 * j + k] - red[2 * jPlus1 + k];
282  }
283  double delta = a[0][0] * a[1][1] - a[0][1] * a[1][0];
284  if( fabs( delta ) > 1.e-14 )
285  {
286  // not parallel
287  double alfa = ( b[0] * a[1][1] - a[0][1] * b[1] ) / delta;
288  double beta = ( -b[0] * a[1][0] + b[1] * a[0][0] ) / delta;
289  if( 0 <= alfa && alfa <= 1. && 0 <= beta && beta <= 1. )
290  {
291  // the intersection is good
292  for( int k = 0; k < 2; k++ )
293  {
294  points[2 * nPoints + k] =
295  blue[2 * i + k] + alfa * ( blue[2 * iPlus1 + k] - blue[2 * i + k] );
296  }
297  markb[i] = 1; // so neighbor number i of blue will be considered too.
298  markr[j] = 1; // this will be used in advancing red around blue quad
299  nPoints++;
300  }
301  } // if the edges are too "parallel", skip them
302  }
303  }
304  else // edge type is 1, so use 3d intersection
305  {
306  CartVect& C = bluec[i];
307  CartVect& D = bluec[iPlus1];
308  for( int j = 0; j < nsRed; j++ )
309  {
310  int jPlus1 = ( j + 1 ) % nsRed; // nsRed is just 4, forget about it, usually
311  CartVect& A = redc[j];
312  CartVect& B = redc[jPlus1];
313  int np = 0;
314  double E[9];
315  intersect_great_circle_arc_with_clat_arc( A.array(), B.array(), C.array(), D.array(), R, E, np );
316  if( np == 0 ) continue;
317  if( np >= 2 )
318  {
319  std::cout << "intersection with 2 points :" << A << B << C << D << "\n";
320  }
321  for( int k = 0; k < np; k++ )
322  {
323  gnomonic_projection( CartVect( E + k * 3 ), R, plane, points[2 * nPoints],
324  points[2 * nPoints + 1] );
325  nPoints++;
326  }
327  markb[i] = 1; // so neighbor number i of blue will be considered too.
328  markr[j] = 1; // this will be used in advancing red around blue quad
329  }
330  }
331  }
332  return MB_SUCCESS;
333 }

References moab::CartVect::array(), moab::E, gnomonic_projection(), intersect_great_circle_arc_with_clat_arc(), MB_SUCCESS, and moab::R.

Referenced by moab::IntxRllCssphere::computeIntersectionBetweenTgtAndSrc().

◆ enforce_convexity()

ErrorCode moab::IntxUtils::enforce_convexity ( Interface mb,
EntityHandle  set,
int  rank = 0 
)
static

Definition at line 1087 of file IntxUtils.cpp.

1088 {
1089  // look at each polygon; compute all angles; if one is reflex, break that angle with
1090  // the next triangle; put the 2 new polys in the set;
1091  // still look at the next poly
1092  // replace it with 2 triangles, and remove from set;
1093  // it should work for all polygons / tested first for case 1, with dt 0.5 (too much deformation)
1094  // get all entities of dimension 2
1095  // then get the connectivity, etc
1096 
1097  Range inputRange;
1098  ErrorCode rval = mb->get_entities_by_dimension( lset, 2, inputRange );MB_CHK_ERR( rval );
1099 
1100  Tag corrTag = 0;
1101  EntityHandle dumH = 0;
1102  rval = mb->tag_get_handle( CORRTAGNAME, 1, MB_TYPE_HANDLE, corrTag, MB_TAG_DENSE, &dumH );
1103  if( rval == MB_TAG_NOT_FOUND ) corrTag = 0;
1104 
1105  Tag gidTag;
1106  rval = mb->tag_get_handle( "GLOBAL_ID", 1, MB_TYPE_INTEGER, gidTag, MB_TAG_DENSE );MB_CHK_ERR( rval );
1107 
1108  std::vector< double > coords;
1109  coords.resize( 3 * MAXEDGES ); // at most 10 vertices per polygon
1110  // we should create a queue with new polygons that need processing for reflex angles
1111  // (obtuse)
1112  std::queue< EntityHandle > newPolys;
1113  int brokenPolys = 0;
1114  Range::iterator eit = inputRange.begin();
1115  while( eit != inputRange.end() || !newPolys.empty() )
1116  {
1117  EntityHandle eh;
1118  if( eit != inputRange.end() )
1119  {
1120  eh = *eit;
1121  ++eit;
1122  }
1123  else
1124  {
1125  eh = newPolys.front();
1126  newPolys.pop();
1127  }
1128  // get the nodes, then the coordinates
1129  const EntityHandle* verts;
1130  int num_nodes;
1131  rval = mb->get_connectivity( eh, verts, num_nodes );MB_CHK_ERR( rval );
1132  int nsides = num_nodes;
1133  // account for possible padded polygons
1134  while( verts[nsides - 2] == verts[nsides - 1] && nsides > 3 )
1135  nsides--;
1136  EntityHandle corrHandle = 0;
1137  if( corrTag )
1138  {
1139  rval = mb->tag_get_data( corrTag, &eh, 1, &corrHandle );MB_CHK_ERR( rval );
1140  }
1141  int gid = 0;
1142  rval = mb->tag_get_data( gidTag, &eh, 1, &gid );MB_CHK_ERR( rval );
1143  coords.resize( 3 * nsides );
1144  if( nsides < 4 ) continue; // if already triangles, don't bother
1145  // get coordinates
1146  rval = mb->get_coords( verts, nsides, &coords[0] );MB_CHK_ERR( rval );
1147  // compute each angle
1148  bool alreadyBroken = false;
1149 
1150  for( int i = 0; i < nsides; i++ )
1151  {
1152  double* A = &coords[3 * i];
1153  double* B = &coords[3 * ( ( i + 1 ) % nsides )];
1154  double* C = &coords[3 * ( ( i + 2 ) % nsides )];
1155  double angle = IntxUtils::oriented_spherical_angle( A, B, C );
1156  if( angle - M_PI > 0. ) // even almost reflex is bad; break it!
1157  {
1158  if( alreadyBroken )
1159  {
1160  mb->list_entities( &eh, 1 );
1161  mb->list_entities( verts, nsides );
1162  double* D = &coords[3 * ( ( i + 3 ) % nsides )];
1163  std::cout << "ABC: " << angle << " \n";
1164  std::cout << "BCD: " << IntxUtils::oriented_spherical_angle( B, C, D ) << " \n";
1165  std::cout << "CDA: " << IntxUtils::oriented_spherical_angle( C, D, A ) << " \n";
1166  std::cout << "DAB: " << IntxUtils::oriented_spherical_angle( D, A, B ) << " \n";
1167  std::cout << " this cell has at least 2 angles > 180, it has serious issues\n";
1168 
1169  return MB_FAILURE;
1170  }
1171  // the bad angle is at i+1;
1172  // create 1 triangle and one polygon; add the polygon to the input range, so
1173  // it will be processed too
1174  // also, add both to the set :) and remove the original polygon from the set
1175  // break the next triangle, even though not optimal
1176  // so create the triangle i+1, i+2, i+3; remove i+2 from original list
1177  // even though not optimal in general, it is good enough.
1178  EntityHandle conn3[3] = { verts[( i + 1 ) % nsides], verts[( i + 2 ) % nsides],
1179  verts[( i + 3 ) % nsides] };
1180  // create a polygon with num_nodes-1 vertices, and connectivity
1181  // verts[i+1], verts[i+3], (all except i+2)
1182  std::vector< EntityHandle > conn( nsides - 1 );
1183  for( int j = 1; j < nsides; j++ )
1184  {
1185  conn[j - 1] = verts[( i + j + 2 ) % nsides];
1186  }
1187  EntityHandle newElement;
1188  rval = mb->create_element( MBTRI, conn3, 3, newElement );MB_CHK_ERR( rval );
1189 
1190  rval = mb->add_entities( lset, &newElement, 1 );MB_CHK_ERR( rval );
1191  if( corrTag )
1192  {
1193  rval = mb->tag_set_data( corrTag, &newElement, 1, &corrHandle );MB_CHK_ERR( rval );
1194  }
1195  rval = mb->tag_set_data( gidTag, &newElement, 1, &gid );MB_CHK_ERR( rval );
1196  if( nsides == 4 )
1197  {
1198  // create another triangle
1199  rval = mb->create_element( MBTRI, &conn[0], 3, newElement );MB_CHK_ERR( rval );
1200  }
1201  else
1202  {
1203  // create another polygon, and add it to the inputRange
1204  rval = mb->create_element( MBPOLYGON, &conn[0], nsides - 1, newElement );MB_CHK_ERR( rval );
1205  newPolys.push( newElement ); // because it has less number of edges, the
1206  // reverse should work to find it.
1207  }
1208  rval = mb->add_entities( lset, &newElement, 1 );MB_CHK_ERR( rval );
1209  if( corrTag )
1210  {
1211  rval = mb->tag_set_data( corrTag, &newElement, 1, &corrHandle );MB_CHK_ERR( rval );
1212  }
1213  rval = mb->tag_set_data( gidTag, &newElement, 1, &gid );MB_CHK_ERR( rval );
1214  rval = mb->remove_entities( lset, &eh, 1 );MB_CHK_ERR( rval );
1215  brokenPolys++;
1216  alreadyBroken = true; // get out of the loop, element is broken
1217  }
1218  }
1219  }
1220  if( brokenPolys > 0 )
1221  {
1222  std::cout << "on local process " << my_rank << ", " << brokenPolys
1223  << " concave polygons were decomposed in convex ones \n";
1224 #ifdef VERBOSE
1225  std::stringstream fff;
1226  fff << "file_set" << mb->id_from_handle( lset ) << "rk_" << my_rank << ".h5m";
1227  rval = mb->write_file( fff.str().c_str(), 0, 0, &lset, 1 );MB_CHK_ERR( rval );
1228  std::cout << "wrote new file set: " << fff.str() << "\n";
1229 #endif
1230  }
1231  return MB_SUCCESS;
1232 }

References moab::angle(), moab::Range::begin(), CORRTAGNAME, moab::Range::end(), ErrorCode, MAXEDGES, mb, MB_CHK_ERR, MB_SUCCESS, MB_TAG_DENSE, MB_TAG_NOT_FOUND, MB_TYPE_HANDLE, MB_TYPE_INTEGER, MBPOLYGON, MBTRI, and oriented_spherical_angle().

Referenced by main(), and update_tracer().

◆ fix_degenerate_quads()

ErrorCode moab::IntxUtils::fix_degenerate_quads ( Interface mb,
EntityHandle  set 
)
static

Definition at line 1236 of file IntxUtils.cpp.

1237 {
1238  Range quads;
1239  ErrorCode rval = mb->get_entities_by_type( set, MBQUAD, quads );MB_CHK_ERR( rval );
1240  Tag gid;
1241  gid = mb->globalId_tag();
1242  for( Range::iterator qit = quads.begin(); qit != quads.end(); ++qit )
1243  {
1244  EntityHandle quad = *qit;
1245  const EntityHandle* conn4 = NULL;
1246  int num_nodes = 0;
1247  rval = mb->get_connectivity( quad, conn4, num_nodes );MB_CHK_ERR( rval );
1248  for( int i = 0; i < num_nodes; i++ )
1249  {
1250  int next_node_index = ( i + 1 ) % num_nodes;
1251  if( conn4[i] == conn4[next_node_index] )
1252  {
1253  // form a triangle and delete the quad
1254  // first get the global id, to set it on triangle later
1255  int global_id = 0;
1256  rval = mb->tag_get_data( gid, &quad, 1, &global_id );MB_CHK_ERR( rval );
1257  int i2 = ( i + 2 ) % num_nodes;
1258  int i3 = ( i + 3 ) % num_nodes;
1259  EntityHandle conn3[3] = { conn4[i], conn4[i2], conn4[i3] };
1260  EntityHandle tri;
1261  rval = mb->create_element( MBTRI, conn3, 3, tri );MB_CHK_ERR( rval );
1262  mb->add_entities( set, &tri, 1 );
1263  mb->remove_entities( set, &quad, 1 );
1264  mb->delete_entities( &quad, 1 );
1265  rval = mb->tag_set_data( gid, &tri, 1, &global_id );MB_CHK_ERR( rval );
1266  }
1267  }
1268  }
1269  return MB_SUCCESS;
1270 }

References moab::Range::begin(), moab::Range::end(), ErrorCode, mb, MB_CHK_ERR, MB_SUCCESS, MBQUAD, and MBTRI.

Referenced by moab::TempestRemapper::ComputeOverlapMesh(), and main().

◆ global_gnomonic_projection()

ErrorCode moab::IntxUtils::global_gnomonic_projection ( Interface mb,
EntityHandle  inSet,
double  R,
bool  centers_only,
EntityHandle outSet 
)
static

Definition at line 549 of file IntxUtils.cpp.

554 {
555  std::string parTagName( "PARALLEL_PARTITION" );
556  Tag part_tag;
557  Range partSets;
558  ErrorCode rval = mb->tag_get_handle( parTagName.c_str(), part_tag );
559  if( MB_SUCCESS == rval && part_tag != 0 )
560  {
561  rval = mb->get_entities_by_type_and_tag( inSet, MBENTITYSET, &part_tag, NULL, 1, partSets, Interface::UNION );MB_CHK_ERR( rval );
562  }
563  rval = ScaleToRadius( mb, inSet, 1.0 );MB_CHK_ERR( rval );
564  // Get all entities of dimension 2
565  Range inputRange; // get
566  rval = mb->get_entities_by_dimension( inSet, 1, inputRange );MB_CHK_ERR( rval );
567  rval = mb->get_entities_by_dimension( inSet, 2, inputRange );MB_CHK_ERR( rval );
568 
569  std::map< EntityHandle, int > partsAssign;
570  std::map< int, EntityHandle > newPartSets;
571  if( !partSets.empty() )
572  {
573  // get all cells, and assign parts
574  for( Range::iterator setIt = partSets.begin(); setIt != partSets.end(); ++setIt )
575  {
576  EntityHandle pSet = *setIt;
577  Range ents;
578  rval = mb->get_entities_by_handle( pSet, ents );MB_CHK_ERR( rval );
579  int val;
580  rval = mb->tag_get_data( part_tag, &pSet, 1, &val );MB_CHK_ERR( rval );
581  // create a new set with the same part id tag, in the outSet
582  EntityHandle newPartSet;
583  rval = mb->create_meshset( MESHSET_SET, newPartSet );MB_CHK_ERR( rval );
584  rval = mb->tag_set_data( part_tag, &newPartSet, 1, &val );MB_CHK_ERR( rval );
585  newPartSets[val] = newPartSet;
586  rval = mb->add_entities( outSet, &newPartSet, 1 );MB_CHK_ERR( rval );
587  for( Range::iterator it = ents.begin(); it != ents.end(); ++it )
588  {
589  partsAssign[*it] = val;
590  }
591  }
592  }
593 
594  if( centers_only )
595  {
596  for( Range::iterator it = inputRange.begin(); it != inputRange.end(); ++it )
597  {
598  CartVect center;
599  EntityHandle cell = *it;
600  rval = mb->get_coords( &cell, 1, center.array() );MB_CHK_ERR( rval );
601  int plane;
602  decide_gnomonic_plane( center, plane );
603  double c[3];
604  c[2] = 0.;
605  gnomonic_projection( center, R, plane, c[0], c[1] );
606 
607  gnomonic_unroll( c[0], c[1], R, plane );
608 
610  rval = mb->create_vertex( c, vertex );MB_CHK_ERR( rval );
611  rval = mb->add_entities( outSet, &vertex, 1 );MB_CHK_ERR( rval );
612  }
613  }
614  else
615  {
616  // distribute the cells to 6 planes, based on the center
617  Range subranges[6];
618  for( Range::iterator it = inputRange.begin(); it != inputRange.end(); ++it )
619  {
620  CartVect center;
621  EntityHandle cell = *it;
622  rval = mb->get_coords( &cell, 1, center.array() );MB_CHK_ERR( rval );
623  int plane;
624  decide_gnomonic_plane( center, plane );
625  subranges[plane - 1].insert( cell );
626  }
627  for( int i = 1; i <= 6; i++ )
628  {
629  Range verts;
630  rval = mb->get_connectivity( subranges[i - 1], verts );MB_CHK_ERR( rval );
631  std::map< EntityHandle, EntityHandle > corr;
632  for( Range::iterator vt = verts.begin(); vt != verts.end(); ++vt )
633  {
634  CartVect vect;
635  EntityHandle v = *vt;
636  rval = mb->get_coords( &v, 1, vect.array() );MB_CHK_ERR( rval );
637  double c[3];
638  c[2] = 0.;
639  gnomonic_projection( vect, R, i, c[0], c[1] );
640  gnomonic_unroll( c[0], c[1], R, i );
642  rval = mb->create_vertex( c, vertex );MB_CHK_ERR( rval );
643  corr[v] = vertex; // for new connectivity
644  }
645  EntityHandle new_conn[20]; // max edges in 2d ?
646  for( Range::iterator eit = subranges[i - 1].begin(); eit != subranges[i - 1].end(); ++eit )
647  {
648  EntityHandle eh = *eit;
649  const EntityHandle* conn = NULL;
650  int num_nodes;
651  rval = mb->get_connectivity( eh, conn, num_nodes );MB_CHK_ERR( rval );
652  // build a new vertex array
653  for( int j = 0; j < num_nodes; j++ )
654  new_conn[j] = corr[conn[j]];
655  EntityType type = mb->type_from_handle( eh );
656  EntityHandle newCell;
657  rval = mb->create_element( type, new_conn, num_nodes, newCell );MB_CHK_ERR( rval );
658  rval = mb->add_entities( outSet, &newCell, 1 );MB_CHK_ERR( rval );
659  std::map< EntityHandle, int >::iterator mit = partsAssign.find( eh );
660  if( mit != partsAssign.end() )
661  {
662  int val = mit->second;
663  rval = mb->add_entities( newPartSets[val], &newCell, 1 );MB_CHK_ERR( rval );
664  }
665  }
666  }
667  }
668 
669  return MB_SUCCESS;
670 }

References moab::CartVect::array(), moab::Range::begin(), center(), decide_gnomonic_plane(), moab::Range::empty(), moab::Range::end(), ErrorCode, gnomonic_projection(), gnomonic_unroll(), moab::Range::insert(), mb, MB_CHK_ERR, MB_SUCCESS, MBENTITYSET, MESHSET_SET, moab::R, ScaleToRadius(), and moab::Interface::UNION.

◆ gnomonic_projection()

ErrorCode moab::IntxUtils::gnomonic_projection ( const CartVect pos,
double  R,
int  plane,
double &  c1,
double &  c2 
)
static

Definition at line 394 of file IntxUtils.cpp.

395 {
396  double alfa = 1.; // the new point will be on line alfa*pos
397 
398  switch( plane )
399  {
400  case 1: {
401  // the plane with x = R; x>y, x>z
402  // c1->y, c2->z
403  alfa = R / pos[0];
404  c1 = alfa * pos[1];
405  c2 = alfa * pos[2];
406  break;
407  }
408  case 2: {
409  // y = R -> zx
410  alfa = R / pos[1];
411  c1 = alfa * pos[2];
412  c2 = alfa * pos[0];
413  break;
414  }
415  case 3: {
416  // x=-R, -> yz
417  alfa = -R / pos[0];
418  c1 = -alfa * pos[1]; // the sign is to preserve orientation
419  c2 = alfa * pos[2];
420  break;
421  }
422  case 4: {
423  // y = -R
424  alfa = -R / pos[1];
425  c1 = -alfa * pos[2]; // the sign is to preserve orientation
426  c2 = alfa * pos[0];
427  break;
428  }
429  case 5: {
430  // z = -R
431  alfa = -R / pos[2];
432  c1 = -alfa * pos[0]; // the sign is to preserve orientation
433  c2 = alfa * pos[1];
434  break;
435  }
436  case 6: {
437  alfa = R / pos[2];
438  c1 = alfa * pos[0];
439  c2 = alfa * pos[1];
440  break;
441  }
442  default:
443  return MB_FAILURE; // error
444  }
445 
446  return MB_SUCCESS; // no error
447 }

References MB_SUCCESS, and moab::R.

Referenced by moab::Intx2MeshOnSphere::computeIntersectionBetweenTgtAndSrc(), moab::IntxRllCssphere::computeIntersectionBetweenTgtAndSrc(), EdgeIntxRllCs(), get_barycenters(), get_intersection_weights(), get_linear_reconstruction(), global_gnomonic_projection(), moab::Intx2MeshOnSphere::setup_tgt_cell(), moab::IntxRllCssphere::setup_tgt_cell(), test_linear_reconstruction(), transform_coordinates(), and moab::BoundBox::update_box_spherical_elem().

◆ gnomonic_unroll()

void moab::IntxUtils::gnomonic_unroll ( double &  c1,
double &  c2,
double  R,
int  plane 
)
static

Definition at line 512 of file IntxUtils.cpp.

513 {
514  double tmp;
515  switch( plane )
516  {
517  case 1:
518  break; // nothing
519  case 2: // rotate + 90
520  tmp = c1;
521  c1 = -c2;
522  c2 = tmp;
523  c1 = c1 + 2 * R;
524  break;
525  case 3:
526  c1 = c1 + 4 * R;
527  break;
528  case 4: // rotate with -90 x-> -y; y -> x
529 
530  tmp = c1;
531  c1 = c2;
532  c2 = -tmp;
533  c1 = c1 - 2 * R;
534  break;
535  case 5: // South Pole
536  // rotate 180 then move to (-2, -2)
537  c1 = -c1 - 2. * R;
538  c2 = -c2 - 2. * R;
539  break;
540  ;
541  case 6: // North Pole
542  c1 = c1 - 2. * R;
543  c2 = c2 + 2. * R;
544  break;
545  }
546  return;
547 }

References moab::R.

Referenced by global_gnomonic_projection(), and transform_coordinates().

◆ intersect_great_circle_arc_with_clat_arc()

ErrorCode moab::IntxUtils::intersect_great_circle_arc_with_clat_arc ( double *  A,
double *  B,
double *  C,
double *  D,
double  R,
double *  E,
int &  np 
)
static

Definition at line 1420 of file IntxUtils.cpp.

1427 {
1428  const double distTol = R * 1.e-6;
1429  const double Tolerance = R * R * 1.e-12; // radius should be 1, usually
1430  np = 0; // number of points in intersection
1431  CartVect a( A ), b( B ), c( C ), d( D );
1432  // check input first
1433  double R2 = R * R;
1434  if( fabs( a.length_squared() - R2 ) + fabs( b.length_squared() - R2 ) + fabs( c.length_squared() - R2 ) +
1435  fabs( d.length_squared() - R2 ) >
1436  10 * Tolerance )
1437  return MB_FAILURE;
1438 
1439  if( ( a - b ).length_squared() < Tolerance ) return MB_FAILURE;
1440  if( ( c - d ).length_squared() < Tolerance ) // edges are too short
1441  return MB_FAILURE;
1442 
1443  // CD is the const latitude arc
1444  if( fabs( C[2] - D[2] ) > distTol ) // cd is not on the same z (constant latitude)
1445  return MB_FAILURE;
1446 
1447  if( fabs( R - C[2] ) < distTol || fabs( R + C[2] ) < distTol ) return MB_FAILURE; // too close to the poles
1448 
1449  // find the points on the circle P(teta) = (r*sin(teta), r*cos(teta), C[2]) that are on the
1450  // great circle arc AB normal to the AB circle:
1451  CartVect n1 = a * b; // the normal to the great circle arc (circle)
1452  // solve the system of equations:
1453  /*
1454  * n1%(x, y, z) = 0 // on the great circle
1455  * z = C[2];
1456  * x^2+y^2+z^2 = R^2
1457  */
1458  double z = C[2];
1459  if( fabs( n1[0] ) + fabs( n1[1] ) < 2 * Tolerance )
1460  {
1461  // it is the Equator; check if the const lat edge is Equator too
1462  if( fabs( C[2] ) > distTol )
1463  {
1464  return MB_FAILURE; // no intx, too far from Eq
1465  }
1466  else
1467  {
1468  // all points are on the equator
1469  //
1470  CartVect cd = c * d;
1471  // by convention, c<d, positive is from c to d
1472  // is a or b between c , d?
1473  CartVect ca = c * a;
1474  CartVect ad = a * d;
1475  CartVect cb = c * b;
1476  CartVect bd = b * d;
1477  bool agtc = ( ca % cd >= -Tolerance ); // a>c?
1478  bool dgta = ( ad % cd >= -Tolerance ); // d>a?
1479  bool bgtc = ( cb % cd >= -Tolerance ); // b>c?
1480  bool dgtb = ( bd % cd >= -Tolerance ); // d>b?
1481  if( agtc )
1482  {
1483  if( dgta )
1484  {
1485  // a is for sure a point
1486  E[0] = a[0];
1487  E[1] = a[1];
1488  E[2] = a[2];
1489  np++;
1490  if( bgtc )
1491  {
1492  if( dgtb )
1493  {
1494  // b is also in between c and d
1495  E[3] = b[0];
1496  E[4] = b[1];
1497  E[5] = b[2];
1498  np++;
1499  }
1500  else
1501  {
1502  // then order is c a d b, intx is ad
1503  E[3] = d[0];
1504  E[4] = d[1];
1505  E[5] = d[2];
1506  np++;
1507  }
1508  }
1509  else
1510  {
1511  // b is less than c, so b c a d, intx is ac
1512  E[3] = c[0];
1513  E[4] = c[1];
1514  E[5] = c[2];
1515  np++; // what if E[0] is E[3]?
1516  }
1517  }
1518  else // c < d < a
1519  {
1520  if( dgtb ) // d is for sure in
1521  {
1522  E[0] = d[0];
1523  E[1] = d[1];
1524  E[2] = d[2];
1525  np++;
1526  if( bgtc ) // c<b<d<a
1527  {
1528  // another point is b
1529  E[3] = b[0];
1530  E[4] = b[1];
1531  E[5] = b[2];
1532  np++;
1533  }
1534  else // b<c<d<a
1535  {
1536  // another point is c
1537  E[3] = c[0];
1538  E[4] = c[1];
1539  E[5] = c[2];
1540  np++;
1541  }
1542  }
1543  else
1544  {
1545  // nothing, order is c, d < a, b
1546  }
1547  }
1548  }
1549  else // a < c < d
1550  {
1551  if( bgtc )
1552  {
1553  // c is for sure in
1554  E[0] = c[0];
1555  E[1] = c[1];
1556  E[2] = c[2];
1557  np++;
1558  if( dgtb )
1559  {
1560  // a < c < b < d; second point is b
1561  E[3] = b[0];
1562  E[4] = b[1];
1563  E[5] = b[2];
1564  np++;
1565  }
1566  else
1567  {
1568  // a < c < d < b; second point is d
1569  E[3] = d[0];
1570  E[4] = d[1];
1571  E[5] = d[2];
1572  np++;
1573  }
1574  }
1575  else // a, b < c < d
1576  {
1577  // nothing
1578  }
1579  }
1580  }
1581  // for the 2 points selected, see if it is only one?
1582  // no problem, maybe it will be collapsed later anyway
1583  if( np > 0 ) return MB_SUCCESS;
1584  return MB_FAILURE; // no intersection
1585  }
1586  {
1587  if( fabs( n1[0] ) <= fabs( n1[1] ) )
1588  {
1589  // resolve eq in x: n0 * x + n1 * y +n2*z = 0; y = -n2/n1*z -n0/n1*x
1590  // (u+v*x)^2+x^2=R2-z^2
1591  // (v^2+1)*x^2 + 2*u*v *x + u^2+z^2-R^2 = 0
1592  // delta = 4*u^2*v^2 - 4*(v^2-1)(u^2+z^2-R^2)
1593  // x1,2 =
1594  double u = -n1[2] / n1[1] * z, v = -n1[0] / n1[1];
1595  double a1 = v * v + 1, b1 = 2 * u * v, c1 = u * u + z * z - R2;
1596  double delta = b1 * b1 - 4 * a1 * c1;
1597  if( delta < -Tolerance ) return MB_FAILURE; // no intersection
1598  if( delta > Tolerance ) // 2 solutions possible
1599  {
1600  double x1 = ( -b1 + sqrt( delta ) ) / 2 / a1;
1601  double x2 = ( -b1 - sqrt( delta ) ) / 2 / a1;
1602  double y1 = u + v * x1;
1603  double y2 = u + v * x2;
1604  if( verify( a, b, c, d, x1, y1, z ) )
1605  {
1606  E[0] = x1;
1607  E[1] = y1;
1608  E[2] = z;
1609  np++;
1610  }
1611  if( verify( a, b, c, d, x2, y2, z ) )
1612  {
1613  E[3 * np + 0] = x2;
1614  E[3 * np + 1] = y2;
1615  E[3 * np + 2] = z;
1616  np++;
1617  }
1618  }
1619  else
1620  {
1621  // one solution
1622  double x1 = -b1 / 2 / a1;
1623  double y1 = u + v * x1;
1624  if( verify( a, b, c, d, x1, y1, z ) )
1625  {
1626  E[0] = x1;
1627  E[1] = y1;
1628  E[2] = z;
1629  np++;
1630  }
1631  }
1632  }
1633  else
1634  {
1635  // resolve eq in y, reverse
1636  // n0 * x + n1 * y +n2*z = 0; x = -n2/n0*z -n1/n0*y = u+v*y
1637  // (u+v*y)^2+y^2 -R2+z^2 =0
1638  // (v^2+1)*y^2 + 2*u*v *y + u^2+z^2-R^2 = 0
1639  //
1640  // x1,2 =
1641  double u = -n1[2] / n1[0] * z, v = -n1[1] / n1[0];
1642  double a1 = v * v + 1, b1 = 2 * u * v, c1 = u * u + z * z - R2;
1643  double delta = b1 * b1 - 4 * a1 * c1;
1644  if( delta < -Tolerance ) return MB_FAILURE; // no intersection
1645  if( delta > Tolerance ) // 2 solutions possible
1646  {
1647  double y1 = ( -b1 + sqrt( delta ) ) / 2 / a1;
1648  double y2 = ( -b1 - sqrt( delta ) ) / 2 / a1;
1649  double x1 = u + v * y1;
1650  double x2 = u + v * y2;
1651  if( verify( a, b, c, d, x1, y1, z ) )
1652  {
1653  E[0] = x1;
1654  E[1] = y1;
1655  E[2] = z;
1656  np++;
1657  }
1658  if( verify( a, b, c, d, x2, y2, z ) )
1659  {
1660  E[3 * np + 0] = x2;
1661  E[3 * np + 1] = y2;
1662  E[3 * np + 2] = z;
1663  np++;
1664  }
1665  }
1666  else
1667  {
1668  // one solution
1669  double y1 = -b1 / 2 / a1;
1670  double x1 = u + v * y1;
1671  if( verify( a, b, c, d, x1, y1, z ) )
1672  {
1673  E[0] = x1;
1674  E[1] = y1;
1675  E[2] = z;
1676  np++;
1677  }
1678  }
1679  }
1680  }
1681 
1682  if( np <= 0 ) return MB_FAILURE;
1683  return MB_SUCCESS;
1684 }

References moab::E, moab::CartVect::length_squared(), length_squared(), MB_SUCCESS, moab::R, and moab::verify().

Referenced by EdgeIntxRllCs().

◆ intersect_great_circle_arcs()

ErrorCode moab::IntxUtils::intersect_great_circle_arcs ( double *  A,
double *  B,
double *  C,
double *  D,
double  R,
double *  E 
)
static

Definition at line 1333 of file IntxUtils.cpp.

1334 {
1335  // first verify A, B, C, D are on the same sphere
1336  double R2 = R * R;
1337  const double Tolerance = 1.e-12 * R2;
1338 
1339  CartVect a( A ), b( B ), c( C ), d( D );
1340 
1341  if( fabs( a.length_squared() - R2 ) + fabs( b.length_squared() - R2 ) + fabs( c.length_squared() - R2 ) +
1342  fabs( d.length_squared() - R2 ) >
1343  10 * Tolerance )
1344  return MB_FAILURE;
1345 
1346  CartVect n1 = a * b;
1347  if( n1.length_squared() < Tolerance ) return MB_FAILURE;
1348 
1349  CartVect n2 = c * d;
1350  if( n2.length_squared() < Tolerance ) return MB_FAILURE;
1351  CartVect n3 = n1 * n2;
1352  n3.normalize();
1353 
1354  n3 = R * n3;
1355  // the intersection is either n3 or -n3
1356  CartVect n4 = a * n3, n5 = n3 * b;
1357  if( n1 % n4 >= -Tolerance && n1 % n5 >= -Tolerance )
1358  {
1359  // n3 is good for ab, see if it is good for cd
1360  n4 = c * n3;
1361  n5 = n3 * d;
1362  if( n2 % n4 >= -Tolerance && n2 % n5 >= -Tolerance )
1363  {
1364  E[0] = n3[0];
1365  E[1] = n3[1];
1366  E[2] = n3[2];
1367  }
1368  else
1369  return MB_FAILURE;
1370  }
1371  else
1372  {
1373  // try -n3
1374  n3 = -n3;
1375  n4 = a * n3, n5 = n3 * b;
1376  if( n1 % n4 >= -Tolerance && n1 % n5 >= -Tolerance )
1377  {
1378  // n3 is good for ab, see if it is good for cd
1379  n4 = c * n3;
1380  n5 = n3 * d;
1381  if( n2 % n4 >= -Tolerance && n2 % n5 >= -Tolerance )
1382  {
1383  E[0] = n3[0];
1384  E[1] = n3[1];
1385  E[2] = n3[2];
1386  }
1387  else
1388  return MB_FAILURE;
1389  }
1390  else
1391  return MB_FAILURE;
1392  }
1393 
1394  return MB_SUCCESS;
1395 }

References moab::E, moab::CartVect::length_squared(), MB_SUCCESS, moab::CartVect::normalize(), and moab::R.

◆ oriented_spherical_angle()

double moab::IntxUtils::oriented_spherical_angle ( double *  A,
double *  B,
double *  C 
)
static

Definition at line 814 of file IntxUtils.cpp.

815 {
816  // assume the same radius, sphere at origin
817  CartVect a( A ), b( B ), c( C );
818  CartVect normalOAB = a * b;
819  CartVect normalOCB = c * b;
820  CartVect orient = ( c - b ) * ( a - b );
821  double ang = angle( normalOAB, normalOCB ); // this is between 0 and M_PI
822  if( ang != ang )
823  {
824  // signal of a nan
825  std::cout << a << " " << b << " " << c << "\n";
826  std::cout << ang << "\n";
827  }
828  if( orient % b < 0 ) return ( 2 * M_PI - ang ); // the other angle, supplement
829 
830  return ang;
831 }

References moab::angle().

Referenced by moab::IntxAreaUtils::area_spherical_polygon_girard(), and enforce_convexity().

◆ remove_duplicate_vertices()

ErrorCode moab::IntxUtils::remove_duplicate_vertices ( Interface mb,
EntityHandle  file_set,
double  merge_tol,
std::vector< Tag > &  tagList 
)
static

Definition at line 1877 of file IntxUtils.cpp.

1881 {
1882  Range verts;
1883  ErrorCode rval = mb->get_entities_by_dimension( file_set, 0, verts );MB_CHK_ERR( rval );
1884  rval = mb->remove_entities( file_set, verts );MB_CHK_ERR( rval );
1885 
1886  MergeMesh mm( mb );
1887 
1888  // remove the vertices from the set, before merging
1889 
1890  rval = mm.merge_all( file_set, merge_tol );MB_CHK_ERR( rval );
1891 
1892  // now correct vertices that are repeated in polygons
1893  rval = remove_padded_vertices( mb, file_set, tagList );
1894  return MB_SUCCESS;
1895 }

References ErrorCode, mb, MB_CHK_ERR, MB_SUCCESS, moab::MergeMesh::merge_all(), and remove_padded_vertices().

◆ remove_padded_vertices()

ErrorCode moab::IntxUtils::remove_padded_vertices ( Interface mb,
EntityHandle  file_set,
std::vector< Tag > &  tagList 
)
static

Definition at line 1897 of file IntxUtils.cpp.

1898 {
1899 
1900  // now correct vertices that are repeated in polygons
1901  Range cells;
1902  ErrorCode rval = mb->get_entities_by_dimension( file_set, 2, cells );MB_CHK_ERR( rval );
1903 
1904  Range verts;
1905  rval = mb->get_connectivity( cells, verts );MB_CHK_ERR( rval );
1906 
1907  Range modifiedCells; // will be deleted at the end; keep the gid
1908  Range newCells;
1909 
1910  for( Range::iterator cit = cells.begin(); cit != cells.end(); ++cit )
1911  {
1912  EntityHandle cell = *cit;
1913  const EntityHandle* connec = NULL;
1914  int num_verts = 0;
1915  rval = mb->get_connectivity( cell, connec, num_verts );MB_CHK_SET_ERR( rval, "Failed to get connectivity" );
1916 
1917  std::vector< EntityHandle > newConnec;
1918  newConnec.push_back( connec[0] ); // at least one vertex
1919  int index = 0;
1920  int new_size = 1;
1921  while( index < num_verts - 2 )
1922  {
1923  int next_index = ( index + 1 );
1924  if( connec[next_index] != newConnec[new_size - 1] )
1925  {
1926  newConnec.push_back( connec[next_index] );
1927  new_size++;
1928  }
1929  index++;
1930  }
1931  // add the last one only if different from previous and first node
1932  if( ( connec[num_verts - 1] != connec[num_verts - 2] ) && ( connec[num_verts - 1] != connec[0] ) )
1933  {
1934  newConnec.push_back( connec[num_verts - 1] );
1935  new_size++;
1936  }
1937  if( new_size < num_verts )
1938  {
1939  // cout << "new cell from " << cell << " has only " << new_size << " vertices \n";
1940  modifiedCells.insert( cell );
1941  // create a new cell with type triangle, quad or polygon
1942  EntityType type = MBTRI;
1943  if( new_size == 3 )
1944  type = MBTRI;
1945  else if( new_size == 4 )
1946  type = MBQUAD;
1947  else if( new_size > 4 )
1948  type = MBPOLYGON;
1949 
1950  // create new cell
1951  EntityHandle newCell;
1952  rval = mb->create_element( type, &newConnec[0], new_size, newCell );MB_CHK_SET_ERR( rval, "Failed to create new cell" );
1953  // set the old id to the new element
1954  newCells.insert( newCell );
1955  double value; // use the same value to reset the tags, even if the tags are int (like Global ID)
1956  for( size_t i = 0; i < tagList.size(); i++ )
1957  {
1958  rval = mb->tag_get_data( tagList[i], &cell, 1, (void*)( &value ) );MB_CHK_SET_ERR( rval, "Failed to get tag value" );
1959  rval = mb->tag_set_data( tagList[i], &newCell, 1, (void*)( &value ) );MB_CHK_SET_ERR( rval, "Failed to set tag value on new cell" );
1960  }
1961  }
1962  }
1963 
1964  rval = mb->remove_entities( file_set, modifiedCells );MB_CHK_SET_ERR( rval, "Failed to remove old cells from file set" );
1965  rval = mb->delete_entities( modifiedCells );MB_CHK_SET_ERR( rval, "Failed to delete old cells" );
1966  rval = mb->add_entities( file_set, newCells );MB_CHK_SET_ERR( rval, "Failed to add new cells to file set" );
1967  rval = mb->add_entities( file_set, verts );MB_CHK_SET_ERR( rval, "Failed to add verts to the file set" );
1968 
1969  return MB_SUCCESS;
1970 }

References moab::Range::begin(), moab::Range::end(), ErrorCode, moab::Range::insert(), mb, MB_CHK_ERR, MB_CHK_SET_ERR, MB_SUCCESS, MBPOLYGON, MBQUAD, and MBTRI.

Referenced by moab::NCHelperDomain::create_mesh(), moab::NCHelperScrip::create_mesh(), and remove_duplicate_vertices().

◆ reverse_gnomonic_projection()

ErrorCode moab::IntxUtils::reverse_gnomonic_projection ( const double &  c1,
const double &  c2,
double  R,
int  plane,
CartVect pos 
)
static

Definition at line 450 of file IntxUtils.cpp.

455 {
456 
457  // the new point will be on line beta*pos
458  double len = sqrt( c1 * c1 + c2 * c2 + R * R );
459  double beta = R / len; // it is less than 1, in general
460 
461  switch( plane )
462  {
463  case 1: {
464  // the plane with x = R; x>y, x>z
465  // c1->y, c2->z
466  pos[0] = beta * R;
467  pos[1] = c1 * beta;
468  pos[2] = c2 * beta;
469  break;
470  }
471  case 2: {
472  // y = R -> zx
473  pos[1] = R * beta;
474  pos[2] = c1 * beta;
475  pos[0] = c2 * beta;
476  break;
477  }
478  case 3: {
479  // x=-R, -> yz
480  pos[0] = -R * beta;
481  pos[1] = -c1 * beta; // the sign is to preserve orientation
482  pos[2] = c2 * beta;
483  break;
484  }
485  case 4: {
486  // y = -R
487  pos[1] = -R * beta;
488  pos[2] = -c1 * beta; // the sign is to preserve orientation
489  pos[0] = c2 * beta;
490  break;
491  }
492  case 5: {
493  // z = -R
494  pos[2] = -R * beta;
495  pos[0] = -c1 * beta; // the sign is to preserve orientation
496  pos[1] = c2 * beta;
497  break;
498  }
499  case 6: {
500  pos[2] = R * beta;
501  pos[0] = c1 * beta;
502  pos[1] = c2 * beta;
503  break;
504  }
505  default:
506  return MB_FAILURE; // error
507  }
508 
509  return MB_SUCCESS; // no error
510 }

References MB_SUCCESS, and moab::R.

Referenced by moab::Intx2MeshOnSphere::findNodes(), moab::IntxRllCssphere::findNodes(), get_barycenters(), and moab::BoundBox::update_box_spherical_elem().

◆ ScaleToRadius()

ErrorCode moab::IntxUtils::ScaleToRadius ( Interface mb,
EntityHandle  set,
double  R 
)
static

Definition at line 771 of file IntxUtils.cpp.

772 {
773  Range nodes;
774  ErrorCode rval = mb->get_entities_by_type( set, MBVERTEX, nodes, true ); // recursive
775  if( rval != moab::MB_SUCCESS ) return rval;
776 
777  // one by one, get the node and project it on the sphere, with a radius given
778  // the center of the sphere is at 0,0,0
779  for( Range::iterator nit = nodes.begin(); nit != nodes.end(); ++nit )
780  {
781  EntityHandle nd = *nit;
782  CartVect pos;
783  rval = mb->get_coords( &nd, 1, (double*)&( pos[0] ) );
784  if( rval != moab::MB_SUCCESS ) return rval;
785  double len = pos.length();
786  if( len == 0. ) return MB_FAILURE;
787  pos = R / len * pos;
788  rval = mb->set_coords( &nd, 1, (double*)&( pos[0] ) );
789  if( rval != moab::MB_SUCCESS ) return rval;
790  }
791  return MB_SUCCESS;
792 }

References moab::Range::begin(), moab::Range::end(), ErrorCode, moab::CartVect::length(), mb, MB_SUCCESS, MBVERTEX, and moab::R.

Referenced by CreateTempestMesh(), global_gnomonic_projection(), and main().

◆ SortAndRemoveDoubles2()

int moab::IntxUtils::SortAndRemoveDoubles2 ( double *  P,
int &  nP,
double  epsilon 
)
static

Definition at line 98 of file IntxUtils.cpp.

99 {
100  if( nP < 2 ) return 0; // nothing to do
101 
102  // center of gravity for the points
103  double c[2] = { 0., 0. };
104  int k = 0;
105  for( k = 0; k < nP; k++ )
106  {
107  c[0] += P[2 * k];
108  c[1] += P[2 * k + 1];
109  }
110  c[0] /= nP;
111  c[1] /= nP;
112 
113  // how many? we dimensioned P at MAXEDGES*10; so we imply we could have at most 5*MAXEDGES
114  // intersection points
115  struct angleAndIndex pairAngleIndex[5 * MAXEDGES];
116 
117  for( k = 0; k < nP; k++ )
118  {
119  double x = P[2 * k] - c[0], y = P[2 * k + 1] - c[1];
120  if( x != 0. || y != 0. )
121  {
122  pairAngleIndex[k].angle = atan2( y, x );
123  }
124  else
125  {
126  pairAngleIndex[k].angle = 0;
127  // it would mean that the cells are touching at a vertex
128  }
129  pairAngleIndex[k].index = k;
130  }
131 
132  // this should be faster than the bubble sort we had before
133  std::sort( pairAngleIndex, pairAngleIndex + nP, angleCompare );
134  // copy now to a new double array
135  double PCopy[10 * MAXEDGES]; // the same dimension as P; very conservative, but faster than
136  // reallocate for a vector
137  for( k = 0; k < nP; k++ ) // index will show where it should go now;
138  {
139  int ck = pairAngleIndex[k].index;
140  PCopy[2 * k] = P[2 * ck];
141  PCopy[2 * k + 1] = P[2 * ck + 1];
142  }
143  // now copy from PCopy over original P location
144  std::copy( PCopy, PCopy + 2 * nP, P );
145 
146  // eliminate duplicates, finally
147 
148  int i = 0, j = 1; // the next one; j may advance faster than i
149  // check the unit
150  // double epsilon_1 = 1.e-5; // these are cm; 2 points are the same if the distance is less
151  // than 1.e-5 cm
152  while( j < nP )
153  {
154  double d2 = dist2( &P[2 * i], &P[2 * j] );
155  if( d2 > epsilon_1 )
156  {
157  i++;
158  P[2 * i] = P[2 * j];
159  P[2 * i + 1] = P[2 * j + 1];
160  }
161  j++;
162  }
163  // test also the last point with the first one (index 0)
164  // the first one could be at -PI; last one could be at +PI, according to atan2 span
165 
166  double d2 = dist2( P, &P[2 * i] ); // check the first and last points (ordered from -pi to +pi)
167  if( d2 > epsilon_1 )
168  {
169  nP = i + 1;
170  }
171  else
172  nP = i; // effectively delete the last point (that would have been the same with first)
173  if( nP == 0 ) nP = 1; // we should be left with at least one point we already tested if nP is 0 originally
174  return 0;
175 }

References moab::angleAndIndex::angle, moab::angleCompare(), dist2(), moab::angleAndIndex::index, and MAXEDGES.

Referenced by moab::Intx2MeshInPlane::computeIntersectionBetweenTgtAndSrc(), moab::Intx2MeshOnSphere::computeIntersectionBetweenTgtAndSrc(), and moab::IntxRllCssphere::computeIntersectionBetweenTgtAndSrc().

◆ spherical_to_cart()

CartVect moab::IntxUtils::spherical_to_cart ( IntxUtils::SphereCoords sc)
static

Definition at line 762 of file IntxUtils.cpp.

763 {
764  CartVect res;
765  res[0] = sc.R * cos( sc.lat ) * cos( sc.lon ); // x coordinate
766  res[1] = sc.R * cos( sc.lat ) * sin( sc.lon ); // y
767  res[2] = sc.R * sin( sc.lat ); // z
768  return res;
769 }

References moab::IntxUtils::SphereCoords::lat, moab::IntxUtils::SphereCoords::lon, and moab::IntxUtils::SphereCoords::R.

Referenced by add_field_value(), IntxUtilsCSLAM::departure_point_case1(), departure_point_swirl(), departure_point_swirl_rot(), main(), set_density(), and IntxUtilsCSLAM::smooth_field().

◆ transform_coordinates()

void moab::IntxUtils::transform_coordinates ( double *  avg_position,
int  projection_type 
)
static

Definition at line 671 of file IntxUtils.cpp.

672 {
673  if( projection_type == 1 )
674  {
675  double R =
676  avg_position[0] * avg_position[0] + avg_position[1] * avg_position[1] + avg_position[2] * avg_position[2];
677  R = sqrt( R );
678  double lat = asin( avg_position[2] / R );
679  double lon = atan2( avg_position[1], avg_position[0] );
680  avg_position[0] = lon;
681  avg_position[1] = lat;
682  avg_position[2] = R;
683  }
684  else if( projection_type == 2 ) // gnomonic projection
685  {
686  CartVect pos( avg_position );
687  int gplane;
688  IntxUtils::decide_gnomonic_plane( pos, gplane );
689 
690  IntxUtils::gnomonic_projection( pos, 1.0, gplane, avg_position[0], avg_position[1] );
691  avg_position[2] = 0;
692  IntxUtils::gnomonic_unroll( avg_position[0], avg_position[1], 1.0, gplane );
693  }
694 }

References decide_gnomonic_plane(), gnomonic_projection(), gnomonic_unroll(), and moab::R.


The documentation for this class was generated from the following files: