MeshKit
1.0
|
00001 /* 00002 * primitives.cpp 00003 * 00004 * Created on: Mar 22, 2010 00005 * Author: iulian 00006 */ 00007 00008 #include "primitives.h" 00009 00010 void filterValid(moab::Interface * mb, std::vector<moab::EntityHandle> & io) { 00011 int next = 0, size = io.size(); 00012 if (size==0) 00013 return; 00014 std::vector<unsigned char> tags(size); 00015 moab::ErrorCode rval = mb->tag_get_data(validTag, &io[0], size, &tags[0] ); 00016 if (moab::MB_SUCCESS != rval) 00017 return; 00018 for (int i = 0; i < size; i++) { 00019 //moab::EntityHandle eh = io[i]; 00020 if (tags[i]) { 00021 io[next++] = io[i]; 00022 } 00023 } 00024 if (next<size) 00025 io.resize(next); 00026 return; 00027 } 00028 00029 moab::ErrorCode contractionRegion(moab::Interface * mb, moab::EntityHandle v1, 00030 moab::EntityHandle v2, std::vector<moab::EntityHandle>& changed) { 00031 moab::EntityHandle vlist[2]; 00032 vlist[0] = v1; 00033 vlist[1] = v2; 00034 // it makes more sense to use vector, than range 00035 // the entities could be very disjoint at some point 00036 // moab::Range adj_ents; 00037 moab::ErrorCode rval = mb->get_adjacencies(vlist, 2, 2, false, changed, 00038 moab::Interface::UNION); 00039 if (opts.useDelayedDeletion) 00040 filterValid(mb, changed); 00041 return rval; 00042 } 00043 00044 // 00045 int classifyVertex(moab::Interface * mb, moab::EntityHandle v1) { 00046 // return 0, 1, or 2 if the vertex is interior, on the border, or 00047 // border only (corner) 00048 // to do 00049 std::vector<moab::EntityHandle> adjEdges; 00050 moab::ErrorCode rval = mb->get_adjacencies(&v1, 1, 1, false, adjEdges, 00051 moab::Interface::UNION); 00052 if (moab::MB_SUCCESS != rval) 00053 return 0; // interior?? 00054 if (opts.useDelayedDeletion) 00055 filterValid(mb, adjEdges); 00056 unsigned int nBorder = 0; 00057 for (unsigned int i = 0; i < adjEdges.size(); i++) { 00058 moab::EntityHandle edg = adjEdges[i]; 00059 std::vector<moab::EntityHandle> adjFaces; 00060 rval = mb->get_adjacencies(&edg, 1, 2, false, adjFaces, 00061 moab::Interface::UNION); 00062 if (opts.useDelayedDeletion) 00063 filterValid(mb, adjFaces); 00064 if (adjFaces.size() == 1) 00065 nBorder++; 00066 } 00067 if (nBorder == 0) 00068 return 0;// everything interior 00069 else if (nBorder == adjEdges.size()) 00070 return 2; 00071 else 00072 return 1; // some edges are interior 00073 } 00074 00075 Vec3 getVec3FromMBVertex(moab::Interface * mbi, moab::EntityHandle v) { 00076 double c[3]; 00077 mbi->get_coords(&v, 1, c); 00078 return Vec3(c[0], c[1], c[2]); 00079 } 00080 // every time we are getting the normal, we compute a new plane 00081 // maybe we should store it?? 00082 // No debate needed 00083 // it will be much cheaper to store it, for "-m" option 00084 // there, we will need it a lot 00085 Plane trianglePlane(moab::Interface * mb, moab::EntityHandle tri) { 00086 // retrieve it from tag 00087 Plane pl; 00088 mb->tag_get_data(planeDataTag, &tri, 1, &pl); 00089 return pl; 00090 } 00091 00092 void computeTrianglePlane (moab::Interface * mb, moab::EntityHandle tri) 00093 { 00094 // get connectivity of triangle 00095 const moab::EntityHandle * conn; 00096 int num_nodes; 00097 moab::ErrorCode rval = mb->get_connectivity(tri, conn, num_nodes); 00098 assert(3==num_nodes && rval == moab::MB_SUCCESS); 00099 Vec3 ve1 = getVec3FromMBVertex(mb, conn[0]); 00100 Vec3 ve2 = getVec3FromMBVertex(mb, conn[1]); 00101 Vec3 ve3 = getVec3FromMBVertex(mb, conn[2]); 00102 Plane pl = Plane(ve1, ve2, ve3); 00103 mb->tag_set_data(planeDataTag, &tri, 1, &pl); 00104 return; 00105 } 00106 00107 moab::ErrorCode contract(moab::Interface * mb, moab::EntityHandle v0, moab::EntityHandle v1, 00108 Vec3 & vnew, std::vector<moab::EntityHandle> & changed) { 00109 00110 // 00113 std::vector<moab::EntityHandle> adj_entities; 00114 contractionRegion(mb, v0, v1, adj_entities); 00115 // those are all triangles that are affected 00116 // find also all edges that are affect 00117 moab::EntityHandle vlist[2]; 00118 vlist[0] = v0; 00119 vlist[1] = v1; 00120 // it makes more sense to use vector, than range 00121 // the entities could be very disjoint at some point 00122 // moab::Range adj_ents; 00123 std::vector<moab::EntityHandle> edges; 00124 moab::ErrorCode rval = mb->get_adjacencies(vlist, 2, 1, false, edges, 00125 moab::Interface::UNION); 00126 if (moab::MB_SUCCESS != rval) return rval; 00127 if (opts.useDelayedDeletion) 00128 filterValid(mb, edges); 00129 if (opts.logfile && opts.selected_output & OUTPUT_CONTRACTIONS) { 00130 *opts.logfile << "Edges Adjacent:" << edges.size(); 00131 for (unsigned int i = 0; i < edges.size(); i++) 00132 *opts.logfile << " " << mb->id_from_handle(edges[i]); 00133 *opts.logfile << std::endl; 00134 } 00135 // we have the edges and the triangles that are affected 00136 // 2 situations 00137 // 1) edge v0 v1 is existing 00138 // we will delete edge (v0, v1), and triangles formed 00139 // with edge (v0, v1) 00140 // 2) edge v0 v1 is not existing, but due to proximity 00141 // only edges v2 v1 , v2, v0 will need to merge 00142 // more important is case 1) 00143 00144 // first, find edge v0, v1 00145 moab::EntityHandle ev0v1; 00146 int foundEdge = 0; 00147 for (unsigned int i = 0; i < edges.size(); i++) { 00148 moab::EntityHandle e = edges[i]; 00149 int nnodes; 00150 const moab::EntityHandle * conn2; 00151 mb->get_connectivity(e, conn2, nnodes); 00152 if (opts.logfile && opts.selected_output & OUTPUT_CONTRACTIONS) 00153 *opts.logfile << "Edge: " << mb->id_from_handle(e) << " nnodes:" 00154 << nnodes << " vertices:" << mb->id_from_handle(conn2[0]) 00155 << " " << mb->id_from_handle(conn2[1]) << std::endl; 00156 if ((conn2[0] == v0 && conn2[1] == v1) || (conn2[0] == v1 && conn2[1] 00157 == v0)) { 00158 foundEdge = 1; 00159 ev0v1 = e; // could be ev1v0, but who cares? 00160 if (opts.logfile && opts.selected_output & OUTPUT_CONTRACTIONS) 00161 *opts.logfile << "Edge found " << mb->id_from_handle(e) 00162 << std::endl; 00163 break; 00164 } 00165 00166 } 00167 // set the position of new vertices in vnew 00168 double newCoords[3]; 00169 newCoords[0] = vnew[0]; 00170 newCoords[1] = vnew[1]; 00171 newCoords[2] = vnew[2]; 00172 mb->set_coords(&v0, 1, newCoords); 00173 mb->set_coords(&v1, 1, newCoords); 00174 // although, vertex v1 will be deleted in the end; do we really need to set it? 00175 // yes, for merging purposes 00176 // 00177 00178 if (opts.useDelayedDeletion) { 00179 // big copy from version 3512 00180 // although vertex v1 will be merged!! 00181 std::vector<moab::EntityHandle> edgePairs; // the one that has v0 will 00182 // be kept 00183 std::vector<moab::EntityHandle> edgesWithV1; 00184 if (foundEdge) { 00185 // this is case 1, the most complicated 00186 // get triangles connected to edge ev0v1 00187 std::vector<moab::EntityHandle> tris; 00188 rval = mb->get_adjacencies(&ev0v1, 1, 2, false, tris, 00189 moab::Interface::UNION); 00190 if (moab::MB_SUCCESS != rval) return rval; 00191 filterValid(mb, tris); 00192 if (opts.logfile && opts.selected_output & OUTPUT_CONTRACTIONS) { 00193 *opts.logfile << "Triangles adjacent to found edge:" 00194 << tris.size() << ":"; 00195 for (unsigned int i = 0; i < tris.size(); i++) 00196 *opts.logfile << " " << mb->id_from_handle(tris[i]); 00197 *opts.logfile << std::endl; 00198 } 00199 for (unsigned int i = 0; i < tris.size(); i++) { 00200 moab::EntityHandle triangleThatCollapses = tris[i]; 00201 std::vector<moab::EntityHandle> localEdges; 00202 rval = mb->get_adjacencies(&triangleThatCollapses, 1, 1, false, 00203 localEdges, moab::Interface::UNION); 00204 if (moab::MB_SUCCESS != rval) return rval; 00205 filterValid(mb, localEdges); 00206 if (opts.logfile && opts.selected_output & OUTPUT_CONTRACTIONS) { 00207 *opts.logfile << "Triangle " << mb->id_from_handle( 00208 triangleThatCollapses) << " Edges: " 00209 << localEdges.size(); 00210 00211 for (unsigned int i = 0; i < localEdges.size(); i++) 00212 *opts.logfile << " " << mb->id_from_handle( 00213 localEdges[i]); 00214 *opts.logfile << std::endl; 00215 } 00216 // find the edges that contains v0 00217 moab::EntityHandle e[2];// the 2 edges e0, e1, that are not ev0v1; 00218 if (localEdges.size() != 3) 00219 return moab::MB_FAILURE; // failure 00220 int index = 0; 00221 for (int k = 0; k < 3; k++) 00222 if (localEdges[k] != ev0v1) 00223 e[index++] = localEdges[k]; 00224 // among those 2 edges, find out which one has v0, and which one v1 00225 if (index != 2) 00226 return moab::MB_FAILURE; // failure 00227 for (int j = 0; j < 2; j++) { 00228 int nn; 00229 const moab::EntityHandle * conn2; 00230 mb->get_connectivity(e[j], conn2, nn); 00231 if (conn2[0] == v0 || conn2[1] == v0) { 00232 // this is the edge that will be kept, the other one collapsed 00233 edgePairs.push_back(e[j]); 00234 //j = (j + 1) % 2;// the other one 00235 int j1 = (j + 1) % 2; // do not modify j, as someone might do something crazy 00236 // with that index in a for_loop (optimizations?) 00237 edgePairs.push_back(e[j1]); 00238 edgesWithV1.push_back(e[j1]); 00239 break; // no need to check the other one. it 00240 // will contain v1 00241 } 00242 } 00243 } 00244 // look at all triangles that are adjacent 00245 // invalidate first tris 00246 unsigned char invalid = 0; 00247 if (tris.size() > 0) 00248 { 00249 // set the invalid tag one by one, we do not want to create an array of invalids 00250 for (unsigned int k = 0; k < tris.size(); k++) 00251 { 00252 moab::EntityHandle ct = tris[k]; 00253 mb->tag_set_data(validTag, &ct, 1, &invalid); 00254 } 00255 } 00256 if (opts.logfile && opts.selected_output & OUTPUT_CONTRACTIONS) { 00257 *opts.logfile << "Triangles invalidated: " << tris.size() 00258 << ":"; 00259 for (unsigned int i = 0; i < tris.size(); i++) 00260 *opts.logfile << " " << mb->id_from_handle(tris[i]); 00261 *opts.logfile << std::endl; 00262 } 00263 // then look at all triangles that are not in tris (adj_entities), and then 00264 // replace connectivity of v1 with v0 00265 std::vector<moab::EntityHandle> trisChanged; 00266 for (unsigned int i = 0; i < adj_entities.size(); i++) { 00267 moab::EntityHandle tr = adj_entities[i]; 00268 if (!ehIsValid(tr)) 00269 continue; 00270 // see the connectivity of tr; if there is a v1, replace it with v0 00271 // will that propagate to edges? or do we have to set it separately? 00272 int nn; 00273 const moab::EntityHandle * conn3; 00274 mb->get_connectivity(tr, conn3, nn); 00275 00276 assert(3==nn); 00277 for (int j = 0; j < 3; j++) { 00278 if (conn3[j] == v1) { 00279 // replace it with v0, and reset it 00280 moab::EntityHandle connNew[3]; 00281 connNew[0] = conn3[0]; 00282 connNew[1] = conn3[1]; 00283 connNew[2] = conn3[2]; 00284 connNew[j] = v0; 00285 if (opts.logfile && opts.selected_output 00286 & OUTPUT_CONTRACTIONS) { 00287 std::vector<moab::EntityHandle> localEdges; 00288 rval = mb->get_adjacencies(&tr, 1, 1, false, 00289 localEdges, moab::Interface::UNION); 00290 if (moab::MB_SUCCESS != rval) return rval; 00291 filterValid(mb, localEdges); 00292 *opts.logfile << "Triangle t" 00293 << mb->id_from_handle(tr) 00294 << " filtered : " << localEdges.size(); 00295 for (unsigned int j = 0; j < localEdges.size(); j++) 00296 *opts.logfile << " e" << mb->id_from_handle( 00297 localEdges[j]); 00298 *opts.logfile << std::endl; 00299 } 00300 if (opts.logfile && opts.selected_output 00301 & OUTPUT_CONTRACTIONS) { 00302 *opts.logfile << "replace connectivity t" 00303 << mb->id_from_handle(tr) << " v" 00304 << mb->id_from_handle(conn3[0]) << " v" 00305 << mb->id_from_handle(conn3[1]) << " v" 00306 << mb->id_from_handle(conn3[2]) 00307 << " to: v"; 00308 } 00309 rval = mb->set_connectivity(tr, connNew, 3); 00310 if (moab::MB_SUCCESS != rval) return rval; 00311 if (opts.logfile && opts.selected_output 00312 & OUTPUT_CONTRACTIONS) { 00313 *opts.logfile << mb->id_from_handle(connNew[0]) 00314 << " v" << mb->id_from_handle(connNew[1]) 00315 << " v" << mb->id_from_handle(connNew[2]) 00316 << std::endl; 00317 } 00318 trisChanged.push_back(tr); 00319 } 00320 } 00321 00322 } 00323 validFaceCount -= tris.size(); 00324 rval = mb->tag_set_data(validTag, &ev0v1, 1, &invalid); 00325 if (moab::MB_SUCCESS != rval) return rval; 00326 // invalidate the edges connected for sure to v1 00327 if (edgesWithV1.size() > 0) 00328 { 00329 for(unsigned int k=0; k<edgesWithV1.size(); k++) 00330 { 00331 moab::EntityHandle eV1=edgesWithV1[k]; 00332 mb->tag_set_data(validTag, &eV1, 1, &invalid); 00333 } 00334 } 00335 // reset the connectivity of some edges (from v1 to v0) 00336 for (unsigned int i = 0; i < edges.size(); i++) { 00337 moab::EntityHandle e1 = edges[i]; 00338 if (!ehIsValid(e1)) // it could be the ones invalidated 00339 continue; 00340 00341 int nn; 00342 const moab::EntityHandle * conn; 00343 mb->get_connectivity(e1, conn, nn); 00344 00345 assert(2==nn); 00346 for (int j = 0; j < 2; j++) { 00347 if (conn[j] == v1) { 00348 // replace it with v0, and reset it 00349 moab::EntityHandle connNew[2]; 00350 connNew[0] = conn[0]; 00351 connNew[1] = conn[1]; 00352 connNew[j] = v0; 00353 if (opts.logfile && opts.selected_output 00354 & OUTPUT_CONTRACTIONS) { 00355 *opts.logfile << "replace connectivity edge: " 00356 << mb->id_from_handle(e1) << " " 00357 << mb->id_from_handle(conn[0]) << " " 00358 << mb->id_from_handle(conn[1]) << " to: "; 00359 } 00360 rval = mb->set_connectivity(e1, connNew, 2); 00361 if (moab::MB_SUCCESS != rval) return rval; 00362 if (opts.logfile && opts.selected_output 00363 & OUTPUT_CONTRACTIONS) { 00364 *opts.logfile << mb->id_from_handle(connNew[0]) 00365 << " " << mb->id_from_handle(connNew[1]) 00366 << std::endl; 00367 } 00368 } 00369 } 00370 } 00371 // the question: is the adjacency between triangles and edges restored? 00372 // yes, it is; check set_connectivity logic 00373 // we need to remove adjacencies between triangles and edges that are not valid 00374 // and add some more adjacencies to the edges that are now part of the triangle 00375 for (unsigned int i = 0; i < trisChanged.size(); i++) { 00376 // get adjacencies now, and bail out early; maybe we should create if missing 00377 std::vector<moab::EntityHandle> localEdges; 00378 moab::EntityHandle tr = trisChanged[i]; 00379 rval = mb->get_adjacencies(&tr, 1, 1, false, localEdges, 00380 moab::Interface::UNION); 00381 if (moab::MB_SUCCESS != rval) return rval; 00382 filterValid(mb, localEdges); 00383 if (opts.logfile && opts.selected_output & OUTPUT_CONTRACTIONS) { 00384 *opts.logfile << "Triangle t" << mb->id_from_handle(tr) 00385 << " filtered : " << localEdges.size(); 00386 for (unsigned int j = 0; j < localEdges.size(); j++) 00387 *opts.logfile << " e" << mb->id_from_handle( 00388 localEdges[j]); 00389 *opts.logfile << std::endl; 00390 } 00391 assert(localEdges.size()==3); 00392 } 00393 00394 filterValid(mb, adj_entities); 00395 changed = adj_entities; // deep copy 00396 if (opts.logfile && opts.selected_output & OUTPUT_CONTRACTIONS) { 00397 *opts.logfile << "Triangles changed:" << changed.size(); 00398 for (unsigned int i = 0; i < changed.size(); i++) 00399 *opts.logfile << " t" << mb->id_from_handle(changed[i]); 00400 *opts.logfile << std::endl; 00401 } 00402 } else // this should appear only when proximity limit > 0 00403 { 00404 // in this case, we only need to worry if vertex 0 and 1 are connected to the same 00405 // vertex 2; then we need to merge edges v0-v2 and v1 - v2 00406 // no triangles get deleted, only those edges; 00407 // the crack v0-v2-v1 gets seamed 00408 // get edges connected to vertex v0 00409 std::vector<moab::EntityHandle> edges0; 00410 rval = mb->get_adjacencies(&v0, 1, 1, false, edges0, 00411 moab::Interface::UNION); 00412 if (moab::MB_SUCCESS != rval) return rval; 00413 filterValid(mb, edges0); 00414 00415 // get edges connected to vertex v1 00416 std::vector<moab::EntityHandle> edges1; 00417 rval = mb->get_adjacencies(&v1, 1, 1, false, edges1, 00418 moab::Interface::UNION); 00419 if (moab::MB_SUCCESS != rval) return rval; 00420 filterValid(mb, edges1); 00421 // find all edges that will be merged, of type v0-v2 v1-v2 (so that they have a 00422 // common vertex v2 00423 // in that case, we will have to merge them as before, and delete the 00424 // one that contains v1 before 00425 // for sure, there is no edge from v0 to v1 !!! 00426 // keep all the vertices from edges1, different from v1 00427 std::vector<moab::EntityHandle> otherVertices1; 00428 for (unsigned int i = 0; i < edges1.size(); i++) { 00429 moab::EntityHandle edgeThatGoes = edges1[1]; 00430 // find the other vertex, not v1 00431 int nn; 00432 const moab::EntityHandle * conn2; 00433 mb->get_connectivity(edgeThatGoes, conn2, nn); 00434 int other = 0; 00435 if (conn2[0] == v1) 00436 other = 1; 00437 else if (conn2[1] == v1)// is this really necessary in a correct model? 00438 other = 0; 00439 otherVertices1.push_back(conn2[other]); 00440 } 00441 for (unsigned int i = 0; i < edges0.size(); i++) { 00442 moab::EntityHandle edgeThatStays = edges0[i]; 00443 // find the other vertex, not v0 00444 int nn; 00445 const moab::EntityHandle * conn2; 00446 mb->get_connectivity(edgeThatStays, conn2, nn); 00447 int other = 0; 00448 if (conn2[0] == v1) 00449 other = 1; 00450 else if (conn2[1] == v1)// is this really necessary in a correct model? 00451 other = 0; 00452 moab::EntityHandle v2 = conn2[other]; 00453 // let's see now if v2 is among vertices from otherVertices1 00454 for (unsigned int i1 = 0; i1 < otherVertices1.size(); i1++) { 00455 if (v2 == otherVertices1[i1]) { 00456 // we have a match, some work to do 00457 // invalidate the edge edges1[i1] 00458 unsigned char invalid = 0; 00459 mb->tag_set_data(validTag, &(edges1[i1]), 1, &invalid); 00460 break; // we stop looking for a match, only one possible 00461 } 00462 } 00463 } 00464 // triangles that need reconnected 00465 std::vector<moab::EntityHandle> tri1; 00466 rval = mb->get_adjacencies(&v1, 1, 2, false, tri1, 00467 moab::Interface::UNION); 00468 if (moab::MB_SUCCESS != rval) return rval; 00469 // start copy tri reconnect 00470 unsigned int i = 0; 00471 for (i=0; i < tri1.size(); i++) { 00472 moab::EntityHandle tr = tri1[i]; 00473 if (!ehIsValid(tr)) 00474 continue; 00475 // see the connectivity of tr; if there is a v1, replace it with v0 00476 // will that propagate to edges? or do we have to set it separately? 00477 int nn; 00478 const moab::EntityHandle * conn3; 00479 mb->get_connectivity(tr, conn3, nn); 00480 00481 assert(3==nn); 00482 for (int j = 0; j < 3; j++) { 00483 if (conn3[j] == v1) { 00484 // replace it with v0, and reset it 00485 moab::EntityHandle connNew[3]; 00486 connNew[0] = conn3[0]; 00487 connNew[1] = conn3[1]; 00488 connNew[2] = conn3[2]; 00489 connNew[j] = v0; 00490 rval = mb->set_connectivity(tr, connNew, 3); 00491 if (moab::MB_SUCCESS != rval) return rval; 00492 if (opts.logfile && opts.selected_output 00493 & OUTPUT_CONTRACTIONS) { 00494 *opts.logfile << mb->id_from_handle(connNew[0]) 00495 << " v" << mb->id_from_handle(connNew[1]) 00496 << " v" << mb->id_from_handle(connNew[2]) 00497 << std::endl; 00498 } 00499 } 00500 } 00501 00502 } 00503 // now reconnect edges1 that are still valid 00504 for (i = 0; i < edges1.size(); i++) { 00505 moab::EntityHandle e1 = edges1[i]; 00506 if (!ehIsValid(e1)) 00507 continue; 00508 // see the connectivity of e1; if there is a v1, replace it with v0 00509 // will that propagate to edges? or do we have to set it separately? 00510 int nn; 00511 const moab::EntityHandle * conn3; 00512 mb->get_connectivity(e1, conn3, nn); 00513 00514 assert(2==nn); 00515 for (int j = 0; j < 2; j++) { 00516 if (conn3[j] == v1) { 00517 // replace it with v0, and reset it 00518 moab::EntityHandle connNew[2]; 00519 connNew[0] = conn3[0]; 00520 connNew[1] = conn3[1]; 00521 connNew[j] = v0; 00522 rval = mb->set_connectivity(e1, connNew, 2); 00523 if (moab::MB_SUCCESS != rval) return rval; 00524 00525 } 00526 } 00527 00528 } 00529 // all the triangles connected to v0 are now changed, need recomputation 00530 // 00531 rval = mb->get_adjacencies(&v0, 1, 2, false, changed, 00532 moab::Interface::UNION); 00533 if (moab::MB_SUCCESS != rval) return rval; 00534 filterValid(mb, changed); 00535 00536 } 00537 // end big copy from version 3512 00538 } else { 00539 // vertex v1 will be merged!! 00540 std::vector<moab::EntityHandle> edgePairsToMerge; // the one that has v0 will 00541 // be kept 00542 if (foundEdge) { 00543 // this is case 1, the most complicated 00544 // get triangles connected to edge ev0v1 00545 std::vector<moab::EntityHandle> tris; 00546 rval = mb->get_adjacencies(&ev0v1, 1, 2, false, tris, 00547 moab::Interface::UNION); 00548 if (moab::MB_SUCCESS != rval) return rval; 00549 // find all edges that will be merged ( xv0, xv1, etc) 00550 if (opts.logfile && opts.selected_output & OUTPUT_CONTRACTIONS) { 00551 *opts.logfile << "Triangles adjacent to found edge:" 00552 << tris.size(); 00553 for (unsigned int i = 0; i < tris.size(); i++) 00554 *opts.logfile << " " << mb->id_from_handle(tris[i]); 00555 *opts.logfile << std::endl; 00556 } 00557 unsigned int i=0; 00558 for (i=0; i < tris.size(); i++) { 00559 moab::EntityHandle triangleThatCollapses = tris[i]; 00560 std::vector<moab::EntityHandle> localEdges; 00561 rval = mb->get_adjacencies(&triangleThatCollapses, 1, 1, false, 00562 localEdges, moab::Interface::UNION); 00563 if (moab::MB_SUCCESS != rval) return rval; 00564 if (opts.logfile && opts.selected_output & OUTPUT_CONTRACTIONS) { 00565 *opts.logfile << "Triangle " << mb->id_from_handle( 00566 triangleThatCollapses) << " Edges: " 00567 << localEdges.size(); 00568 00569 for (unsigned int i = 0; i < localEdges.size(); i++) 00570 *opts.logfile << " " << mb->id_from_handle( 00571 localEdges[i]); 00572 *opts.logfile << std::endl; 00573 } 00574 // find the edges that contains v0 00575 moab::EntityHandle e[2];// the 2 edges e0, e1, that are not ev0v1; 00576 if (localEdges.size() != 3) 00577 return moab::MB_FAILURE; // failure 00578 int index = 0; 00579 for (int k = 0; k < 3; k++) 00580 if (localEdges[k] != ev0v1) 00581 e[index++] = localEdges[k]; 00582 // among those 2 edges, find out which one has v0, and which one v1 00583 if (index != 2) 00584 return moab::MB_FAILURE; // failure 00585 for (int j = 0; j < 2; j++) { 00586 int nn; 00587 const moab::EntityHandle * conn2; 00588 mb->get_connectivity(e[j], conn2, nn); 00589 if (conn2[0] == v0 || conn2[1] == v0) { 00590 // this is the edge that will be kept, the other one collapsed 00591 edgePairsToMerge.push_back(e[j]); 00592 //j = (j + 1) % 2; 00593 int j1 = (j + 1)%2;// do not modify original j 00594 edgePairsToMerge.push_back(e[j1]); 00595 break; // no need to check the other one. it 00596 // will contain v1 00597 } 00598 } 00599 } 00600 // first merge vertices v0 and v1 : will also NOT delete v1 (yet) 00601 // the tag on v1 will be deleted too, and we do not want that, at least until 00602 // after the merging of edges, and deleting the pair 00603 rval = mb->merge_entities(v0, v1, false, false); 00604 if (moab::MB_SUCCESS != rval) return rval; 00605 // merge edgePairsToMerge // now, v0 and v1 should be collapsed! 00606 for (unsigned int j = 0; j < edgePairsToMerge.size(); j += 2) { 00607 // will also delete edges that contained v1 before 00608 if (opts.logfile && opts.selected_output & OUTPUT_CONTRACTIONS) 00609 *opts.logfile << "Edges merged:" << mb->id_from_handle( 00610 edgePairsToMerge[j]) << " " << mb->id_from_handle( 00611 edgePairsToMerge[j + 1]) << std::endl; 00612 mb->merge_entities(edgePairsToMerge[j], 00613 edgePairsToMerge[j + 1], false, true); 00614 00615 } 00616 // the only things that need deleted are triangles 00617 if (opts.logfile && opts.selected_output & OUTPUT_CONTRACTIONS) { 00618 *opts.logfile << "Triangles invalidated:" << tris.size(); 00619 for (unsigned int i = 0; i < tris.size(); i++) 00620 *opts.logfile << " " << mb->id_from_handle(tris[i]); 00621 *opts.logfile << std::endl; 00622 } 00623 rval = mb->delete_entities(&(tris[0]), tris.size()); 00624 if (moab::MB_SUCCESS != rval) return rval; 00625 if (iniSet) 00626 mb->remove_entities(iniSet, &(tris[0]), tris.size()); 00627 validFaceCount -= tris.size(); 00628 // hopefully, all adjacencies are preserved 00629 // delete now the edge ev0v1 00630 if (opts.logfile && opts.selected_output & OUTPUT_CONTRACTIONS) 00631 *opts.logfile << "Edge invalidated" 00632 << mb->id_from_handle(ev0v1) << std::endl; 00633 rval = mb->delete_entities(&ev0v1, 1); 00634 if (moab::MB_SUCCESS != rval) return rval; 00635 if (iniSet) 00636 mb->remove_entities(iniSet, &ev0v1, 1);// it may not be part of it, but 00637 // delete it anyway 00638 // among adj_entities, remove the tris triangles, and return them 00639 for (unsigned int j = 0; j < adj_entities.size(); j++) { 00640 moab::EntityHandle F = adj_entities[j]; 00641 int inTris = 0; 00642 for (unsigned int k = 0; k < tris.size(); k++) 00643 if (F == tris[k]) { 00644 inTris = 1; 00645 break; 00646 } 00647 if (!inTris) 00648 changed.push_back(F); 00649 } 00650 if (opts.logfile && opts.selected_output & OUTPUT_CONTRACTIONS) { 00651 *opts.logfile << "Triangles changed:" << changed.size(); 00652 for (unsigned int i = 0; i < changed.size(); i++) 00653 *opts.logfile << " " << mb->id_from_handle(changed[i]); 00654 *opts.logfile << std::endl; 00655 } 00656 00657 } else // this should appear only when proximity limit > 0 00658 { 00659 // in this case, we only need to worry if vertex 0 and 1 are connected to the same 00660 // vertex 2; then we need to merge edges v0-v2 and v1 - v2 00661 // no triangles get deleted, only those edges 00662 // get edges connected to vertex v0 00663 std::vector<moab::EntityHandle> edges0; 00664 rval = mb->get_adjacencies(&v0, 1, 1, false, edges0, 00665 moab::Interface::UNION); 00666 if (moab::MB_SUCCESS != rval) return rval; 00667 00668 // get edges connected to vertex v1 00669 std::vector<moab::EntityHandle> edges1; 00670 rval = mb->get_adjacencies(&v1, 1, 1, false, edges1, 00671 moab::Interface::UNION); 00672 if (moab::MB_SUCCESS != rval) return rval; 00673 // find all edges that will be merged, of type v0-v2 v1-v2 (so that they have a 00674 // common vertex v2 00675 // in that case, we will have to merge them as before, and delete the 00676 // one that contains v1 before 00677 // for sure, there is no edge from v0 to v1 !!! 00678 // keep all the vertices from edges1, different from v1 00679 std::vector<moab::EntityHandle> otherVertices1; 00680 for (unsigned int i1 = 0; i1 < edges1.size(); i1++) { 00681 moab::EntityHandle edgeThatGoes = edges1[i1]; 00682 // find the other vertex, not v1 00683 int nn; 00684 const moab::EntityHandle * conn2; 00685 mb->get_connectivity(edgeThatGoes, conn2, nn); 00686 int other = 0; 00687 if (conn2[0] == v1) 00688 other = 1; 00689 else if (conn2[1] == v1)// is this really necessary in a correct model? 00690 other = 0; 00691 otherVertices1.push_back(conn2[other]); 00692 } 00693 for (unsigned int i = 0; i < edges0.size(); i++) { 00694 moab::EntityHandle edgeThatStays = edges0[i]; 00695 // find the other vertex, not v0 00696 int nn; 00697 const moab::EntityHandle * conn2; 00698 mb->get_connectivity(edgeThatStays, conn2, nn); 00699 int other = 0; 00700 if (conn2[0] == v1) 00701 other = 1; 00702 else if (conn2[1] == v1)// is this really necessary in a correct model? 00703 other = 0; 00704 moab::EntityHandle v2 = conn2[other]; 00705 // let's see now if v2 is among vertices from otherVertices1 00706 // if yes, then we have a match, edges that need collapsed 00707 for (unsigned int i1 = 0; i1 < otherVertices1.size(); i1++) { 00708 if (v2 == otherVertices1[i1]) { 00709 // we have a match, some work to do 00710 edgePairsToMerge.push_back(edgeThatStays); 00711 edgePairsToMerge.push_back(edges1[i1]); 00712 break; // we stopp looking for a match, only one possible 00713 } 00714 } 00715 } 00716 00717 // first merge vertices v0 and v1 : will also NOT delete v1 (yet) 00718 // the tag on v1 will be deleted too, and we do not want that, at least until 00719 // after the merging of edges, and deleting the pair 00720 rval = mb->merge_entities(v0, v1, false, false); 00721 if (moab::MB_SUCCESS != rval) return rval; 00722 // merge edgePairsToMerge // now, v0 and v1 should be collapsed! 00723 for (unsigned int j = 0; j < edgePairsToMerge.size(); j += 2) { 00724 // will also delete edges that contained v1 before 00725 mb->merge_entities(edgePairsToMerge[j], 00726 edgePairsToMerge[j + 1], false, true); 00727 } 00728 // all the triangles connected to v0 are now changed, need recomputation 00729 // 00730 rval = mb->get_adjacencies(&v0, 1, 2, false, changed, 00731 moab::Interface::UNION); 00732 if (moab::MB_SUCCESS != rval) return rval; 00733 00734 } 00735 } 00736 return moab::MB_SUCCESS; 00737 00738 } 00739