MOAB: Mesh Oriented datABase  (version 5.3.0)
IntxRllCssphere.cpp
Go to the documentation of this file.
00001 /*
00002  * IntxRllCssphere.cpp
00003  *
00004  *  Created on: Aug 8, 2014
00005  *      Author: iulian
00006  */
00007 
00008 #include "moab/IntxMesh/IntxRllCssphere.hpp"
00009 #include "moab/GeomUtil.hpp"
00010 #include "moab/IntxMesh/IntxUtils.hpp"
00011 
00012 namespace moab
00013 {
00014 
00015 IntxRllCssphere::IntxRllCssphere( Interface* mbimpl ) : Intx2Mesh( mbimpl ), R( 0.0 ), plane( 0 ) {}
00016 
00017 IntxRllCssphere::~IntxRllCssphere() {}
00018 
00019 /*
00020  * return also the area for robustness verification
00021  */
00022 double IntxRllCssphere::setup_tgt_cell( EntityHandle tgt, int& nsTgt )
00023 {
00024     // get coordinates of the tgt quad, to decide the gnomonic plane
00025     double cellArea = 0;
00026 
00027     int num_nodes;
00028     ErrorCode rval = mb->get_connectivity( tgt, tgtConn, num_nodes );
00029 
00030     if( MB_SUCCESS != rval ) return 1;
00031     nsTgt = num_nodes;
00032     // these edges will never be polygons, only quads or triangles
00033 
00034     // CartVect coords[4];
00035     rval = mb->get_coords( tgtConn, nsTgt, &( tgtCoords[0][0] ) );
00036     if( MB_SUCCESS != rval ) return 1;
00037     CartVect middle = tgtCoords[0];
00038     for( int i = 1; i < nsTgt; i++ )
00039         middle += tgtCoords[i];
00040     middle = 1. / nsTgt * middle;
00041 
00042     IntxUtils::decide_gnomonic_plane( middle, plane );  // output the plane
00043     for( int j = 0; j < nsTgt; j++ )
00044     {
00045         // populate coords in the plane for intersection
00046         // they should be oriented correctly, positively
00047         int rc = IntxUtils::gnomonic_projection( tgtCoords[j], R, plane, tgtCoords2D[2 * j], tgtCoords2D[2 * j + 1] );
00048         if( rc != 0 ) return 1;
00049     }
00050 
00051     for( int j = 1; j < nsTgt - 1; j++ )
00052         cellArea += IntxUtils::area2D( &tgtCoords2D[0], &tgtCoords2D[2 * j], &tgtCoords2D[2 * j + 2] );
00053 
00054     // take tgt coords in order and compute area in plane
00055     return cellArea;
00056 }
00057 
00058 /* the elements are convex for sure, then do a gnomonic projection of both,
00059  *  compute intersection in the plane, then go back to the sphere for the points
00060  *  */
00061 ErrorCode IntxRllCssphere::computeIntersectionBetweenTgtAndSrc( EntityHandle tgt, EntityHandle src, double* P, int& nP,
00062                                                                 double& area, int markb[MAXEDGES], int markr[MAXEDGES],
00063                                                                 int& nsSrc, int& nsTgt, bool check_boxes_first )
00064 {
00065     // the area will be used from now on, to see how well we fill the tgt cell with polygons
00066     // the points will be at most 40; they will describe a convex patch, after the points will be
00067     // ordered and collapsed (eliminate doubles)
00068 
00069     // CartVect srccoords[4];
00070     int num_nodes  = 0;
00071     ErrorCode rval = mb->get_connectivity( src, srcConn, num_nodes );MB_CHK_ERR( rval );
00072 
00073     nsSrc = num_nodes;
00074     rval  = mb->get_coords( srcConn, nsSrc, &( srcCoords[0][0] ) );MB_CHK_ERR( rval );
00075 
00076     // determine the type of edge: const lat or not?
00077     // just look at the consecutive z coordinates for the edge
00078     for( int i = 0; i < nsSrc; i++ )
00079     {
00080         int nexti = ( i + 1 ) % nsSrc;
00081         if( fabs( srcCoords[i][2] - srcCoords[nexti][2] ) < 1.e-6 )
00082             srcEdgeType[i] = 1;
00083         else
00084             srcEdgeType[i] = 0;
00085     }
00086     area = 0.;
00087     nP   = 0;  // number of intersection points we are marking the boundary of src!
00088     if( check_boxes_first )
00089     {
00090         // look at the boxes formed with vertices; if they are far away, return false early
00091         // make sure the tgt is setup already
00092         setup_tgt_cell( tgt, nsTgt );  // we do not need area here
00093         if( !GeomUtil::bounding_boxes_overlap( tgtCoords, nsTgt, srcCoords, nsSrc, box_error ) )
00094             return MB_SUCCESS;  // no error, but no intersection, decide early to get out
00095     }
00096 #ifdef ENABLE_DEBUG
00097     if( dbg_1 )
00098     {
00099         std::cout << "tgt " << mb->id_from_handle( tgt ) << "\n";
00100         for( int j = 0; j < nsTgt; j++ )
00101         {
00102             std::cout << tgtCoords[j] << "\n";
00103         }
00104         std::cout << "src " << mb->id_from_handle( src ) << "\n";
00105         for( int j = 0; j < nsSrc; j++ )
00106         {
00107             std::cout << srcCoords[j] << "\n";
00108         }
00109         mb->list_entities( &tgt, 1 );
00110         mb->list_entities( &src, 1 );
00111     }
00112 #endif
00113     for( int j = 0; j < nsSrc; j++ )
00114     {
00115         rval = IntxUtils::gnomonic_projection( srcCoords[j], R, plane, srcCoords2D[2 * j], srcCoords2D[2 * j + 1] );MB_CHK_ERR( rval );
00116     }
00117 #ifdef ENABLE_DEBUG
00118     if( dbg_1 )
00119     {
00120         std::cout << "gnomonic plane: " << plane << "\n";
00121         std::cout << " tgt                                src\n";
00122         for( int j = 0; j < nsTgt; j++ )
00123         {
00124             std::cout << tgtCoords2D[2 * j] << " " << tgtCoords2D[2 * j + 1] << "\n";
00125         }
00126         for( int j = 0; j < nsSrc; j++ )
00127         {
00128             std::cout << srcCoords2D[2 * j] << " " << srcCoords2D[2 * j + 1] << "\n";
00129         }
00130     }
00131 #endif
00132     rval = IntxUtils::EdgeIntxRllCs( srcCoords2D, srcCoords, srcEdgeType, nsSrc, tgtCoords2D, tgtCoords, nsTgt, markb,
00133                                      markr, plane, R, P, nP );MB_CHK_ERR( rval );
00134 
00135     int side[MAXEDGES] = { 0 };  // this refers to what side? src or tgt?// more tolerant here with epsilon_area
00136     int extraPoints    = IntxUtils::borderPointsOfXinY2( srcCoords2D, nsSrc, tgtCoords2D, nsTgt, &( P[2 * nP] ), side,
00137                                                       2 * epsilon_area );
00138     if( extraPoints >= 1 )
00139     {
00140         for( int k = 0; k < nsSrc; k++ )
00141         {
00142             if( side[k] )
00143             {
00144                 // this means that vertex k of src is inside convex tgt; mark edges k-1 and k in
00145                 // src,
00146                 //   as being "intersected" by tgt; (even though they might not be intersected by
00147                 //   other edges, the fact that their apex is inside, is good enough)
00148                 markb[k] = 1;
00149                 markb[( k + nsSrc - 1 ) % nsSrc] =
00150                     1;  // it is the previous edge, actually, but instead of doing -1, it is
00151                 // better to do modulo +3 (modulo 4)
00152                 // null side b for next call
00153                 side[k] = 0;
00154             }
00155         }
00156     }
00157     nP += extraPoints;
00158 
00159     extraPoints =
00160         IntxUtils::borderPointsOfCSinRLL( tgtCoords, tgtCoords2D, nsTgt, srcCoords, nsSrc, srcEdgeType, &( P[2 * nP] ),
00161                                           side,
00162                                           100 * epsilon_area );  // we need to compare with 0 a volume from 3 vector
00163                                                                  // product; // lots of round off errors at stake
00164     if( extraPoints >= 1 )
00165     {
00166         for( int k = 0; k < nsTgt; k++ )
00167         {
00168             if( side[k] )
00169             {
00170                 // this is to mark that tgt edges k-1 and k are intersecting src
00171                 markr[k] = 1;
00172                 markr[( k + nsTgt - 1 ) % nsTgt] =
00173                     1;  // it is the previous edge, actually, but instead of doing -1, it is
00174                 // better to do modulo +3 (modulo 4)
00175                 // null side b for next call
00176             }
00177         }
00178     }
00179     nP += extraPoints;
00180 
00181     // now sort and orient the points in P, such that they are forming a convex polygon
00182     // this will be the foundation of our new mesh
00183     // this works if the polygons are convex
00184     IntxUtils::SortAndRemoveDoubles2( P, nP, epsilon_1 );  // nP should be at most 8 in the end ?
00185     // if there are more than 3 points, some area will be positive
00186 
00187     if( nP >= 3 )
00188     {
00189         for( int k = 1; k < nP - 1; k++ )
00190             area += IntxUtils::area2D( P, &P[2 * k], &P[2 * k + 2] );
00191     }
00192 
00193     return MB_SUCCESS;  // no error
00194 }
00195 
00196 // this method will also construct the triangles/polygons in the new mesh
00197 // if we accept planar polygons, we just save them
00198 // also, we could just create new vertices every time, and merge only in the end;
00199 // could be too expensive, and the tolerance for merging could be an
00200 // interesting topic
00201 ErrorCode IntxRllCssphere::findNodes( EntityHandle tgt, int nsTgt, EntityHandle src, int nsSrc, double* iP, int nP )
00202 {
00203     // first of all, check against tgt and src vertices
00204     //
00205 #ifdef ENABLE_DEBUG
00206     if( dbg_1 )
00207     {
00208         std::cout << "tgt, src, nP, P " << mb->id_from_handle( tgt ) << " " << mb->id_from_handle( src ) << " " << nP
00209                   << "\n";
00210         for( int n = 0; n < nP; n++ )
00211             std::cout << " \t" << iP[2 * n] << "\t" << iP[2 * n + 1] << "\n";
00212     }
00213 #endif
00214 
00215     // get the edges for the tgt triangle; the extra points will be on those edges, saved as
00216     // lists (unordered)
00217 
00218     // first get the list of edges adjacent to the tgt cell
00219     // use the neighTgtEdgeTag
00220     EntityHandle adjTgtEdges[MAXEDGES];
00221     ErrorCode rval = mb->tag_get_data( neighTgtEdgeTag, &tgt, 1, &( adjTgtEdges[0] ) );MB_CHK_SET_ERR( rval, "can't get edge tgt tag" );
00222     // we know that we have only nsTgt edges here; [nsTgt, MAXEDGES) are ignored, but it is small
00223     // potatoes
00224 
00225     // these will be in the new mesh, mbOut
00226     // some of them will be handles to the initial vertices from src or tgt meshes (lagr or euler)
00227 
00228     EntityHandle* foundIds = new EntityHandle[nP];
00229     for( int i = 0; i < nP; i++ )
00230     {
00231         double* pp = &iP[2 * i];  // iP+2*i
00232         // project the point back on the sphere
00233         CartVect pos;
00234         IntxUtils::reverse_gnomonic_projection( pp[0], pp[1], R, plane, pos );
00235         int found = 0;
00236         // first, are they on vertices from tgt or src?
00237         // priority is the tgt mesh (mb2?)
00238         int j                = 0;
00239         EntityHandle outNode = (EntityHandle)0;
00240         for( j = 0; j < nsTgt && !found; j++ )
00241         {
00242             // int node = tgtTri.v[j];
00243             double d2 = IntxUtils::dist2( pp, &tgtCoords2D[2 * j] );
00244             if( d2 < epsilon_1 )
00245             {
00246 
00247                 foundIds[i] = tgtConn[j];  // no new node
00248                 found       = 1;
00249 #ifdef ENABLE_DEBUG
00250                 if( dbg_1 )
00251                     std::cout << "  tgt node j:" << j << " id:" << mb->id_from_handle( tgtConn[j] )
00252                               << " 2d coords:" << tgtCoords2D[2 * j] << "  " << tgtCoords2D[2 * j + 1] << " d2: " << d2
00253                               << " \n";
00254 #endif
00255             }
00256         }
00257 
00258         for( j = 0; j < nsSrc && !found; j++ )
00259         {
00260             // int node = srcTri.v[j];
00261             double d2 = IntxUtils::dist2( pp, &srcCoords2D[2 * j] );
00262             if( d2 < epsilon_1 )
00263             {
00264                 // suspect is srcConn[j] corresponding in mbOut
00265 
00266                 foundIds[i] = srcConn[j];  // no new node
00267                 found       = 1;
00268 #ifdef ENABLE_DEBUG
00269                 if( dbg_1 )
00270                     std::cout << "  src node " << j << " " << mb->id_from_handle( srcConn[j] ) << " d2:" << d2 << " \n";
00271 #endif
00272             }
00273         }
00274         if( !found )
00275         {
00276             // find the edge it belongs, first, on the tgt element
00277             //
00278             for( j = 0; j < nsTgt; j++ )
00279             {
00280                 int j1      = ( j + 1 ) % nsTgt;
00281                 double area = IntxUtils::area2D( &tgtCoords2D[2 * j], &tgtCoords2D[2 * j1], pp );
00282 #ifdef ENABLE_DEBUG
00283                 if( dbg_1 )
00284                     std::cout << "   edge " << j << ": " << mb->id_from_handle( adjTgtEdges[j] ) << " " << tgtConn[j]
00285                               << " " << tgtConn[j1] << "  area : " << area << "\n";
00286 #endif
00287                 if( fabs( area ) < epsilon_1 / 2 )
00288                 {
00289                     // found the edge; now find if there is a point in the list here
00290                     // std::vector<EntityHandle> * expts = extraNodesMap[tgtEdges[j]];
00291                     int indx = TgtEdges.index( adjTgtEdges[j] );
00292                     // CID 181167 (#1 of 1): Argument cannot be negative (NEGATIVE_RETURNS)
00293                     if( indx < 0 )
00294                     {
00295                         std::cerr << " error in adjacent tgt edge: " << mb->id_from_handle( adjTgtEdges[j] ) << "\n";
00296                         delete[] foundIds;
00297                         return MB_FAILURE;
00298                     }
00299                     std::vector< EntityHandle >* expts = extraNodesVec[indx];
00300                     // if the points pp is between extra points, then just give that id
00301                     // if not, create a new point, (check the id)
00302                     // get the coordinates of the extra points so far
00303                     int nbExtraNodesSoFar = expts->size();
00304                     if( nbExtraNodesSoFar > 0 )
00305                     {
00306                         CartVect* coords1 = new CartVect[nbExtraNodesSoFar];
00307                         mb->get_coords( &( *expts )[0], nbExtraNodesSoFar, &( coords1[0][0] ) );
00308                         // std::list<int>::iterator it;
00309                         for( int k = 0; k < nbExtraNodesSoFar && !found; k++ )
00310                         {
00311                             // int pnt = *it;
00312                             double d2 = ( pos - coords1[k] ).length_squared();
00313                             if( d2 < epsilon_1 )
00314                             {
00315                                 found       = 1;
00316                                 foundIds[i] = ( *expts )[k];
00317 #ifdef ENABLE_DEBUG
00318                                 if( dbg_1 ) std::cout << " found node:" << foundIds[i] << std::endl;
00319 #endif
00320                             }
00321                         }
00322                         delete[] coords1;
00323                     }
00324                     if( !found )
00325                     {
00326                         // create a new point in 2d (at the intersection)
00327                         // foundIds[i] = m_num2dPoints;
00328                         // expts.push_back(m_num2dPoints);
00329                         // need to create a new node in mbOut
00330                         // this will be on the edge, and it will be added to the local list
00331                         mb->create_vertex( pos.array(), outNode );
00332                         ( *expts ).push_back( outNode );
00333                         foundIds[i] = outNode;
00334                         found       = 1;
00335 #ifdef ENABLE_DEBUG
00336                         if( dbg_1 ) std::cout << " new node: " << outNode << std::endl;
00337 #endif
00338                     }
00339                 }
00340             }
00341         }
00342         if( !found )
00343         {
00344             std::cout << " tgt quad: ";
00345             for( int j1 = 0; j1 < nsTgt; j1++ )
00346             {
00347                 std::cout << tgtCoords2D[2 * j1] << " " << tgtCoords2D[2 * j1 + 1] << "\n";
00348             }
00349             std::cout << " a point pp is not on a tgt quad " << *pp << " " << pp[1] << " tgt quad "
00350                       << mb->id_from_handle( tgt ) << " \n";
00351             delete[] foundIds;
00352             return MB_FAILURE;
00353         }
00354     }
00355 #ifdef ENABLE_DEBUG
00356     if( dbg_1 )
00357     {
00358         std::cout << " candidate polygon: nP" << nP << " plane: " << plane << "\n";
00359         for( int i1 = 0; i1 < nP; i1++ )
00360             std::cout << iP[2 * i1] << " " << iP[2 * i1 + 1] << " " << foundIds[i1] << "\n";
00361     }
00362 #endif
00363     // first, find out if we have nodes collapsed; shrink them
00364     // we may have to reduce nP
00365     // it is possible that some nodes are collapsed after intersection only
00366     // nodes will always be in order (convex intersection)
00367     correct_polygon( foundIds, nP );
00368     // now we can build the triangles, from P array, with foundIds
00369     // we will put them in the out set
00370     if( nP >= 3 )
00371     {
00372         EntityHandle polyNew;
00373         mb->create_element( MBPOLYGON, foundIds, nP, polyNew );
00374         mb->add_entities( outSet, &polyNew, 1 );
00375 
00376         // tag it with the index ids from tgt and src sets
00377         int id = rs1.index( src );  // index starts from 0
00378         mb->tag_set_data( srcParentTag, &polyNew, 1, &id );
00379         id = rs2.index( tgt );
00380         mb->tag_set_data( tgtParentTag, &polyNew, 1, &id );
00381 
00382         counting++;
00383         mb->tag_set_data( countTag, &polyNew, 1, &counting );
00384 
00385 #ifdef ENABLE_DEBUG
00386         if( dbg_1 )
00387         {
00388 
00389             std::cout << "Counting: " << counting << "\n";
00390             std::cout << " polygon " << mb->id_from_handle( polyNew ) << "  nodes: " << nP << " :";
00391             for( int i1 = 0; i1 < nP; i1++ )
00392                 std::cout << " " << mb->id_from_handle( foundIds[i1] );
00393             std::cout << " plane: " << plane << "\n";
00394             std::vector< CartVect > posi( nP );
00395             mb->get_coords( foundIds, nP, &( posi[0][0] ) );
00396             for( int i1 = 0; i1 < nP; i1++ )
00397                 std::cout << foundIds[i1] << " " << posi[i1] << "\n";
00398 
00399             std::stringstream fff;
00400             fff << "file0" << counting << ".vtk";
00401             mb->write_mesh( fff.str().c_str(), &outSet, 1 );
00402         }
00403 #endif
00404     }
00405     // disable_debug();
00406     delete[] foundIds;
00407     foundIds = NULL;
00408     return MB_SUCCESS;
00409 }
00410 
00411 } /* namespace moab */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines