Salome HOME
Copyright update 2022
[tools/medcoupling.git] / src / INTERP_KERNEL / Geometric2D / InterpKernelGeo2DQuadraticPolygon.cxx
index 7494e5328b275c1089b3c7f2b52eab84ba5392b6..f6c1ee3164a5cbcf525d754ca07fad61c474a9b4 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2019  CEA/DEN, EDF R&D
+// Copyright (C) 2007-2022  CEA/DEN, EDF R&D
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
@@ -540,10 +540,10 @@ void QuadraticPolygon::buildFromCrudeDataArray2(const std::map<mcIdType,INTERP_K
             {
               mcIdType idBg=direct?subEdge[2*j]:subEdge[2*nbOfSubEdges-2*j-1];
               mcIdType idEnd=direct?subEdge[2*j+1]:subEdge[2*nbOfSubEdges-2*j-2];
-              bool direction11,found=false;
-              bool direct1;//store if needed the direction in 1
-              mcIdType offset2;
-              mcIdType nbOfSubEdges1;
+              bool direction11=false,found=false;
+              bool direct1=false;//store if needed the direction in 1
+              mcIdType offset2=0;
+              mcIdType nbOfSubEdges1=0;
               for(std::vector<std::pair<mcIdType,std::pair<bool,mcIdType> > >::const_iterator it=idIns1.begin();it!=idIns1.end() && !found;it++)
                 {
                   mcIdType idIn1=(*it).first;//store if needed the cell id in 1
@@ -672,8 +672,8 @@ void QuadraticPolygon::appendCrudeData(const std::map<INTERP_KERNEL::Node *,mcId
 /*!
  * This method make the hypothesis that \a this and \a other are split at the minimum into edges that are fully IN, OUT or ON.
  * This method returns newly created polygons in \a conn and \a connI and the corresponding ids ( \a idThis, \a idOther) are stored respectively into \a nbThis and \a nbOther.
- * @param [in,out] edgesThis, parameter that keep informed the caller about the edges in this not shared by the result of intersection of \a this with \a other
- * @param [in,out] edgesBoundaryOther, parameter that stores all edges in result of intersection that are not
+ * @param [in,out] edgesThis parameter that keep informed the caller about the edges in this not shared by the result of intersection of \a this with \a other
+ * @param [in,out] edgesBoundaryOther parameter that stores all edges in result of intersection that are not
  */
 void QuadraticPolygon::buildPartitionsAbs(QuadraticPolygon& other, std::set<INTERP_KERNEL::Edge *>& edgesThis, std::set<INTERP_KERNEL::Edge *>& edgesBoundaryOther,
                                           const std::map<INTERP_KERNEL::Node *,mcIdType>& mapp, mcIdType idThis, mcIdType idOther, mcIdType offset,
@@ -1080,7 +1080,7 @@ std::list<QuadraticPolygon *> QuadraticPolygon::zipConsecutiveInSegments() const
 }
 
 /*!
- * @param [in] pol1zip is a list of set of edges (=an opened polygon) coming from split polygon 1.
+ * @param [in] pol1Zip is a list of set of edges (=an opened polygon) coming from split polygon 1.
  * @param [in] pol1 should be considered as pol1Simplified.
  * @param [in] pol2 is split pol2.
  * @param [out] results the resulting \b CLOSED polygons.
@@ -1089,7 +1089,7 @@ void QuadraticPolygon::ClosePolygons(std::list<QuadraticPolygon *>& pol1Zip, con
                                      std::vector<QuadraticPolygon *>& results)
 {
   bool directionKnownInPol2=false;
-  bool directionInPol2;
+  bool directionInPol2=false;
   bool needCleaning = false;
   for(std::list<QuadraticPolygon *>::iterator iter=pol1Zip.begin();iter!=pol1Zip.end();)
     {
@@ -1304,24 +1304,55 @@ void QuadraticPolygon::ComputeResidual(const QuadraticPolygon& pol1, const std::
       // retPolsUnderConstruction initially empty -> see if(!pol1Zip.empty()) below ...
       for(std::list<QuadraticPolygon *>::iterator itConstr=retPolsUnderContruction.begin();itConstr!=retPolsUnderContruction.end();)
         {
-          if((*itConstr)->getStartNode()==(*itConstr)->getEndNode())  // reconstruction of a cell is finished
-            {
-              itConstr++;
-              continue;
-            }
-          Node *curN=(*itConstr)->getEndNode();
-          bool smthHappened=false;
-          // Complete a partially reconstructed polygon with boundary edges by matching nodes:
+          Node *startN = (*itConstr)->getStartNode();
+          Node *curN = (*itConstr)->getEndNode();
+          if(startN == curN)  // reconstruction of a cell is finished
+            {  itConstr++; continue;  }
+
+          bool smthHappened=false, doneEarly=false;
+          // Complete a partially reconstructed polygon with boundary edges of pol2 by matching nodes:
           for(std::list<Edge *>::iterator it2=edgesInPol2OnBoundaryL.begin();it2!=edgesInPol2OnBoundaryL.end();)
             {
-              if(curN==(*it2)->getStartNode())
-                { (*it2)->incrRef(); (*itConstr)->pushBack(new ElementaryEdge(*it2,true)); curN=(*it2)->getEndNode(); smthHappened=true; it2=edgesInPol2OnBoundaryL.erase(it2); }
-              else if(curN==(*it2)->getEndNode())
-                { (*it2)->incrRef(); (*itConstr)->pushBack(new ElementaryEdge(*it2,false)); curN=(*it2)->getStartNode(); smthHappened=true; it2=edgesInPol2OnBoundaryL.erase(it2); }
+              if(curN==(*it2)->getEndNode())  // only end node should be considered if orientation is correct for input meshes
+                                              // in the funny case of cells exactly included (see test case testIntersect2DMeshesTmp13) this is mandatory to take edges from pol2 in the right order.
+                {
+                  (*it2)->incrRef();
+                  (*itConstr)->pushBack(new ElementaryEdge(*it2,false));
+                  curN=(*it2)->getStartNode();
+                  smthHappened=true;
+                  it2=edgesInPol2OnBoundaryL.erase(it2);
+                }
               else
                 it2++;
+              if (curN == startN) // we might end here
+                { doneEarly = true;  break;  }
+            }
+
+          // It might be the case that the lookup on start nodes made above failed because pol2 is wrongly oriented.
+          // Be somewhat flexible and keep on supporting this case here (useful for voronisation notably):
+          if(!smthHappened)
+            {
+              for(std::list<Edge *>::iterator it2=edgesInPol2OnBoundaryL.begin();it2!=edgesInPol2OnBoundaryL.end();)
+                {
+                  if(curN==(*it2)->getStartNode())
+                    {
+                      (*it2)->incrRef();
+                      (*itConstr)->pushBack(new ElementaryEdge(*it2,true));
+                      curN=(*it2)->getEndNode();
+                      smthHappened=true;
+                      it2=edgesInPol2OnBoundaryL.erase(it2);
+                    }
+                  else
+                    it2++;
+                  if (curN == startN) // we might end here
+                      { doneEarly = true;  break;  }
+                }
             }
-          if(smthHappened)
+
+          if (doneEarly)
+            {  itConstr++; continue;  }
+
+          if(smthHappened) // Now continue the construction by finding the next bit in pol1Zip. Not too sure what are the cases where the boolean if False ...
             {
               for(std::list<QuadraticPolygon *>::iterator itZip=pol1Zip.begin();itZip!=pol1Zip.end();)
                 {
@@ -1338,7 +1369,7 @@ void QuadraticPolygon::ComputeResidual(const QuadraticPolygon& pol1, const std::
                     itZip++;
                 }
             }
-          else
+          else // Nothing happened.
             {
               for(std::list<ElementaryEdge *>::const_iterator it5=(*itConstr)->_sub_edges.begin();it5!=(*itConstr)->_sub_edges.end();it5++)
                 {