Compute the polygonal (dual) mesh of the primal simplex grid in 2-D.
To run: ComputeTriDual input_file output_file
An example to demonstrate computing the dual polygonal grid of a triangulation on a spherical surface.
#include <iostream>
#include <vector>
#ifdef MOAB_HAVE_MPI
#endif
{
rval =
mb->get_connectivity( cells, verts );
MB_CHK_SET_ERR( rval,
"Failed to get connectivity" );
std::vector< double* > ccenters;
rval =
iface->get_node_coords( 3, cells.
size(), 0, startv, ccenters );
MB_CHK_SET_ERR( rval,
"Can't get node coords" );
std::vector< int > gids( cells.
size() );
rval =
mb->get_coords( cells, ccenters[0], ccenters[1], ccenters[2] );
MB_CHK_SET_ERR( rval,
"Failed to get coordinates" );
rval =
mb->tag_get_data( gidTag, cells, &gids[0] );
MB_CHK_SET_ERR( rval,
"Can't set global_id tag" );
rval =
mb->add_entities( dual_set, dualverts );
MB_CHK_SET_ERR( rval,
"Can't add entities" );
rval =
mb->tag_set_data( gidTag, dualverts, &gids[0] );
MB_CHK_SET_ERR( rval,
"Can't set global_id tag" );
#define CC( ind ) moab::CartVect( ccenters[0][ind], ccenters[1][ind], ccenters[2][ind] )
#define CCXMY( ind, cv ) \
moab::CartVect( ccenters[0][ind] - ( cv )[0], ccenters[1][ind] - ( cv )[1], ccenters[2][ind] - ( cv )[2] )
std::map< size_t, std::vector< moab::EntityHandle > > polygonConn;
{
std::vector< moab::EntityHandle > adjs;
rval =
mb->get_adjacencies( &vtx, 1, 2,
true, adjs );
MB_CHK_SET_ERR( rval,
"Failed to get adjacencies" );
const size_t nEdges = adjs.size();
double vxyz[3];
rval =
mb->get_coords( &vtx, 1, vxyz );
MB_CHK_SET_ERR( rval,
"Failed to get coordinates" );
double dNode0Mag = node0.
length();
std::vector< double > dAngles;
dAngles.resize( nEdges );
dAngles[0] = 0.0;
for( size_t j = 1; j < nEdges; j++ )
{
double dNodeDiffMag = nodeDiff.
length();
double dSide = nodeCross % nodeDiff;
double dDotNorm = ( node0 % nodeDiff ) / ( dNode0Mag * dNodeDiffMag );
if( dDotNorm > 1.0 )
{
dDotNorm = 1.0;
}
dAngles[j] = acos( dDotNorm );
if( dSide > 0.0 )
{
dAngles[j] = -dAngles[j] + 2.0 * M_PI;
}
}
std::vector< moab::EntityHandle >&
face = polygonConn[nEdges];
if(
face.size() == 0 )
face.reserve( nEdges * verts.
size() / 4 );
face.push_back( dualverts[adjs[0] - svtx] );
double dCurrentAngle = 0.0;
for( size_t j = 1; j < nEdges; j++ )
{
int ixNextNode = 1;
double dNextAngle = 2.0 * M_PI;
for( size_t k = 1; k < nEdges; k++ )
{
if( ( dAngles[k] > dCurrentAngle ) && ( dAngles[k] < dNextAngle ) )
{
ixNextNode = k;
dNextAngle = dAngles[k];
}
}
face.push_back( dualverts[adjs[ixNextNode] - svtx] );
dCurrentAngle = dNextAngle;
}
}
std::map< size_t, std::vector< moab::EntityHandle > >::iterator eit;
for( eit = polygonConn.begin(); eit != polygonConn.end(); ++eit )
{
const size_t nVPerE = eit->first;
const size_t nElePerType = static_cast< int >( eit->second.size() / nVPerE );
std::copy( eit->second.begin(), eit->second.end(), conn );
eit->second.clear();
moab::Range mbcells( starte, starte + nElePerType - 1 );
dualcells.
merge( mbcells );
}
rval =
mb->add_entities( dual_set, dualcells );
MB_CHK_SET_ERR( rval,
"Can't add polygonal entities" );
assert( dualcells.
size() == verts.
size() );
gids.resize( verts.
size() );
rval =
mb->tag_get_data( gidTag, verts, &gids[0] );
MB_CHK_SET_ERR( rval,
"Can't set global_id tag" );
if( gids[0] == gids[1] && gids[0] < 0 )
{
#ifdef MOAB_HAVE_MPI
#else
for( size_t ix = 0; ix < gids.size(); ++ix )
gids[ix] = ix + 1;
rval =
mb->tag_set_data( gidTag, dualcells, &gids[0] );
MB_CHK_SET_ERR( rval,
"Can't set global_id tag" );
std::cout << "GIDs: " << gids[0] << " " << gids[1] << " " << gids[2] << " " << gids[3] << " " << gids[4] << " "
<< gids[5] << "\n";
#endif
}
gids.clear();
rval =
mb->delete_entities( cells );
MB_CHK_SET_ERR( rval,
"Can't remove entities" );
rval =
mb->delete_entities( verts );
MB_CHK_SET_ERR( rval,
"Can't remove entities" );
}
int main(
int argc,
char** argv )
{
if( NULL ==
mb )
return 1;
std::string inputFile = std::string(
MESH_DIR ) +
"/globalmpas_deltri.h5m";
opts.
addOpt< std::string >(
"inFile,i",
"Specify the input file name string ", &inputFile );
#ifdef MOAB_HAVE_HDF5
std::string outputFile = "outDualMesh.h5m";
#else
std::string outputFile = "outDualMesh.vtk";
#endif
opts.
addOpt< std::string >(
"outFile,o",
"Specify the input file name string ", &outputFile );
const char* readopts = "";
rval =
mb->load_file( inputFile.c_str(), &triangle_set, readopts );
MB_CHK_SET_ERR( rval,
"Failed to read" );
rval =
mb->get_entities_by_dimension( triangle_set, 2, cells );
MB_CHK_SET_ERR( rval,
"Failed to get cells" );
std::cout <<
"Original number of triangular cells : " << cells.
size() <<
"\n";
rval =
mb->write_file( outputFile.c_str() );
MB_CHK_SET_ERR( rval,
"Failed to write new file" );
rval =
mb->get_entities_by_dimension( dual_set, 2, cells );
MB_CHK_SET_ERR( rval,
"Failed to get cells" );
std::cout <<
"Wrote the dual mesh: " << outputFile <<
" containing " << cells.
size() <<
" polygonal cells\n";
return 0;
}