LCOV - code coverage report
Current view: top level - algs/Qslim - primitives.cpp (source / functions) Hit Total Coverage
Test: coverage_sk.info Lines: 159 443 35.9 %
Date: 2020-07-01 15:24:36 Functions: 8 9 88.9 %
Branches: 159 1004 15.8 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * primitives.cpp
       3                 :            :  *
       4                 :            :  *  Created on: Mar 22, 2010
       5                 :            :  *      Author: iulian
       6                 :            :  */
       7                 :            : 
       8                 :            : #include "primitives.h"
       9                 :            : 
      10                 :      65628 : void filterValid(moab::Interface * mb, std::vector<moab::EntityHandle> & io) {
      11                 :      65628 :         int next = 0, size = io.size();
      12         [ -  + ]:      65628 :         if (size==0)
      13                 :          0 :           return;
      14         [ +  - ]:      65628 :         std::vector<unsigned char> tags(size);
      15 [ +  - ][ +  - ]:      65628 :         moab::ErrorCode rval = mb->tag_get_data(validTag, &io[0], size, &tags[0] );
                 [ +  - ]
      16         [ -  + ]:      65628 :         if (moab::MB_SUCCESS != rval)
      17                 :          0 :                         return;
      18         [ +  + ]:     800422 :         for (int i = 0; i < size; i++) {
      19                 :            :                 //moab::EntityHandle eh = io[i];
      20 [ +  - ][ +  + ]:     734794 :                 if (tags[i]) {
      21 [ +  - ][ +  - ]:     629382 :                         io[next++] = io[i];
      22                 :            :                 }
      23                 :            :         }
      24         [ +  + ]:      65628 :         if (next<size)
      25         [ +  - ]:      28488 :                 io.resize(next);
      26                 :      65628 :         return;
      27                 :            : }
      28                 :            : 
      29                 :      61160 : moab::ErrorCode contractionRegion(moab::Interface * mb, moab::EntityHandle v1,
      30                 :            :                 moab::EntityHandle v2, std::vector<moab::EntityHandle>& changed) {
      31                 :            :         moab::EntityHandle vlist[2];
      32                 :      61160 :         vlist[0] = v1;
      33                 :      61160 :         vlist[1] = v2;
      34                 :            :         // it makes more sense to use vector, than range
      35                 :            :         //  the entities could be very disjoint at some point
      36                 :            :         // moab::Range adj_ents;
      37                 :            :         moab::ErrorCode rval = mb->get_adjacencies(vlist, 2, 2, false, changed,
      38         [ +  - ]:      61160 :                         moab::Interface::UNION);
      39         [ +  - ]:      61160 :         if (opts.useDelayedDeletion)
      40         [ +  - ]:      61160 :                 filterValid(mb, changed);
      41                 :      61160 :         return rval;
      42                 :            : }
      43                 :            : 
      44                 :            : //
      45                 :          0 : int classifyVertex(moab::Interface * mb, moab::EntityHandle v1) {
      46                 :            :         // return 0, 1, or 2 if the vertex is interior, on the border, or
      47                 :            :         // border only (corner)
      48                 :            :         // to do
      49         [ #  # ]:          0 :         std::vector<moab::EntityHandle> adjEdges;
      50                 :            :         moab::ErrorCode rval = mb->get_adjacencies(&v1, 1, 1, false, adjEdges,
      51         [ #  # ]:          0 :                         moab::Interface::UNION);
      52         [ #  # ]:          0 :         if (moab::MB_SUCCESS != rval)
      53                 :          0 :                 return 0; // interior??
      54         [ #  # ]:          0 :         if (opts.useDelayedDeletion)
      55         [ #  # ]:          0 :                 filterValid(mb, adjEdges);
      56                 :          0 :         unsigned int nBorder = 0;
      57         [ #  # ]:          0 :         for (unsigned int i = 0; i < adjEdges.size(); i++) {
      58         [ #  # ]:          0 :                 moab::EntityHandle edg = adjEdges[i];
      59         [ #  # ]:          0 :                 std::vector<moab::EntityHandle> adjFaces;
      60                 :            :                 rval = mb->get_adjacencies(&edg, 1, 2, false, adjFaces,
      61         [ #  # ]:          0 :                                 moab::Interface::UNION);
      62         [ #  # ]:          0 :                 if (opts.useDelayedDeletion)
      63         [ #  # ]:          0 :                         filterValid(mb, adjFaces);
      64         [ #  # ]:          0 :                 if (adjFaces.size() == 1)
      65                 :          0 :                         nBorder++;
      66                 :          0 :         }
      67         [ #  # ]:          0 :         if (nBorder == 0)
      68                 :          0 :                 return 0;// everything interior
      69         [ #  # ]:          0 :         else if (nBorder == adjEdges.size())
      70                 :          0 :                 return 2;
      71                 :            :         else
      72                 :          0 :                 return 1; // some edges are interior
      73                 :            : }
      74                 :            : 
      75                 :    1154548 : Vec3 getVec3FromMBVertex(moab::Interface * mbi, moab::EntityHandle v) {
      76                 :            :         double c[3];
      77         [ +  - ]:    1154548 :         mbi->get_coords(&v, 1, c);
      78         [ +  - ]:    1154548 :         return Vec3(c[0], c[1], c[2]);
      79                 :            : }
      80                 :            : // every time we are getting the normal, we compute a new plane
      81                 :            : // maybe we should store it??
      82                 :            : //  No debate needed
      83                 :            : // it will be much cheaper to store it, for "-m" option
      84                 :            : // there, we will need it a lot
      85                 :      10400 : Plane trianglePlane(moab::Interface * mb, moab::EntityHandle tri) {
      86                 :            :         // retrieve it from tag
      87                 :      10400 :         Plane pl;
      88                 :      10400 :         mb->tag_get_data(planeDataTag, &tri, 1, &pl);
      89                 :      10400 :         return pl;
      90                 :            : }
      91                 :            : 
      92                 :      10000 : void computeTrianglePlane (moab::Interface * mb, moab::EntityHandle tri)
      93                 :            : {
      94                 :            :         // get connectivity of triangle
      95                 :            :         const moab::EntityHandle * conn;
      96                 :            :         int num_nodes;
      97         [ +  - ]:      10000 :         moab::ErrorCode rval = mb->get_connectivity(tri, conn, num_nodes);
      98 [ +  - ][ -  + ]:      10000 :           assert(3==num_nodes && rval == moab::MB_SUCCESS);
                 [ #  # ]
      99         [ +  - ]:      10000 :         Vec3 ve1 = getVec3FromMBVertex(mb, conn[0]);
     100         [ +  - ]:      10000 :         Vec3 ve2 = getVec3FromMBVertex(mb, conn[1]);
     101         [ +  - ]:      10000 :         Vec3 ve3 = getVec3FromMBVertex(mb, conn[2]);
     102         [ +  - ]:      10000 :         Plane pl = Plane(ve1, ve2, ve3);
     103         [ +  - ]:      10000 :         mb->tag_set_data(planeDataTag, &tri, 1, &pl);
     104                 :      10000 :         return;
     105                 :            : }
     106                 :            : 
     107                 :        544 : moab::ErrorCode contract(moab::Interface * mb, moab::EntityHandle v0, moab::EntityHandle v1,
     108                 :            :                 Vec3 & vnew, std::vector<moab::EntityHandle> & changed) {
     109                 :            : 
     110                 :            :         //
     111                 :            :         //// Collect all the faces that are going to be changed
     112                 :            :         ////
     113         [ +  - ]:        544 :         std::vector<moab::EntityHandle> adj_entities;
     114         [ +  - ]:        544 :         contractionRegion(mb, v0, v1, adj_entities);
     115                 :            :         // those are all triangles that are affected
     116                 :            :         // find also all edges that are affect
     117                 :            :         moab::EntityHandle vlist[2];
     118                 :        544 :         vlist[0] = v0;
     119                 :        544 :         vlist[1] = v1;
     120                 :            :         // it makes more sense to use vector, than range
     121                 :            :         //  the entities could be very disjoint at some point
     122                 :            :         // moab::Range adj_ents;
     123         [ +  - ]:       1088 :         std::vector<moab::EntityHandle> edges;
     124                 :            :         moab::ErrorCode rval = mb->get_adjacencies(vlist, 2, 1, false, edges,
     125         [ +  - ]:        544 :                         moab::Interface::UNION);
     126         [ -  + ]:        544 :         if (moab::MB_SUCCESS != rval) return rval;
     127         [ +  - ]:        544 :         if (opts.useDelayedDeletion)
     128         [ +  - ]:        544 :                 filterValid(mb, edges);
     129 [ -  + ][ #  # ]:        544 :         if (opts.logfile && opts.selected_output & OUTPUT_CONTRACTIONS) {
     130 [ #  # ][ #  # ]:          0 :                 *opts.logfile << "Edges Adjacent:" << edges.size();
     131         [ #  # ]:          0 :                 for (unsigned int i = 0; i < edges.size(); i++)
     132 [ #  # ][ #  # ]:          0 :                         *opts.logfile << " " << mb->id_from_handle(edges[i]);
         [ #  # ][ #  # ]
     133         [ #  # ]:          0 :                 *opts.logfile << std::endl;
     134                 :            :         }
     135                 :            :         // we have the edges and the triangles that are affected
     136                 :            :         // 2 situations
     137                 :            :         //   1) edge v0 v1 is existing
     138                 :            :         //      we will delete edge (v0, v1), and triangles formed
     139                 :            :         //       with edge (v0, v1)
     140                 :            :         //   2) edge v0 v1 is not existing, but due to proximity
     141                 :            :         //      only edges v2 v1 , v2, v0 will need to merge
     142                 :            :         // more important is case 1)
     143                 :            : 
     144                 :            :         // first, find edge v0, v1
     145                 :            :         moab::EntityHandle ev0v1;
     146                 :        544 :         int foundEdge = 0;
     147         [ +  - ]:       3596 :         for (unsigned int i = 0; i < edges.size(); i++) {
     148         [ +  - ]:       3596 :                 moab::EntityHandle e = edges[i];
     149                 :            :                 int nnodes;
     150                 :            :                 const moab::EntityHandle * conn2;
     151         [ +  - ]:       3596 :                 mb->get_connectivity(e, conn2, nnodes);
     152 [ -  + ][ #  # ]:       3596 :                 if (opts.logfile && opts.selected_output & OUTPUT_CONTRACTIONS)
     153 [ #  # ][ #  # ]:          0 :                         *opts.logfile << "Edge: " << mb->id_from_handle(e) << " nnodes:"
         [ #  # ][ #  # ]
     154 [ #  # ][ #  # ]:          0 :                                         << nnodes << " vertices:" << mb->id_from_handle(conn2[0])
         [ #  # ][ #  # ]
     155 [ #  # ][ #  # ]:          0 :                                         << " " << mb->id_from_handle(conn2[1]) << std::endl;
         [ #  # ][ #  # ]
     156 [ +  + ][ +  + ]:       3596 :                 if ((conn2[0] == v0 && conn2[1] == v1) || (conn2[0] == v1 && conn2[1]
         [ +  + ][ +  + ]
     157                 :        728 :                                 == v0)) {
     158                 :        544 :                         foundEdge = 1;
     159                 :        544 :                         ev0v1 = e; // could be ev1v0, but who cares?
     160 [ -  + ][ #  # ]:        544 :                         if (opts.logfile && opts.selected_output & OUTPUT_CONTRACTIONS)
     161 [ #  # ][ #  # ]:          0 :                                 *opts.logfile << "Edge found " << mb->id_from_handle(e)
                 [ #  # ]
     162         [ #  # ]:          0 :                                                 << std::endl;
     163                 :        544 :                         break;
     164                 :            :                 }
     165                 :            : 
     166                 :            :         }
     167                 :            :         // set the position of new vertices in vnew
     168                 :            :         double newCoords[3];
     169         [ +  - ]:        544 :         newCoords[0] = vnew[0];
     170         [ +  - ]:        544 :         newCoords[1] = vnew[1];
     171         [ +  - ]:        544 :         newCoords[2] = vnew[2];
     172         [ +  - ]:        544 :         mb->set_coords(&v0, 1, newCoords);
     173         [ +  - ]:        544 :         mb->set_coords(&v1, 1, newCoords);
     174                 :            :         // although, vertex v1 will be deleted in the end; do we really need to set it?
     175                 :            :         // yes, for merging purposes
     176                 :            :         //
     177                 :            : 
     178         [ +  - ]:        544 :         if (opts.useDelayedDeletion) {
     179                 :            :                 // big copy from version 3512
     180                 :            :                 // although vertex v1 will be merged!!
     181         [ +  - ]:        544 :                 std::vector<moab::EntityHandle> edgePairs; // the one that has v0 will
     182                 :            :                 // be kept
     183 [ +  - ][ +  - ]:       1088 :                 std::vector<moab::EntityHandle> edgesWithV1;
     184         [ +  - ]:        544 :                 if (foundEdge) {
     185                 :            :                         // this is case 1, the most complicated
     186                 :            :                         // get triangles connected to edge ev0v1
     187         [ +  - ]:        544 :                         std::vector<moab::EntityHandle> tris;
     188                 :            :                         rval = mb->get_adjacencies(&ev0v1, 1, 2, false, tris,
     189         [ +  - ]:        544 :                                         moab::Interface::UNION);
     190         [ -  + ]:        544 :                               if (moab::MB_SUCCESS != rval) return rval;
     191         [ +  - ]:        544 :                         filterValid(mb, tris);
     192 [ -  + ][ #  # ]:        544 :                         if (opts.logfile && opts.selected_output & OUTPUT_CONTRACTIONS) {
     193         [ #  # ]:          0 :                                 *opts.logfile << "Triangles adjacent to found edge:"
     194 [ #  # ][ #  # ]:          0 :                                                 << tris.size() << ":";
     195         [ #  # ]:          0 :                                 for (unsigned int i = 0; i < tris.size(); i++)
     196 [ #  # ][ #  # ]:          0 :                                         *opts.logfile << " " << mb->id_from_handle(tris[i]);
         [ #  # ][ #  # ]
     197         [ #  # ]:          0 :                                 *opts.logfile << std::endl;
     198                 :            :                         }
     199         [ +  + ]:       1546 :                         for (unsigned int i = 0; i < tris.size(); i++) {
     200         [ +  - ]:       1002 :                                 moab::EntityHandle triangleThatCollapses = tris[i];
     201         [ +  - ]:       1002 :                                 std::vector<moab::EntityHandle> localEdges;
     202                 :            :                                 rval = mb->get_adjacencies(&triangleThatCollapses, 1, 1, false,
     203         [ +  - ]:       1002 :                                                 localEdges, moab::Interface::UNION);
     204         [ -  + ]:       1002 :                                         if (moab::MB_SUCCESS != rval) return rval;
     205         [ +  - ]:       1002 :                                 filterValid(mb, localEdges);
     206 [ -  + ][ #  # ]:       1002 :                                 if (opts.logfile && opts.selected_output & OUTPUT_CONTRACTIONS) {
     207         [ #  # ]:          0 :                                         *opts.logfile << "Triangle " << mb->id_from_handle(
     208 [ #  # ][ #  # ]:          0 :                                                         triangleThatCollapses) << " Edges: "
                 [ #  # ]
     209         [ #  # ]:          0 :                                                         << localEdges.size();
     210                 :            : 
     211         [ #  # ]:          0 :                                         for (unsigned int i = 0; i < localEdges.size(); i++)
     212         [ #  # ]:          0 :                                                 *opts.logfile << " " << mb->id_from_handle(
     213 [ #  # ][ #  # ]:          0 :                                                                 localEdges[i]);
                 [ #  # ]
     214         [ #  # ]:          0 :                                         *opts.logfile << std::endl;
     215                 :            :                                 }
     216                 :            :                                 // find the edges that contains v0
     217                 :            :                                 moab::EntityHandle e[2];// the 2 edges e0, e1, that are not ev0v1;
     218         [ -  + ]:       1002 :                                 if (localEdges.size() != 3)
     219                 :          0 :                                         return moab::MB_FAILURE; // failure
     220                 :       1002 :                                 int index = 0;
     221         [ +  + ]:       4008 :                                 for (int k = 0; k < 3; k++)
     222 [ +  - ][ +  + ]:       3006 :                                         if (localEdges[k] != ev0v1)
     223         [ +  - ]:       2004 :                                                 e[index++] = localEdges[k];
     224                 :            :                                 // among those 2 edges, find out which one has v0, and which one v1
     225         [ -  + ]:       1002 :                                 if (index != 2)
     226                 :          0 :                                         return moab::MB_FAILURE; // failure
     227 [ +  - ][ +  - ]:       2554 :                                 for (int j = 0; j < 2; j++) {
     228                 :            :                                         int nn;
     229                 :            :                                         const moab::EntityHandle * conn2;
     230         [ +  - ]:       1552 :                                         mb->get_connectivity(e[j], conn2, nn);
     231 [ +  + ][ +  + ]:       1552 :                                         if (conn2[0] == v0 || conn2[1] == v0) {
     232                 :            :                                                 // this is the edge that will be kept, the other one collapsed
     233         [ +  - ]:       1002 :                                                 edgePairs.push_back(e[j]);
     234                 :            :                                                 //j = (j + 1) % 2;// the other one
     235                 :       1002 :                                                 int j1 = (j + 1) % 2; //  do not modify j, as someone might do something crazy
     236                 :            :                                                 // with that index in a for_loop (optimizations?)
     237         [ +  - ]:       1002 :                                                 edgePairs.push_back(e[j1]);
     238         [ +  - ]:       1002 :                                                 edgesWithV1.push_back(e[j1]);
     239                 :       1002 :                                                 break; // no need to check the other one. it
     240                 :            :                                                 // will contain v1
     241                 :            :                                         }
     242                 :            :                                 }
     243                 :       1002 :                         }
     244                 :            :                         // look at all triangles that are adjacent
     245                 :            :                         // invalidate first tris
     246                 :        544 :                         unsigned char invalid = 0;
     247         [ +  + ]:        544 :                         if (tris.size() > 0)
     248                 :            :       {
     249                 :            :         // set the invalid tag one by one, we do not want to create an array of invalids
     250         [ +  + ]:       1544 :         for (unsigned int k = 0; k < tris.size(); k++)
     251                 :            :         {
     252         [ +  - ]:       1002 :           moab::EntityHandle ct = tris[k];
     253         [ +  - ]:       1002 :           mb->tag_set_data(validTag, &ct, 1, &invalid);
     254                 :            :         }
     255                 :            :       }
     256 [ -  + ][ #  # ]:        544 :                         if (opts.logfile && opts.selected_output & OUTPUT_CONTRACTIONS) {
     257 [ #  # ][ #  # ]:          0 :                                 *opts.logfile << "Triangles invalidated: " << tris.size()
     258         [ #  # ]:          0 :                                                 << ":";
     259         [ #  # ]:          0 :                                 for (unsigned int i = 0; i < tris.size(); i++)
     260 [ #  # ][ #  # ]:          0 :                                         *opts.logfile << " " << mb->id_from_handle(tris[i]);
         [ #  # ][ #  # ]
     261         [ #  # ]:          0 :                                 *opts.logfile << std::endl;
     262                 :            :                         }
     263                 :            :                         // then look at all triangles that are not in tris (adj_entities), and then
     264                 :            :                         // replace connectivity of v1 with v0
     265 [ +  - ][ +  - ]:       1088 :                         std::vector<moab::EntityHandle> trisChanged;
     266         [ +  + ]:       6034 :                         for (unsigned int i = 0; i < adj_entities.size(); i++) {
     267         [ +  - ]:       5490 :                                 moab::EntityHandle tr = adj_entities[i];
     268 [ +  - ][ +  + ]:       5490 :                                 if (!ehIsValid(tr))
     269                 :       1002 :                                         continue;
     270                 :            :                                 // see the connectivity of tr; if there is a v1, replace it with v0
     271                 :            :                                 // will that propagate to edges? or do we have to set it separately?
     272                 :            :                                 int nn;
     273                 :            :                                 const moab::EntityHandle * conn3;
     274         [ +  - ]:       4488 :                                 mb->get_connectivity(tr, conn3, nn);
     275                 :            : 
     276 [ -  + ][ #  # ]:       4488 :                                 assert(3==nn);
     277         [ +  + ]:      17952 :                                 for (int j = 0; j < 3; j++) {
     278         [ +  + ]:      13464 :                                         if (conn3[j] == v1) {
     279                 :            :                                                 // replace it with v0, and reset it
     280                 :            :                                                 moab::EntityHandle connNew[3];
     281                 :       1834 :                                                 connNew[0] = conn3[0];
     282                 :       1834 :                                                 connNew[1] = conn3[1];
     283                 :       1834 :                                                 connNew[2] = conn3[2];
     284                 :       1834 :                                                 connNew[j] = v0;
     285 [ -  + ][ #  # ]:       1834 :                                                 if (opts.logfile && opts.selected_output
     286                 :          0 :                                                                 & OUTPUT_CONTRACTIONS) {
     287         [ #  # ]:          0 :                                                         std::vector<moab::EntityHandle> localEdges;
     288                 :            :                                                         rval = mb->get_adjacencies(&tr, 1, 1, false,
     289         [ #  # ]:          0 :                                                                         localEdges, moab::Interface::UNION);
     290         [ #  # ]:          0 :                                                                       if (moab::MB_SUCCESS != rval) return rval;
     291         [ #  # ]:          0 :                                                         filterValid(mb, localEdges);
     292         [ #  # ]:          0 :                                                         *opts.logfile << "Triangle t"
     293 [ #  # ][ #  # ]:          0 :                                                                         << mb->id_from_handle(tr)
     294 [ #  # ][ #  # ]:          0 :                                                                         << "  filtered : " << localEdges.size();
     295         [ #  # ]:          0 :                                                         for (unsigned int j = 0; j < localEdges.size(); j++)
     296         [ #  # ]:          0 :                                                                 *opts.logfile << " e" << mb->id_from_handle(
     297 [ #  # ][ #  # ]:          0 :                                                                                 localEdges[j]);
                 [ #  # ]
     298 [ #  # ][ #  # ]:          0 :                                                         *opts.logfile << std::endl;
     299                 :            :                                                 }
     300 [ -  + ][ #  # ]:       1834 :                                                 if (opts.logfile && opts.selected_output
     301                 :          0 :                                                                 & OUTPUT_CONTRACTIONS) {
     302         [ #  # ]:          0 :                                                         *opts.logfile << "replace connectivity t"
     303 [ #  # ][ #  # ]:          0 :                                                                         << mb->id_from_handle(tr) << " v"
                 [ #  # ]
     304 [ #  # ][ #  # ]:          0 :                                                                         << mb->id_from_handle(conn3[0]) << " v"
                 [ #  # ]
     305 [ #  # ][ #  # ]:          0 :                                                                         << mb->id_from_handle(conn3[1]) << " v"
                 [ #  # ]
     306 [ #  # ][ #  # ]:          0 :                                                                         << mb->id_from_handle(conn3[2])
     307         [ #  # ]:          0 :                                                                         << "  to: v";
     308                 :            :                                                 }
     309         [ +  - ]:       1834 :                                                 rval = mb->set_connectivity(tr, connNew, 3);
     310         [ -  + ]:       1834 :                                                             if (moab::MB_SUCCESS != rval) return rval;
     311 [ -  + ][ #  # ]:       1834 :                                                 if (opts.logfile && opts.selected_output
     312                 :          0 :                                                                 & OUTPUT_CONTRACTIONS) {
     313 [ #  # ][ #  # ]:          0 :                                                         *opts.logfile << mb->id_from_handle(connNew[0])
     314 [ #  # ][ #  # ]:          0 :                                                                         << " v" << mb->id_from_handle(connNew[1])
                 [ #  # ]
     315 [ #  # ][ #  # ]:          0 :                                                                         << " v" << mb->id_from_handle(connNew[2])
                 [ #  # ]
     316         [ #  # ]:          0 :                                                                         << std::endl;
     317                 :            :                                                 }
     318         [ +  - ]:       1834 :                                                 trisChanged.push_back(tr);
     319                 :            :                                         }
     320                 :            :                                 }
     321                 :            : 
     322                 :            :                         }
     323                 :        544 :                         validFaceCount -= tris.size();
     324         [ +  - ]:        544 :                         rval = mb->tag_set_data(validTag, &ev0v1, 1, &invalid);
     325         [ -  + ]:        544 :                               if (moab::MB_SUCCESS != rval) return rval;
     326                 :            :                         // invalidate the edges connected for sure to v1
     327         [ +  + ]:        544 :       if (edgesWithV1.size() > 0)
     328                 :            :       {
     329         [ +  + ]:       1544 :         for(unsigned int k=0; k<edgesWithV1.size(); k++)
     330                 :            :         {
     331         [ +  - ]:       1002 :           moab::EntityHandle eV1=edgesWithV1[k];
     332         [ +  - ]:       1002 :           mb->tag_set_data(validTag, &eV1, 1, &invalid);
     333                 :            :         }
     334                 :            :       }
     335                 :            :                         // reset the connectivity of some edges (from v1 to v0)
     336         [ +  + ]:       6900 :                         for (unsigned int i = 0; i < edges.size(); i++) {
     337         [ +  - ]:       6356 :                                 moab::EntityHandle e1 = edges[i];
     338 [ +  - ][ +  + ]:       6356 :                                 if (!ehIsValid(e1)) // it could be the ones invalidated
     339                 :       1546 :                                         continue;
     340                 :            : 
     341                 :            :                                 int nn;
     342                 :            :                                 const moab::EntityHandle * conn;
     343         [ +  - ]:       4810 :                                 mb->get_connectivity(e1, conn, nn);
     344                 :            : 
     345 [ -  + ][ #  # ]:       4810 :                                 assert(2==nn);
     346         [ +  + ]:      14430 :                                 for (int j = 0; j < 2; j++) {
     347         [ +  + ]:       9620 :                                         if (conn[j] == v1) {
     348                 :            :                                                 // replace it with v0, and reset it
     349                 :            :                                                 moab::EntityHandle connNew[2];
     350                 :       1402 :                                                 connNew[0] = conn[0];
     351                 :       1402 :                                                 connNew[1] = conn[1];
     352                 :       1402 :                                                 connNew[j] = v0;
     353 [ -  + ][ #  # ]:       1402 :                                                 if (opts.logfile && opts.selected_output
     354                 :          0 :                                                                 & OUTPUT_CONTRACTIONS) {
     355         [ #  # ]:          0 :                                                         *opts.logfile << "replace connectivity edge: "
     356 [ #  # ][ #  # ]:          0 :                                                                         << mb->id_from_handle(e1) << " "
                 [ #  # ]
     357 [ #  # ][ #  # ]:          0 :                                                                         << mb->id_from_handle(conn[0]) << " "
                 [ #  # ]
     358 [ #  # ][ #  # ]:          0 :                                                                         << mb->id_from_handle(conn[1]) << "  to: ";
                 [ #  # ]
     359                 :            :                                                 }
     360         [ +  - ]:       1402 :                                                 rval = mb->set_connectivity(e1, connNew, 2);
     361         [ -  + ]:       1402 :                                                             if (moab::MB_SUCCESS != rval) return rval;
     362 [ -  + ][ #  # ]:       1402 :                                                 if (opts.logfile && opts.selected_output
     363                 :          0 :                                                                 & OUTPUT_CONTRACTIONS) {
     364 [ #  # ][ #  # ]:          0 :                                                         *opts.logfile << mb->id_from_handle(connNew[0])
     365 [ #  # ][ #  # ]:          0 :                                                                         << " " << mb->id_from_handle(connNew[1])
                 [ #  # ]
     366         [ #  # ]:       1402 :                                                                         << std::endl;
     367                 :            :                                                 }
     368                 :            :                                         }
     369                 :            :                                 }
     370                 :            :                         }
     371                 :            :                         // the question: is the adjacency between triangles and edges restored?
     372                 :            :                         // yes, it is; check set_connectivity logic
     373                 :            :                         // we need to remove adjacencies between triangles and edges that are not valid
     374                 :            :                         // and add some more adjacencies to the edges that are now part of the triangle
     375         [ +  + ]:       2378 :                         for (unsigned int i = 0; i < trisChanged.size(); i++) {
     376                 :            :                                 // get adjacencies now, and bail out early; maybe we should create if missing
     377         [ +  - ]:       1834 :                                 std::vector<moab::EntityHandle> localEdges;
     378         [ +  - ]:       1834 :                                 moab::EntityHandle tr = trisChanged[i];
     379                 :            :                                 rval = mb->get_adjacencies(&tr, 1, 1, false, localEdges,
     380         [ +  - ]:       1834 :                                                 moab::Interface::UNION);
     381         [ -  + ]:       1834 :                                         if (moab::MB_SUCCESS != rval) return rval;
     382         [ +  - ]:       1834 :                                 filterValid(mb, localEdges);
     383 [ -  + ][ #  # ]:       1834 :                                 if (opts.logfile && opts.selected_output & OUTPUT_CONTRACTIONS) {
     384 [ #  # ][ #  # ]:          0 :                                         *opts.logfile << "Triangle t" << mb->id_from_handle(tr)
                 [ #  # ]
     385 [ #  # ][ #  # ]:          0 :                                                         << "  filtered : " << localEdges.size();
     386         [ #  # ]:          0 :                                         for (unsigned int j = 0; j < localEdges.size(); j++)
     387         [ #  # ]:          0 :                                                 *opts.logfile << " e" << mb->id_from_handle(
     388 [ #  # ][ #  # ]:          0 :                                                                 localEdges[j]);
                 [ #  # ]
     389         [ #  # ]:          0 :                                         *opts.logfile << std::endl;
     390                 :            :                                 }
     391 [ -  + ][ #  # ]:       1834 :                                 assert(localEdges.size()==3);
                 [ +  - ]
     392                 :       1834 :                         }
     393                 :            : 
     394         [ +  - ]:        544 :                         filterValid(mb, adj_entities);
     395         [ +  - ]:        544 :                         changed = adj_entities; // deep copy
     396 [ -  + ][ #  # ]:        544 :                         if (opts.logfile && opts.selected_output & OUTPUT_CONTRACTIONS) {
     397 [ #  # ][ #  # ]:          0 :                                 *opts.logfile << "Triangles changed:" << changed.size();
     398         [ #  # ]:          0 :                                 for (unsigned int i = 0; i < changed.size(); i++)
     399 [ #  # ][ #  # ]:          0 :                                         *opts.logfile << " t" << mb->id_from_handle(changed[i]);
         [ #  # ][ #  # ]
     400 [ #  # ][ +  - ]:        544 :                                 *opts.logfile << std::endl;
     401                 :        544 :                         }
     402                 :            :                 } else // this should appear only when proximity limit > 0
     403                 :            :                 {
     404                 :            :                         // in this case, we only need to worry if vertex 0 and 1 are connected to the same
     405                 :            :                         // vertex 2; then we need to merge edges v0-v2 and v1 - v2
     406                 :            :                         // no triangles get deleted, only those edges;
     407                 :            :                         // the crack v0-v2-v1 gets seamed
     408                 :            :                         // get edges connected to vertex v0
     409         [ #  # ]:          0 :                         std::vector<moab::EntityHandle> edges0;
     410                 :            :                         rval = mb->get_adjacencies(&v0, 1, 1, false, edges0,
     411         [ #  # ]:          0 :                                         moab::Interface::UNION);
     412         [ #  # ]:          0 :                               if (moab::MB_SUCCESS != rval) return rval;
     413         [ #  # ]:          0 :                         filterValid(mb, edges0);
     414                 :            : 
     415                 :            :                         // get edges connected to vertex v1
     416 [ #  # ][ #  # ]:          0 :                         std::vector<moab::EntityHandle> edges1;
     417                 :            :                         rval = mb->get_adjacencies(&v1, 1, 1, false, edges1,
     418         [ #  # ]:          0 :                                         moab::Interface::UNION);
     419         [ #  # ]:          0 :                               if (moab::MB_SUCCESS != rval) return rval;
     420         [ #  # ]:          0 :                         filterValid(mb, edges1);
     421                 :            :                         // find all edges that will be merged, of type v0-v2 v1-v2 (so that they have a
     422                 :            :                         // common vertex v2
     423                 :            :                         // in that case, we will have to merge them as before, and delete the
     424                 :            :                         // one that contains v1 before
     425                 :            :                         // for sure, there is no edge from v0 to v1 !!!
     426                 :            :                         // keep all the vertices from edges1, different from v1
     427 [ #  # ][ #  # ]:          0 :                         std::vector<moab::EntityHandle> otherVertices1;
     428         [ #  # ]:          0 :                         for (unsigned int i = 0; i < edges1.size(); i++) {
     429         [ #  # ]:          0 :                                 moab::EntityHandle edgeThatGoes = edges1[1];
     430                 :            :                                 // find the other vertex, not v1
     431                 :            :                                 int nn;
     432                 :            :                                 const moab::EntityHandle * conn2;
     433         [ #  # ]:          0 :                                 mb->get_connectivity(edgeThatGoes, conn2, nn);
     434                 :          0 :                                 int other = 0;
     435         [ #  # ]:          0 :                                 if (conn2[0] == v1)
     436                 :          0 :                                         other = 1;
     437         [ #  # ]:          0 :                                 else if (conn2[1] == v1)// is this really necessary in a correct model?
     438                 :          0 :                                         other = 0;
     439         [ #  # ]:          0 :                                 otherVertices1.push_back(conn2[other]);
     440                 :            :                         }
     441         [ #  # ]:          0 :                         for (unsigned int i = 0; i < edges0.size(); i++) {
     442         [ #  # ]:          0 :                                 moab::EntityHandle edgeThatStays = edges0[i];
     443                 :            :                                 // find the other vertex, not v0
     444                 :            :                                 int nn;
     445                 :            :                                 const moab::EntityHandle * conn2;
     446         [ #  # ]:          0 :                                 mb->get_connectivity(edgeThatStays, conn2, nn);
     447                 :          0 :                                 int other = 0;
     448         [ #  # ]:          0 :                                 if (conn2[0] == v1)
     449                 :          0 :                                         other = 1;
     450         [ #  # ]:          0 :                                 else if (conn2[1] == v1)// is this really necessary in a correct model?
     451                 :          0 :                                         other = 0;
     452                 :          0 :                                 moab::EntityHandle v2 = conn2[other];
     453                 :            :                                 // let's see now if v2 is among vertices from otherVertices1
     454         [ #  # ]:          0 :                                 for (unsigned int i1 = 0; i1 < otherVertices1.size(); i1++) {
     455 [ #  # ][ #  # ]:          0 :                                         if (v2 == otherVertices1[i1]) {
     456                 :            :                                                 // we have a match, some work to do
     457                 :            :                                                 // invalidate the edge edges1[i1]
     458                 :          0 :                                                 unsigned char invalid = 0;
     459 [ #  # ][ #  # ]:          0 :                                                 mb->tag_set_data(validTag, &(edges1[i1]), 1, &invalid);
     460                 :          0 :                                                 break; // we stop looking for a match, only one possible
     461                 :            :                                         }
     462                 :            :                                 }
     463                 :            :                         }
     464                 :            :                         // triangles that need reconnected
     465 [ #  # ][ #  # ]:          0 :                         std::vector<moab::EntityHandle> tri1;
     466                 :            :                         rval = mb->get_adjacencies(&v1, 1, 2, false, tri1,
     467         [ #  # ]:          0 :                                         moab::Interface::UNION);
     468         [ #  # ]:          0 :                               if (moab::MB_SUCCESS != rval) return rval;
     469                 :            :                         // start copy tri reconnect
     470                 :          0 :                         unsigned int i = 0;
     471         [ #  # ]:          0 :                         for (i=0; i < tri1.size(); i++) {
     472         [ #  # ]:          0 :                                 moab::EntityHandle tr = tri1[i];
     473 [ #  # ][ #  # ]:          0 :                                 if (!ehIsValid(tr))
     474                 :          0 :                                         continue;
     475                 :            :                                 // see the connectivity of tr; if there is a v1, replace it with v0
     476                 :            :                                 // will that propagate to edges? or do we have to set it separately?
     477                 :            :                                 int nn;
     478                 :            :                                 const moab::EntityHandle * conn3;
     479         [ #  # ]:          0 :                                 mb->get_connectivity(tr, conn3, nn);
     480                 :            : 
     481 [ #  # ][ #  # ]:          0 :                                 assert(3==nn);
     482         [ #  # ]:          0 :                                 for (int j = 0; j < 3; j++) {
     483         [ #  # ]:          0 :                                         if (conn3[j] == v1) {
     484                 :            :                                                 // replace it with v0, and reset it
     485                 :            :                                                 moab::EntityHandle connNew[3];
     486                 :          0 :                                                 connNew[0] = conn3[0];
     487                 :          0 :                                                 connNew[1] = conn3[1];
     488                 :          0 :                                                 connNew[2] = conn3[2];
     489                 :          0 :                                                 connNew[j] = v0;
     490         [ #  # ]:          0 :                                                 rval = mb->set_connectivity(tr, connNew, 3);
     491         [ #  # ]:          0 :                                                             if (moab::MB_SUCCESS != rval) return rval;
     492 [ #  # ][ #  # ]:          0 :                                                 if (opts.logfile && opts.selected_output
     493                 :          0 :                                                                 & OUTPUT_CONTRACTIONS) {
     494 [ #  # ][ #  # ]:          0 :                                                         *opts.logfile << mb->id_from_handle(connNew[0])
     495 [ #  # ][ #  # ]:          0 :                                                                         << " v" << mb->id_from_handle(connNew[1])
                 [ #  # ]
     496 [ #  # ][ #  # ]:          0 :                                                                         << " v" << mb->id_from_handle(connNew[2])
                 [ #  # ]
     497         [ #  # ]:          0 :                                                                         << std::endl;
     498                 :            :                                                 }
     499                 :            :                                         }
     500                 :            :                                 }
     501                 :            : 
     502                 :            :                         }
     503                 :            :                         // now reconnect edges1 that are still valid
     504         [ #  # ]:          0 :                         for (i = 0; i < edges1.size(); i++) {
     505         [ #  # ]:          0 :                                 moab::EntityHandle e1 = edges1[i];
     506 [ #  # ][ #  # ]:          0 :                                 if (!ehIsValid(e1))
     507                 :          0 :                                         continue;
     508                 :            :                                 // see the connectivity of e1; if there is a v1, replace it with v0
     509                 :            :                                 // will that propagate to edges? or do we have to set it separately?
     510                 :            :                                 int nn;
     511                 :            :                                 const moab::EntityHandle * conn3;
     512         [ #  # ]:          0 :                                 mb->get_connectivity(e1, conn3, nn);
     513                 :            : 
     514 [ #  # ][ #  # ]:          0 :                                 assert(2==nn);
     515         [ #  # ]:          0 :                                 for (int j = 0; j < 2; j++) {
     516         [ #  # ]:          0 :                                         if (conn3[j] == v1) {
     517                 :            :                                                 // replace it with v0, and reset it
     518                 :            :                                                 moab::EntityHandle connNew[2];
     519                 :          0 :                                                 connNew[0] = conn3[0];
     520                 :          0 :                                                 connNew[1] = conn3[1];
     521                 :          0 :                                                 connNew[j] = v0;
     522         [ #  # ]:          0 :                                                 rval = mb->set_connectivity(e1, connNew, 2);
     523         [ #  # ]:          0 :                                                             if (moab::MB_SUCCESS != rval) return rval;
     524                 :            : 
     525                 :            :                                         }
     526                 :            :                                 }
     527                 :            : 
     528                 :            :                         }
     529                 :            :                         // all the triangles connected to v0 are now changed, need recomputation
     530                 :            :                         //
     531                 :            :                         rval = mb->get_adjacencies(&v0, 1, 2, false, changed,
     532         [ #  # ]:          0 :                                         moab::Interface::UNION);
     533         [ #  # ]:          0 :                               if (moab::MB_SUCCESS != rval) return rval;
     534 [ #  # ][ #  # ]:        544 :                         filterValid(mb, changed);
                 [ +  - ]
     535                 :            : 
     536                 :        544 :                 }
     537                 :            :                 // end big copy from version 3512
     538                 :            :         } else {
     539                 :            :                 // vertex v1 will be merged!!
     540         [ #  # ]:          0 :                 std::vector<moab::EntityHandle> edgePairsToMerge; // the one that has v0 will
     541                 :            :                 // be kept
     542         [ #  # ]:          0 :                 if (foundEdge) {
     543                 :            :                         // this is case 1, the most complicated
     544                 :            :                         // get triangles connected to edge ev0v1
     545         [ #  # ]:          0 :                         std::vector<moab::EntityHandle> tris;
     546                 :            :                         rval = mb->get_adjacencies(&ev0v1, 1, 2, false, tris,
     547         [ #  # ]:          0 :                                         moab::Interface::UNION);
     548         [ #  # ]:          0 :                               if (moab::MB_SUCCESS != rval) return rval;
     549                 :            :                         // find all edges that will be merged ( xv0, xv1, etc)
     550 [ #  # ][ #  # ]:          0 :                         if (opts.logfile && opts.selected_output & OUTPUT_CONTRACTIONS) {
     551         [ #  # ]:          0 :                                 *opts.logfile << "Triangles adjacent to found edge:"
     552         [ #  # ]:          0 :                                                 << tris.size();
     553         [ #  # ]:          0 :                                 for (unsigned int i = 0; i < tris.size(); i++)
     554 [ #  # ][ #  # ]:          0 :                                         *opts.logfile << " " << mb->id_from_handle(tris[i]);
         [ #  # ][ #  # ]
     555         [ #  # ]:          0 :                                 *opts.logfile << std::endl;
     556                 :            :                         }
     557                 :          0 :                         unsigned int i=0;
     558         [ #  # ]:          0 :                         for (i=0; i < tris.size(); i++) {
     559         [ #  # ]:          0 :                                 moab::EntityHandle triangleThatCollapses = tris[i];
     560         [ #  # ]:          0 :                                 std::vector<moab::EntityHandle> localEdges;
     561                 :            :                                 rval = mb->get_adjacencies(&triangleThatCollapses, 1, 1, false,
     562         [ #  # ]:          0 :                                                 localEdges, moab::Interface::UNION);
     563         [ #  # ]:          0 :                                         if (moab::MB_SUCCESS != rval) return rval;
     564 [ #  # ][ #  # ]:          0 :                                 if (opts.logfile && opts.selected_output & OUTPUT_CONTRACTIONS) {
     565         [ #  # ]:          0 :                                         *opts.logfile << "Triangle " << mb->id_from_handle(
     566 [ #  # ][ #  # ]:          0 :                                                         triangleThatCollapses) << " Edges: "
                 [ #  # ]
     567         [ #  # ]:          0 :                                                         << localEdges.size();
     568                 :            : 
     569         [ #  # ]:          0 :                                         for (unsigned int i = 0; i < localEdges.size(); i++)
     570         [ #  # ]:          0 :                                                 *opts.logfile << " " << mb->id_from_handle(
     571 [ #  # ][ #  # ]:          0 :                                                                 localEdges[i]);
                 [ #  # ]
     572         [ #  # ]:          0 :                                         *opts.logfile << std::endl;
     573                 :            :                                 }
     574                 :            :                                 // find the edges that contains v0
     575                 :            :                                 moab::EntityHandle e[2];// the 2 edges e0, e1, that are not ev0v1;
     576         [ #  # ]:          0 :                                 if (localEdges.size() != 3)
     577                 :          0 :                                         return moab::MB_FAILURE; // failure
     578                 :          0 :                                 int index = 0;
     579         [ #  # ]:          0 :                                 for (int k = 0; k < 3; k++)
     580 [ #  # ][ #  # ]:          0 :                                         if (localEdges[k] != ev0v1)
     581         [ #  # ]:          0 :                                                 e[index++] = localEdges[k];
     582                 :            :                                 // among those 2 edges, find out which one has v0, and which one v1
     583         [ #  # ]:          0 :                                 if (index != 2)
     584                 :          0 :                                         return moab::MB_FAILURE; // failure
     585 [ #  # ][ #  # ]:          0 :                                 for (int j = 0; j < 2; j++) {
     586                 :            :                                         int nn;
     587                 :            :                                         const moab::EntityHandle * conn2;
     588         [ #  # ]:          0 :                                         mb->get_connectivity(e[j], conn2, nn);
     589 [ #  # ][ #  # ]:          0 :                                         if (conn2[0] == v0 || conn2[1] == v0) {
     590                 :            :                                                 // this is the edge that will be kept, the other one collapsed
     591         [ #  # ]:          0 :                                                 edgePairsToMerge.push_back(e[j]);
     592                 :            :                                                 //j = (j + 1) % 2;
     593                 :          0 :             int j1 = (j + 1)%2;// do not modify original j
     594         [ #  # ]:          0 :                                                 edgePairsToMerge.push_back(e[j1]);
     595                 :          0 :                                                 break; // no need to check the other one. it
     596                 :            :                                                 // will contain v1
     597                 :            :                                         }
     598                 :            :                                 }
     599                 :          0 :                         }
     600                 :            :                         // first merge vertices v0 and v1 : will also NOT delete v1 (yet)
     601                 :            :                         // the tag on v1 will be deleted too, and we do not want that, at least until
     602                 :            :                         // after the merging of edges, and deleting the pair
     603         [ #  # ]:          0 :                         rval = mb->merge_entities(v0, v1, false, false);
     604         [ #  # ]:          0 :                               if (moab::MB_SUCCESS != rval) return rval;
     605                 :            :                         // merge edgePairsToMerge // now, v0 and v1 should be collapsed!
     606         [ #  # ]:          0 :                         for (unsigned int j = 0; j < edgePairsToMerge.size(); j += 2) {
     607                 :            :                                 // will also delete edges that contained v1 before
     608 [ #  # ][ #  # ]:          0 :                                 if (opts.logfile && opts.selected_output & OUTPUT_CONTRACTIONS)
     609         [ #  # ]:          0 :                                         *opts.logfile << "Edges merged:" << mb->id_from_handle(
     610 [ #  # ][ #  # ]:          0 :                                                         edgePairsToMerge[j]) << " " << mb->id_from_handle(
         [ #  # ][ #  # ]
     611 [ #  # ][ #  # ]:          0 :                                                         edgePairsToMerge[j + 1]) << std::endl;
         [ #  # ][ #  # ]
     612         [ #  # ]:          0 :                                 mb->merge_entities(edgePairsToMerge[j],
     613 [ #  # ][ #  # ]:          0 :                                                 edgePairsToMerge[j + 1], false, true);
     614                 :            : 
     615                 :            :                         }
     616                 :            :                         // the only things that need deleted are triangles
     617 [ #  # ][ #  # ]:          0 :                         if (opts.logfile && opts.selected_output & OUTPUT_CONTRACTIONS) {
     618 [ #  # ][ #  # ]:          0 :                                 *opts.logfile << "Triangles invalidated:" << tris.size();
     619         [ #  # ]:          0 :                                 for (unsigned int i = 0; i < tris.size(); i++)
     620 [ #  # ][ #  # ]:          0 :                                         *opts.logfile << " " << mb->id_from_handle(tris[i]);
         [ #  # ][ #  # ]
     621         [ #  # ]:          0 :                                 *opts.logfile << std::endl;
     622                 :            :                         }
     623 [ #  # ][ #  # ]:          0 :                         rval = mb->delete_entities(&(tris[0]), tris.size());
     624         [ #  # ]:          0 :                               if (moab::MB_SUCCESS != rval) return rval;
     625         [ #  # ]:          0 :                         if (iniSet)
     626 [ #  # ][ #  # ]:          0 :                           mb->remove_entities(iniSet, &(tris[0]), tris.size());
     627                 :          0 :                         validFaceCount -= tris.size();
     628                 :            :                         // hopefully, all adjacencies are preserved
     629                 :            :                         // delete now the edge ev0v1
     630 [ #  # ][ #  # ]:          0 :                         if (opts.logfile && opts.selected_output & OUTPUT_CONTRACTIONS)
     631         [ #  # ]:          0 :                                 *opts.logfile << "Edge invalidated"
     632 [ #  # ][ #  # ]:          0 :                                                 << mb->id_from_handle(ev0v1) << std::endl;
                 [ #  # ]
     633         [ #  # ]:          0 :                         rval = mb->delete_entities(&ev0v1, 1);
     634         [ #  # ]:          0 :                               if (moab::MB_SUCCESS != rval) return rval;
     635         [ #  # ]:          0 :                         if (iniSet)
     636         [ #  # ]:          0 :                           mb->remove_entities(iniSet, &ev0v1, 1);// it may not be part of it, but
     637                 :            :                         // delete it anyway
     638                 :            :                         // among adj_entities, remove the tris triangles, and return them
     639         [ #  # ]:          0 :                         for (unsigned int j = 0; j < adj_entities.size(); j++) {
     640         [ #  # ]:          0 :                                 moab::EntityHandle F = adj_entities[j];
     641                 :          0 :                                 int inTris = 0;
     642         [ #  # ]:          0 :                                 for (unsigned int k = 0; k < tris.size(); k++)
     643 [ #  # ][ #  # ]:          0 :                                         if (F == tris[k]) {
     644                 :          0 :                                                 inTris = 1;
     645                 :          0 :                                                 break;
     646                 :            :                                         }
     647         [ #  # ]:          0 :                                 if (!inTris)
     648         [ #  # ]:          0 :                                         changed.push_back(F);
     649                 :            :                         }
     650 [ #  # ][ #  # ]:          0 :                         if (opts.logfile && opts.selected_output & OUTPUT_CONTRACTIONS) {
     651 [ #  # ][ #  # ]:          0 :                                 *opts.logfile << "Triangles changed:" << changed.size();
     652         [ #  # ]:          0 :                                 for (unsigned int i = 0; i < changed.size(); i++)
     653 [ #  # ][ #  # ]:          0 :                                         *opts.logfile << " " << mb->id_from_handle(changed[i]);
         [ #  # ][ #  # ]
     654 [ #  # ][ #  # ]:          0 :                                 *opts.logfile << std::endl;
     655                 :          0 :                         }
     656                 :            : 
     657                 :            :                 } else // this should appear only when proximity limit > 0
     658                 :            :                 {
     659                 :            :                         // in this case, we only need to worry if vertex 0 and 1 are connected to the same
     660                 :            :                         // vertex 2; then we need to merge edges v0-v2 and v1 - v2
     661                 :            :                         // no triangles get deleted, only those edges
     662                 :            :                         // get edges connected to vertex v0
     663         [ #  # ]:          0 :                         std::vector<moab::EntityHandle> edges0;
     664                 :            :                         rval = mb->get_adjacencies(&v0, 1, 1, false, edges0,
     665         [ #  # ]:          0 :                                         moab::Interface::UNION);
     666         [ #  # ]:          0 :                               if (moab::MB_SUCCESS != rval) return rval;
     667                 :            : 
     668                 :            :                         // get edges connected to vertex v1
     669 [ #  # ][ #  # ]:          0 :                         std::vector<moab::EntityHandle> edges1;
     670                 :            :                         rval = mb->get_adjacencies(&v1, 1, 1, false, edges1,
     671         [ #  # ]:          0 :                                         moab::Interface::UNION);
     672         [ #  # ]:          0 :                               if (moab::MB_SUCCESS != rval) return rval;
     673                 :            :                         // find all edges that will be merged, of type v0-v2 v1-v2 (so that they have a
     674                 :            :                         // common vertex v2
     675                 :            :                         // in that case, we will have to merge them as before, and delete the
     676                 :            :                         // one that contains v1 before
     677                 :            :                         // for sure, there is no edge from v0 to v1 !!!
     678                 :            :                         // keep all the vertices from edges1, different from v1
     679 [ #  # ][ #  # ]:          0 :                         std::vector<moab::EntityHandle> otherVertices1;
     680         [ #  # ]:          0 :                         for (unsigned int i1 = 0; i1 < edges1.size(); i1++) {
     681         [ #  # ]:          0 :                                 moab::EntityHandle edgeThatGoes = edges1[i1];
     682                 :            :                                 // find the other vertex, not v1
     683                 :            :                                 int nn;
     684                 :            :                                 const moab::EntityHandle * conn2;
     685         [ #  # ]:          0 :                                 mb->get_connectivity(edgeThatGoes, conn2, nn);
     686                 :          0 :                                 int other = 0;
     687         [ #  # ]:          0 :                                 if (conn2[0] == v1)
     688                 :          0 :                                         other = 1;
     689         [ #  # ]:          0 :                                 else if (conn2[1] == v1)// is this really necessary in a correct model?
     690                 :          0 :                                         other = 0;
     691         [ #  # ]:          0 :                                 otherVertices1.push_back(conn2[other]);
     692                 :            :                         }
     693         [ #  # ]:          0 :                         for (unsigned int i = 0; i < edges0.size(); i++) {
     694         [ #  # ]:          0 :                                 moab::EntityHandle edgeThatStays = edges0[i];
     695                 :            :                                 // find the other vertex, not v0
     696                 :            :                                 int nn;
     697                 :            :                                 const moab::EntityHandle * conn2;
     698         [ #  # ]:          0 :                                 mb->get_connectivity(edgeThatStays, conn2, nn);
     699                 :          0 :                                 int other = 0;
     700         [ #  # ]:          0 :                                 if (conn2[0] == v1)
     701                 :          0 :                                         other = 1;
     702         [ #  # ]:          0 :                                 else if (conn2[1] == v1)// is this really necessary in a correct model?
     703                 :          0 :                                         other = 0;
     704                 :          0 :                                 moab::EntityHandle v2 = conn2[other];
     705                 :            :                                 // let's see now if v2 is among vertices from otherVertices1
     706                 :            :                                 // if yes, then we have a match, edges that need collapsed
     707         [ #  # ]:          0 :                                 for (unsigned int i1 = 0; i1 < otherVertices1.size(); i1++) {
     708 [ #  # ][ #  # ]:          0 :                                         if (v2 == otherVertices1[i1]) {
     709                 :            :                                                 // we have a match, some work to do
     710         [ #  # ]:          0 :                                                 edgePairsToMerge.push_back(edgeThatStays);
     711 [ #  # ][ #  # ]:          0 :                                                 edgePairsToMerge.push_back(edges1[i1]);
     712                 :          0 :                                                 break; // we stopp looking for a match, only one possible
     713                 :            :                                         }
     714                 :            :                                 }
     715                 :            :                         }
     716                 :            : 
     717                 :            :                         // first merge vertices v0 and v1 : will also NOT delete v1 (yet)
     718                 :            :                         // the tag on v1 will be deleted too, and we do not want that, at least until
     719                 :            :                         // after the merging of edges, and deleting the pair
     720         [ #  # ]:          0 :                         rval = mb->merge_entities(v0, v1, false, false);
     721         [ #  # ]:          0 :                               if (moab::MB_SUCCESS != rval) return rval;
     722                 :            :                         // merge edgePairsToMerge // now, v0 and v1 should be collapsed!
     723         [ #  # ]:          0 :                         for (unsigned int j = 0; j < edgePairsToMerge.size(); j += 2) {
     724                 :            :                                 // will also delete edges that contained v1 before
     725         [ #  # ]:          0 :                                 mb->merge_entities(edgePairsToMerge[j],
     726 [ #  # ][ #  # ]:          0 :                                                 edgePairsToMerge[j + 1], false, true);
     727                 :            :                         }
     728                 :            :                         // all the triangles connected to v0 are now changed, need recomputation
     729                 :            :                         //
     730                 :            :                         rval = mb->get_adjacencies(&v0, 1, 2, false, changed,
     731         [ #  # ]:          0 :                                         moab::Interface::UNION);
     732 [ #  # ][ #  # ]:          0 :                               if (moab::MB_SUCCESS != rval) return rval;
                 [ #  # ]
     733                 :            : 
     734                 :          0 :                 }
     735                 :            :         }
     736                 :       1088 :         return moab::MB_SUCCESS;
     737                 :            : 
     738 [ +  - ][ +  - ]:        312 : }
     739                 :            : 

Generated by: LCOV version 1.11