| 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; |
| 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 | |
| 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 | | |
| | 1122 | template <typename ITER> static inline |
| | 1123 | MBErrorCode 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 | { |
| | 1193 | |
| | 1194 | MBErrorCode 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 | |
| | 1205 | MBErrorCode 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 | |
| | 1270 | MBErrorCode 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 | |