LCOV - code coverage report
Current view: top level - src - MeshTopoUtil.cpp (source / functions) Hit Total Coverage
Test: coverage_sk.info Lines: 184 362 50.8 %
Date: 2020-12-16 07:07:30 Functions: 11 18 61.1 %
Branches: 258 1001 25.8 %

           Branch data     Line data    Source code
       1                 :            : /**
       2                 :            :  * MOAB, a Mesh-Oriented datABase, is a software component for creating,
       3                 :            :  * storing and accessing finite element mesh data.
       4                 :            :  *
       5                 :            :  * Copyright 2004 Sandia Corporation.  Under the terms of Contract
       6                 :            :  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
       7                 :            :  * retains certain rights in this software.
       8                 :            :  *
       9                 :            :  * This library is free software; you can redistribute it and/or
      10                 :            :  * modify it under the terms of the GNU Lesser General Public
      11                 :            :  * License as published by the Free Software Foundation; either
      12                 :            :  * version 2.1 of the License, or (at your option) any later version.
      13                 :            :  *
      14                 :            :  */
      15                 :            : 
      16                 :            : #ifdef WIN32
      17                 :            : #pragma warning( disable : 4786 )
      18                 :            : #endif
      19                 :            : 
      20                 :            : #include "moab/MeshTopoUtil.hpp"
      21                 :            : #include "moab/Range.hpp"
      22                 :            : #include "Internals.hpp"
      23                 :            : #include "moab/Interface.hpp"
      24                 :            : #include "moab/CN.hpp"
      25                 :            : 
      26                 :            : #include <assert.h>
      27                 :            : 
      28                 :            : #define RR                                        \
      29                 :            :     {                                             \
      30                 :            :         if( MB_SUCCESS != result ) return result; \
      31                 :            :     }
      32                 :            : 
      33                 :            : namespace moab
      34                 :            : {
      35                 :            : 
      36                 :            : //! generate all the AEntities bounding the vertices
      37                 :          2 : ErrorCode MeshTopoUtil::construct_aentities( const Range& vertices )
      38                 :            : {
      39         [ +  - ]:          2 :     Range out_range;
      40                 :            :     ErrorCode result;
      41         [ +  - ]:          2 :     result = mbImpl->get_adjacencies( vertices, 1, true, out_range, Interface::UNION );
      42         [ -  + ]:          2 :     if( MB_SUCCESS != result ) return result;
      43         [ +  - ]:          2 :     out_range.clear();
      44         [ +  - ]:          2 :     result = mbImpl->get_adjacencies( vertices, 2, true, out_range, Interface::UNION );
      45         [ -  + ]:          2 :     if( MB_SUCCESS != result ) return result;
      46         [ +  - ]:          2 :     out_range.clear();
      47         [ +  - ]:          2 :     result = mbImpl->get_adjacencies( vertices, 3, true, out_range, Interface::UNION );
      48                 :            : 
      49                 :          2 :     return result;
      50                 :            : }
      51                 :            : 
      52                 :            : //! given an entity, get its average position (avg vertex locations)
      53                 :          0 : ErrorCode MeshTopoUtil::get_average_position( Range& entities, double* avg_position )
      54                 :            : {
      55         [ #  # ]:          0 :     std::vector< EntityHandle > ent_vec;
      56 [ #  # ][ #  # ]:          0 :     std::copy( entities.begin(), entities.end(), std::back_inserter( ent_vec ) );
         [ #  # ][ #  # ]
      57 [ #  # ][ #  # ]:          0 :     return get_average_position( &ent_vec[0], ent_vec.size(), avg_position );
      58                 :            : }
      59                 :            : 
      60                 :            : //! given an entity, get its average position (avg vertex locations)
      61                 :          4 : ErrorCode MeshTopoUtil::get_average_position( const EntityHandle* entities, const int num_entities,
      62                 :            :                                               double* avg_position )
      63                 :            : {
      64                 :            :     double dum_pos[3];
      65                 :          4 :     avg_position[0] = avg_position[1] = avg_position[2] = 0.0;
      66                 :            : 
      67         [ +  - ]:          4 :     Range connect;
      68         [ +  - ]:          4 :     ErrorCode result = mbImpl->get_adjacencies( entities, num_entities, 0, false, connect, Interface::UNION );
      69         [ -  + ]:          4 :     if( MB_SUCCESS != result ) return result;
      70                 :            : 
      71 [ +  - ][ -  + ]:          4 :     if( connect.empty() ) return MB_FAILURE;
      72                 :            : 
      73 [ +  - ][ +  - ]:         36 :     for( Range::iterator rit = connect.begin(); rit != connect.end(); ++rit )
         [ +  - ][ +  - ]
                 [ +  + ]
      74                 :            :     {
      75 [ +  - ][ +  - ]:         32 :         result = mbImpl->get_coords( &( *rit ), 1, dum_pos );
      76         [ -  + ]:         32 :         if( MB_SUCCESS != result ) return result;
      77                 :         32 :         avg_position[0] += dum_pos[0];
      78                 :         32 :         avg_position[1] += dum_pos[1];
      79                 :         32 :         avg_position[2] += dum_pos[2];
      80                 :            :     }
      81         [ +  - ]:          4 :     avg_position[0] /= (double)connect.size();
      82         [ +  - ]:          4 :     avg_position[1] /= (double)connect.size();
      83         [ +  - ]:          4 :     avg_position[2] /= (double)connect.size();
      84                 :            : 
      85                 :          4 :     return MB_SUCCESS;
      86                 :            : }
      87                 :            : 
      88                 :            : //! given an entity, get its average position (avg vertex locations)
      89                 :          4 : ErrorCode MeshTopoUtil::get_average_position( const EntityHandle entity, double* avg_position )
      90                 :            : {
      91                 :          4 :     const EntityHandle* connect = NULL;
      92                 :          4 :     int num_connect             = 0;
      93 [ +  - ][ -  + ]:          4 :     if( MBVERTEX == mbImpl->type_from_handle( entity ) ) return mbImpl->get_coords( &entity, 1, avg_position );
                 [ #  # ]
      94                 :            : 
      95         [ +  - ]:          4 :     ErrorCode result = mbImpl->get_connectivity( entity, connect, num_connect );
      96         [ -  + ]:          4 :     if( MB_SUCCESS != result ) return result;
      97                 :            : 
      98         [ +  - ]:          4 :     return get_average_position( connect, num_connect, avg_position );
      99                 :            : }
     100                 :            : 
     101                 :            : // given an entity, find the entities of next higher dimension around
     102                 :            : // that entity, ordered by connection through next higher dimension entities;
     103                 :            : // if any of the star entities is in only one entity of next higher dimension,
     104                 :            : // on_boundary is returned true
     105                 :          2 : ErrorCode MeshTopoUtil::star_entities( const EntityHandle star_center, std::vector< EntityHandle >& star_ents,
     106                 :            :                                        bool& bdy_entity, const EntityHandle starting_star_entity,
     107                 :            :                                        std::vector< EntityHandle >* star_entities_dp2, Range* star_candidates_dp2 )
     108                 :            : {
     109                 :            :     // now start the traversal
     110                 :          2 :     bdy_entity               = false;
     111                 :          2 :     EntityHandle last_entity = starting_star_entity, last_dp2 = 0, next_entity, next_dp2;
     112         [ +  - ]:          2 :     std::vector< EntityHandle > star_dp2;
     113                 :            :     ErrorCode result;
     114         [ +  - ]:          2 :     int center_dim = mbImpl->dimension_from_handle( star_center );
     115                 :            : 
     116         [ +  - ]:          4 :     Range tmp_candidates_dp2;
     117         [ -  + ]:          2 :     if( NULL != star_candidates_dp2 )
     118         [ #  # ]:          0 :         tmp_candidates_dp2 = *star_candidates_dp2;
     119                 :            :     else
     120                 :            :     {
     121         [ +  - ]:          2 :         result = mbImpl->get_adjacencies( &star_center, 1, center_dim + 2, false, tmp_candidates_dp2 );
     122         [ -  + ]:          2 :         if( MB_SUCCESS != result ) return result;
     123                 :            :     }
     124                 :            : 
     125         [ +  + ]:          8 :     do
     126                 :            :     {
     127                 :            :         // get the next star entity
     128         [ +  - ]:          8 :         result = star_next_entity( star_center, last_entity, last_dp2, &tmp_candidates_dp2, next_entity, next_dp2 );
     129         [ -  + ]:          8 :         if( MB_SUCCESS != result ) return result;
     130                 :            : 
     131                 :            :         // special case: if starting_star_entity isn't connected to any entities of next
     132                 :            :         // higher dimension, it's the only entity in the star; put it on the list and return
     133 [ +  + ][ -  + ]:          8 :         if( star_ents.empty() && next_entity == 0 && next_dp2 == 0 )
         [ #  # ][ -  + ]
     134                 :            :         {
     135         [ #  # ]:          0 :             star_ents.push_back( last_entity );
     136                 :          0 :             bdy_entity = true;
     137                 :          0 :             return MB_SUCCESS;
     138                 :            :         }
     139                 :            : 
     140                 :            :         // if we're at a bdy and bdy_entity hasn't been set yet, we're at the
     141                 :            :         // first bdy; reverse the lists and start traversing in the other direction; but,
     142                 :            :         // pop the last star entity off the list and find it again, so that we properly
     143                 :            :         // check for next_dp2
     144 [ +  + ][ +  + ]:          8 :         if( 0 == next_dp2 && !bdy_entity )
     145                 :            :         {
     146         [ +  - ]:          1 :             star_ents.push_back( next_entity );
     147                 :          1 :             bdy_entity = true;
     148         [ +  - ]:          1 :             std::reverse( star_ents.begin(), star_ents.end() );
     149         [ +  - ]:          1 :             star_ents.pop_back();
     150         [ +  - ]:          1 :             last_entity = star_ents.back();
     151         [ +  - ]:          2 :             if( !star_dp2.empty() )
     152                 :            :             {
     153         [ +  - ]:          1 :                 std::reverse( star_dp2.begin(), star_dp2.end() );
     154         [ +  - ]:          1 :                 last_dp2 = star_dp2.back();
     155                 :            :             }
     156                 :            :         }
     157                 :            :         // else if we're not on the bdy and next_entity is already in star, that means
     158                 :            :         // we've come all the way around; don't put next_entity on list again, and
     159                 :            :         // zero out last_dp2 to terminate while loop
     160 [ +  + ][ +  - ]:         15 :         else if( !bdy_entity && std::find( star_ents.begin(), star_ents.end(), next_entity ) != star_ents.end() &&
         [ +  - ][ +  + ]
         [ -  + ][ +  + ]
         [ +  + ][ +  +  
             #  #  #  # ]
     161 [ +  - ][ +  - ]:          8 :                  ( std::find( star_dp2.begin(), star_dp2.end(), next_dp2 ) != star_dp2.end() || !next_dp2 ) )
         [ #  # ][ +  + ]
                 [ +  + ]
           [ #  #  #  # ]
     162                 :            :         {
     163                 :          1 :             last_dp2 = 0;
     164                 :            :         }
     165                 :            : 
     166                 :            :         // else, just assign last entities seen and go on to next iteration
     167                 :            :         else
     168                 :            :         {
     169 [ +  - ][ +  - ]:          6 :             if( std::find( star_ents.begin(), star_ents.end(), next_entity ) == star_ents.end() )
                 [ +  - ]
     170         [ +  - ]:          6 :                 star_ents.push_back( next_entity );
     171         [ +  + ]:          6 :             if( 0 != next_dp2 )
     172                 :            :             {
     173         [ +  - ]:          5 :                 star_dp2.push_back( next_dp2 );
     174         [ +  - ]:          5 :                 tmp_candidates_dp2.erase( next_dp2 );
     175                 :            :             }
     176                 :          6 :             last_entity = next_entity;
     177                 :          6 :             last_dp2    = next_dp2;
     178                 :            :         }
     179                 :            :     } while( 0 != last_dp2 );
     180                 :            : 
     181                 :            :     // copy over the star_dp2 list, if requested
     182         [ +  - ]:          2 :     if( NULL != star_entities_dp2 ) ( *star_entities_dp2 ).swap( star_dp2 );
     183                 :            : 
     184                 :          4 :     return MB_SUCCESS;
     185                 :            : }
     186                 :            : 
     187                 :          8 : ErrorCode MeshTopoUtil::star_next_entity( const EntityHandle star_center, const EntityHandle last_entity,
     188                 :            :                                           const EntityHandle last_dp1, Range* star_candidates_dp1,
     189                 :            :                                           EntityHandle& next_entity, EntityHandle& next_dp1 )
     190                 :            : {
     191                 :            :     // given a star_center, a last_entity (whose dimension should be 1 greater than center)
     192                 :            :     // and last_dp1 (dimension 2 higher than center), returns the next star entity across
     193                 :            :     // last_dp1, and the next dp1 entity sharing next_entity; if star_candidates is non-empty,
     194                 :            :     // star must come from those
     195 [ +  - ][ +  - ]:         16 :     Range from_ents, to_ents;
     196         [ +  - ]:          8 :     from_ents.insert( star_center );
     197 [ +  + ][ +  - ]:          8 :     if( 0 != last_dp1 ) from_ents.insert( last_dp1 );
     198                 :            : 
     199         [ +  - ]:          8 :     int dim = mbImpl->dimension_from_handle( star_center );
     200                 :            : 
     201         [ +  - ]:          8 :     ErrorCode result = mbImpl->get_adjacencies( from_ents, dim + 1, true, to_ents );
     202         [ -  + ]:          8 :     if( MB_SUCCESS != result ) return result;
     203                 :            : 
     204                 :            :     // remove last_entity from result, and should only have 1 left, if any
     205 [ +  + ][ +  - ]:          8 :     if( 0 != last_entity ) to_ents.erase( last_entity );
     206                 :            : 
     207                 :            :     // if no last_dp1, contents of to_ents should share dp1-dimensional entity with last_entity
     208 [ +  + ][ -  + ]:          8 :     if( 0 != last_entity && 0 == last_dp1 )
     209                 :            :     {
     210         [ #  # ]:          0 :         Range tmp_to_ents;
     211 [ #  # ][ #  # ]:          0 :         for( Range::iterator rit = to_ents.begin(); rit != to_ents.end(); ++rit )
         [ #  # ][ #  # ]
                 [ #  # ]
     212                 :            :         {
     213 [ #  # ][ #  # ]:          0 :             if( 0 != common_entity( last_entity, *rit, dim + 2 ) ) tmp_to_ents.insert( *rit );
         [ #  # ][ #  # ]
                 [ #  # ]
     214                 :            :         }
     215         [ #  # ]:          0 :         to_ents = tmp_to_ents;
     216                 :            :     }
     217                 :            : 
     218 [ +  + ][ +  - ]:          8 :     if( 0 == last_dp1 && to_ents.size() > 1 && NULL != star_candidates_dp1 && !star_candidates_dp1->empty() )
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  + ]
     219                 :            :     {
     220                 :            :         // if we have a choice of to_ents and no previous dp1 and there are dp1 candidates,
     221                 :            :         // the one we choose needs to be adjacent to one of the candidates
     222         [ +  - ]:          2 :         result = mbImpl->get_adjacencies( *star_candidates_dp1, dim + 1, true, from_ents, Interface::UNION );
     223         [ -  + ]:          2 :         if( MB_SUCCESS != result ) return result;
     224 [ +  - ][ +  - ]:          2 :         to_ents = intersect( to_ents, from_ents );
     225                 :            :     }
     226                 :            : 
     227 [ +  - ][ +  - ]:          8 :     if( !to_ents.empty() )
     228 [ +  - ][ +  - ]:          8 :         next_entity = *to_ents.begin();
     229                 :            :     else
     230                 :            :     {
     231                 :          0 :         next_entity = 0;
     232                 :          0 :         next_dp1    = 0;
     233                 :          0 :         return MB_SUCCESS;
     234                 :            :     }
     235                 :            : 
     236                 :            :     // get next_dp1
     237         [ +  - ]:          8 :     if( 0 != star_candidates_dp1 )
     238         [ +  - ]:          8 :         to_ents = *star_candidates_dp1;
     239                 :            :     else
     240         [ #  # ]:          0 :         to_ents.clear();
     241                 :            : 
     242         [ +  - ]:          8 :     result = mbImpl->get_adjacencies( &next_entity, 1, dim + 2, true, to_ents );
     243         [ -  + ]:          8 :     if( MB_SUCCESS != result ) return result;
     244                 :            : 
     245                 :            :     // can't be last one
     246 [ +  + ][ +  - ]:          8 :     if( 0 != last_dp1 ) to_ents.erase( last_dp1 );
     247                 :            : 
     248 [ +  - ][ +  + ]:          8 :     if( !to_ents.empty() ) next_dp1 = *to_ents.begin();
         [ +  - ][ +  - ]
     249                 :            : 
     250                 :            :     // could be zero, means we're at bdy
     251                 :            :     else
     252                 :          2 :         next_dp1 = 0;
     253                 :            : 
     254                 :         16 :     return MB_SUCCESS;
     255                 :            : }
     256                 :            : 
     257                 :          0 : ErrorCode MeshTopoUtil::star_entities_nonmanifold( const EntityHandle star_entity,
     258                 :            :                                                    std::vector< std::vector< EntityHandle > >& stars,
     259                 :            :                                                    std::vector< bool >* bdy_flags,
     260                 :            :                                                    std::vector< std::vector< EntityHandle > >* dp2_stars )
     261                 :            : {
     262                 :            :     // Get a series of (d+1)-dimensional stars around a d-dimensional entity, such that
     263                 :            :     // each star is on a (d+2)-manifold containing the d-dimensional entity; each star
     264                 :            :     // is either open or closed, and also defines a (d+2)-star whose entities are bounded by
     265                 :            :     // (d+1)-entities on the star and on the (d+2)-manifold
     266                 :            :     //
     267                 :            :     // Algorithm:
     268                 :            :     // get the (d+2)-manifold entities; for d=1 / d+2=3, just assume all connected elements, since
     269                 :            :     //   we don't do 4d yet
     270                 :            :     // get intersection of (d+1)-entities adjacent to star entity and union of (d+1)-entities
     271                 :            :     //   adjacent to (d+2)-manifold entities; these will be the entities in the star
     272                 :            :     // while (d+1)-entities
     273                 :            :     //   remove (d+1)-entity from (d+1)-entities
     274                 :            :     //   get the (d+1)-star and (d+2)-star around that (d+1)-entity (using star_entities)
     275                 :            :     //   save that star to the star list, and the bdy flag and (d+2)-star if requested
     276                 :            :     //   remove (d+2)-entities from the (d+2)-manifold entities
     277                 :            :     //   remove (d+1)-entities from the (d+1)-entities
     278                 :            :     // (end while)
     279                 :            : 
     280         [ #  # ]:          0 :     int this_dim = mbImpl->dimension_from_handle( star_entity );
     281 [ #  # ][ #  # ]:          0 :     if( 3 <= this_dim || 0 > this_dim ) return MB_FAILURE;
     282                 :            : 
     283                 :            :     // get the (d+2)-manifold entities; for d=1 / d+2=3, just assume all connected elements, since
     284                 :            :     //   we don't do 4d yet
     285         [ #  # ]:          0 :     Range dp2_manifold;
     286         [ #  # ]:          0 :     ErrorCode result = get_manifold( star_entity, this_dim + 2, dp2_manifold );
     287         [ #  # ]:          0 :     if( MB_SUCCESS != result ) return result;
     288                 :            : 
     289                 :            :     // get intersection of (d+1)-entities adjacent to star and union of (d+1)-entities
     290                 :            :     //   adjacent to (d+2)-manifold entities; also add manifold (d+1)-entities, to catch
     291                 :            :     //   any not connected to (d+2)-entities
     292         [ #  # ]:          0 :     Range dp1_manifold;
     293         [ #  # ]:          0 :     result = mbImpl->get_adjacencies( dp2_manifold, this_dim + 1, false, dp1_manifold, Interface::UNION );
     294         [ #  # ]:          0 :     if( MB_SUCCESS != result ) return result;
     295                 :            : 
     296         [ #  # ]:          0 :     result = mbImpl->get_adjacencies( &star_entity, 1, this_dim + 1, false, dp1_manifold );
     297         [ #  # ]:          0 :     if( MB_SUCCESS != result ) return result;
     298                 :            : 
     299         [ #  # ]:          0 :     result = get_manifold( star_entity, this_dim + 1, dp1_manifold );
     300         [ #  # ]:          0 :     if( MB_SUCCESS != result ) return result;
     301                 :            : 
     302                 :            :     // while (d+1)-entities
     303 [ #  # ][ #  # ]:          0 :     while( !dp1_manifold.empty() )
     304                 :            :     {
     305                 :            : 
     306                 :            :         //   get (d+1)-entity from (d+1)-entities (don't remove it until after star,
     307                 :            :         //     since the star entities must come from dp1_manifold)
     308 [ #  # ][ #  # ]:          0 :         EntityHandle this_ent = *dp1_manifold.begin();
     309                 :            : 
     310                 :            :         //   get the (d+1)-star and (d+2)-star around that (d+1)-entity (using star_entities)
     311 [ #  # ][ #  # ]:          0 :         std::vector< EntityHandle > this_star_dp1, this_star_dp2;
                 [ #  # ]
     312                 :            :         bool on_bdy;
     313         [ #  # ]:          0 :         result = star_entities( star_entity, this_star_dp1, on_bdy, this_ent, &this_star_dp2, &dp2_manifold );
     314         [ #  # ]:          0 :         if( MB_SUCCESS != result ) return result;
     315                 :            : 
     316                 :            :         // if there's no star entities, it must mean this_ent isn't bounded by any dp2
     317                 :            :         // entities (wasn't put into star in star_entities 'cuz we're passing in non-null
     318                 :            :         // dp2_manifold above); put it in
     319         [ #  # ]:          0 :         if( this_star_dp1.empty() )
     320                 :            :         {
     321         [ #  # ]:          0 :             Range dum_range;
     322         [ #  # ]:          0 :             result = mbImpl->get_adjacencies( &this_ent, 1, this_dim + 2, false, dum_range );
     323         [ #  # ]:          0 :             if( MB_SUCCESS != result ) return result;
     324 [ #  # ][ #  # ]:          0 :             if( dum_range.empty() ) this_star_dp1.push_back( this_ent );
         [ #  # ][ #  # ]
     325                 :            :         }
     326                 :            : 
     327                 :            :         // now we can remove it
     328 [ #  # ][ #  # ]:          0 :         dp1_manifold.erase( dp1_manifold.begin() );
     329                 :            : 
     330                 :            :         //   save that star to the star list, and the bdy flag and (d+2)-star if requested
     331         [ #  # ]:          0 :         if( !this_star_dp1.empty() )
     332                 :            :         {
     333         [ #  # ]:          0 :             stars.push_back( this_star_dp1 );
     334 [ #  # ][ #  # ]:          0 :             if( NULL != bdy_flags ) bdy_flags->push_back( on_bdy );
     335 [ #  # ][ #  # ]:          0 :             if( NULL != dp2_stars ) dp2_stars->push_back( this_star_dp2 );
     336                 :            :         }
     337                 :            : 
     338                 :            :         //   remove (d+2)-entities from the (d+2)-manifold entities
     339 [ #  # ][ #  # ]:          0 :         for( std::vector< EntityHandle >::iterator vit = this_star_dp2.begin(); vit != this_star_dp2.end(); ++vit )
                 [ #  # ]
     340 [ #  # ][ #  # ]:          0 :             dp2_manifold.erase( *vit );
     341                 :            : 
     342                 :            :         //   remove (d+1)-entities from the (d+1)-entities
     343 [ #  # ][ #  # ]:          0 :         for( std::vector< EntityHandle >::iterator vit = this_star_dp1.begin(); vit != this_star_dp1.end(); ++vit )
         [ #  # ][ #  # ]
     344 [ #  # ][ #  # ]:          0 :             dp1_manifold.erase( *vit );
     345                 :            : 
     346                 :            :         // (end while)
     347                 :          0 :     }
     348                 :            : 
     349                 :            :     // check for leftover dp2 manifold entities, these should be in one of the
     350                 :            :     // stars
     351 [ #  # ][ #  # ]:          0 :     if( !dp2_manifold.empty() )
     352                 :            :     {
     353 [ #  # ][ #  # ]:          0 :         for( Range::iterator rit = dp2_manifold.begin(); rit != dp2_manifold.end(); ++rit ) {}
         [ #  # ][ #  # ]
                 [ #  # ]
     354                 :            :     }
     355                 :            : 
     356                 :          0 :     return MB_SUCCESS;
     357                 :            : }
     358                 :            : 
     359                 :            : //! get (target_dim)-dimensional manifold entities connected to star_entity; that is,
     360                 :            : //! the entities with <= 1 connected (target_dim+2)-dimensional adjacent entities;
     361                 :            : //! for target_dim=3, just return all of them
     362                 :            : //! just insert into the list, w/o clearing manifold list first
     363                 :          0 : ErrorCode MeshTopoUtil::get_manifold( const EntityHandle star_entity, const int target_dim, Range& manifold )
     364                 :            : {
     365                 :            :     // get all the entities of target dimension connected to star
     366         [ #  # ]:          0 :     Range tmp_range;
     367         [ #  # ]:          0 :     ErrorCode result = mbImpl->get_adjacencies( &star_entity, 1, target_dim, false, tmp_range );
     368         [ #  # ]:          0 :     if( MB_SUCCESS != result ) return result;
     369                 :            : 
     370                 :            :     // now save the ones which are (target_dim+1)-dimensional manifold;
     371                 :            :     // for target_dim=3, just return whole range, since we don't do 4d
     372         [ #  # ]:          0 :     if( target_dim == 3 )
     373                 :            :     {
     374         [ #  # ]:          0 :         manifold.merge( tmp_range );
     375                 :          0 :         return MB_SUCCESS;
     376                 :            :     }
     377                 :            : 
     378 [ #  # ][ #  # ]:          0 :     for( Range::iterator rit = tmp_range.begin(); rit != tmp_range.end(); ++rit )
         [ #  # ][ #  # ]
                 [ #  # ]
     379                 :            :     {
     380         [ #  # ]:          0 :         Range dum_range;
     381                 :            :         // get (target_dim+1)-dimensional entities
     382 [ #  # ][ #  # ]:          0 :         result = mbImpl->get_adjacencies( &( *rit ), 1, target_dim + 1, false, dum_range );
     383         [ #  # ]:          0 :         if( MB_SUCCESS != result ) return result;
     384                 :            : 
     385                 :            :         // if there are only 1 or zero, add to manifold list
     386 [ #  # ][ #  # ]:          0 :         if( 1 >= dum_range.size() ) manifold.insert( *rit );
         [ #  # ][ #  # ]
                 [ #  # ]
     387                 :          0 :     }
     388                 :            : 
     389                 :          0 :     return MB_SUCCESS;
     390                 :            : }
     391                 :            : 
     392                 :            : //! get "bridge" or "2nd order" adjacencies, going through dimension bridge_dim
     393                 :          0 : ErrorCode MeshTopoUtil::get_bridge_adjacencies( Range& from_entities, int bridge_dim, int to_dim, Range& to_ents,
     394                 :            :                                                 int num_layers )
     395                 :            : {
     396 [ #  # ][ #  # ]:          0 :     Range bridge_ents, accum_layers, new_toents( from_entities );
                 [ #  # ]
     397                 :            :     ErrorCode result;
     398 [ #  # ][ #  # ]:          0 :     if( 0 == num_layers || from_entities.empty() ) return MB_FAILURE;
         [ #  # ][ #  # ]
     399                 :            : 
     400                 :            :     // for each layer, get bridge-adj entities and accumulate
     401         [ #  # ]:          0 :     for( int nl = 0; nl < num_layers; nl++ )
     402                 :            :     {
     403         [ #  # ]:          0 :         Range new_bridges;
     404                 :            :         // get bridge ents
     405         [ #  # ]:          0 :         result = mbImpl->get_adjacencies( new_toents, bridge_dim, true, new_bridges, Interface::UNION );
     406         [ #  # ]:          0 :         if( MB_SUCCESS != result ) return result;
     407                 :            : 
     408                 :            :         // get to_dim adjacencies, merge into to_ents
     409 [ #  # ][ #  # ]:          0 :         Range new_layer;
     410         [ #  # ]:          0 :         if( -1 == to_dim )
     411                 :            :         {
     412         [ #  # ]:          0 :             result = mbImpl->get_adjacencies( new_bridges, 3, false, new_layer, Interface::UNION );
     413         [ #  # ]:          0 :             if( MB_SUCCESS != result ) return result;
     414         [ #  # ]:          0 :             for( int d = 2; d >= 1; d-- )
     415                 :            :             {
     416         [ #  # ]:          0 :                 result = mbImpl->get_adjacencies( to_ents, d, true, new_layer, Interface::UNION );
     417         [ #  # ]:          0 :                 if( MB_SUCCESS != result ) return result;
     418                 :            :             }
     419                 :            :         }
     420                 :            :         else
     421                 :            :         {
     422         [ #  # ]:          0 :             result = mbImpl->get_adjacencies( new_bridges, to_dim, false, new_layer, Interface::UNION );
     423         [ #  # ]:          0 :             if( MB_SUCCESS != result ) return result;
     424                 :            :         }
     425                 :            : 
     426                 :            :         // subtract last_toents to get new_toents
     427         [ #  # ]:          0 :         accum_layers.merge( new_layer );
     428 [ #  # ][ #  # ]:          0 :         if( nl < num_layers - 1 ) new_toents = subtract( new_layer, new_toents );
         [ #  # ][ #  # ]
     429                 :          0 :     }
     430         [ #  # ]:          0 :     to_ents.merge( accum_layers );
     431                 :            : 
     432                 :          0 :     return MB_SUCCESS;
     433                 :            : }
     434                 :            : 
     435                 :            : //! get "bridge" or "2nd order" adjacencies, going through dimension bridge_dim
     436                 :      59540 : ErrorCode MeshTopoUtil::get_bridge_adjacencies( const EntityHandle from_entity, const int bridge_dim, const int to_dim,
     437                 :            :                                                 Range& to_adjs )
     438                 :            : {
     439                 :            :     // get pointer to connectivity for this entity
     440                 :            :     const EntityHandle* connect;
     441                 :            :     int num_connect;
     442                 :      59540 :     ErrorCode result     = MB_SUCCESS;
     443         [ +  - ]:      59540 :     EntityType from_type = TYPE_FROM_HANDLE( from_entity );
     444         [ -  + ]:      59540 :     if( from_type == MBVERTEX )
     445                 :            :     {
     446                 :          0 :         connect     = &from_entity;
     447                 :          0 :         num_connect = 1;
     448                 :            :     }
     449                 :            :     else
     450                 :            :     {
     451         [ +  - ]:      59540 :         result = mbImpl->get_connectivity( from_entity, connect, num_connect );
     452         [ -  + ]:      59540 :         if( MB_SUCCESS != result ) return result;
     453                 :            :     }
     454                 :            : 
     455         [ -  + ]:      59540 :     if( from_type >= MBENTITYSET ) return MB_FAILURE;
     456                 :            : 
     457         [ +  - ]:      59540 :     int from_dim = CN::Dimension( from_type );
     458                 :            : 
     459         [ +  - ]:      59540 :     Range to_ents;
     460                 :            : 
     461         [ +  - ]:      59540 :     if( bridge_dim < from_dim )
     462                 :            :     {
     463                 :            :         // looping over each sub-entity of dimension bridge_dim...
     464         [ -  + ]:      59540 :         if( MBPOLYGON == from_type )
     465                 :            :         {
     466         [ #  # ]:          0 :             for( int i = 0; i < num_connect; i++ )
     467                 :            :             {
     468                 :            :                 // loop over edges, and get the vertices
     469                 :          0 :                 EntityHandle verts_on_edge[2] = { connect[i], connect[( i + 1 ) % num_connect] };
     470         [ #  # ]:          0 :                 to_ents.clear();
     471                 :            :                 ErrorCode tmp_result =
     472         [ #  # ]:          0 :                     mbImpl->get_adjacencies( verts_on_edge, 2, to_dim, false, to_ents, Interface::INTERSECT );
     473         [ #  # ]:          0 :                 if( MB_SUCCESS != tmp_result ) result = tmp_result;
     474         [ #  # ]:          0 :                 to_adjs.merge( to_ents );
     475                 :            :             }
     476                 :            :         }
     477                 :            :         else
     478                 :            :         {
     479                 :            :             EntityHandle bridge_verts[MAX_SUB_ENTITIES];
     480                 :            :             int bridge_indices[MAX_SUB_ENTITIES];
     481 [ +  - ][ +  + ]:     323414 :             for( int i = 0; i < CN::NumSubEntities( from_type, bridge_dim ); i++ )
     482                 :            :             {
     483                 :            : 
     484                 :            :                 // get the vertices making up this sub-entity
     485 [ +  - ][ +  - ]:     263874 :                 int num_bridge_verts = CN::VerticesPerEntity( CN::SubEntityType( from_type, bridge_dim, i ) );
     486 [ +  - ][ -  + ]:     263874 :                 assert( num_bridge_verts >= 0 && num_bridge_verts <= MAX_SUB_ENTITIES );
     487         [ +  - ]:     263874 :                 CN::SubEntityVertexIndices( from_type, bridge_dim, i, bridge_indices );
     488         [ +  + ]:    1105126 :                 for( int j = 0; j < num_bridge_verts; ++j )
     489                 :            :                 {
     490 [ +  - ][ +  - ]:     841252 :                     if( bridge_indices[j] >= 0 && bridge_indices[j] < num_connect )
     491                 :     841252 :                         bridge_verts[j] = connect[bridge_indices[j]];
     492                 :            :                     else
     493                 :          0 :                         bridge_verts[j] = 0;
     494                 :            :                 }
     495                 :            :                 // CN::SubEntityConn(connect, from_type, bridge_dim, i, &bridge_verts[0],
     496                 :            :                 // num_bridge_verts);
     497                 :            : 
     498                 :            :                 // get the to_dim entities adjacent
     499         [ +  - ]:     263874 :                 to_ents.clear();
     500                 :            :                 ErrorCode tmp_result = mbImpl->get_adjacencies( bridge_verts, num_bridge_verts, to_dim, false, to_ents,
     501         [ +  - ]:     263874 :                                                                 Interface::INTERSECT );
     502         [ -  + ]:     263874 :                 if( MB_SUCCESS != tmp_result ) result = tmp_result;
     503                 :            : 
     504         [ +  - ]:     263874 :                 to_adjs.merge( to_ents );
     505                 :            :             }
     506                 :            :         }
     507                 :            :     }
     508                 :            : 
     509                 :            :     // now get the direct ones too, or only in the case where we're
     510                 :            :     // going to higher dimension for bridge
     511 [ +  - ][ +  - ]:     119080 :     Range bridge_ents, tmp_ents;
     512         [ +  - ]:      59540 :     tmp_ents.insert( from_entity );
     513         [ +  - ]:      59540 :     ErrorCode tmp_result = mbImpl->get_adjacencies( tmp_ents, bridge_dim, false, bridge_ents, Interface::UNION );
     514         [ -  + ]:      59540 :     if( MB_SUCCESS != tmp_result ) return tmp_result;
     515                 :            : 
     516         [ +  - ]:      59540 :     tmp_result = mbImpl->get_adjacencies( bridge_ents, to_dim, false, to_adjs, Interface::UNION );
     517         [ -  + ]:      59540 :     if( MB_SUCCESS != tmp_result ) return tmp_result;
     518                 :            : 
     519                 :            :     // if to_dimension is same as that of from_entity, make sure from_entity isn't
     520                 :            :     // in list
     521 [ +  - ][ +  - ]:      59540 :     if( to_dim == from_dim ) to_adjs.erase( from_entity );
     522                 :            : 
     523                 :     119080 :     return result;
     524                 :            : }
     525                 :            : 
     526                 :            : //! return a common entity of the specified dimension, or 0 if there isn't one
     527                 :          0 : EntityHandle MeshTopoUtil::common_entity( const EntityHandle ent1, const EntityHandle ent2, const int dim )
     528                 :            : {
     529 [ #  # ][ #  # ]:          0 :     Range tmp_range, tmp_range2;
     530         [ #  # ]:          0 :     tmp_range.insert( ent1 );
     531         [ #  # ]:          0 :     tmp_range.insert( ent2 );
     532         [ #  # ]:          0 :     ErrorCode result = mbImpl->get_adjacencies( tmp_range, dim, false, tmp_range2 );
     533 [ #  # ][ #  # ]:          0 :     if( MB_SUCCESS != result || tmp_range2.empty() )
         [ #  # ][ #  # ]
     534                 :          0 :         return 0;
     535                 :            :     else
     536 [ #  # ][ #  # ]:          0 :         return *tmp_range2.begin();
     537                 :            : }
     538                 :            : 
     539                 :            : //! return the opposite side entity given a parent and bounding entity.
     540                 :            : //! This function is only defined for certain types of parent/child types;
     541                 :            : //! See CN.hpp::OppositeSide for details.
     542                 :            : //!
     543                 :            : //! \param parent The parent element
     544                 :            : //! \param child The child element
     545                 :            : //! \param opposite_element The index of the opposite element
     546                 :          0 : ErrorCode MeshTopoUtil::opposite_entity( const EntityHandle parent, const EntityHandle child,
     547                 :            :                                          EntityHandle& opposite_element )
     548                 :            : {
     549                 :            :     // get the side no.
     550                 :            :     int side_no, offset, sense;
     551         [ #  # ]:          0 :     ErrorCode result = mbImpl->side_number( parent, child, side_no, offset, sense );
     552         [ #  # ]:          0 :     if( MB_SUCCESS != result ) return result;
     553                 :            : 
     554                 :            :     // get the child index from CN
     555                 :            :     int opposite_index, opposite_dim;
     556                 :          0 :     int status = CN::OppositeSide( mbImpl->type_from_handle( parent ), side_no, mbImpl->dimension_from_handle( child ),
     557 [ #  # ][ #  # ]:          0 :                                    opposite_index, opposite_dim );
                 [ #  # ]
     558         [ #  # ]:          0 :     if( 0 != status ) return MB_FAILURE;
     559                 :            : 
     560                 :            :     // now get the side element from MOAB
     561         [ #  # ]:          0 :     result = mbImpl->side_element( parent, opposite_dim, opposite_index, opposite_element );
     562         [ #  # ]:          0 :     if( MB_SUCCESS != result ) return result;
     563                 :            : 
     564                 :          0 :     return MB_SUCCESS;
     565                 :            : }
     566                 :            : 
     567                 :          1 : ErrorCode MeshTopoUtil::split_entities_manifold( Range& entities, Range& new_entities, Range* fill_entities )
     568                 :            : {
     569         [ +  - ]:          1 :     Range tmp_range, *tmp_ptr_fill_entity;
     570         [ +  - ]:          1 :     if( NULL != fill_entities )
     571                 :          1 :         tmp_ptr_fill_entity = &tmp_range;
     572                 :            :     else
     573                 :          0 :         tmp_ptr_fill_entity = NULL;
     574                 :            : 
     575 [ +  - ][ +  - ]:          5 :     for( Range::iterator rit = entities.begin(); rit != entities.end(); ++rit )
         [ +  - ][ +  - ]
                 [ +  + ]
     576                 :            :     {
     577                 :            :         EntityHandle new_entity;
     578 [ +  - ][ +  - ]:          4 :         if( NULL != tmp_ptr_fill_entity ) tmp_ptr_fill_entity->clear();
     579                 :            : 
     580         [ +  - ]:          4 :         EntityHandle this_ent = *rit;
     581         [ +  - ]:          4 :         ErrorCode result      = split_entities_manifold( &this_ent, 1, &new_entity, tmp_ptr_fill_entity );
     582         [ -  + ]:          4 :         if( MB_SUCCESS != result ) return result;
     583                 :            : 
     584         [ +  - ]:          4 :         new_entities.insert( new_entity );
     585 [ +  - ][ +  - ]:          4 :         if( NULL != fill_entities ) fill_entities->merge( *tmp_ptr_fill_entity );
     586                 :            :     }
     587                 :            : 
     588                 :          1 :     return MB_SUCCESS;
     589                 :            : }
     590                 :            : 
     591                 :          4 : ErrorCode MeshTopoUtil::split_entities_manifold( EntityHandle* entities, const int num_entities,
     592                 :            :                                                  EntityHandle* new_entities, Range* fill_entities,
     593                 :            :                                                  EntityHandle* gowith_ents )
     594                 :            : {
     595                 :            :     // split entities by duplicating them; splitting manifold means that there is at
     596                 :            :     // most two higher-dimension entities bounded by a given entity; after split, the
     597                 :            :     // new entity bounds one and the original entity bounds the other
     598                 :            : 
     599                 :            : #define ITERATE_RANGE( range, it ) for( Range::iterator it = range.begin(); it != range.end(); ++it )
     600                 :            : #define GET_CONNECT_DECL( ent, connect, num_connect )                                     \
     601                 :            :     const EntityHandle* connect = NULL;                                                   \
     602                 :            :     int num_connect             = 0;                                                      \
     603                 :            :     {                                                                                     \
     604                 :            :         ErrorCode connect_result = mbImpl->get_connectivity( ent, connect, num_connect ); \
     605                 :            :         if( MB_SUCCESS != connect_result ) return connect_result;                         \
     606                 :            :     }
     607                 :            : #define GET_CONNECT( ent, connect, num_connect )                                          \
     608                 :            :     {                                                                                     \
     609                 :            :         ErrorCode connect_result = mbImpl->get_connectivity( ent, connect, num_connect ); \
     610                 :            :         if( MB_SUCCESS != connect_result ) return connect_result;                         \
     611                 :            :     }
     612                 :            : #define TC                         \
     613                 :            :     if( MB_SUCCESS != tmp_result ) \
     614                 :            :     {                              \
     615                 :            :         result = tmp_result;       \
     616                 :            :         continue;                  \
     617                 :            :     }
     618                 :            : 
     619                 :          4 :     ErrorCode result = MB_SUCCESS;
     620         [ +  + ]:          8 :     for( int i = 0; i < num_entities; i++ )
     621                 :            :     {
     622                 :            :         ErrorCode tmp_result;
     623                 :            : 
     624                 :            :         // get original higher-dimensional bounding entities
     625 [ +  - ][ +  + ]:         40 :         Range up_adjs[4];
           [ +  -  -  #  
                      # ]
     626                 :            :         // can only do a split_manifold if there are at most 2 entities of each
     627                 :            :         // higher dimension; otherwise it's a split non-manifold
     628                 :          4 :         bool valid_up_adjs = true;
     629         [ +  + ]:         16 :         for( int dim = 1; dim <= 3; dim++ )
     630                 :            :         {
     631         [ +  - ]:         12 :             tmp_result = mbImpl->get_adjacencies( entities + i, 1, dim, false, up_adjs[dim] );
     632         [ -  + ]:         12 :             TC;
     633 [ +  - ][ +  - ]:         12 :             if( dim > CN::Dimension( TYPE_FROM_HANDLE( entities[i] ) ) && up_adjs[dim].size() > 2 )
         [ +  + ][ +  - ]
         [ -  + ][ -  + ]
     634                 :            :             {
     635                 :          0 :                 valid_up_adjs = false;
     636                 :          0 :                 break;
     637                 :            :             }
     638                 :            :         }
     639         [ -  + ]:          4 :         if( !valid_up_adjs ) return MB_FAILURE;
     640                 :            : 
     641                 :            :         // ok to split; create the new entity, with connectivity of the original
     642 [ +  - ][ -  + ]:          4 :         GET_CONNECT_DECL( entities[i], connect, num_connect );
     643                 :            :         EntityHandle new_entity;
     644 [ +  - ][ +  - ]:          4 :         result = mbImpl->create_element( mbImpl->type_from_handle( entities[i] ), connect, num_connect, new_entity );
     645         [ -  + ]:          4 :         TC;
     646                 :            : 
     647                 :            :         // by definition, new entity and original will be equivalent; need to add explicit
     648                 :            :         // adjs to distinguish them; don't need to check if there's already one there,
     649                 :            :         // 'cuz add_adjacency does that for us
     650         [ +  + ]:         16 :         for( int dim = 1; dim <= 3; dim++ )
     651                 :            :         {
     652 [ +  - ][ +  - ]:         12 :             if( up_adjs[dim].empty() || dim == CN::Dimension( TYPE_FROM_HANDLE( entities[i] ) ) ) continue;
         [ +  - ][ +  - ]
         [ +  + ][ +  + ]
     653                 :            : 
     654 [ +  - ][ +  - ]:          8 :             if( dim < CN::Dimension( TYPE_FROM_HANDLE( entities[i] ) ) )
                 [ +  + ]
     655                 :            :             {
     656                 :            :                 // adjacencies from other entities to this one; if any of those are equivalent
     657                 :            :                 // entities, need to make explicit adjacency to new entity too
     658 [ +  - ][ +  - ]:         20 :                 for( Range::iterator rit = up_adjs[dim].begin(); rit != up_adjs[dim].end(); ++rit )
         [ +  - ][ +  - ]
                 [ +  + ]
     659                 :            :                 {
     660 [ +  - ][ +  - ]:         16 :                     if( equivalent_entities( *rit ) ) result = mbImpl->add_adjacencies( *rit, &new_entity, 1, false );
         [ -  + ][ #  # ]
                 [ #  # ]
     661                 :            :                 }
     662                 :            :             }
     663                 :            :             else
     664                 :            :             {
     665                 :            : 
     666                 :            :                 // get the two up-elements
     667 [ +  - ][ +  - ]:          4 :                 EntityHandle up_elem1 = *( up_adjs[dim].begin() ),
     668 [ +  - ][ +  - ]:          4 :                              up_elem2 = ( up_adjs[dim].size() > 1 ? *( up_adjs[dim].rbegin() ) : 0 );
         [ +  - ][ +  - ]
         [ +  - ][ #  # ]
     669                 :            : 
     670                 :            :                 // if two, and a gowith entity was input, make sure the new entity goes with
     671                 :            :                 // that one
     672 [ -  + ][ #  # ]:          4 :                 if( gowith_ents && up_elem2 && gowith_ents[i] != up_elem1 && gowith_ents[i] == up_elem2 )
         [ #  # ][ #  # ]
     673                 :            :                 {
     674                 :          0 :                     EntityHandle tmp_elem = up_elem1;
     675                 :          0 :                     up_elem1              = up_elem2;
     676                 :          0 :                     up_elem2              = tmp_elem;
     677                 :            :                 }
     678                 :            : 
     679         [ +  - ]:          4 :                 mbImpl->remove_adjacencies( entities[i], &up_elem1, 1 );
     680                 :            :                 // (ok if there's an error, that just means there wasn't an explicit adj)
     681                 :            : 
     682         [ +  - ]:          4 :                 tmp_result = mbImpl->add_adjacencies( new_entity, &up_elem1, 1, false );
     683         [ -  + ]:          4 :                 TC;
     684         [ -  + ]:          4 :                 if( !up_elem2 ) continue;
     685                 :            : 
     686                 :            :                 // add adj to other up_adj
     687         [ +  - ]:          4 :                 tmp_result = mbImpl->add_adjacencies( entities[i], &up_elem2, 1, false );
     688         [ -  + ]:          4 :                 TC;
     689                 :            :             }
     690                 :            :         }
     691                 :            : 
     692                 :            :         // if we're asked to build a next-higher-dimension object, do so
     693                 :          4 :         EntityHandle fill_entity = 0;
     694                 :            :         EntityHandle tmp_ents[2];
     695         [ +  - ]:          4 :         if( NULL != fill_entities )
     696                 :            :         {
     697                 :            :             // how to do this depends on dimension
     698 [ +  - ][ +  - ]:          4 :             switch( CN::Dimension( TYPE_FROM_HANDLE( entities[i] ) ) )
           [ -  -  +  - ]
     699                 :            :             {
     700                 :            :                 case 0:
     701                 :          0 :                     tmp_ents[0] = entities[i];
     702                 :          0 :                     tmp_ents[1] = new_entity;
     703         [ #  # ]:          0 :                     tmp_result  = mbImpl->create_element( MBEDGE, tmp_ents, 2, fill_entity );
     704         [ #  # ]:          0 :                     TC;
     705                 :          0 :                     break;
     706                 :            :                 case 1:
     707         [ #  # ]:          0 :                     tmp_result = mbImpl->create_element( MBPOLYGON, connect, 2, fill_entity );
     708         [ #  # ]:          0 :                     TC;
     709                 :            :                     // need to create explicit adj in this case
     710         [ #  # ]:          0 :                     tmp_result = mbImpl->add_adjacencies( entities[i], &fill_entity, 1, false );
     711         [ #  # ]:          0 :                     TC;
     712         [ #  # ]:          0 :                     tmp_result = mbImpl->add_adjacencies( new_entity, &fill_entity, 1, false );
     713         [ #  # ]:          0 :                     TC;
     714                 :          0 :                     break;
     715                 :            :                 case 2:
     716                 :          4 :                     tmp_ents[0] = entities[i];
     717                 :          4 :                     tmp_ents[1] = new_entity;
     718         [ +  - ]:          4 :                     tmp_result  = mbImpl->create_element( MBPOLYHEDRON, tmp_ents, 2, fill_entity );
     719         [ -  + ]:          4 :                     TC;
     720                 :          4 :                     break;
     721                 :            :             }
     722         [ -  + ]:          4 :             if( 0 == fill_entity )
     723                 :            :             {
     724                 :          0 :                 result = MB_FAILURE;
     725                 :          0 :                 continue;
     726                 :            :             }
     727         [ +  - ]:          4 :             fill_entities->insert( fill_entity );
     728                 :            :         }
     729                 :            : 
     730         [ +  + ]:         20 :         new_entities[i] = new_entity;
     731                 :            : 
     732         [ #  # ]:          4 :     }  // end for over input entities
     733                 :            : 
     734         [ #  # ]:          4 :     return result;
     735                 :            : }
     736                 :            : 
     737                 :          0 : ErrorCode MeshTopoUtil::split_entity_nonmanifold( EntityHandle split_ent, Range& old_adjs, Range& new_adjs,
     738                 :            :                                                   EntityHandle& new_entity )
     739                 :            : {
     740                 :            :     // split an entity into two entities; new entity gets explicit adj to new_adjs,
     741                 :            :     // old to old_adjs
     742                 :            : 
     743                 :            :     // make new entities and add adjacencies
     744                 :            :     // create the new entity
     745                 :          0 :     EntityType split_type = mbImpl->type_from_handle( split_ent );
     746                 :            : 
     747                 :            :     ErrorCode result;
     748         [ #  # ]:          0 :     if( MBVERTEX == split_type )
     749                 :            :     {
     750                 :            :         double coords[3];
     751 [ #  # ][ #  # ]:          0 :         result = mbImpl->get_coords( &split_ent, 1, coords );RR;
     752 [ #  # ][ #  # ]:          0 :         result = mbImpl->create_vertex( coords, new_entity );RR;
     753                 :            :     }
     754                 :            :     else
     755                 :            :     {
     756                 :            :         const EntityHandle* connect;
     757                 :            :         int num_connect;
     758 [ #  # ][ #  # ]:          0 :         result = mbImpl->get_connectivity( split_ent, connect, num_connect );RR;
     759 [ #  # ][ #  # ]:          0 :         result = mbImpl->create_element( split_type, connect, num_connect, new_entity );RR;
     760                 :            : 
     761                 :            :         // remove any explicit adjacencies between new_adjs and split entity
     762 [ #  # ][ #  # ]:          0 :         for( Range::iterator rit = new_adjs.begin(); rit != new_adjs.end(); ++rit )
         [ #  # ][ #  # ]
                 [ #  # ]
     763 [ #  # ][ #  # ]:          0 :             mbImpl->remove_adjacencies( split_ent, &( *rit ), 1 );
     764                 :            :     }
     765                 :            : 
     766         [ #  # ]:          0 :     if( MBVERTEX != split_type )
     767                 :            :     {
     768                 :            :         //  add adj's between new_adjs & new entity, old_adjs & split_entity
     769 [ #  # ][ #  # ]:          0 :         for( Range::iterator rit = new_adjs.begin(); rit != new_adjs.end(); ++rit )
         [ #  # ][ #  # ]
                 [ #  # ]
     770 [ #  # ][ #  # ]:          0 :             mbImpl->add_adjacencies( new_entity, &( *rit ), 1, true );
     771 [ #  # ][ #  # ]:          0 :         for( Range::iterator rit = old_adjs.begin(); rit != old_adjs.end(); ++rit )
         [ #  # ][ #  # ]
                 [ #  # ]
     772 [ #  # ][ #  # ]:          0 :             mbImpl->add_adjacencies( split_ent, &( *rit ), 1, true );
     773                 :            :     }
     774         [ #  # ]:          0 :     else if( split_ent != new_entity )
     775                 :            :     {
     776                 :            :         // in addition to explicit adjs, need to check if vertex is part of any
     777                 :            :         // other entities, and check those entities against ents in old and new adjs
     778         [ #  # ]:          0 :         Range other_adjs;
     779         [ #  # ]:          0 :         for( int i = 1; i < 4; i++ )
     780                 :            :         {
     781 [ #  # ][ #  # ]:          0 :             result = mbImpl->get_adjacencies( &split_ent, 1, i, false, other_adjs, Interface::UNION );RR;
     782                 :            :         }
     783 [ #  # ][ #  # ]:          0 :         other_adjs = subtract( other_adjs, old_adjs );
     784 [ #  # ][ #  # ]:          0 :         other_adjs = subtract( other_adjs, new_adjs );
     785 [ #  # ][ #  # ]:          0 :         for( Range::iterator rit1 = other_adjs.begin(); rit1 != other_adjs.end(); ++rit1 )
         [ #  # ][ #  # ]
                 [ #  # ]
     786                 :            :         {
     787                 :            :             // find an adjacent lower-dimensional entity in old_ or new_ adjs
     788                 :          0 :             bool found = false;
     789 [ #  # ][ #  # ]:          0 :             for( Range::iterator rit2 = old_adjs.begin(); rit2 != old_adjs.end(); ++rit2 )
         [ #  # ][ #  # ]
                 [ #  # ]
     790                 :            :             {
     791 [ #  # ][ #  # ]:          0 :                 if( mbImpl->dimension_from_handle( *rit1 ) != mbImpl->dimension_from_handle( *rit2 ) &&
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     792 [ #  # ][ #  # ]:          0 :                     common_entity( *rit1, *rit2, mbImpl->dimension_from_handle( *rit1 ) ) )
         [ #  # ][ #  # ]
                 [ #  # ]
     793                 :            :                 {
     794                 :          0 :                     found = true;
     795 [ #  # ][ #  # ]:          0 :                     old_adjs.insert( *rit1 );
     796                 :          0 :                     break;
     797                 :            :                 }
     798                 :            :             }
     799         [ #  # ]:          0 :             if( found ) continue;
     800 [ #  # ][ #  # ]:          0 :             for( Range::iterator rit2 = new_adjs.begin(); rit2 != new_adjs.end(); ++rit2 )
         [ #  # ][ #  # ]
                 [ #  # ]
     801                 :            :             {
     802 [ #  # ][ #  # ]:          0 :                 if( mbImpl->dimension_from_handle( *rit1 ) != mbImpl->dimension_from_handle( *rit2 ) &&
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     803 [ #  # ][ #  # ]:          0 :                     common_entity( *rit1, *rit2, mbImpl->dimension_from_handle( *rit1 ) ) )
         [ #  # ][ #  # ]
                 [ #  # ]
     804                 :            :                 {
     805                 :          0 :                     found = true;
     806 [ #  # ][ #  # ]:          0 :                     new_adjs.insert( *rit1 );
     807                 :          0 :                     break;
     808                 :            :                 }
     809                 :            :             }
     810         [ #  # ]:          0 :             if( !found ) return MB_FAILURE;
     811                 :            :         }
     812                 :            : 
     813                 :            :         // instead of adjs replace in connectivity
     814 [ #  # ][ #  # ]:          0 :         std::vector< EntityHandle > connect;
     815 [ #  # ][ #  # ]:          0 :         for( Range::iterator rit = new_adjs.begin(); rit != new_adjs.end(); ++rit )
         [ #  # ][ #  # ]
                 [ #  # ]
     816                 :            :         {
     817                 :          0 :             connect.clear();
     818 [ #  # ][ #  # ]:          0 :             result = mbImpl->get_connectivity( &( *rit ), 1, connect );RR;
         [ #  # ][ #  # ]
     819         [ #  # ]:          0 :             std::replace( connect.begin(), connect.end(), split_ent, new_entity );
     820 [ #  # ][ #  # ]:          0 :             result = mbImpl->set_connectivity( *rit, &connect[0], connect.size() );RR;
         [ #  # ][ #  # ]
     821                 :          0 :         }
     822                 :            :     }
     823                 :            : 
     824                 :          0 :     return result;
     825                 :            : 
     826                 :            :     /*
     827                 :            : 
     828                 :            :     Commented out for now, because I decided to do a different implementation
     829                 :            :     for the sake of brevity.  However, I still think this function is the right
     830                 :            :     way to do it, if I ever get the time.  Sigh.
     831                 :            : 
     832                 :            :         // split entity d, producing entity nd; generates various new entities,
     833                 :            :         // see algorithm description in notes from 2/25/05
     834                 :            :       const EntityHandle split_types = {MBEDGE, MBPOLYGON, MBPOLYHEDRON};
     835                 :            :       ErrorCode result = MB_SUCCESS;
     836                 :            :       const int dim = CN::Dimension(TYPE_FROM_HANDLE(d));
     837                 :            :       MeshTopoUtil mtu(this);
     838                 :            : 
     839                 :            :         // get all (d+2)-, (d+1)-cells connected to d
     840                 :            :       Range dp2s, dp1s, dp1s_manif, dp2s_manif;
     841                 :            :       result = get_adjacencies(&d, 1, dim+2, false, dp2s); RR;
     842                 :            :       result = get_adjacencies(&d, 1, dim+1, false, dp1s); RR;
     843                 :            : 
     844                 :            :         // also get (d+1)-cells connected to d which are manifold
     845                 :            :       get_manifold_dp1s(d, dp1s_manif);
     846                 :            :       get_manifold_dp2s(d, dp2s_manif);
     847                 :            : 
     848                 :            :         // make new cell nd, then ndp1
     849                 :            :       result = copy_entity(d, nd); RR;
     850                 :            :       EntityHandle tmp_connect[] = {d, nd};
     851                 :            :       EntityHandle ndp1;
     852                 :            :       result = create_element(split_types[dim],
     853                 :            :                               tmp_connect, 2, ndp1); RR;
     854                 :            : 
     855                 :            :         // modify (d+2)-cells, depending on what type they are
     856                 :            :       ITERATE_RANGE(dp2s, dp2) {
     857                 :            :           // first, get number of connected manifold (d+1)-entities
     858                 :            :         Range tmp_range, tmp_range2(dp1s_manif);
     859                 :            :         tmp_range.insert(*dp2);
     860                 :            :         tmp_range.insert(d);
     861                 :            :         tmp_result = get_adjacencies(tmp_range, 1, false, tmp_range2); TC;
     862                 :            :         EntityHandle ndp2;
     863                 :            : 
     864                 :            :           // a. manif (d+1)-cells is zero
     865                 :            :         if (tmp_range2.empty()) {
     866                 :            :             // construct new (d+1)-cell
     867                 :            :           EntityHandle ndp1a;
     868                 :            :           EntityHandle tmp_result = create_element(split_types[dim],
     869                 :            :                                                      tmp_connect, 2, ndp1a); TC;
     870                 :            :             // now make new (d+2)-cell
     871                 :            :           EntityHandle tmp_connect2[] = {ndp1, ndp1a};
     872                 :            :           tmp_result = create_element(split_types[dim+1],
     873                 :            :                                       tmp_connect2, 2, ndp2); TC;
     874                 :            :             // need to add explicit adjacencies, since by definition ndp1, ndp1a will be equivalent
     875                 :            :           tmp_result = add_adjacencies(ndp1a, &dp2, 1, false); TC;
     876                 :            :           tmp_result = add_adjacencies(ndp1a, &ndp2, 1, false); TC;
     877                 :            :           tmp_result = add_adjacencies(ndp1, &ndp2, 1, false); TC;
     878                 :            : 
     879                 :            :             // now insert nd into connectivity of dp2, right after d if dim < 1
     880                 :            :           std::vector<EntityHandle> connect;
     881                 :            :           tmp_result = get_connectivity(&dp2, 1, connect); TC;
     882                 :            :           if (dim < 1) {
     883                 :            :             std::vector<EntityHandle>::iterator vit = std::find(connect.begin(), connect.end(), d);
     884                 :            :             if (vit == connect.end()) {
     885                 :            :               result = MB_FAILURE;
     886                 :            :               continue;
     887                 :            :             }
     888                 :            :             connect.insert(vit, nd);
     889                 :            :           }
     890                 :            :           else
     891                 :            :             connect.push_back(nd);
     892                 :            :           tmp_result = set_connectivity(dp2, connect); TC;
     893                 :            : 
     894                 :            :             // if dim < 1, need to add explicit adj from ndp2 to higher-dim ents, since it'll
     895                 :            :             // be equiv to other dp2 entities
     896                 :            :           if (dim < 1) {
     897                 :            :             Range tmp_dp3s;
     898                 :            :             tmp_result = get_adjacencies(&dp2, 1, dim+3, false, tmp_dp3s); TC;
     899                 :            :             tmp_result = add_adjacencies(ndp2, tmp_dp3s, false); TC;
     900                 :            :           }
     901                 :            :         } // end if (tmp_range2.empty())
     902                 :            : 
     903                 :            :           // b. single manifold (d+1)-cell, which isn't adjacent to manifold (d+2)-cell
     904                 :            :         else if (tmp_range2.size() == 1) {
     905                 :            :             // b1. check validity, and skip if not valid
     906                 :            : 
     907                 :            :             // only change if not dp1-adjacent to manifold dp2cell; check that...
     908                 :            :           Range tmp_adjs(dp2s_manif);
     909                 :            :           tmp_result = get_adjacencies(&(*tmp_range2.begin()), 1, dim+2, false, tmp_adjs); TC;
     910                 :            :           if (!tmp_adjs.empty()) continue;
     911                 :            : 
     912                 :            :           EntityHandle dp1 = *tmp_range2.begin();
     913                 :            : 
     914                 :            :             // b2. make new (d+1)- and (d+2)-cell next to dp2
     915                 :            : 
     916                 :            :             // get the (d+2)-cell on the other side of dp1
     917                 :            :           tmp_result = get_adjacencies(&dp1, 1, dim+2, false, tmp_adjs); TC;
     918                 :            :           EntityHandle odp2 = *tmp_adjs.begin();
     919                 :            :           if (odp2 == dp2) odp2 = *tmp_adjs.rbegin();
     920                 :            : 
     921                 :            :             // get od, the d-cell on dp1_manif which isn't d
     922                 :            :           tmp_result = get_adjacencies(&dp1_manif, 1, dim, false, tmp_adjs); TC;
     923                 :            :           tmp_adjs.erase(d);
     924                 :            :           if (tmp_adjs.size() != 1) {
     925                 :            :             result = MB_FAILURE;
     926                 :            :             continue;
     927                 :            :           }
     928                 :            :           EntityHandle od = *tmp_adjs.begin();
     929                 :            : 
     930                 :            :             // make a new (d+1)-cell from od and nd
     931                 :            :           tmp_adjs.insert(nd);
     932                 :            :           tmp_result = create_element(split_types[1], tmp_adjs, ndp1a); TC;
     933                 :            : 
     934                 :            :             // construct new (d+2)-cell from dp1, ndp1, ndp1a
     935                 :            :           tmp_adjs.clear();
     936                 :            :           tmp_adjs.insert(dp1); tmp_adjs.insert(ndp1); tmp_adjs.insert(ndp1a);
     937                 :            :           tmp_result = create_element(split_types[2], tmp_adjs, ndp2); TC;
     938                 :            : 
     939                 :            :             // b3. replace d, dp1 in connect/adjs of odp2
     940                 :            :           std::vector<EntityHandle> connect;
     941                 :            :           tmp_result = get_connectivity(&odp2, 1, connect); TC;
     942                 :            :           if (dim == 0) {
     943                 :            :             *(std::find(connect.begin(), connect.end(), d)) = nd;
     944                 :            :             remove_adjacency(dp1, odp2);
     945                 :            : 
     946                 :            : 
     947                 :            : 
     948                 :            :             // if dp1 was explicitly adj to odp2, remove it
     949                 :            :           remove_adjacency
     950                 :            : 
     951                 :            :     ...
     952                 :            : 
     953                 :            :     */
     954                 :            : }
     955                 :            : 
     956                 :            : //! return whether entity is equivalent to any other of same type and same vertices;
     957                 :            : //! if equivalent entity is found, it's returned in equiv_ents and return value is true,
     958                 :            : //! false otherwise.
     959                 :         16 : bool MeshTopoUtil::equivalent_entities( const EntityHandle entity, Range* equiv_ents )
     960                 :            : {
     961                 :         16 :     const EntityHandle* connect = NULL;
     962                 :         16 :     int num_connect             = 0;
     963         [ +  - ]:         16 :     ErrorCode result            = mbImpl->get_connectivity( entity, connect, num_connect );
     964         [ -  + ]:         16 :     if( MB_SUCCESS != result ) return false;
     965                 :            : 
     966         [ +  - ]:         16 :     Range dum;
     967 [ +  - ][ +  - ]:         16 :     result = mbImpl->get_adjacencies( connect, num_connect, mbImpl->dimension_from_handle( entity ), false, dum );
     968         [ +  - ]:         16 :     dum.erase( entity );
     969                 :            : 
     970 [ -  + ][ #  # ]:         16 :     if( NULL != equiv_ents ) { equiv_ents->swap( dum ); }
     971                 :            : 
     972 [ +  - ][ -  + ]:         16 :     if( !dum.empty() )
     973                 :          0 :         return true;
     974                 :            :     else
     975                 :         16 :         return false;
     976                 :            : }
     977                 :            : 
     978 [ +  - ][ +  - ]:        228 : }  // namespace moab

Generated by: LCOV version 1.11