LCOV - code coverage report
Current view: top level - algs/AdvFront - AF2Rule.cpp (source / functions) Hit Total Coverage
Test: coverage_sk.info Lines: 205 234 87.6 %
Date: 2020-07-01 15:24:36 Functions: 21 23 91.3 %
Branches: 269 514 52.3 %

           Branch data     Line data    Source code
       1                 :            : #include "meshkit/AF2Rule.hpp"
       2                 :            : 
       3                 :            : // C++
       4                 :            : #include <set>
       5                 :            : #include <stack>
       6                 :            : 
       7                 :            : // MeshKit
       8                 :            : #include "meshkit/AF2Binding.hpp"
       9                 :            : #include "meshkit/AF2RuleApplication.hpp"
      10                 :            : #include "meshkit/Error.hpp"
      11                 :            : using namespace MeshKit;
      12                 :            : /**
      13                 :            :  * A template method for allocating an array to hold the contents of a list
      14                 :            :  * of pointers and copying the pointers from the list to the array.
      15                 :            :  */
      16                 :            : template<class T>
      17                 :       1674 : void aF2RuleCopyListToArray(std::list<T*> const & aListOfPtr,
      18                 :            :     T** & anArrayOfPtr, unsigned int offset = 0u)
      19                 :            : {
      20 [ +  - ][ +  - ]:       1674 :   anArrayOfPtr = new T*[offset + aListOfPtr.size()];
         [ +  - ][ +  - ]
                 [ +  - ]
      21                 :            :   typedef typename std::list<T*>::const_iterator ItrType;
      22                 :       1674 :   unsigned int indx = offset;
      23 [ +  - ][ +  - ]:       3773 :   for (ItrType itr = aListOfPtr.begin(); itr != aListOfPtr.end(); ++itr)
         [ +  + ][ +  - ]
         [ +  - ][ +  + ]
         [ +  - ][ +  - ]
         [ +  + ][ +  - ]
         [ +  - ][ +  + ]
         [ +  - ][ +  - ]
                 [ +  + ]
      24                 :            :   {
      25 [ +  - ][ -  + ]:       2099 :     if (*itr == NULL)
         [ +  - ][ -  + ]
         [ +  - ][ -  + ]
         [ +  - ][ -  + ]
         [ +  - ][ -  + ]
      26                 :            :     {
      27 [ #  # ][ #  # ]:          0 :       MeshKit::Error badArg(MK_BAD_INPUT);
         [ #  # ][ #  # ]
                 [ #  # ]
      28 [ #  # ][ #  # ]:          0 :       badArg.set_string(
         [ #  # ][ #  # ]
                 [ #  # ]
      29                 :            :           "AF2Rule constructor arguments may not contain any null pointers.");
      30 [ #  # ][ #  # ]:          0 :       throw badArg;
         [ #  # ][ #  # ]
                 [ #  # ]
      31                 :            :     }
      32 [ +  - ][ +  - ]:       2099 :     anArrayOfPtr[indx] = *itr;
         [ +  - ][ +  - ]
                 [ +  - ]
      33                 :       2099 :     ++indx;
      34                 :            :   }
      35                 :       1674 : }
      36                 :            : 
      37                 :            : /**
      38                 :            :  * A template method for deleting the objects that are pointed to by the
      39                 :            :  * pointers in a dynamically allocated array of pointers and then deleting
      40                 :            :  * the array itself.
      41                 :            :  */
      42                 :            : template<class T>
      43                 :       1395 : void aF2RuleDeepDeletePtrArray(T** & anArrayOfPtr, int arraySize)
      44                 :            : {
      45 [ +  + ][ +  + ]:       3747 :   for (int indx = 0; indx < arraySize; ++indx)
         [ +  + ][ +  + ]
                 [ +  + ]
      46                 :            :   {
      47 [ +  - ][ +  - ]:       2352 :     delete anArrayOfPtr[indx];
      48                 :            :   }
      49 [ +  - ][ +  - ]:       1395 :   delete[] anArrayOfPtr;
         [ +  - ][ +  - ]
                 [ +  - ]
      50                 :       1395 : }
      51                 :            : 
      52                 :        279 : AF2Rule::AF2Rule(std::string const & ruleNameArg, unsigned int maxQuality,
      53                 :            :     std::list<const AF2RuleExistVertex*> const & ruleVertices,
      54                 :            :     const AF2RuleExistEdge* baselineEdge,
      55                 :            :     std::list<const AF2RuleExistEdge*> const & otherRuleEdges,
      56                 :            :     const AF2FreeZoneDef* freeZoneDef,
      57                 :            :     std::list<const AF2RuleNewVertex*> const & ruleNewVertices,
      58                 :            :     std::list<const AF2RuleNewEdge*> const & ruleNewEdges,
      59                 :            :     std::list<const AF2RuleNewFace*> const & ruleNewFaces) :
      60                 :            :     ruleName(ruleNameArg),
      61                 :            :     maxQualityLevel(maxQuality),
      62                 :        279 :     numExVertices(ruleVertices.size()),
      63                 :        279 :     numExEdges(1u + otherRuleEdges.size()),
      64                 :            :     freeZoneDef(freeZoneDef),
      65                 :        279 :     numNewVertices(ruleNewVertices.size()),
      66                 :        279 :     numNewEdges(ruleNewEdges.size()),
      67                 :        558 :     numNewFaces(ruleNewFaces.size())
      68                 :            : {
      69         [ -  + ]:        279 :   if (baselineEdge == NULL)
      70                 :            :   {
      71         [ #  # ]:          0 :     MeshKit::Error badArg(MeshKit::MK_BAD_INPUT);
      72         [ #  # ]:          0 :     badArg.set_string("The baseline edge may not be null.");
      73         [ #  # ]:          0 :     throw badArg;
      74                 :            :   }
      75         [ -  + ]:        279 :   if (numExVertices < 2)
      76                 :            :   {
      77         [ #  # ]:          0 :     MeshKit::Error badArg(MeshKit::MK_BAD_INPUT);
      78         [ #  # ]:          0 :     badArg.set_string("AF2Rule must define at least two existing vertices.");
      79         [ #  # ]:          0 :     throw badArg;
      80                 :            :   }
      81         [ +  - ]:        279 :   aF2RuleCopyListToArray(ruleVertices, exVertices);
      82         [ +  - ]:        279 :   aF2RuleCopyListToArray(otherRuleEdges, exEdges, 1u);
      83                 :        279 :   exEdges[0] = baselineEdge;
      84         [ +  - ]:        279 :   aF2RuleCopyListToArray(ruleNewVertices, newVertices);
      85         [ +  - ]:        279 :   aF2RuleCopyListToArray(ruleNewEdges, newEdges);
      86         [ +  - ]:        279 :   aF2RuleCopyListToArray(ruleNewFaces, newFaces);
      87         [ +  - ]:        279 :   checkExEndpointsAndFindIsolatedVertices();
      88                 :        279 : }
      89                 :            : 
      90                 :        558 : AF2Rule::~AF2Rule()
      91                 :            : {
      92         [ +  - ]:        279 :   delete[] exIsoVertices;
      93                 :        279 :   aF2RuleDeepDeletePtrArray(newFaces, numNewFaces);
      94                 :        279 :   aF2RuleDeepDeletePtrArray(newEdges, numNewEdges);
      95                 :        279 :   aF2RuleDeepDeletePtrArray(newVertices, numNewVertices);
      96                 :        279 :   aF2RuleDeepDeletePtrArray(exEdges, numExEdges);
      97                 :        279 :   aF2RuleDeepDeletePtrArray(exVertices, numExVertices);
      98         [ +  - ]:        279 :   delete freeZoneDef;
      99                 :        279 : }
     100                 :            : 
     101                 :          0 : AF2Rule::AF2Rule(const AF2Rule & toCopy) :
     102                 :            :     ruleName(toCopy.ruleName),
     103                 :            :     maxQualityLevel(toCopy.maxQualityLevel),
     104                 :            :     numExVertices(toCopy.numExVertices),
     105                 :            :     numExEdges(toCopy.numExEdges),
     106         [ #  # ]:          0 :     freeZoneDef(toCopy.freeZoneDef->clone()),
     107                 :            :     numNewVertices(toCopy.numNewVertices),
     108                 :            :     numNewEdges(toCopy.numNewEdges),
     109                 :          0 :     numNewFaces(toCopy.numNewFaces)
     110                 :            : {
     111         [ #  # ]:          0 :   MeshKit::Error notImpl(MeshKit::MK_NOT_IMPLEMENTED);
     112         [ #  # ]:          0 :   notImpl.set_string("AF2Rule copy construction is not supported.");
     113         [ #  # ]:          0 :   throw notImpl;
     114                 :            : }
     115                 :            : 
     116                 :          0 : AF2Rule& AF2Rule::operator=(const AF2Rule & rhs)
     117                 :            : {
     118         [ #  # ]:          0 :   MeshKit::Error notImpl(MeshKit::MK_NOT_IMPLEMENTED);
     119         [ #  # ]:          0 :   notImpl.set_string("AF2Rule assignment operator is not supported.");
     120         [ #  # ]:          0 :   throw notImpl;
     121                 :            : }
     122                 :            : 
     123                 :        279 : void AF2Rule::checkExEndpointsAndFindIsolatedVertices()
     124                 :            : {
     125         [ +  - ]:        279 :   std::set<const AF2RuleExistVertex*> endPoints;
     126         [ +  + ]:        770 :   for (unsigned int exEdgeIndx = 0; exEdgeIndx < numExEdges; ++exEdgeIndx)
     127                 :            :   {
     128 [ +  + ][ -  + ]:        491 :     if (exEdgeIndx > 0 && exEdges[exEdgeIndx] == exEdges[0])
     129                 :            :     {
     130         [ #  # ]:          0 :       MeshKit::Error badArg(MeshKit::MK_BAD_INPUT);
     131         [ #  # ]:          0 :       badArg.set_string("The baseline edge may not be listed in the rule's other existing edges.");
     132         [ #  # ]:          0 :       throw badArg;
     133                 :            :     }
     134 [ +  - ][ +  - ]:        491 :     endPoints.insert(exEdges[exEdgeIndx]->getStart());
     135 [ +  - ][ +  - ]:        491 :     endPoints.insert(exEdges[exEdgeIndx]->getEnd());
     136                 :            :   }
     137                 :            : 
     138         [ +  - ]:        558 :   std::list<const AF2RuleExistVertex*> isoVertList;
     139         [ +  - ]:        558 :   std::set<const AF2RuleExistVertex*> allVertSet;
     140         [ +  + ]:       1070 :   for (unsigned int exVtxIndx = 0; exVtxIndx < numExVertices; ++exVtxIndx)
     141                 :            :   {
     142         [ +  - ]:        791 :     allVertSet.insert(exVertices[exVtxIndx]);
     143                 :            :     std::set<const AF2RuleExistVertex*>::iterator endPntItr =
     144         [ +  - ]:        791 :         endPoints.find(exVertices[exVtxIndx]);
     145 [ +  - ][ +  + ]:        791 :     if (endPntItr == endPoints.end())
     146                 :            :     {
     147                 :            :       // the vertex is an isolated vertex rather than an endpoint of an edge
     148         [ +  - ]:         26 :       isoVertList.push_back(exVertices[exVtxIndx]);
     149                 :            :     }
     150                 :            :     else
     151                 :            :     {
     152         [ +  - ]:        765 :       endPoints.erase(endPntItr);
     153                 :            :     }
     154                 :            :   }
     155                 :            : 
     156         [ -  + ]:        279 :   if (!endPoints.empty())
     157                 :            :   {
     158         [ #  # ]:          0 :     MeshKit::Error badArg(MeshKit::MK_BAD_INPUT);
     159         [ #  # ]:          0 :     badArg.set_string("The endpoints of the rule's existing edges are not all existing vertices.");
     160         [ #  # ]:          0 :     throw badArg;
     161                 :            :   }
     162                 :            : 
     163         [ -  + ]:        279 :   if (allVertSet.size() != numExVertices)
     164                 :            :   {
     165         [ #  # ]:          0 :     MeshKit::Error badArg(MeshKit::MK_BAD_INPUT);
     166         [ #  # ]:          0 :     badArg.set_string("There is a duplicate existing vertex.");
     167         [ #  # ]:          0 :     throw badArg;
     168                 :            :   }
     169                 :            : 
     170                 :        279 :   numExIsoVertices = isoVertList.size();
     171         [ +  - ]:        558 :   aF2RuleCopyListToArray(isoVertList, exIsoVertices);
     172                 :        279 : }
     173                 :            : 
     174                 :         90 : std::string AF2Rule::getName() const
     175                 :            : {
     176                 :         90 :   return ruleName;
     177                 :            : }
     178                 :            : 
     179                 :            : std::map<const AF2RuleExistEdge*, std::list<const AF2Edge2D*>*>*
     180                 :      78616 :     AF2Rule::findPotentialEdgeMatches(AF2Neighborhood const & ngbhd,
     181                 :            :     unsigned int matchQuality) const
     182                 :            : {
     183                 :            :   // define a map to hold the potential match information
     184                 :            :   std::map<const AF2RuleExistEdge*, std::list<const AF2Edge2D*>*>* matchMap =
     185         [ +  - ]:      78616 :       new std::map<const AF2RuleExistEdge*, std::list<const AF2Edge2D*>*>();
     186                 :            : 
     187                 :            :   // First match the baseline edge
     188                 :            :   std::list<const AF2Edge2D*>* baselineEdgeMatches =
     189         [ +  - ]:      78616 :       new std::list<const AF2Edge2D*>();
     190         [ +  + ]:      78616 :   if (isMatchingEdge(*(ngbhd.getBaselineEdge2D()), *exEdges[0], matchQuality))
     191                 :            :   {
     192         [ +  - ]:      75309 :     baselineEdgeMatches->push_back(ngbhd.getBaselineEdge2D());
     193                 :            :   }
     194                 :      78616 :   (*matchMap)[exEdges[0]] = baselineEdgeMatches;
     195                 :            : 
     196                 :            :   // Match any other existing edges that the rule may define
     197                 :      78616 :   const std::list<const AF2Edge2D*>* ngbhdEdges = ngbhd.getEdges2D();
     198         [ +  + ]:     157417 :   for (unsigned int indx = 1u; indx < numExEdges; ++indx)
     199                 :            :   {
     200                 :      78801 :     const AF2RuleExistEdge* ruleEdge = exEdges[indx];
     201                 :            :     std::list<const AF2Edge2D*>* possMatches =
     202 [ +  - ][ +  - ]:      78801 :         new std::list<const AF2Edge2D*>();
     203   [ +  -  +  - ]:    4502062 :     for (std::list<const AF2Edge2D*>::const_iterator ngbEdgeItr =
                 [ +  + ]
     204                 :    2329832 :         ngbhdEdges->begin(); ngbEdgeItr != ngbhdEdges->end(); ++ngbEdgeItr)
     205                 :            :     {
     206 [ +  - ][ +  - ]:    2172230 :       if (isMatchingEdge(**ngbEdgeItr, *ruleEdge, matchQuality))
                 [ +  + ]
     207                 :            :       {
     208 [ +  - ][ +  - ]:      24378 :         possMatches->push_back(*ngbEdgeItr);
     209                 :            :       }
     210                 :            :     }
     211         [ +  - ]:      78801 :     (*matchMap)[ruleEdge] = possMatches;
     212                 :            :   }
     213                 :            : 
     214                 :      78616 :   return matchMap;
     215                 :            : }
     216                 :            : 
     217                 :            : std::map<const AF2RuleExistVertex*, std::list<const AF2Point2D*>*>*
     218                 :      78616 :     AF2Rule::findPotentialVertexMatches(AF2Neighborhood const & ngbhd,
     219                 :            :     unsigned int matchQuality) const
     220                 :            : {
     221                 :      78616 :   const std::list<const AF2Point2D*>* ngbhdPoints = ngbhd.getPoints2D();
     222                 :            :   std::map<const AF2RuleExistVertex*,
     223                 :            :       std::list<const AF2Point2D*>*>* matchMap =
     224         [ +  - ]:      78616 :       new std::map<const AF2RuleExistVertex*, std::list<const AF2Point2D*>*>();
     225         [ +  + ]:      88387 :   for (unsigned indx = 0; indx < numExIsoVertices; ++indx)
     226                 :            :   {
     227                 :       9771 :     const AF2RuleExistVertex* ruleVertex = exIsoVertices[indx];
     228                 :            :     std::list<const AF2Point2D*>* possMatches =
     229 [ +  - ][ +  - ]:       9771 :         new std::list<const AF2Point2D*>();
     230   [ +  -  +  - ]:     580352 :     for (std::list<const AF2Point2D*>::const_iterator ngbPointItr =
                 [ +  + ]
     231                 :     299947 :         ngbhdPoints->begin(); ngbPointItr != ngbhdPoints->end(); ++ngbPointItr)
     232                 :            :     {
     233 [ +  - ][ +  - ]:     280405 :       if (isMatchingVertex(**ngbPointItr, *ruleVertex, matchQuality))
                 [ +  + ]
     234                 :            :       {
     235 [ +  - ][ +  - ]:       3589 :         possMatches->push_back(*ngbPointItr);
     236                 :            :       }
     237                 :            :     }
     238         [ +  - ]:       9771 :     (*matchMap)[ruleVertex] = possMatches;
     239                 :            :   }
     240                 :            : 
     241                 :      78616 :   return matchMap;
     242                 :            : }
     243                 :            : 
     244                 :    2250846 : bool AF2Rule::isMatchingEdge(AF2Edge2D const & edge,
     245                 :            :     AF2RuleExistEdge const & ruleEdge, unsigned int matchQuality) const
     246                 :            : {
     247         [ +  + ]:    4501692 :   if (!isMatchingVertex(*(edge.getStart()), *(ruleEdge.getStart()),
     248   [ +  +  +  + ]:    2544414 :       matchQuality) || !isMatchingVertex(*(edge.getEnd()),
     249                 :     293568 :       *(ruleEdge.getEnd()), matchQuality))
     250                 :            :   {
     251                 :    2151159 :     return false;
     252                 :            :   }
     253                 :            : 
     254                 :      99687 :   double matchTol = 0.25 + 0.15 * matchQuality;
     255                 :      99687 :   matchTol *= matchTol;
     256                 :      99687 :   return ruleEdge.isMatching(*(edge.getStart()), *(edge.getEnd()), matchTol);
     257                 :            : }
     258                 :            : 
     259                 :    2678035 : bool AF2Rule::isMatchingVertex(AF2Point2D const & point,
     260                 :            :     AF2RuleExistVertex const & ruleVertex, unsigned int matchQuality) const
     261                 :            : {
     262                 :    2678035 :   double matchTol = 0.25 + 0.15 * matchQuality;
     263                 :    2678035 :   matchTol *= matchTol;
     264                 :    2678035 :   return ruleVertex.isMatching(point, matchTol);
     265                 :            : }
     266                 :            : 
     267                 :     117498 : void AF2Rule::applyRule(AF2Neighborhood const & ngbhd,
     268                 :            :     unsigned int matchQuality, AF2RuleAppVisitor & visitor) const
     269                 :            : {
     270         [ +  + ]:     117498 :   if (matchQuality < maxQualityLevel)
     271                 :            :   {
     272                 :     117498 :     return;
     273                 :            :   }
     274                 :            : 
     275                 :            :   std::map<const AF2RuleExistEdge*, std::list<const AF2Edge2D*>*>*
     276         [ +  - ]:      78616 :     matchingEdgesMap = findPotentialEdgeMatches(ngbhd, matchQuality);
     277                 :            :   std::map<const AF2RuleExistVertex*, std::list<const AF2Point2D*>*>*
     278         [ +  - ]:      78616 :       matchingVerticesMap = findPotentialVertexMatches(ngbhd, matchQuality);
     279                 :            : 
     280         [ +  - ]:      78616 :   AF2Binding binding;
     281                 :            : 
     282 [ +  - ][ +  - ]:     157232 :   std::stack<std::list<const AF2Edge2D*>::const_iterator> edgeMatchItrStack;
     283                 :      78616 :   unsigned int edgeToMatchIndx = 0;
     284                 :      78616 :   --edgeToMatchIndx;
     285                 :      78616 :   bool  consistentMatch = true;
     286                 :      78616 :   const AF2RuleExistEdge* edgeToMatch = NULL;
     287                 :            :   while (true)
     288                 :            :   {
     289         [ +  + ]:     311245 :     if (consistentMatch)
     290                 :            :     {
     291                 :     169602 :       ++edgeToMatchIndx;
     292         [ +  + ]:     169602 :       if (edgeToMatchIndx == numExEdges)
     293                 :            :       {
     294                 :            :         // all edges have been matched
     295                 :            :         // stage two matches any isolated vertices and proceeds
     296                 :            :         // to stages three and four
     297                 :            :         applyRuleStageTwo(ngbhd, matchQuality, visitor,
     298         [ +  - ]:      27959 :             matchingVerticesMap, binding);
     299                 :            :         // now mark the match as inconsistent, so that the edge binding
     300                 :            :         // for the final edge is released and the search continues
     301                 :      27959 :         consistentMatch = false;
     302                 :            :       }
     303                 :            :       else
     304                 :            :       {
     305                 :            :         // not all edges have been matched yet, so set up to attempt to
     306                 :            :         // match the next edge given the current binding
     307                 :     141643 :         edgeToMatch = exEdges[edgeToMatchIndx];
     308 [ +  - ][ +  - ]:     169602 :         edgeMatchItrStack.push((*matchingEdgesMap)[edgeToMatch]->begin());
                 [ +  - ]
     309                 :            :       }
     310                 :            :     }
     311                 :            : 
     312         [ +  + ]:     311245 :     if (!consistentMatch)
     313                 :            :     {
     314         [ +  + ]:     169602 :       if (edgeToMatchIndx == 0)
     315                 :            :       {
     316                 :            :         // all edges beyond the base edge have examined all possible matches
     317                 :      78616 :         break;
     318                 :            :       }
     319                 :      90986 :       --edgeToMatchIndx;
     320                 :      90986 :       edgeToMatch = exEdges[edgeToMatchIndx];
     321                 :            :       // release the edge binding from the last time edgeToMatch was bound
     322         [ +  - ]:      90986 :       binding.release(edgeToMatch);
     323                 :            :     }
     324                 :            : 
     325                 :     232629 :     consistentMatch = false;
     326         [ +  - ]:     232629 :     std::list<const AF2Edge2D*>::const_iterator itr = edgeMatchItrStack.top();
     327         [ +  - ]:     232629 :     edgeMatchItrStack.pop();
     328 [ +  - ][ +  - ]:     327446 :     for (; itr != (*matchingEdgesMap)[edgeToMatch]->end(); ++itr)
         [ +  - ][ +  - ]
                 [ +  + ]
     329                 :            :     {
     330                 :            :       // check consistency
     331                 :      94817 :       consistentMatch = true;
     332 [ +  - ][ +  - ]:      94817 :       if (!binding.isConsistent(edgeToMatch, *itr))
                 [ +  + ]
     333                 :            :       {
     334                 :       3831 :         consistentMatch = false;
     335                 :            :       }
     336                 :            :       else
     337                 :            :       {
     338                 :            :         // bind the edge and store the next position of the iterator
     339                 :            :         // on the iterator stack for later examination
     340 [ +  - ][ +  - ]:      90986 :         binding.bind(edgeToMatch, *itr);
     341 [ +  - ][ +  - ]:      90986 :         edgeMatchItrStack.push(++itr);
     342                 :            : 
     343                 :            :         // break out of this loop and proceed to bind other edges or vertices
     344                 :            :         // or check the free zone and finish applying the rule
     345                 :      90986 :         break;
     346                 :            :       }
     347                 :            :     }
     348                 :      78616 :   }
     349                 :            : }
     350                 :            : 
     351                 :      27959 : void AF2Rule::applyRuleStageTwo(AF2Neighborhood const & ngbhd,
     352                 :            :     unsigned int matchQuality, AF2RuleAppVisitor & visitor,
     353                 :            :     std::map<const AF2RuleExistVertex*, std::list<const AF2Point2D*>*>* const &
     354                 :            :     matchingVerticesMap, AF2Binding & binding) const
     355                 :            : {
     356                 :            :   // Note: At this point it would be possible to filter the lists
     357                 :            :   // of vertices that are potential matches, removing any potential
     358                 :            :   // matches that are already bound as endpoints of edges, but it's
     359                 :            :   // not clear that the performance improvement, if any, would offset
     360                 :            :   // the additional memory for storing the filtered list and the
     361                 :            :   // additional computation.
     362                 :            : 
     363 [ +  - ][ +  - ]:      27959 :   std::stack<std::list<const AF2Point2D*>::const_iterator> vertexMatchItrStack;
     364                 :      27959 :   unsigned int vertexToMatchIndx = 0;
     365                 :      27959 :   --vertexToMatchIndx;
     366                 :      27959 :   bool  consistentMatch = true;
     367                 :      27959 :   const AF2RuleExistVertex* vertexToMatch = NULL;
     368                 :            :   while (true)
     369                 :            :   {
     370         [ +  + ]:      40622 :     if (consistentMatch)
     371                 :            :     {
     372                 :      31320 :       ++vertexToMatchIndx;
     373         [ +  + ]:      31320 :       if (vertexToMatchIndx == numExIsoVertices)
     374                 :            :       {
     375                 :            :         // all edges and all vertices have been matched
     376         [ +  - ]:      22018 :         applyRuleStageThree(ngbhd, matchQuality, visitor, binding);
     377                 :            :         // now mark the match as inconsistent, so that the vertex binding
     378                 :            :         // for the final vertex is released and the search continues
     379                 :            :         // or (if there were no vertices to match) the search is terminated
     380                 :      22018 :         consistentMatch = false;
     381                 :            :       }
     382                 :            :       else
     383                 :            :       {
     384                 :            :         // not all isolated vertices have been matched yet, so set up to
     385                 :            :         // attempt to match the next vertex given the current binding
     386                 :       9302 :         vertexToMatch = exIsoVertices[vertexToMatchIndx];
     387                 :            :         vertexMatchItrStack.push(
     388 [ +  - ][ +  - ]:      31320 :             (*matchingVerticesMap)[vertexToMatch]->begin());
                 [ +  - ]
     389                 :            :       }
     390                 :            :     }
     391                 :            : 
     392         [ +  + ]:      40622 :     if (!consistentMatch)
     393                 :            :     {
     394         [ +  + ]:      31320 :       if (vertexToMatchIndx == 0)
     395                 :            :       {
     396                 :            :         // all isolated vertices have explored all possible matches
     397                 :      27959 :         break;
     398                 :            :       }
     399                 :       3361 :       --vertexToMatchIndx;
     400                 :       3361 :       vertexToMatch = exIsoVertices[vertexToMatchIndx];
     401                 :            :       // release the vertex binding from the last time vertexToMatch was bound
     402         [ +  - ]:       3361 :       binding.release(vertexToMatch);
     403                 :            :     }
     404                 :            : 
     405                 :      12663 :     consistentMatch = false;
     406                 :            :     std::list<const AF2Point2D*>::const_iterator itr =
     407         [ +  - ]:      12663 :         vertexMatchItrStack.top();
     408         [ +  - ]:      12663 :     vertexMatchItrStack.pop();
     409 [ #  # ][ +  - ]:      16024 :     for (; itr != (*matchingVerticesMap)[vertexToMatch]->end(); ++itr)
         [ +  - ][ +  - ]
                 [ +  + ]
     410                 :            :     {
     411                 :            :       // check consistency
     412                 :       3361 :       consistentMatch = true;
     413 [ +  - ][ +  - ]:       3361 :       if (!binding.isConsistent(vertexToMatch, *itr))
                 [ -  + ]
     414                 :            :       {
     415                 :          0 :         consistentMatch = false;
     416                 :            :       }
     417                 :            :       else
     418                 :            :       {
     419                 :            :         // bind the vertex and store the next position of the iterator
     420                 :            :         // on the iterator stack for later examination
     421 [ +  - ][ +  - ]:       3361 :         binding.bind(vertexToMatch, *itr);
     422 [ +  - ][ +  - ]:       3361 :         vertexMatchItrStack.push(++itr);
     423                 :            : 
     424                 :            :         // break out of this loop and proceed to bind other vertices
     425                 :            :         // or check the free zone and finish applying the rule
     426                 :       3361 :         break;
     427                 :            :       }
     428                 :            :     }
     429                 :      27959 :   }
     430                 :      27959 : }
     431                 :            : 
     432                 :      22018 : void AF2Rule::applyRuleStageThree(AF2Neighborhood const & ngbhd,
     433                 :            :     unsigned int matchQuality, AF2RuleAppVisitor & visitor,
     434                 :            :     AF2Binding const & binding) const
     435                 :            : {
     436                 :      22018 :   bool emptyFreeZone = true;
     437                 :            : 
     438                 :      22018 :   AF2FreeZone* freeZone = freeZoneDef->makeFreeZone(binding, matchQuality);
     439         [ +  + ]:      22018 :   if (!freeZone->isConvex())
     440                 :            :   {
     441                 :          4 :     emptyFreeZone = false;
     442                 :            :   }
     443                 :            : 
     444                 :      22018 :   const std::list<const AF2Point2D*>* ngbhdPoints = ngbhd.getPoints2D();
     445 [ +  - ][ +  + ]:    1574238 :   for (std::list<const AF2Point2D*>::const_iterator itr = ngbhdPoints->begin();
     446 [ +  + ][ +  - ]:    1046882 :       emptyFreeZone && itr != ngbhdPoints->end(); ++itr)
         [ +  + ][ +  + ]
                 [ #  # ]
     447                 :            :   {
     448 [ +  - ][ +  - ]:     505338 :     emptyFreeZone = !freeZone->nearContains(**itr);
     449                 :            :   }
     450                 :            : 
     451                 :      22018 :   const std::list<const AF2Edge2D*>* ngbhdEdges = ngbhd.getEdges2D();
     452 [ +  - ][ +  + ]:     966408 :   for (std::list<const AF2Edge2D*>::const_iterator itr = ngbhdEdges->begin();
     453 [ +  + ][ +  - ]:     639422 :       emptyFreeZone && itr != ngbhdEdges->end(); ++itr)
         [ +  + ][ +  + ]
                 [ #  # ]
     454                 :            :   {
     455                 :            :     emptyFreeZone = !freeZone->nearIntersects(
     456 [ +  - ][ +  - ]:     304968 :         *((*itr)->getStart()), *((*itr)->getEnd()));
         [ +  - ][ +  - ]
                 [ +  - ]
     457                 :            :   }
     458                 :            : 
     459         [ +  - ]:      22018 :   delete freeZone;
     460                 :            : 
     461         [ +  + ]:      22018 :   if (emptyFreeZone)
     462                 :            :   {
     463                 :            :     // This binding would be an acceptable way to apply the rule, so
     464                 :            :     // build an AF2RuleApplication and pass it to the visitor
     465 [ +  - ][ +  - ]:       7468 :     const AF2Point2D** newPointsArray = new const AF2Point2D*[numNewVertices];
     466         [ +  - ]:       7468 :     std::list<const AF2Point2D*> newPointsList;
     467         [ +  + ]:      12201 :     for (unsigned int nvi = 0; nvi < numNewVertices; ++nvi)
     468                 :            :     {
     469                 :       4733 :       newPointsArray[nvi] =
     470 [ +  - ][ +  - ]:       4733 :           new AF2Point2D(newVertices[nvi]->getLocation(binding));
     471         [ +  - ]:       4733 :       newPointsList.push_back(newPointsArray[nvi]);
     472                 :            :     }
     473                 :            : 
     474         [ +  - ]:      14936 :     std::list<const AF2Polygon2D*> newPolygonsList;
     475         [ +  + ]:      18531 :     for (unsigned int nfi = 0; nfi < numNewFaces; ++nfi)
     476                 :            :     {
     477         [ +  - ]:      11063 :       std::list<const AF2Point2D*> polygonVertices;
     478 [ +  - ][ +  + ]:      44252 :       for (unsigned int fvi = 0; fvi < newFaces[nfi]->getNumVertices(); ++fvi)
     479                 :            :       {
     480         [ +  - ]:      33189 :         unsigned int polyVertIndex = newFaces[nfi]->getVertexIndex(fvi);
     481         [ +  + ]:      33189 :         if (polyVertIndex < numExVertices)
     482                 :            :         {
     483                 :            :           polygonVertices.push_back(binding.getBoundValue(
     484 [ +  - ][ +  - ]:      24862 :               exVertices[polyVertIndex]));
     485                 :            :         }
     486                 :            :         else
     487                 :            :         {
     488                 :            :           polygonVertices.push_back(
     489         [ +  - ]:       8327 :               newPointsArray[polyVertIndex - numExVertices]);
     490                 :            :         }
     491                 :            :       }
     492 [ +  - ][ +  - ]:      11063 :       newPolygonsList.push_back(new AF2Polygon2D(polygonVertices));
                 [ +  - ]
     493                 :      11063 :     }
     494                 :            : 
     495                 :            :     AF2RuleApplication* ruleApplication =
     496 [ +  - ][ +  - ]:       7468 :         new AF2RuleApplication(newPointsList, newPolygonsList);
     497         [ +  - ]:       7468 :     visitor.visit(*ruleApplication);
     498                 :            : 
     499                 :            :     // clean up memory allocated to define the rule application
     500         [ +  - ]:       7468 :     delete ruleApplication;
     501 [ +  - ][ +  - ]:      37062 :     for (std::list<const AF2Polygon2D*>::const_iterator itr =
                 [ +  + ]
     502 [ +  - ][ +  - ]:      25999 :         newPolygonsList.begin(); itr != newPolygonsList.end(); ++itr)
     503                 :            :     {
     504 [ +  - ][ +  - ]:      11063 :       delete *itr;
     505                 :            :     }
     506         [ +  + ]:      12201 :     for (unsigned int nvi = 0; nvi < numNewVertices; ++nvi)
     507                 :            :     {
     508                 :       4733 :       delete newPointsArray[nvi];
     509                 :            :     }
     510         [ +  - ]:      14936 :     delete[] newPointsArray;
     511                 :            :   }
     512                 :      22018 : }

Generated by: LCOV version 1.11