![]() |
Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
#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) |
Definition at line 16 of file IntxUtils.hpp.
static double moab::IntxUtils::area2D | ( | double * | a, |
double * | b, | ||
double * | c | ||
) | [inline, static] |
Definition at line 26 of file IntxUtils.hpp.
Referenced by moab::Intx2MeshInPlane::computeIntersectionBetweenTgtAndSrc(), moab::IntxRllCssphere::computeIntersectionBetweenTgtAndSrc(), moab::Intx2MeshOnSphere::computeIntersectionBetweenTgtAndSrc(), moab::Intx2MeshInPlane::findNodes(), moab::IntxRllCssphere::findNodes(), moab::Intx2MeshOnSphere::findNodes(), moab::IntxAreaUtils::positive_orientation(), moab::Intx2MeshInPlane::setup_tgt_cell(), moab::IntxRllCssphere::setup_tgt_cell(), and moab::Intx2MeshOnSphere::setup_tgt_cell().
{
// (b-a)x(c-a) / 2
return ( ( b[0] - a[0] ) * ( c[1] - a[1] ) - ( b[1] - a[1] ) * ( c[0] - a[0] ) ) / 2;
}
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 1750 of file IntxUtils.cpp.
Referenced by moab::IntxRllCssphere::computeIntersectionBetweenTgtAndSrc().
{
int extraPoints = 0;
// first decide the blue z coordinates
CartVect A( 0. ), B( 0. ), C( 0. ), D( 0. );
for( int i = 0; i < nsBlue; i++ )
{
if( blueEdgeType[i] == 0 )
{
int iP1 = ( i + 1 ) % nsBlue;
if( bluec[i][2] > bluec[iP1][2] )
{
A = bluec[i];
B = bluec[iP1];
C = bluec[( i + 2 ) % nsBlue];
D = bluec[( i + 3 ) % nsBlue]; // it could be back to A, if triangle on top
break;
}
}
}
if( nsBlue == 3 && B[2] < 0 )
{
// select D to be C
D = C;
C = B; // B is the south pole then
}
// so we have A, B, C, D, with A at the top, b going down, then C, D, D > C, A > B
// AB is const longitude, BC and DA constant latitude
// check now each of the red points if they are inside this rectangle
for( int i = 0; i < nsRed; i++ )
{
CartVect& X = redc[i];
if( X[2] > A[2] || X[2] < B[2] ) continue; // it is above or below the rectangle
// now decide if it is between the planes OAB and OCD
if( ( ( A * B ) % X >= -epsil ) && ( ( C * D ) % X >= -epsil ) )
{
side[i] = 1; //
// it means point X is in the rectangle that we want , on the sphere
// pass the coords 2d
P[extraPoints * 2] = red2dc[2 * i];
P[extraPoints * 2 + 1] = red2dc[2 * i + 1];
extraPoints++;
}
}
return extraPoints;
}
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.
Referenced by moab::Intx2MeshInPlane::computeIntersectionBetweenTgtAndSrc(), moab::IntxRllCssphere::computeIntersectionBetweenTgtAndSrc(), and moab::Intx2MeshOnSphere::computeIntersectionBetweenTgtAndSrc().
{
// 2 triangles, 3 corners, is the corner of X in Y?
// Y must have a positive area
/*
*/
int extraPoint = 0;
for( int i = 0; i < nX; i++ )
{
// compute double the area of all nY triangles formed by a side of Y and a corner of X; if
// one is negative, stop (negative means it is outside; X and Y are all oriented such that
// they are positive oriented;
// if one area is negative, it means it is outside the convex region, for sure)
double* A = X + 2 * i;
int inside = 1;
for( int j = 0; j < nY; j++ )
{
double* B = Y + 2 * j;
int j1 = ( j + 1 ) % nY;
double* C = Y + 2 * j1; // no copy of data
double area2 = ( B[0] - A[0] ) * ( C[1] - A[1] ) - ( C[0] - A[0] ) * ( B[1] - A[1] );
if( area2 < -epsilon_area * 200 )
{
inside = 0;
break;
}
}
if( inside )
{
side[i] = 1; // so vertex i of X is inside the convex region formed by Y
// so side has nX dimension (first array)
P[extraPoint * 2] = A[0];
P[extraPoint * 2 + 1] = A[1];
extraPoint++;
}
}
return extraPoint;
}
IntxUtils::SphereCoords moab::IntxUtils::cart_to_spherical | ( | CartVect & | cart3d | ) | [static] |
Definition at line 726 of file IntxUtils.cpp.
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().
{
SphereCoords res;
res.R = cart3d.length();
if( res.R < 0 )
{
res.lon = res.lat = 0.;
return res;
}
res.lat = asin( cart3d[2] / res.R );
res.lon = atan2( cart3d[1], cart3d[0] );
if( res.lon < 0 ) res.lon += 2 * M_PI; // M_PI is defined in math.h? it seems to be true, although
// there are some defines it depends on :(
// #if defined __USE_BSD || defined __USE_XOPEN ???
return res;
}
void moab::IntxUtils::decide_gnomonic_plane | ( | const CartVect & | pos, |
int & | oPlane | ||
) | [static] |
Definition at line 349 of file IntxUtils.cpp.
Referenced by moab::Intx2MeshOnSphere::computeIntersectionBetweenTgtAndSrc(), get_gnomonic_plane(), global_gnomonic_projection(), moab::IntxRllCssphere::setup_tgt_cell(), moab::Intx2MeshOnSphere::setup_tgt_cell(), transform_coordinates(), and moab::BoundBox::update_box_spherical_elem().
{
// decide plane, based on max x, y, z
if( fabs( pos[0] ) < fabs( pos[1] ) )
{
if( fabs( pos[2] ) < fabs( pos[1] ) )
{
// pos[1] is biggest
if( pos[1] > 0 )
plane = 2;
else
plane = 4;
}
else
{
// pos[2] is biggest
if( pos[2] < 0 )
plane = 5;
else
plane = 6;
}
}
else
{
if( fabs( pos[2] ) < fabs( pos[0] ) )
{
// pos[0] is the greatest
if( pos[0] > 0 )
plane = 1;
else
plane = 3;
}
else
{
// pos[2] is biggest
if( pos[2] < 0 )
plane = 5;
else
plane = 6;
}
}
return;
}
ErrorCode moab::IntxUtils::deep_copy_set_with_quads | ( | Interface * | mb, |
EntityHandle | source_set, | ||
EntityHandle | dest_set | ||
) | [static] |
Definition at line 1805 of file IntxUtils.cpp.
References moab::Interface::add_entities(), moab::Range::begin(), CORRTAGNAME, moab::dum, moab::Range::end(), ErrorCode, moab::Interface::get_connectivity(), moab::Interface::get_coords(), moab::ReadUtilIface::get_element_connect(), moab::Interface::get_entities_by_type(), moab::ReadUtilIface::get_node_coords(), moab::Interface::globalId_tag(), MB_CHK_ERR, MB_SUCCESS, MB_TAG_CREAT, MB_TAG_DENSE, MB_TYPE_HANDLE, MBQUAD, moab::Interface::query_interface(), moab::Range::size(), moab::Interface::tag_get_data(), moab::Interface::tag_get_handle(), moab::Interface::tag_set_data(), and moab::ReadUtilIface::update_adjacencies().
{
ReadUtilIface* read_iface;
ErrorCode rval = mb->query_interface( read_iface );MB_CHK_ERR( rval );
// create the handle tag for the corresponding element / vertex
EntityHandle dum = 0;
Tag corrTag = 0; // it will be created here
rval = mb->tag_get_handle( CORRTAGNAME, 1, MB_TYPE_HANDLE, corrTag, MB_TAG_DENSE | MB_TAG_CREAT, &dum );MB_CHK_ERR( rval );
// give the same global id to new verts and cells created in the lagr(departure) mesh
Tag gid = mb->globalId_tag();
Range quads;
rval = mb->get_entities_by_type( source_set, MBQUAD, quads );MB_CHK_ERR( rval );
Range connecVerts;
rval = mb->get_connectivity( quads, connecVerts );MB_CHK_ERR( rval );
std::map< EntityHandle, EntityHandle > newNodes;
std::vector< double* > coords;
EntityHandle start_vert, start_elem, *connect;
int num_verts = connecVerts.size();
rval = read_iface->get_node_coords( 3, num_verts, 0, start_vert, coords );
if( MB_SUCCESS != rval ) return rval;
// fill it up
int i = 0;
for( Range::iterator vit = connecVerts.begin(); vit != connecVerts.end(); ++vit, i++ )
{
EntityHandle oldV = *vit;
CartVect posi;
rval = mb->get_coords( &oldV, 1, &( posi[0] ) );MB_CHK_ERR( rval );
int global_id;
rval = mb->tag_get_data( gid, &oldV, 1, &global_id );MB_CHK_ERR( rval );
EntityHandle new_vert = start_vert + i;
// Cppcheck warning (false positive): variable coords is assigned a value that is never used
coords[0][i] = posi[0];
coords[1][i] = posi[1];
coords[2][i] = posi[2];
newNodes[oldV] = new_vert;
// set also the correspondent tag :)
rval = mb->tag_set_data( corrTag, &oldV, 1, &new_vert );MB_CHK_ERR( rval );
// also the other side
// need to check if we really need this; the new vertex will never need the old vertex
// we have the global id which is the same
rval = mb->tag_set_data( corrTag, &new_vert, 1, &oldV );MB_CHK_ERR( rval );
// set the global id on the corresponding vertex the same as the initial vertex
rval = mb->tag_set_data( gid, &new_vert, 1, &global_id );MB_CHK_ERR( rval );
}
// now create new quads in order (in a sequence)
rval = read_iface->get_element_connect( quads.size(), 4, MBQUAD, 0, start_elem, connect );
if( MB_SUCCESS != rval ) return rval;
int ie = 0;
for( Range::iterator it = quads.begin(); it != quads.end(); ++it, ie++ )
{
EntityHandle q = *it;
int nnodes;
const EntityHandle* conn;
rval = mb->get_connectivity( q, conn, nnodes );MB_CHK_ERR( rval );
int global_id;
rval = mb->tag_get_data( gid, &q, 1, &global_id );MB_CHK_ERR( rval );
for( int ii = 0; ii < nnodes; ii++ )
{
EntityHandle v1 = conn[ii];
connect[4 * ie + ii] = newNodes[v1];
}
EntityHandle newElement = start_elem + ie;
// set the corresponding tag; not sure we need this one, from old to new
rval = mb->tag_set_data( corrTag, &q, 1, &newElement );MB_CHK_ERR( rval );
rval = mb->tag_set_data( corrTag, &newElement, 1, &q );MB_CHK_ERR( rval );
// set the global id
rval = mb->tag_set_data( gid, &newElement, 1, &global_id );MB_CHK_ERR( rval );
rval = mb->add_entities( dest_set, &newElement, 1 );MB_CHK_ERR( rval );
}
rval = read_iface->update_adjacencies( start_elem, quads.size(), 4, connect );MB_CHK_ERR( rval );
return MB_SUCCESS;
}
static double moab::IntxUtils::dist2 | ( | double * | a, |
double * | b | ||
) | [inline, static] |
Definition at line 20 of file IntxUtils.hpp.
Referenced by moab::Intx2MeshInPlane::findNodes(), moab::IntxRllCssphere::findNodes(), moab::Intx2MeshOnSphere::findNodes(), and SortAndRemoveDoubles2().
{
double abx = b[0] - a[0], aby = b[1] - a[1];
return sqrt( abx * abx + aby * aby );
}
double moab::IntxUtils::distance_on_great_circle | ( | CartVect & | p1, |
CartVect & | p2 | ||
) | [static] |
Definition at line 1085 of file IntxUtils.cpp.
References cart_to_spherical(), moab::IntxUtils::SphereCoords::lat, moab::IntxUtils::SphereCoords::lon, and moab::IntxUtils::SphereCoords::R.
{
SphereCoords sph1 = cart_to_spherical( p1 );
SphereCoords sph2 = cart_to_spherical( p2 );
// radius should be the same
return sph1.R *
acos( sin( sph1.lon ) * sin( sph2.lon ) + cos( sph1.lat ) * cos( sph2.lat ) * cos( sph2.lon - sph2.lon ) );
}
double moab::IntxUtils::distance_on_sphere | ( | double | la1, |
double | te1, | ||
double | la2, | ||
double | te2 | ||
) | [static] |
Definition at line 1341 of file IntxUtils.cpp.
Referenced by IntxUtilsCSLAM::quasi_smooth_field(), and IntxUtilsCSLAM::slotted_cylinder_field().
{
return acos( sin( te1 ) * sin( te2 ) + cos( te1 ) * cos( te2 ) * cos( la1 - la2 ) );
}
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.
References MAXEDGES, and MB_SUCCESS.
Referenced by moab::Intx2MeshInPlane::computeIntersectionBetweenTgtAndSrc(), and moab::Intx2MeshOnSphere::computeIntersectionBetweenTgtAndSrc().
{
/* EDGEINTERSECTIONS computes edge intersections of two elements
[P,n]=EdgeIntersections(X,Y) computes for the two given elements * red
and blue ( stored column wise )
(point coordinates are stored column-wise, in counter clock
order) the points P where their edges intersect. In addition,
in n the indices of which neighbors of red are also intersecting
with blue are given.
*/
// points is an array with enough slots (24 * 2 doubles)
nPoints = 0;
for( int i = 0; i < MAXEDGES; i++ )
{
markb[i] = markr[i] = 0;
}
for( int i = 0; i < nsBlue; i++ )
{
for( int j = 0; j < nsRed; j++ )
{
double b[2];
double a[2][2]; // 2*2
int iPlus1 = ( i + 1 ) % nsBlue;
int jPlus1 = ( j + 1 ) % nsRed;
for( int k = 0; k < 2; k++ )
{
b[k] = red[2 * j + k] - blue[2 * i + k];
// row k of a: a(k, 0), a(k, 1)
a[k][0] = blue[2 * iPlus1 + k] - blue[2 * i + k];
a[k][1] = red[2 * j + k] - red[2 * jPlus1 + k];
}
double delta = a[0][0] * a[1][1] - a[0][1] * a[1][0];
if( fabs( delta ) > 1.e-14 ) // this is close to machine epsilon
{
// not parallel
double alfa = ( b[0] * a[1][1] - a[0][1] * b[1] ) / delta;
double beta = ( -b[0] * a[1][0] + b[1] * a[0][0] ) / delta;
if( 0 <= alfa && alfa <= 1. && 0 <= beta && beta <= 1. )
{
// the intersection is good
for( int k = 0; k < 2; k++ )
{
points[2 * nPoints + k] = blue[2 * i + k] + alfa * ( blue[2 * iPlus1 + k] - blue[2 * i + k] );
}
markb[i] = 1; // so neighbor number i of blue will be considered too.
markr[j] = 1; // this will be used in advancing red around blue quad
nPoints++;
}
}
// the case delta ~ 0. will be considered by the interior points logic
}
}
return MB_SUCCESS;
}
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.
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().
{
// if blue edge type is 1, intersect in 3d then project to 2d by gnomonic projection
// everything else the same (except if there are 2 points resulting, which is rare)
for( int i = 0; i < 4; i++ )
{ // always at most 4 , so maybe don't bother
markb[i] = markr[i] = 0;
}
for( int i = 0; i < nsBlue; i++ )
{
int iPlus1 = ( i + 1 ) % nsBlue;
if( blueEdgeType[i] == 0 ) // old style, just 2d
{
for( int j = 0; j < nsRed; j++ )
{
double b[2];
double a[2][2]; // 2*2
int jPlus1 = ( j + 1 ) % nsRed;
for( int k = 0; k < 2; k++ )
{
b[k] = red[2 * j + k] - blue[2 * i + k];
// row k of a: a(k, 0), a(k, 1)
a[k][0] = blue[2 * iPlus1 + k] - blue[2 * i + k];
a[k][1] = red[2 * j + k] - red[2 * jPlus1 + k];
}
double delta = a[0][0] * a[1][1] - a[0][1] * a[1][0];
if( fabs( delta ) > 1.e-14 )
{
// not parallel
double alfa = ( b[0] * a[1][1] - a[0][1] * b[1] ) / delta;
double beta = ( -b[0] * a[1][0] + b[1] * a[0][0] ) / delta;
if( 0 <= alfa && alfa <= 1. && 0 <= beta && beta <= 1. )
{
// the intersection is good
for( int k = 0; k < 2; k++ )
{
points[2 * nPoints + k] =
blue[2 * i + k] + alfa * ( blue[2 * iPlus1 + k] - blue[2 * i + k] );
}
markb[i] = 1; // so neighbor number i of blue will be considered too.
markr[j] = 1; // this will be used in advancing red around blue quad
nPoints++;
}
} // if the edges are too "parallel", skip them
}
}
else // edge type is 1, so use 3d intersection
{
CartVect& C = bluec[i];
CartVect& D = bluec[iPlus1];
for( int j = 0; j < nsRed; j++ )
{
int jPlus1 = ( j + 1 ) % nsRed; // nsRed is just 4, forget about it, usually
CartVect& A = redc[j];
CartVect& B = redc[jPlus1];
int np = 0;
double E[9];
intersect_great_circle_arc_with_clat_arc( A.array(), B.array(), C.array(), D.array(), R, E, np );
if( np == 0 ) continue;
if( np >= 2 )
{
std::cout << "intersection with 2 points :" << A << B << C << D << "\n";
}
for( int k = 0; k < np; k++ )
{
gnomonic_projection( CartVect( E + k * 3 ), R, plane, points[2 * nPoints],
points[2 * nPoints + 1] );
nPoints++;
}
markb[i] = 1; // so neighbor number i of blue will be considered too.
markr[j] = 1; // this will be used in advancing red around blue quad
}
}
}
return MB_SUCCESS;
}
ErrorCode moab::IntxUtils::enforce_convexity | ( | Interface * | mb, |
EntityHandle | set, | ||
int | rank = 0 |
||
) | [static] |
Definition at line 1097 of file IntxUtils.cpp.
References moab::Interface::add_entities(), moab::angle(), moab::Range::begin(), CORRTAGNAME, moab::Interface::create_element(), moab::Range::end(), ErrorCode, moab::Interface::get_connectivity(), moab::Interface::get_coords(), moab::Interface::get_entities_by_dimension(), moab::Interface::id_from_handle(), moab::Interface::list_entities(), MAXEDGES, MB_CHK_ERR, MB_SUCCESS, MB_TAG_DENSE, MB_TAG_NOT_FOUND, MB_TYPE_HANDLE, MB_TYPE_INTEGER, MBPOLYGON, MBTRI, oriented_spherical_angle(), moab::Interface::remove_entities(), moab::Interface::tag_get_data(), moab::Interface::tag_get_handle(), moab::Interface::tag_set_data(), and moab::Interface::write_file().
Referenced by main(), and update_tracer().
{
// look at each polygon; compute all angles; if one is reflex, break that angle with
// the next triangle; put the 2 new polys in the set;
// still look at the next poly
// replace it with 2 triangles, and remove from set;
// it should work for all polygons / tested first for case 1, with dt 0.5 (too much deformation)
// get all entities of dimension 2
// then get the connectivity, etc
Range inputRange;
ErrorCode rval = mb->get_entities_by_dimension( lset, 2, inputRange );MB_CHK_ERR( rval );
Tag corrTag = 0;
EntityHandle dumH = 0;
rval = mb->tag_get_handle( CORRTAGNAME, 1, MB_TYPE_HANDLE, corrTag, MB_TAG_DENSE, &dumH );
if( rval == MB_TAG_NOT_FOUND ) corrTag = 0;
Tag gidTag;
rval = mb->tag_get_handle( "GLOBAL_ID", 1, MB_TYPE_INTEGER, gidTag, MB_TAG_DENSE );MB_CHK_ERR( rval );
std::vector< double > coords;
coords.resize( 3 * MAXEDGES ); // at most 10 vertices per polygon
// we should create a queue with new polygons that need processing for reflex angles
// (obtuse)
std::queue< EntityHandle > newPolys;
int brokenPolys = 0;
Range::iterator eit = inputRange.begin();
while( eit != inputRange.end() || !newPolys.empty() )
{
EntityHandle eh;
if( eit != inputRange.end() )
{
eh = *eit;
++eit;
}
else
{
eh = newPolys.front();
newPolys.pop();
}
// get the nodes, then the coordinates
const EntityHandle* verts;
int num_nodes;
rval = mb->get_connectivity( eh, verts, num_nodes );MB_CHK_ERR( rval );
int nsides = num_nodes;
// account for possible padded polygons
while( verts[nsides - 2] == verts[nsides - 1] && nsides > 3 )
nsides--;
EntityHandle corrHandle = 0;
if( corrTag )
{
rval = mb->tag_get_data( corrTag, &eh, 1, &corrHandle );MB_CHK_ERR( rval );
}
int gid = 0;
rval = mb->tag_get_data( gidTag, &eh, 1, &gid );MB_CHK_ERR( rval );
coords.resize( 3 * nsides );
if( nsides < 4 ) continue; // if already triangles, don't bother
// get coordinates
rval = mb->get_coords( verts, nsides, &coords[0] );MB_CHK_ERR( rval );
// compute each angle
bool alreadyBroken = false;
for( int i = 0; i < nsides; i++ )
{
double* A = &coords[3 * i];
double* B = &coords[3 * ( ( i + 1 ) % nsides )];
double* C = &coords[3 * ( ( i + 2 ) % nsides )];
double angle = IntxUtils::oriented_spherical_angle( A, B, C );
if( angle - M_PI > 0. ) // even almost reflex is bad; break it!
{
if( alreadyBroken )
{
mb->list_entities( &eh, 1 );
mb->list_entities( verts, nsides );
double* D = &coords[3 * ( ( i + 3 ) % nsides )];
std::cout << "ABC: " << angle << " \n";
std::cout << "BCD: " << IntxUtils::oriented_spherical_angle( B, C, D ) << " \n";
std::cout << "CDA: " << IntxUtils::oriented_spherical_angle( C, D, A ) << " \n";
std::cout << "DAB: " << IntxUtils::oriented_spherical_angle( D, A, B ) << " \n";
std::cout << " this cell has at least 2 angles > 180, it has serious issues\n";
return MB_FAILURE;
}
// the bad angle is at i+1;
// create 1 triangle and one polygon; add the polygon to the input range, so
// it will be processed too
// also, add both to the set :) and remove the original polygon from the set
// break the next triangle, even though not optimal
// so create the triangle i+1, i+2, i+3; remove i+2 from original list
// even though not optimal in general, it is good enough.
EntityHandle conn3[3] = {verts[( i + 1 ) % nsides], verts[( i + 2 ) % nsides],
verts[( i + 3 ) % nsides]};
// create a polygon with num_nodes-1 vertices, and connectivity
// verts[i+1], verts[i+3], (all except i+2)
std::vector< EntityHandle > conn( nsides - 1 );
for( int j = 1; j < nsides; j++ )
{
conn[j - 1] = verts[( i + j + 2 ) % nsides];
}
EntityHandle newElement;
rval = mb->create_element( MBTRI, conn3, 3, newElement );MB_CHK_ERR( rval );
rval = mb->add_entities( lset, &newElement, 1 );MB_CHK_ERR( rval );
if( corrTag )
{
rval = mb->tag_set_data( corrTag, &newElement, 1, &corrHandle );MB_CHK_ERR( rval );
}
rval = mb->tag_set_data( gidTag, &newElement, 1, &gid );MB_CHK_ERR( rval );
if( nsides == 4 )
{
// create another triangle
rval = mb->create_element( MBTRI, &conn[0], 3, newElement );MB_CHK_ERR( rval );
}
else
{
// create another polygon, and add it to the inputRange
rval = mb->create_element( MBPOLYGON, &conn[0], nsides - 1, newElement );MB_CHK_ERR( rval );
newPolys.push( newElement ); // because it has less number of edges, the
// reverse should work to find it.
}
rval = mb->add_entities( lset, &newElement, 1 );MB_CHK_ERR( rval );
if( corrTag )
{
rval = mb->tag_set_data( corrTag, &newElement, 1, &corrHandle );MB_CHK_ERR( rval );
}
rval = mb->tag_set_data( gidTag, &newElement, 1, &gid );MB_CHK_ERR( rval );
rval = mb->remove_entities( lset, &eh, 1 );MB_CHK_ERR( rval );
brokenPolys++;
alreadyBroken = true; // get out of the loop, element is broken
}
}
}
if( brokenPolys > 0 )
{
std::cout << "on local process " << my_rank << ", " << brokenPolys
<< " concave polygons were decomposed in convex ones \n";
#ifdef VERBOSE
std::stringstream fff;
fff << "file_set" << mb->id_from_handle( lset ) << "rk_" << my_rank << ".h5m";
rval = mb->write_file( fff.str().c_str(), 0, 0, &lset, 1 );MB_CHK_ERR( rval );
std::cout << "wrote new file set: " << fff.str() << "\n";
#endif
}
return MB_SUCCESS;
}
ErrorCode moab::IntxUtils::fix_degenerate_quads | ( | Interface * | mb, |
EntityHandle | set | ||
) | [static] |
Definition at line 1246 of file IntxUtils.cpp.
References moab::Interface::add_entities(), moab::Range::begin(), moab::Interface::create_element(), moab::Interface::delete_entities(), moab::Range::end(), ErrorCode, moab::Interface::get_connectivity(), moab::Interface::get_entities_by_type(), moab::Interface::globalId_tag(), MB_CHK_ERR, MB_SUCCESS, MBQUAD, MBTRI, moab::Interface::remove_entities(), moab::Interface::tag_get_data(), and moab::Interface::tag_set_data().
Referenced by moab::TempestRemapper::ComputeOverlapMesh(), and main().
{
Range quads;
ErrorCode rval = mb->get_entities_by_type( set, MBQUAD, quads );MB_CHK_ERR( rval );
Tag gid;
gid = mb->globalId_tag();
for( Range::iterator qit = quads.begin(); qit != quads.end(); ++qit )
{
EntityHandle quad = *qit;
const EntityHandle* conn4 = NULL;
int num_nodes = 0;
rval = mb->get_connectivity( quad, conn4, num_nodes );MB_CHK_ERR( rval );
for( int i = 0; i < num_nodes; i++ )
{
int next_node_index = ( i + 1 ) % num_nodes;
if( conn4[i] == conn4[next_node_index] )
{
// form a triangle and delete the quad
// first get the global id, to set it on triangle later
int global_id = 0;
rval = mb->tag_get_data( gid, &quad, 1, &global_id );MB_CHK_ERR( rval );
int i2 = ( i + 2 ) % num_nodes;
int i3 = ( i + 3 ) % num_nodes;
EntityHandle conn3[3] = {conn4[i], conn4[i2], conn4[i3]};
EntityHandle tri;
rval = mb->create_element( MBTRI, conn3, 3, tri );MB_CHK_ERR( rval );
mb->add_entities( set, &tri, 1 );
mb->remove_entities( set, &quad, 1 );
mb->delete_entities( &quad, 1 );
rval = mb->tag_set_data( gid, &tri, 1, &global_id );MB_CHK_ERR( rval );
}
}
}
return MB_SUCCESS;
}
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.
References moab::Interface::add_entities(), moab::CartVect::array(), moab::Range::begin(), center(), moab::Interface::create_element(), moab::Interface::create_meshset(), moab::Interface::create_vertex(), decide_gnomonic_plane(), moab::Range::empty(), moab::Range::end(), ErrorCode, moab::Interface::get_connectivity(), moab::Interface::get_coords(), moab::Interface::get_entities_by_dimension(), moab::Interface::get_entities_by_handle(), moab::Interface::get_entities_by_type_and_tag(), gnomonic_projection(), gnomonic_unroll(), moab::Range::insert(), MB_CHK_ERR, MB_SUCCESS, MBENTITYSET, MESHSET_SET, ScaleToRadius(), moab::Interface::tag_get_data(), moab::Interface::tag_get_handle(), moab::Interface::tag_set_data(), moab::Interface::type_from_handle(), and moab::Interface::UNION.
{
std::string parTagName( "PARALLEL_PARTITION" );
Tag part_tag;
Range partSets;
ErrorCode rval = mb->tag_get_handle( parTagName.c_str(), part_tag );
if( MB_SUCCESS == rval && part_tag != 0 )
{
rval = mb->get_entities_by_type_and_tag( inSet, MBENTITYSET, &part_tag, NULL, 1, partSets, Interface::UNION );MB_CHK_ERR( rval );
}
rval = ScaleToRadius( mb, inSet, 1.0 );MB_CHK_ERR( rval );
// Get all entities of dimension 2
Range inputRange; // get
rval = mb->get_entities_by_dimension( inSet, 1, inputRange );MB_CHK_ERR( rval );
rval = mb->get_entities_by_dimension( inSet, 2, inputRange );MB_CHK_ERR( rval );
std::map< EntityHandle, int > partsAssign;
std::map< int, EntityHandle > newPartSets;
if( !partSets.empty() )
{
// get all cells, and assign parts
for( Range::iterator setIt = partSets.begin(); setIt != partSets.end(); ++setIt )
{
EntityHandle pSet = *setIt;
Range ents;
rval = mb->get_entities_by_handle( pSet, ents );MB_CHK_ERR( rval );
int val;
rval = mb->tag_get_data( part_tag, &pSet, 1, &val );MB_CHK_ERR( rval );
// create a new set with the same part id tag, in the outSet
EntityHandle newPartSet;
rval = mb->create_meshset( MESHSET_SET, newPartSet );MB_CHK_ERR( rval );
rval = mb->tag_set_data( part_tag, &newPartSet, 1, &val );MB_CHK_ERR( rval );
newPartSets[val] = newPartSet;
rval = mb->add_entities( outSet, &newPartSet, 1 );MB_CHK_ERR( rval );
for( Range::iterator it = ents.begin(); it != ents.end(); ++it )
{
partsAssign[*it] = val;
}
}
}
if( centers_only )
{
for( Range::iterator it = inputRange.begin(); it != inputRange.end(); ++it )
{
CartVect center;
EntityHandle cell = *it;
rval = mb->get_coords( &cell, 1, center.array() );MB_CHK_ERR( rval );
int plane;
decide_gnomonic_plane( center, plane );
double c[3];
c[2] = 0.;
gnomonic_projection( center, R, plane, c[0], c[1] );
gnomonic_unroll( c[0], c[1], R, plane );
EntityHandle vertex;
rval = mb->create_vertex( c, vertex );MB_CHK_ERR( rval );
rval = mb->add_entities( outSet, &vertex, 1 );MB_CHK_ERR( rval );
}
}
else
{
// distribute the cells to 6 planes, based on the center
Range subranges[6];
for( Range::iterator it = inputRange.begin(); it != inputRange.end(); ++it )
{
CartVect center;
EntityHandle cell = *it;
rval = mb->get_coords( &cell, 1, center.array() );MB_CHK_ERR( rval );
int plane;
decide_gnomonic_plane( center, plane );
subranges[plane - 1].insert( cell );
}
for( int i = 1; i <= 6; i++ )
{
Range verts;
rval = mb->get_connectivity( subranges[i - 1], verts );MB_CHK_ERR( rval );
std::map< EntityHandle, EntityHandle > corr;
for( Range::iterator vt = verts.begin(); vt != verts.end(); ++vt )
{
CartVect vect;
EntityHandle v = *vt;
rval = mb->get_coords( &v, 1, vect.array() );MB_CHK_ERR( rval );
double c[3];
c[2] = 0.;
gnomonic_projection( vect, R, i, c[0], c[1] );
gnomonic_unroll( c[0], c[1], R, i );
EntityHandle vertex;
rval = mb->create_vertex( c, vertex );MB_CHK_ERR( rval );
corr[v] = vertex; // for new connectivity
}
EntityHandle new_conn[20]; // max edges in 2d ?
for( Range::iterator eit = subranges[i - 1].begin(); eit != subranges[i - 1].end(); ++eit )
{
EntityHandle eh = *eit;
const EntityHandle* conn = NULL;
int num_nodes;
rval = mb->get_connectivity( eh, conn, num_nodes );MB_CHK_ERR( rval );
// build a new vertex array
for( int j = 0; j < num_nodes; j++ )
new_conn[j] = corr[conn[j]];
EntityType type = mb->type_from_handle( eh );
EntityHandle newCell;
rval = mb->create_element( type, new_conn, num_nodes, newCell );MB_CHK_ERR( rval );
rval = mb->add_entities( outSet, &newCell, 1 );MB_CHK_ERR( rval );
std::map< EntityHandle, int >::iterator mit = partsAssign.find( eh );
if( mit != partsAssign.end() )
{
int val = mit->second;
rval = mb->add_entities( newPartSets[val], &newCell, 1 );MB_CHK_ERR( rval );
}
}
}
}
return MB_SUCCESS;
}
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.
References MB_SUCCESS.
Referenced by moab::IntxRllCssphere::computeIntersectionBetweenTgtAndSrc(), moab::Intx2MeshOnSphere::computeIntersectionBetweenTgtAndSrc(), EdgeIntxRllCs(), get_barycenters(), get_intersection_weights(), get_linear_reconstruction(), global_gnomonic_projection(), moab::IntxRllCssphere::setup_tgt_cell(), moab::Intx2MeshOnSphere::setup_tgt_cell(), test_linear_reconstruction(), transform_coordinates(), and moab::BoundBox::update_box_spherical_elem().
{
double alfa = 1.; // the new point will be on line alfa*pos
switch( plane )
{
case 1: {
// the plane with x = R; x>y, x>z
// c1->y, c2->z
alfa = R / pos[0];
c1 = alfa * pos[1];
c2 = alfa * pos[2];
break;
}
case 2: {
// y = R -> zx
alfa = R / pos[1];
c1 = alfa * pos[2];
c2 = alfa * pos[0];
break;
}
case 3: {
// x=-R, -> yz
alfa = -R / pos[0];
c1 = -alfa * pos[1]; // the sign is to preserve orientation
c2 = alfa * pos[2];
break;
}
case 4: {
// y = -R
alfa = -R / pos[1];
c1 = -alfa * pos[2]; // the sign is to preserve orientation
c2 = alfa * pos[0];
break;
}
case 5: {
// z = -R
alfa = -R / pos[2];
c1 = -alfa * pos[0]; // the sign is to preserve orientation
c2 = alfa * pos[1];
break;
}
case 6: {
alfa = R / pos[2];
c1 = alfa * pos[0];
c2 = alfa * pos[1];
break;
}
default:
return MB_FAILURE; // error
}
return MB_SUCCESS; // no error
}
void moab::IntxUtils::gnomonic_unroll | ( | double & | c1, |
double & | c2, | ||
double | R, | ||
int | plane | ||
) | [static] |
Definition at line 512 of file IntxUtils.cpp.
References moab::R.
Referenced by global_gnomonic_projection(), and transform_coordinates().
{
double tmp;
switch( plane )
{
case 1:
break; // nothing
case 2: // rotate + 90
tmp = c1;
c1 = -c2;
c2 = tmp;
c1 = c1 + 2 * R;
break;
case 3:
c1 = c1 + 4 * R;
break;
case 4: // rotate with -90 x-> -y; y -> x
tmp = c1;
c1 = c2;
c2 = -tmp;
c1 = c1 - 2 * R;
break;
case 5: // South Pole
// rotate 180 then move to (-2, -2)
c1 = -c1 - 2. * R;
c2 = -c2 - 2. * R;
break;
;
case 6: // North Pole
c1 = c1 - 2. * R;
c2 = c2 + 2. * R;
break;
}
return;
}
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 1437 of file IntxUtils.cpp.
References moab::CartVect::length_squared(), MB_SUCCESS, moab::R, and moab::verify().
Referenced by EdgeIntxRllCs().
{
const double distTol = R * 1.e-6;
const double Tolerance = R * R * 1.e-12; // radius should be 1, usually
np = 0; // number of points in intersection
CartVect a( A ), b( B ), c( C ), d( D );
// check input first
double R2 = R * R;
if( fabs( a.length_squared() - R2 ) + fabs( b.length_squared() - R2 ) + fabs( c.length_squared() - R2 ) +
fabs( d.length_squared() - R2 ) >
10 * Tolerance )
return MB_FAILURE;
if( ( a - b ).length_squared() < Tolerance ) return MB_FAILURE;
if( ( c - d ).length_squared() < Tolerance ) // edges are too short
return MB_FAILURE;
// CD is the const latitude arc
if( fabs( C[2] - D[2] ) > distTol ) // cd is not on the same z (constant latitude)
return MB_FAILURE;
if( fabs( R - C[2] ) < distTol || fabs( R + C[2] ) < distTol ) return MB_FAILURE; // too close to the poles
// find the points on the circle P(teta) = (r*sin(teta), r*cos(teta), C[2]) that are on the
// great circle arc AB normal to the AB circle:
CartVect n1 = a * b; // the normal to the great circle arc (circle)
// solve the system of equations:
/*
* n1%(x, y, z) = 0 // on the great circle
* z = C[2];
* x^2+y^2+z^2 = R^2
*/
double z = C[2];
if( fabs( n1[0] ) + fabs( n1[1] ) < 2 * Tolerance )
{
// it is the Equator; check if the const lat edge is Equator too
if( fabs( C[2] ) > distTol )
{
return MB_FAILURE; // no intx, too far from Eq
}
else
{
// all points are on the equator
//
CartVect cd = c * d;
// by convention, c= -Tolerance ); // a>c?
bool dgta = ( ad % cd >= -Tolerance ); // d>a?
bool bgtc = ( cb % cd >= -Tolerance ); // b>c?
bool dgtb = ( bd % cd >= -Tolerance ); // d>b?
if( agtc )
{
if( dgta )
{
// a is for sure a point
E[0] = a[0];
E[1] = a[1];
E[2] = a[2];
np++;
if( bgtc )
{
if( dgtb )
{
// b is also in between c and d
E[3] = b[0];
E[4] = b[1];
E[5] = b[2];
np++;
}
else
{
// then order is c a d b, intx is ad
E[3] = d[0];
E[4] = d[1];
E[5] = d[2];
np++;
}
}
else
{
// b is less than c, so b c a d, intx is ac
E[3] = c[0];
E[4] = c[1];
E[5] = c[2];
np++; // what if E[0] is E[3]?
}
}
else // c < d < a
{
if( dgtb ) // d is for sure in
{
E[0] = d[0];
E[1] = d[1];
E[2] = d[2];
np++;
if( bgtc ) // c 0 ) return MB_SUCCESS;
return MB_FAILURE; // no intersection
}
{
if( fabs( n1[0] ) <= fabs( n1[1] ) )
{
// resolve eq in x: n0 * x + n1 * y +n2*z = 0; y = -n2/n1*z -n0/n1*x
// (u+v*x)^2+x^2=R2-z^2
// (v^2+1)*x^2 + 2*u*v *x + u^2+z^2-R^2 = 0
// delta = 4*u^2*v^2 - 4*(v^2-1)(u^2+z^2-R^2)
// x1,2 =
double u = -n1[2] / n1[1] * z, v = -n1[0] / n1[1];
double a1 = v * v + 1, b1 = 2 * u * v, c1 = u * u + z * z - R2;
double delta = b1 * b1 - 4 * a1 * c1;
if( delta < -Tolerance ) return MB_FAILURE; // no intersection
if( delta > Tolerance ) // 2 solutions possible
{
double x1 = ( -b1 + sqrt( delta ) ) / 2 / a1;
double x2 = ( -b1 - sqrt( delta ) ) / 2 / a1;
double y1 = u + v * x1;
double y2 = u + v * x2;
if( verify( a, b, c, d, x1, y1, z ) )
{
E[0] = x1;
E[1] = y1;
E[2] = z;
np++;
}
if( verify( a, b, c, d, x2, y2, z ) )
{
E[3 * np + 0] = x2;
E[3 * np + 1] = y2;
E[3 * np + 2] = z;
np++;
}
}
else
{
// one solution
double x1 = -b1 / 2 / a1;
double y1 = u + v * x1;
if( verify( a, b, c, d, x1, y1, z ) )
{
E[0] = x1;
E[1] = y1;
E[2] = z;
np++;
}
}
}
else
{
// resolve eq in y, reverse
// n0 * x + n1 * y +n2*z = 0; x = -n2/n0*z -n1/n0*y = u+v*y
// (u+v*y)^2+y^2 -R2+z^2 =0
// (v^2+1)*y^2 + 2*u*v *y + u^2+z^2-R^2 = 0
//
// x1,2 =
double u = -n1[2] / n1[0] * z, v = -n1[1] / n1[0];
double a1 = v * v + 1, b1 = 2 * u * v, c1 = u * u + z * z - R2;
double delta = b1 * b1 - 4 * a1 * c1;
if( delta < -Tolerance ) return MB_FAILURE; // no intersection
if( delta > Tolerance ) // 2 solutions possible
{
double y1 = ( -b1 + sqrt( delta ) ) / 2 / a1;
double y2 = ( -b1 - sqrt( delta ) ) / 2 / a1;
double x1 = u + v * y1;
double x2 = u + v * y2;
if( verify( a, b, c, d, x1, y1, z ) )
{
E[0] = x1;
E[1] = y1;
E[2] = z;
np++;
}
if( verify( a, b, c, d, x2, y2, z ) )
{
E[3 * np + 0] = x2;
E[3 * np + 1] = y2;
E[3 * np + 2] = z;
np++;
}
}
else
{
// one solution
double y1 = -b1 / 2 / a1;
double x1 = u + v * y1;
if( verify( a, b, c, d, x1, y1, z ) )
{
E[0] = x1;
E[1] = y1;
E[2] = z;
np++;
}
}
}
}
if( np <= 0 ) return MB_FAILURE;
return MB_SUCCESS;
}
ErrorCode moab::IntxUtils::intersect_great_circle_arcs | ( | double * | A, |
double * | B, | ||
double * | C, | ||
double * | D, | ||
double | R, | ||
double * | E | ||
) | [static] |
Definition at line 1350 of file IntxUtils.cpp.
References moab::CartVect::length_squared(), MB_SUCCESS, moab::CartVect::normalize(), and moab::R.
{
// first verify A, B, C, D are on the same sphere
double R2 = R * R;
const double Tolerance = 1.e-12 * R2;
CartVect a( A ), b( B ), c( C ), d( D );
if( fabs( a.length_squared() - R2 ) + fabs( b.length_squared() - R2 ) + fabs( c.length_squared() - R2 ) +
fabs( d.length_squared() - R2 ) >
10 * Tolerance )
return MB_FAILURE;
CartVect n1 = a * b;
if( n1.length_squared() < Tolerance ) return MB_FAILURE;
CartVect n2 = c * d;
if( n2.length_squared() < Tolerance ) return MB_FAILURE;
CartVect n3 = n1 * n2;
n3.normalize();
n3 = R * n3;
// the intersection is either n3 or -n3
CartVect n4 = a * n3, n5 = n3 * b;
if( n1 % n4 >= -Tolerance && n1 % n5 >= -Tolerance )
{
// n3 is good for ab, see if it is good for cd
n4 = c * n3;
n5 = n3 * d;
if( n2 % n4 >= -Tolerance && n2 % n5 >= -Tolerance )
{
E[0] = n3[0];
E[1] = n3[1];
E[2] = n3[2];
}
else
return MB_FAILURE;
}
else
{
// try -n3
n3 = -n3;
n4 = a * n3, n5 = n3 * b;
if( n1 % n4 >= -Tolerance && n1 % n5 >= -Tolerance )
{
// n3 is good for ab, see if it is good for cd
n4 = c * n3;
n5 = n3 * d;
if( n2 % n4 >= -Tolerance && n2 % n5 >= -Tolerance )
{
E[0] = n3[0];
E[1] = n3[1];
E[2] = n3[2];
}
else
return MB_FAILURE;
}
else
return MB_FAILURE;
}
return MB_SUCCESS;
}
double moab::IntxUtils::oriented_spherical_angle | ( | double * | A, |
double * | B, | ||
double * | C | ||
) | [static] |
Definition at line 814 of file IntxUtils.cpp.
References moab::angle().
Referenced by moab::IntxAreaUtils::area_spherical_polygon_girard(), and enforce_convexity().
{
// assume the same radius, sphere at origin
CartVect a( A ), b( B ), c( C );
CartVect normalOAB = a * b;
CartVect normalOCB = c * b;
CartVect orient = ( c - b ) * ( a - b );
double ang = angle( normalOAB, normalOCB ); // this is between 0 and M_PI
if( ang != ang )
{
// signal of a nan
std::cout << a << " " << b << " " << c << "\n";
std::cout << ang << "\n";
}
if( orient % b < 0 ) return ( 2 * M_PI - ang ); // the other angle, supplement
return ang;
}
ErrorCode moab::IntxUtils::remove_duplicate_vertices | ( | Interface * | mb, |
EntityHandle | file_set, | ||
double | merge_tol, | ||
std::vector< Tag > & | tagList | ||
) | [static] |
Definition at line 1894 of file IntxUtils.cpp.
References ErrorCode, moab::Interface::get_entities_by_dimension(), MB_CHK_ERR, MB_SUCCESS, moab::MergeMesh::merge_all(), moab::Interface::remove_entities(), and remove_padded_vertices().
{
Range verts;
ErrorCode rval = mb->get_entities_by_dimension( file_set, 0, verts );MB_CHK_ERR( rval );
rval = mb->remove_entities( file_set, verts );MB_CHK_ERR( rval );
MergeMesh mm( mb );
// remove the vertices from the set, before merging
rval = mm.merge_all( file_set, merge_tol );MB_CHK_ERR( rval );
// now correct vertices that are repeated in polygons
rval = remove_padded_vertices( mb, file_set, tagList );
return MB_SUCCESS;
}
ErrorCode moab::IntxUtils::remove_padded_vertices | ( | Interface * | mb, |
EntityHandle | file_set, | ||
std::vector< Tag > & | tagList | ||
) | [static] |
Definition at line 1914 of file IntxUtils.cpp.
References moab::Interface::add_entities(), moab::Range::begin(), moab::Interface::create_element(), moab::Interface::delete_entities(), moab::Range::end(), ErrorCode, moab::Interface::get_connectivity(), moab::Interface::get_entities_by_dimension(), moab::Range::insert(), MB_CHK_ERR, MB_CHK_SET_ERR, MB_SUCCESS, MBPOLYGON, MBQUAD, MBTRI, moab::Interface::remove_entities(), moab::Interface::tag_get_data(), and moab::Interface::tag_set_data().
Referenced by moab::NCHelperDomain::create_mesh(), moab::NCHelperScrip::create_mesh(), and remove_duplicate_vertices().
{
// now correct vertices that are repeated in polygons
Range cells;
ErrorCode rval = mb->get_entities_by_dimension( file_set, 2, cells );MB_CHK_ERR( rval );
Range verts;
rval = mb->get_connectivity( cells, verts );MB_CHK_ERR( rval );
Range modifiedCells; // will be deleted at the end; keep the gid
Range newCells;
for( Range::iterator cit = cells.begin(); cit != cells.end(); ++cit )
{
EntityHandle cell = *cit;
const EntityHandle* connec = NULL;
int num_verts = 0;
rval = mb->get_connectivity( cell, connec, num_verts );MB_CHK_SET_ERR( rval, "Failed to get connectivity" );
std::vector< EntityHandle > newConnec;
newConnec.push_back( connec[0] ); // at least one vertex
int index = 0;
int new_size = 1;
while( index < num_verts - 2 )
{
int next_index = ( index + 1 );
if( connec[next_index] != newConnec[new_size - 1] )
{
newConnec.push_back( connec[next_index] );
new_size++;
}
index++;
}
// add the last one only if different from previous and first node
if( ( connec[num_verts - 1] != connec[num_verts - 2] ) && ( connec[num_verts - 1] != connec[0] ) )
{
newConnec.push_back( connec[num_verts - 1] );
new_size++;
}
if( new_size < num_verts )
{
// cout << "new cell from " << cell << " has only " << new_size << " vertices \n";
modifiedCells.insert( cell );
// create a new cell with type triangle, quad or polygon
EntityType type = MBTRI;
if( new_size == 3 )
type = MBTRI;
else if( new_size == 4 )
type = MBQUAD;
else if( new_size > 4 )
type = MBPOLYGON;
// create new cell
EntityHandle newCell;
rval = mb->create_element( type, &newConnec[0], new_size, newCell );MB_CHK_SET_ERR( rval, "Failed to create new cell" );
// set the old id to the new element
newCells.insert( newCell );
double value; // use the same value to reset the tags, even if the tags are int (like Global ID)
for( size_t i = 0; i < tagList.size(); i++ )
{
rval = mb->tag_get_data( tagList[i], &cell, 1, (void*)( &value ) );MB_CHK_SET_ERR( rval, "Failed to get tag value" );
rval = mb->tag_set_data( tagList[i], &newCell, 1, (void*)( &value ) );MB_CHK_SET_ERR( rval, "Failed to set tag value on new cell" );
}
}
}
rval = mb->remove_entities( file_set, modifiedCells );MB_CHK_SET_ERR( rval, "Failed to remove old cells from file set" );
rval = mb->delete_entities( modifiedCells );MB_CHK_SET_ERR( rval, "Failed to delete old cells" );
rval = mb->add_entities( file_set, newCells );MB_CHK_SET_ERR( rval, "Failed to add new cells to file set" );
rval = mb->add_entities( file_set, verts );MB_CHK_SET_ERR( rval, "Failed to add verts to the file set" );
return MB_SUCCESS;
}
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.
References MB_SUCCESS, and moab::R.
Referenced by moab::IntxRllCssphere::findNodes(), moab::Intx2MeshOnSphere::findNodes(), get_barycenters(), and moab::BoundBox::update_box_spherical_elem().
{
// the new point will be on line beta*pos
double len = sqrt( c1 * c1 + c2 * c2 + R * R );
double beta = R / len; // it is less than 1, in general
switch( plane )
{
case 1: {
// the plane with x = R; x>y, x>z
// c1->y, c2->z
pos[0] = beta * R;
pos[1] = c1 * beta;
pos[2] = c2 * beta;
break;
}
case 2: {
// y = R -> zx
pos[1] = R * beta;
pos[2] = c1 * beta;
pos[0] = c2 * beta;
break;
}
case 3: {
// x=-R, -> yz
pos[0] = -R * beta;
pos[1] = -c1 * beta; // the sign is to preserve orientation
pos[2] = c2 * beta;
break;
}
case 4: {
// y = -R
pos[1] = -R * beta;
pos[2] = -c1 * beta; // the sign is to preserve orientation
pos[0] = c2 * beta;
break;
}
case 5: {
// z = -R
pos[2] = -R * beta;
pos[0] = -c1 * beta; // the sign is to preserve orientation
pos[1] = c2 * beta;
break;
}
case 6: {
pos[2] = R * beta;
pos[0] = c1 * beta;
pos[1] = c2 * beta;
break;
}
default:
return MB_FAILURE; // error
}
return MB_SUCCESS; // no error
}
ErrorCode moab::IntxUtils::ScaleToRadius | ( | Interface * | mb, |
EntityHandle | set, | ||
double | R | ||
) | [static] |
Definition at line 771 of file IntxUtils.cpp.
References moab::Range::begin(), moab::Range::end(), ErrorCode, moab::Interface::get_coords(), moab::Interface::get_entities_by_type(), moab::CartVect::length(), MB_SUCCESS, MBVERTEX, and moab::Interface::set_coords().
Referenced by CreateTempestMesh(), global_gnomonic_projection(), and main().
{
Range nodes;
ErrorCode rval = mb->get_entities_by_type( set, MBVERTEX, nodes, true ); // recursive
if( rval != moab::MB_SUCCESS ) return rval;
// one by one, get the node and project it on the sphere, with a radius given
// the center of the sphere is at 0,0,0
for( Range::iterator nit = nodes.begin(); nit != nodes.end(); ++nit )
{
EntityHandle nd = *nit;
CartVect pos;
rval = mb->get_coords( &nd, 1, (double*)&( pos[0] ) );
if( rval != moab::MB_SUCCESS ) return rval;
double len = pos.length();
if( len == 0. ) return MB_FAILURE;
pos = R / len * pos;
rval = mb->set_coords( &nd, 1, (double*)&( pos[0] ) );
if( rval != moab::MB_SUCCESS ) return rval;
}
return MB_SUCCESS;
}
int moab::IntxUtils::SortAndRemoveDoubles2 | ( | double * | P, |
int & | nP, | ||
double | epsilon | ||
) | [static] |
Definition at line 98 of file IntxUtils.cpp.
References moab::angleAndIndex::angle, moab::angleCompare(), dist2(), moab::angleAndIndex::index, and MAXEDGES.
Referenced by moab::Intx2MeshInPlane::computeIntersectionBetweenTgtAndSrc(), moab::IntxRllCssphere::computeIntersectionBetweenTgtAndSrc(), and moab::Intx2MeshOnSphere::computeIntersectionBetweenTgtAndSrc().
{
if( nP < 2 ) return 0; // nothing to do
// center of gravity for the points
double c[2] = {0., 0.};
int k = 0;
for( k = 0; k < nP; k++ )
{
c[0] += P[2 * k];
c[1] += P[2 * k + 1];
}
c[0] /= nP;
c[1] /= nP;
// how many? we dimensioned P at MAXEDGES*10; so we imply we could have at most 5*MAXEDGES
// intersection points
struct angleAndIndex pairAngleIndex[5 * MAXEDGES];
for( k = 0; k < nP; k++ )
{
double x = P[2 * k] - c[0], y = P[2 * k + 1] - c[1];
if( x != 0. || y != 0. )
{
pairAngleIndex[k].angle = atan2( y, x );
}
else
{
pairAngleIndex[k].angle = 0;
// it would mean that the cells are touching at a vertex
}
pairAngleIndex[k].index = k;
}
// this should be faster than the bubble sort we had before
std::sort( pairAngleIndex, pairAngleIndex + nP, angleCompare );
// copy now to a new double array
double PCopy[10 * MAXEDGES]; // the same dimension as P; very conservative, but faster than
// reallocate for a vector
for( k = 0; k < nP; k++ ) // index will show where it should go now;
{
int ck = pairAngleIndex[k].index;
PCopy[2 * k] = P[2 * ck];
PCopy[2 * k + 1] = P[2 * ck + 1];
}
// now copy from PCopy over original P location
std::copy( PCopy, PCopy + 2 * nP, P );
// eliminate duplicates, finally
int i = 0, j = 1; // the next one; j may advance faster than i
// check the unit
// double epsilon_1 = 1.e-5; // these are cm; 2 points are the same if the distance is less
// than 1.e-5 cm
while( j < nP )
{
double d2 = dist2( &P[2 * i], &P[2 * j] );
if( d2 > epsilon_1 )
{
i++;
P[2 * i] = P[2 * j];
P[2 * i + 1] = P[2 * j + 1];
}
j++;
}
// test also the last point with the first one (index 0)
// the first one could be at -PI; last one could be at +PI, according to atan2 span
double d2 = dist2( P, &P[2 * i] ); // check the first and last points (ordered from -pi to +pi)
if( d2 > epsilon_1 )
{
nP = i + 1;
}
else
nP = i; // effectively delete the last point (that would have been the same with first)
if( nP == 0 ) nP = 1; // we should be left with at least one point we already tested if nP is 0 originally
return 0;
}
CartVect moab::IntxUtils::spherical_to_cart | ( | IntxUtils::SphereCoords & | sc | ) | [static] |
Definition at line 762 of file IntxUtils.cpp.
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().
{
CartVect res;
res[0] = sc.R * cos( sc.lat ) * cos( sc.lon ); // x coordinate
res[1] = sc.R * cos( sc.lat ) * sin( sc.lon ); // y
res[2] = sc.R * sin( sc.lat ); // z
return res;
}
void moab::IntxUtils::transform_coordinates | ( | double * | avg_position, |
int | projection_type | ||
) | [static] |
Definition at line 671 of file IntxUtils.cpp.
References decide_gnomonic_plane(), gnomonic_projection(), gnomonic_unroll(), and moab::R.
{
if( projection_type == 1 )
{
double R =
avg_position[0] * avg_position[0] + avg_position[1] * avg_position[1] + avg_position[2] * avg_position[2];
R = sqrt( R );
double lat = asin( avg_position[2] / R );
double lon = atan2( avg_position[1], avg_position[0] );
avg_position[0] = lon;
avg_position[1] = lat;
avg_position[2] = R;
}
else if( projection_type == 2 ) // gnomonic projection
{
CartVect pos( avg_position );
int gplane;
IntxUtils::decide_gnomonic_plane( pos, gplane );
IntxUtils::gnomonic_projection( pos, 1.0, gplane, avg_position[0], avg_position[1] );
avg_position[2] = 0;
IntxUtils::gnomonic_unroll( avg_position[0], avg_position[1], 1.0, gplane );
}
}