| | 1049 | |
| | 1050 | template <typename ITER> static |
| | 1051 | MBErrorCode get_adjacencies_union( MBCore* gMB, |
| | 1052 | ITER begin, ITER end, |
| | 1053 | int to_dimension, |
| | 1054 | bool create_if_missing, |
| | 1055 | MBRange& adj_entities ) |
| | 1056 | { |
| | 1057 | const size_t DEFAULT_MAX_BLOCKS_SIZE = 4000; |
| | 1058 | const size_t MAX_OUTER_ITERATIONS = 100; |
| | 1059 | |
| | 1060 | std::vector<MBEntityHandle> temp_vec, storage; |
| | 1061 | std::vector<MBEntityHandle>::const_iterator ti; |
| | 1062 | MBErrorCode result = MB_SUCCESS, tmp_result; |
| | 1063 | ITER i = begin; |
| | 1064 | MBRange::iterator ins; |
| | 1065 | const MBEntityHandle* conn; |
| | 1066 | int conn_len; |
| | 1067 | |
| | 1068 | // Just copy any vertices from the input range into the output |
| | 1069 | size_t remaining = end - begin; |
| | 1070 | assert(begin + remaining == end); |
| | 1071 | |
| | 1072 | // How many entities to work with at once? 2000 or so shouldn't require |
| | 1073 | // too much memory, but don't iterate in outer loop more than a |
| | 1074 | // 1000 times (make it bigger if many input entiites.) |
| | 1075 | const size_t block_size = std::max( DEFAULT_MAX_BLOCKS_SIZE, remaining/MAX_OUTER_ITERATIONS ); |
| | 1076 | while (remaining > 0) { |
| | 1077 | const size_t count = remaining > block_size ? block_size : remaining; |
| | 1078 | remaining -= count; |
| | 1079 | temp_vec.clear(); |
| | 1080 | for (size_t j = 0; j < count; ++i, ++j) { |
| | 1081 | if (MBCN::Dimension(TYPE_FROM_HANDLE(*i)) == to_dimension) { |
| | 1082 | temp_vec.push_back(*i); |
| | 1083 | } |
| | 1084 | else if (to_dimension == 0 && TYPE_FROM_HANDLE(*i) != MBPOLYHEDRON) { |
| | 1085 | tmp_result = gMB->get_connectivity( *i, conn, conn_len, false, &storage ); |
| | 1086 | if (MB_SUCCESS != tmp_result) { |
| | 1087 | result = tmp_result; |
| | 1088 | continue; |
| | 1089 | } |
| | 1090 | temp_vec.insert( temp_vec.end(), conn, conn + conn_len ); |
| | 1091 | } |
| | 1092 | else { |
| | 1093 | tmp_result = gMB->a_entity_factory()->get_adjacencies( *i, to_dimension, |
| | 1094 | create_if_missing, temp_vec); |
| | 1095 | } |
| | 1096 | } |
| | 1097 | |
| | 1098 | std::sort( temp_vec.begin(), temp_vec.end() ); |
| | 1099 | ins = adj_entities.begin(); |
| | 1100 | ti = temp_vec.begin(); |
| | 1101 | while (ti != temp_vec.end()) { |
| | 1102 | MBEntityHandle first = *ti; |
| | 1103 | MBEntityHandle second = *ti; |
| | 1104 | for (++ti; ti != temp_vec.end() && (*ti - second <= 1); ++ti) |
| | 1105 | second = *ti; |
| | 1106 | ins = adj_entities.insert( ins, first, second ); |
| | 1107 | } |
| | 1108 | } |
| | 1109 | return result; |
| | 1110 | } |
| | 1111 | |
| | 1112 | template <typename ITER> static |
| | 1113 | MBErrorCode get_adjacencies_intersection( MBCore* mb, |
| | 1114 | ITER begin, ITER end, |
| | 1115 | const int to_dimension, |
| | 1116 | const bool create_if_missing, |
| | 1117 | std::vector<MBEntityHandle>& adj_entities ) |
| | 1118 | { |
| | 1119 | const size_t SORT_THRESHOLD = 200; |
| | 1120 | std::vector<MBEntityHandle> temp_vec; |
| | 1121 | std::vector<MBEntityHandle>::iterator adj_it, w_it; |
| | 1122 | MBErrorCode result = MB_SUCCESS; |
| | 1123 | |
| | 1124 | for (ITER from_it = begin; from_it != end; from_it++) |
| | 1125 | { |
| | 1126 | // running results kept in adj_entities; clear temp_vec, which is working space |
| | 1127 | temp_vec.clear(); |
| | 1128 | |
| | 1129 | // get the next set of adjacencies |
| | 1130 | MBEntityType type = TYPE_FROM_HANDLE(*from_it); |
| | 1131 | if (to_dimension == MBCN::Dimension(type)) |
| | 1132 | temp_vec.push_back(*from_it); |
| | 1133 | else if(to_dimension == 0 && type != MBPOLYHEDRON) |
| | 1134 | result = mb->get_connectivity(&(*from_it), 1, temp_vec); |
| | 1135 | else |
| | 1136 | result = mb->a_entity_factory()->get_adjacencies(*from_it, to_dimension, |
| | 1137 | create_if_missing, temp_vec); |
| | 1138 | if (MB_SUCCESS != result) |
| | 1139 | return result; |
| | 1140 | |
| | 1141 | // If first iteration and input is empty, begin with first set of adjacencies |
| | 1142 | if (from_it == begin && adj_entities.empty()) { |
| | 1143 | adj_entities.swap( temp_vec ); |
| | 1144 | continue; |
| | 1145 | } |
| | 1146 | |
| | 1147 | // otherwise intersect with the current set of results |
| | 1148 | w_it = adj_it = adj_entities.begin(); |
| | 1149 | if (temp_vec.size()*adj_entities.size() < SORT_THRESHOLD) { |
| | 1150 | for (; adj_it != adj_entities.end(); ++adj_it) |
| | 1151 | if (std::find(temp_vec.begin(), temp_vec.end(), *adj_it) != temp_vec.end()) |
| | 1152 | { *w_it = *adj_it; ++w_it; } |
| | 1153 | } |
| | 1154 | else { |
| | 1155 | std::sort( temp_vec.begin(), temp_vec.end() ); |
| | 1156 | for (; adj_it != adj_entities.end(); ++adj_it) |
| | 1157 | if (std::binary_search(temp_vec.begin(), temp_vec.end(), *adj_it)) |
| | 1158 | { *w_it = *adj_it; ++w_it; } |
| | 1159 | } |
| | 1160 | adj_entities.erase( w_it, adj_entities.end() ); |
| | 1161 | |
| | 1162 | // we're intersecting, so if there are no more results, we're done |
| | 1163 | if (adj_entities.empty()) |
| | 1164 | break; |
| | 1165 | } |
| | 1166 | |
| | 1167 | return MB_SUCCESS; |
| | 1168 | } |
| | 1169 | |
| | 1170 | template <typename ITER> static |
| | 1171 | MBErrorCode get_adjacencies_intersection( MBCore* mb, |
| | 1172 | ITER begin, ITER end, |
| | 1173 | const int to_dimension, |
| | 1174 | const bool create_if_missing, |
| | 1175 | MBRange& adj_entities ) |
| | 1176 | { |
| | 1177 | std::vector<MBEntityHandle> results; |
| | 1178 | MBErrorCode rval = get_adjacencies_intersection( mb, begin, end, to_dimension, |
| | 1179 | create_if_missing, results ); |
| | 1180 | if (MB_SUCCESS != rval) |
| | 1181 | return rval; |
| | 1182 | |
| | 1183 | if (adj_entities.empty()) { |
| | 1184 | std::copy( results.begin(), results.end(), mb_range_inserter(adj_entities) ); |
| | 1185 | return MB_SUCCESS; |
| | 1186 | } |
| | 1187 | |
| | 1188 | MBRange::iterator it = adj_entities.begin(); |
| | 1189 | while (it != adj_entities.end()) { |
| | 1190 | if (std::find( results.begin(), results.end(), *it) == results.end()) |
| | 1191 | it = adj_entities.erase( it ); |
| | 1192 | else |
| | 1193 | ++it; |
| | 1194 | } |
| | 1195 | return MB_SUCCESS; |
| | 1196 | } |
| | 1197 | |
| 1067 | | |
| 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; |
| | 1216 | else if (operation_type == MBInterface::INTERSECT) |
| | 1217 | return get_adjacencies_intersection( this, from_entities, from_entities+num_entities, |
| | 1218 | to_dimension, create_if_missing, adj_entities ); |
| | 1219 | else if (operation_type != MBInterface::UNION) |
| | 1220 | return MB_FAILURE; |
| | 1221 | |
| | 1222 | // do union |
| | 1223 | std::vector<MBEntityHandle> tmp_storage; |
| | 1224 | const MBEntityHandle* conn; |
| | 1225 | int len; |
| 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 | | { |
| 1130 | | MBRange temp_range; |
| 1131 | | std::vector<MBEntityHandle> temp_vec; |
| 1132 | | std::vector<MBEntityHandle>::const_iterator adj_it; |
| 1133 | | MBErrorCode result = MB_SUCCESS, tmp_result; |
| 1134 | | |
| 1135 | | for (ITER from_it = begin; from_it != end; from_it++) |
| 1136 | | { |
| 1137 | | // running results kept in adj_entities; clear temp_vec and temp_range, which are working space |
| 1138 | | temp_vec.clear(); |
| 1139 | | temp_range.clear(); |
| 1140 | | |
| 1141 | | // get the next set of adjacencies |
| 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); |
| 1147 | | else |
| 1148 | | tmp_result = mb->a_entity_factory()->get_adjacencies(*from_it, to_dimension, |
| 1149 | | create_if_missing, temp_vec); |
| 1150 | | |
| 1151 | | if (MB_SUCCESS != tmp_result) result = tmp_result; |
| 1152 | | |
| 1153 | | std::sort( temp_vec.begin(), temp_vec.end() ); |
| 1154 | | |
| 1155 | | // if we're on the first iteration and we didn't come in with entities, |
| 1156 | | // just get the first results and move on |
| 1157 | | if (adj_entities.empty() && from_it == begin) { |
| 1158 | | std::copy(temp_vec.rbegin(), temp_vec.rend(), mb_range_inserter(adj_entities)); |
| 1159 | | continue; |
| 1160 | | } |
| 1161 | | |
| 1162 | | // operate on the vectors |
| 1163 | | MBRange::iterator hint = adj_entities.begin(); |
| 1164 | | if (operation_type == MBInterface::INTERSECT) { |
| 1165 | | adj_it = temp_vec.begin(); |
| 1166 | | while (hint != adj_entities.end()) { |
| 1167 | | while (adj_it != temp_vec.end() && *adj_it < *hint) |
| 1168 | | ++adj_it; |
| 1169 | | if (adj_it == temp_vec.end()) { |
| 1170 | | adj_entities.erase( hint, adj_entities.end() ); |
| 1171 | | break; |
| 1172 | | } |
| 1173 | | |
| 1174 | | if (*adj_it == *hint) |
| 1175 | | ++hint; |
| 1176 | | else |
| 1177 | | hint = adj_entities.erase(hint); |
| 1178 | | } |
| 1179 | | |
| 1180 | | // If doing INTERSECT and the current results are the empty set, |
| 1181 | | // then the final result must also be the empty set. |
| 1182 | | if (adj_entities.empty()) |
| 1183 | | return MB_SUCCESS; |
| 1184 | | } |
| 1185 | | else if (operation_type == MBInterface::UNION) { |
| 1186 | | for (adj_it = temp_vec.begin(); adj_it != temp_vec.end(); ++adj_it) |
| 1187 | | hint = adj_entities.insert( hint, *adj_it ); |
| 1188 | | } |
| 1189 | | } |
| 1190 | | |
| 1191 | | return result; |
| 1192 | | } |