LCOV - code coverage report
Current view: top level - src - FBEngine.cpp (source / functions) Hit Total Coverage
Test: coverage_sk.info Lines: 1558 1941 80.3 %
Date: 2020-12-16 07:07:30 Functions: 53 68 77.9 %
Branches: 1764 5516 32.0 %

           Branch data     Line data    Source code
       1                 :            : #include <iostream>
       2                 :            : #include <map>
       3                 :            : 
       4                 :            : #include "moab/FBEngine.hpp"
       5                 :            : #include "moab/Interface.hpp"
       6                 :            : #include "moab/GeomTopoTool.hpp"
       7                 :            : #include "moab/GeomUtil.hpp"
       8                 :            : #include "moab/OrientedBoxTreeTool.hpp"
       9                 :            : 
      10                 :            : #include <stdlib.h>
      11                 :            : #include <cstring>
      12                 :            : #include <map>
      13                 :            : #include <set>
      14                 :            : #include <queue>
      15                 :            : #include <algorithm>
      16                 :            : #include "assert.h"
      17                 :            : 
      18                 :            : #include "SmoothCurve.hpp"
      19                 :            : #include "SmoothFace.hpp"
      20                 :            : 
      21                 :            : // this is just to replace MBI with moab interface, which is _mbImpl in this class
      22                 :            : #define MBI _mbImpl
      23                 :            : #define MBERRORR( rval, STR )              \
      24                 :            :     {                                      \
      25                 :            :         if( MB_SUCCESS != rval )           \
      26                 :            :         {                                  \
      27                 :            :             std::cout << STR << std::endl; \
      28                 :            :             return rval;                   \
      29                 :            :         }                                  \
      30                 :            :     }
      31                 :            : 
      32                 :            : namespace moab
      33                 :            : {
      34                 :            : 
      35                 :            : // some tolerances for ray tracing and geometry intersections
      36                 :            : // these are involved in ray tracing, at least
      37                 :            : 
      38                 :            : double tolerance         = 0.01;  // TODO: how is this used ????
      39                 :            : double tolerance_segment = 0.01;  // for segments intersection, points collapse, area coordinates for triangles
      40                 :            : // it should be a relative, not an absolute value
      41                 :            : // as this splitting operation can create small edges, it should be relatively high
      42                 :            : // or, it should be coordinated with the decimation errors
      43                 :            : // we really just want to preserve the integrity of the mesh, we should avoid creating small edges
      44                 :            : // or angles
      45                 :            : const bool Debug_surf_eval = false;
      46                 :            : bool debug_splits          = false;
      47                 :            : 
      48                 :            : // will compute intersection between a segment and slice of a plane
      49                 :            : // output is the intersection point
      50                 :       2834 : bool intersect_segment_and_plane_slice( CartVect& from, CartVect& to, CartVect& p1, CartVect& p2, CartVect&,
      51                 :            :                                         CartVect& normPlane, CartVect& intx_point, double& parPos )
      52                 :            : {
      53                 :            :     //
      54                 :            :     // plane eq is normPlane % r + d = 0, or normPlane % r - normPlane%p1 = 0
      55         [ +  - ]:       2834 :     double dd      = -normPlane % p1;
      56                 :       2834 :     double valFrom = normPlane % from + dd;
      57                 :       2834 :     double valTo   = normPlane % to + dd;
      58                 :            : 
      59         [ -  + ]:       2834 :     if( fabs( valFrom ) < tolerance_segment )
      60                 :            :     {
      61                 :          0 :         intx_point   = from;
      62                 :          0 :         parPos       = 0.;
      63 [ #  # ][ #  # ]:          0 :         double proj1 = ( intx_point - p1 ) % ( p2 - p1 );
      64 [ #  # ][ #  # ]:          0 :         double proj2 = ( intx_point - p2 ) % ( p1 - p2 );
      65 [ #  # ][ #  # ]:          0 :         if( proj1 <= -tolerance_segment || proj2 <= -tolerance_segment ) return false;
      66         [ #  # ]:          0 :         if( debug_splits ) std::cout << "intx : " << intx_point << "\n";
      67                 :          0 :         return true;
      68                 :            :     }
      69         [ +  + ]:       2834 :     if( fabs( valTo ) < tolerance_segment )
      70                 :            :     {
      71                 :         15 :         intx_point   = to;
      72                 :         15 :         parPos       = 1;
      73 [ +  - ][ +  - ]:         15 :         double proj1 = ( intx_point - p1 ) % ( p2 - p1 );
      74 [ +  - ][ +  - ]:         15 :         double proj2 = ( intx_point - p2 ) % ( p1 - p2 );
      75 [ +  - ][ -  + ]:         15 :         if( proj1 <= -tolerance_segment || proj2 <= -tolerance_segment ) return false;
      76         [ -  + ]:         15 :         if( debug_splits ) std::cout << "intx : " << intx_point << "\n";
      77                 :         15 :         return true;
      78                 :            :     }
      79         [ +  + ]:       2819 :     if( valFrom * valTo > 0 ) return false;  // no intersection, although it could be very close
      80                 :            :     // else, it could intersect the plane; check for the slice too.
      81                 :       1755 :     parPos     = valFrom / ( valFrom - valTo );  // this is 0 for valFrom 0, 1 for valTo 0
      82 [ +  - ][ +  - ]:       1755 :     intx_point = from + ( to - from ) * parPos;
      83                 :            :     // now check if the intx_point is indeed between p1 and p2 in the slice.
      84 [ +  - ][ +  - ]:       1755 :     double proj1 = ( intx_point - p1 ) % ( p2 - p1 );
      85 [ +  - ][ +  - ]:       1755 :     double proj2 = ( intx_point - p2 ) % ( p1 - p2 );
      86 [ +  + ][ -  + ]:       1755 :     if( proj1 <= -tolerance_segment || proj2 <= -tolerance_segment ) return false;
      87                 :            : 
      88         [ -  + ]:       1747 :     if( debug_splits ) std::cout << "intx : " << intx_point << "\n";
      89                 :       2834 :     return true;
      90                 :            : }
      91                 :            : 
      92                 :         15 : ErrorCode area_coordinates( Interface* mbi, EntityHandle tri, CartVect& pnt, double* area_coord,
      93                 :            :                             EntityHandle& boundary_handle )
      94                 :            : {
      95                 :            : 
      96                 :            :     int nnodes;
      97                 :            :     const EntityHandle* conn3;
      98         [ +  - ]:         15 :     ErrorCode rval = mbi->get_connectivity( tri, conn3, nnodes );
      99 [ -  + ][ #  # ]:         15 :     MBERRORR( rval, "Failed to get connectivity" );
                 [ #  # ]
     100         [ -  + ]:         15 :     assert( 3 == nnodes );
     101 [ +  - ][ +  + ]:         60 :     CartVect P[3];
     102         [ +  - ]:         15 :     rval = mbi->get_coords( conn3, nnodes, (double*)&P[0] );
     103 [ -  + ][ #  # ]:         15 :     MBERRORR( rval, "Failed to get coordinates" );
                 [ #  # ]
     104                 :            : 
     105         [ +  - ]:         15 :     CartVect r0( P[0] - pnt );
     106         [ +  - ]:         15 :     CartVect r1( P[1] - pnt );
     107         [ +  - ]:         15 :     CartVect r2( P[2] - pnt );
     108         [ -  + ]:         15 :     if( debug_splits )
     109                 :            :     {
     110 [ #  # ][ #  # ]:          0 :         std::cout << " nodes:" << conn3[0] << " " << conn3[1] << " " << conn3[2] << "\n";
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     111 [ #  # ][ #  # ]:          0 :         std::cout << " distances: " << r0.length() << " " << r1.length() << " " << r2.length() << "\n";
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     112                 :            :     }
     113 [ +  - ][ +  + ]:         15 :     if( r0.length() < tolerance_segment )
     114                 :            :     {
     115                 :          1 :         area_coord[0]   = 1.;
     116                 :          1 :         area_coord[1]   = 0.;
     117                 :          1 :         area_coord[2]   = 0.;
     118                 :          1 :         boundary_handle = conn3[0];
     119                 :          1 :         return MB_SUCCESS;
     120                 :            :     }
     121 [ +  - ][ +  + ]:         14 :     if( r1.length() < tolerance_segment )
     122                 :            :     {
     123                 :          2 :         area_coord[0]   = 0.;
     124                 :          2 :         area_coord[1]   = 1.;
     125                 :          2 :         area_coord[2]   = 0.;
     126                 :          2 :         boundary_handle = conn3[1];
     127                 :          2 :         return MB_SUCCESS;
     128                 :            :     }
     129 [ +  - ][ +  + ]:         12 :     if( r2.length() < tolerance_segment )
     130                 :            :     {
     131                 :          3 :         area_coord[0]   = 0.;
     132                 :          3 :         area_coord[1]   = 0.;
     133                 :          3 :         area_coord[2]   = 1.;
     134                 :          3 :         boundary_handle = conn3[2];
     135                 :          3 :         return MB_SUCCESS;
     136                 :            :     }
     137                 :            : 
     138         [ +  - ]:          9 :     CartVect v1( P[1] - P[0] );
     139         [ +  - ]:          9 :     CartVect v2( P[2] - P[0] );
     140                 :            : 
     141 [ +  - ][ +  - ]:          9 :     double areaDouble = ( v1 * v2 ).length();  // the same for CartVect
     142 [ -  + ][ #  # ]:          9 :     if( areaDouble < tolerance_segment * tolerance_segment ) { MBERRORR( MB_FAILURE, "area of triangle too small" ); }
                 [ #  # ]
     143 [ +  - ][ +  - ]:          9 :     area_coord[0] = ( r1 * r2 ).length() / areaDouble;
     144 [ +  - ][ +  - ]:          9 :     area_coord[1] = ( r2 * r0 ).length() / areaDouble;
     145 [ +  - ][ +  - ]:          9 :     area_coord[2] = ( r0 * r1 ).length() / areaDouble;
     146                 :            : 
     147         [ -  + ]:          9 :     if( fabs( area_coord[0] + area_coord[1] + area_coord[2] - 1 ) > tolerance_segment )
     148 [ #  # ][ #  # ]:          0 :     { MBERRORR( MB_FAILURE, "point outside triangle" ); }
     149                 :            :     // the tolerance is used here for area coordinates (0 to 1), and in other
     150                 :            :     // parts it is used as an absolute distance; pretty inconsistent.
     151                 :          9 :     bool side0 = ( area_coord[0] < tolerance_segment );
     152                 :          9 :     bool side1 = ( area_coord[1] < tolerance_segment );
     153                 :          9 :     bool side2 = ( area_coord[2] < tolerance_segment );
     154 [ +  - ][ +  - ]:          9 :     if( !side0 && !side1 && !side2 ) return MB_SUCCESS;  // interior point
                 [ +  + ]
     155                 :            :     // now, find out what boundary is in question
     156                 :            :     // first, get all edges, in order
     157         [ +  - ]:          2 :     std::vector< EntityHandle > edges;
     158                 :            :     EntityHandle nn2[2];
     159         [ +  + ]:          8 :     for( int i = 0; i < 3; i++ )
     160                 :            :     {
     161                 :          6 :         nn2[0] = conn3[( i + 1 ) % 3];
     162                 :          6 :         nn2[1] = conn3[( i + 2 ) % 3];
     163         [ +  - ]:          6 :         std::vector< EntityHandle > adjacent;
     164         [ +  - ]:          6 :         rval = mbi->get_adjacencies( nn2, 2, 1, false, adjacent, Interface::INTERSECT );
     165 [ -  + ][ #  # ]:          6 :         MBERRORR( rval, "Failed to get edges" );
                 [ #  # ]
     166 [ -  + ][ #  # ]:          6 :         if( adjacent.size() != 1 ) MBERRORR( MB_FAILURE, "Failed to get adjacent edges" );
                 [ #  # ]
     167                 :            :         // should be only one edge here
     168 [ +  - ][ +  - ]:          6 :         edges.push_back( adjacent[0] );
                 [ +  - ]
     169                 :          6 :     }
     170                 :            : 
     171 [ -  + ][ #  # ]:          2 :     if( side0 ) boundary_handle = edges[0];
     172 [ -  + ][ #  # ]:          2 :     if( side1 ) boundary_handle = edges[1];
     173 [ +  - ][ +  - ]:          2 :     if( side2 ) boundary_handle = edges[2];
     174                 :            : 
     175                 :         15 :     return MB_SUCCESS;
     176                 :            : }
     177                 :            : 
     178                 :         12 : FBEngine::FBEngine( Interface* impl, GeomTopoTool* topoTool, const bool smooth )
     179                 :            :     : _mbImpl( impl ), _my_geomTopoTool( topoTool ), _t_created( false ), _smooth( smooth ), _initialized( false ),
     180 [ +  - ][ +  + ]:         72 :       _smthFace( NULL ), _smthCurve( NULL )
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  -  
          #  #  #  #  #  
                      # ]
     181                 :            : {
     182         [ +  + ]:         12 :     if( !_my_geomTopoTool )
     183                 :            :     {
     184 [ +  - ][ +  - ]:         11 :         _my_geomTopoTool = new GeomTopoTool( _mbImpl );
     185                 :         11 :         _t_created       = true;
     186                 :            :     }
     187                 :            :     // should this be part of the constructor or not?
     188                 :            :     // Init();
     189         [ #  # ]:         12 : }
     190                 :         84 : FBEngine::~FBEngine()
     191                 :            : {
     192                 :         12 :     clean();
     193                 :         12 :     _smooth = false;
     194 [ +  - ][ +  + ]:         72 : }
     195                 :            : 
     196                 :         12 : void FBEngine::clean()
     197                 :            : {
     198         [ +  + ]:         12 :     if( _smooth )
     199                 :            :     {
     200                 :          8 :         _faces.clear();
     201                 :          8 :         _edges.clear();
     202                 :          8 :         int size1 = _my_gsets[1].size();
     203                 :          8 :         int i     = 0;
     204         [ +  + ]:         38 :         for( i = 0; i < size1; i++ )
     205         [ +  - ]:         30 :             delete _smthCurve[i];
     206         [ +  - ]:          8 :         delete[] _smthCurve;
     207                 :          8 :         _smthCurve = NULL;
     208                 :          8 :         size1      = _my_gsets[2].size();
     209         [ +  + ]:         20 :         for( i = 0; i < size1; i++ )
     210         [ +  - ]:         12 :             delete _smthFace[i];
     211         [ +  - ]:          8 :         delete[] _smthFace;
     212                 :          8 :         _smthFace = NULL;
     213                 :            :         //_smooth = false;
     214                 :            :     }
     215                 :            : 
     216         [ +  + ]:         72 :     for( int j = 0; j < 5; j++ )
     217                 :         60 :         _my_gsets[j].clear();
     218 [ +  + ][ +  - ]:         12 :     if( _t_created ) delete _my_geomTopoTool;
     219                 :         12 :     _my_geomTopoTool = NULL;
     220                 :         12 :     _t_created       = false;
     221                 :         12 : }
     222                 :            : 
     223                 :         11 : ErrorCode FBEngine::Init()
     224                 :            : {
     225         [ +  + ]:         11 :     if( !_initialized )
     226                 :            :     {
     227         [ -  + ]:         10 :         if( !_my_geomTopoTool ) return MB_FAILURE;
     228                 :            : 
     229                 :         10 :         ErrorCode rval = _my_geomTopoTool->find_geomsets( _my_gsets );
     230         [ -  + ]:         10 :         assert( rval == MB_SUCCESS );
     231         [ -  + ]:         10 :         if( MB_SUCCESS != rval ) { return rval; }
     232                 :            : 
     233                 :         10 :         rval = split_quads();
     234         [ -  + ]:         10 :         assert( rval == MB_SUCCESS );
     235                 :            : 
     236                 :         10 :         rval = _my_geomTopoTool->construct_obb_trees();
     237         [ -  + ]:         10 :         assert( rval == MB_SUCCESS );
     238                 :            : 
     239         [ +  + ]:         10 :         if( _smooth ) rval = initializeSmoothing();
     240         [ -  + ]:         10 :         assert( rval == MB_SUCCESS );
     241                 :            : 
     242                 :         10 :         _initialized = true;
     243                 :            :     }
     244                 :         11 :     return MB_SUCCESS;
     245                 :            : }
     246                 :          8 : ErrorCode FBEngine::initializeSmoothing()
     247                 :            : {
     248                 :            :     //
     249                 :            :     /*ErrorCode rval = Init();
     250                 :            :      MBERRORR(rval, "failed initialize");*/
     251                 :            :     // first of all, we need to retrieve all the surfaces from the (root) set
     252                 :            :     // in icesheet_test we use iGeom, but maybe that is a stretch
     253                 :            :     // get directly the sets with geom dim 2, and from there create the SmoothFace
     254                 :            :     Tag geom_tag;
     255         [ +  - ]:          8 :     ErrorCode rval = MBI->tag_get_handle( GEOM_DIMENSION_TAG_NAME, 1, MB_TYPE_INTEGER, geom_tag );
     256 [ -  + ][ #  # ]:          8 :     MBERRORR( rval, "can't get geom tag" );
                 [ #  # ]
     257                 :            : 
     258         [ +  - ]:          8 :     int numSurfaces = _my_gsets[2].size();
     259                 :            :     // SmoothFace ** smthFace = new SmoothFace *[numSurfaces];
     260 [ +  - ][ +  - ]:          8 :     _smthFace = new SmoothFace*[numSurfaces];
     261                 :            : 
     262                 :            :     // there should also be a map from surfaces to evaluators
     263                 :            :     // std::map<MBEntityHandle, SmoothFace*> mapSurfaces;
     264                 :            : 
     265                 :          8 :     int i = 0;
     266         [ +  - ]:          8 :     Range::iterator it;
     267 [ +  - ][ +  - ]:         20 :     for( it = _my_gsets[2].begin(); it != _my_gsets[2].end(); ++it, i++ )
         [ +  - ][ +  - ]
                 [ +  + ]
     268                 :            :     {
     269         [ +  - ]:         12 :         EntityHandle face = *it;
     270 [ +  - ][ +  - ]:         12 :         _smthFace[i] = new SmoothFace( MBI, face, _my_geomTopoTool );  // geom topo tool will be used for searching,
     271                 :            :         // among other things; also for senses in edge sets...
     272         [ +  - ]:         12 :         _faces[face] = _smthFace[i];
     273                 :            :     }
     274                 :            : 
     275         [ +  - ]:          8 :     int numCurves = _my_gsets[1].size();  // csets.size();
     276                 :            :     // SmoothCurve ** smthCurve = new SmoothCurve *[numCurves];
     277 [ +  - ][ +  - ]:          8 :     _smthCurve = new SmoothCurve*[numCurves];
     278                 :            :     // there should also be a map from surfaces to evaluators
     279                 :            :     // std::map<MBEntityHandle, SmoothCurve*> mapCurves;
     280                 :            : 
     281                 :          8 :     i = 0;
     282 [ +  - ][ +  - ]:         38 :     for( it = _my_gsets[1].begin(); it != _my_gsets[1].end(); ++it, i++ )
         [ +  - ][ +  - ]
                 [ +  + ]
     283                 :            :     {
     284         [ +  - ]:         30 :         EntityHandle curve = *it;
     285 [ +  - ][ +  - ]:         30 :         _smthCurve[i]      = new SmoothCurve( MBI, curve, _my_geomTopoTool );
     286         [ +  - ]:         30 :         _edges[curve]      = _smthCurve[i];
     287                 :            :     }
     288                 :            : 
     289         [ +  + ]:         20 :     for( i = 0; i < numSurfaces; i++ )
     290                 :            :     {
     291         [ +  - ]:         12 :         _smthFace[i]->init_gradient();                   // this will also retrieve the triangles in each surface
     292         [ +  - ]:         12 :         _smthFace[i]->compute_tangents_for_each_edge();  // this one will consider all edges
     293                 :            :                                                          // internal, so the
     294                 :            :         // tangents are all in the direction of the edge; a little bit of waste, as we store
     295                 :            :         // one tangent for each edge node , even though they are equal here...
     296                 :            :         // no loops are considered
     297                 :            :     }
     298                 :            : 
     299                 :            :     // this will be used to mark boundary edges, so for them the control points are computed earlier
     300                 :          8 :     unsigned char value = 0;  // default value is "not used"=0 for the tag
     301                 :            :     // unsigned char def_data_bit = 1;// valid by default
     302                 :            :     // rval = mb->tag_create("valid", 1, MB_TAG_BIT, validTag, &def_data_bit);
     303                 :            :     Tag markTag;
     304                 :            :     rval = MBI->tag_get_handle( "MARKER", 1, MB_TYPE_BIT, markTag, MB_TAG_EXCL | MB_TAG_BIT,
     305         [ +  - ]:          8 :                                 &value );  // default value : 0 = not computed yet
     306                 :            :     // each feature edge will need to have a way to retrieve at every moment the surfaces it belongs
     307                 :            :     // to from edge sets, using the sense tag, we can get faces, and from each face, using the map,
     308                 :            :     // we can get the SmoothFace (surface evaluator), that has everything, including the normals!!!
     309         [ -  + ]:          8 :     assert( rval == MB_SUCCESS );
     310                 :            : 
     311                 :            :     // create the tag also for control points on the edges
     312                 :          8 :     double defCtrlPoints[9] = { 0., 0., 0., 0., 0., 0., 0., 0., 0. };
     313                 :            :     Tag edgeCtrlTag;
     314                 :            :     rval = MBI->tag_get_handle( "CONTROLEDGE", 9, MB_TYPE_DOUBLE, edgeCtrlTag, MB_TAG_DENSE | MB_TAG_CREAT,
     315         [ +  - ]:          8 :                                 &defCtrlPoints );
     316         [ -  + ]:          8 :     assert( rval == MB_SUCCESS );
     317                 :            : 
     318                 :            :     Tag facetCtrlTag;
     319                 :          8 :     double defControls[18] = { 0. };
     320                 :            :     rval = MBI->tag_get_handle( "CONTROLFACE", 18, MB_TYPE_DOUBLE, facetCtrlTag, MB_TAG_CREAT | MB_TAG_DENSE,
     321         [ +  - ]:          8 :                                 &defControls );
     322         [ -  + ]:          8 :     assert( rval == MB_SUCCESS );
     323                 :            : 
     324                 :            :     Tag facetEdgeCtrlTag;
     325                 :          8 :     double defControls2[27] = { 0. };  // corresponding to 9 control points on edges, in order
     326                 :            :                                        // from edge 0, 1, 2 ( 1-2, 2-0, 0-1 )
     327                 :            :     rval = MBI->tag_get_handle( "CONTROLEDGEFACE", 27, MB_TYPE_DOUBLE, facetEdgeCtrlTag, MB_TAG_CREAT | MB_TAG_DENSE,
     328         [ +  - ]:          8 :                                 &defControls2 );
     329         [ -  + ]:          8 :     assert( rval == MB_SUCCESS );
     330                 :            :     // if the
     331                 :          8 :     double min_dot = -1.0;  // depends on _angle, but now we ignore it, for the time being
     332         [ +  + ]:         38 :     for( i = 0; i < numCurves; i++ )
     333                 :            :     {
     334         [ +  - ]:         30 :         _smthCurve[i]->compute_tangents_for_each_edge();  // do we need surfaces now? or just the chains?
     335                 :            :         // the computed edges will be marked accordingly; later one, only internal edges to surfaces
     336                 :            :         // are left
     337         [ +  - ]:         30 :         _smthCurve[i]->compute_control_points_on_boundary_edges( min_dot, _faces, edgeCtrlTag, markTag );
     338                 :            :     }
     339                 :            : 
     340                 :            :     // when done with boundary edges, compute the control points on all edges in the surfaces
     341                 :            : 
     342         [ +  + ]:         20 :     for( i = 0; i < numSurfaces; i++ )
     343                 :            :     {
     344                 :            :         // also pass the tags for
     345         [ +  - ]:         12 :         _smthFace[i]->compute_control_points_on_edges( min_dot, edgeCtrlTag, markTag );
     346                 :            :     }
     347                 :            : 
     348                 :            :     // now we should be able to compute the control points for the facets
     349                 :            : 
     350         [ +  + ]:         20 :     for( i = 0; i < numSurfaces; i++ )
     351                 :            :     {
     352                 :            :         // also pass the tags for edge and facet control points
     353         [ +  - ]:         12 :         _smthFace[i]->compute_internal_control_points_on_facets( min_dot, facetCtrlTag, facetEdgeCtrlTag );
     354                 :            :     }
     355                 :            :     // we will need to compute the tangents for all edges in the model
     356                 :            :     // they will be needed for control points for each edge
     357                 :            :     // the boundary edges and the feature edges are more complicated
     358                 :            :     // the boundary edges need to consider their loops, but feature edges need to consider loops and
     359                 :            :     // the normals on each connected surface
     360                 :            : 
     361                 :            :     // some control points
     362                 :            :     if( Debug_surf_eval )
     363                 :            :         for( i = 0; i < numSurfaces; i++ )
     364                 :            :             _smthFace[i]->DumpModelControlPoints();
     365                 :            : 
     366                 :          8 :     return MB_SUCCESS;
     367                 :            : }
     368                 :            : 
     369                 :            : // clean up the smooth tags data if created, so the files will be smaller
     370                 :            : // if saved
     371                 :            : // also, recompute the tags if topology is modified
     372                 :          4 : void FBEngine::delete_smooth_tags()
     373                 :            : {
     374                 :            :     // get all tags from database that are created for smooth data, and
     375                 :            :     // delete them; it will delete all data associated with them
     376                 :            :     // first tags from faces, edges:
     377         [ +  - ]:          4 :     std::vector< Tag > smoothTags;
     378         [ +  - ]:          4 :     int size1 = (int)_my_gsets[2].size();
     379                 :            : 
     380         [ +  + ]:         10 :     for( int i = 0; i < size1; i++ )
     381                 :            :     {
     382                 :            :         // these 2 will append gradient tag and plane tag
     383         [ +  - ]:          6 :         _smthFace[i]->append_smooth_tags( smoothTags );
     384                 :            :     }
     385                 :            :     // then , get other tags:
     386                 :            :     // "TANGENTS", "MARKER", "CONTROLEDGE", "CONTROLFACE", "CONTROLEDGEFACE"
     387                 :            :     Tag tag_handle;
     388         [ +  - ]:          4 :     ErrorCode rval = _mbImpl->tag_get_handle( "TANGENTS", 6, MB_TYPE_DOUBLE, tag_handle );
     389 [ +  - ][ +  - ]:          4 :     if( rval != MB_TAG_NOT_FOUND ) smoothTags.push_back( tag_handle );
     390                 :            : 
     391         [ +  - ]:          4 :     rval = _mbImpl->tag_get_handle( "MARKER", 1, MB_TYPE_BIT, tag_handle );
     392 [ +  - ][ +  - ]:          4 :     if( rval != MB_TAG_NOT_FOUND ) smoothTags.push_back( tag_handle );
     393                 :            : 
     394         [ +  - ]:          4 :     rval = _mbImpl->tag_get_handle( "CONTROLEDGE", 9, MB_TYPE_DOUBLE, tag_handle );
     395 [ +  - ][ +  - ]:          4 :     if( rval != MB_TAG_NOT_FOUND ) smoothTags.push_back( tag_handle );
     396                 :            : 
     397         [ +  - ]:          4 :     rval = _mbImpl->tag_get_handle( "CONTROLFACE", 18, MB_TYPE_DOUBLE, tag_handle );
     398 [ +  - ][ +  - ]:          4 :     if( rval != MB_TAG_NOT_FOUND ) smoothTags.push_back( tag_handle );
     399                 :            : 
     400         [ +  - ]:          4 :     rval = _mbImpl->tag_get_handle( "CONTROLEDGEFACE", 27, MB_TYPE_DOUBLE, tag_handle );
     401 [ +  - ][ +  - ]:          4 :     if( rval != MB_TAG_NOT_FOUND ) smoothTags.push_back( tag_handle );
     402                 :            : 
     403                 :            :     // a lot of tags, delete them
     404         [ +  + ]:         36 :     for( unsigned int k = 0; k < smoothTags.size(); k++ )
     405                 :            :     {
     406                 :            :         // could be a lot of data
     407 [ +  - ][ +  - ]:         32 :         _mbImpl->tag_delete( smoothTags[k] );
     408                 :          4 :     }
     409                 :          4 : }
     410                 :            : /*
     411                 :            : #define COPY_RANGE(r, vec) {                      \
     412                 :            :     EntityHandle *tmp_ptr = reinterpret_cast<EntityHandle*>(vec); \
     413                 :            :     std::copy(r.begin(), r.end(), tmp_ptr);}
     414                 :            : */
     415                 :            : 
     416                 :            : /*static inline void
     417                 :            :  ProcessError(const char* desc);*/
     418                 :            : 
     419                 :         37 : ErrorCode FBEngine::getRootSet( EntityHandle* root_set )
     420                 :            : {
     421                 :         37 :     *root_set = _my_geomTopoTool->get_root_model_set();
     422                 :         37 :     return MB_SUCCESS;
     423                 :            : }
     424                 :            : 
     425                 :          3 : ErrorCode FBEngine::getNumEntSets( EntityHandle set, int num_hops, int* all_sets )
     426                 :            : {
     427                 :          3 :     ErrorCode rval = MBI->num_contained_meshsets( set, all_sets, num_hops + 1 );
     428                 :          3 :     return rval;
     429                 :            : }
     430                 :            : 
     431                 :         18 : ErrorCode FBEngine::createEntSet( int isList, EntityHandle* pSet )
     432                 :            : {
     433                 :            :     ErrorCode rval;
     434                 :            : 
     435         [ +  - ]:         18 :     if( isList )
     436                 :         18 :         rval = MBI->create_meshset( MESHSET_ORDERED, *pSet );
     437                 :            :     else
     438                 :          0 :         rval = MBI->create_meshset( MESHSET_SET, *pSet );
     439                 :            : 
     440                 :         18 :     return rval;
     441                 :            : }
     442                 :            : 
     443                 :        118 : ErrorCode FBEngine::getEntities( EntityHandle set_handle, int entity_type, Range& gentities )
     444                 :            : {
     445                 :            :     int i;
     446 [ +  - ][ -  + ]:        118 :     if( 0 > entity_type || 4 < entity_type ) { return MB_FAILURE; }
     447         [ +  + ]:        118 :     else if( entity_type < 4 )
     448                 :            :     {                                                            // 4 means all entities
     449 [ +  - ][ +  - ]:        111 :         gentities = _my_geomTopoTool->geoRanges()[entity_type];  // all from root set!
     450                 :            :     }
     451                 :            :     else
     452                 :            :     {
     453         [ +  - ]:          7 :         gentities.clear();
     454         [ +  + ]:         35 :         for( i = 0; i < 4; i++ )
     455                 :            :         {
     456 [ +  - ][ +  - ]:         28 :             gentities.merge( _my_geomTopoTool->geoRanges()[i] );
     457                 :            :         }
     458                 :            :     }
     459         [ +  - ]:        118 :     Range sets;
     460                 :            :     // see now if they are in the set passed as input or not
     461         [ +  - ]:        118 :     ErrorCode rval = MBI->get_entities_by_type( set_handle, MBENTITYSET, sets );
     462 [ -  + ][ #  # ]:        118 :     MBERRORR( rval, "can't get sets in the initial set" );
                 [ #  # ]
     463 [ +  - ][ +  - ]:        118 :     gentities = intersect( gentities, sets );
     464                 :            : 
     465                 :        118 :     return MB_SUCCESS;
     466                 :            : }
     467                 :            : 
     468                 :         18 : ErrorCode FBEngine::addEntArrToSet( Range entities, EntityHandle set )
     469                 :            : {
     470                 :         18 :     return MBI->add_entities( set, entities );
     471                 :            : }
     472                 :            : 
     473                 :         12 : ErrorCode FBEngine::addEntSet( EntityHandle entity_set_to_add, EntityHandle entity_set_handle )
     474                 :            : {
     475                 :         12 :     return MBI->add_entities( entity_set_handle, &entity_set_to_add, 1 );
     476                 :            : }
     477                 :            : 
     478                 :         39 : ErrorCode FBEngine::getNumOfType( EntityHandle set, int ent_type, int* pNum )
     479                 :            : {
     480 [ +  - ][ -  + ]:         39 :     if( 0 > ent_type || 4 < ent_type )
     481                 :            :     {
     482         [ #  # ]:          0 :         std::cout << "Invalid type\n";
     483                 :          0 :         return MB_FAILURE;
     484                 :            :     }
     485                 :            :     // get sets of geom dimension tag from here, and intersect with the gentities from geo
     486                 :            :     // ranges
     487                 :            : 
     488                 :            :     // get the geom dimensions sets in the set (AKA gentities)
     489         [ +  - ]:         39 :     Range geom_sets;
     490                 :            :     Tag geom_tag;
     491                 :            :     ErrorCode rval =
     492         [ +  - ]:         39 :         _mbImpl->tag_get_handle( GEOM_DIMENSION_TAG_NAME, 1, MB_TYPE_INTEGER, geom_tag, MB_TAG_SPARSE | MB_TAG_CREAT );
     493 [ -  + ][ #  # ]:         39 :     MBERRORR( rval, "Failed to get geom tag." );
                 [ #  # ]
     494         [ +  - ]:         39 :     rval = _mbImpl->get_entities_by_type_and_tag( set, MBENTITYSET, &geom_tag, NULL, 1, geom_sets, Interface::UNION );
     495 [ -  + ][ #  # ]:         39 :     MBERRORR( rval, "Failed to get gentities from set" );
                 [ #  # ]
     496                 :            : 
     497         [ -  + ]:         39 :     if( ent_type == 4 )
     498                 :            :     {
     499                 :          0 :         *pNum = 0;
     500         [ #  # ]:          0 :         for( int k = 0; k <= 3; k++ )
     501                 :            :         {
     502 [ #  # ][ #  # ]:          0 :             Range gEntsOfTypeK = intersect( geom_sets, _my_geomTopoTool->geoRanges()[k] );
     503         [ #  # ]:          0 :             *pNum += (int)gEntsOfTypeK.size();
     504                 :          0 :         }
     505                 :            :     }
     506                 :            :     else
     507                 :            :     {
     508 [ +  - ][ +  - ]:         39 :         Range gEntsOfType = intersect( geom_sets, _my_geomTopoTool->geoRanges()[ent_type] );
     509         [ +  - ]:         39 :         *pNum             = (int)gEntsOfType.size();
     510                 :            :     }
     511                 :            :     // we do not really check if it is in the set or not;
     512                 :            :     // _my_gsets[i].find(gent) != _my_gsets[i].end()
     513                 :         39 :     return MB_SUCCESS;
     514                 :            : }
     515                 :            : 
     516                 :        223 : ErrorCode FBEngine::getEntType( EntityHandle gent, int* type )
     517                 :            : {
     518         [ +  - ]:        343 :     for( int i = 0; i < 4; i++ )
     519                 :            :     {
     520 [ +  - ][ +  - ]:        343 :         if( _my_geomTopoTool->geoRanges()[i].find( gent ) != _my_geomTopoTool->geoRanges()[i].end() )
         [ +  - ][ +  + ]
     521                 :            :         {
     522                 :        223 :             *type = i;
     523                 :        223 :             return MB_SUCCESS;
     524                 :            :         }
     525                 :            :     }
     526                 :          0 :     *type = -1;  // failure
     527                 :        223 :     return MB_FAILURE;
     528                 :            : }
     529                 :         22 : ErrorCode FBEngine::getEntBoundBox( EntityHandle gent, double* min_x, double* min_y, double* min_z, double* max_x,
     530                 :            :                                     double* max_y, double* max_z )
     531                 :            : {
     532                 :            :     ErrorCode rval;
     533                 :            :     int type;
     534         [ +  - ]:         22 :     rval = getEntType( gent, &type );
     535 [ -  + ][ #  # ]:         22 :     MBERRORR( rval, "Failed to get entity type." );
                 [ #  # ]
     536                 :            : 
     537         [ +  + ]:         22 :     if( type == 0 )
     538                 :            :     {
     539         [ +  - ]:         11 :         rval = getVtxCoord( gent, min_x, min_y, min_z );
     540 [ -  + ][ #  # ]:         11 :         MBERRORR( rval, "Failed to get vertex coordinates." );
                 [ #  # ]
     541                 :         11 :         max_x = min_x;
     542                 :         11 :         max_y = min_y;
     543                 :         11 :         max_z = min_z;
     544                 :            :     }
     545         [ -  + ]:         11 :     else if( type == 1 )
     546                 :            :     {
     547 [ #  # ][ #  # ]:          0 :         MBERRORR( MB_FAILURE, "iGeom_getEntBoundBox is not supported for Edge entity type." );
     548                 :            :     }
     549 [ -  + ][ #  # ]:         11 :     else if( type == 2 || type == 3 )
     550                 :            :     {
     551                 :            : 
     552                 :            :         EntityHandle root;
     553 [ +  - ][ +  - ]:         44 :         CartVect center, axis[3];
                 [ +  + ]
     554         [ +  - ]:         11 :         rval = _my_geomTopoTool->get_root( gent, root );
     555 [ -  + ][ #  # ]:         11 :         MBERRORR( rval, "Failed to get tree root in iGeom_getEntBoundBox." );
                 [ #  # ]
     556                 :            :         rval = _my_geomTopoTool->obb_tree()->box( root, center.array(), axis[0].array(), axis[1].array(),
     557 [ +  - ][ +  - ]:         11 :                                                   axis[2].array() );
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     558 [ -  + ][ #  # ]:         11 :         MBERRORR( rval, "Failed to get closest point in iGeom_getEntBoundBox." );
                 [ #  # ]
     559                 :            : 
     560 [ +  - ][ +  + ]:         44 :         CartVect absv[3];
     561         [ +  + ]:         44 :         for( int i = 0; i < 3; i++ )
     562                 :            :         {
     563 [ +  - ][ +  - ]:         33 :             absv[i] = CartVect( fabs( axis[i][0] ), fabs( axis[i][1] ), fabs( axis[i][2] ) );
         [ +  - ][ +  - ]
     564                 :            :         }
     565 [ +  - ][ +  - ]:         11 :         CartVect min, max;
     566 [ +  - ][ +  - ]:         11 :         min    = center - absv[0] - absv[1] - absv[2];
                 [ +  - ]
     567 [ +  - ][ +  - ]:         11 :         max    = center + absv[0] + absv[1] + absv[2];
                 [ +  - ]
     568         [ +  - ]:         11 :         *min_x = min[0];
     569         [ +  - ]:         11 :         *min_y = min[1];
     570         [ +  - ]:         11 :         *min_z = min[2];
     571         [ +  - ]:         11 :         *max_x = max[0];
     572         [ +  - ]:         11 :         *max_y = max[1];
     573         [ +  - ]:         11 :         *max_z = max[2];
     574                 :            :     }
     575                 :            :     else
     576                 :          0 :         return MB_FAILURE;
     577                 :            : 
     578                 :         22 :     return MB_SUCCESS;
     579                 :            : }
     580                 :         51 : ErrorCode FBEngine::getEntClosestPt( EntityHandle this_gent, double near_x, double near_y, double near_z, double* on_x,
     581                 :            :                                      double* on_y, double* on_z )
     582                 :            : {
     583                 :            :     ErrorCode rval;
     584                 :            :     int type;
     585         [ +  - ]:         51 :     rval = getEntType( this_gent, &type );
     586 [ -  + ][ #  # ]:         51 :     MBERRORR( rval, "Failed to get entity type." );
                 [ #  # ]
     587                 :            : 
     588         [ +  + ]:         51 :     if( type == 0 )
     589                 :            :     {
     590         [ +  - ]:         29 :         rval = getVtxCoord( this_gent, on_x, on_y, on_z );
     591 [ -  + ][ #  # ]:         29 :         MBERRORR( rval, "Failed to get vertex coordinates." );
                 [ #  # ]
     592                 :            :     }
     593 [ +  + ][ +  + ]:         22 :     else if( _smooth && type == 1 )
     594                 :            :     {
     595                 :         12 :         *on_x                  = near_x;
     596                 :         12 :         *on_y                  = near_y;
     597                 :         12 :         *on_z                  = near_z;
     598         [ +  - ]:         12 :         SmoothCurve* smthcurve = _edges[this_gent];
     599                 :            :         // call the new method from smooth edge
     600         [ +  - ]:         12 :         smthcurve->move_to_curve( *on_x, *on_y, *on_z );
     601                 :            :     }
     602 [ -  + ][ #  # ]:         10 :     else if( type == 2 || type == 3 )
     603                 :            :     {
     604                 :         10 :         double point[3] = { near_x, near_y, near_z };
     605                 :            :         double point_out[3];
     606                 :            :         EntityHandle root, facet_out;
     607 [ +  + ][ +  - ]:         10 :         if( _smooth && 2 == type )
     608                 :            :         {
     609         [ +  - ]:          8 :             SmoothFace* smthFace = _faces[this_gent];
     610                 :          8 :             *on_x                = near_x;
     611                 :          8 :             *on_y                = near_y;
     612                 :          8 :             *on_z                = near_z;
     613         [ +  - ]:          8 :             smthFace->move_to_surface( *on_x, *on_y, *on_z );
     614                 :            :         }
     615                 :            :         else
     616                 :            :         {
     617         [ +  - ]:          2 :             rval = _my_geomTopoTool->get_root( this_gent, root );
     618 [ -  + ][ #  # ]:          2 :             MBERRORR( rval, "Failed to get tree root in iGeom_getEntClosestPt." );
                 [ #  # ]
     619 [ +  - ][ +  - ]:          2 :             rval = _my_geomTopoTool->obb_tree()->closest_to_location( point, root, point_out, facet_out );
     620 [ -  + ][ #  # ]:          2 :             MBERRORR( rval, "Failed to get closest point in iGeom_getEntClosestPt." );
                 [ #  # ]
     621                 :            : 
     622                 :          2 :             *on_x = point_out[0];
     623                 :          2 :             *on_y = point_out[1];
     624                 :          2 :             *on_z = point_out[2];
     625                 :         10 :         }
     626                 :            :     }
     627                 :            :     else
     628                 :          0 :         return MB_TYPE_OUT_OF_RANGE;
     629                 :            : 
     630                 :         51 :     return MB_SUCCESS;
     631                 :            : }
     632                 :            : 
     633                 :         58 : ErrorCode FBEngine::getVtxCoord( EntityHandle vertex_handle, double* x0, double* y0, double* z0 )
     634                 :            : {
     635                 :            :     int type;
     636         [ +  - ]:         58 :     ErrorCode rval = getEntType( vertex_handle, &type );
     637 [ -  + ][ #  # ]:         58 :     MBERRORR( rval, "Failed to get entity type in getVtxCoord." );
                 [ #  # ]
     638                 :            : 
     639 [ -  + ][ #  # ]:         58 :     if( type != 0 ) { MBERRORR( MB_FAILURE, "Entity is not a vertex type." ); }
                 [ #  # ]
     640                 :            : 
     641         [ +  - ]:         58 :     Range entities;
     642         [ +  - ]:         58 :     rval = MBI->get_entities_by_type( vertex_handle, MBVERTEX, entities );
     643 [ -  + ][ #  # ]:         58 :     MBERRORR( rval, "can't get nodes in vertex set." );
                 [ #  # ]
     644                 :            : 
     645 [ +  - ][ -  + ]:         58 :     if( entities.size() != 1 ) { MBERRORR( MB_FAILURE, "Vertex has multiple points." ); }
         [ #  # ][ #  # ]
     646                 :            :     double coords[3];
     647         [ +  - ]:         58 :     EntityHandle node = entities[0];
     648         [ +  - ]:         58 :     rval              = MBI->get_coords( &node, 1, coords );
     649 [ -  + ][ #  # ]:         58 :     MBERRORR( rval, "can't get coordinates." );
                 [ #  # ]
     650                 :         58 :     *x0 = coords[0];
     651                 :         58 :     *y0 = coords[1];
     652                 :         58 :     *z0 = coords[2];
     653                 :            : 
     654                 :         58 :     return MB_SUCCESS;
     655                 :            : }
     656                 :            : 
     657                 :          3 : ErrorCode FBEngine::gsubtract( EntityHandle entity_set_1, EntityHandle entity_set_2, EntityHandle result_entity_set )
     658                 :            : {
     659                 :            :     /*result_entity_set = subtract(entity_set_1, entity_set_2);*/
     660 [ +  - ][ +  - ]:          6 :     Range ents1, ents2;
     661         [ +  - ]:          3 :     ErrorCode rval = MBI->get_entities_by_type( entity_set_1, MBENTITYSET, ents1 );
     662 [ -  + ][ #  # ]:          3 :     MBERRORR( rval, "can't get entities from set 1." );
                 [ #  # ]
     663                 :            : 
     664         [ +  - ]:          3 :     rval = MBI->get_entities_by_type( entity_set_2, MBENTITYSET, ents2 );
     665 [ -  + ][ #  # ]:          3 :     MBERRORR( rval, "can't get entities from set 2." );
                 [ #  # ]
     666                 :            : 
     667 [ +  - ][ +  - ]:          3 :     ents1 = subtract( ents1, ents2 );
     668         [ +  - ]:          3 :     rval  = MBI->clear_meshset( &result_entity_set, 1 );
     669 [ -  + ][ #  # ]:          3 :     MBERRORR( rval, "can't empty set." );
                 [ #  # ]
     670                 :            : 
     671         [ +  - ]:          3 :     rval = MBI->add_entities( result_entity_set, ents1 );
     672 [ -  + ][ #  # ]:          3 :     MBERRORR( rval, "can't add result to set." );
                 [ #  # ]
     673                 :            : 
     674                 :          6 :     return rval;
     675                 :            : }
     676                 :            : 
     677                 :          8 : ErrorCode FBEngine::getEntNrmlXYZ( EntityHandle entity_handle, double x, double y, double z, double* nrml_i,
     678                 :            :                                    double* nrml_j, double* nrml_k )
     679                 :            : {
     680                 :            :     // just do for surface and volume
     681                 :            :     int type;
     682         [ +  - ]:          8 :     ErrorCode rval = getEntType( entity_handle, &type );
     683 [ -  + ][ #  # ]:          8 :     MBERRORR( rval, "Failed to get entity type in iGeom_getEntNrmlXYZ." );
                 [ #  # ]
     684                 :            : 
     685 [ -  + ][ #  # ]:          8 :     if( type != 2 && type != 3 )
     686 [ #  # ][ #  # ]:          0 :     { MBERRORR( MB_FAILURE, "Entities passed into gentityNormal must be face or volume." ); }
     687                 :            : 
     688 [ +  - ][ +  - ]:          8 :     if( _smooth && 2 == type )
     689                 :            :     {
     690         [ +  - ]:          8 :         SmoothFace* smthFace = _faces[entity_handle];
     691                 :            :         //*on_x = near_x; *on_y = near_y; *on_z = near_z;
     692         [ +  - ]:          8 :         smthFace->normal_at( x, y, z, *nrml_i, *nrml_j, *nrml_k );
     693                 :            :     }
     694                 :            :     else
     695                 :            :     {
     696                 :            :         // get closest location and facet
     697                 :          0 :         double point[3] = { x, y, z };
     698                 :            :         double point_out[3];
     699                 :            :         EntityHandle root, facet_out;
     700         [ #  # ]:          0 :         _my_geomTopoTool->get_root( entity_handle, root );
     701 [ #  # ][ #  # ]:          0 :         rval = _my_geomTopoTool->obb_tree()->closest_to_location( point, root, point_out, facet_out );
     702 [ #  # ][ #  # ]:          0 :         MBERRORR( rval, "Failed to get closest location in iGeom_getEntNrmlXYZ." );
                 [ #  # ]
     703                 :            : 
     704                 :            :         // get facet normal
     705                 :            :         const EntityHandle* conn;
     706                 :            :         int len;
     707 [ #  # ][ #  # ]:          0 :         CartVect coords[3], normal;
                 [ #  # ]
     708         [ #  # ]:          0 :         rval = MBI->get_connectivity( facet_out, conn, len );
     709 [ #  # ][ #  # ]:          0 :         MBERRORR( rval, "Failed to get triangle connectivity in iGeom_getEntNrmlXYZ." );
                 [ #  # ]
     710 [ #  # ][ #  # ]:          0 :         if( len != 3 ) MBERRORR( MB_FAILURE, " not a triangle, error " );
                 [ #  # ]
     711                 :            : 
     712 [ #  # ][ #  # ]:          0 :         rval = MBI->get_coords( conn, len, coords[0].array() );
     713 [ #  # ][ #  # ]:          0 :         MBERRORR( rval, "Failed to get triangle coordinates in iGeom_getEntNrmlXYZ." );
                 [ #  # ]
     714                 :            : 
     715         [ #  # ]:          0 :         coords[1] -= coords[0];
     716         [ #  # ]:          0 :         coords[2] -= coords[0];
     717         [ #  # ]:          0 :         normal = coords[1] * coords[2];
     718         [ #  # ]:          0 :         normal.normalize();
     719         [ #  # ]:          0 :         *nrml_i = normal[0];
     720         [ #  # ]:          0 :         *nrml_j = normal[1];
     721         [ #  # ]:          0 :         *nrml_k = normal[2];
     722                 :            :     }
     723                 :          8 :     return MB_SUCCESS;
     724                 :            : }
     725                 :            : 
     726                 :          5 : ErrorCode FBEngine::getPntRayIntsct( double x, double y, double z, double dir_x, double dir_y, double dir_z,
     727                 :            :                                      std::vector< EntityHandle >& intersect_entity_handles,
     728                 :            :                                      /* int storage_order,*/
     729                 :            :                                      std::vector< double >& intersect_coords, std::vector< double >& param_coords )
     730                 :            : {
     731                 :            :     // this is pretty cool
     732                 :            :     // we will return only surfaces (gentities )
     733                 :            :     //
     734                 :            :     ErrorCode rval;
     735                 :            : 
     736         [ +  - ]:          5 :     unsigned int numfaces = _my_gsets[2].size();
     737                 :            :     // do ray fire
     738                 :          5 :     const double point[] = { x, y, z };
     739                 :          5 :     const double dir[]   = { dir_x, dir_y, dir_z };
     740         [ +  - ]:          5 :     CartVect P( point );
     741         [ +  - ]:          5 :     CartVect V( dir );
     742                 :            : 
     743                 :            :     // std::vector<double> distances;
     744         [ +  - ]:          5 :     std::vector< EntityHandle > facets;
     745                 :            :     // std::vector<EntityHandle> sets;
     746                 :            :     unsigned int i;
     747         [ +  + ]:         13 :     for( i = 0; i < numfaces; i++ )
     748                 :            :     {
     749         [ +  - ]:          8 :         EntityHandle face = _my_gsets[2][i];
     750                 :            :         EntityHandle rootForFace;
     751         [ +  - ]:          8 :         rval = _my_geomTopoTool->get_root( face, rootForFace );
     752 [ -  + ][ #  # ]:          8 :         MBERRORR( rval, "Failed to get root of face." );
                 [ #  # ]
     753         [ +  - ]:          8 :         std::vector< double > distances_out;
     754 [ +  - ][ +  - ]:         16 :         std::vector< EntityHandle > sets_out;
     755 [ +  - ][ +  - ]:         16 :         std::vector< EntityHandle > facets_out;
     756                 :            :         rval = _my_geomTopoTool->obb_tree()->ray_intersect_sets( distances_out, sets_out, facets_out, rootForFace,
     757 [ +  - ][ +  - ]:          8 :                                                                  tolerance, point, dir );
     758                 :            :         unsigned int j;
     759         [ +  + ]:         12 :         for( j = 0; j < distances_out.size(); j++ )
     760 [ +  - ][ +  - ]:          4 :             param_coords.push_back( distances_out[j] );
     761         [ +  + ]:         12 :         for( j = 0; j < sets_out.size(); j++ )
     762 [ +  - ][ +  - ]:          4 :             intersect_entity_handles.push_back( sets_out[j] );
     763         [ +  + ]:         12 :         for( j = 0; j < facets_out.size(); j++ )
     764 [ +  - ][ +  - ]:          4 :             facets.push_back( facets_out[j] );
     765                 :            : 
     766 [ -  + ][ #  # ]:          8 :         MBERRORR( rval, "Failed to get ray intersections." );
         [ #  # ][ +  - ]
     767                 :          8 :     }
     768                 :            :     // facets.size == distances.size()!!
     769         [ +  + ]:          9 :     for( i = 0; i < param_coords.size(); i++ )
     770                 :            :     {
     771 [ +  - ][ +  - ]:          4 :         CartVect intx = P + param_coords[i] * V;
                 [ +  - ]
     772         [ +  + ]:         16 :         for( int j = 0; j < 3; j++ )
     773 [ +  - ][ +  - ]:         12 :             intersect_coords.push_back( intx[j] );
     774                 :            :     }
     775         [ +  - ]:          5 :     if( _smooth )
     776                 :            :     {
     777                 :            :         // correct the intersection point and the distance for smooth surfaces
     778         [ +  + ]:          9 :         for( i = 0; i < intersect_entity_handles.size(); i++ )
     779                 :            :         {
     780                 :            :             // EntityHandle geoSet = MBH_cast(sets[i]);
     781 [ +  - ][ +  - ]:          4 :             SmoothFace* sFace = _faces[intersect_entity_handles[i]];
     782                 :            :             // correct coordinates and distance from point
     783                 :            :             /*moab::ErrorCode ray_intersection_correct(moab::EntityHandle facet, // (IN) the facet
     784                 :            :              where the patch is defined moab::CartVect &pt, // (IN) shoot from moab::CartVect &ray,
     785                 :            :              // (IN) ray direction moab::CartVect &eval_pt, // (INOUT) The intersection point double
     786                 :            :              & distance, // (IN OUT) the new distance bool &outside);*/
     787 [ +  - ][ +  - ]:          4 :             CartVect pos( &( intersect_coords[3 * i] ) );
     788         [ +  - ]:          4 :             double dist  = param_coords[i];
     789                 :          4 :             bool outside = false;
     790 [ +  - ][ +  - ]:          4 :             rval         = sFace->ray_intersection_correct( facets[i], P, V, pos, dist, outside );
     791 [ -  + ][ #  # ]:          4 :             MBERRORR( rval, "Failed to get better point on ray." );
                 [ #  # ]
     792         [ +  - ]:          4 :             param_coords[i] = dist;
     793                 :            : 
     794         [ +  + ]:         16 :             for( int j = 0; j < 3; j++ )
     795 [ +  - ][ +  - ]:         12 :                 intersect_coords[3 * i + j] = pos[j];
     796                 :            :         }
     797                 :            :     }
     798                 :          5 :     return MB_SUCCESS;
     799                 :            : }
     800                 :            : 
     801                 :        135 : ErrorCode FBEngine::getAdjacentEntities( const EntityHandle from, const int to_dim, Range& adjs )
     802                 :            : {
     803                 :        135 :     int this_dim = -1;
     804         [ +  - ]:        224 :     for( int i = 0; i < 4; i++ )
     805                 :            :     {
     806 [ +  - ][ +  - ]:        224 :         if( _my_geomTopoTool->geoRanges()[i].find( from ) != _my_geomTopoTool->geoRanges()[i].end() )
         [ +  - ][ +  + ]
     807                 :            :         {
     808                 :        135 :             this_dim = i;
     809                 :        135 :             break;
     810                 :            :         }
     811                 :            :     }
     812                 :            : 
     813                 :            :     // check target dimension
     814         [ -  + ]:        135 :     if( -1 == this_dim )
     815                 :            :     {
     816                 :            :         // ProcessError(iBase_FAILURE, "Entity not a geometry entity.");
     817                 :          0 :         return MB_FAILURE;
     818                 :            :     }
     819 [ +  - ][ -  + ]:        135 :     else if( 0 > to_dim || 3 < to_dim )
     820                 :            :     {
     821                 :            :         // ProcessError(iBase_FAILURE, "To dimension must be between 0 and 3.");
     822                 :          0 :         return MB_FAILURE;
     823                 :            :     }
     824         [ -  + ]:        135 :     else if( to_dim == this_dim )
     825                 :            :     {
     826                 :            :         // ProcessError(iBase_FAILURE,
     827                 :            :         //      "To dimension must be different from entity dimension.");
     828                 :          0 :         return MB_FAILURE;
     829                 :            :     }
     830                 :            : 
     831                 :        135 :     ErrorCode rval = MB_SUCCESS;
     832                 :        135 :     adjs.clear();
     833         [ +  + ]:        135 :     if( to_dim > this_dim )
     834                 :            :     {
     835                 :         92 :         int diffDim = to_dim - this_dim;
     836                 :         92 :         rval        = MBI->get_parent_meshsets( from, adjs, diffDim );
     837         [ -  + ]:         92 :         if( MB_SUCCESS != rval ) return rval;
     838         [ +  + ]:         92 :         if( diffDim > 1 )
     839                 :            :         {
     840                 :            :             // subtract the parents that come with diffDim-1 hops
     841         [ +  - ]:         24 :             Range extra;
     842         [ +  - ]:         24 :             rval = MBI->get_parent_meshsets( from, extra, diffDim - 1 );
     843         [ -  + ]:         24 :             if( MB_SUCCESS != rval ) return rval;
     844 [ +  - ][ +  - ]:         92 :             adjs = subtract( adjs, extra );
                 [ +  - ]
     845                 :            :         }
     846                 :            :     }
     847                 :            :     else
     848                 :            :     {
     849                 :         43 :         int diffDim = this_dim - to_dim;
     850                 :         43 :         rval        = MBI->get_child_meshsets( from, adjs, diffDim );
     851         [ -  + ]:         43 :         if( MB_SUCCESS != rval ) return rval;
     852         [ +  + ]:         43 :         if( diffDim > 1 )
     853                 :            :         {
     854                 :            :             // subtract the children that come with diffDim-1 hops
     855         [ +  - ]:          6 :             Range extra;
     856         [ +  - ]:          6 :             rval = MBI->get_child_meshsets( from, extra, diffDim - 1 );
     857         [ -  + ]:          6 :             if( MB_SUCCESS != rval ) return rval;
     858 [ +  - ][ +  - ]:          6 :             adjs = subtract( adjs, extra );
                 [ +  - ]
     859                 :            :         }
     860                 :            :     }
     861                 :            : 
     862                 :        135 :     return rval;
     863                 :            : }
     864                 :            : 
     865                 :            : // so far, this one is
     866                 :            : // used only for __MKModelEntityGeo tag
     867                 :            : 
     868                 :          0 : ErrorCode FBEngine::createTag( const char* tag_name, int tag_size, int tag_type, Tag& tag_handle_out )
     869                 :            : {
     870                 :            :     // this is copied from iMesh_MOAB.cpp; different name to not have trouble
     871                 :            :     // with it
     872                 :            :     // also, we do not want to depend on iMesh.h...
     873                 :            :     // iMesh is more complicated, because of the options passed
     874                 :            : 
     875                 :            :     DataType mb_data_type_table2[] = { MB_TYPE_OPAQUE, MB_TYPE_INTEGER, MB_TYPE_DOUBLE, MB_TYPE_HANDLE,
     876                 :          0 :                                        MB_TYPE_HANDLE };
     877                 :          0 :     moab::TagType storage          = MB_TAG_SPARSE;
     878                 :            :     ErrorCode result;
     879                 :            : 
     880                 :            :     result =
     881         [ #  # ]:          0 :         MBI->tag_get_handle( tag_name, tag_size, mb_data_type_table2[tag_type], tag_handle_out, storage | MB_TAG_EXCL );
     882                 :            : 
     883         [ #  # ]:          0 :     if( MB_SUCCESS != result )
     884                 :            :     {
     885         [ #  # ]:          0 :         std::string msg( "iMesh_createTag: " );
     886         [ #  # ]:          0 :         if( MB_ALREADY_ALLOCATED == result )
     887                 :            :         {
     888         [ #  # ]:          0 :             msg += "Tag already exists with name: \"";
     889         [ #  # ]:          0 :             msg += tag_name;
     890 [ #  # ][ #  # ]:          0 :             std::cout << msg << "\n";
     891                 :            :         }
     892                 :            :         else
     893                 :            :         {
     894 [ #  # ][ #  # ]:          0 :             std::cout << "Failed to create tag with name: " << tag_name << "\n";
                 [ #  # ]
     895         [ #  # ]:          0 :             return MB_FAILURE;
     896                 :          0 :         }
     897                 :            :     }
     898                 :            : 
     899                 :            :     // end copy
     900                 :          0 :     return MB_SUCCESS;
     901                 :            : }
     902                 :            : 
     903                 :          0 : ErrorCode FBEngine::getArrData( const EntityHandle* entity_handles, int entity_handles_size, Tag tag_handle,
     904                 :            :                                 void* tag_values_out )
     905                 :            : {
     906                 :            :     // responsibility of the user to have tag_values_out properly allocated
     907                 :            :     // only some types of Tags are possible (double, int, etc)
     908                 :          0 :     return MBI->tag_get_data( tag_handle, entity_handles, entity_handles_size, tag_values_out );
     909                 :            : }
     910                 :            : 
     911                 :          0 : ErrorCode FBEngine::setArrData( const EntityHandle* entity_handles, int entity_handles_size, Tag tag_handle,
     912                 :            :                                 const void* tag_values )
     913                 :            : {
     914                 :            :     // responsibility of the user to have tag_values_out properly allocated
     915                 :            :     // only some types of Tags are possible (double, int, etc)
     916                 :          0 :     return MBI->tag_set_data( tag_handle, entity_handles, entity_handles_size, tag_values );
     917                 :            : }
     918                 :            : 
     919                 :        123 : ErrorCode FBEngine::getEntAdj( EntityHandle handle, int type_requested, Range& adjEnts )
     920                 :            : {
     921                 :        123 :     return getAdjacentEntities( handle, type_requested, adjEnts );
     922                 :            : }
     923                 :            : 
     924                 :          0 : ErrorCode FBEngine::getEgFcSense( EntityHandle mbedge, EntityHandle mbface, int& sense_out )
     925                 :            : {
     926                 :            : 
     927                 :            :     // this one is important, for establishing the orientation of the edges in faces
     928                 :            :     // use senses
     929         [ #  # ]:          0 :     std::vector< EntityHandle > faces;
     930         [ #  # ]:          0 :     std::vector< int > senses;  // 0 is forward and 1 is backward
     931         [ #  # ]:          0 :     ErrorCode rval = _my_geomTopoTool->get_senses( mbedge, faces, senses );
     932         [ #  # ]:          0 :     if( MB_SUCCESS != rval ) return rval;
     933                 :            : 
     934         [ #  # ]:          0 :     for( unsigned int i = 0; i < faces.size(); i++ )
     935                 :            :     {
     936 [ #  # ][ #  # ]:          0 :         if( faces[i] == mbface )
     937                 :            :         {
     938         [ #  # ]:          0 :             sense_out = senses[i];
     939                 :          0 :             return MB_SUCCESS;
     940                 :            :         }
     941                 :            :     }
     942                 :          0 :     return MB_FAILURE;
     943                 :            : }
     944                 :            : // we assume the measures array was allocated correctly
     945                 :          0 : ErrorCode FBEngine::measure( const EntityHandle* moab_entities, int entities_size, double* measures )
     946                 :            : {
     947                 :            :     ErrorCode rval;
     948         [ #  # ]:          0 :     for( int i = 0; i < entities_size; i++ )
     949                 :            :     {
     950                 :          0 :         measures[i] = 0.;
     951                 :            : 
     952                 :            :         int type;
     953                 :          0 :         EntityHandle gset = moab_entities[i];
     954         [ #  # ]:          0 :         rval              = getEntType( gset, &type );
     955         [ #  # ]:          0 :         if( MB_SUCCESS != rval ) return rval;
     956         [ #  # ]:          0 :         if( type == 1 )
     957                 :            :         {  // edge: get all edges part of the edge set
     958         [ #  # ]:          0 :             Range entities;
     959         [ #  # ]:          0 :             rval = MBI->get_entities_by_type( gset, MBEDGE, entities );
     960         [ #  # ]:          0 :             if( MB_SUCCESS != rval ) return rval;
     961                 :            : 
     962 [ #  # ][ #  # ]:          0 :             for( Range::iterator it = entities.begin(); it != entities.end(); ++it )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     963                 :            :             {
     964         [ #  # ]:          0 :                 EntityHandle edge = *it;
     965 [ #  # ][ #  # ]:          0 :                 CartVect vv[2];
     966                 :          0 :                 const EntityHandle* conn2 = NULL;
     967                 :            :                 int num_nodes;
     968         [ #  # ]:          0 :                 rval = MBI->get_connectivity( edge, conn2, num_nodes );
     969 [ #  # ][ #  # ]:          0 :                 if( MB_SUCCESS != rval || num_nodes != 2 ) return MB_FAILURE;
     970 [ #  # ][ #  # ]:          0 :                 rval = MBI->get_coords( conn2, 2, (double*)&( vv[0][0] ) );
     971         [ #  # ]:          0 :                 if( MB_SUCCESS != rval ) return rval;
     972                 :            : 
     973         [ #  # ]:          0 :                 vv[0] = vv[1] - vv[0];
     974         [ #  # ]:          0 :                 measures[i] += vv[0].length();
     975                 :          0 :             }
     976                 :            :         }
     977         [ #  # ]:          0 :         if( type == 2 )
     978                 :            :         {  // surface
     979                 :            :             // get triangles in surface; TODO: quads!
     980         [ #  # ]:          0 :             Range entities;
     981         [ #  # ]:          0 :             rval = MBI->get_entities_by_type( gset, MBTRI, entities );
     982         [ #  # ]:          0 :             if( MB_SUCCESS != rval ) return rval;
     983                 :            : 
     984 [ #  # ][ #  # ]:          0 :             for( Range::iterator it = entities.begin(); it != entities.end(); ++it )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     985                 :            :             {
     986         [ #  # ]:          0 :                 EntityHandle tri = *it;
     987 [ #  # ][ #  # ]:          0 :                 CartVect vv[3];
     988                 :          0 :                 const EntityHandle* conn3 = NULL;
     989                 :            :                 int num_nodes;
     990         [ #  # ]:          0 :                 rval = MBI->get_connectivity( tri, conn3, num_nodes );
     991 [ #  # ][ #  # ]:          0 :                 if( MB_SUCCESS != rval || num_nodes != 3 ) return MB_FAILURE;
     992 [ #  # ][ #  # ]:          0 :                 rval = MBI->get_coords( conn3, 3, (double*)&( vv[0][0] ) );
     993         [ #  # ]:          0 :                 if( MB_SUCCESS != rval ) return rval;
     994                 :            : 
     995         [ #  # ]:          0 :                 vv[1] = vv[1] - vv[0];
     996         [ #  # ]:          0 :                 vv[2] = vv[2] - vv[0];
     997         [ #  # ]:          0 :                 vv[0] = vv[1] * vv[2];
     998         [ #  # ]:          0 :                 measures[i] += vv[0].length() / 2;  // area of triangle
     999                 :          0 :             }
    1000                 :            :         }
    1001                 :            :     }
    1002                 :          0 :     return MB_SUCCESS;
    1003                 :            : }
    1004                 :            : 
    1005                 :          0 : ErrorCode FBEngine::getEntNrmlSense( EntityHandle /*face*/, EntityHandle /*region*/, int& /*sense*/ )
    1006                 :            : {
    1007                 :          0 :     return MB_NOT_IMPLEMENTED;  // not implemented
    1008                 :            : }
    1009                 :            : 
    1010                 :          0 : ErrorCode FBEngine::getEgEvalXYZ( EntityHandle /*edge*/, double /*x*/, double /*y*/, double /*z*/, double& /*on_x*/,
    1011                 :            :                                   double& /*on_y*/, double& /*on_z*/, double& /*tngt_i*/, double& /*tngt_j*/,
    1012                 :            :                                   double& /*tngt_k*/, double& /*cvtr_i*/, double& /*cvtr_j*/, double& /*cvtr_k*/ )
    1013                 :            : {
    1014                 :          0 :     return MB_NOT_IMPLEMENTED;  // not implemented
    1015                 :            : }
    1016                 :          0 : ErrorCode FBEngine::getFcEvalXYZ( EntityHandle /*face*/, double /*x*/, double /*y*/, double /*z*/, double& /*on_x*/,
    1017                 :            :                                   double& /*on_y*/, double& /*on_z*/, double& /*nrml_i*/, double& /*nrml_j*/,
    1018                 :            :                                   double& /*nrml_k*/, double& /*cvtr1_i*/, double& /*cvtr1_j*/, double& /*cvtr1_k*/,
    1019                 :            :                                   double& /*cvtr2_i*/, double& /*cvtr2_j*/, double& /*cvtr2_k*/ )
    1020                 :            : {
    1021                 :          0 :     return MB_NOT_IMPLEMENTED;  // not implemented
    1022                 :            : }
    1023                 :            : 
    1024                 :          8 : ErrorCode FBEngine::getEgVtxSense( EntityHandle edge, EntityHandle vtx1, EntityHandle vtx2, int& sense )
    1025                 :            : {
    1026                 :            :     // need to decide first or second vertex
    1027                 :            :     // important for moab
    1028                 :            :     int type;
    1029                 :            : 
    1030                 :            :     EntityHandle v1, v2;
    1031         [ +  - ]:          8 :     ErrorCode rval = getEntType( vtx1, &type );
    1032 [ +  - ][ -  + ]:          8 :     if( MB_SUCCESS != rval || type != 0 ) return MB_FAILURE;
    1033                 :            :     // edge: get one vertex as part of the vertex set
    1034         [ +  - ]:          8 :     Range entities;
    1035         [ +  - ]:          8 :     rval = MBI->get_entities_by_type( vtx1, MBVERTEX, entities );
    1036         [ -  + ]:          8 :     if( MB_SUCCESS != rval ) return rval;
    1037 [ +  - ][ -  + ]:          8 :     if( entities.size() < 1 ) return MB_FAILURE;
    1038         [ +  - ]:          8 :     v1 = entities[0];  // the first vertex
    1039         [ +  - ]:          8 :     entities.clear();
    1040         [ +  - ]:          8 :     rval = getEntType( vtx2, &type );
    1041 [ +  - ][ -  + ]:          8 :     if( MB_SUCCESS != rval || type != 0 ) return MB_FAILURE;
    1042         [ +  - ]:          8 :     rval = MBI->get_entities_by_type( vtx2, MBVERTEX, entities );
    1043         [ -  + ]:          8 :     if( MB_SUCCESS != rval ) return rval;
    1044 [ +  - ][ -  + ]:          8 :     if( entities.size() < 1 ) return MB_FAILURE;
    1045         [ +  - ]:          8 :     v2 = entities[0];  // the first vertex
    1046         [ +  - ]:          8 :     entities.clear();
    1047                 :            :     // now get the edges, and get the first node and the last node in sequence of edges
    1048                 :            :     // the order is important...
    1049                 :            :     // these are ordered sets !!
    1050         [ +  - ]:         16 :     std::vector< EntityHandle > ents;
    1051         [ +  - ]:          8 :     rval = MBI->get_entities_by_type( edge, MBEDGE, ents );
    1052         [ -  + ]:          8 :     if( MB_SUCCESS != rval ) return rval;
    1053         [ -  + ]:          8 :     if( ents.size() < 1 ) return MB_FAILURE;
    1054                 :            : 
    1055                 :          8 :     const EntityHandle* conn = NULL;
    1056                 :            :     int len;
    1057                 :            :     EntityHandle startNode, endNode;
    1058 [ +  - ][ +  - ]:          8 :     rval = MBI->get_connectivity( ents[0], conn, len );
    1059         [ -  + ]:          8 :     if( MB_SUCCESS != rval ) return rval;
    1060                 :          8 :     startNode = conn[0];
    1061 [ +  - ][ +  - ]:          8 :     rval      = MBI->get_connectivity( ents[ents.size() - 1], conn, len );
    1062         [ -  + ]:          8 :     if( MB_SUCCESS != rval ) return rval;
    1063                 :            : 
    1064                 :          8 :     endNode = conn[1];
    1065                 :          8 :     sense   = 1;  //
    1066 [ -  + ][ #  # ]:          8 :     if( ( startNode == endNode ) && ( v1 == startNode ) )
    1067                 :            :     {
    1068                 :          0 :         sense = 0;  // periodic
    1069                 :            :     }
    1070 [ +  + ][ +  - ]:          8 :     if( ( startNode == v1 ) && ( endNode == v2 ) )
    1071                 :            :     {
    1072                 :          3 :         sense = 1;  // forward
    1073                 :            :     }
    1074 [ +  + ][ +  - ]:          8 :     if( ( startNode == v2 ) && ( endNode == v1 ) )
    1075                 :            :     {
    1076                 :          5 :         sense = -1;  // reverse
    1077                 :            :     }
    1078                 :         16 :     return MB_SUCCESS;
    1079                 :            : }
    1080                 :            : 
    1081                 :          0 : ErrorCode FBEngine::getEntURange( EntityHandle edge, double& u_min, double& u_max )
    1082                 :            : {
    1083                 :          0 :     SmoothCurve* smoothCurve = _edges[edge];  // this is a map
    1084                 :            :     // now, call smoothCurve methods
    1085                 :          0 :     smoothCurve->get_param_range( u_min, u_max );
    1086                 :          0 :     return MB_SUCCESS;
    1087                 :            : }
    1088                 :            : 
    1089                 :         12 : ErrorCode FBEngine::getEntUtoXYZ( EntityHandle edge, double u, double& x, double& y, double& z )
    1090                 :            : {
    1091                 :         12 :     SmoothCurve* smoothCurve = _edges[edge];  // this is a map
    1092                 :            :     // now, call smoothCurve methods
    1093                 :         12 :     smoothCurve->position_from_u( u, x, y, z );
    1094                 :         12 :     return MB_SUCCESS;
    1095                 :            : }
    1096                 :            : 
    1097                 :          0 : ErrorCode FBEngine::getEntTgntU( EntityHandle edge, double u, double& i, double& j, double& k )
    1098                 :            : {
    1099         [ #  # ]:          0 :     SmoothCurve* smoothCurve = _edges[edge];  // this is a map
    1100                 :            :     // now, call smoothCurve methods
    1101                 :            :     double tg[3];
    1102                 :            :     double x, y, z;
    1103         [ #  # ]:          0 :     smoothCurve->position_from_u( u, x, y, z, tg );
    1104                 :          0 :     i = tg[0];
    1105                 :          0 :     j = tg[1];
    1106                 :          0 :     k = tg[2];
    1107                 :          0 :     return MB_SUCCESS;
    1108                 :            : }
    1109                 :          0 : ErrorCode FBEngine::isEntAdj( EntityHandle entity1, EntityHandle entity2, bool& adjacent_out )
    1110                 :            : {
    1111                 :            :     int type1, type2;
    1112         [ #  # ]:          0 :     ErrorCode rval = getEntType( entity1, &type1 );
    1113         [ #  # ]:          0 :     if( MB_SUCCESS != rval ) return rval;
    1114         [ #  # ]:          0 :     rval = getEntType( entity2, &type2 );
    1115         [ #  # ]:          0 :     if( MB_SUCCESS != rval ) return rval;
    1116                 :            : 
    1117         [ #  # ]:          0 :     Range adjs;
    1118         [ #  # ]:          0 :     if( type1 < type2 )
    1119                 :            :     {
    1120         [ #  # ]:          0 :         rval = MBI->get_parent_meshsets( entity1, adjs, type2 - type1 );
    1121         [ #  # ]:          0 :         if( MB_SUCCESS != rval ) return rval;  // MBERRORR("Failed to get parent meshsets in iGeom_isEntAdj.");
    1122                 :            :     }
    1123                 :            :     else
    1124                 :            :     {
    1125                 :            :         // note: if they ave the same type, they will not be adjacent, in our definition
    1126         [ #  # ]:          0 :         rval = MBI->get_child_meshsets( entity1, adjs, type1 - type2 );
    1127         [ #  # ]:          0 :         if( MB_SUCCESS != rval ) return rval;  // MBERRORR("Failed to get child meshsets in iGeom_isEntAdj.");
    1128                 :            :     }
    1129                 :            : 
    1130                 :            :     // adjacent_out = adjs.find(entity2) != _my_gsets[type2].end();
    1131                 :            :     // hmmm, possible bug here; is this called?
    1132 [ #  # ][ #  # ]:          0 :     adjacent_out = adjs.find( entity2 ) != adjs.end();
                 [ #  # ]
    1133                 :            : 
    1134                 :          0 :     return MB_SUCCESS;
    1135                 :            : }
    1136                 :            : 
    1137                 :          4 : ErrorCode FBEngine::split_surface_with_direction( EntityHandle face, std::vector< double >& xyz, double* direction,
    1138                 :            :                                                   int closed, double min_dot, EntityHandle& oNewFace )
    1139                 :            : {
    1140                 :            : 
    1141                 :            :     // first of all, find all intersection points (piercing in the face along the direction)
    1142                 :            :     // assume it is robust; what if it is not sufficiently robust?
    1143                 :            :     // if the polyline is open, find the intersection with the boundary edges, of the
    1144                 :            :     // polyline extruded at ends
    1145                 :            : 
    1146                 :            :     ErrorCode rval;
    1147                 :            : 
    1148                 :            :     // then find the position
    1149                 :          4 :     int numIniPoints = (int)xyz.size() / 3;
    1150 [ +  + ][ +  - ]:          4 :     if( ( closed && numIniPoints < 3 ) || ( !closed && numIniPoints < 2 ) )
         [ +  + ][ -  + ]
    1151 [ #  # ][ #  # ]:          0 :         MBERRORR( MB_FAILURE, "not enough polyline points " );
    1152                 :            :     EntityHandle rootForFace;
    1153                 :            : 
    1154         [ +  - ]:          4 :     rval = _my_geomTopoTool->get_root( face, rootForFace );
    1155 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "Failed to get root of face." );
                 [ #  # ]
    1156                 :            : 
    1157                 :          4 :     const double dir[] = { direction[0], direction[1], direction[2] };
    1158         [ +  - ]:          4 :     std::vector< EntityHandle > nodes;  // get the nodes closest to the ray traces of interest
    1159                 :            : 
    1160                 :            :     // these are nodes on the boundary of original face;
    1161                 :            :     // if the cutting line is not closed, the starting - ending vertices of the
    1162                 :            :     // polygonal line must come from this list
    1163                 :            : 
    1164         [ +  - ]:          8 :     std::vector< CartVect > b_pos;
    1165         [ +  - ]:          8 :     std::vector< EntityHandle > boundary_nodes;
    1166         [ +  - ]:          8 :     std::vector< EntityHandle > splittingNodes;
    1167         [ +  - ]:          8 :     Range boundary_mesh_edges;
    1168         [ +  + ]:          4 :     if( !closed )
    1169                 :            :     {
    1170         [ +  - ]:          1 :         rval = boundary_nodes_on_face( face, boundary_nodes );
    1171 [ -  + ][ #  # ]:          1 :         MBERRORR( rval, "Failed to get boundary nodes." );
                 [ #  # ]
    1172         [ +  - ]:          1 :         b_pos.resize( boundary_nodes.size() );
    1173 [ +  - ][ +  - ]:          1 :         rval = _mbImpl->get_coords( &( boundary_nodes[0] ), boundary_nodes.size(), (double*)( &b_pos[0][0] ) );
         [ +  - ][ +  - ]
    1174 [ -  + ][ #  # ]:          1 :         MBERRORR( rval, "Failed to get coordinates for boundary nodes." );
                 [ #  # ]
    1175         [ +  - ]:          1 :         rval = boundary_mesh_edges_on_face( face, boundary_mesh_edges );
    1176 [ -  + ][ #  # ]:          1 :         MBERRORR( rval, "Failed to get mesh boundary edges for face." );
                 [ #  # ]
    1177                 :            :     }
    1178                 :            :     //
    1179                 :          4 :     int i = 0;
    1180         [ +  - ]:          4 :     CartVect dirct( direction );
    1181         [ +  - ]:          4 :     dirct.normalize();  // maybe an overkill?
    1182         [ +  + ]:         21 :     for( ; i < numIniPoints; i++ )
    1183                 :            :     {
    1184                 :            : 
    1185 [ +  - ][ +  - ]:         17 :         const double point[] = { xyz[3 * i], xyz[3 * i + 1], xyz[3 * i + 2] };  // or even point( &(xyz[3*i]) ); //
                 [ +  - ]
    1186         [ +  - ]:         17 :         CartVect p1( point );
    1187 [ +  + ][ +  + ]:         17 :         if( !closed && ( ( 0 == i ) || ( numIniPoints - 1 == i ) ) )
                 [ +  + ]
    1188                 :            :         {
    1189                 :            : 
    1190                 :            :             // find the intersection point between a plane and boundary mesh edges
    1191                 :            :             // this will be the closest point on the boundary of face
    1192                 :            :             /// the segment is the first or last segment in the polyline
    1193                 :          2 :             int i1 = i + 1;
    1194         [ +  + ]:          2 :             if( i == numIniPoints - 1 ) i1 = i - 1;  // previous point if the last
    1195                 :            :             // the direction is from point to point1
    1196 [ +  - ][ +  - ]:          2 :             const double point1[] = { xyz[3 * i1], xyz[3 * i1 + 1], xyz[3 * i1 + 2] };
                 [ +  - ]
    1197         [ +  - ]:          2 :             CartVect p2( point1 );
    1198 [ +  - ][ +  - ]:          2 :             CartVect normPlane = ( p2 - p1 ) * dirct;
    1199         [ +  - ]:          2 :             normPlane.normalize();
    1200                 :            :             //(roughly, from p1 to p2, perpendicular to dirct, in the "xy" plane
    1201                 :            :             // if the intx point is "outside" p1 - p2, skip if the intx point is closer to p2
    1202         [ +  - ]:          2 :             CartVect perpDir    = dirct * normPlane;
    1203         [ +  - ]:          2 :             Range::iterator ite = boundary_mesh_edges.begin();
    1204                 :            :             // do a linear search for the best intersection point position (on a boundary edge)
    1205         [ -  + ]:          2 :             if( debug_splits )
    1206                 :            :             {
    1207 [ #  # ][ #  # ]:          0 :                 std::cout << " p1:" << p1 << "\n";
                 [ #  # ]
    1208 [ #  # ][ #  # ]:          0 :                 std::cout << " p2:" << p2 << "\n";
                 [ #  # ]
    1209 [ #  # ][ #  # ]:          0 :                 std::cout << " perpDir:" << perpDir << "\n";
                 [ #  # ]
    1210 [ #  # ][ #  # ]:          0 :                 std::cout << " boundary edges size:" << boundary_mesh_edges.size() << "\n";
         [ #  # ][ #  # ]
    1211                 :            :             }
    1212 [ +  - ][ +  - ]:        153 :             for( ; ite != boundary_mesh_edges.end(); ++ite )
         [ +  - ][ +  - ]
    1213                 :            :             {
    1214         [ +  - ]:        153 :                 EntityHandle candidateEdge = *ite;
    1215                 :            :                 const EntityHandle* conn2;
    1216                 :            :                 int nno;
    1217         [ +  - ]:        153 :                 rval = _mbImpl->get_connectivity( candidateEdge, conn2, nno );
    1218 [ -  + ][ #  # ]:        153 :                 MBERRORR( rval, "Failed to get conn for boundary edge" );
                 [ #  # ]
    1219 [ +  - ][ +  + ]:        459 :                 CartVect pts[2];
    1220 [ +  - ][ +  - ]:        153 :                 rval = _mbImpl->get_coords( conn2, 2, &( pts[0][0] ) );
    1221 [ -  + ][ #  # ]:        153 :                 MBERRORR( rval, "Failed to get coords of nodes for boundary edge" );
                 [ #  # ]
    1222         [ +  - ]:        153 :                 CartVect intx_point;
    1223                 :            :                 double parPos;
    1224                 :            :                 bool intersect =
    1225         [ +  - ]:        153 :                     intersect_segment_and_plane_slice( pts[0], pts[1], p1, p2, dirct, normPlane, intx_point, parPos );
    1226         [ -  + ]:        153 :                 if( debug_splits )
    1227                 :            :                 {
    1228 [ #  # ][ #  # ]:          0 :                     std::cout << "   Edge:" << _mbImpl->id_from_handle( candidateEdge ) << "\n";
         [ #  # ][ #  # ]
    1229 [ #  # ][ #  # ]:          0 :                     std::cout << "   Node 1:" << _mbImpl->id_from_handle( conn2[0] ) << pts[0] << "\n";
         [ #  # ][ #  # ]
                 [ #  # ]
    1230 [ #  # ][ #  # ]:          0 :                     std::cout << "   Node 2:" << _mbImpl->id_from_handle( conn2[1] ) << pts[1] << "\n";
         [ #  # ][ #  # ]
                 [ #  # ]
    1231 [ #  # ][ #  # ]:          0 :                     std::cout << "    Intersect bool:" << intersect << "\n";
                 [ #  # ]
    1232                 :            :                 }
    1233         [ +  + ]:        153 :                 if( intersect )
    1234                 :            :                 {
    1235 [ +  - ][ +  - ]:          3 :                     double proj1 = ( intx_point - p1 ) % perpDir;
    1236 [ +  - ][ +  - ]:          3 :                     double proj2 = ( intx_point - p2 ) % perpDir;
    1237         [ +  + ]:          3 :                     if( ( fabs( proj1 ) > fabs( proj2 ) )  // this means it is closer to p2 than p1
    1238                 :            :                     )
    1239                 :          1 :                         continue;  // basically, this means the intersection point is with a
    1240                 :            :                                    //  boundary edge on the other side, closer to p2 than p1, so we
    1241                 :            :                                    //  skip it
    1242         [ -  + ]:          2 :                     if( parPos == 0 )
    1243                 :            :                     {
    1244                 :            :                         // close to vertex 1, nothing to do
    1245         [ #  # ]:          0 :                         nodes.push_back( conn2[0] );
    1246         [ #  # ]:          0 :                         splittingNodes.push_back( conn2[0] );
    1247                 :            :                     }
    1248         [ -  + ]:          2 :                     else if( parPos == 1. )
    1249                 :            :                     {
    1250                 :            :                         // close to vertex 2, nothing to do
    1251         [ #  # ]:          0 :                         nodes.push_back( conn2[1] );
    1252         [ #  # ]:          0 :                         splittingNodes.push_back( conn2[1] );
    1253                 :            :                     }
    1254                 :            :                     else
    1255                 :            :                     {
    1256                 :            :                         // break the edge, create a new node at intersection point (will be smoothed
    1257                 :            :                         // out)
    1258                 :            :                         EntityHandle newVertex;
    1259 [ +  - ][ +  - ]:          2 :                         rval = _mbImpl->create_vertex( &( intx_point[0] ), newVertex );
    1260 [ -  + ][ #  # ]:          2 :                         MBERRORR( rval, "can't create vertex" );
                 [ #  # ]
    1261         [ +  - ]:          2 :                         nodes.push_back( newVertex );
    1262         [ +  - ]:          2 :                         split_internal_edge( candidateEdge, newVertex );
    1263         [ +  - ]:          2 :                         splittingNodes.push_back( newVertex );
    1264         [ +  - ]:          2 :                         _brokenEdges[newVertex] = candidateEdge;
    1265         [ +  - ]:          2 :                         _piercedEdges.insert( candidateEdge );
    1266                 :            :                     }
    1267                 :        152 :                     break;  // break from the loop over boundary edges, we are interested in the
    1268                 :            :                             // first
    1269                 :            :                             //      split (hopefully, the only split)
    1270                 :            :                 }
    1271                 :            :             }
    1272 [ +  - ][ +  - ]:          2 :             if( ite == boundary_mesh_edges.end() )
                 [ -  + ]
    1273 [ #  # ][ #  # ]:          2 :                 MBERRORR( MB_FAILURE, "Failed to find boundary intersection edge. Bail out" );
    1274                 :            :         }
    1275                 :            :         else
    1276                 :            :         {
    1277         [ +  - ]:         15 :             std::vector< double > distances_out;
    1278 [ +  - ][ +  - ]:         30 :             std::vector< EntityHandle > sets_out;
    1279 [ +  - ][ +  - ]:         30 :             std::vector< EntityHandle > facets_out;
    1280                 :            :             rval = _my_geomTopoTool->obb_tree()->ray_intersect_sets( distances_out, sets_out, facets_out, rootForFace,
    1281 [ +  - ][ +  - ]:         15 :                                                                      tolerance, point, dir );
    1282 [ -  + ][ #  # ]:         15 :             MBERRORR( rval, "Failed to get ray intersections." );
                 [ #  # ]
    1283         [ -  + ]:         15 :             if( distances_out.size() < 1 )
    1284 [ #  # ][ #  # ]:          0 :                 MBERRORR( MB_FAILURE, "Failed to get one intersection point, bad direction." );
    1285                 :            : 
    1286         [ +  + ]:         15 :             if( distances_out.size() > 1 )
    1287         [ +  - ]:          7 :             { std::cout << " too many intersection points. Only the first one considered\n"; }
    1288         [ +  - ]:         15 :             std::vector< EntityHandle >::iterator pFace = std::find( sets_out.begin(), sets_out.end(), face );
    1289                 :            : 
    1290 [ +  - ][ -  + ]:         15 :             if( pFace == sets_out.end() ) MBERRORR( MB_FAILURE, "Failed to intersect given face, bad direction." );
         [ #  # ][ #  # ]
    1291         [ +  - ]:         15 :             unsigned int index = pFace - sets_out.begin();
    1292                 :            :             // get the closest node of the triangle, and modify locally the triangle(s), so the
    1293                 :            :             // intersection point is at a new vertex, if needed
    1294         [ +  - ]:         15 :             CartVect P( point );
    1295         [ +  - ]:         15 :             CartVect Dir( dir );
    1296 [ +  - ][ +  - ]:         15 :             CartVect newPoint = P + distances_out[index] * Dir;
                 [ +  - ]
    1297                 :            :             // get the triangle coordinates
    1298                 :            : 
    1299                 :            :             double area_coord[3];
    1300                 :         15 :             EntityHandle boundary_handle = 0;  // if 0, not on a boundary
    1301 [ +  - ][ +  - ]:         15 :             rval = area_coordinates( _mbImpl, facets_out[index], newPoint, area_coord, boundary_handle );
    1302 [ -  + ][ #  # ]:         15 :             MBERRORR( rval, "Failed to get area coordinates" );
                 [ #  # ]
    1303                 :            : 
    1304         [ -  + ]:         15 :             if( debug_splits )
    1305                 :            :             {
    1306 [ #  # ][ #  # ]:          0 :                 std::cout << " int point:" << newPoint << " area coord " << area_coord[0] << " " << area_coord[1] << " "
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1307 [ #  # ][ #  # ]:          0 :                           << area_coord[2] << "\n";
    1308 [ #  # ][ #  # ]:          0 :                 std::cout << " triangle: " << _mbImpl->id_from_handle( facets_out[index] )
         [ #  # ][ #  # ]
    1309 [ #  # ][ #  # ]:          0 :                           << " boundary:" << boundary_handle << "\n";
                 [ #  # ]
    1310                 :            :             }
    1311                 :            :             EntityType type;
    1312 [ +  + ][ +  - ]:         15 :             if( boundary_handle ) type = _mbImpl->type_from_handle( boundary_handle );
    1313 [ +  + ][ +  + ]:         15 :             if( boundary_handle && ( type == MBVERTEX ) )
    1314                 :            :             {
    1315                 :            :                 // nothing to do, we are happy
    1316         [ +  - ]:          6 :                 nodes.push_back( boundary_handle );
    1317                 :            :             }
    1318                 :            :             else
    1319                 :            :             {
    1320                 :            :                 // for an edge, we will split 2 triangles
    1321                 :            :                 // for interior point, we will create 3 triangles out of one
    1322                 :            :                 // create a new vertex
    1323                 :            :                 EntityHandle newVertex;
    1324 [ +  - ][ +  - ]:          9 :                 rval = _mbImpl->create_vertex( &( newPoint[0] ), newVertex );
    1325         [ +  + ]:          9 :                 if( boundary_handle )  // this is edge
    1326                 :            :                 {
    1327         [ +  - ]:          2 :                     split_internal_edge( boundary_handle, newVertex );
    1328         [ +  - ]:          2 :                     _piercedEdges.insert( boundary_handle );  // to be removed at the end
    1329                 :            :                 }
    1330                 :            :                 else
    1331 [ +  - ][ +  - ]:          7 :                     divide_triangle( facets_out[index], newVertex );
    1332                 :            : 
    1333 [ +  - ][ +  - ]:         15 :                 nodes.push_back( newVertex );
    1334                 :         15 :             }
    1335                 :            :         }
    1336                 :            :     }
    1337                 :            :     // now, we have to find more intersection points, either interior to triangles, or on edges, or
    1338                 :            :     // on vertices use the same tolerance as before starting from 2 points on 2 triangles, and
    1339                 :            :     // having the direction, get more intersection points between the plane formed by direction and
    1340                 :            :     // those 2 points, and edges from triangulation (the triangles involved will be part of the same
    1341                 :            :     // gentity , original face ( moab set)
    1342                 :            :     // int closed = 1;// closed = 0 if the polyline is not closed
    1343                 :            : 
    1344         [ +  - ]:          4 :     CartVect Dir( direction );
    1345         [ +  - ]:          8 :     std::vector< EntityHandle > chainedEdges;
    1346                 :            : 
    1347         [ +  + ]:         20 :     for( i = 0; i < numIniPoints - 1 + closed; i++ )
    1348                 :            :     {
    1349                 :         16 :         int nextIndex = ( i + 1 ) % numIniPoints;
    1350         [ +  - ]:         16 :         std::vector< EntityHandle > trianglesAlong;
    1351 [ +  - ][ +  - ]:         32 :         std::vector< CartVect > points;
    1352                 :            :         // otherwise to edges or even nodes
    1353 [ +  - ][ +  - ]:         32 :         std::vector< EntityHandle > entities;
    1354                 :            :         // start with initial points, intersect along the direction, find the facets
    1355 [ +  - ][ +  - ]:         16 :         rval = compute_intersection_points( face, nodes[i], nodes[nextIndex], Dir, points, entities, trianglesAlong );
                 [ +  - ]
    1356 [ -  + ][ #  # ]:         16 :         MBERRORR( rval, "can't get intersection points along a line" );
                 [ #  # ]
    1357 [ +  - ][ +  - ]:         32 :         std::vector< EntityHandle > nodesAlongPolyline;
    1358                 :            :         // refactor code; move some edge creation for each 2 intersection points
    1359 [ +  - ][ +  - ]:         16 :         nodesAlongPolyline.push_back( entities[0] );  // it is for sure a node
    1360                 :         16 :         int num_points = (int)points.size();          // it should be num_triangles + 1
    1361         [ +  + ]:       1791 :         for( int j = 0; j < num_points - 1; j++ )
    1362                 :            :         {
    1363         [ +  - ]:       1775 :             EntityHandle tri = trianglesAlong[j];  // this is happening in trianglesAlong i
    1364         [ +  - ]:       1775 :             EntityHandle e1  = entities[j];
    1365         [ +  - ]:       1775 :             EntityHandle e2  = entities[j + 1];
    1366         [ +  - ]:       1775 :             EntityType et1   = _mbImpl->type_from_handle( e1 );
    1367                 :            :             // EntityHandle vertex1 = nodesAlongPolyline[i];// irrespective of the entity type i,
    1368                 :            :             // we already have the vertex there
    1369         [ +  - ]:       1775 :             EntityType et2 = _mbImpl->type_from_handle( e2 );
    1370 [ +  + ][ +  - ]:       1775 :             if( et2 == MBVERTEX ) { nodesAlongPolyline.push_back( e2 ); }
    1371                 :            :             else  // if (et2==MBEDGE)
    1372                 :            :             {
    1373         [ +  - ]:       1744 :                 CartVect coord_vert = points[j + 1];
    1374                 :            :                 EntityHandle newVertex;
    1375         [ +  - ]:       1744 :                 rval = _mbImpl->create_vertex( (double*)&coord_vert, newVertex );
    1376 [ -  + ][ #  # ]:       1744 :                 MBERRORR( rval, "can't create vertex" );
                 [ #  # ]
    1377         [ +  - ]:       1744 :                 nodesAlongPolyline.push_back( newVertex );
    1378                 :            :             }
    1379                 :            :             // if vertices, do not split anything, just get the edge for polyline
    1380 [ +  + ][ -  + ]:       1775 :             if( et2 == MBVERTEX && et1 == MBVERTEX )
    1381                 :            :             {
    1382                 :            :                 // nothing to do, just continue;
    1383                 :          0 :                 continue;  // continue the for loop
    1384                 :            :             }
    1385                 :            : 
    1386         [ -  + ]:       1775 :             if( debug_splits )
    1387                 :            :             {
    1388 [ #  # ][ #  # ]:          0 :                 std::cout << "tri: type: " << _mbImpl->type_from_handle( tri )
                 [ #  # ]
    1389 [ #  # ][ #  # ]:          0 :                           << " id:" << _mbImpl->id_from_handle( tri ) << "\n    e1:" << e1
         [ #  # ][ #  # ]
                 [ #  # ]
    1390 [ #  # ][ #  # ]:          0 :                           << " id:" << _mbImpl->id_from_handle( e1 ) << "   e2:" << e2
         [ #  # ][ #  # ]
                 [ #  # ]
    1391 [ #  # ][ #  # ]:          0 :                           << " id:" << _mbImpl->id_from_handle( e2 ) << "\n";
         [ #  # ][ #  # ]
    1392                 :            :             }
    1393                 :            :             // here, at least one is an edge
    1394 [ +  - ][ +  - ]:       1775 :             rval = BreakTriangle2( tri, e1, e2, nodesAlongPolyline[j], nodesAlongPolyline[j + 1] );
                 [ +  - ]
    1395 [ -  + ][ #  # ]:       1775 :             MBERRORR( rval, "can't break triangle 2" );
                 [ #  # ]
    1396 [ +  + ][ +  - ]:       1775 :             if( et2 == MBEDGE ) _piercedEdges.insert( e2 );
    1397         [ +  - ]:       1775 :             _piercedTriangles.insert( tri );
    1398                 :            :         }
    1399                 :            :         // nodesAlongPolyline will define a new geometric edge
    1400         [ -  + ]:         16 :         if( debug_splits )
    1401                 :            :         {
    1402 [ #  # ][ #  # ]:          0 :             std::cout << "nodesAlongPolyline: " << nodesAlongPolyline.size() << "\n";
                 [ #  # ]
    1403 [ #  # ][ #  # ]:          0 :             std::cout << "points: " << num_points << "\n";
                 [ #  # ]
    1404                 :            :         }
    1405                 :            :         // if needed, create edges along polyline, or revert the existing ones, to
    1406                 :            :         // put them in a new edge set
    1407                 :            :         EntityHandle new_geo_edge;
    1408         [ +  - ]:         16 :         rval = create_new_gedge( nodesAlongPolyline, new_geo_edge );
    1409 [ -  + ][ #  # ]:         16 :         MBERRORR( rval, "can't create a new edge" );
                 [ #  # ]
    1410 [ +  - ][ +  - ]:         16 :         chainedEdges.push_back( new_geo_edge );
    1411                 :            :         // end copy
    1412                 :         16 :     }
    1413                 :            :     // the segment between point_i and point_i+1 is in trianglesAlong_i
    1414                 :            :     // points_i is on entities_i
    1415                 :            :     // all these edges are oriented correctly
    1416         [ +  - ]:          4 :     rval = split_surface( face, chainedEdges, splittingNodes, oNewFace );
    1417 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't split surface" );
                 [ #  # ]
    1418                 :            :     //
    1419         [ +  - ]:          4 :     rval = chain_edges( min_dot );  // acos(0.8)~= 36 degrees
    1420 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't chain edges" );
                 [ #  # ]
    1421                 :          8 :     return MB_SUCCESS;
    1422                 :            : }
    1423                 :            : /**
    1424                 :            :  *  this method splits along the polyline defined by points and entities
    1425                 :            :  *  the polyline will be defined with
    1426                 :            :  *  // the entities are now only nodes and edges, no triangles!!!
    1427                 :            :  *  the first and last ones are also nodes for sure
    1428                 :            :  */
    1429                 :          4 : ErrorCode FBEngine::split_surface( EntityHandle face, std::vector< EntityHandle >& chainedEdges,
    1430                 :            :                                    std::vector< EntityHandle >& splittingNodes, EntityHandle& newFace )
    1431                 :            : {
    1432                 :            :     // use now the chained edges to create a new face (loop or clean split)
    1433                 :            :     // use a fill to determine the new sets, up to the polyline
    1434                 :            :     // points on the polyline will be moved to the closest point location, with some constraints
    1435                 :            :     // then the sets will be reset, geometry recomputed. new vertices, new edges, etc.
    1436                 :            : 
    1437         [ +  - ]:          4 :     Range iniTris;
    1438                 :            :     ErrorCode rval;
    1439         [ +  - ]:          4 :     rval = _mbImpl->get_entities_by_type( face, MBTRI, iniTris );
    1440 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't get initial triangles" );
                 [ #  # ]
    1441                 :            : 
    1442                 :            :     // start from a triangle that is not in the triangles to delete
    1443                 :            :     // flood fill
    1444                 :            : 
    1445                 :          4 :     bool closed = splittingNodes.size() == 0;
    1446         [ +  + ]:          4 :     if( !closed )
    1447                 :            :     {
    1448                 :            :         //
    1449 [ -  + ][ #  # ]:          1 :         if( splittingNodes.size() != 2 ) MBERRORR( MB_FAILURE, "need to have exactly 2 nodes for splitting" );
                 [ #  # ]
    1450                 :            :         // we will have to split the boundary edges
    1451                 :            :         // first, find the actual boundary, and try to split with the 2 end points (nodes)
    1452                 :            :         // get the adjacent edges, and see which one has the end nodes
    1453 [ +  - ][ +  - ]:          1 :         rval = split_boundary( face, splittingNodes[0] );
    1454 [ -  + ][ #  # ]:          1 :         MBERRORR( rval, "can't split with first node" );
                 [ #  # ]
    1455 [ +  - ][ +  - ]:          1 :         rval = split_boundary( face, splittingNodes[1] );
    1456 [ -  + ][ #  # ]:          1 :         MBERRORR( rval, "can't split with second node)" );
                 [ #  # ]
    1457                 :            :     }
    1458                 :            :     // we will separate triangles to delete, unaffected, new_triangles,
    1459                 :            :     //  nodesAlongPolyline,
    1460 [ +  - ][ +  - ]:          8 :     Range first, second;
    1461         [ +  - ]:          4 :     rval = separate( face, chainedEdges, first, second );
    1462                 :            : 
    1463                 :            :     // now, we are done with the computations;
    1464                 :            :     // we need to put the new nodes on the smooth surface
    1465         [ +  - ]:          4 :     if( this->_smooth )
    1466                 :            :     {
    1467         [ +  - ]:          4 :         rval = smooth_new_intx_points( face, chainedEdges );
    1468 [ -  + ][ #  # ]:          4 :         MBERRORR( rval, "can't smooth new points" );
                 [ #  # ]
    1469                 :            :     }
    1470                 :            : 
    1471                 :            :     // create the new set
    1472         [ +  - ]:          4 :     rval = _mbImpl->create_meshset( MESHSET_SET, newFace );
    1473 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't create a new face" );
                 [ #  # ]
    1474                 :            : 
    1475         [ +  - ]:          4 :     _my_geomTopoTool->add_geo_set( newFace, 2 );
    1476                 :            : 
    1477                 :            :     // the new face will have the first set (positive sense triangles, to the left)
    1478         [ +  - ]:          4 :     rval = _mbImpl->add_entities( newFace, first );
    1479 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't add first range triangles to new face" );
                 [ #  # ]
    1480                 :            : 
    1481         [ +  + ]:         20 :     for( unsigned int j = 0; j < chainedEdges.size(); j++ )
    1482                 :            :     {
    1483         [ +  - ]:         16 :         EntityHandle new_geo_edge = chainedEdges[j];
    1484                 :            :         // both faces will have the edge now
    1485         [ +  - ]:         16 :         rval = _mbImpl->add_parent_child( face, new_geo_edge );
    1486 [ -  + ][ #  # ]:         16 :         MBERRORR( rval, "can't add parent child relations for new edge" );
                 [ #  # ]
    1487                 :            : 
    1488         [ +  - ]:         16 :         rval = _mbImpl->add_parent_child( newFace, new_geo_edge );
    1489 [ -  + ][ #  # ]:         16 :         MBERRORR( rval, "can't add parent child relations for new edge" );
                 [ #  # ]
    1490                 :            :         // add senses
    1491                 :            :         // sense newFace is 1, old face is -1
    1492         [ +  - ]:         16 :         rval = _my_geomTopoTool->set_sense( new_geo_edge, newFace, 1 );
    1493 [ -  + ][ #  # ]:         16 :         MBERRORR( rval, "can't set sense for new edge" );
                 [ #  # ]
    1494                 :            : 
    1495         [ +  - ]:         16 :         rval = _my_geomTopoTool->set_sense( new_geo_edge, face, -1 );
    1496 [ -  + ][ #  # ]:         16 :         MBERRORR( rval, "can't set sense for new edge in original face" );
                 [ #  # ]
    1497                 :            :     }
    1498                 :            : 
    1499         [ +  - ]:          4 :     rval = set_neumann_tags( face, newFace );
    1500 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't set NEUMANN set tags" );
                 [ #  # ]
    1501                 :            : 
    1502                 :            :     // now, we should remove from the original set all tris, and put the "second" range
    1503         [ +  - ]:          4 :     rval = _mbImpl->remove_entities( face, iniTris );
    1504 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't remove original tris from initial face set" );
                 [ #  # ]
    1505                 :            : 
    1506         [ +  - ]:          4 :     rval = _mbImpl->add_entities( face, second );
    1507 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't add second range to the original set" );
                 [ #  # ]
    1508                 :            : 
    1509         [ +  + ]:          4 :     if( !closed )
    1510                 :            :     {
    1511         [ +  - ]:          1 :         rval = redistribute_boundary_edges_to_faces( face, newFace, chainedEdges );
    1512 [ -  + ][ #  # ]:          1 :         MBERRORR( rval, "fail to reset the proper boundary faces" );
                 [ #  # ]
    1513                 :            :     }
    1514                 :            : 
    1515                 :            :     /*if (_smooth)
    1516                 :            :       delete_smooth_tags();// they need to be recomputed, anyway
    1517                 :            :     // this will remove the extra smooth faces and edges
    1518                 :            :     clean();*/
    1519                 :            :     // also, these nodes need to be moved to the smooth surface, sometimes before deleting the old
    1520                 :            :     // triangles
    1521                 :            :     // remove the triangles from the set, then delete triangles (also some edges need to be
    1522                 :            :     // deleted!)
    1523         [ +  - ]:          4 :     rval = _mbImpl->delete_entities( _piercedTriangles );
    1524                 :            : 
    1525 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't delete triangles" );
                 [ #  # ]
    1526         [ +  - ]:          4 :     _piercedTriangles.clear();
    1527                 :            :     // delete edges that are broke up in 2
    1528         [ +  - ]:          4 :     rval = _mbImpl->delete_entities( _piercedEdges );
    1529 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't delete edges" );
                 [ #  # ]
    1530         [ +  - ]:          4 :     _piercedEdges.clear();
    1531                 :            : 
    1532         [ -  + ]:          4 :     if( debug_splits )
    1533                 :            :     {
    1534         [ #  # ]:          0 :         _mbImpl->write_file( "newFace.vtk", "vtk", 0, &newFace, 1 );
    1535         [ #  # ]:          0 :         _mbImpl->write_file( "leftoverFace.vtk", "vtk", 0, &face, 1 );
    1536                 :            :     }
    1537                 :          8 :     return MB_SUCCESS;
    1538                 :            : }
    1539                 :            : 
    1540                 :          4 : ErrorCode FBEngine::smooth_new_intx_points( EntityHandle face, std::vector< EntityHandle >& chainedEdges )
    1541                 :            : {
    1542                 :            : 
    1543                 :            :     // do not move nodes from the original face
    1544                 :            :     // first get all triangles, and then all nodes from those triangles
    1545                 :            : 
    1546         [ +  - ]:          4 :     Range tris;
    1547         [ +  - ]:          4 :     ErrorCode rval = _mbImpl->get_entities_by_type( face, MBTRI, tris );
    1548 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't get triangles" );
                 [ #  # ]
    1549                 :            : 
    1550         [ +  - ]:          8 :     Range ini_nodes;
    1551         [ +  - ]:          4 :     rval = _mbImpl->get_connectivity( tris, ini_nodes );
    1552 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't get connectivities" );
                 [ #  # ]
    1553                 :            : 
    1554         [ +  - ]:          4 :     SmoothFace* smthFace = _faces[face];
    1555                 :            : 
    1556                 :            :     // get all nodes from chained edges
    1557         [ +  - ]:          8 :     Range mesh_edges;
    1558         [ +  + ]:         20 :     for( unsigned int j = 0; j < chainedEdges.size(); j++ )
    1559                 :            :     {
    1560                 :            :         // keep adding to the range of mesh edges
    1561 [ +  - ][ +  - ]:         16 :         rval = _mbImpl->get_entities_by_dimension( chainedEdges[j], 1, mesh_edges );
    1562 [ -  + ][ #  # ]:         16 :         MBERRORR( rval, "can't get mesh edges" );
                 [ #  # ]
    1563                 :            :     }
    1564                 :            :     // nodes along polyline
    1565         [ +  - ]:          8 :     Range nodes_on_polyline;
    1566         [ +  - ]:          4 :     rval = _mbImpl->get_connectivity( mesh_edges, nodes_on_polyline, true );  // corners only
    1567 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't get nodes on the polyline" );
                 [ #  # ]
    1568                 :            : 
    1569         [ +  - ]:          8 :     Range new_intx_nodes = subtract( nodes_on_polyline, ini_nodes );
    1570                 :            : 
    1571         [ +  - ]:          8 :     std::vector< double > ini_coords;
    1572         [ +  - ]:          4 :     int num_points = (int)new_intx_nodes.size();
    1573         [ +  - ]:          4 :     ini_coords.resize( 3 * num_points );
    1574 [ +  - ][ +  - ]:          4 :     rval = _mbImpl->get_coords( new_intx_nodes, &( ini_coords[0] ) );
    1575 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't get coordinates" );
                 [ #  # ]
    1576                 :            : 
    1577                 :          4 :     int i = 0;
    1578 [ +  - ][ +  - ]:       1759 :     for( Range::iterator it = new_intx_nodes.begin(); it != new_intx_nodes.end(); ++it )
         [ +  - ][ +  - ]
                 [ +  + ]
    1579                 :            :     {
    1580                 :            :         /*EntityHandle node = *it;*/
    1581                 :       1755 :         int i3 = 3 * i;
    1582 [ +  - ][ +  - ]:       1755 :         smthFace->move_to_surface( ini_coords[i3], ini_coords[i3 + 1], ini_coords[i3 + 2] );
         [ +  - ][ +  - ]
    1583                 :            :         // reset the coordinates of this node
    1584                 :       1755 :         ++i;
    1585                 :            :     }
    1586 [ +  - ][ +  - ]:          4 :     rval = _mbImpl->set_coords( new_intx_nodes, &( ini_coords[0] ) );
                 [ +  - ]
    1587 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't set smoothed coordinates for the new nodes" );
                 [ #  # ]
    1588                 :            : 
    1589                 :          8 :     return MB_SUCCESS;
    1590                 :            : }
    1591                 :            : // we will use the fact that the splitting edge is oriented right now
    1592                 :            : // to the left will be new face, to the right, old face
    1593                 :            : // (to the left, positively oriented triangles)
    1594                 :          4 : ErrorCode FBEngine::separate( EntityHandle face, std::vector< EntityHandle >& chainedEdges, Range& first,
    1595                 :            :                               Range& second )
    1596                 :            : {
    1597                 :            :     // Range unaffectedTriangles = subtract(iniTriangles, _piercedTriangles);
    1598                 :            :     // insert in each
    1599                 :            :     // start with a new triangle, and flood to get the first range; what is left is the
    1600                 :            :     // second range
    1601                 :            :     // flood fill is considering edges adjacent to seed triangles; if there is
    1602                 :            :     //  an edge in the new_geo_edge, it is skipped; triangles in the
    1603                 :            :     // triangles to delete are not added
    1604                 :            :     // first, create all edges of the new triangles
    1605                 :            : 
    1606                 :            :     //
    1607                 :            :     // new face will have the new edge oriented positively
    1608                 :            :     // get mesh edges from geo edge (splitting gedge);
    1609                 :            : 
    1610         [ +  - ]:          4 :     Range mesh_edges;
    1611                 :            :     ErrorCode rval;
    1612                 :            :     // mesh_edges
    1613         [ +  + ]:         20 :     for( unsigned int j = 0; j < chainedEdges.size(); j++ )
    1614                 :            :     {
    1615                 :            :         // this will keep adding edges to the mesh_edges range
    1616                 :            :         // when we get out, the mesh_edges will be in this range, but not ordered
    1617 [ +  - ][ +  - ]:         16 :         rval = _mbImpl->get_entities_by_type( chainedEdges[j], MBEDGE, mesh_edges );
    1618 [ -  + ][ #  # ]:         16 :         MBERRORR( rval, "can't get new polyline edges" );
                 [ #  # ]
    1619         [ -  + ]:         16 :         if( debug_splits )
    1620                 :            :         {
    1621 [ #  # ][ #  # ]:          0 :             std::cout << " At chained edge " << j << " " << _mbImpl->id_from_handle( chainedEdges[j] )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1622 [ #  # ][ #  # ]:          0 :                       << " mesh_edges Range size:" << mesh_edges.size() << "\n";
         [ #  # ][ #  # ]
    1623                 :            :         }
    1624                 :            :     }
    1625                 :            : 
    1626                 :            :     // get a positive triangle adjacent to mesh_edge[0]
    1627                 :            :     // add to first triangles to the left, second triangles to the right of the mesh_edges ;
    1628                 :            : 
    1629                 :            :     // create a temp tag, and when done, delete it
    1630                 :            :     // default value: 0
    1631                 :            :     // 3 to be deleted, pierced
    1632                 :            :     // 1 first set
    1633                 :            :     // 2 second set
    1634                 :            :     // create the tag also for control points on the edges
    1635                 :          4 :     int defVal = 0;
    1636                 :            :     Tag separateTag;
    1637         [ +  - ]:          4 :     rval = MBI->tag_get_handle( "SEPARATE_TAG", 1, MB_TYPE_INTEGER, separateTag, MB_TAG_DENSE | MB_TAG_CREAT, &defVal );
    1638 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't create temp tag for separation" );
                 [ #  # ]
    1639                 :            :     // the deleted triangles will get a value 3, from start
    1640                 :          4 :     int delVal = 3;
    1641 [ +  - ][ +  - ]:       1792 :     for( Range::iterator it1 = this->_piercedTriangles.begin(); it1 != _piercedTriangles.end(); ++it1 )
         [ +  - ][ +  - ]
                 [ +  + ]
    1642                 :            :     {
    1643         [ +  - ]:       1788 :         EntityHandle trToDelete = *it1;
    1644         [ +  - ]:       1788 :         rval                    = _mbImpl->tag_set_data( separateTag, &trToDelete, 1, &delVal );
    1645 [ -  + ][ #  # ]:       1788 :         MBERRORR( rval, "can't set delete tag value" );
                 [ #  # ]
    1646                 :            :     }
    1647                 :            : 
    1648                 :            :     // find a triangle that will be in the first range, positively oriented about the splitting edge
    1649                 :          4 :     EntityHandle seed1 = 0;
    1650 [ +  - ][ +  - ]:          8 :     for( Range::iterator it = mesh_edges.begin(); it != mesh_edges.end() && !seed1; ++it )
         [ +  - ][ +  - ]
         [ +  - ][ +  + ]
                 [ +  - ]
           [ +  +  #  # ]
    1651                 :            :     {
    1652         [ +  - ]:          4 :         EntityHandle meshEdge = *it;
    1653         [ +  - ]:          4 :         Range adj_tri;
    1654         [ +  - ]:          4 :         rval = _mbImpl->get_adjacencies( &meshEdge, 1, 2, false, adj_tri );
    1655 [ -  + ][ #  # ]:          4 :         MBERRORR( rval, "can't get adj_tris to mesh edge" );
                 [ #  # ]
    1656                 :            : 
    1657 [ +  - ][ +  - ]:         12 :         for( Range::iterator it2 = adj_tri.begin(); it2 != adj_tri.end(); ++it2 )
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    1658                 :            :         {
    1659         [ +  - ]:          8 :             EntityHandle tr = *it2;
    1660 [ +  - ][ +  - ]:          8 :             if( _piercedTriangles.find( tr ) != _piercedTriangles.end() )
         [ +  - ][ -  + ]
    1661                 :          0 :                 continue;  // do not attach pierced triangles, they are not good
    1662                 :            :             int num1, sense, offset;
    1663         [ +  - ]:          8 :             rval = _mbImpl->side_number( tr, meshEdge, num1, sense, offset );
    1664 [ -  + ][ #  # ]:          8 :             MBERRORR( rval, "edge not adjacent" );
                 [ #  # ]
    1665         [ +  + ]:          8 :             if( sense == 1 )
    1666                 :            :             {
    1667                 :            :                 // firstSet.insert(tr);
    1668         [ +  - ]:          4 :                 if( !seed1 )
    1669                 :            :                 {
    1670                 :          4 :                     seed1 = tr;
    1671                 :          8 :                     break;
    1672                 :            :                 }
    1673                 :            :             }
    1674                 :            :         }
    1675                 :          4 :     }
    1676                 :            : 
    1677                 :            :     // flood fill first set, the rest will be in second set
    1678                 :            :     // the edges from new_geo_edge will not be crossed
    1679                 :            : 
    1680                 :            :     // get edges of face (adjacencies)
    1681                 :            :     // also get the old boundary edges, from face; they will be edges to not cross, too
    1682         [ +  - ]:          8 :     Range bound_edges;
    1683         [ +  - ]:          4 :     rval = getAdjacentEntities( face, 1, bound_edges );
    1684 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't get boundary edges" );
                 [ #  # ]
    1685                 :            : 
    1686                 :            :     // add to the do not cross edges range, all edges from initial boundary
    1687         [ +  - ]:          8 :     Range initialBoundaryEdges;
    1688 [ +  - ][ +  - ]:         10 :     for( Range::iterator it = bound_edges.begin(); it != bound_edges.end(); ++it )
         [ +  - ][ +  - ]
                 [ +  + ]
    1689                 :            :     {
    1690         [ +  - ]:          6 :         EntityHandle bound_edge = *it;
    1691         [ +  - ]:          6 :         rval                    = _mbImpl->get_entities_by_dimension( bound_edge, 1, initialBoundaryEdges );
    1692                 :            :     }
    1693                 :            : 
    1694         [ +  - ]:          8 :     Range doNotCrossEdges = unite( initialBoundaryEdges, mesh_edges );  // add the splitting edges !
    1695                 :            : 
    1696                 :            :     // use a second method, with tags
    1697                 :            :     //
    1698 [ +  - ][ +  - ]:          8 :     std::queue< EntityHandle > queue1;
    1699         [ +  - ]:          4 :     queue1.push( seed1 );
    1700         [ +  - ]:          8 :     std::vector< EntityHandle > arr1;
    1701 [ +  - ][ +  + ]:      17575 :     while( !queue1.empty() )
    1702                 :            :     {
    1703                 :            :         // start copy
    1704         [ +  - ]:      17571 :         EntityHandle currentTriangle = queue1.front();
    1705         [ +  - ]:      17571 :         queue1.pop();
    1706         [ +  - ]:      17571 :         arr1.push_back( currentTriangle );
    1707                 :            :         // add new triangles that share an edge
    1708         [ +  - ]:      17571 :         Range currentEdges;
    1709         [ +  - ]:      17571 :         rval = _mbImpl->get_adjacencies( &currentTriangle, 1, 1, true, currentEdges, Interface::UNION );
    1710 [ -  + ][ #  # ]:      17571 :         MBERRORR( rval, "can't get adjacencies" );
                 [ #  # ]
    1711 [ +  - ][ +  - ]:      70284 :         for( Range::iterator it = currentEdges.begin(); it != currentEdges.end(); ++it )
         [ +  - ][ +  - ]
         [ +  + ][ +  - ]
    1712                 :            :         {
    1713         [ +  - ]:      52713 :             EntityHandle frontEdge = *it;
    1714 [ +  - ][ +  - ]:      52713 :             if( doNotCrossEdges.find( frontEdge ) == doNotCrossEdges.end() )
         [ +  - ][ +  + ]
    1715                 :            :             {
    1716                 :            :                 // this is an edge that can be crossed
    1717         [ +  - ]:      50828 :                 Range adj_tri;
    1718         [ +  - ]:      50828 :                 rval = _mbImpl->get_adjacencies( &frontEdge, 1, 2, false, adj_tri, Interface::UNION );
    1719 [ -  + ][ #  # ]:      50828 :                 MBERRORR( rval, "can't get adj_tris" );
                 [ #  # ]
    1720                 :            :                 // if the triangle is not in first range, add it to the queue
    1721 [ +  - ][ +  - ]:     154336 :                 for( Range::iterator it2 = adj_tri.begin(); it2 != adj_tri.end(); ++it2 )
         [ +  - ][ +  - ]
         [ +  + ][ +  - ]
    1722                 :            :                 {
    1723         [ +  - ]:     103508 :                     EntityHandle tri2 = *it2;
    1724                 :     103508 :                     int val           = 0;
    1725         [ +  - ]:     103508 :                     rval              = _mbImpl->tag_get_data( separateTag, &tri2, 1, &val );
    1726 [ -  + ][ #  # ]:     103508 :                     MBERRORR( rval, "can't get tag value" );
                 [ #  # ]
    1727         [ +  + ]:     103508 :                     if( val ) continue;
    1728                 :            :                     // else, set it to 1
    1729                 :      17567 :                     val  = 1;
    1730         [ +  - ]:      17567 :                     rval = _mbImpl->tag_set_data( separateTag, &tri2, 1, &val );
    1731 [ -  + ][ #  # ]:      17567 :                     MBERRORR( rval, "can't get tag value" );
                 [ #  # ]
    1732                 :            : 
    1733         [ +  - ]:      17567 :                     queue1.push( tri2 );
    1734                 :      50828 :                 }
    1735                 :            :             }  // end edge do not cross
    1736                 :            :         }      // end while
    1737                 :      17571 :     }
    1738                 :            : 
    1739         [ +  - ]:          4 :     std::sort( arr1.begin(), arr1.end() );
    1740                 :            :     // Range first1;
    1741 [ +  - ][ +  - ]:          4 :     std::copy( arr1.rbegin(), arr1.rend(), range_inserter( first ) );
    1742                 :            : 
    1743                 :            :     // std::cout<< "\n first1.size() " << first1.size() << " first.size(): " << first.size() <<
    1744                 :            :     // "\n";
    1745         [ -  + ]:          4 :     if( debug_splits )
    1746                 :            :     {
    1747                 :            :         EntityHandle tmpSet;
    1748         [ #  # ]:          0 :         _mbImpl->create_meshset( MESHSET_SET, tmpSet );
    1749         [ #  # ]:          0 :         _mbImpl->add_entities( tmpSet, first );
    1750         [ #  # ]:          0 :         _mbImpl->write_file( "dbg1.vtk", "vtk", 0, &tmpSet, 1 );
    1751                 :            :     }
    1752                 :            :     // now, decide the set 2:
    1753                 :            :     // first, get all ini tris
    1754         [ +  - ]:          8 :     Range initr;
    1755         [ +  - ]:          4 :     rval = _mbImpl->get_entities_by_type( face, MBTRI, initr );
    1756 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't get tris " );
                 [ #  # ]
    1757 [ +  - ][ +  - ]:          4 :     second        = unite( initr, _newTriangles );
    1758         [ +  - ]:          8 :     Range second2 = subtract( second, _piercedTriangles );
    1759 [ +  - ][ +  - ]:          4 :     second        = subtract( second2, first );
    1760         [ +  - ]:          4 :     _newTriangles.clear();
    1761         [ -  + ]:          4 :     if( debug_splits )
    1762                 :            :     {
    1763 [ #  # ][ #  # ]:          0 :         std::cout << "\n second.size() " << second.size() << " first.size(): " << first.size() << "\n";
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1764                 :            :         // debugging code
    1765                 :            :         EntityHandle tmpSet2;
    1766         [ #  # ]:          0 :         _mbImpl->create_meshset( MESHSET_SET, tmpSet2 );
    1767         [ #  # ]:          0 :         _mbImpl->add_entities( tmpSet2, second );
    1768         [ #  # ]:          0 :         _mbImpl->write_file( "dbg2.vtk", "vtk", 0, &tmpSet2, 1 );
    1769                 :            :     }
    1770                 :            :     /*Range intex = intersect(first, second);
    1771                 :            :     if (!intex.empty() && debug_splits)
    1772                 :            :     {
    1773                 :            :       std::cout << "error, the sets should be disjoint\n";
    1774                 :            :       for (Range::iterator it1=intex.begin(); it1!=intex.end(); ++it1)
    1775                 :            :       {
    1776                 :            :         std::cout<<_mbImpl->id_from_handle(*it1) << "\n";
    1777                 :            :       }
    1778                 :            :     }*/
    1779         [ +  - ]:          4 :     rval = _mbImpl->tag_delete( separateTag );
    1780 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't delete tag " );
                 [ #  # ]
    1781                 :          8 :     return MB_SUCCESS;
    1782                 :            : }
    1783                 :            : // if there is an edge between 2 nodes, then check it's orientation, and revert it if needed
    1784                 :         16 : ErrorCode FBEngine::create_new_gedge( std::vector< EntityHandle >& nodesAlongPolyline, EntityHandle& new_geo_edge )
    1785                 :            : {
    1786                 :            : 
    1787         [ +  - ]:         16 :     ErrorCode rval = _mbImpl->create_meshset( MESHSET_ORDERED, new_geo_edge );
    1788 [ -  + ][ #  # ]:         16 :     MBERRORR( rval, "can't create geo edge" );
                 [ #  # ]
    1789                 :            : 
    1790                 :            :     // now, get the edges, or create if not existing
    1791         [ +  - ]:         16 :     std::vector< EntityHandle > mesh_edges;
    1792         [ +  + ]:       1791 :     for( unsigned int i = 0; i < nodesAlongPolyline.size() - 1; i++ )
    1793                 :            :     {
    1794 [ +  - ][ +  - ]:       1775 :         EntityHandle n1 = nodesAlongPolyline[i], n2 = nodesAlongPolyline[i + 1];
    1795                 :            : 
    1796                 :            :         EntityHandle nn2[2];
    1797                 :       1775 :         nn2[0] = n1;
    1798                 :       1775 :         nn2[1] = n2;
    1799                 :            : 
    1800         [ +  - ]:       1775 :         std::vector< EntityHandle > adjacent;
    1801         [ +  - ]:       1775 :         rval = _mbImpl->get_adjacencies( nn2, 2, 1, false, adjacent, Interface::INTERSECT );
    1802                 :            :         // see if there is an edge between those 2 already, and if it is oriented as we like
    1803                 :       1775 :         bool new_edge = true;
    1804         [ -  + ]:       1775 :         if( adjacent.size() >= 1 )
    1805                 :            :         {
    1806                 :            :             // check the orientation
    1807                 :          0 :             const EntityHandle* conn2 = NULL;
    1808                 :          0 :             int nnodes                = 0;
    1809 [ #  # ][ #  # ]:          0 :             rval                      = _mbImpl->get_connectivity( adjacent[0], conn2, nnodes );
    1810 [ #  # ][ #  # ]:          0 :             MBERRORR( rval, "can't get connectivity" );
                 [ #  # ]
    1811 [ #  # ][ #  # ]:          0 :             if( conn2[0] == nn2[0] && conn2[1] == nn2[1] )
    1812                 :            :             {
    1813                 :            :                 // everything is fine
    1814 [ #  # ][ #  # ]:          0 :                 mesh_edges.push_back( adjacent[0] );
    1815                 :          0 :                 new_edge = false;  // we found one that's good, no need to create a new one
    1816                 :            :             }
    1817                 :            :             else
    1818                 :            :             {
    1819 [ #  # ][ #  # ]:          0 :                 _piercedEdges.insert( adjacent[0] );  // we want to remove this one, it will be not needed
    1820                 :            :             }
    1821                 :            :         }
    1822         [ +  - ]:       1775 :         if( new_edge )
    1823                 :            :         {
    1824                 :            :             // there is no edge between n1 and n2, create one
    1825                 :            :             EntityHandle mesh_edge;
    1826         [ +  - ]:       1775 :             rval = _mbImpl->create_element( MBEDGE, nn2, 2, mesh_edge );
    1827 [ -  + ][ #  # ]:       1775 :             MBERRORR( rval, "Failed to create a new edge" );
                 [ #  # ]
    1828 [ +  - ][ +  - ]:       1775 :             mesh_edges.push_back( mesh_edge );
    1829                 :            :         }
    1830                 :       1775 :     }
    1831                 :            : 
    1832                 :            :     // add loops edges to the edge set
    1833         [ +  - ]:         16 :     rval = _mbImpl->add_entities( new_geo_edge, &mesh_edges[0],
    1834         [ +  - ]:         32 :                                   mesh_edges.size() );  // only one edge
    1835 [ -  + ][ #  # ]:         16 :     MBERRORR( rval, "can't add edges to new_geo_set" );
                 [ #  # ]
    1836                 :            :     // check vertex sets for vertex 1 and vertex 2?
    1837                 :            :     // get all sets of dimension 0 from database, and see if our ends are here or not
    1838                 :            : 
    1839         [ +  - ]:         32 :     Range ends_geo_edge;
    1840 [ +  - ][ +  - ]:         16 :     ends_geo_edge.insert( nodesAlongPolyline[0] );
    1841 [ +  - ][ +  - ]:         16 :     ends_geo_edge.insert( nodesAlongPolyline[nodesAlongPolyline.size() - 1] );
    1842                 :            : 
    1843 [ +  - ][ +  + ]:         48 :     for( unsigned int k = 0; k < ends_geo_edge.size(); k++ )
    1844                 :            :     {
    1845         [ +  - ]:         32 :         EntityHandle node = ends_geo_edge[k];
    1846                 :            :         EntityHandle nodeSet;
    1847         [ +  - ]:         32 :         bool found = find_vertex_set_for_node( node, nodeSet );
    1848                 :            : 
    1849         [ +  + ]:         32 :         if( !found )
    1850                 :            :         {
    1851                 :            :             // create a node set and add the node
    1852                 :            : 
    1853         [ +  - ]:         17 :             rval = _mbImpl->create_meshset( MESHSET_SET, nodeSet );
    1854 [ -  + ][ #  # ]:         17 :             MBERRORR( rval, "Failed to create a new vertex set" );
                 [ #  # ]
    1855                 :            : 
    1856         [ +  - ]:         17 :             rval = _mbImpl->add_entities( nodeSet, &node, 1 );
    1857 [ -  + ][ #  # ]:         17 :             MBERRORR( rval, "Failed to add the node to the set" );
                 [ #  # ]
    1858                 :            : 
    1859         [ +  - ]:         17 :             rval = _my_geomTopoTool->add_geo_set( nodeSet, 0 );  //
    1860 [ -  + ][ #  # ]:         17 :             MBERRORR( rval, "Failed to commit the node set" );
                 [ #  # ]
    1861                 :            : 
    1862         [ -  + ]:         17 :             if( debug_splits )
    1863                 :            :             {
    1864 [ #  # ][ #  # ]:          0 :                 std::cout << " create a vertex set " << _mbImpl->id_from_handle( nodeSet )
                 [ #  # ]
    1865 [ #  # ][ #  # ]:          0 :                           << " global id:" << this->_my_geomTopoTool->global_id( nodeSet ) << " for node " << node
         [ #  # ][ #  # ]
                 [ #  # ]
    1866         [ #  # ]:          0 :                           << "\n";
    1867                 :            :             }
    1868                 :            :         }
    1869                 :            : 
    1870         [ +  - ]:         32 :         rval = _mbImpl->add_parent_child( new_geo_edge, nodeSet );
    1871 [ -  + ][ #  # ]:         32 :         MBERRORR( rval, "Failed to add parent child relation" );
                 [ #  # ]
    1872                 :            :     }
    1873                 :            :     // finally, put the edge in the range of edges
    1874 [ +  - ][ -  + ]:         16 :     rval = _my_geomTopoTool->add_geo_set( new_geo_edge, 1 );MB_CHK_ERR( rval );
         [ #  # ][ #  # ]
    1875                 :            : 
    1876                 :         32 :     return rval;
    1877                 :            : }
    1878                 :            : 
    1879                 :          0 : void FBEngine::print_debug_triangle( EntityHandle t )
    1880                 :            : {
    1881 [ #  # ][ #  # ]:          0 :     std::cout << " triangle id:" << _mbImpl->id_from_handle( t ) << "\n";
         [ #  # ][ #  # ]
    1882                 :          0 :     const EntityHandle* conn3 = NULL;
    1883                 :          0 :     int nnodes                = 0;
    1884         [ #  # ]:          0 :     _mbImpl->get_connectivity( t, conn3, nnodes );
    1885                 :            :     // get coords
    1886 [ #  # ][ #  # ]:          0 :     CartVect P[3];
    1887         [ #  # ]:          0 :     _mbImpl->get_coords( conn3, 3, (double*)&P[0] );
    1888 [ #  # ][ #  # ]:          0 :     std::cout << "  nodes:" << conn3[0] << " " << conn3[1] << " " << conn3[2] << "\n";
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1889 [ #  # ][ #  # ]:          0 :     CartVect PP[3];
    1890         [ #  # ]:          0 :     PP[0] = P[1] - P[0];
    1891         [ #  # ]:          0 :     PP[1] = P[2] - P[1];
    1892         [ #  # ]:          0 :     PP[2] = P[0] - P[2];
    1893                 :            : 
    1894 [ #  # ][ #  # ]:          0 :     std::cout << "  pos:" << P[0] << " " << P[1] << " " << P[2] << "\n";
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1895 [ #  # ][ #  # ]:          0 :     std::cout << "   x,y diffs " << PP[0][0] << " " << PP[0][1] << ",  " << PP[1][0] << " " << PP[1][1] << ",  "
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1896 [ #  # ][ #  # ]:          0 :               << PP[2][0] << " " << PP[2][1] << "\n";
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1897                 :          0 :     return;
    1898                 :            : }
    1899                 :            : // actual breaking of triangles
    1900                 :            : // case 1: n2 interior to triangle
    1901                 :          0 : ErrorCode FBEngine::BreakTriangle( EntityHandle, EntityHandle, EntityHandle, EntityHandle, EntityHandle, EntityHandle )
    1902                 :            : {
    1903                 :          0 :     std::cout << "FBEngine::BreakTriangle not implemented yet\n";
    1904                 :          0 :     return MB_FAILURE;
    1905                 :            : }
    1906                 :            : // case 2, n1 and n2 on boundary
    1907                 :       1775 : ErrorCode FBEngine::BreakTriangle2( EntityHandle tri, EntityHandle e1, EntityHandle e2, EntityHandle n1,
    1908                 :            :                                     EntityHandle n2 )  // nodesAlongPolyline are on entities!
    1909                 :            : {
    1910                 :            :     // we have the nodes, we just need to reconnect to form new triangles
    1911                 :            :     ErrorCode rval;
    1912                 :       1775 :     const EntityHandle* conn3 = NULL;
    1913                 :       1775 :     int nnodes                = 0;
    1914         [ +  - ]:       1775 :     rval                      = _mbImpl->get_connectivity( tri, conn3, nnodes );
    1915 [ -  + ][ #  # ]:       1775 :     MBERRORR( rval, "Failed to get connectivity" );
                 [ #  # ]
    1916         [ -  + ]:       1775 :     assert( 3 == nnodes );
    1917                 :            : 
    1918         [ +  - ]:       1775 :     EntityType et1 = _mbImpl->type_from_handle( e1 );
    1919         [ +  - ]:       1775 :     EntityType et2 = _mbImpl->type_from_handle( e2 );
    1920                 :            : 
    1921         [ +  + ]:       1775 :     if( MBVERTEX == et1 )
    1922                 :            :     {
    1923                 :            :         // find the vertex in conn3, and form 2 other triangles
    1924                 :         31 :         int index = -1;
    1925         [ +  - ]:         64 :         for( index = 0; index < 3; index++ )
    1926                 :            :         {
    1927         [ +  + ]:         64 :             if( conn3[index] == e1 )  // also n1
    1928                 :         31 :                 break;
    1929                 :            :         }
    1930         [ -  + ]:         31 :         if( index == 3 ) return MB_FAILURE;
    1931                 :            :         // 2 triangles: n1, index+1, n2, and n1, n2, index+2
    1932                 :         31 :         EntityHandle conn[6] = { n1, conn3[( index + 1 ) % 3], n2, n1, n2, conn3[( index + 2 ) % 3] };
    1933                 :            :         EntityHandle newTriangle;
    1934         [ +  - ]:         31 :         rval = _mbImpl->create_element( MBTRI, conn, 3, newTriangle );
    1935 [ -  + ][ #  # ]:         31 :         MBERRORR( rval, "Failed to create a new triangle" );
                 [ #  # ]
    1936         [ +  - ]:         31 :         _newTriangles.insert( newTriangle );
    1937 [ -  + ][ #  # ]:         31 :         if( debug_splits ) print_debug_triangle( newTriangle );
    1938         [ +  - ]:         31 :         rval = _mbImpl->create_element( MBTRI, conn + 3, 3, newTriangle );  // the second triangle
    1939 [ -  + ][ #  # ]:         31 :         MBERRORR( rval, "Failed to create a new triangle" );
                 [ #  # ]
    1940         [ +  - ]:         31 :         _newTriangles.insert( newTriangle );
    1941 [ -  + ][ #  # ]:         31 :         if( debug_splits ) print_debug_triangle( newTriangle );
    1942                 :            :     }
    1943         [ +  + ]:       1744 :     else if( MBVERTEX == et2 )
    1944                 :            :     {
    1945                 :         31 :         int index = -1;
    1946         [ +  - ]:         72 :         for( index = 0; index < 3; index++ )
    1947                 :            :         {
    1948         [ +  + ]:         72 :             if( conn3[index] == e2 )  // also n2
    1949                 :         31 :                 break;
    1950                 :            :         }
    1951         [ -  + ]:         31 :         if( index == 3 ) return MB_FAILURE;
    1952                 :            :         // 2 triangles: n1, index+1, n2, and n1, n2, index+2
    1953                 :         31 :         EntityHandle conn[6] = { n2, conn3[( index + 1 ) % 3], n1, n2, n1, conn3[( index + 2 ) % 3] };
    1954                 :            :         EntityHandle newTriangle;
    1955         [ +  - ]:         31 :         rval = _mbImpl->create_element( MBTRI, conn, 3, newTriangle );
    1956 [ -  + ][ #  # ]:         31 :         MBERRORR( rval, "Failed to create a new triangle" );
                 [ #  # ]
    1957         [ +  - ]:         31 :         _newTriangles.insert( newTriangle );
    1958 [ -  + ][ #  # ]:         31 :         if( debug_splits ) print_debug_triangle( newTriangle );
    1959         [ +  - ]:         31 :         rval = _mbImpl->create_element( MBTRI, conn + 3, 3, newTriangle );  // the second triangle
    1960 [ -  + ][ #  # ]:         31 :         MBERRORR( rval, "Failed to create a new triangle" );
                 [ #  # ]
    1961         [ +  - ]:         31 :         _newTriangles.insert( newTriangle );
    1962 [ -  + ][ #  # ]:         31 :         if( debug_splits ) print_debug_triangle( newTriangle );
    1963                 :            :     }
    1964                 :            :     else
    1965                 :            :     {
    1966                 :            :         // both are edges adjacent to triangle tri
    1967                 :            :         // there are several configurations possible for n1, n2, between conn3 nodes.
    1968                 :            :         int num1, num2, sense, offset;
    1969         [ +  - ]:       1713 :         rval = _mbImpl->side_number( tri, e1, num1, sense, offset );
    1970 [ -  + ][ #  # ]:       1713 :         MBERRORR( rval, "edge not adjacent" );
                 [ #  # ]
    1971                 :            : 
    1972         [ +  - ]:       1713 :         rval = _mbImpl->side_number( tri, e2, num2, sense, offset );
    1973 [ -  + ][ #  # ]:       1713 :         MBERRORR( rval, "edge not adjacent" );
                 [ #  # ]
    1974                 :            : 
    1975                 :            :         const EntityHandle* conn12;  // connectivity for edge 1
    1976                 :            :         const EntityHandle* conn22;  // connectivity for edge 2
    1977                 :            :         // int nnodes;
    1978         [ +  - ]:       1713 :         rval = _mbImpl->get_connectivity( e1, conn12, nnodes );
    1979 [ -  + ][ #  # ]:       1713 :         MBERRORR( rval, "Failed to get connectivity of edge 1" );
                 [ #  # ]
    1980         [ -  + ]:       1713 :         assert( 2 == nnodes );
    1981         [ +  - ]:       1713 :         rval = _mbImpl->get_connectivity( e2, conn22, nnodes );
    1982 [ -  + ][ #  # ]:       1713 :         MBERRORR( rval, "Failed to get connectivity of edge 2" );
                 [ #  # ]
    1983         [ -  + ]:       1713 :         assert( 2 == nnodes );
    1984                 :            :         // now, having the side number, work through
    1985         [ -  + ]:       1713 :         if( debug_splits )
    1986                 :            :         {
    1987 [ #  # ][ #  # ]:          0 :             std::cout << "tri conn3:" << conn3[0] << " " << conn3[1] << " " << conn3[2] << "\n";
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1988 [ #  # ][ #  # ]:          0 :             std::cout << " edge1: conn12:" << conn12[0] << " " << conn12[1] << "  side: " << num1 << "\n";
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1989 [ #  # ][ #  # ]:          0 :             std::cout << " edge2: conn22:" << conn22[0] << " " << conn22[1] << "  side: " << num2 << "\n";
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1990                 :            :         }
    1991                 :       1713 :         int unaffectedSide = 3 - num1 - num2;
    1992                 :       1713 :         int i3             = ( unaffectedSide + 2 ) % 3;  // to 0 is 2, to 1 is 0, to 2 is 1
    1993                 :            :         // triangles will be formed with triVertexIndex , n1, n2 (in what order?)
    1994                 :            :         EntityHandle v1, v2;  // to hold the 2 nodes on edges
    1995         [ +  + ]:       1713 :         if( num1 == i3 )
    1996                 :            :         {
    1997                 :        848 :             v1 = n1;
    1998                 :        848 :             v2 = n2;
    1999                 :            :         }
    2000                 :            :         else  // if (num2==i3)
    2001                 :            :         {
    2002                 :        865 :             v1 = n2;
    2003                 :        865 :             v2 = n1;
    2004                 :            :         }
    2005                 :            :         // three triangles are formed
    2006                 :       1713 :         int i1 = ( i3 + 1 ) % 3;
    2007                 :       1713 :         int i2 = ( i3 + 2 ) % 3;
    2008                 :            :         // we could break the surface differently
    2009                 :       1713 :         EntityHandle conn[9] = { conn3[i3], v1, v2, v1, conn3[i1], conn3[i2], v2, v1, conn3[i2] };
    2010                 :            :         EntityHandle newTriangle;
    2011 [ -  + ][ #  # ]:       1713 :         if( debug_splits ) std::cout << "Split 2 edges :\n";
    2012         [ +  - ]:       1713 :         rval = _mbImpl->create_element( MBTRI, conn, 3, newTriangle );
    2013 [ -  + ][ #  # ]:       1713 :         MBERRORR( rval, "Failed to create a new triangle" );
                 [ #  # ]
    2014         [ +  - ]:       1713 :         _newTriangles.insert( newTriangle );
    2015 [ -  + ][ #  # ]:       1713 :         if( debug_splits ) print_debug_triangle( newTriangle );
    2016         [ +  - ]:       1713 :         rval = _mbImpl->create_element( MBTRI, conn + 3, 3, newTriangle );  // the second triangle
    2017 [ -  + ][ #  # ]:       1713 :         MBERRORR( rval, "Failed to create a new triangle" );
                 [ #  # ]
    2018         [ +  - ]:       1713 :         _newTriangles.insert( newTriangle );
    2019 [ -  + ][ #  # ]:       1713 :         if( debug_splits ) print_debug_triangle( newTriangle );
    2020         [ +  - ]:       1713 :         rval = _mbImpl->create_element( MBTRI, conn + 6, 3, newTriangle );  // the second triangle
    2021 [ -  + ][ #  # ]:       1713 :         MBERRORR( rval, "Failed to create a new triangle" );
                 [ #  # ]
    2022         [ +  - ]:       1713 :         _newTriangles.insert( newTriangle );
    2023 [ -  + ][ #  # ]:       1713 :         if( debug_splits ) print_debug_triangle( newTriangle );
    2024                 :            :     }
    2025                 :            : 
    2026                 :       1775 :     return MB_SUCCESS;
    2027                 :            : }
    2028                 :            : 
    2029                 :            : // build the list of intx points and entities from database involved
    2030                 :            : // vertices, edges, triangles
    2031                 :            : // it could be just a list of vertices (easiest case to handle after)
    2032                 :            : 
    2033                 :         16 : ErrorCode FBEngine::compute_intersection_points( EntityHandle&, EntityHandle from, EntityHandle to, CartVect& Dir,
    2034                 :            :                                                  std::vector< CartVect >& points, std::vector< EntityHandle >& entities,
    2035                 :            :                                                  std::vector< EntityHandle >& triangles )
    2036                 :            : {
    2037                 :            :     // keep a stack of triangles to process, and do not add those already processed
    2038                 :            :     // either mark them, or maybe keep them in a local set?
    2039                 :            :     // from and to are now nodes, start from them
    2040 [ +  - ][ +  - ]:         16 :     CartVect p1, p2;  // the position of from and to
    2041         [ +  - ]:         16 :     ErrorCode rval = _mbImpl->get_coords( &from, 1, (double*)&p1 );
    2042 [ -  + ][ #  # ]:         16 :     MBERRORR( rval, "failed to get 'from' coordinates" );
                 [ #  # ]
    2043         [ +  - ]:         16 :     rval = _mbImpl->get_coords( &to, 1, (double*)&p2 );
    2044 [ -  + ][ #  # ]:         16 :     MBERRORR( rval, "failed to get 'from' coordinates" );
                 [ #  # ]
    2045                 :            : 
    2046         [ +  - ]:         16 :     CartVect vect( p2 - p1 );
    2047         [ +  - ]:         16 :     double dist2 = vect.length();
    2048         [ -  + ]:         16 :     if( dist2 < tolerance_segment )
    2049                 :            :     {
    2050                 :            :         // we are done, return
    2051                 :          0 :         return MB_SUCCESS;
    2052                 :            :     }
    2053         [ +  - ]:         16 :     CartVect normPlane = Dir * vect;
    2054         [ +  - ]:         16 :     normPlane.normalize();
    2055         [ +  - ]:         16 :     std::set< EntityHandle > visitedTriangles;
    2056                 :         16 :     CartVect currentPoint = p1;
    2057                 :            :     // push the current point if it is empty
    2058         [ +  - ]:         16 :     if( points.size() == 0 )
    2059                 :            :     {
    2060         [ +  - ]:         16 :         points.push_back( p1 );
    2061         [ +  - ]:         16 :         entities.push_back( from );  // this is a node now
    2062                 :            :     }
    2063                 :            : 
    2064                 :            :     // these will be used in many loops
    2065                 :         16 :     CartVect intx = p1;  // somewhere to start
    2066                 :         16 :     double param  = -1.;
    2067                 :            : 
    2068                 :            :     // first intersection
    2069                 :         16 :     EntityHandle currentBoundary = from;  // it is a node, in the beginning
    2070                 :            : 
    2071         [ +  - ]:         16 :     vect = p2 - currentPoint;
    2072 [ +  - ][ +  + ]:       1791 :     while( vect.length() > 0. )
    2073                 :            :     {
    2074                 :            :         // advance towards "to" node, from boundary handle
    2075         [ +  - ]:       1775 :         EntityType etype = _mbImpl->type_from_handle( currentBoundary );
    2076                 :            :         // if vertex, look for other triangles connected which intersect our plane (defined by p1,
    2077                 :            :         // p2, dir)
    2078         [ +  - ]:       1775 :         std::vector< EntityHandle > adj_tri;
    2079         [ +  - ]:       1775 :         rval           = _mbImpl->get_adjacencies( &currentBoundary, 1, 2, false, adj_tri );
    2080                 :       1775 :         unsigned int j = 0;
    2081                 :            :         EntityHandle tri;
    2082         [ +  + ]:       5330 :         for( ; j < adj_tri.size(); j++ )
    2083                 :            :         {
    2084         [ +  - ]:       3602 :             tri = adj_tri[j];
    2085 [ +  - ][ +  - ]:       3602 :             if( visitedTriangles.find( tri ) != visitedTriangles.end() )
                 [ +  + ]
    2086                 :       1770 :                 continue;  // get another triangle, this one was already visited
    2087                 :            :             // check if it is one of the triangles that was pierced already
    2088 [ +  - ][ +  - ]:       1856 :             if( _piercedTriangles.find( tri ) != _piercedTriangles.end() ) continue;
         [ +  - ][ +  + ]
    2089                 :            :             // if vertex, look for opposite edge
    2090                 :            :             // if edge, look for 2 opposite edges
    2091                 :            :             // get vertices
    2092                 :            :             int nnodes;
    2093                 :            :             const EntityHandle* conn3;
    2094         [ +  - ]:       1832 :             rval = _mbImpl->get_connectivity( tri, conn3, nnodes );
    2095 [ -  + ][ #  # ]:       1832 :             MBERRORR( rval, "Failed to get connectivity" );
                 [ #  # ]
    2096                 :            :             // if one of the nodes is to, stop right there
    2097                 :            :             {
    2098 [ +  + ][ +  + ]:       1832 :                 if( conn3[0] == to || conn3[1] == to || conn3[2] == to )
                 [ +  + ]
    2099                 :            :                 {
    2100         [ +  - ]:         16 :                     visitedTriangles.insert( tri );
    2101         [ +  - ]:         16 :                     triangles.push_back( tri );
    2102                 :         16 :                     currentPoint = p2;
    2103         [ +  - ]:         16 :                     points.push_back( p2 );
    2104         [ +  - ]:         16 :                     entities.push_back( to );  // we are done
    2105                 :         47 :                     break;                     // this is break from for loop, we still need to get out of while
    2106                 :            :                     // we will get out, because vect will become 0, (p2-p2)
    2107                 :            :                 }
    2108                 :            :             }
    2109                 :            :             EntityHandle nn2[2];
    2110         [ +  + ]:       1816 :             if( MBVERTEX == etype )
    2111                 :            :             {
    2112                 :         88 :                 nn2[0] = conn3[0];
    2113                 :         88 :                 nn2[1] = conn3[1];
    2114         [ +  + ]:         88 :                 if( nn2[0] == currentBoundary ) nn2[0] = conn3[2];
    2115         [ +  + ]:         88 :                 if( nn2[1] == currentBoundary ) nn2[1] = conn3[2];
    2116                 :            :                 // get coordinates
    2117 [ +  - ][ +  + ]:        264 :                 CartVect Pt[2];
    2118                 :            : 
    2119         [ +  - ]:         88 :                 rval = _mbImpl->get_coords( nn2, 2, (double*)&Pt[0] );
    2120 [ -  + ][ #  # ]:         88 :                 MBERRORR( rval, "Failed to get coordinates" );
                 [ #  # ]
    2121                 :            :                 // see the intersection
    2122 [ +  - ][ +  + ]:         88 :                 if( intersect_segment_and_plane_slice( Pt[0], Pt[1], currentPoint, p2, Dir, normPlane, intx, param ) )
    2123                 :            :                 {
    2124                 :            :                     // we should stop for loop, and decide if it is edge or vertex
    2125         [ -  + ]:         31 :                     if( param == 0. )
    2126                 :          0 :                         currentBoundary = nn2[0];
    2127                 :            :                     else
    2128                 :            :                     {
    2129         [ -  + ]:         31 :                         if( param == 1. )
    2130                 :          0 :                             currentBoundary = nn2[1];
    2131                 :            :                         else  // param between 0 and 1, so edge
    2132                 :            :                         {
    2133                 :            :                             // find the edge between vertices
    2134         [ +  - ]:         31 :                             std::vector< EntityHandle > edges1;
    2135                 :            :                             // change the create flag to true, because that edge must exist in
    2136                 :            :                             // current triangle if we want to advance; nn2 are 2 nodes in current
    2137                 :            :                             // triangle!!
    2138         [ +  - ]:         31 :                             rval = _mbImpl->get_adjacencies( nn2, 2, 1, true, edges1, Interface::INTERSECT );
    2139 [ -  + ][ #  # ]:         31 :                             MBERRORR( rval, "Failed to get edges" );
                 [ #  # ]
    2140 [ -  + ][ #  # ]:         31 :                             if( edges1.size() != 1 ) MBERRORR( MB_FAILURE, "Failed to get adjacent edges to 2 nodes" );
                 [ #  # ]
    2141 [ +  - ][ +  - ]:         31 :                             currentBoundary = edges1[0];
    2142                 :            :                         }
    2143                 :            :                     }
    2144         [ +  - ]:         31 :                     visitedTriangles.insert( tri );
    2145                 :         31 :                     currentPoint = intx;
    2146         [ +  - ]:         31 :                     points.push_back( intx );
    2147         [ +  - ]:         31 :                     entities.push_back( currentBoundary );
    2148         [ +  - ]:         31 :                     triangles.push_back( tri );
    2149         [ -  + ]:         31 :                     if( debug_splits )
    2150 [ #  # ][ #  # ]:          0 :                         std::cout << "vtx new tri : " << _mbImpl->id_from_handle( tri )
                 [ #  # ]
    2151 [ #  # ][ #  # ]:          0 :                                   << " type bdy:" << _mbImpl->type_from_handle( currentBoundary ) << "\n";
         [ #  # ][ #  # ]
    2152                 :         88 :                     break;  // out of for loop over triangles
    2153                 :            :                 }
    2154                 :            :             }
    2155                 :            :             else  // this is MBEDGE, we have the other triangle to try out
    2156                 :            :             {
    2157                 :            :                 // first find the nodes from existing boundary
    2158                 :            :                 int nnodes2;
    2159                 :            :                 const EntityHandle* conn2;
    2160         [ +  - ]:       1728 :                 rval = _mbImpl->get_connectivity( currentBoundary, conn2, nnodes2 );
    2161 [ -  + ][ #  # ]:       3513 :                 MBERRORR( rval, "Failed to get connectivity" );
                 [ #  # ]
    2162                 :       1728 :                 int thirdIndex = -1;
    2163         [ +  - ]:       3493 :                 for( int tj = 0; tj < 3; tj++ )
    2164                 :            :                 {
    2165 [ +  + ][ +  + ]:       3493 :                     if( ( conn3[tj] != conn2[0] ) && ( conn3[tj] != conn2[1] ) )
    2166                 :            :                     {
    2167                 :       1728 :                         thirdIndex = tj;
    2168                 :       1728 :                         break;
    2169                 :            :                     }
    2170                 :            :                 }
    2171 [ -  + ][ #  # ]:       1728 :                 if( -1 == thirdIndex ) MBERRORR( MB_FAILURE, " can't get third node" );
                 [ #  # ]
    2172 [ +  - ][ +  + ]:       6912 :                 CartVect Pt[3];
    2173         [ +  - ]:       1728 :                 rval = _mbImpl->get_coords( conn3, 3, (double*)&Pt[0] );
    2174 [ -  + ][ #  # ]:       1728 :                 MBERRORR( rval, "Failed to get coords" );
                 [ #  # ]
    2175                 :       1728 :                 int indexFirst  = ( thirdIndex + 1 ) % 3;
    2176                 :       1728 :                 int indexSecond = ( thirdIndex + 2 ) % 3;
    2177                 :       1728 :                 int index[2]    = { indexFirst, indexSecond };
    2178         [ +  - ]:       4321 :                 for( int k = 0; k < 2; k++ )
    2179                 :            :                 {
    2180                 :       2593 :                     nn2[0] = conn3[index[k]], nn2[1] = conn3[thirdIndex];
    2181 [ +  - ][ +  + ]:       2593 :                     if( intersect_segment_and_plane_slice( Pt[index[k]], Pt[thirdIndex], currentPoint, p2, Dir,
    2182                 :       5186 :                                                            normPlane, intx, param ) )
    2183                 :            :                     {
    2184                 :            :                         // we should stop for loop, and decide if it is edge or vertex
    2185         [ -  + ]:       1728 :                         if( param == 0. )
    2186                 :          0 :                             currentBoundary = conn3[index[k]];  // it is not really possible
    2187                 :            :                         else
    2188                 :            :                         {
    2189         [ +  + ]:       1728 :                             if( param == 1. )
    2190                 :         15 :                                 currentBoundary = conn3[thirdIndex];
    2191                 :            :                             else  // param between 0 and 1, so edge is fine
    2192                 :            :                             {
    2193                 :            :                                 // find the edge between vertices
    2194         [ +  - ]:       1713 :                                 std::vector< EntityHandle > edges1;
    2195                 :            :                                 // change the create flag to true, because that edge must exist in
    2196                 :            :                                 // current triangle if we want to advance; nn2 are 2 nodes in
    2197                 :            :                                 // current triangle!!
    2198         [ +  - ]:       1713 :                                 rval = _mbImpl->get_adjacencies( nn2, 2, 1, true, edges1, Interface::INTERSECT );
    2199 [ -  + ][ #  # ]:       1713 :                                 MBERRORR( rval, "Failed to get edges" );
                 [ #  # ]
    2200         [ -  + ]:       1713 :                                 if( edges1.size() != 1 )
    2201 [ #  # ][ #  # ]:          0 :                                     MBERRORR( MB_FAILURE, "Failed to get adjacent edges to 2 nodes" );
    2202 [ +  - ][ +  - ]:       1713 :                                 currentBoundary = edges1[0];
    2203                 :            :                             }
    2204                 :            :                         }
    2205         [ +  - ]:       1728 :                         visitedTriangles.insert( tri );
    2206                 :       1728 :                         currentPoint = intx;
    2207         [ +  - ]:       1728 :                         points.push_back( intx );
    2208         [ +  - ]:       1728 :                         entities.push_back( currentBoundary );
    2209         [ +  - ]:       1728 :                         triangles.push_back( tri );
    2210         [ -  + ]:       1728 :                         if( debug_splits )
    2211                 :            :                         {
    2212 [ #  # ][ #  # ]:          0 :                             std::cout << "edge new tri : " << _mbImpl->id_from_handle( tri )
                 [ #  # ]
    2213 [ #  # ][ #  # ]:          0 :                                       << "  type bdy: " << _mbImpl->type_from_handle( currentBoundary )
                 [ #  # ]
    2214 [ #  # ][ #  # ]:          0 :                                       << " id: " << _mbImpl->id_from_handle( currentBoundary ) << "\n";
         [ #  # ][ #  # ]
    2215         [ #  # ]:          0 :                             _mbImpl->list_entity( currentBoundary );
    2216                 :            :                         }
    2217                 :       1728 :                         break;  // out of for loop over triangles
    2218                 :            :                     }
    2219                 :            :                     // we should not reach here
    2220                 :            :                 }
    2221                 :            :             }
    2222                 :            :         }
    2223                 :            :         /*if (j==adj_tri.size())
    2224                 :            :          {
    2225                 :            :          MBERRORR(MB_FAILURE, "did not advance");
    2226                 :            :          }*/
    2227 [ +  - ][ +  - ]:       1775 :         vect = p2 - currentPoint;
    2228                 :       1775 :     }
    2229                 :            : 
    2230         [ -  + ]:         16 :     if( debug_splits )
    2231 [ #  # ][ #  # ]:          0 :         std::cout << "nb entities: " << entities.size() << " triangles:" << triangles.size()
         [ #  # ][ #  # ]
    2232 [ #  # ][ #  # ]:          0 :                   << " points.size(): " << points.size() << "\n";
                 [ #  # ]
    2233                 :            : 
    2234                 :         16 :     return MB_SUCCESS;
    2235                 :            : }
    2236                 :            : 
    2237                 :          0 : ErrorCode FBEngine::split_edge_at_point( EntityHandle edge, CartVect& point, EntityHandle& new_edge )
    2238                 :            : {
    2239                 :            :     // return MB_NOT_IMPLEMENTED;
    2240                 :            :     // first, we need to find the closest point on the smooth edge, then
    2241                 :            :     // split the smooth edge, then call the split_edge_at_mesh_node
    2242                 :            :     // or maybe just find the closest node??
    2243                 :            :     // first of all, we need to find a point on the smooth edge, close by
    2244                 :            :     // then split the mesh edge (if needed)
    2245                 :            :     // this would be quite a drama, as the new edge has to be inserted in
    2246                 :            :     // order for proper geo edge definition
    2247                 :            : 
    2248                 :            :     // first of all, find a closest point
    2249                 :            :     // usually called for
    2250         [ #  # ]:          0 :     if( debug_splits )
    2251 [ #  # ][ #  # ]:          0 :     { std::cout << "Split edge " << _mbImpl->id_from_handle( edge ) << " at point:" << point << "\n"; }
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    2252         [ #  # ]:          0 :     int dim = _my_geomTopoTool->dimension( edge );
    2253         [ #  # ]:          0 :     if( dim != 1 ) return MB_FAILURE;
    2254         [ #  # ]:          0 :     if( !_smooth ) return MB_FAILURE;  // call it only for smooth option...
    2255                 :            :     // maybe we should do something for linear too
    2256                 :            : 
    2257         [ #  # ]:          0 :     SmoothCurve* curve = this->_edges[edge];
    2258                 :            :     EntityHandle closeNode;
    2259                 :            :     int edgeIndex;
    2260 [ #  # ][ #  # ]:          0 :     double u = curve->u_from_position( point[0], point[1], point[2], closeNode, edgeIndex );
         [ #  # ][ #  # ]
    2261         [ #  # ]:          0 :     if( 0 == closeNode )
    2262                 :            :     {
    2263                 :            :         // we really need to split an existing edge
    2264                 :            :         // do not do that yet
    2265                 :            :         // evaluate from u:
    2266                 :            :         /*double pos[3];
    2267                 :            :         curve->position_from_u(u,  pos[0], pos[1], pos[2] );*/
    2268                 :            :         // create a new node here, and split one edge
    2269                 :            :         // change also connectivity, create new triangles on both sides ...
    2270 [ #  # ][ #  # ]:          0 :         std::cout << "not found a close node,  u is: " << u << " edge index: " << edgeIndex << "\n";
         [ #  # ][ #  # ]
                 [ #  # ]
    2271                 :          0 :         return MB_FAILURE;  // not implemented yet
    2272                 :            :     }
    2273         [ #  # ]:          0 :     return split_edge_at_mesh_node( edge, closeNode, new_edge );
    2274                 :            : }
    2275                 :            : 
    2276                 :          0 : ErrorCode FBEngine::split_edge_at_mesh_node( EntityHandle edge, EntityHandle node, EntityHandle& new_edge )
    2277                 :            : {
    2278                 :            :     // the node should be in the list of nodes
    2279                 :            : 
    2280         [ #  # ]:          0 :     int dim = _my_geomTopoTool->dimension( edge );
    2281         [ #  # ]:          0 :     if( dim != 1 ) return MB_FAILURE;  // not an edge
    2282                 :            : 
    2283         [ #  # ]:          0 :     if( debug_splits )
    2284                 :            :     {
    2285 [ #  # ][ #  # ]:          0 :         std::cout << "Split edge " << _mbImpl->id_from_handle( edge )
                 [ #  # ]
    2286 [ #  # ][ #  # ]:          0 :                   << " with global id: " << _my_geomTopoTool->global_id( edge )
                 [ #  # ]
    2287 [ #  # ][ #  # ]:          0 :                   << " at node:" << _mbImpl->id_from_handle( node ) << "\n";
         [ #  # ][ #  # ]
    2288                 :            :     }
    2289                 :            : 
    2290                 :            :     // now get the edges
    2291                 :            :     // the order is important...
    2292                 :            :     // these are ordered sets !!
    2293         [ #  # ]:          0 :     std::vector< EntityHandle > ents;
    2294         [ #  # ]:          0 :     ErrorCode rval = _mbImpl->get_entities_by_type( edge, MBEDGE, ents );
    2295         [ #  # ]:          0 :     if( MB_SUCCESS != rval ) return rval;
    2296         [ #  # ]:          0 :     if( ents.size() < 1 ) return MB_FAILURE;  // no edges
    2297                 :            : 
    2298                 :          0 :     const EntityHandle* conn = NULL;
    2299                 :            :     int len;
    2300                 :            :     // find the edge connected to the splitting node
    2301                 :          0 :     int num_mesh_edges = (int)ents.size();
    2302                 :            :     int index_edge;
    2303                 :          0 :     EntityHandle firstNode = 0;
    2304         [ #  # ]:          0 :     for( index_edge = 0; index_edge < num_mesh_edges; index_edge++ )
    2305                 :            :     {
    2306 [ #  # ][ #  # ]:          0 :         rval = MBI->get_connectivity( ents[index_edge], conn, len );
    2307         [ #  # ]:          0 :         if( MB_SUCCESS != rval ) return rval;
    2308         [ #  # ]:          0 :         if( index_edge == 0 ) firstNode = conn[0];  // will be used to decide vertex sets adjacencies
    2309         [ #  # ]:          0 :         if( conn[0] == node )
    2310                 :            :         {
    2311         [ #  # ]:          0 :             if( index_edge == 0 )
    2312                 :            :             {
    2313                 :          0 :                 new_edge = 0;       // no need to split, it is the first node
    2314                 :          0 :                 return MB_SUCCESS;  // no split
    2315                 :            :             }
    2316                 :            :             else
    2317                 :          0 :                 return MB_FAILURE;  // we should have found the node already , wrong
    2318                 :            :                                     // connectivity
    2319                 :            :         }
    2320         [ #  # ]:          0 :         else if( conn[1] == node )
    2321                 :            :         {
    2322                 :            :             // we found the index of interest
    2323                 :          0 :             break;
    2324                 :            :         }
    2325                 :            :     }
    2326         [ #  # ]:          0 :     if( index_edge == num_mesh_edges - 1 )
    2327                 :            :     {
    2328                 :          0 :         new_edge = 0;       // no need to split, it is the last node
    2329                 :          0 :         return MB_SUCCESS;  // no split
    2330                 :            :     }
    2331                 :            : 
    2332                 :            :     // here, we have 0 ... index_edge edges in the first set,
    2333                 :            :     // create a vertex set and add the node to it
    2334                 :            : 
    2335         [ #  # ]:          0 :     if( debug_splits )
    2336 [ #  # ][ #  # ]:          0 :     { std::cout << "Split edge with " << num_mesh_edges << " mesh edges, at index (0 based) " << index_edge << "\n"; }
         [ #  # ][ #  # ]
                 [ #  # ]
    2337                 :            : 
    2338                 :            :     // at this moment, the node set should have been already created in new_geo_edge
    2339                 :            :     EntityHandle nodeSet;  // the node set that has the node (find it!)
    2340         [ #  # ]:          0 :     bool found = find_vertex_set_for_node( node, nodeSet );
    2341                 :            : 
    2342         [ #  # ]:          0 :     if( !found )
    2343                 :            :     {
    2344                 :            :         // create a node set and add the node
    2345                 :            : 
    2346                 :            :         // must be an error, but create one nevertheless
    2347         [ #  # ]:          0 :         rval = _mbImpl->create_meshset( MESHSET_SET, nodeSet );
    2348 [ #  # ][ #  # ]:          0 :         MBERRORR( rval, "Failed to create a new vertex set" );
                 [ #  # ]
    2349                 :            : 
    2350         [ #  # ]:          0 :         rval = _mbImpl->add_entities( nodeSet, &node, 1 );
    2351 [ #  # ][ #  # ]:          0 :         MBERRORR( rval, "Failed to add the node to the set" );
                 [ #  # ]
    2352                 :            : 
    2353         [ #  # ]:          0 :         rval = _my_geomTopoTool->add_geo_set( nodeSet, 0 );  //
    2354 [ #  # ][ #  # ]:          0 :         MBERRORR( rval, "Failed to commit the node set" );
                 [ #  # ]
    2355                 :            : 
    2356         [ #  # ]:          0 :         if( debug_splits )
    2357                 :            :         {
    2358         [ #  # ]:          0 :             std::cout << " create a vertex set (this should have been created before!)"
    2359 [ #  # ][ #  # ]:          0 :                       << _mbImpl->id_from_handle( nodeSet )
    2360 [ #  # ][ #  # ]:          0 :                       << " global id:" << this->_my_geomTopoTool->global_id( nodeSet ) << "\n";
         [ #  # ][ #  # ]
    2361                 :            :         }
    2362                 :            :     }
    2363                 :            : 
    2364                 :            :     // we need to remove the remaining mesh edges from first set, and add it
    2365                 :            :     // to the second set, in order
    2366                 :            : 
    2367         [ #  # ]:          0 :     rval = _mbImpl->create_meshset( MESHSET_ORDERED, new_edge );
    2368 [ #  # ][ #  # ]:          0 :     MBERRORR( rval, "can't create geo edge" );
                 [ #  # ]
    2369                 :            : 
    2370                 :          0 :     int remaining = num_mesh_edges - 1 - index_edge;
    2371                 :            : 
    2372                 :            :     // add edges to the edge set
    2373 [ #  # ][ #  # ]:          0 :     rval = _mbImpl->add_entities( new_edge, &ents[index_edge + 1], remaining );
    2374 [ #  # ][ #  # ]:          0 :     MBERRORR( rval, "can't add edges to the new edge" );
                 [ #  # ]
    2375                 :            : 
    2376                 :            :     // also, remove the second node set from old edge
    2377                 :            :     // remove the edges index_edge+1 and up
    2378                 :            : 
    2379 [ #  # ][ #  # ]:          0 :     rval = _mbImpl->remove_entities( edge, &ents[index_edge + 1], remaining );
    2380 [ #  # ][ #  # ]:          0 :     MBERRORR( rval, "can't remove edges from the old edge" );
                 [ #  # ]
    2381                 :            : 
    2382                 :            :     // need to find the adjacent vertex sets
    2383         [ #  # ]:          0 :     Range vertexRange;
    2384         [ #  # ]:          0 :     rval = getAdjacentEntities( edge, 0, vertexRange );
    2385                 :            : 
    2386                 :            :     EntityHandle secondSet;
    2387 [ #  # ][ #  # ]:          0 :     if( vertexRange.size() == 1 )
    2388                 :            :     {
    2389                 :            :         // initially a periodic edge, OK to add the new set to both edges, and the
    2390                 :            :         // second set
    2391         [ #  # ]:          0 :         secondSet = vertexRange[0];
    2392                 :            :     }
    2393                 :            :     else
    2394                 :            :     {
    2395 [ #  # ][ #  # ]:          0 :         if( vertexRange.size() > 2 ) return MB_FAILURE;  // something must be wrong with too many vertices
    2396                 :            :         // find first node
    2397                 :            :         int k;
    2398         [ #  # ]:          0 :         for( k = 0; k < 2; k++ )
    2399                 :            :         {
    2400         [ #  # ]:          0 :             Range verts;
    2401 [ #  # ][ #  # ]:          0 :             rval = _mbImpl->get_entities_by_type( vertexRange[k], MBVERTEX, verts );
    2402                 :            : 
    2403 [ #  # ][ #  # ]:          0 :             MBERRORR( rval, "can't get vertices from vertex set" );
                 [ #  # ]
    2404 [ #  # ][ #  # ]:          0 :             if( verts.size() != 1 ) MBERRORR( MB_FAILURE, " node set not defined well" );
         [ #  # ][ #  # ]
    2405 [ #  # ][ #  # ]:          0 :             if( firstNode == verts[0] )
    2406                 :            :             {
    2407         [ #  # ]:          0 :                 secondSet = vertexRange[1 - k];  // the other set; it is 1 or 0
    2408      [ #  #  # ]:          0 :                 break;
    2409                 :            :             }
    2410                 :          0 :         }
    2411         [ #  # ]:          0 :         if( k >= 2 )
    2412                 :            :         {
    2413                 :            :             // it means we didn't find the right node set
    2414 [ #  # ][ #  # ]:          0 :             MBERRORR( MB_FAILURE, " can't find the right vertex" );
    2415                 :            :         }
    2416                 :            :         // remove the second set from the connectivity with the
    2417                 :            :         //  edge (parent-child relation)
    2418                 :            :         // remove_parent_child( EntityHandle parent,
    2419                 :            :         //                                          EntityHandle child )
    2420         [ #  # ]:          0 :         rval = _mbImpl->remove_parent_child( edge, secondSet );
    2421 [ #  # ][ #  # ]:          0 :         MBERRORR( rval, " can't remove the second vertex from edge" );
                 [ #  # ]
    2422                 :            :     }
    2423                 :            :     // at this point, we just need to add to both edges the new node set (vertex)
    2424         [ #  # ]:          0 :     rval = _mbImpl->add_parent_child( edge, nodeSet );
    2425 [ #  # ][ #  # ]:          0 :     MBERRORR( rval, " can't add new vertex to old edge" );
                 [ #  # ]
    2426                 :            : 
    2427         [ #  # ]:          0 :     rval = _mbImpl->add_parent_child( new_edge, nodeSet );
    2428 [ #  # ][ #  # ]:          0 :     MBERRORR( rval, " can't add new vertex to new edge" );
                 [ #  # ]
    2429                 :            : 
    2430                 :            :     // one thing that I forgot: add the secondSet as a child to new edge!!!
    2431                 :            :     // (so far, the new edge has only one end vertex!)
    2432         [ #  # ]:          0 :     rval = _mbImpl->add_parent_child( new_edge, secondSet );
    2433 [ #  # ][ #  # ]:          0 :     MBERRORR( rval, " can't add second vertex to new edge" );
                 [ #  # ]
    2434                 :            : 
    2435                 :            :     // now, add the edge and vertex to geo tool
    2436                 :            : 
    2437         [ #  # ]:          0 :     rval = _my_geomTopoTool->add_geo_set( new_edge, 1 );
    2438 [ #  # ][ #  # ]:          0 :     MBERRORR( rval, " can't add new edge" );
                 [ #  # ]
    2439                 :            : 
    2440                 :            :     // next, get the adjacent faces to initial edge, and add them as parents
    2441                 :            :     // to the new edge
    2442                 :            : 
    2443                 :            :     // need to find the adjacent face sets
    2444         [ #  # ]:          0 :     Range faceRange;
    2445         [ #  # ]:          0 :     rval = getAdjacentEntities( edge, 2, faceRange );
    2446                 :            : 
    2447                 :            :     // these faces will be adjacent to the new edge too!
    2448                 :            :     // need to set the senses of new edge within faces
    2449                 :            : 
    2450 [ #  # ][ #  # ]:          0 :     for( Range::iterator it = faceRange.begin(); it != faceRange.end(); ++it )
         [ #  # ][ #  # ]
                 [ #  # ]
    2451                 :            :     {
    2452         [ #  # ]:          0 :         EntityHandle face = *it;
    2453         [ #  # ]:          0 :         rval              = _mbImpl->add_parent_child( face, new_edge );
    2454 [ #  # ][ #  # ]:          0 :         MBERRORR( rval, " can't add new edge - face parent relation" );
                 [ #  # ]
    2455                 :            :         int sense;
    2456         [ #  # ]:          0 :         rval = _my_geomTopoTool->get_sense( edge, face, sense );
    2457 [ #  # ][ #  # ]:          0 :         MBERRORR( rval, " can't get initial sense of edge in the adjacent face" );
                 [ #  # ]
    2458                 :            :         // keep the same sense for the new edge within the faces
    2459         [ #  # ]:          0 :         rval = _my_geomTopoTool->set_sense( new_edge, face, sense );
    2460 [ #  # ][ #  # ]:          0 :         MBERRORR( rval, " can't set sense of new edge in the adjacent face" );
                 [ #  # ]
    2461                 :            :     }
    2462                 :            : 
    2463                 :          0 :     return MB_SUCCESS;
    2464                 :            : }
    2465                 :            : 
    2466                 :          2 : ErrorCode FBEngine::split_bedge_at_new_mesh_node( EntityHandle edge, EntityHandle node, EntityHandle brokenEdge,
    2467                 :            :                                                   EntityHandle& new_edge )
    2468                 :            : {
    2469                 :            :     // the node should be in the list of nodes
    2470                 :            : 
    2471         [ +  - ]:          2 :     int dim = _my_geomTopoTool->dimension( edge );
    2472         [ -  + ]:          2 :     if( dim != 1 ) return MB_FAILURE;  // not an edge
    2473                 :            : 
    2474         [ -  + ]:          2 :     if( debug_splits )
    2475                 :            :     {
    2476 [ #  # ][ #  # ]:          0 :         std::cout << "Split edge " << _mbImpl->id_from_handle( edge )
                 [ #  # ]
    2477 [ #  # ][ #  # ]:          0 :                   << " with global id: " << _my_geomTopoTool->global_id( edge )
                 [ #  # ]
    2478 [ #  # ][ #  # ]:          0 :                   << " at new node:" << _mbImpl->id_from_handle( node ) << "breaking mesh edge"
         [ #  # ][ #  # ]
    2479 [ #  # ][ #  # ]:          0 :                   << _mbImpl->id_from_handle( brokenEdge ) << "\n";
                 [ #  # ]
    2480                 :            :     }
    2481                 :            : 
    2482                 :            :     // now get the edges
    2483                 :            :     // the order is important...
    2484                 :            :     // these are ordered sets !!
    2485         [ +  - ]:          2 :     std::vector< EntityHandle > ents;
    2486         [ +  - ]:          2 :     ErrorCode rval = _mbImpl->get_entities_by_type( edge, MBEDGE, ents );
    2487         [ -  + ]:          2 :     if( MB_SUCCESS != rval ) return rval;
    2488         [ -  + ]:          2 :     if( ents.size() < 1 ) return MB_FAILURE;  // no edges
    2489                 :            : 
    2490                 :          2 :     const EntityHandle* conn = NULL;
    2491                 :            :     int len;
    2492                 :            :     // the edge connected to the splitting node is brokenEdge
    2493                 :            :     // find the small edges it is broken into, which are connected to
    2494                 :            :     // new vertex (node) and its ends; also, if necessary, reorient these small edges
    2495                 :            :     // for proper orientation
    2496         [ +  - ]:          2 :     rval = _mbImpl->get_connectivity( brokenEdge, conn, len );
    2497 [ -  + ][ #  # ]:          2 :     MBERRORR( rval, "Failed to get connectivity of broken edge" );
                 [ #  # ]
    2498                 :            : 
    2499                 :            :     // we already created the new edges, make sure they are oriented fine; if not, revert them
    2500                 :          2 :     EntityHandle conn02[] = { conn[0], node };  // first node and new node
    2501                 :            :     // default, intersect
    2502         [ +  - ]:          4 :     std::vector< EntityHandle > adj_edges;
    2503         [ +  - ]:          2 :     rval = _mbImpl->get_adjacencies( conn02, 2, 1, false, adj_edges );
    2504 [ +  - ][ -  + ]:          2 :     if( adj_edges.size() < 1 || rval != MB_SUCCESS ) MBERRORR( MB_FAILURE, " Can't find small split edge" );
         [ -  + ][ #  # ]
                 [ #  # ]
    2505                 :            : 
    2506                 :            :     // get this edge connectivity;
    2507         [ +  - ]:          2 :     EntityHandle firstEdge         = adj_edges[0];
    2508                 :          2 :     const EntityHandle* connActual = NULL;
    2509         [ +  - ]:          2 :     rval                           = _mbImpl->get_connectivity( firstEdge, connActual, len );
    2510 [ -  + ][ #  # ]:          2 :     MBERRORR( rval, "Failed to get connectivity of first split edge" );
                 [ #  # ]
    2511                 :            :     // if it is the same as conn02, we are happy
    2512         [ -  + ]:          2 :     if( conn02[0] != connActual[0] )
    2513                 :            :     {
    2514                 :            :         // reset connectivity of edge
    2515         [ #  # ]:          0 :         rval = _mbImpl->set_connectivity( firstEdge, conn02, 2 );
    2516 [ #  # ][ #  # ]:          0 :         MBERRORR( rval, "Failed to reset connectivity of first split edge" );
                 [ #  # ]
    2517                 :            :     }
    2518                 :            :     //  now treat the second edge
    2519                 :          2 :     adj_edges.clear();                          //
    2520                 :          2 :     EntityHandle conn21[] = { node, conn[1] };  //  new node and second node
    2521         [ +  - ]:          2 :     rval                  = _mbImpl->get_adjacencies( conn21, 2, 1, false, adj_edges );
    2522 [ +  - ][ -  + ]:          2 :     if( adj_edges.size() < 1 || rval != MB_SUCCESS ) MBERRORR( MB_FAILURE, " Can't find second small split edge" );
         [ -  + ][ #  # ]
                 [ #  # ]
    2523                 :            : 
    2524                 :            :     // get this edge connectivity;
    2525         [ +  - ]:          2 :     EntityHandle secondEdge = adj_edges[0];
    2526         [ +  - ]:          2 :     rval                    = _mbImpl->get_connectivity( firstEdge, connActual, len );
    2527 [ -  + ][ #  # ]:          2 :     MBERRORR( rval, "Failed to get connectivity of first split edge" );
                 [ #  # ]
    2528                 :            :     // if it is the same as conn21, we are happy
    2529         [ +  - ]:          2 :     if( conn21[0] != connActual[0] )
    2530                 :            :     {
    2531                 :            :         // reset connectivity of edge
    2532         [ +  - ]:          2 :         rval = _mbImpl->set_connectivity( secondEdge, conn21, 2 );
    2533 [ -  + ][ #  # ]:          2 :         MBERRORR( rval, "Failed to reset connectivity of first split edge" );
                 [ #  # ]
    2534                 :            :     }
    2535                 :            : 
    2536                 :          2 :     int num_mesh_edges = (int)ents.size();
    2537                 :            :     int index_edge;  // this is the index of the edge that will be removed (because it is split)
    2538                 :            :     // the rest of edges will be put in order in the (remaining) edge and new edge
    2539                 :            : 
    2540         [ +  - ]:        251 :     for( index_edge = 0; index_edge < num_mesh_edges; index_edge++ )
    2541 [ +  - ][ +  + ]:        251 :         if( brokenEdge == ents[index_edge] ) break;
    2542 [ -  + ][ #  # ]:          2 :     if( index_edge >= num_mesh_edges ) MBERRORR( MB_FAILURE, "can't find the broken edge" );
                 [ #  # ]
    2543                 :            : 
    2544                 :            :     // so the edges up to index_edge and firstEdge, will form the "old" edge
    2545                 :            :     // the edges secondEdge and from index_edge+1 to end will form the new_edge
    2546                 :            : 
    2547                 :            :     // here, we have 0 ... index_edge edges in the first set,
    2548                 :            :     // create a vertex set and add the node to it
    2549                 :            : 
    2550         [ -  + ]:          2 :     if( debug_splits )
    2551 [ #  # ][ #  # ]:          0 :     { std::cout << "Split edge with " << num_mesh_edges << " mesh edges, at index (0 based) " << index_edge << "\n"; }
         [ #  # ][ #  # ]
                 [ #  # ]
    2552                 :            : 
    2553                 :            :     // at this moment, the node set should have been already created in new_geo_edge
    2554                 :            :     EntityHandle nodeSet;  // the node set that has the node (find it!)
    2555         [ +  - ]:          2 :     bool found = find_vertex_set_for_node( node, nodeSet );
    2556                 :            : 
    2557         [ -  + ]:          2 :     if( !found )
    2558                 :            :     {
    2559                 :            :         // create a node set and add the node
    2560                 :            : 
    2561                 :            :         // must be an error, but create one nevertheless
    2562         [ #  # ]:          0 :         rval = _mbImpl->create_meshset( MESHSET_SET, nodeSet );
    2563 [ #  # ][ #  # ]:          0 :         MBERRORR( rval, "Failed to create a new vertex set" );
                 [ #  # ]
    2564                 :            : 
    2565         [ #  # ]:          0 :         rval = _mbImpl->add_entities( nodeSet, &node, 1 );
    2566 [ #  # ][ #  # ]:          0 :         MBERRORR( rval, "Failed to add the node to the set" );
                 [ #  # ]
    2567                 :            : 
    2568         [ #  # ]:          0 :         rval = _my_geomTopoTool->add_geo_set( nodeSet, 0 );  //
    2569 [ #  # ][ #  # ]:          0 :         MBERRORR( rval, "Failed to commit the node set" );
                 [ #  # ]
    2570                 :            : 
    2571         [ #  # ]:          0 :         if( debug_splits )
    2572                 :            :         {
    2573         [ #  # ]:          0 :             std::cout << " create a vertex set (this should have been created before!)"
    2574 [ #  # ][ #  # ]:          0 :                       << _mbImpl->id_from_handle( nodeSet )
    2575 [ #  # ][ #  # ]:          0 :                       << " global id:" << this->_my_geomTopoTool->global_id( nodeSet ) << "\n";
         [ #  # ][ #  # ]
    2576                 :            :         }
    2577                 :            :     }
    2578                 :            : 
    2579                 :            :     // we need to remove the remaining mesh edges from first set, and add it
    2580                 :            :     // to the second set, in order
    2581                 :            : 
    2582         [ +  - ]:          2 :     rval = _mbImpl->create_meshset( MESHSET_ORDERED, new_edge );
    2583 [ -  + ][ #  # ]:          2 :     MBERRORR( rval, "can't create geo edge" );
                 [ #  # ]
    2584                 :            : 
    2585                 :          2 :     int remaining = num_mesh_edges - 1 - index_edge;
    2586                 :            : 
    2587                 :            :     // add edges to the new edge set
    2588         [ +  - ]:          2 :     rval = _mbImpl->add_entities( new_edge, &secondEdge, 1 );  // add the second split edge to new edge
    2589 [ -  + ][ #  # ]:          2 :     MBERRORR( rval, "can't add second split edge to the new edge" );
                 [ #  # ]
    2590                 :            :     // then add the rest
    2591 [ +  - ][ +  - ]:          2 :     rval = _mbImpl->add_entities( new_edge, &ents[index_edge + 1], remaining );
    2592 [ -  + ][ #  # ]:          2 :     MBERRORR( rval, "can't add edges to the new edge" );
                 [ #  # ]
    2593                 :            : 
    2594                 :            :     // also, remove the second node set from old edge
    2595                 :            :     // remove the edges index_edge and up
    2596                 :            : 
    2597 [ +  - ][ +  - ]:          2 :     rval = _mbImpl->remove_entities( edge, &ents[index_edge], remaining + 1 );  // include the
    2598 [ -  + ][ #  # ]:          2 :     MBERRORR( rval, "can't remove edges from the old edge" );
                 [ #  # ]
    2599                 :            :     // add the firstEdge too
    2600         [ +  - ]:          2 :     rval = _mbImpl->add_entities( edge, &firstEdge, 1 );  // add the second split edge to new edge
    2601 [ -  + ][ #  # ]:          2 :     MBERRORR( rval, "can't add first split edge to the old edge" );
                 [ #  # ]
    2602                 :            : 
    2603                 :            :     // need to find the adjacent vertex sets
    2604         [ +  - ]:          4 :     Range vertexRange;
    2605         [ +  - ]:          2 :     rval = getAdjacentEntities( edge, 0, vertexRange );
    2606                 :            : 
    2607                 :            :     EntityHandle secondSet;
    2608 [ +  - ][ +  + ]:          2 :     if( vertexRange.size() == 1 )
    2609                 :            :     {
    2610                 :            :         // initially a periodic edge, OK to add the new set to both edges, and the
    2611                 :            :         // second set
    2612         [ +  - ]:          1 :         secondSet = vertexRange[0];
    2613                 :            :     }
    2614                 :            :     else
    2615                 :            :     {
    2616 [ +  - ][ -  + ]:          1 :         if( vertexRange.size() > 2 ) return MB_FAILURE;  // something must be wrong with too many vertices
    2617                 :            :         // find first node
    2618                 :            :         EntityHandle firstNode;
    2619                 :            : 
    2620 [ +  - ][ +  - ]:          1 :         rval = MBI->get_connectivity( ents[0], conn, len );
    2621         [ -  + ]:          1 :         if( MB_SUCCESS != rval ) return rval;
    2622                 :          1 :         firstNode = conn[0];  // this is the first node of the initial edge
    2623                 :            :                               // we will use it to identify the vertex set associated with it
    2624                 :            :         int k;
    2625         [ +  - ]:          2 :         for( k = 0; k < 2; k++ )
    2626                 :            :         {
    2627         [ +  - ]:          1 :             Range verts;
    2628 [ +  - ][ +  - ]:          1 :             rval = _mbImpl->get_entities_by_type( vertexRange[k], MBVERTEX, verts );
    2629                 :            : 
    2630 [ -  + ][ #  # ]:          1 :             MBERRORR( rval, "can't get vertices from vertex set" );
                 [ #  # ]
    2631 [ +  - ][ -  + ]:          1 :             if( verts.size() != 1 ) MBERRORR( MB_FAILURE, " node set not defined well" );
         [ #  # ][ #  # ]
    2632 [ +  - ][ +  - ]:          1 :             if( firstNode == verts[0] )
    2633                 :            :             {
    2634         [ +  - ]:          1 :                 secondSet = vertexRange[1 - k];  // the other set; it is 1 or 0
    2635      [ -  -  + ]:          1 :                 break;
    2636                 :            :             }
    2637                 :          0 :         }
    2638         [ -  + ]:          1 :         if( k >= 2 )
    2639                 :            :         {
    2640                 :            :             // it means we didn't find the right node set
    2641 [ #  # ][ #  # ]:          0 :             MBERRORR( MB_FAILURE, " can't find the right vertex" );
    2642                 :            :         }
    2643                 :            :         // remove the second set from the connectivity with the
    2644                 :            :         //  edge (parent-child relation)
    2645                 :            :         // remove_parent_child( EntityHandle parent,
    2646                 :            :         //                                          EntityHandle child )
    2647         [ +  - ]:          1 :         rval = _mbImpl->remove_parent_child( edge, secondSet );
    2648 [ -  + ][ #  # ]:          1 :         MBERRORR( rval, " can't remove the second vertex from edge" );
                 [ #  # ]
    2649                 :            :     }
    2650                 :            :     // at this point, we just need to add to both edges the new node set (vertex)
    2651         [ +  - ]:          2 :     rval = _mbImpl->add_parent_child( edge, nodeSet );
    2652 [ -  + ][ #  # ]:          2 :     MBERRORR( rval, " can't add new vertex to old edge" );
                 [ #  # ]
    2653                 :            : 
    2654         [ +  - ]:          2 :     rval = _mbImpl->add_parent_child( new_edge, nodeSet );
    2655 [ -  + ][ #  # ]:          2 :     MBERRORR( rval, " can't add new vertex to new edge" );
                 [ #  # ]
    2656                 :            : 
    2657                 :            :     // one thing that I forgot: add the secondSet as a child to new edge!!!
    2658                 :            :     // (so far, the new edge has only one end vertex!)
    2659         [ +  - ]:          2 :     rval = _mbImpl->add_parent_child( new_edge, secondSet );
    2660 [ -  + ][ #  # ]:          2 :     MBERRORR( rval, " can't add second vertex to new edge" );
                 [ #  # ]
    2661                 :            : 
    2662                 :            :     // now, add the edge and vertex to geo tool
    2663                 :            : 
    2664         [ +  - ]:          2 :     rval = _my_geomTopoTool->add_geo_set( new_edge, 1 );
    2665 [ -  + ][ #  # ]:          2 :     MBERRORR( rval, " can't add new edge" );
                 [ #  # ]
    2666                 :            : 
    2667                 :            :     // next, get the adjacent faces to initial edge, and add them as parents
    2668                 :            :     // to the new edge
    2669                 :            : 
    2670                 :            :     // need to find the adjacent face sets
    2671         [ +  - ]:          4 :     Range faceRange;
    2672         [ +  - ]:          2 :     rval = getAdjacentEntities( edge, 2, faceRange );
    2673                 :            : 
    2674                 :            :     // these faces will be adjacent to the new edge too!
    2675                 :            :     // need to set the senses of new edge within faces
    2676                 :            : 
    2677 [ +  - ][ +  - ]:          4 :     for( Range::iterator it = faceRange.begin(); it != faceRange.end(); ++it )
         [ +  - ][ +  - ]
                 [ +  + ]
    2678                 :            :     {
    2679         [ +  - ]:          2 :         EntityHandle face = *it;
    2680         [ +  - ]:          2 :         rval              = _mbImpl->add_parent_child( face, new_edge );
    2681 [ -  + ][ #  # ]:          2 :         MBERRORR( rval, " can't add new edge - face parent relation" );
                 [ #  # ]
    2682                 :            :         int sense;
    2683         [ +  - ]:          2 :         rval = _my_geomTopoTool->get_sense( edge, face, sense );
    2684 [ -  + ][ #  # ]:          2 :         MBERRORR( rval, " can't get initial sense of edge in the adjacent face" );
                 [ #  # ]
    2685                 :            :         // keep the same sense for the new edge within the faces
    2686         [ +  - ]:          2 :         rval = _my_geomTopoTool->set_sense( new_edge, face, sense );
    2687 [ -  + ][ #  # ]:          2 :         MBERRORR( rval, " can't set sense of new edge in the adjacent face" );
                 [ #  # ]
    2688                 :            :     }
    2689                 :            : 
    2690                 :          4 :     return MB_SUCCESS;
    2691                 :            : }
    2692                 :            : 
    2693                 :          2 : ErrorCode FBEngine::split_boundary( EntityHandle face, EntityHandle atNode )
    2694                 :            : {
    2695                 :            :     // find the boundary edges, and split the one that we find it is a part of
    2696         [ -  + ]:          2 :     if( debug_splits )
    2697                 :            :     {
    2698 [ #  # ][ #  # ]:          0 :         std::cout << "Split face " << _mbImpl->id_from_handle( face )
                 [ #  # ]
    2699 [ #  # ][ #  # ]:          0 :                   << " at node:" << _mbImpl->id_from_handle( atNode ) << "\n";
         [ #  # ][ #  # ]
    2700                 :            :     }
    2701         [ +  - ]:          2 :     Range bound_edges;
    2702         [ +  - ]:          2 :     ErrorCode rval = getAdjacentEntities( face, 1, bound_edges );
    2703 [ -  + ][ #  # ]:          2 :     MBERRORR( rval, " can't get boundary edges" );
                 [ #  # ]
    2704 [ +  - ][ +  - ]:          2 :     bool brokEdge = _brokenEdges.find( atNode ) != _brokenEdges.end();
    2705                 :            : 
    2706 [ +  - ][ #  # ]:          4 :     for( Range::iterator it = bound_edges.begin(); it != bound_edges.end(); ++it )
         [ +  - ][ +  - ]
                 [ +  - ]
    2707                 :            :     {
    2708         [ +  - ]:          2 :         EntityHandle b_edge = *it;
    2709                 :            :         // get all edges in range
    2710         [ +  - ]:          2 :         Range mesh_edges;
    2711         [ +  - ]:          2 :         rval = _mbImpl->get_entities_by_dimension( b_edge, 1, mesh_edges );
    2712 [ -  + ][ #  # ]:          2 :         MBERRORR( rval, " can't get mesh edges" );
                 [ #  # ]
    2713         [ +  - ]:          2 :         if( brokEdge )
    2714                 :            :         {
    2715         [ +  - ]:          2 :             EntityHandle brokenEdge = _brokenEdges[atNode];
    2716 [ +  - ][ +  - ]:          2 :             if( mesh_edges.find( brokenEdge ) != mesh_edges.end() )
         [ +  - ][ +  - ]
    2717                 :            :             {
    2718                 :            :                 EntityHandle new_edge;
    2719         [ +  - ]:          2 :                 rval = split_bedge_at_new_mesh_node( b_edge, atNode, brokenEdge, new_edge );
    2720                 :          2 :                 return rval;
    2721                 :            :             }
    2722                 :            :         }
    2723                 :            :         else
    2724                 :            :         {
    2725         [ #  # ]:          0 :             Range nodes;
    2726         [ #  # ]:          0 :             rval = _mbImpl->get_connectivity( mesh_edges, nodes );
    2727 [ #  # ][ #  # ]:          0 :             MBERRORR( rval, " can't get nodes from mesh edges" );
                 [ #  # ]
    2728                 :            : 
    2729 [ #  # ][ #  # ]:          0 :             if( nodes.find( atNode ) != nodes.end() )
         [ #  # ][ #  # ]
    2730                 :            :             {
    2731                 :            :                 // we found our boundary edge candidate
    2732                 :            :                 EntityHandle new_edge;
    2733         [ #  # ]:          0 :                 rval = split_edge_at_mesh_node( b_edge, atNode, new_edge );
    2734         [ #  # ]:          0 :                 return rval;
    2735         [ -  + ]:          2 :             }
    2736                 :            :         }
    2737                 :          0 :     }
    2738                 :            :     // if the node was not found in any "current" boundary, it broke an existing
    2739                 :            :     // boundary edge
    2740 [ #  # ][ #  # ]:          0 :     MBERRORR( MB_FAILURE, " we did not find an appropriate boundary edge" );
    2741                 :          2 :     ;  //
    2742                 :            : }
    2743                 :            : 
    2744                 :         34 : bool FBEngine::find_vertex_set_for_node( EntityHandle iNode, EntityHandle& oVertexSet )
    2745                 :            : {
    2746                 :         34 :     bool found = false;
    2747         [ +  - ]:         34 :     Range vertex_sets;
    2748                 :            : 
    2749                 :         34 :     const int zero               = 0;
    2750                 :         34 :     const void* const zero_val[] = { &zero };
    2751                 :            :     Tag geom_tag;
    2752         [ +  - ]:         34 :     ErrorCode rval = MBI->tag_get_handle( GEOM_DIMENSION_TAG_NAME, 1, MB_TYPE_INTEGER, geom_tag );
    2753         [ -  + ]:         34 :     if( MB_SUCCESS != rval ) return false;
    2754         [ +  - ]:         34 :     rval = _mbImpl->get_entities_by_type_and_tag( 0, MBENTITYSET, &geom_tag, zero_val, 1, vertex_sets );
    2755         [ -  + ]:         34 :     if( MB_SUCCESS != rval ) return false;
    2756                 :            :     // local _gsets, as we might have not updated the local lists
    2757                 :            :     // see if ends of geo edge generated is in a geo set 0 or not
    2758                 :            : 
    2759 [ +  - ][ +  - ]:        172 :     for( Range::iterator vsit = vertex_sets.begin(); vsit != vertex_sets.end(); ++vsit )
         [ +  - ][ +  - ]
                 [ +  + ]
    2760                 :            :     {
    2761         [ +  - ]:        155 :         EntityHandle vset = *vsit;
    2762                 :            :         // is the node part of this set?
    2763 [ +  - ][ +  + ]:        155 :         if( _mbImpl->contains_entities( vset, &iNode, 1 ) )
    2764                 :            :         {
    2765                 :            : 
    2766                 :         17 :             found      = true;
    2767                 :         17 :             oVertexSet = vset;
    2768                 :         17 :             break;
    2769                 :            :         }
    2770                 :            :     }
    2771                 :         34 :     return found;
    2772                 :            : }
    2773                 :          1 : ErrorCode FBEngine::redistribute_boundary_edges_to_faces( EntityHandle face, EntityHandle newFace,
    2774                 :            :                                                           std::vector< EntityHandle >& chainedEdges )
    2775                 :            : {
    2776                 :            : 
    2777                 :            :     // so far, original boundary edges are all parent/child relations for face
    2778                 :            :     // we should get them all, and see if they are truly adjacent to face or newFace
    2779                 :            :     // decide also on the orientation/sense with respect to the triangles
    2780         [ +  - ]:          1 :     Range r1;  // range in old face
    2781         [ +  - ]:          2 :     Range r2;  // range of tris in new face
    2782         [ +  - ]:          1 :     ErrorCode rval = _mbImpl->get_entities_by_dimension( face, 2, r1 );
    2783 [ -  + ][ #  # ]:          1 :     MBERRORR( rval, " can't get triangles from old face" );
                 [ #  # ]
    2784         [ +  - ]:          1 :     rval = _mbImpl->get_entities_by_dimension( newFace, 2, r2 );
    2785 [ -  + ][ #  # ]:          1 :     MBERRORR( rval, " can't get triangles from new face" );
                 [ #  # ]
    2786                 :            :     // right now, all boundary edges are children of face
    2787                 :            :     // we need to get them all, and verify if they indeed are adjacent to face
    2788         [ +  - ]:          2 :     Range children;
    2789         [ +  - ]:          1 :     rval = _mbImpl->get_child_meshsets( face, children );  // only direct children are of interest
    2790 [ -  + ][ #  # ]:          1 :     MBERRORR( rval, " can't get children sets from face" );
                 [ #  # ]
    2791                 :            : 
    2792 [ +  - ][ +  - ]:          7 :     for( Range::iterator it = children.begin(); it != children.end(); ++it )
         [ +  - ][ +  - ]
                 [ +  + ]
    2793                 :            :     {
    2794         [ +  - ]:          6 :         EntityHandle edge = *it;
    2795 [ +  - ][ +  - ]:          6 :         if( std::find( chainedEdges.begin(), chainedEdges.end(), edge ) != chainedEdges.end() )
                 [ +  + ]
    2796                 :          5 :             continue;  // we already set this one fine
    2797                 :            :         // get one mesh edge from the edge; we have to get all of them!!
    2798 [ +  - ][ -  + ]:          3 :         if( _my_geomTopoTool->dimension( edge ) != 1 ) continue;  // not an edge
    2799         [ +  - ]:          3 :         Range mesh_edges;
    2800         [ +  - ]:          3 :         rval = _mbImpl->get_entities_by_handle( edge, mesh_edges );
    2801 [ -  + ][ #  # ]:          3 :         MBERRORR( rval, " can't get mesh edges from edge" );
                 [ #  # ]
    2802 [ +  - ][ -  + ]:          3 :         if( mesh_edges.empty() ) MBERRORR( MB_FAILURE, " no mesh edges" );
         [ #  # ][ #  # ]
    2803         [ +  - ]:          3 :         EntityHandle mesh_edge = mesh_edges[0];  // first one is enough
    2804                 :            :         // get its triangles; see which one is in r1 or r2; it should not be in both
    2805         [ +  - ]:          6 :         Range triangles;
              [ +  +  - ]
    2806         [ +  - ]:          3 :         rval = _mbImpl->get_adjacencies( &mesh_edge, 1, 2, false, triangles );
    2807 [ -  + ][ #  # ]:          3 :         MBERRORR( rval, " can't get adjacent triangles" );
                 [ #  # ]
    2808         [ +  - ]:          6 :         Range intx1 = intersect( triangles, r1 );
              [ +  -  + ]
    2809         [ +  - ]:          6 :         Range intx2 = intersect( triangles, r2 );
              [ +  -  + ]
    2810 [ +  - ][ +  + ]:          3 :         if( !intx1.empty() && !intx2.empty() ) MBERRORR( MB_FAILURE, " at least one should be empty" );
         [ +  - ][ -  + ]
         [ -  + ][ #  # ]
                 [ #  # ]
    2811                 :            : 
    2812 [ +  - ][ +  + ]:          3 :         if( intx2.empty() )
    2813                 :            :         {
    2814                 :            :             // it means it is in the range r1; the sense should be fine, no need to reset
    2815                 :            :             // the sense should have been fine, also
    2816                 :          2 :             continue;
    2817                 :            :         }
    2818                 :            :         // so it must be a triangle in r2;
    2819         [ +  - ]:          1 :         EntityHandle triangle = intx2[0];  // one triangle only
    2820                 :            :         // remove the edge from boundary of face, and add it to the boundary of newFace
    2821                 :            :         // remove_parent_child( EntityHandle parent,  EntityHandle child )
    2822         [ +  - ]:          1 :         rval = _mbImpl->remove_parent_child( face, edge );
    2823 [ -  + ][ #  # ]:          1 :         MBERRORR( rval, " can't remove parent child relation for edge" );
                 [ #  # ]
    2824                 :            :         // add to the new face
    2825         [ +  - ]:          1 :         rval = _mbImpl->add_parent_child( newFace, edge );
    2826 [ -  + ][ #  # ]:          1 :         MBERRORR( rval, " can't add parent child relation for edge" );
                 [ #  # ]
    2827                 :            : 
    2828                 :            :         // set some sense, based on the sense of the mesh_edge in triangle
    2829                 :            :         int num1, sense, offset;
    2830         [ +  - ]:          1 :         rval = _mbImpl->side_number( triangle, mesh_edge, num1, sense, offset );
    2831 [ -  + ][ #  # ]:          1 :         MBERRORR( rval, "mesh edge not adjacent to triangle" );
                 [ #  # ]
    2832                 :            : 
    2833         [ +  - ]:          1 :         rval = this->_my_geomTopoTool->set_sense( edge, newFace, sense );
    2834 [ -  + ][ #  # ]:          3 :         MBERRORR( rval, "can't set proper sense of edge in face" );
                 [ #  # ]
              [ +  -  + ]
    2835                 :          1 :     }
    2836                 :            : 
    2837                 :          2 :     return MB_SUCCESS;
    2838                 :            : }
    2839                 :            : 
    2840                 :          4 : ErrorCode FBEngine::set_neumann_tags( EntityHandle face, EntityHandle newFace )
    2841                 :            : {
    2842                 :            :     // these are for debugging purposes only
    2843                 :            :     // check the initial tag, then
    2844                 :            :     Tag ntag;
    2845         [ +  - ]:          4 :     ErrorCode rval = _mbImpl->tag_get_handle( NEUMANN_SET_TAG_NAME, 1, MB_TYPE_INTEGER, ntag );
    2846 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't get tag handle" );
                 [ #  # ]
    2847                 :            :     // check the value for face
    2848                 :            :     int nval;
    2849         [ +  - ]:          4 :     rval = _mbImpl->tag_get_data( ntag, &face, 1, &nval );
    2850         [ +  - ]:          4 :     if( MB_SUCCESS == rval ) { nval++; }
    2851                 :            :     else
    2852                 :            :     {
    2853                 :          0 :         nval = 1;
    2854         [ #  # ]:          0 :         rval = _mbImpl->tag_set_data( ntag, &face, 1, &nval );
    2855 [ #  # ][ #  # ]:          0 :         MBERRORR( rval, "can't set tag" );
                 [ #  # ]
    2856                 :          0 :         nval = 2;
    2857                 :            :     }
    2858         [ +  - ]:          4 :     rval = _mbImpl->tag_set_data( ntag, &newFace, 1, &nval );
    2859 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't set tag" );
                 [ #  # ]
    2860                 :            : 
    2861                 :          4 :     return MB_SUCCESS;
    2862                 :            : }
    2863                 :            : 
    2864                 :            : // split the quads if needed; it will create a new gtt, which will
    2865                 :            : // contain triangles instead of quads
    2866                 :         10 : ErrorCode FBEngine::split_quads()
    2867                 :            : {
    2868                 :            :     // first see if we have any quads in the 2d faces
    2869                 :            :     //  _my_gsets[2] is a range of surfaces (moab sets of dimension 2)
    2870                 :         10 :     int num_quads = 0;
    2871 [ +  - ][ +  - ]:         26 :     for( Range::iterator it = _my_gsets[2].begin(); it != _my_gsets[2].end(); ++it )
         [ +  - ][ +  - ]
                 [ +  + ]
    2872                 :            :     {
    2873         [ +  - ]:         16 :         EntityHandle surface = *it;
    2874                 :         16 :         int num_q            = 0;
    2875         [ +  - ]:         16 :         _mbImpl->get_number_entities_by_type( surface, MBQUAD, num_q );
    2876                 :         16 :         num_quads += num_q;
    2877                 :            :     }
    2878                 :            : 
    2879         [ +  + ]:         10 :     if( num_quads == 0 ) return MB_SUCCESS;  // nothing to do
    2880                 :            : 
    2881                 :          1 :     GeomTopoTool* new_gtt = NULL;
    2882         [ +  - ]:          1 :     ErrorCode rval        = _my_geomTopoTool->duplicate_model( new_gtt );
    2883 [ -  + ][ #  # ]:          1 :     MBERRORR( rval, "can't duplicate model" );
                 [ #  # ]
    2884 [ +  - ][ +  - ]:          1 :     if( this->_t_created ) delete _my_geomTopoTool;
    2885                 :            : 
    2886                 :          1 :     _t_created = true;  // this one is for sure created here, even if the original gtt was not
    2887                 :            : 
    2888                 :            :     // if we were using smart pointers, we would decrease the reference to the _my_geomTopoTool, at
    2889                 :            :     // least
    2890                 :          1 :     _my_geomTopoTool = new_gtt;
    2891                 :            : 
    2892                 :            :     // replace the _my_gsets with the new ones, from the new set
    2893         [ +  - ]:          1 :     _my_geomTopoTool->find_geomsets( _my_gsets );
    2894                 :            : 
    2895                 :            :     // we have duplicated now the model, and the quads are part of the new _my_gsets[2]
    2896                 :            :     // we will split them now, by creating triangles along the smallest diagonal
    2897                 :            :     // maybe we will come up with a better criteria, but for the time being, it should be fine.
    2898                 :            :     // what we will do: we will remove all quads from the surface sets, and split them
    2899                 :            : 
    2900 [ +  - ][ +  - ]:          3 :     for( Range::iterator it2 = _my_gsets[2].begin(); it2 != _my_gsets[2].end(); ++it2 )
         [ +  - ][ +  - ]
                 [ +  + ]
    2901                 :            :     {
    2902         [ +  - ]:          2 :         EntityHandle surface = *it2;
    2903         [ +  - ]:          2 :         Range quads;
    2904         [ +  - ]:          2 :         rval = _mbImpl->get_entities_by_type( surface, MBQUAD, quads );
    2905 [ -  + ][ #  # ]:          2 :         MBERRORR( rval, "can't get quads from the surface set" );
                 [ #  # ]
    2906         [ +  - ]:          2 :         rval = _mbImpl->remove_entities( surface, quads );
    2907 [ -  + ][ #  # ]:          2 :         MBERRORR( rval, "can't remove quads from the surface set" );  // they are not deleted, just
                 [ #  # ]
    2908                 :            :                                                                       // removed from the set
    2909 [ +  - ][ +  - ]:        129 :         for( Range::iterator it = quads.begin(); it != quads.end(); ++it )
         [ +  - ][ +  - ]
         [ +  + ][ +  - ]
    2910                 :            :         {
    2911         [ +  - ]:        127 :             EntityHandle quad = *it;
    2912                 :            :             int nnodes;
    2913                 :            :             const EntityHandle* conn;
    2914         [ +  - ]:        127 :             rval = _mbImpl->get_connectivity( quad, conn, nnodes );
    2915 [ -  + ][ #  # ]:        127 :             MBERRORR( rval, "can't get quad connectivity" );
                 [ #  # ]
    2916                 :            :             // get all vertices position, to see which one is the shortest diagonal
    2917 [ +  - ][ +  + ]:        635 :             CartVect pos[4];
    2918         [ +  - ]:        127 :             rval = _mbImpl->get_coords( conn, 4, (double*)&pos[0] );
    2919 [ -  + ][ #  # ]:        127 :             MBERRORR( rval, "can't get node coordinates" );
                 [ #  # ]
    2920 [ +  - ][ +  - ]:        127 :             bool diag1 = ( ( pos[2] - pos[0] ).length_squared() < ( pos[3] - pos[1] ).length_squared() );
         [ +  - ][ +  - ]
    2921                 :            :             EntityHandle newTris[2];
    2922                 :        127 :             EntityHandle tri1[3] = { conn[0], conn[1], conn[2] };
    2923                 :        127 :             EntityHandle tri2[3] = { conn[0], conn[2], conn[3] };
    2924         [ +  + ]:        127 :             if( !diag1 )
    2925                 :            :             {
    2926                 :         68 :                 tri1[2] = conn[3];
    2927                 :         68 :                 tri2[0] = conn[1];
    2928                 :            :             }
    2929         [ +  - ]:        127 :             rval = _mbImpl->create_element( MBTRI, tri1, 3, newTris[0] );
    2930 [ -  + ][ #  # ]:        127 :             MBERRORR( rval, "can't create triangle 1" );
                 [ #  # ]
    2931         [ +  - ]:        127 :             rval = _mbImpl->create_element( MBTRI, tri2, 3, newTris[1] );
    2932 [ -  + ][ #  # ]:        127 :             MBERRORR( rval, "can't create triangle 2" );
                 [ #  # ]
    2933         [ +  - ]:        127 :             rval = _mbImpl->add_entities( surface, newTris, 2 );
    2934 [ -  + ][ #  # ]:        127 :             MBERRORR( rval, "can't add triangles to the set" );
                 [ #  # ]
    2935                 :            :         }
    2936                 :            :         //
    2937                 :          2 :     }
    2938                 :         10 :     return MB_SUCCESS;
    2939                 :            : }
    2940                 :          1 : ErrorCode FBEngine::boundary_mesh_edges_on_face( EntityHandle face, Range& boundary_mesh_edges )
    2941                 :            : {
    2942                 :            :     // this list is used only for finding the intersecting mesh edge for starting the
    2943                 :            :     // polygonal cutting line at boundary (if !closed)
    2944         [ +  - ]:          1 :     Range bound_edges;
    2945         [ +  - ]:          1 :     ErrorCode rval = getAdjacentEntities( face, 1, bound_edges );
    2946 [ -  + ][ #  # ]:          1 :     MBERRORR( rval, " can't get boundary edges" );
                 [ #  # ]
    2947 [ +  - ][ +  - ]:          2 :     for( Range::iterator it = bound_edges.begin(); it != bound_edges.end(); ++it )
         [ +  - ][ +  - ]
                 [ +  + ]
    2948                 :            :     {
    2949         [ +  - ]:          1 :         EntityHandle b_edge = *it;
    2950                 :            :         // get all edges in range
    2951                 :            :         // Range mesh_edges;
    2952         [ +  - ]:          1 :         rval = _mbImpl->get_entities_by_dimension( b_edge, 1, boundary_mesh_edges );
    2953 [ -  + ][ #  # ]:          1 :         MBERRORR( rval, " can't get mesh edges" );
                 [ #  # ]
    2954                 :            :     }
    2955                 :          1 :     return MB_SUCCESS;
    2956                 :            : }
    2957                 :          1 : ErrorCode FBEngine::boundary_nodes_on_face( EntityHandle face, std::vector< EntityHandle >& boundary_nodes )
    2958                 :            : {
    2959                 :            :     // even if we repeat some nodes, it is OK
    2960                 :            :     // this list is used only for finding the closest boundary node for starting the
    2961                 :            :     // polygonal cutting line at boundary (if !closed)
    2962         [ +  - ]:          1 :     Range bound_edges;
    2963         [ +  - ]:          1 :     ErrorCode rval = getAdjacentEntities( face, 1, bound_edges );
    2964 [ -  + ][ #  # ]:          1 :     MBERRORR( rval, " can't get boundary edges" );
                 [ #  # ]
    2965         [ +  - ]:          2 :     Range b_nodes;
    2966 [ +  - ][ +  - ]:          2 :     for( Range::iterator it = bound_edges.begin(); it != bound_edges.end(); ++it )
         [ +  - ][ +  - ]
                 [ +  + ]
    2967                 :            :     {
    2968         [ +  - ]:          1 :         EntityHandle b_edge = *it;
    2969                 :            :         // get all edges in range
    2970         [ +  - ]:          1 :         Range mesh_edges;
    2971         [ +  - ]:          1 :         rval = _mbImpl->get_entities_by_dimension( b_edge, 1, mesh_edges );
    2972 [ -  + ][ #  # ]:          1 :         MBERRORR( rval, " can't get mesh edges" );
                 [ #  # ]
    2973         [ +  - ]:          1 :         rval = _mbImpl->get_connectivity( mesh_edges, b_nodes );
    2974 [ -  + ][ #  # ]:          1 :         MBERRORR( rval, " can't get nodes from mesh edges" );
         [ #  # ][ +  - ]
    2975                 :          1 :     }
    2976                 :            :     // create now a vector based on Range of nodes
    2977 [ +  - ][ +  - ]:          1 :     boundary_nodes.resize( b_nodes.size() );
    2978 [ +  - ][ +  - ]:          1 :     std::copy( b_nodes.begin(), b_nodes.end(), boundary_nodes.begin() );
                 [ +  - ]
    2979                 :          2 :     return MB_SUCCESS;
    2980                 :            : }
    2981                 :            : // used for splitting an edge
    2982                 :          4 : ErrorCode FBEngine::split_internal_edge( EntityHandle& edge, EntityHandle& newVertex )
    2983                 :            : {
    2984                 :            :     // split the edge, and form 4 new triangles and 2 edges
    2985                 :            :     // get 2 triangles adjacent to edge
    2986         [ +  - ]:          4 :     Range adj_tri;
    2987         [ +  - ]:          4 :     ErrorCode rval = _mbImpl->get_adjacencies( &edge, 1, 2, false, adj_tri );
    2988 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't get adj_tris" );
                 [ #  # ]
    2989 [ +  - ][ +  - ]:          4 :     adj_tri = subtract( adj_tri, _piercedTriangles );
    2990 [ +  - ][ -  + ]:          4 :     if( adj_tri.size() >= 3 ) { std::cout << "WARNING: non manifold geometry. Are you sure?"; }
                 [ #  # ]
    2991 [ +  - ][ +  - ]:         10 :     for( Range::iterator it = adj_tri.begin(); it != adj_tri.end(); ++it )
         [ +  - ][ +  - ]
                 [ +  + ]
    2992                 :            :     {
    2993         [ +  - ]:          6 :         EntityHandle tri = *it;
    2994         [ +  - ]:          6 :         _piercedTriangles.insert( tri );
    2995                 :            :         const EntityHandle* conn3;
    2996                 :            :         int nnodes;
    2997         [ +  - ]:          6 :         rval = _mbImpl->get_connectivity( tri, conn3, nnodes );
    2998 [ -  + ][ #  # ]:          6 :         MBERRORR( rval, "can't get nodes" );
                 [ #  # ]
    2999                 :            :         int num1, sense, offset;
    3000         [ +  - ]:          6 :         rval = _mbImpl->side_number( tri, edge, num1, sense, offset );
    3001 [ -  + ][ #  # ]:          6 :         MBERRORR( rval, "can't get side number" );
                 [ #  # ]
    3002                 :            :         // after we know the side number, we can split in 2 triangles
    3003                 :            :         // node i is opposite to edge i
    3004                 :          6 :         int num2 = ( num1 + 1 ) % 3;
    3005                 :          6 :         int num3 = ( num2 + 1 ) % 3;
    3006                 :            :         // the edge from num1 to num2 is split into 2 edges
    3007                 :          6 :         EntityHandle t1[] = { conn3[num2], conn3[num3], newVertex };
    3008                 :          6 :         EntityHandle t2[] = { conn3[num1], newVertex, conn3[num3] };
    3009                 :            :         EntityHandle newTriangle, newTriangle2;
    3010         [ +  - ]:          6 :         rval = _mbImpl->create_element( MBTRI, t1, 3, newTriangle );
    3011 [ -  + ][ #  # ]:          6 :         MBERRORR( rval, "can't create triangle" );
                 [ #  # ]
    3012         [ +  - ]:          6 :         _newTriangles.insert( newTriangle );
    3013         [ +  - ]:          6 :         rval = _mbImpl->create_element( MBTRI, t2, 3, newTriangle2 );
    3014 [ -  + ][ #  # ]:          6 :         MBERRORR( rval, "can't create triangle" );
                 [ #  # ]
    3015         [ +  - ]:          6 :         _newTriangles.insert( newTriangle2 );
    3016                 :            :         // create edges with this, indirectly
    3017         [ +  - ]:          6 :         std::vector< EntityHandle > edges0;
    3018         [ +  - ]:          6 :         rval = _mbImpl->get_adjacencies( &newTriangle, 1, 1, true, edges0 );
    3019 [ -  + ][ #  # ]:          6 :         MBERRORR( rval, "can't get new edges" );
                 [ #  # ]
    3020                 :          6 :         edges0.clear();
    3021         [ +  - ]:          6 :         rval = _mbImpl->get_adjacencies( &newTriangle2, 1, 1, true, edges0 );
    3022 [ -  + ][ #  # ]:          6 :         MBERRORR( rval, "can't get new edges" );
                 [ #  # ]
    3023         [ -  + ]:          6 :         if( debug_splits )
    3024                 :            :         {
    3025         [ #  # ]:          0 :             std::cout << "2 (out of 4) triangles formed:\n";
    3026         [ #  # ]:          0 :             _mbImpl->list_entity( newTriangle );
    3027         [ #  # ]:          0 :             print_debug_triangle( newTriangle );
    3028         [ #  # ]:          0 :             _mbImpl->list_entity( newTriangle2 );
    3029 [ #  # ][ +  - ]:          6 :             print_debug_triangle( newTriangle2 );
    3030                 :            :         }
    3031                 :          6 :     }
    3032                 :          4 :     return MB_SUCCESS;
    3033                 :            : }
    3034                 :            : // triangle split
    3035                 :          7 : ErrorCode FBEngine::divide_triangle( EntityHandle triangle, EntityHandle& newVertex )
    3036                 :            : {
    3037                 :            :     //
    3038         [ +  - ]:          7 :     _piercedTriangles.insert( triangle );
    3039                 :          7 :     int nnodes                = 0;
    3040                 :          7 :     const EntityHandle* conn3 = NULL;
    3041         [ +  - ]:          7 :     ErrorCode rval            = _mbImpl->get_connectivity( triangle, conn3, nnodes );
    3042 [ -  + ][ #  # ]:          7 :     MBERRORR( rval, "can't get nodes" );
                 [ #  # ]
    3043                 :          7 :     EntityHandle t1[] = { conn3[0], conn3[1], newVertex };
    3044                 :          7 :     EntityHandle t2[] = { conn3[1], conn3[2], newVertex };
    3045                 :          7 :     EntityHandle t3[] = { conn3[2], conn3[0], newVertex };
    3046                 :            :     EntityHandle newTriangle, newTriangle2, newTriangle3;
    3047         [ +  - ]:          7 :     rval = _mbImpl->create_element( MBTRI, t1, 3, newTriangle );
    3048 [ -  + ][ #  # ]:          7 :     MBERRORR( rval, "can't create triangle" );
                 [ #  # ]
    3049         [ +  - ]:          7 :     _newTriangles.insert( newTriangle );
    3050         [ +  - ]:          7 :     rval = _mbImpl->create_element( MBTRI, t2, 3, newTriangle3 );
    3051 [ -  + ][ #  # ]:          7 :     MBERRORR( rval, "can't create triangle" );
                 [ #  # ]
    3052         [ +  - ]:          7 :     _newTriangles.insert( newTriangle3 );
    3053         [ +  - ]:          7 :     rval = _mbImpl->create_element( MBTRI, t3, 3, newTriangle2 );
    3054 [ -  + ][ #  # ]:          7 :     MBERRORR( rval, "can't create triangle" );
                 [ #  # ]
    3055         [ +  - ]:          7 :     _newTriangles.insert( newTriangle2 );
    3056                 :            : 
    3057                 :            :     // create all edges
    3058         [ +  - ]:          7 :     std::vector< EntityHandle > edges0;
    3059         [ +  - ]:          7 :     rval = _mbImpl->get_adjacencies( &newTriangle, 1, 1, true, edges0 );
    3060 [ -  + ][ #  # ]:          7 :     MBERRORR( rval, "can't get new edges" );
                 [ #  # ]
    3061                 :          7 :     edges0.clear();
    3062         [ +  - ]:          7 :     rval = _mbImpl->get_adjacencies( &newTriangle2, 1, 1, true, edges0 );
    3063 [ -  + ][ #  # ]:          7 :     MBERRORR( rval, "can't get new edges" );
                 [ #  # ]
    3064         [ -  + ]:          7 :     if( debug_splits )
    3065                 :            :     {
    3066         [ #  # ]:          0 :         std::cout << "3 triangles formed:\n";
    3067         [ #  # ]:          0 :         _mbImpl->list_entity( newTriangle );
    3068         [ #  # ]:          0 :         print_debug_triangle( newTriangle );
    3069         [ #  # ]:          0 :         _mbImpl->list_entity( newTriangle3 );
    3070         [ #  # ]:          0 :         print_debug_triangle( newTriangle3 );
    3071         [ #  # ]:          0 :         _mbImpl->list_entity( newTriangle2 );
    3072         [ #  # ]:          0 :         print_debug_triangle( newTriangle2 );
    3073         [ #  # ]:          0 :         std::cout << "original nodes in tri:\n";
    3074         [ #  # ]:          0 :         _mbImpl->list_entity( conn3[0] );
    3075         [ #  # ]:          0 :         _mbImpl->list_entity( conn3[1] );
    3076         [ #  # ]:          0 :         _mbImpl->list_entity( conn3[2] );
    3077                 :            :     }
    3078                 :          7 :     return MB_SUCCESS;
    3079                 :            : }
    3080                 :            : 
    3081                 :          1 : ErrorCode FBEngine::create_volume_with_direction( EntityHandle newFace1, EntityHandle newFace2, double* direction,
    3082                 :            :                                                   EntityHandle& volume )
    3083                 :            : {
    3084                 :            : 
    3085                 :            :     // MESHSET
    3086                 :            :     // ErrorCode rval = _mbImpl->create_meshset(MESHSET_ORDERED, new_geo_edge);
    3087         [ +  - ]:          1 :     ErrorCode rval = _mbImpl->create_meshset( MESHSET_SET, volume );
    3088 [ -  + ][ #  # ]:          1 :     MBERRORR( rval, "can't create volume" );
                 [ #  # ]
    3089                 :            : 
    3090                 :          1 :     int volumeMatId = 1;  // just give a mat id, for debugging, mostly
    3091                 :            :     Tag matTag;
    3092         [ +  - ]:          1 :     rval = _mbImpl->tag_get_handle( MATERIAL_SET_TAG_NAME, 1, MB_TYPE_INTEGER, matTag );
    3093 [ -  + ][ #  # ]:          1 :     MBERRORR( rval, "can't get material tag" );
                 [ #  # ]
    3094                 :            : 
    3095         [ +  - ]:          1 :     rval = _mbImpl->tag_set_data( matTag, &volume, 1, &volumeMatId );
    3096 [ -  + ][ #  # ]:          1 :     MBERRORR( rval, "can't set material tag value on volume" );
                 [ #  # ]
    3097                 :            : 
    3098                 :            :     // get the edges of those 2 faces, and get the vertices of those edges
    3099                 :            :     // in order, they should be created in the same order (?); check for that, anyway
    3100         [ +  - ]:          1 :     rval = _mbImpl->add_parent_child( volume, newFace1 );
    3101 [ -  + ][ #  # ]:          1 :     MBERRORR( rval, "can't add first face to volume" );
                 [ #  # ]
    3102                 :            : 
    3103         [ +  - ]:          1 :     rval = _mbImpl->add_parent_child( volume, newFace2 );
    3104 [ -  + ][ #  # ]:          1 :     MBERRORR( rval, "can't add second face to volume" );
                 [ #  # ]
    3105                 :            : 
    3106                 :            :     // first is bottom, so it is negatively oriented
    3107         [ +  - ]:          1 :     rval = _my_geomTopoTool->add_geo_set( volume, 3 );
    3108 [ -  + ][ #  # ]:          1 :     MBERRORR( rval, "can't add volume to the gtt" );
                 [ #  # ]
    3109                 :            : 
    3110                 :            :     // set senses
    3111                 :            :     // bottom face is negatively oriented, its normal is toward interior of the volume
    3112         [ +  - ]:          1 :     rval = _my_geomTopoTool->set_sense( newFace1, volume, -1 );
    3113 [ -  + ][ #  # ]:          1 :     MBERRORR( rval, "can't set bottom face sense to the volume" );
                 [ #  # ]
    3114                 :            : 
    3115                 :            :     // the top face is positively oriented
    3116         [ +  - ]:          1 :     rval = _my_geomTopoTool->set_sense( newFace2, volume, 1 );
    3117 [ -  + ][ #  # ]:          1 :     MBERRORR( rval, "can't set top face sense to the volume" );
                 [ #  # ]
    3118                 :            : 
    3119                 :            :     // the children should be in the same direction
    3120                 :            :     //   get the side edges of each face, and form lateral faces, along direction
    3121         [ +  - ]:          1 :     std::vector< EntityHandle > edges1;
    3122         [ +  - ]:          2 :     std::vector< EntityHandle > edges2;
    3123                 :            : 
    3124         [ +  - ]:          1 :     rval = _mbImpl->get_child_meshsets( newFace1, edges1 );  // no hops
    3125 [ -  + ][ #  # ]:          1 :     MBERRORR( rval, "can't get children edges or first face, bottom" );
                 [ #  # ]
    3126                 :            : 
    3127         [ +  - ]:          1 :     rval = _mbImpl->get_child_meshsets( newFace2, edges2 );  // no hops
    3128 [ -  + ][ #  # ]:          1 :     MBERRORR( rval, "can't get children edges for second face, top" );
                 [ #  # ]
    3129                 :            : 
    3130 [ -  + ][ #  # ]:          1 :     if( edges1.size() != edges2.size() ) MBERRORR( MB_FAILURE, "wrong correspondence " );
                 [ #  # ]
    3131                 :            : 
    3132         [ +  + ]:          5 :     for( unsigned int i = 0; i < edges1.size(); ++i )
    3133                 :            :     {
    3134                 :            :         EntityHandle newLatFace;
    3135 [ +  - ][ +  - ]:          4 :         rval = weave_lateral_face_from_edges( edges1[i], edges2[i], direction, newLatFace );
                 [ +  - ]
    3136 [ -  + ][ #  # ]:          4 :         MBERRORR( rval, "can't weave lateral face" );
                 [ #  # ]
    3137         [ +  - ]:          4 :         rval = _mbImpl->add_parent_child( volume, newLatFace );
    3138 [ -  + ][ #  # ]:          4 :         MBERRORR( rval, "can't add lateral face to volume" );
                 [ #  # ]
    3139                 :            : 
    3140                 :            :         // set sense as positive
    3141         [ +  - ]:          4 :         rval = _my_geomTopoTool->set_sense( newLatFace, volume, 1 );
    3142 [ -  + ][ #  # ]:          4 :         MBERRORR( rval, "can't set lateral face sense to the volume" );
                 [ #  # ]
    3143                 :            :     }
    3144                 :            : 
    3145         [ +  - ]:          1 :     rval = set_default_neumann_tags();
    3146 [ -  + ][ #  # ]:          1 :     MBERRORR( rval, "can't set new neumann tags" );
                 [ #  # ]
    3147                 :            : 
    3148                 :          2 :     return MB_SUCCESS;
    3149                 :            : }
    3150                 :            : 
    3151                 :          8 : ErrorCode FBEngine::get_nodes_from_edge( EntityHandle gedge, std::vector< EntityHandle >& nodes )
    3152                 :            : {
    3153         [ +  - ]:          8 :     std::vector< EntityHandle > ents;
    3154         [ +  - ]:          8 :     ErrorCode rval = _mbImpl->get_entities_by_type( gedge, MBEDGE, ents );
    3155         [ -  + ]:          8 :     if( MB_SUCCESS != rval ) return rval;
    3156         [ -  + ]:          8 :     if( ents.size() < 1 ) return MB_FAILURE;
    3157                 :            : 
    3158         [ +  - ]:          8 :     nodes.resize( ents.size() + 1 );
    3159                 :          8 :     const EntityHandle* conn = NULL;
    3160                 :            :     int len;
    3161         [ +  + ]:       1414 :     for( unsigned int i = 0; i < ents.size(); ++i )
    3162                 :            :     {
    3163 [ +  - ][ +  - ]:       1406 :         rval = _mbImpl->get_connectivity( ents[i], conn, len );
    3164 [ -  + ][ #  # ]:       1406 :         MBERRORR( rval, "can't get edge connectivity" );
                 [ #  # ]
    3165         [ +  - ]:       1406 :         nodes[i] = conn[0];
    3166                 :            :     }
    3167                 :            :     // the last one is conn[1]
    3168         [ +  - ]:          8 :     nodes[ents.size()] = conn[1];
    3169                 :          8 :     return MB_SUCCESS;
    3170                 :            : }
    3171                 :          4 : ErrorCode FBEngine::weave_lateral_face_from_edges( EntityHandle bEdge, EntityHandle tEdge, double* direction,
    3172                 :            :                                                    EntityHandle& newLatFace )
    3173                 :            : {
    3174                 :            :     // in weird cases might need to create new vertices in the interior;
    3175                 :            :     // in most cases, it is OK
    3176                 :            : 
    3177         [ +  - ]:          4 :     ErrorCode rval = _mbImpl->create_meshset( MESHSET_SET, newLatFace );
    3178 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't create new lateral face" );
                 [ #  # ]
    3179                 :            : 
    3180                 :            :     EntityHandle v[4];  // vertex sets
    3181                 :            :     // bot edge will be v1->v2
    3182                 :            :     // top edge will be v3->v4
    3183                 :            :     // we need to create edges from v1 to v3 and from v2 to v4
    3184         [ +  - ]:          4 :     std::vector< EntityHandle > adj;
    3185         [ +  - ]:          4 :     rval = _mbImpl->get_child_meshsets( bEdge, adj );
    3186 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't get children nodes" );
                 [ #  # ]
    3187                 :          4 :     bool periodic = false;
    3188         [ -  + ]:          4 :     if( adj.size() == 1 )
    3189                 :            :     {
    3190         [ #  # ]:          0 :         v[0] = v[1] = adj[0];
    3191                 :          0 :         periodic    = true;
    3192                 :            :     }
    3193                 :            :     else
    3194                 :            :     {
    3195         [ +  - ]:          4 :         v[0] = adj[0];
    3196         [ +  - ]:          4 :         v[1] = adj[1];
    3197                 :            :     }
    3198                 :            :     int senseB;
    3199         [ +  - ]:          4 :     rval = getEgVtxSense( bEdge, v[0], v[1], senseB );
    3200 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't get bottom edge sense" );
                 [ #  # ]
    3201         [ +  + ]:          4 :     if( -1 == senseB )
    3202                 :            :     {
    3203         [ +  - ]:          1 :         v[1] = adj[0];  // so , bEdge will be oriented from v[0] to v[1], and will start at
    3204                 :            :                         // nodes1, coords1..
    3205         [ +  - ]:          1 :         v[0] = adj[1];
    3206                 :            :     }
    3207                 :          4 :     adj.clear();
    3208         [ +  - ]:          4 :     rval = _mbImpl->get_child_meshsets( tEdge, adj );
    3209 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't get children nodes" );
                 [ #  # ]
    3210         [ -  + ]:          4 :     if( adj.size() == 1 )
    3211                 :            :     {
    3212         [ #  # ]:          0 :         v[2] = v[3] = adj[0];
    3213 [ #  # ][ #  # ]:          0 :         if( !periodic ) MBERRORR( MB_FAILURE, "top edge is periodic, but bottom edge is not" );
                 [ #  # ]
    3214                 :            :     }
    3215                 :            :     else
    3216                 :            :     {
    3217         [ +  - ]:          4 :         v[2] = adj[0];
    3218         [ +  - ]:          4 :         v[3] = adj[1];
    3219 [ -  + ][ #  # ]:          4 :         if( periodic ) MBERRORR( MB_FAILURE, "top edge is not periodic, but bottom edge is" );
                 [ #  # ]
    3220                 :            :     }
    3221                 :            : 
    3222                 :            :     // now, using nodes on bottom edge and top edge, create triangles, oriented outwards the
    3223                 :            :     //  volume (sense positive on bottom edge)
    3224         [ +  - ]:          8 :     std::vector< EntityHandle > nodes1;
    3225         [ +  - ]:          4 :     rval = get_nodes_from_edge( bEdge, nodes1 );
    3226 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't get nodes from bott edge" );
                 [ #  # ]
    3227                 :            : 
    3228         [ +  - ]:          8 :     std::vector< EntityHandle > nodes2;
    3229         [ +  - ]:          4 :     rval = get_nodes_from_edge( tEdge, nodes2 );
    3230 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't get nodes from top edge" );
                 [ #  # ]
    3231                 :            : 
    3232 [ +  - ][ +  - ]:          8 :     std::vector< CartVect > coords1, coords2;
    3233         [ +  - ]:          4 :     coords1.resize( nodes1.size() );
    3234         [ +  - ]:          4 :     coords2.resize( nodes2.size() );
    3235                 :            : 
    3236                 :          4 :     int N1 = (int)nodes1.size();
    3237                 :          4 :     int N2 = (int)nodes2.size();
    3238                 :            : 
    3239 [ +  - ][ +  - ]:          4 :     rval = _mbImpl->get_coords( &( nodes1[0] ), nodes1.size(), (double*)&( coords1[0] ) );
                 [ +  - ]
    3240 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't get coords of nodes from bott edge" );
                 [ #  # ]
    3241                 :            : 
    3242 [ +  - ][ +  - ]:          4 :     rval = _mbImpl->get_coords( &( nodes2[0] ), nodes2.size(), (double*)&( coords2[0] ) );
                 [ +  - ]
    3243 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't get coords of nodes from top edge" );
                 [ #  # ]
    3244         [ +  - ]:          4 :     CartVect up( direction );
    3245                 :            : 
    3246                 :            :     // see if the start and end coordinates are matching, if not, reverse edge 2 nodes and
    3247                 :            :     // coordinates
    3248 [ +  - ][ +  - ]:          4 :     CartVect v1 = ( coords1[0] - coords2[0] ) * up;
         [ +  - ][ +  - ]
    3249 [ +  - ][ +  - ]:          4 :     CartVect v2 = ( coords1[0] - coords2[N2 - 1] ) * up;
         [ +  - ][ +  - ]
    3250 [ +  - ][ +  - ]:          4 :     if( v1.length_squared() > v2.length_squared() )
                 [ -  + ]
    3251                 :            :     {
    3252                 :            :         // we need to reverse coords2 and node2, as nodes are not above each other
    3253                 :            :         // the edges need to be found between v0 and v3, v1 and v2!
    3254         [ #  # ]:          0 :         for( unsigned int k = 0; k < nodes2.size() / 2; k++ )
    3255                 :            :         {
    3256         [ #  # ]:          0 :             EntityHandle tmp    = nodes2[k];
    3257 [ #  # ][ #  # ]:          0 :             nodes2[k]           = nodes2[N2 - 1 - k];
    3258         [ #  # ]:          0 :             nodes2[N2 - 1 - k]  = tmp;
    3259         [ #  # ]:          0 :             CartVect tv         = coords2[k];
    3260 [ #  # ][ #  # ]:          0 :             coords2[k]          = coords2[N2 - 1 - k];
    3261         [ #  # ]:          0 :             coords2[N2 - 1 - k] = tv;
    3262                 :            :         }
    3263                 :            :     }
    3264                 :            :     // make sure v[2] has nodes2[0], if not, reverse v[2] and v[3]
    3265 [ +  - ][ +  - ]:          4 :     if( !_mbImpl->contains_entities( v[2], &( nodes2[0] ), 1 ) )
                 [ +  + ]
    3266                 :            :     {
    3267                 :            :         // reverse v[2] and v[3], so v[2] will be above v[0]
    3268                 :          1 :         EntityHandle tmp = v[2];
    3269                 :          1 :         v[2]             = v[3];
    3270                 :          1 :         v[3]             = tmp;
    3271                 :            :     }
    3272                 :            :     // now we know that v[0]--v[3] will be vertex sets in the order we want
    3273 [ +  - ][ +  - ]:          4 :     EntityHandle nd[4] = { nodes1[0], nodes1[N1 - 1], nodes2[0], nodes2[N2 - 1] };
         [ +  - ][ +  - ]
    3274                 :            : 
    3275                 :          4 :     adj.clear();
    3276                 :            :     EntityHandle e1, e2;
    3277                 :            :     // find edge 1 between v[0] and v[2], and e2 between v[1] and v[3]
    3278         [ +  - ]:          4 :     rval = _mbImpl->get_parent_meshsets( v[0], adj );
    3279 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't get edges connected to vertex set 1" );
                 [ #  # ]
    3280                 :          4 :     bool found = false;
    3281         [ +  + ]:         15 :     for( unsigned int j = 0; j < adj.size(); j++ )
    3282                 :            :     {
    3283         [ +  - ]:         11 :         EntityHandle ed = adj[j];
    3284         [ +  - ]:         11 :         Range vertices;
    3285         [ +  - ]:         11 :         rval = _mbImpl->get_child_meshsets( ed, vertices );
    3286 [ +  - ][ +  - ]:         11 :         if( vertices.find( v[2] ) != vertices.end() )
         [ +  - ][ +  + ]
    3287                 :            :         {
    3288                 :          3 :             found = true;
    3289                 :          3 :             e1    = ed;
    3290         [ +  + ]:         11 :             break;
    3291                 :            :         }
    3292                 :          8 :     }
    3293         [ +  + ]:          4 :     if( !found )
    3294                 :            :     {
    3295                 :            :         // create an edge from v[0] to v[2]
    3296         [ +  - ]:          1 :         rval = _mbImpl->create_meshset( MESHSET_SET, e1 );
    3297 [ -  + ][ #  # ]:          1 :         MBERRORR( rval, "can't create edge 1" );
                 [ #  # ]
    3298                 :            : 
    3299         [ +  - ]:          1 :         rval = _mbImpl->add_parent_child( e1, v[0] );
    3300 [ -  + ][ #  # ]:          1 :         MBERRORR( rval, "can't add parent - child relation" );
                 [ #  # ]
    3301                 :            : 
    3302         [ +  - ]:          1 :         rval = _mbImpl->add_parent_child( e1, v[2] );
    3303 [ -  + ][ #  # ]:          1 :         MBERRORR( rval, "can't add parent - child relation" );
                 [ #  # ]
    3304                 :            : 
    3305                 :          1 :         EntityHandle nn2[2] = { nd[0], nd[2] };
    3306                 :            :         EntityHandle medge;
    3307         [ +  - ]:          1 :         rval = _mbImpl->create_element( MBEDGE, nn2, 2, medge );
    3308 [ -  + ][ #  # ]:          1 :         MBERRORR( rval, "can't create mesh edge" );
                 [ #  # ]
    3309                 :            : 
    3310         [ +  - ]:          1 :         rval = _mbImpl->add_entities( e1, &medge, 1 );
    3311 [ -  + ][ #  # ]:          1 :         MBERRORR( rval, "can't add mesh edge to geo edge" );
                 [ #  # ]
    3312                 :            : 
    3313         [ +  - ]:          1 :         rval = this->_my_geomTopoTool->add_geo_set( e1, 1 );
    3314 [ -  + ][ #  # ]:          1 :         MBERRORR( rval, "can't add edge to gtt" );
                 [ #  # ]
    3315                 :            :     }
    3316                 :            : 
    3317                 :            :     // find the edge from v2 to v4 (if not, create one)
    3318         [ +  - ]:          4 :     rval = _mbImpl->get_parent_meshsets( v[1], adj );
    3319 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't get edges connected to vertex set 2" );
                 [ #  # ]
    3320                 :          4 :     found = false;
    3321         [ +  + ]:         20 :     for( unsigned int i = 0; i < adj.size(); i++ )
    3322                 :            :     {
    3323         [ +  - ]:         16 :         EntityHandle ed = adj[i];
    3324         [ +  - ]:         16 :         Range vertices;
    3325         [ +  - ]:         16 :         rval = _mbImpl->get_child_meshsets( ed, vertices );
    3326 [ +  - ][ +  - ]:         16 :         if( vertices.find( v[3] ) != vertices.end() )
         [ +  - ][ +  + ]
    3327                 :            :         {
    3328                 :          1 :             found = true;
    3329                 :          1 :             e2    = ed;
    3330         [ +  + ]:         16 :             break;
    3331                 :            :         }
    3332                 :         15 :     }
    3333         [ +  + ]:          4 :     if( !found )
    3334                 :            :     {
    3335                 :            :         // create an edge from v2 to v4
    3336         [ +  - ]:          3 :         rval = _mbImpl->create_meshset( MESHSET_SET, e2 );
    3337 [ -  + ][ #  # ]:          3 :         MBERRORR( rval, "can't create edge 1" );
                 [ #  # ]
    3338                 :            : 
    3339         [ +  - ]:          3 :         rval = _mbImpl->add_parent_child( e2, v[1] );
    3340 [ -  + ][ #  # ]:          3 :         MBERRORR( rval, "can't add parent - child relation" );
                 [ #  # ]
    3341                 :            : 
    3342         [ +  - ]:          3 :         rval = _mbImpl->add_parent_child( e2, v[3] );
    3343 [ -  + ][ #  # ]:          3 :         MBERRORR( rval, "can't add parent - child relation" );
                 [ #  # ]
    3344                 :            : 
    3345                 :          3 :         EntityHandle nn2[2] = { nd[1], nd[3] };
    3346                 :            :         EntityHandle medge;
    3347         [ +  - ]:          3 :         rval = _mbImpl->create_element( MBEDGE, nn2, 2, medge );
    3348 [ -  + ][ #  # ]:          3 :         MBERRORR( rval, "can't create mesh edge" );
                 [ #  # ]
    3349                 :            : 
    3350         [ +  - ]:          3 :         rval = _mbImpl->add_entities( e2, &medge, 1 );
    3351 [ -  + ][ #  # ]:          3 :         MBERRORR( rval, "can't add mesh edge to geo edge" );
                 [ #  # ]
    3352                 :            : 
    3353         [ +  - ]:          3 :         rval = _my_geomTopoTool->add_geo_set( e2, 1 );
    3354 [ -  + ][ #  # ]:          3 :         MBERRORR( rval, "can't add edge to gtt" );
                 [ #  # ]
    3355                 :            :     }
    3356                 :            : 
    3357                 :            :     // now we have the four edges, add them to the face, as children
    3358                 :            : 
    3359                 :            :     // add children to face
    3360         [ +  - ]:          4 :     rval = _mbImpl->add_parent_child( newLatFace, bEdge );
    3361 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't add parent - child relation" );
                 [ #  # ]
    3362                 :            : 
    3363         [ +  - ]:          4 :     rval = _mbImpl->add_parent_child( newLatFace, tEdge );
    3364 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't add parent - child relation" );
                 [ #  # ]
    3365                 :            : 
    3366         [ +  - ]:          4 :     rval = _mbImpl->add_parent_child( newLatFace, e1 );
    3367 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't add parent - child relation" );
                 [ #  # ]
    3368                 :            : 
    3369         [ +  - ]:          4 :     rval = _mbImpl->add_parent_child( newLatFace, e2 );
    3370 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't add parent - child relation" );
                 [ #  # ]
    3371                 :            : 
    3372         [ +  - ]:          4 :     rval = _my_geomTopoTool->add_geo_set( newLatFace, 2 );
    3373 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't add face to gtt" );
                 [ #  # ]
    3374                 :            :     // add senses
    3375                 :            :     //
    3376         [ +  - ]:          4 :     rval = _my_geomTopoTool->set_sense( bEdge, newLatFace, 1 );
    3377 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't set bottom edge sense to the lateral face" );
                 [ #  # ]
    3378                 :            : 
    3379                 :            :     int Tsense;
    3380         [ +  - ]:          4 :     rval = getEgVtxSense( tEdge, v[3], v[2], Tsense );
    3381 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't get top edge sense" );
                 [ #  # ]
    3382                 :            :     // we need to see what sense has topEdge in face
    3383         [ +  - ]:          4 :     rval = _my_geomTopoTool->set_sense( tEdge, newLatFace, Tsense );
    3384 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't set top edge sense to the lateral face" );
                 [ #  # ]
    3385                 :            : 
    3386         [ +  - ]:          4 :     rval = _my_geomTopoTool->set_sense( e1, newLatFace, -1 );
    3387 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't set first vert edge sense" );
                 [ #  # ]
    3388                 :            : 
    3389         [ +  - ]:          4 :     rval = _my_geomTopoTool->set_sense( e2, newLatFace, 1 );
    3390 [ -  + ][ #  # ]:          4 :     MBERRORR( rval, "can't set second edge sense to the lateral face" );
                 [ #  # ]
    3391                 :            :     // first, create edges along direction, for the
    3392                 :            : 
    3393                 :          4 :     int indexB = 0, indexT = 0;  // indices of the current nodes in the weaving process
    3394                 :            :     // weaving is either up or down; the triangles are oriented positively either way
    3395                 :            :     // up is nodes1[indexB], nodes2[indexT+1], nodes2[indexT]
    3396                 :            :     // down is nodes1[indexB], nodes1[indexB+1], nodes2[indexT]
    3397                 :            :     // the decision to weave up or down is based on which one is closer to the direction normal
    3398                 :            :     /*
    3399                 :            :      *
    3400                 :            :      *     --------*------*-----------*                           ^
    3401                 :            :      *            /   .    \ .      .           ------> dir1      |  up
    3402                 :            :      *           /.         \   .  .                              |
    3403                 :            :      *     -----*------------*----*
    3404                 :            :      *
    3405                 :            :      */
    3406                 :            :     // we have to change the logic to account for cases when the curve in xy plane is not straight
    3407                 :            :     // (for example, when merging curves with a min_dot < -0.5, which means that the edges
    3408                 :            :     // could be even closed (periodic), with one vertex
    3409                 :            :     // the top and bottom curves should follow the same path in the "xy" plane (better to say
    3410                 :            :     // the plane perpendicular to the direction of weaving)
    3411                 :            :     // in this logic, the vector dir1 varies along the curve !!!
    3412 [ +  - ][ +  - ]:          4 :     CartVect dir1 = coords1[1] - coords1[0];  // we should have at least 2 nodes, N1>=2!!
                 [ +  - ]
    3413                 :            : 
    3414         [ +  - ]:          4 :     CartVect planeNormal = dir1 * up;
    3415         [ +  - ]:          4 :     dir1                 = up * planeNormal;
    3416         [ +  - ]:          4 :     dir1.normalize();
    3417                 :            :     // this direction will be updated constantly with the direction of last edge added
    3418                 :          4 :     bool weaveDown = true;
    3419                 :            : 
    3420         [ +  - ]:          4 :     CartVect startP = coords1[0];  // used for origin of comparisons
    3421                 :            :     while( 1 )
    3422                 :            :     {
    3423 [ +  + ][ +  + ]:       1410 :         if( ( indexB == N1 - 1 ) && ( indexT == N2 - 1 ) ) break;  // we cannot advance anymore
    3424         [ +  + ]:       1406 :         if( indexB == N1 - 1 ) { weaveDown = false; }
    3425         [ +  + ]:       1403 :         else if( indexT == N2 - 1 )
    3426                 :            :         {
    3427                 :          1 :             weaveDown = true;
    3428                 :            :         }
    3429                 :            :         else
    3430                 :            :         {
    3431                 :            :             // none are at the end, we have to decide which way to go, based on which  index + 1 is
    3432                 :            :             // closer
    3433 [ +  - ][ +  - ]:       1402 :             double proj1 = ( coords1[indexB + 1] - startP ) % dir1;
                 [ +  - ]
    3434 [ +  - ][ +  - ]:       1402 :             double proj2 = ( coords2[indexT + 1] - startP ) % dir1;
                 [ +  - ]
    3435         [ +  + ]:       1402 :             if( proj1 < proj2 )
    3436                 :        748 :                 weaveDown = true;
    3437                 :            :             else
    3438                 :        654 :                 weaveDown = false;
    3439                 :            :         }
    3440 [ +  - ][ +  - ]:       1406 :         EntityHandle nTri[3] = { nodes1[indexB], 0, nodes2[indexT] };
    3441         [ +  + ]:       1406 :         if( weaveDown )
    3442                 :            :         {
    3443         [ +  - ]:        749 :             nTri[1] = nodes1[indexB + 1];
    3444         [ +  - ]:        749 :             nTri[2] = nodes2[indexT];
    3445                 :        749 :             indexB++;
    3446                 :            :         }
    3447                 :            :         else
    3448                 :            :         {
    3449         [ +  - ]:        657 :             nTri[1] = nodes2[indexT + 1];
    3450                 :        657 :             indexT++;
    3451                 :            :         }
    3452                 :            :         EntityHandle triangle;
    3453         [ +  - ]:       1406 :         rval = _mbImpl->create_element( MBTRI, nTri, 3, triangle );
    3454 [ -  + ][ #  # ]:       1406 :         MBERRORR( rval, "can't create triangle" );
                 [ #  # ]
    3455                 :            : 
    3456         [ +  - ]:       1406 :         rval = _mbImpl->add_entities( newLatFace, &triangle, 1 );
    3457 [ -  + ][ #  # ]:       1406 :         MBERRORR( rval, "can't add triangle to face set" );
                 [ #  # ]
    3458         [ +  + ]:       1406 :         if( weaveDown )
    3459                 :            :         {
    3460                 :            :             // increase was from nodes1[indexB-1] to nodes1[indexb]
    3461 [ +  - ][ +  - ]:        749 :             dir1 = coords1[indexB] - coords1[indexB - 1];  // we should have at least 2 nodes, N1>=2!!
                 [ +  - ]
    3462                 :            :         }
    3463                 :            :         else
    3464                 :            :         {
    3465 [ +  - ][ +  - ]:        657 :             dir1 = coords2[indexT] - coords2[indexT - 1];
                 [ +  - ]
    3466                 :            :         }
    3467 [ +  - ][ +  - ]:       1406 :         dir1 = up * ( dir1 * up );
    3468         [ +  - ]:       1406 :         dir1.normalize();
    3469                 :            :     }
    3470                 :            :     // we do not check yet if the triangles are inverted
    3471                 :            :     // if yes, we should correct them. HOW?
    3472                 :            :     // we probably need a better meshing strategy, one that can overcome really bad meshes.
    3473                 :            :     // again, these faces are not what we should use for geometry, maybe we should use the
    3474                 :            :     //  extruded quads, identified AFTER hexa are created.
    3475                 :            :     // right now, I see only a cosmetic use of these lateral faces
    3476                 :            :     // the whole idea of volume maybe is overrated
    3477                 :            :     // volume should be just quads extruded from bottom ?
    3478                 :            :     //
    3479                 :          8 :     return MB_SUCCESS;
    3480                 :            : }
    3481                 :            : // this will be used during creation of the volume, to set unique
    3482                 :            : // tags on all surfaces
    3483                 :            : // it is changing original tags, so do not use it if you want to preserve
    3484                 :            : // initial neumann tags
    3485                 :          1 : ErrorCode FBEngine::set_default_neumann_tags()
    3486                 :            : {
    3487                 :            :     // these are for debugging purposes only
    3488                 :            :     // check the initial tag, then
    3489                 :            :     Tag ntag;
    3490         [ +  - ]:          1 :     ErrorCode rval = _mbImpl->tag_get_handle( NEUMANN_SET_TAG_NAME, 1, MB_TYPE_INTEGER, ntag );
    3491 [ -  + ][ #  # ]:          1 :     MBERRORR( rval, "can't get tag handle" );
                 [ #  # ]
    3492                 :            :     // get all surfaces in the model now
    3493 [ +  - ][ +  + ]:         11 :     Range sets[5];
                 [ #  # ]
    3494         [ +  - ]:          1 :     rval = _my_geomTopoTool->find_geomsets( sets );
    3495 [ -  + ][ #  # ]:          1 :     MBERRORR( rval, "can't get geo sets" );
                 [ #  # ]
    3496         [ +  - ]:          1 :     int nfaces = (int)sets[2].size();
    3497 [ +  - ][ +  - ]:          1 :     int* vals  = new int[nfaces];
    3498         [ +  + ]:          9 :     for( int i = 0; i < nfaces; i++ )
    3499                 :            :     {
    3500                 :          8 :         vals[i] = i + 1;
    3501                 :            :     }
    3502         [ +  - ]:          1 :     rval = _mbImpl->tag_set_data( ntag, sets[2], (void*)vals );
    3503 [ -  + ][ #  # ]:          1 :     MBERRORR( rval, "can't set tag values for neumann sets" );
                 [ #  # ]
    3504                 :            : 
    3505         [ +  - ]:          1 :     delete[] vals;
    3506                 :            : 
    3507         [ +  + ]:          6 :     return MB_SUCCESS;
           [ #  #  #  # ]
    3508                 :            : }
    3509                 :            : // a reverse operation for splitting an gedge at a mesh node
    3510                 :          4 : ErrorCode FBEngine::chain_edges( double min_dot )
    3511                 :            : {
    3512 [ +  - ][ +  + ]:         44 :     Range sets[5];
                 [ #  # ]
    3513                 :            :     ErrorCode rval;
    3514                 :            :     while( 1 )  // break out only if no edges are chained
    3515                 :            :     {
    3516         [ +  - ]:          6 :         rval = _my_geomTopoTool->find_geomsets( sets );
    3517 [ -  + ][ #  # ]:          6 :         MBERRORR( rval, "can't get geo sets" );
                 [ #  # ]
    3518                 :            :         // these gentities are "always" current, while the ones in this-> _my_gsets[0:4] are
    3519                 :            :         // the "originals" before FBEngine modifications
    3520         [ +  - ]:          6 :         int nedges = (int)sets[1].size();
    3521                 :            :         // as long as we have chainable edges, continue;
    3522                 :          6 :         bool chain = false;
    3523         [ +  + ]:         37 :         for( int i = 0; i < nedges; i++ )
    3524                 :            :         {
    3525         [ +  - ]:         33 :             EntityHandle edge = sets[1][i];
    3526                 :            :             EntityHandle next_edge;
    3527                 :         33 :             bool chainable = false;
    3528         [ +  - ]:         33 :             rval           = chain_able_edge( edge, min_dot, next_edge, chainable );
    3529 [ -  + ][ #  # ]:         33 :             MBERRORR( rval, "can't determine chain-ability" );
                 [ #  # ]
    3530         [ +  + ]:         33 :             if( chainable )
    3531                 :            :             {
    3532         [ +  - ]:          2 :                 rval = chain_two_edges( edge, next_edge );
    3533 [ -  + ][ #  # ]:          2 :                 MBERRORR( rval, "can't chain 2 edges" );
                 [ #  # ]
    3534                 :          2 :                 chain = true;
    3535                 :          2 :                 break;  // interrupt for loop
    3536                 :            :             }
    3537                 :            :         }
    3538         [ +  + ]:          6 :         if( !chain )
    3539                 :            :         {
    3540                 :          6 :             break;  // break out of while loop
    3541                 :            :         }
    3542                 :            :     }
    3543         [ +  + ]:         24 :     return MB_SUCCESS;
           [ #  #  #  # ]
    3544                 :            : }
    3545                 :            : 
    3546                 :            : // determine if from the end of edge we can extend with another edge; return also the
    3547                 :            : //  extension edge (next_edge)
    3548                 :         33 : ErrorCode FBEngine::chain_able_edge( EntityHandle edge, double min_dot, EntityHandle& next_edge, bool& chainable )
    3549                 :            : {
    3550                 :            :     // get the end, then get all parents of end
    3551                 :            :     // see if some are the starts of
    3552                 :         33 :     chainable = false;
    3553                 :            :     EntityHandle v1, v2;
    3554         [ +  - ]:         33 :     ErrorCode rval = get_vert_edges( edge, v1, v2 );
    3555 [ -  + ][ #  # ]:         33 :     MBERRORR( rval, "can't get vertices" );
                 [ #  # ]
    3556         [ +  + ]:         33 :     if( v1 == v2 ) return MB_SUCCESS;  // it is periodic, can't chain it with another edge!
    3557                 :            : 
    3558                 :            :     // v2 is a set, get its parents, which should be edges
    3559         [ +  - ]:         27 :     Range edges;
    3560         [ +  - ]:         27 :     rval = _mbImpl->get_parent_meshsets( v2, edges );
    3561 [ -  + ][ #  # ]:         27 :     MBERRORR( rval, "can't get parents of vertex set" );
                 [ #  # ]
    3562                 :            :     // get parents of current edge (faces)
    3563         [ +  - ]:         54 :     Range faces;
    3564         [ +  - ]:         27 :     rval = _mbImpl->get_parent_meshsets( edge, faces );
    3565 [ -  + ][ #  # ]:         27 :     MBERRORR( rval, "can't get parents of edge set" );
                 [ #  # ]
    3566                 :            :     // get also the last edge "tangent" at the vertex
    3567         [ +  - ]:         54 :     std::vector< EntityHandle > mesh_edges;
    3568         [ +  - ]:         27 :     rval = _mbImpl->get_entities_by_type( edge, MBEDGE, mesh_edges );
    3569 [ -  + ][ #  # ]:         27 :     MBERRORR( rval, "can't get mesh edges from edge set" );
                 [ #  # ]
    3570         [ +  - ]:         27 :     EntityHandle lastMeshEdge = mesh_edges[mesh_edges.size() - 1];
    3571                 :         27 :     const EntityHandle* conn2 = NULL;
    3572                 :         27 :     int len                   = 0;
    3573         [ +  - ]:         27 :     rval                      = _mbImpl->get_connectivity( lastMeshEdge, conn2, len );
    3574 [ -  + ][ #  # ]:         27 :     MBERRORR( rval, "can't connectivity of last mesh edge" );
                 [ #  # ]
    3575                 :            :     // get the coordinates of last edge
    3576 [ -  + ][ #  # ]:         27 :     if( len != 2 ) MBERRORR( MB_FAILURE, "bad number of vertices" );
                 [ #  # ]
    3577 [ +  - ][ +  + ]:         81 :     CartVect P[2];
    3578         [ +  - ]:         27 :     rval = _mbImpl->get_coords( conn2, len, (double*)&P[0] );
    3579 [ -  + ][ #  # ]:         27 :     MBERRORR( rval, "Failed to get coordinates" );
                 [ #  # ]
    3580                 :            : 
    3581         [ +  - ]:         27 :     CartVect vec1( P[1] - P[0] );
    3582         [ +  - ]:         27 :     vec1.normalize();
    3583 [ +  - ][ +  - ]:         85 :     for( Range::iterator edgeIter = edges.begin(); edgeIter != edges.end(); ++edgeIter )
         [ +  - ][ +  - ]
                 [ +  + ]
    3584                 :            :     {
    3585         [ +  - ]:         58 :         EntityHandle otherEdge = *edgeIter;
    3586         [ +  + ]:         58 :         if( edge == otherEdge ) continue;
    3587                 :            :         // get faces parents of this edge
    3588         [ +  - ]:         31 :         Range faces2;
    3589         [ +  - ]:         31 :         rval = _mbImpl->get_parent_meshsets( otherEdge, faces2 );
    3590 [ -  + ][ #  # ]:         31 :         MBERRORR( rval, "can't get parents of other edge set" );
                 [ #  # ]
    3591 [ +  - ][ +  + ]:         31 :         if( faces != faces2 ) continue;
    3592                 :            :         // now, if the first mesh edge is within given angle, we can go on
    3593         [ +  - ]:         23 :         std::vector< EntityHandle > mesh_edges2;
    3594         [ +  - ]:         23 :         rval = _mbImpl->get_entities_by_type( otherEdge, MBEDGE, mesh_edges2 );
    3595 [ -  + ][ #  # ]:         23 :         MBERRORR( rval, "can't get mesh edges from other edge set" );
                 [ #  # ]
    3596         [ +  - ]:         23 :         EntityHandle firstMeshEdge = mesh_edges2[0];
    3597                 :            :         const EntityHandle* conn22;
    3598                 :            :         int len2;
    3599         [ +  - ]:         23 :         rval = _mbImpl->get_connectivity( firstMeshEdge, conn22, len2 );
    3600 [ -  + ][ #  # ]:         23 :         MBERRORR( rval, "can't connectivity of first mesh edge" );
                 [ #  # ]
    3601 [ -  + ][ #  # ]:         23 :         if( len2 != 2 ) MBERRORR( MB_FAILURE, "bad number of vertices" );
                 [ #  # ]
    3602         [ -  + ]:         23 :         if( conn2[1] != conn22[0] ) continue;  // the mesh edges are not one after the other
    3603                 :            :         // get the coordinates of first edge
    3604                 :            : 
    3605                 :            :         // CartVect P2[2];
    3606         [ +  - ]:         23 :         rval = _mbImpl->get_coords( conn22, len, (double*)&P[0] );
    3607         [ +  - ]:         23 :         CartVect vec2( P[1] - P[0] );
    3608         [ +  - ]:         23 :         vec2.normalize();
    3609 [ +  - ][ +  + ]:         23 :         if( vec1 % vec2 < min_dot ) continue;
    3610                 :            :         // we found our edge, victory! we can get out
    3611                 :          2 :         next_edge = otherEdge;
    3612                 :          2 :         chainable = true;
    3613 [ +  + ][ +  + ]:         31 :         return MB_SUCCESS;
    3614                 :          0 :     }
    3615                 :            : 
    3616                 :         58 :     return MB_SUCCESS;  // in general, hard to come by chain-able edges
    3617                 :            : }
    3618                 :          2 : ErrorCode FBEngine::chain_two_edges( EntityHandle edge, EntityHandle next_edge )
    3619                 :            : {
    3620                 :            :     // the biggest thing is to see the sense tags; or maybe not...
    3621                 :            :     // they should be correct :)
    3622                 :            :     // get the vertex sets
    3623                 :            :     EntityHandle v11, v12, v21, v22;
    3624         [ +  - ]:          2 :     ErrorCode rval = get_vert_edges( edge, v11, v12 );
    3625 [ -  + ][ #  # ]:          2 :     MBERRORR( rval, "can't get vert sets" );
                 [ #  # ]
    3626         [ +  - ]:          2 :     rval = get_vert_edges( next_edge, v21, v22 );
    3627 [ -  + ][ #  # ]:          2 :     MBERRORR( rval, "can't get vert sets" );
                 [ #  # ]
    3628         [ -  + ]:          2 :     assert( v12 == v21 );
    3629         [ +  - ]:          2 :     std::vector< EntityHandle > mesh_edges;
    3630         [ +  - ]:          2 :     rval = MBI->get_entities_by_type( next_edge, MBEDGE, mesh_edges );
    3631 [ -  + ][ #  # ]:          2 :     MBERRORR( rval, "can't get mesh edges" );
                 [ #  # ]
    3632                 :            : 
    3633 [ +  - ][ +  - ]:          2 :     rval = _mbImpl->add_entities( edge, &mesh_edges[0], (int)mesh_edges.size() );
    3634 [ -  + ][ #  # ]:          2 :     MBERRORR( rval, "can't add new mesh edges" );
                 [ #  # ]
    3635                 :            :     // remove the child - parent relation for second vertex of first edge
    3636         [ +  - ]:          2 :     rval = _mbImpl->remove_parent_child( edge, v12 );
    3637 [ -  + ][ #  # ]:          2 :     MBERRORR( rval, "can't remove parent - child relation between first edge and middle vertex" );
                 [ #  # ]
    3638                 :            : 
    3639         [ +  - ]:          2 :     if( v22 != v11 )  // the edge would become periodic, do not add again the relationship
    3640                 :            :     {
    3641         [ +  - ]:          2 :         rval = _mbImpl->add_parent_child( edge, v22 );
    3642 [ -  + ][ #  # ]:          2 :         MBERRORR( rval, "can't add second vertex to edge " );
                 [ #  # ]
    3643                 :            :     }
    3644                 :            :     // we can now safely eliminate next_edge
    3645         [ +  - ]:          2 :     rval = _mbImpl->remove_parent_child( next_edge, v21 );
    3646 [ -  + ][ #  # ]:          2 :     MBERRORR( rval, "can't remove child - parent relation " );
                 [ #  # ]
    3647                 :            : 
    3648         [ +  - ]:          2 :     rval = _mbImpl->remove_parent_child( next_edge, v22 );
    3649 [ -  + ][ #  # ]:          2 :     MBERRORR( rval, "can't remove child - parent relation " );
                 [ #  # ]
    3650                 :            : 
    3651                 :            :     // remove the next_edge relation to the faces
    3652         [ +  - ]:          4 :     Range faces;
    3653         [ +  - ]:          2 :     rval = _mbImpl->get_parent_meshsets( next_edge, faces );
    3654 [ -  + ][ #  # ]:          2 :     MBERRORR( rval, "can't get parent faces " );
                 [ #  # ]
    3655                 :            : 
    3656 [ +  - ][ +  - ]:          6 :     for( Range::iterator it = faces.begin(); it != faces.end(); ++it )
         [ +  - ][ +  - ]
                 [ +  + ]
    3657                 :            :     {
    3658         [ +  - ]:          4 :         EntityHandle ff = *it;
    3659         [ +  - ]:          4 :         rval            = _mbImpl->remove_parent_child( ff, next_edge );
    3660 [ -  + ][ #  # ]:          4 :         MBERRORR( rval, "can't remove parent-edge rel " );
                 [ #  # ]
    3661                 :            :     }
    3662                 :            : 
    3663         [ +  - ]:          2 :     rval = _mbImpl->delete_entities( &next_edge, 1 );
    3664 [ -  + ][ #  # ]:          2 :     MBERRORR( rval, "can't remove edge set " );
                 [ #  # ]
    3665                 :            : 
    3666                 :            :     // delete the vertex set that is idle now (v12 = v21)
    3667         [ +  - ]:          2 :     rval = _mbImpl->delete_entities( &v12, 1 );
    3668 [ -  + ][ #  # ]:          2 :     MBERRORR( rval, "can't remove edge set " );
                 [ #  # ]
    3669                 :          4 :     return MB_SUCCESS;
    3670                 :            : }
    3671                 :         37 : ErrorCode FBEngine::get_vert_edges( EntityHandle edge, EntityHandle& v1, EntityHandle& v2 )
    3672                 :            : {
    3673                 :            :     // need to decide first or second vertex
    3674                 :            :     // important for moab
    3675                 :            : 
    3676         [ +  - ]:         37 :     Range children;
    3677                 :            :     // EntityHandle v1, v2;
    3678         [ +  - ]:         37 :     ErrorCode rval = _mbImpl->get_child_meshsets( edge, children );
    3679 [ -  + ][ #  # ]:         37 :     MBERRORR( rval, "can't get child meshsets" );
                 [ #  # ]
    3680 [ +  - ][ +  + ]:         37 :     if( children.size() == 1 )
    3681                 :            :     {
    3682                 :            :         // this is periodic edge, get out early
    3683         [ +  - ]:          6 :         v1 = children[0];
    3684                 :          6 :         v2 = v1;
    3685                 :          6 :         return MB_SUCCESS;
    3686                 :            :     }
    3687 [ +  - ][ -  + ]:         31 :     else if( children.size() > 2 )
    3688 [ #  # ][ #  # ]:          0 :         MBERRORR( MB_FAILURE, "too many vertices in one edge" );
    3689                 :            :     // edge: get one vertex as part of the vertex set
    3690         [ +  - ]:         62 :     Range entities;
    3691 [ +  - ][ +  - ]:         31 :     rval = MBI->get_entities_by_type( children[0], MBVERTEX, entities );
    3692 [ -  + ][ #  # ]:         31 :     MBERRORR( rval, "can't get entities from vertex set" );
                 [ #  # ]
    3693 [ +  - ][ -  + ]:         31 :     if( entities.size() < 1 ) MBERRORR( MB_FAILURE, "no mesh nodes in vertex set" );
         [ #  # ][ #  # ]
    3694         [ +  - ]:         31 :     EntityHandle node0 = entities[0];  // the first vertex
    3695         [ +  - ]:         31 :     entities.clear();
    3696                 :            : 
    3697                 :            :     // now get the edges, and get the first node and the last node in sequence of edges
    3698                 :            :     // the order is important...
    3699                 :            :     // these are ordered sets !!
    3700         [ +  - ]:         62 :     std::vector< EntityHandle > ents;
    3701         [ +  - ]:         31 :     rval = MBI->get_entities_by_type( edge, MBEDGE, ents );
    3702 [ -  + ][ #  # ]:         31 :     MBERRORR( rval, "can't get mesh edges" );
                 [ #  # ]
    3703 [ -  + ][ #  # ]:         31 :     if( ents.size() < 1 ) MBERRORR( MB_FAILURE, "no mesh edges in edge set" );
                 [ #  # ]
    3704                 :            : 
    3705                 :         31 :     const EntityHandle* conn = NULL;
    3706                 :            :     int len;
    3707 [ +  - ][ +  - ]:         31 :     rval = MBI->get_connectivity( ents[0], conn, len );
    3708 [ -  + ][ #  # ]:         31 :     MBERRORR( rval, "can't connectivity of first mesh edge" );
                 [ #  # ]
    3709                 :            : 
    3710         [ +  + ]:         31 :     if( conn[0] == node0 )
    3711                 :            :     {
    3712         [ +  - ]:         21 :         v1 = children[0];
    3713         [ +  - ]:         21 :         v2 = children[1];
    3714                 :            :     }
    3715                 :            :     else  // the other way around, although we should check (we are paranoid)
    3716                 :            :     {
    3717         [ +  - ]:         10 :         v2 = children[0];
    3718         [ +  - ]:         10 :         v1 = children[1];
    3719                 :            :     }
    3720                 :            : 
    3721                 :         68 :     return MB_SUCCESS;
    3722                 :            : }
    3723 [ +  - ][ +  - ]:         44 : }  // namespace moab

Generated by: LCOV version 1.11