MeshKit  1.0
primitives.cpp
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines