Changeset 3299

Show
Ignore:
Timestamp:
11/06/09 16:29:04 (2 weeks ago)
Author:
kraftche
Message:

o Fix very broken vector-vector get_connectivity:

assumed that all entities in array had the same type as the first entity.

o Change vector-range get_connectivity such that it is worst-case

O(n ln n) instead of O(n2)

o Rewrite vector-vector get_adjacencies with specialized code instead

of call to range-range get_adjacencies

o Templatize implementation of range-range get_adjacencies such that

it can be shared by range-range get_adjacencies and vetor-range
get_adjacencies w/out converting the input list.

o Fix bug in some forms of get_adjancies when input list contains

only one entity and target type is vertex: still need to handle
INTERSECT/UNION flag if 'output' container is not empty.

o Fix inconsistent behavior for different versions and special

cases of get_adjacencies: all should return input entities if
asked for adjacent entities of the same dimension (not returning
such entities would be more consistent with iMesh, but that broke
other code in MOAB.)

Time required to skin a mesh using vertex->element adjacencies
was reduced from 9.32 seconds to 7.88 seconds with these changes.

Passes all tests.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • MOAB/trunk/MBCore.cpp

    r3297 r3299  
    947947  if (MB_SUCCESS != result) return result; 
    948948   
    949   std::copy(tmp_connect.begin(), tmp_connect.end(), mb_range_inserter(connectivity)); 
     949  std::sort( tmp_connect.begin(), tmp_connect.end() ); 
     950  std::copy(tmp_connect.rbegin(), tmp_connect.rend(), mb_range_inserter(connectivity)); 
    950951  return result; 
    951952} 
     
    957958                                      bool topological_connectivity) const 
    958959{ 
    959   if (num_handles == 0) return MB_FAILURE; 
    960    
    961     // Make sure the entity should have a connectivity. 
    962   MBEntityType type = TYPE_FROM_HANDLE(entity_handles[0]); 
    963  
    964   int i; 
    965   connectivity.clear(); 
    966  
    967   // handle the special case where someone asks for the connectivity 
    968   // of a vertex.  This actually kind of makes sense for a sphere element. 
    969   if (type == MBVERTEX) 
    970   { 
    971     connectivity.reserve(num_handles); 
    972     std::copy(entity_handles, entity_handles+num_handles,  
    973               std::back_inserter(connectivity)); 
    974     return MB_SUCCESS; 
    975   } 
    976  
    977     // WARNING: This is very dependent on the ordering of the MBEntityType enum 
    978   if(type <= MBVERTEX || type >= MBENTITYSET) 
    979     return MB_TYPE_OUT_OF_RANGE; 
    980  
    981   MBErrorCode result = MB_SUCCESS, temp_result; 
    982   for (i = 0; i < num_handles; i++) { 
    983     const EntitySequence* seq = 0; 
    984  
    985       // We know that connectivity is stored in an EntitySequence so jump straight 
    986       // to the entity sequence 
    987     temp_result = sequence_manager()->find(entity_handles[i], seq); 
    988     if (seq == NULL) { 
    989       result = MB_ENTITY_NOT_FOUND; 
    990       continue; 
    991     } 
    992     else if (temp_result != MB_SUCCESS) { 
    993       result = temp_result; 
    994       continue; 
    995     } 
    996  
    997     const ElementSequence *elem_seq = static_cast<const ElementSequence*>(seq); 
    998       // let's be smart about this... 
    999     temp_result = elem_seq->get_connectivity(entity_handles[i], connectivity, 
    1000                                              topological_connectivity); 
    1001     if (MB_SUCCESS != temp_result) { 
    1002       result = temp_result; 
    1003       continue; 
    1004     } 
    1005   } 
    1006    
    1007   return result; 
     960  connectivity.clear(); // this seems wrong as compared to other API functions, 
     961                        // but changing it breaks lost of code, so I'm leaving 
     962                        // it in.  - j.kraftcheck 2009-11-06 
     963   
     964  MBErrorCode rval; 
     965  std::vector<MBEntityHandle> tmp_storage; // used only for structured mesh 
     966  const MBEntityHandle* conn; 
     967  int len; 
     968  for (int i = 0; i < num_handles; ++i) { 
     969    rval = get_connectivity( entity_handles[i], conn, len, topological_connectivity, &tmp_storage ); 
     970    if (MB_SUCCESS != rval) 
     971      return rval; 
     972    connectivity.insert( connectivity.end(), conn, conn + len ); 
     973  } 
     974  return MB_SUCCESS; 
    1008975} 
    1009976 
     
    10801047} 
    10811048 
    1082 MBErrorCode MBCore::get_adjacencies(const MBEntityHandle *from_entities, 
    1083                                       const int num_entities, 
    1084                                       const int to_dimension, 
    1085                                       const bool create_if_missing, 
    1086                                       std::vector<MBEntityHandle> &adj_entities, 
    1087                                       const int operation_type) 
     1049MBErrorCode MBCore::get_adjacencies( const MBEntityHandle *from_entities, 
     1050                                     const int num_entities, 
     1051                                     const int to_dimension, 
     1052                                     const bool create_if_missing, 
     1053                                     std::vector<MBEntityHandle> &adj_entities, 
     1054                                     const int operation_type ) 
    10881055{ 
    10891056  MBErrorCode result; 
    1090   if (num_entities == 1) { 
     1057  if (num_entities == 1 && adj_entities.empty()) { 
    10911058    if(to_dimension == 0 && TYPE_FROM_HANDLE(from_entities[0]) != MBPOLYHEDRON) 
    10921059      result = get_connectivity(&from_entities[0], 1, adj_entities); 
    10931060    else 
    10941061      result = aEntityFactory->get_adjacencies(from_entities[0], to_dimension,  
    1095                                                create_if_missing, adj_entities); 
    1096     std::vector<MBEntityHandle>::iterator iter =  
    1097       std::remove(adj_entities.begin(), adj_entities.end(), MBEntityHandle(0)); 
    1098     if(iter != adj_entities.end()) 
    1099       adj_entities.erase(iter, adj_entities.end()); 
     1062                                             create_if_missing, adj_entities); 
     1063     
     1064    //adj_entities.erase( std::remove( adj_entities.begin(), adj_entities.end(), 0 ), adj_entities.end() ); 
    11001065    return result; 
    11011066  } 
    11021067   
    1103   MBRange temp_range, temp_range2; 
    1104   std::copy(from_entities, from_entities+num_entities, 
    1105             mb_range_inserter(temp_range)); 
    1106    
    1107   result = get_adjacencies(temp_range, to_dimension, create_if_missing, temp_range2, 
    1108                            operation_type); 
    1109   if (MB_SUCCESS != result)  
    1110     return result; 
    1111    
    1112   adj_entities.clear(); 
    1113   adj_entities.reserve(temp_range2.size()); 
    1114   for (MBRange::const_iterator it = temp_range2.begin(); 
    1115        it != temp_range2.end(); 
    1116        ++it) 
    1117     adj_entities.push_back(*it); 
    1118    
     1068  if (operation_type == MBInterface::UNION) { 
     1069    std::vector<MBEntityHandle> tmp_storage; 
     1070    const MBEntityHandle* conn; 
     1071    int len; 
     1072    for (int i = 0; i < num_entities; ++i) { 
     1073      if(to_dimension == 0 && TYPE_FROM_HANDLE(from_entities[0]) != MBPOLYHEDRON) { 
     1074        result = get_connectivity(from_entities[i], conn, len, false, &tmp_storage); 
     1075        adj_entities.insert( adj_entities.end(), conn, conn+len ); 
     1076        if (MB_SUCCESS != result) 
     1077          return result; 
     1078      } 
     1079      else { 
     1080        result = aEntityFactory->get_adjacencies(from_entities[i], to_dimension,  
     1081                                                 create_if_missing, adj_entities); 
     1082        if (MB_SUCCESS != result) 
     1083          return result; 
     1084      } 
     1085    } 
     1086    std::sort( adj_entities.begin(), adj_entities.end() ); 
     1087    adj_entities.erase( std::unique( adj_entities.begin(), adj_entities.end() ), adj_entities.end() ); 
     1088    return MB_SUCCESS; 
     1089  } 
     1090   
     1091  std::vector<MBEntityHandle> tmp_adj; 
     1092  for (int i = 0; i < num_entities; ++i) { 
     1093    tmp_adj.clear(); 
     1094    if(to_dimension == 0 && TYPE_FROM_HANDLE(from_entities[i]) != MBPOLYHEDRON) 
     1095      result = get_connectivity(&from_entities[i], 1, tmp_adj); 
     1096    else 
     1097      result = aEntityFactory->get_adjacencies(from_entities[i], to_dimension,  
     1098                                               create_if_missing, tmp_adj); 
     1099    if (MB_SUCCESS != result) 
     1100      return result; 
     1101     
     1102    if (tmp_adj.empty()) { 
     1103      adj_entities.clear(); 
     1104      return MB_SUCCESS; 
     1105    } 
     1106    else if (i == 0 && adj_entities.empty()) 
     1107      adj_entities.swap(tmp_adj); 
     1108    else { 
     1109      std::sort( tmp_adj.begin(), tmp_adj.end() ); 
     1110      std::vector<MBEntityHandle>::iterator it, w; 
     1111      for( it = w = adj_entities.begin(); it != adj_entities.end(); ++it ) { 
     1112        if (std::binary_search( tmp_adj.begin(), tmp_adj.end(), *it )) 
     1113          { *w = *it; ++w; } 
     1114      } 
     1115      adj_entities.erase( w, adj_entities.end() ); 
     1116    } 
     1117  } 
     1118  
    11191119  return MB_SUCCESS; 
    11201120} 
    11211121 
    1122 MBErrorCode MBCore::get_adjacencies(const MBEntityHandle *from_entities, 
    1123                                     const int num_entities, 
    1124                                     const int to_dimension, 
    1125                                       const bool create_if_missing, 
    1126                                       MBRange &adj_entities, 
    1127                                       const int operation_type) 
    1128 { 
    1129   MBRange tmp_from_entities; 
    1130   std::copy(from_entities, from_entities+num_entities, mb_range_inserter(tmp_from_entities)); 
    1131   return get_adjacencies(tmp_from_entities, to_dimension, create_if_missing,  
    1132                          adj_entities, operation_type); 
    1133 } 
    1134  
    1135 MBErrorCode MBCore::get_vertices( const MBRange& from_entities, 
    1136                                   MBRange& adj_entities ) 
    1137 { 
    1138   const size_t DEFAULT_MAX_BLOCKS_SIZE = 4000; 
    1139   const size_t MAX_OUTER_ITERATIONS = 100; 
    1140  
    1141   std::vector<MBEntityHandle> temp_vec, storage; 
    1142   std::vector<MBEntityHandle>::const_iterator ti; 
    1143   MBErrorCode result = MB_SUCCESS, tmp_result; 
    1144   MBRange::const_iterator i = from_entities.begin(); 
    1145   MBRange::iterator ins; 
    1146   const MBEntityHandle* conn; 
    1147   int conn_len; 
    1148  
    1149     // Just copy any vertices from the input range into the output 
    1150   size_t remaining = from_entities.size(); 
    1151   for (; i != from_entities.end() && TYPE_FROM_HANDLE(*i) == MBVERTEX; ++i)  
    1152     --remaining; 
    1153   adj_entities.merge( from_entities.begin(), i ); 
    1154    
    1155     // How many entities to work with at once? 2000 or so shouldn't require 
    1156     // too much memory, but don't iterate in outer loop more than a 
    1157     // 1000 times (make it bigger if many input entiites.)  
    1158   const size_t block_size = std::max( DEFAULT_MAX_BLOCKS_SIZE, remaining/MAX_OUTER_ITERATIONS ); 
    1159   while (remaining > 0) { 
    1160     const size_t count = remaining > block_size ? block_size : remaining; 
    1161     remaining -= count; 
    1162     temp_vec.clear(); 
    1163     for (size_t j = 0; j < count; ++i, ++j) { 
    1164       tmp_result = get_connectivity( *i, conn, conn_len, false, &storage ); 
    1165       if (MB_SUCCESS != tmp_result) { 
    1166         result = tmp_result; 
    1167         continue; 
    1168       } 
    1169  
    1170       if (TYPE_FROM_HANDLE(*i) == MBPOLYHEDRON) { 
    1171         storage.clear(); 
    1172         tmp_result = get_connectivity( conn, conn_len, storage ); 
    1173         if (MB_SUCCESS != tmp_result) { 
    1174           result = tmp_result; 
    1175           continue; 
    1176         } 
    1177         conn_len = storage.size(); 
    1178         conn = &storage[0]; 
    1179       } 
    1180  
    1181       const size_t oldsize = temp_vec.size(); 
    1182       temp_vec.resize( oldsize + conn_len ); 
    1183       memcpy( &temp_vec[oldsize], conn, sizeof(MBEntityHandle)*conn_len ); 
    1184     } 
    1185  
    1186     std::sort( temp_vec.begin(), temp_vec.end() ); 
    1187     ins = adj_entities.begin(); 
    1188     ti = temp_vec.begin(); 
    1189     while (ti != temp_vec.end()) { 
    1190       MBEntityHandle first = *ti; 
    1191       MBEntityHandle second = *ti; 
    1192       for (++ti; ti != temp_vec.end() && (*ti - second <= 1); ++ti) 
    1193         second = *ti; 
    1194       ins = adj_entities.insert( ins, first, second ); 
    1195     } 
    1196   } 
    1197   return result; 
    1198 } 
    1199  
    1200 MBErrorCode MBCore::get_adjacencies(const MBRange &from_entities, 
    1201                                       const int to_dimension, 
    1202                                       const bool create_if_missing, 
    1203                                       MBRange &adj_entities, 
    1204                                       const int operation_type) 
    1205 { 
    1206   if (operation_type != MBInterface::INTERSECT && 
    1207       operation_type != MBInterface::UNION) return MB_FAILURE; 
    1208  
    1209   if(from_entities.size() == 0) 
    1210     return MB_SUCCESS; 
    1211  
    1212     // special case for getting all vertices 
    1213   if (to_dimension == 0 && operation_type == MBInterface::UNION) { 
    1214     return get_vertices( from_entities, adj_entities ); 
    1215   } 
    1216  
     1122template <typename ITER> static inline 
     1123MBErrorCode get_adjacencies_common( MBCore* mb, 
     1124                             ITER begin, ITER end, 
     1125                             const int to_dimension, 
     1126                             const bool create_if_missing, 
     1127                             MBRange &adj_entities, 
     1128                             const int operation_type ) 
     1129{ 
    12171130  MBRange temp_range; 
    12181131  std::vector<MBEntityHandle> temp_vec; 
     
    12201133  MBErrorCode result = MB_SUCCESS, tmp_result; 
    12211134 
    1222   for (MBRange::const_iterator from_it = from_entities.begin();  
    1223        from_it != from_entities.end(); from_it++)  
     1135  for (ITER from_it = begin; from_it != end; from_it++)  
    12241136  { 
    12251137      // running results kept in adj_entities; clear temp_vec and temp_range, which are working space 
     
    12281140 
    12291141      // get the next set of adjacencies 
    1230     if(to_dimension == 0 && TYPE_FROM_HANDLE(*from_it) != MBPOLYHEDRON) 
    1231       tmp_result = get_connectivity(&(*from_it), 1, temp_vec); 
     1142    MBEntityType type = TYPE_FROM_HANDLE(*from_it); 
     1143    if (to_dimension == MBCN::Dimension(type))  
     1144      { temp_vec.push_back(*from_it); tmp_result = MB_SUCCESS; } 
     1145    else if(to_dimension == 0 && type != MBPOLYHEDRON) 
     1146      tmp_result = mb->get_connectivity(&(*from_it), 1, temp_vec); 
    12321147    else 
    1233       tmp_result = aEntityFactory->get_adjacencies(*from_it, to_dimension,  
     1148      tmp_result = mb->a_entity_factory()->get_adjacencies(*from_it, to_dimension,  
    12341149                                                   create_if_missing, temp_vec); 
    12351150     
     
    12401155      // if we're on the first iteration and we didn't come in with entities, 
    12411156      // just get the first results and move on 
    1242     if (adj_entities.empty() && from_it == from_entities.begin()) { 
     1157    if (adj_entities.empty() && from_it == begin) { 
    12431158      std::copy(temp_vec.rbegin(), temp_vec.rend(), mb_range_inserter(adj_entities)); 
    12441159      continue; 
     
    12761191  return result; 
    12771192} 
     1193 
     1194MBErrorCode MBCore::get_adjacencies( const MBEntityHandle *from_entities, 
     1195                                     const int num_entities, 
     1196                                     const int to_dimension, 
     1197                                     const bool create_if_missing, 
     1198                                     MBRange &adj_entities, 
     1199                                     const int operation_type ) 
     1200{ 
     1201  return get_adjacencies_common( this, from_entities, from_entities + num_entities, 
     1202                          to_dimension, create_if_missing, adj_entities, operation_type ); 
     1203} 
     1204 
     1205MBErrorCode MBCore::get_vertices( const MBRange& from_entities, 
     1206                                  MBRange& adj_entities ) 
     1207{ 
     1208  const size_t DEFAULT_MAX_BLOCKS_SIZE = 4000; 
     1209  const size_t MAX_OUTER_ITERATIONS = 100; 
     1210 
     1211  std::vector<MBEntityHandle> temp_vec, storage; 
     1212  std::vector<MBEntityHandle>::const_iterator ti; 
     1213  MBErrorCode result = MB_SUCCESS, tmp_result; 
     1214  MBRange::const_iterator i = from_entities.begin(); 
     1215  MBRange::iterator ins; 
     1216  const MBEntityHandle* conn; 
     1217  int conn_len; 
     1218 
     1219    // Just copy any vertices from the input range into the output 
     1220  size_t remaining = from_entities.size(); 
     1221  for (; i != from_entities.end() && TYPE_FROM_HANDLE(*i) == MBVERTEX; ++i)  
     1222    --remaining; 
     1223  adj_entities.merge( from_entities.begin(), i ); 
     1224   
     1225    // How many entities to work with at once? 2000 or so shouldn't require 
     1226    // too much memory, but don't iterate in outer loop more than a 
     1227    // 1000 times (make it bigger if many input entiites.)  
     1228  const size_t block_size = std::max( DEFAULT_MAX_BLOCKS_SIZE, remaining/MAX_OUTER_ITERATIONS ); 
     1229  while (remaining > 0) { 
     1230    const size_t count = remaining > block_size ? block_size : remaining; 
     1231    remaining -= count; 
     1232    temp_vec.clear(); 
     1233    for (size_t j = 0; j < count; ++i, ++j) { 
     1234      tmp_result = get_connectivity( *i, conn, conn_len, false, &storage ); 
     1235      if (MB_SUCCESS != tmp_result) { 
     1236        result = tmp_result; 
     1237        continue; 
     1238      } 
     1239 
     1240      if (TYPE_FROM_HANDLE(*i) == MBPOLYHEDRON) { 
     1241        storage.clear(); 
     1242        tmp_result = get_connectivity( conn, conn_len, storage ); 
     1243        if (MB_SUCCESS != tmp_result) { 
     1244          result = tmp_result; 
     1245          continue; 
     1246        } 
     1247        conn_len = storage.size(); 
     1248        conn = &storage[0]; 
     1249      } 
     1250 
     1251      const size_t oldsize = temp_vec.size(); 
     1252      temp_vec.resize( oldsize + conn_len ); 
     1253      memcpy( &temp_vec[oldsize], conn, sizeof(MBEntityHandle)*conn_len ); 
     1254    } 
     1255 
     1256    std::sort( temp_vec.begin(), temp_vec.end() ); 
     1257    ins = adj_entities.begin(); 
     1258    ti = temp_vec.begin(); 
     1259    while (ti != temp_vec.end()) { 
     1260      MBEntityHandle first = *ti; 
     1261      MBEntityHandle second = *ti; 
     1262      for (++ti; ti != temp_vec.end() && (*ti - second <= 1); ++ti) 
     1263        second = *ti; 
     1264      ins = adj_entities.insert( ins, first, second ); 
     1265    } 
     1266  } 
     1267  return result; 
     1268} 
     1269 
     1270MBErrorCode MBCore::get_adjacencies(const MBRange &from_entities, 
     1271                                      const int to_dimension, 
     1272                                      const bool create_if_missing, 
     1273                                      MBRange &adj_entities, 
     1274                                      const int operation_type) 
     1275{ 
     1276  if (operation_type != MBInterface::INTERSECT && 
     1277      operation_type != MBInterface::UNION) return MB_FAILURE; 
     1278 
     1279  if(from_entities.size() == 0) 
     1280    return MB_SUCCESS; 
     1281 
     1282    // special case for getting all vertices 
     1283  if (to_dimension == 0 && operation_type == MBInterface::UNION) { 
     1284    return get_vertices( from_entities, adj_entities ); 
     1285  } 
     1286 
     1287  return get_adjacencies_common( this, from_entities.begin(), from_entities.end(), 
     1288                           to_dimension, create_if_missing, adj_entities, operation_type ); 
     1289} 
     1290 
    12781291 
    12791292MBErrorCode MBCore::add_adjacencies(const MBEntityHandle entity_handle,