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