]> SALOME platform Git repositories - tools/medcoupling.git/commitdiff
Salome HOME
Intersection of 2D mesh with a 1D line: Intersect2DMeshWith1DLine
authorabn <adrien.bruneton@cea.fr>
Mon, 12 May 2014 14:36:37 +0000 (16:36 +0200)
committerabn <adrien.bruneton@cea.fr>
Mon, 12 May 2014 14:36:37 +0000 (16:36 +0200)
First working version. Still some doc and code re-factoring to be done.

12 files changed:
src/INTERP_KERNEL/Geometric2D/InterpKernelGeo2DComposedEdge.cxx
src/INTERP_KERNEL/Geometric2D/InterpKernelGeo2DComposedEdge.hxx
src/INTERP_KERNEL/Geometric2D/InterpKernelGeo2DElementaryEdge.cxx
src/INTERP_KERNEL/Geometric2D/InterpKernelGeo2DElementaryEdge.hxx
src/INTERP_KERNEL/Geometric2D/InterpKernelGeo2DQuadraticPolygon.cxx
src/INTERP_KERNEL/Geometric2D/InterpKernelGeo2DQuadraticPolygon.hxx
src/MEDCoupling/MEDCouplingUMesh.cxx
src/MEDCoupling/MEDCouplingUMesh.hxx
src/MEDCoupling/Test/MEDCouplingBasicsTest5.cxx
src/MEDCoupling/Test/MEDCouplingBasicsTest5.hxx
src/MEDCoupling_Swig/MEDCouplingBasicsTest.py
src/MEDCoupling_Swig/MEDCouplingCommon.i

index e3a7385308c96aa1e7b055d8e58f7e32cae479ef..2d3a1d9184992774f8213813c35c0b31a5bd6ff9 100644 (file)
@@ -137,7 +137,7 @@ void ComposedEdge::initLocations() const
 }
 
 /**
- * Reset the status of all edges (OUT, IN, ON) because they were potentially assignated
+ * Reset the status of all edges (OUT, IN, ON) because they were potentially assigned
  * by the previous candidate processing.
  */
 void ComposedEdge::initLocationsWithOther(const ComposedEdge& other) const
index e014d59428c5bd882aa325f2ace562aff4d9e349..142a7cc8d1ea3575cfb1d67d68f57464aa7fb85e 100644 (file)
@@ -37,6 +37,11 @@ namespace INTERP_KERNEL
   class ElementaryEdge;
   class IteratorOnComposedEdge;
 
+  /**
+     * A set of quadratic or linear edges, described mainly by their connectivity
+     * The set is assumed to be connected, but not necessarily closed (i.e. not necessarily forming a closed polygon).
+     * Some methods however requires a closed form.
+  */
   class ComposedEdge
   {
     friend class IteratorOnComposedEdge;
index 45088dbef42cce33c2b8f8fb3b0b0b3f7b195718..4db25de03e02b098484b11b138a37e1fd13d56fb 100644 (file)
@@ -223,10 +223,9 @@ void ElementaryEdge::fillGlobalInfoAbs2(const std::map<INTERP_KERNEL::Node *,int
 }
 
 /*!
- * This method builds from descending conn of a quadratic polygon stored in crude mode (MEDCoupling). Descending conn is in FORTRAN relative mode in order to give the
- * orientation of edge. Called by QuadraticPolygon::buildFromCrudeDataArray.
+ * This method builds from a start node, an end node and a direction a new ElementaryEdge.
  */
-ElementaryEdge *ElementaryEdge::BuildEdgeFromCrudeDataArray(bool direction, INTERP_KERNEL::Node *start, INTERP_KERNEL::Node *end)
+ElementaryEdge *ElementaryEdge::BuildEdgeFromStartEndDir(bool direction, INTERP_KERNEL::Node *start, INTERP_KERNEL::Node *end)
 {
   Edge *ptr=Edge::BuildEdgeFrom(start,end);
   return new ElementaryEdge(ptr,direction);
index 06ada0fb6fca716dd491e2e86e23425122999200..26b19a0735549f80173e4065c71e9c0d46fa80ad 100644 (file)
@@ -72,7 +72,7 @@ namespace INTERP_KERNEL
                                                std::vector<int>& edgesThis, std::vector<double>& addCoo, std::map<INTERP_KERNEL::Node *,int> mapAddCoo) const;
     INTERPKERNEL_EXPORT void fillGlobalInfoAbs2(const std::map<INTERP_KERNEL::Node *,int>& mapThis, const std::map<INTERP_KERNEL::Node *,int>& mapOther, int offset1, int offset2, double fact, double baryX, double baryY,
                                                 std::vector<int>& edgesOther, std::vector<double>& addCoo, std::map<INTERP_KERNEL::Node *,int>& mapAddCoo) const;
-    INTERPKERNEL_EXPORT static ElementaryEdge *BuildEdgeFromCrudeDataArray(bool direction, INTERP_KERNEL::Node *start, INTERP_KERNEL::Node *end);
+    INTERPKERNEL_EXPORT static ElementaryEdge *BuildEdgeFromStartEndDir(bool direction, INTERP_KERNEL::Node *start, INTERP_KERNEL::Node *end);
   private:
     bool _direction;
     Edge *_ptr;
index 5df47c7fcba43cbe3c507abe6b8355bc089d2eff..255f9a0801bbadbbc68d7dc2566c75dadee8b8cd 100644 (file)
@@ -408,6 +408,57 @@ void QuadraticPolygon::appendEdgeFromCrudeDataArray(std::size_t edgePos, const s
     }
 }
 
+void QuadraticPolygon::appendEdgeFromCrudeDataArray2(const std::map<int,INTERP_KERNEL::Node *>& mapp, bool isQuad,
+                                                    const int *nodalBg, const double *coords,
+                                                    const int segId, const std::vector<std::vector<int> >& intersectEdges)
+{
+  if(!isQuad)
+    {
+      bool direct=true;
+      int edgeId=segId;
+      const std::vector<int>& subEdge=intersectEdges[edgeId];
+      std::size_t nbOfSubEdges=subEdge.size()/2;
+      for(std::size_t j=0;j<nbOfSubEdges;j++)
+        appendSubEdgeFromCrudeDataArray(0,j,direct,edgeId,subEdge,mapp);
+    }
+  else
+    {
+      std::size_t nbOfSeg; //=std::distance(descBg,descEnd);
+      nbOfSeg = 1;
+      const double *st=coords+2*(nodalBg[0]);
+      INTERP_KERNEL::Node *st0=new INTERP_KERNEL::Node(st[0],st[1]);
+      const double *endd=coords+2*(nodalBg[1]);
+      INTERP_KERNEL::Node *endd0=new INTERP_KERNEL::Node(endd[0],endd[1]);
+      const double *middle=coords+2*(nodalBg[2]);
+      INTERP_KERNEL::Node *middle0=new INTERP_KERNEL::Node(middle[0],middle[1]);
+      EdgeLin *e1,*e2;
+      e1=new EdgeLin(st0,middle0);
+      e2=new EdgeLin(middle0,endd0);
+      SegSegIntersector inters(*e1,*e2);
+      bool colinearity=inters.areColinears();
+      delete e1; delete e2;
+      //
+      bool direct=true;
+      int edgeId=segId;
+      const std::vector<int>& subEdge=intersectEdges[edgeId];
+      std::size_t nbOfSubEdges=subEdge.size()/2;
+      if(colinearity)
+        {
+          for(std::size_t j=0;j<nbOfSubEdges;j++)
+            appendSubEdgeFromCrudeDataArray(0,j,direct,edgeId,subEdge,mapp);
+        }
+      else
+        {
+          Edge *e=new EdgeArcCircle(st0,middle0,endd0,true);
+          for(std::size_t j=0;j<nbOfSubEdges;j++)
+            appendSubEdgeFromCrudeDataArray(e,j,direct,edgeId,subEdge,mapp);
+          e->decrRef();
+        }
+      st0->decrRef(); endd0->decrRef(); middle0->decrRef();
+    }
+}
+
+
 void QuadraticPolygon::appendSubEdgeFromCrudeDataArray(Edge *baseEdge, std::size_t j, bool direct, int edgeId, const std::vector<int>& subEdge, const std::map<int,INTERP_KERNEL::Node *>& mapp)
 {
   std::size_t nbOfSubEdges=subEdge.size()/2;
@@ -415,7 +466,7 @@ void QuadraticPolygon::appendSubEdgeFromCrudeDataArray(Edge *baseEdge, std::size
     {//it is not a quadratic subedge
       Node *start=(*mapp.find(direct?subEdge[2*j]:subEdge[2*nbOfSubEdges-2*j-1])).second;
       Node *end=(*mapp.find(direct?subEdge[2*j+1]:subEdge[2*nbOfSubEdges-2*j-2])).second;
-      ElementaryEdge *e=ElementaryEdge::BuildEdgeFromCrudeDataArray(true,start,end);
+      ElementaryEdge *e=ElementaryEdge::BuildEdgeFromStartEndDir(true,start,end);
       pushBack(e);
     }
   else
@@ -429,8 +480,10 @@ void QuadraticPolygon::appendSubEdgeFromCrudeDataArray(Edge *baseEdge, std::size
 }
 
 /*!
- * This method builds from descending conn of a quadratic polygon stored in crude mode (MEDCoupling). Descending conn is in FORTRAN relative mode in order to give the
+ * This method builds a QP from the descending conn of a cell stored in crude mode (MEDCoupling). Descending conn is in FORTRAN relative mode in order, to give the
  * orientation of edge.
+ * The information stored in intersectEdges1 and colinear1 is also used to know which intermediate nodes (intersection points with the other polygon) should be considered
+ * on the edges.
  */
 void QuadraticPolygon::buildFromCrudeDataArray2(const std::map<int,INTERP_KERNEL::Node *>& mapp, bool isQuad, const int *nodalBg, const double *coords, const int *descBg, const int *descEnd, const std::vector<std::vector<int> >& intersectEdges,
                                                 const INTERP_KERNEL::QuadraticPolygon& pol1, const int *descBg1, const int *descEnd1, const std::vector<std::vector<int> >& intersectEdges1,
@@ -530,7 +583,7 @@ void QuadraticPolygon::buildFromCrudeDataArray2(const std::map<int,INTERP_KERNEL
                   //appendEdgeFromCrudeDataArray(j,mapp,isQuad,nodalBg,coords,descBg,descEnd,intersectEdges);
                   Node *start=(*mapp.find(idBg)).second;
                   Node *end=(*mapp.find(idEnd)).second;
-                  ElementaryEdge *e=ElementaryEdge::BuildEdgeFromCrudeDataArray(true,start,end);
+                  ElementaryEdge *e=ElementaryEdge::BuildEdgeFromStartEndDir(true,start,end);
                   pushBack(e);
                   alreadyExistingIn2[descBg[i]].push_back(e);
                 }
@@ -548,14 +601,164 @@ void QuadraticPolygon::buildFromCrudeDataArray2(const std::map<int,INTERP_KERNEL
     }
 }
 
+void QuadraticPolygon::buildFromCrudeDataArray3(const std::map<int,INTERP_KERNEL::Node *>& mapp, bool isQuad, const int *nodalBg, const double *coords, const int segId, const std::vector<std::vector<int> >& intersectEdges,
+                                                const INTERP_KERNEL::QuadraticPolygon& pol1, const int *descBg1, const int *descEnd1, const std::vector<std::vector<int> >& intersectEdges1,
+                                                const std::vector< std::vector<int> >& colinear1,
+                                                std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> >& alreadyExistingIn2)
+{
+  bool direct=true;
+  int edgeId=segId;//current edge id of pol2
+  std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> >::const_iterator it1=alreadyExistingIn2.find(segId);
+  if(it1!=alreadyExistingIn2.end())
+    {
+      const std::vector<INTERP_KERNEL::ElementaryEdge *>& edgesAlreadyBuilt=(*it1).second;
+      for(std::vector<INTERP_KERNEL::ElementaryEdge *>::const_iterator it3=edgesAlreadyBuilt.begin();it3!=edgesAlreadyBuilt.end();it3++)
+        {
+          Edge *ee=(*it3)->getPtr(); ee->incrRef();
+          pushBack(new ElementaryEdge(ee,(*it3)->getDirection()));
+        }
+      return;
+    }
+  bool directos=colinear1[edgeId].empty();
+  std::vector<std::pair<int,std::pair<bool,int> > > idIns1;
+  int offset1=0;
+  if(!directos)
+    {// if the current edge of pol2 has one or more colinear edges part into pol1
+      const std::vector<int>& c=colinear1[edgeId];
+      std::size_t nbOfEdgesIn1=std::distance(descBg1,descEnd1);
+      for(std::size_t j=0;j<nbOfEdgesIn1;j++)
+        {
+          int edgeId1=abs(descBg1[j])-1;
+          if(std::find(c.begin(),c.end(),edgeId1)!=c.end())
+            {
+              idIns1.push_back(std::pair<int,std::pair<bool,int> >(edgeId1,std::pair<bool,int>(descBg1[j]>0,offset1)));// it exists an edge into pol1 given by tuple (idIn1,direct1) that is colinear at edge 'edgeId' in pol2
+              //std::pair<edgeId1); direct1=descBg1[j]>0;
+            }
+          offset1+=intersectEdges1[edgeId1].size()/2;//offset1 is used to find the INTERP_KERNEL::Edge * instance into pol1 that will be part of edge into pol2
+        }
+      directos=idIns1.empty();
+    }
+  if(directos)
+    {//no subpart of edge 'edgeId' of pol2 is in pol1 so let's operate the same thing that QuadraticPolygon::buildFromCrudeDataArray method
+      std::size_t oldSz=_sub_edges.size();
+      appendEdgeFromCrudeDataArray2(mapp,isQuad,nodalBg,coords,segId,intersectEdges);
+      std::size_t newSz=_sub_edges.size();
+      std::size_t zeSz=newSz-oldSz;
+      alreadyExistingIn2[segId].resize(zeSz);
+      std::list<ElementaryEdge *>::const_reverse_iterator it5=_sub_edges.rbegin();
+      for(std::size_t p=0;p<zeSz;p++,it5++)
+        alreadyExistingIn2[segId][zeSz-p-1]=*it5;
+    }
+  else
+    {//there is subpart of edge 'edgeId' of pol2 inside pol1
+      const std::vector<int>& subEdge=intersectEdges[edgeId];
+      std::size_t nbOfSubEdges=subEdge.size()/2;
+      for(std::size_t j=0;j<nbOfSubEdges;j++)
+        {
+          int idBg=direct?subEdge[2*j]:subEdge[2*nbOfSubEdges-2*j-1];
+          int 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
+          int offset2;
+          std::size_t nbOfSubEdges1;
+          for(std::vector<std::pair<int,std::pair<bool,int> > >::const_iterator it=idIns1.begin();it!=idIns1.end() && !found;it++)
+            {
+              int idIn1=(*it).first;//store if needed the cell id in 1
+              direct1=(*it).second.first;
+              offset1=(*it).second.second;
+              const std::vector<int>& subEdge1PossiblyAlreadyIn1=intersectEdges1[idIn1];
+              nbOfSubEdges1=subEdge1PossiblyAlreadyIn1.size()/2;
+              offset2=0;
+              for(std::size_t k=0;k<nbOfSubEdges1 && !found;k++)
+                {//perform a loop on all subedges of pol1 that includes edge 'edgeId' of pol2. For the moment we iterate only on subedges of ['idIn1']... To improve
+                  if(subEdge1PossiblyAlreadyIn1[2*k]==idBg && subEdge1PossiblyAlreadyIn1[2*k+1]==idEnd)
+                    { direction11=true; found=true; }
+                  else if(subEdge1PossiblyAlreadyIn1[2*k]==idEnd && subEdge1PossiblyAlreadyIn1[2*k+1]==idBg)
+                    { direction11=false; found=true; }
+                  else
+                    offset2++;
+                }
+            }
+          if(!found)
+            {//the current subedge of edge 'edgeId' of pol2 is not a part of the colinear edge 'idIn1' of pol1 -> build new Edge instance
+              //appendEdgeFromCrudeDataArray(j,mapp,isQuad,nodalBg,coords,descBg,descEnd,intersectEdges);
+              Node *start=(*mapp.find(idBg)).second;
+              Node *end=(*mapp.find(idEnd)).second;
+              ElementaryEdge *e=ElementaryEdge::BuildEdgeFromStartEndDir(true,start,end);
+              pushBack(e);
+              alreadyExistingIn2[segId].push_back(e);
+            }
+          else
+            {//the current subedge of edge 'edgeId' of pol2 is part of the colinear edge 'idIn1' of pol1 -> reuse Edge instance of pol1
+              ElementaryEdge *e=pol1[offset1+(direct1?offset2:nbOfSubEdges1-offset2-1)];
+              Edge *ee=e->getPtr();
+              ee->incrRef();
+              ElementaryEdge *e2=new ElementaryEdge(ee,!(direct1^direction11));
+              pushBack(e2);
+              alreadyExistingIn2[segId].push_back(e2);
+            }
+        }
+    }
+}
+
+/**
+ * @param edgeId current edge id of pol2
+ */
+void QuadraticPolygon::updateLocOfEdgeFromCrudeDataArray(const int edgeId, const std::vector<std::vector<int> >& intersectEdges,
+                                                         const INTERP_KERNEL::QuadraticPolygon& pol1, const int *descBg1, const int *descEnd1,
+                                                         const std::vector<std::vector<int> >& intersectEdges1, const std::vector< std::vector<int> >& colinear1) const
+{
+  std::size_t nbOfEdgesIn1=std::distance(descBg1,descEnd1);
+  const std::vector<int>& c=colinear1[edgeId];
+  if(c.empty())
+    return;
+  const std::vector<int>& subEdge=intersectEdges[edgeId];
+  std::size_t nbOfSubEdges=subEdge.size()/2;
+  //
+  int offset1=0;
+  for(std::size_t j=0;j<nbOfEdgesIn1;j++)
+    {
+      int edgeId1=abs(descBg1[j])-1;
+      if(std::find(c.begin(),c.end(),edgeId1)!=c.end())
+        {
+          for(std::size_t k=0;k<nbOfSubEdges;k++)
+            {
+              int idBg = subEdge[2*k];
+              int idEnd = subEdge[2*k+1];
+              int idIn1=edgeId1;
+              bool direct1=descBg1[j]>0;
+              const std::vector<int>& subEdge1PossiblyAlreadyIn1=intersectEdges1[idIn1];
+              std::size_t nbOfSubEdges1=subEdge1PossiblyAlreadyIn1.size()/2;
+              int offset2=0;
+              bool found=false;
+              for(std::size_t kk=0;kk<nbOfSubEdges1 && !found;kk++)
+                {
+                  found=(subEdge1PossiblyAlreadyIn1[2*kk]==idBg && subEdge1PossiblyAlreadyIn1[2*kk+1]==idEnd) || \
+                      (subEdge1PossiblyAlreadyIn1[2*kk]==idEnd && subEdge1PossiblyAlreadyIn1[2*kk+1]==idBg);
+                  if(!found)
+                    offset2++;
+                }
+              if(found)
+                {
+                  ElementaryEdge *e=pol1[offset1+(direct1?offset2:nbOfSubEdges1-offset2-1)];
+                  e->getPtr()->declareOn();
+                }
+            }
+        }
+      offset1+=intersectEdges1[edgeId1].size()/2;//offset1 is used to find the INTERP_KERNEL::Edge * instance into pol1 that will be part of edge into pol2
+    }
+}
+
+
 /*!
  * Method expected to be called on pol2. Every params not suffixed by numbered are supposed to refer to pol2 (this).
- * Method to find edges that are ON.
+ * Method to find edges that are ON, and mark them correspondingly on pol1.
  */
 void QuadraticPolygon::updateLocOfEdgeFromCrudeDataArray2(const int *descBg, const int *descEnd, const std::vector<std::vector<int> >& intersectEdges,
                                                           const INTERP_KERNEL::QuadraticPolygon& pol1, const int *descBg1, const int *descEnd1,
                                                           const std::vector<std::vector<int> >& intersectEdges1, const std::vector< std::vector<int> >& colinear1) const
 {
+  std::size_t nbOfEdgesIn1=std::distance(descBg1,descEnd1);
   std::size_t nbOfSeg=std::distance(descBg,descEnd);
   for(std::size_t i=0;i<nbOfSeg;i++)//loop over all edges of pol2
     {
@@ -567,7 +770,6 @@ void QuadraticPolygon::updateLocOfEdgeFromCrudeDataArray2(const int *descBg, con
       const std::vector<int>& subEdge=intersectEdges[edgeId];
       std::size_t nbOfSubEdges=subEdge.size()/2;
       //
-      std::size_t nbOfEdgesIn1=std::distance(descBg1,descEnd1);
       int offset1=0;
       for(std::size_t j=0;j<nbOfEdgesIn1;j++)
         {
@@ -586,7 +788,8 @@ void QuadraticPolygon::updateLocOfEdgeFromCrudeDataArray2(const int *descBg, con
                   bool found=false;
                   for(std::size_t kk=0;kk<nbOfSubEdges1 && !found;kk++)
                     {
-                      found=(subEdge1PossiblyAlreadyIn1[2*kk]==idBg && subEdge1PossiblyAlreadyIn1[2*kk+1]==idEnd) || (subEdge1PossiblyAlreadyIn1[2*kk]==idEnd && subEdge1PossiblyAlreadyIn1[2*kk+1]==idBg);
+                      found=(subEdge1PossiblyAlreadyIn1[2*kk]==idBg && subEdge1PossiblyAlreadyIn1[2*kk+1]==idEnd) || \
+                            (subEdge1PossiblyAlreadyIn1[2*kk]==idEnd && subEdge1PossiblyAlreadyIn1[2*kk+1]==idBg);
                       if(!found)
                         offset2++;
                     }
@@ -602,7 +805,7 @@ void QuadraticPolygon::updateLocOfEdgeFromCrudeDataArray2(const int *descBg, con
     }
 }
 
-void QuadraticPolygon::appendCrudeData(const std::map<INTERP_KERNEL::Node *,int>& mapp, double xBary, double yBary, double fact, int offset, std::vector<double>& addCoordsQuadratic, std::vector<int>& conn, std::vector<int>& connI) const
+void QuadraticPolygon::appendCrudeData(const std::map<INTERP_KERNEL::Node *,int>& mapp, int offset, std::vector<double>& addCoordsQuadratic, std::vector<int>& conn, std::vector<int>& connI) const
 {
   int nbOfNodesInPg=0;
   bool presenceOfQuadratic=presenceOfQuadraticEdge();
@@ -622,7 +825,7 @@ void QuadraticPolygon::appendCrudeData(const std::map<INTERP_KERNEL::Node *,int>
       for(std::list<ElementaryEdge *>::const_iterator it=_sub_edges.begin();it!=_sub_edges.end();it++,j++,nbOfNodesInPg++)
         {
           INTERP_KERNEL::Node *node=(*it)->getPtr()->buildRepresentantOfMySelf();
-          node->unApplySimilarity(xBary,yBary,fact);
+          //node->unApplySimilarity(xBary,yBary,fact);
           addCoordsQuadratic.push_back((*node)[0]);
           addCoordsQuadratic.push_back((*node)[1]);
           conn.push_back(off+j);
@@ -633,21 +836,26 @@ void QuadraticPolygon::appendCrudeData(const std::map<INTERP_KERNEL::Node *,int>
 }
 
 /*!
- * This method make the hypothesis that 'this' and 'other' are splited at the minimum into edges that are fully IN, OUT or ON.
+ * This method make the hypothesis that 'this' and 'other' are split at the minimum into edges that are fully IN, OUT or ON.
  * This method returns newly created polygons in 'conn' and 'connI' and the corresponding ids ('idThis','idOther') are stored respectively into 'nbThis' and 'nbOther'.
- * @param [in,out] edgesThis, parameter that keep informed the caller abount the edges in this not shared by the result of intersection of \a this with \a other
- * @param [in,out] edgesBoundaryOther, parameter that strores 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 *,int>& mapp, int idThis, int idOther, int offset, std::vector<double>& addCoordsQuadratic, std::vector<int>& conn, std::vector<int>& connI, std::vector<int>& nbThis, std::vector<int>& nbOther)
+void QuadraticPolygon::buildPartitionsAbs(QuadraticPolygon& other, std::set<INTERP_KERNEL::Edge *>& edgesThis,
+                                          std::set<INTERP_KERNEL::Edge *>& edgesBoundaryOther, const std::map<INTERP_KERNEL::Node *,int>& mapp,
+                                          int idThis, int idOther, int offset, std::vector<double>& addCoordsQuadratic, std::vector<int>& conn,
+                                          std::vector<int>& connI, std::vector<int>& nbThis, std::vector<int>& nbOther)
 {
   double xBaryBB, yBaryBB;
   double fact=normalizeExt(&other, xBaryBB, yBaryBB);
-  //Locate 'this' relative to 'other'
+  //Locate 'this' relative to 'other' (edges of 'this', aka 'pol1' are marked as IN or OUT)
   other.performLocatingOperationSlow(*this);  // without any assumption
-  std::vector<QuadraticPolygon *> res=buildIntersectionPolygons(other,*this);
+  std::vector<QuadraticPolygon *> res = BuildIntersectionPolygons(other,*this);
+  unApplyGlobalSimilarityExt(other,xBaryBB,yBaryBB,fact);
+
   for(std::vector<QuadraticPolygon *>::iterator it=res.begin();it!=res.end();it++)
     {
-      (*it)->appendCrudeData(mapp,xBaryBB,yBaryBB,fact,offset,addCoordsQuadratic,conn,connI);
+      (*it)->appendCrudeData(mapp,offset,addCoordsQuadratic,conn,connI);
       INTERP_KERNEL::IteratorOnComposedEdge it1(*it);
       for(it1.first();!it1.finished();it1.next())
         {
@@ -666,9 +874,64 @@ void QuadraticPolygon::buildPartitionsAbs(QuadraticPolygon& other, std::set<INTE
       nbOther.push_back(idOther);
       delete *it;
     }
-  unApplyGlobalSimilarityExt(other,xBaryBB,yBaryBB,fact);
 }
 
+void QuadraticPolygon::BuildPartitionFromZipList(const QuadraticPolygon & pol1, const std::list<INTERP_KERNEL::QuadraticPolygon *> & zip_list,
+                                                 std::set<INTERP_KERNEL::Edge *> & edgesThis, std::set<INTERP_KERNEL::Edge *> & edgesBoundaryOther,
+                                                 const std::map<INTERP_KERNEL::Node *,int>& mapp,
+                                                 const int idThis, const std::vector<std::vector<int> > & mapZipTo2,
+                                                 int offset, std::vector<double>& addCoordsQuadratic,
+                                                 std::vector<int>& conn,std::vector<int>& connI,
+                                                 std::vector<int>& nbThis, std::vector<int>& nbOther, std::vector<int>& nbOtherI)
+{
+  std::vector<QuadraticPolygon *> res;
+  if(!zip_list.empty())
+    ClosePolygonsSimple(pol1, zip_list, res, mapZipTo2, nbOther,nbOtherI);
+
+  for(std::vector<QuadraticPolygon *>::iterator it=res.begin();it!=res.end();it++)
+    {
+      (*it)->appendCrudeData(mapp,offset,addCoordsQuadratic,conn,connI);
+      INTERP_KERNEL::IteratorOnComposedEdge it1(*it);
+      for(it1.first();!it1.finished();it1.next())
+        {
+          Edge *e=it1.current()->getPtr();
+          if(edgesThis.find(e)!=edgesThis.end())
+            edgesThis.erase(e);
+          else
+            {
+              if(edgesBoundaryOther.find(e)!=edgesBoundaryOther.end())
+                edgesBoundaryOther.erase(e);
+              else
+                edgesBoundaryOther.insert(e);
+            }
+        }
+      // Mapping to pol1 (mapping to pol2s has been handled in ClosePolygonsSimple).
+      nbThis.push_back(idThis);
+      delete (*it);
+    }
+}
+
+/** @sa ComposedEdge::initLocationsWithOther()
+ */
+void QuadraticPolygon::initLocationsWithSeveralOthers(const std::vector<QuadraticPolygon> & others) const
+{
+  std::set<Edge *> s1,s2;
+  for(std::list<ElementaryEdge *>::const_iterator it1=_sub_edges.begin();it1!=_sub_edges.end();it1++)
+    s1.insert((*it1)->getPtr());
+  std::vector<QuadraticPolygon>::const_iterator it_qp;
+  for(it_qp=others.begin(); it_qp!=others.end(); it_qp++)
+    for(std::list<ElementaryEdge *>::const_iterator it2=(*it_qp)._sub_edges.begin();it2!=(*it_qp)._sub_edges.end();it2++)
+      s2.insert((*it2)->getPtr());
+  initLocations();
+  for(it_qp=others.begin(); it_qp!=others.end(); it_qp++)
+    (*it_qp).initLocations();
+  std::vector<Edge *> s3;
+  std::set_intersection(s1.begin(),s1.end(),s2.begin(),s2.end(),std::back_insert_iterator< std::vector<Edge *> >(s3));
+  for(std::vector<Edge *>::const_iterator it3=s3.begin();it3!=s3.end();it3++)
+    (*it3)->declareOn();
+}
+
+
 /*!
  * Warning This method is \b NOT const. 'this' and 'other' are modified after call of this method.
  * 'other' is a QuadraticPolygon of \b non closed edges.
@@ -876,7 +1139,7 @@ std::vector<QuadraticPolygon *> QuadraticPolygon::intersectMySelfWith(const Quad
   SplitPolygonsEachOther(cpyOfThis,cpyOfOther,nbOfSplits);
   //At this point cpyOfThis and cpyOfOther have been splited at maximum edge so that in/out can been done.
   performLocatingOperation(cpyOfOther);
-  return other.buildIntersectionPolygons(cpyOfThis,cpyOfOther);
+  return BuildIntersectionPolygons(cpyOfThis,cpyOfOther);
 }
 
 /*!
@@ -942,36 +1205,35 @@ void QuadraticPolygon::performLocatingOperation(QuadraticPolygon& pol2) const
     }
 }
 
-void QuadraticPolygon::performLocatingOperationSlow(QuadraticPolygon& pol2) const
+void QuadraticPolygon::performLocatingOperationSlow(QuadraticPolygon& pol1) const
 {
-  IteratorOnComposedEdge it(&pol2);
+  IteratorOnComposedEdge it(&pol1);
   for(it.first();!it.finished();it.next())
     {
       ElementaryEdge *cur=it.current();
-      cur->locateFullyMySelfAbsolute(*this);
+      cur->locateFullyMySelfAbsolute(*this); // *this=pol2=other
     }
 }
 
 /*!
  * Given 2 polygons 'pol1' and 'pol2' (localized) the resulting polygons are returned.
  *
- * this : pol2 simplified.
  * @param pol1 pol1 split.
  * @param pol2 pol2 split.
  */
-std::vector<QuadraticPolygon *> QuadraticPolygon::buildIntersectionPolygons(const QuadraticPolygon& pol1, const QuadraticPolygon& pol2) const
+std::vector<QuadraticPolygon *> QuadraticPolygon::BuildIntersectionPolygons(const QuadraticPolygon& pol1, const QuadraticPolygon& pol2)
 {
   std::vector<QuadraticPolygon *> ret;
   std::list<QuadraticPolygon *> pol2Zip=pol2.zipConsecutiveInSegments();
   if(!pol2Zip.empty())
-    closePolygons(pol2Zip,pol1,ret);
+    ClosePolygons(pol2Zip,pol1,pol2,ret);
   else
     {//borders of pol2 do not cross pol1,and pol2 borders are outside of pol1. That is to say, either pol2 and pol1
       //do not overlap or  pol1 is fully inside pol2. So in the first case no intersection, in the other case
       //the intersection is pol1.
       ElementaryEdge *e1FromPol1=pol1[0];
       TypeOfEdgeLocInPolygon loc=FULL_ON_1;
-      loc=e1FromPol1->locateFullyMySelf(*this,loc);
+      loc=e1FromPol1->locateFullyMySelf(pol2,loc);
       if(loc==FULL_IN_1)
         ret.push_back(new QuadraticPolygon(pol1));
     }
@@ -1014,14 +1276,61 @@ std::list<QuadraticPolygon *> QuadraticPolygon::zipConsecutiveInSegments() const
   return ret;
 }
 
+std::list<QuadraticPolygon *> QuadraticPolygon::ZipConsecutiveSegments2(const std::vector<int> & candidates2,
+                                                                        const std::vector<QuadraticPolygon> & pol2s,
+                                                                        std::vector<std::vector<int> > & mapZipTo2)
+{
+  int prevI = -2;
+  TypeOfEdgeLocInPolygon prevLoc = FULL_UNKNOWN;
+  std::list<QuadraticPolygon *> ret;
+  std::vector<int>::const_iterator it2; int ii=0;
+  QuadraticPolygon *tmpQp = 0;
+  for(it2 = candidates2.begin(), ii = 0; it2 != candidates2.end(); it2++, ii++)
+    {
+      IteratorOnComposedEdge it_ii(const_cast<ComposedEdge*>(static_cast<const ComposedEdge*>(&pol2s[ii]))); // hmmm ... :-)
+      bool firstEdge = true;
+      for (; !it_ii.finished(); it_ii.next())
+        {
+          if(it_ii.current()->getLoc() == FULL_IN_1)
+            {
+              // only keep consecutive items from mesh2 (consecutive seg IDs and consecutive IN pieces)
+              if(prevLoc != FULL_IN_1 || (firstEdge && *it2 != prevI+1))
+                {
+                  // the start node of a new QP has to be ON (otherwise we hit a piece of line starting in the middle of a cell)
+                  if (it_ii.current()->getStartNode()->getLoc() == ON_1)
+                    {
+                      tmpQp = new QuadraticPolygon;
+                      ret.push_back(tmpQp);
+                      mapZipTo2.push_back(std::vector<int>(0));
+                    }
+                  else
+                    continue; // firstEdge remains to its current value
+                }
+              tmpQp->pushBack(it_ii.current()->clone());
+              // Mapping - one quadratic polygon in ret is linked to several 1D cells:
+              if (std::find(mapZipTo2.back().begin(),mapZipTo2.back().end(), *it2)  == mapZipTo2.back().end())
+                mapZipTo2.back().push_back(*it2);
+            }
+          prevLoc = it_ii.current()->getLoc();
+          firstEdge = false;
+        }
+      prevI = *it2;
+    }
+  // Now clean line pieces not ending ON:
+  for(std::list<QuadraticPolygon *>::iterator it3 = ret.begin(); it3 != ret.end(); it3++)
+    if ((*it3)->back()->getEndNode()->getLoc() != ON_1)
+      ret.erase(it3);
+
+  return ret;
+}
+
 /*!
- * 'this' should be considered as pol2Simplified.
- * @param pol2zip is a list of set of edges (openned polygon) coming from split polygon 2.
+ * @param pol2zip is a list of set of edges (=an opened polygon) coming from split polygon 2.
  * @param pol1 is split pol1.
  * @param results the resulting \b CLOSED polygons.
  */
-void QuadraticPolygon::closePolygons(std::list<QuadraticPolygon *>& pol2Zip, const QuadraticPolygon& pol1,
-                                     std::vector<QuadraticPolygon *>& results) const
+void QuadraticPolygon::ClosePolygons(std::list<QuadraticPolygon *>& pol2Zip, const QuadraticPolygon& pol1, const QuadraticPolygon& pol2,
+                                     std::vector<QuadraticPolygon *>& results)
 {
   bool directionKnownInPol1=false;
   bool directionInPol1;
@@ -1036,7 +1345,7 @@ void QuadraticPolygon::closePolygons(std::list<QuadraticPolygon *>& pol2Zip, con
         }
       if(!directionKnownInPol1)
         {
-          if(!(*iter)->amIAChanceToBeCompletedBy(pol1,*this,directionInPol1))
+          if(!(*iter)->haveIAChanceToBeCompletedBy(pol1,pol2,directionInPol1))
             { delete *iter; iter=pol2Zip.erase(iter); continue; }
           else
             directionKnownInPol1=true;
@@ -1052,10 +1361,89 @@ void QuadraticPolygon::closePolygons(std::list<QuadraticPolygon *>& pol2Zip, con
     }
 }
 
+void QuadraticPolygon::ClosePolygonsSimple(const QuadraticPolygon& pol1, const std::list<QuadraticPolygon *> & zip_list,
+                                     std::vector<QuadraticPolygon *>& results,const std::vector<std::vector<int> > & mapZipTo2,
+                                     std::vector<int>& nbOther, std::vector<int>& nbOtherI)
+{
+  // Register all edges of pol1 as 'alive' to start with. They will be consumed as they are
+  // added to the newly formed cells. Edges of pol2s (in zip_list) might be used more than once.
+  std::set<ElementaryEdge *> edges1_alive;
+  IteratorOnComposedEdge it(const_cast<QuadraticPolygon *>(&pol1));
+  for(; !it.finished(); it.next())
+    edges1_alive.insert(it.current());
+
+  int inf_loop_detect, i;
+  std::list<QuadraticPolygon *>::const_iterator itt;
+  for (inf_loop_detect = pol1.recursiveSize() + 1, itt = zip_list.begin(); itt != zip_list.end(); itt++)
+    inf_loop_detect += 2*(*itt)->recursiveSize();
+
+  for (i = 0, it.first(); !edges1_alive.empty() && i <= inf_loop_detect;)
+    {
+      QuadraticPolygon * qp = new QuadraticPolygon();
+      results.push_back(qp);
+      // Mapping initialization
+      int nbElemFrom2 = 0;
+      // Start anywhere valid (=alive) on pol1
+      ElementaryEdge * startE;
+      for (startE = it.current(); edges1_alive.find(it.current()) == edges1_alive.end(); it.nextLoop(), startE = it.current());
+
+      // Close the new cell:
+      do
+        {
+          ElementaryEdge *tmp_e = it.current();
+          qp->pushBack(tmp_e->clone());
+          edges1_alive.erase(tmp_e);
+          Node * nodeToTest = tmp_e->getEndNode();
+          it.nextLoop(); i++;
+          // Try to match the end node of the latest added edge from pol1 with one of the node from
+          // one of the ComposedEdge in zip_list
+          std::list<QuadraticPolygon *>::const_iterator ret;
+          bool direction;
+          int idx; // for mapping
+          ret = CheckInList2(nodeToTest, zip_list, direction, idx);
+          if (ret == zip_list.end())
+            continue;
+          size_t oldSz = nbOther.size();
+          size_t addSz = std::distance(mapZipTo2[idx].begin(), mapZipTo2[idx].end());
+          nbOther.resize(oldSz+addSz);
+          std::copy(mapZipTo2[idx].begin(), mapZipTo2[idx].end(), &nbOther[oldSz]);
+          nbElemFrom2 += addSz;
+          if (!direction)
+            (*ret)->reverse();  // TODO: discuss with Anthony - API of IteratorOnComposedEdge should allow an easy reverse looping?
+          // Switch to zip_list
+          IteratorOnComposedEdge it_pol2(*ret);
+          ElementaryEdge *tmp_e2;
+          for(/* it_pol2.first() */; !it_pol2.finished(); it_pol2.next(), i++)
+            {
+              tmp_e2 = it_pol2.current();
+              qp->pushBack(tmp_e2->clone());
+            }
+          // search where we landed on pol1 to resume looping on it.
+          if (!edges1_alive.empty())
+            {
+              int j;
+              for(j = 0; it.current()->getStartNode() != tmp_e2->getEndNode() && j < inf_loop_detect; j++) // better way of doing this?
+                it.nextLoop();
+              if (j >= inf_loop_detect) // could be a bit more precise and stop before ...
+                throw Exception("QuadraticPolygon::ClosePolygonsSimple() - Internal error - 1D intersection was looping infinitely!");
+              // sanity check - if we are not done with the cell completion, we should land
+              // on a live edge.
+              if(edges1_alive.find(it.current()) == edges1_alive.end() && it.current() != startE)
+                throw Exception("QuadraticPolygon::ClosePolygonsSimple() - Internal error ! Should never happen.");
+            }
+        }
+      while(it.current() != startE && !edges1_alive.empty() && i < inf_loop_detect);
+      // Complete mapping
+      nbOtherI.push_back(nbElemFrom2+nbOtherI.back());
+    }
+  if (i >= inf_loop_detect)
+    throw Exception("QuadraticPolygon::ClosePolygonsSimple() - Internal error - 1D intersection was looping infinitely!");
+}
+
 /*!
  * 'this' is expected to be set of edges (not closed) of pol2 split.
  */
-bool QuadraticPolygon::amIAChanceToBeCompletedBy(const QuadraticPolygon& pol1Splitted,const QuadraticPolygon& pol2NotSplitted, bool& direction)
+bool QuadraticPolygon::haveIAChanceToBeCompletedBy(const QuadraticPolygon& pol1Splitted,const QuadraticPolygon& pol2NotSplitted, bool& direction)
 {
   IteratorOnComposedEdge it(const_cast<QuadraticPolygon *>(&pol1Splitted));
   bool found=false;
@@ -1069,7 +1457,7 @@ bool QuadraticPolygon::amIAChanceToBeCompletedBy(const QuadraticPolygon& pol1Spl
         it.next();
     }
   if(!found)
-    throw Exception("Internal error : polygons uncompatible each others. Should never happend");
+    throw Exception("Internal error: polygons incompatible with each others. Should never happen!");
   //Ok we found correspondance between this and pol1. Searching for right direction to close polygon.
   ElementaryEdge *e=_sub_edges.back();
   if(e->getLoc()==FULL_ON_1)
@@ -1099,7 +1487,7 @@ bool QuadraticPolygon::amIAChanceToBeCompletedBy(const QuadraticPolygon& pol1Spl
 }
 
 /*!
- * This method fills as much as possible 'this' (part of pol2 split) with edges of 'pol1Splitted'.
+ * This method fills as much as possible 'this' (a sub-part of pol2 split) with edges of 'pol1Splitted'.
  */
 std::list<QuadraticPolygon *>::iterator QuadraticPolygon::fillAsMuchAsPossibleWith(const QuadraticPolygon& pol1Splitted,
                                                                                    std::list<QuadraticPolygon *>::iterator iStart,
@@ -1151,6 +1539,28 @@ std::list<QuadraticPolygon *>::iterator QuadraticPolygon::CheckInList(Node *n, s
   return iEnd;
 }
 
+std::list<QuadraticPolygon *>::const_iterator QuadraticPolygon::CheckInList2(Node *n, const std::list<QuadraticPolygon *> & zip_list,
+                                                                             bool & direction, int & index)
+{
+  direction = true;
+  index = 0;
+  for(std::list<QuadraticPolygon *>::const_iterator iter = zip_list.begin(); iter!=zip_list.end(); iter++, index++)
+    {
+      if ((*iter)->front()->getStartNode() == n)
+        return iter;
+      else
+        {
+          if ((*iter)->back()->getEndNode() == n)
+            {
+              direction = false;
+              return iter;
+            }
+        }
+    }
+  return zip_list.end();
+}
+
+
 void QuadraticPolygon::ComputeResidual(const QuadraticPolygon& pol1, const std::set<Edge *>& notUsedInPol1, const std::set<Edge *>& edgesInPol2OnBoundary, const std::map<INTERP_KERNEL::Node *,int>& mapp, int offset, int idThis,
                                        std::vector<double>& addCoordsQuadratic, std::vector<int>& conn, std::vector<int>& connI, std::vector<int>& nb1, std::vector<int>& nb2)
 {
@@ -1166,7 +1576,7 @@ void QuadraticPolygon::ComputeResidual(const QuadraticPolygon& pol1, const std::
   std::list<QuadraticPolygon *> pol1Zip;
   if(pol1.size()==(int)notUsedInPol1.size() && edgesInPol2OnBoundary.empty())
     {
-      pol1.appendCrudeData(mapp,0.,0.,1.,offset,addCoordsQuadratic,conn,connI); nb1.push_back(idThis); nb2.push_back(-1);
+      pol1.appendCrudeData(mapp,offset,addCoordsQuadratic,conn,connI); nb1.push_back(idThis); nb2.push_back(-1);
       return ;
     }
   while(!notUsedInPol1L.empty())
@@ -1272,7 +1682,7 @@ void QuadraticPolygon::ComputeResidual(const QuadraticPolygon& pol1, const std::
     {
       if((*it1)->getStartNode()==(*it1)->getEndNode())
         {
-          (*it1)->appendCrudeData(mapp,0.,0.,1.,offset,addCoordsQuadratic,conn,connI); nb1.push_back(idThis); nb2.push_back(-1);
+          (*it1)->appendCrudeData(mapp,offset,addCoordsQuadratic,conn,connI); nb1.push_back(idThis); nb2.push_back(-1);
           for(std::list<QuadraticPolygon *>::iterator it6=pol1ZipConsumed[*it1].begin();it6!=pol1ZipConsumed[*it1].end();it6++)
             delete *it6;
           delete *it1;
index 670ac67456a65dec4fcd2b0d9e2efcb501a7efa0..2935032b225f7e43cccbfa0d78c5c2fcb83b741e 100644 (file)
@@ -71,13 +71,31 @@ namespace INTERP_KERNEL
                                                       const INTERP_KERNEL::QuadraticPolygon& pol1, const int *descBg1, const int *descEnd1, const std::vector<std::vector<int> >& intersectEdges1,
                                                       const std::vector< std::vector<int> >& colinear1,
                                                       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> >& alreadyExistingIn2);
+    INTERPKERNEL_EXPORT void buildFromCrudeDataArray3(const std::map<int,INTERP_KERNEL::Node *>& mapp, bool isQuad, const int *nodalBg, const double *coords, const int segId, const std::vector<std::vector<int> >& intersectEdges,
+                                                    const INTERP_KERNEL::QuadraticPolygon& pol1, const int *descBg1, const int *descEnd1, const std::vector<std::vector<int> >& intersectEdges1,
+                                                    const std::vector< std::vector<int> >& colinear1,
+                                                    std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> >& alreadyExistingIn2);
+    INTERPKERNEL_EXPORT void updateLocOfEdgeFromCrudeDataArray(const int edgeId, const std::vector<std::vector<int> >& intersectEdges,
+                                                             const INTERP_KERNEL::QuadraticPolygon& pol1, const int *descBg1, const int *descEnd1,
+                                                             const std::vector<std::vector<int> >& intersectEdges1, const std::vector< std::vector<int> >& colinear1) const;
     INTERPKERNEL_EXPORT void updateLocOfEdgeFromCrudeDataArray2(const int *descBg, const int *descEnd, const std::vector<std::vector<int> >& intersectEdges, const INTERP_KERNEL::QuadraticPolygon& pol1, const int *descBg1, const int *descEnd1, const std::vector<std::vector<int> >& intersectEdges1, const std::vector< std::vector<int> >& colinear1) const;
     INTERPKERNEL_EXPORT void appendEdgeFromCrudeDataArray(std::size_t edgeId, const std::map<int,INTERP_KERNEL::Node *>& mapp, bool isQuad, const int *nodalBg, const double *coords,
                                                           const int *descBg,  const int *descEnd, const std::vector<std::vector<int> >& intersectEdges);
+    INTERPKERNEL_EXPORT void appendEdgeFromCrudeDataArray2(const std::map<int,INTERP_KERNEL::Node *>& mapp, bool isQuad,
+                                                        const int *nodalBg, const double *coords,
+                                                        const int segId, const std::vector<std::vector<int> >& intersectEdges);
     INTERPKERNEL_EXPORT void appendSubEdgeFromCrudeDataArray(Edge *baseEdge, std::size_t j, bool direct, int edgeId, const std::vector<int>& subEdge, const std::map<int,INTERP_KERNEL::Node *>& mapp);
-    INTERPKERNEL_EXPORT void appendCrudeData(const std::map<INTERP_KERNEL::Node *,int>& mapp, double xBary, double yBary, double fact, int offset, std::vector<double>& addCoordsQuadratic, std::vector<int>& conn, std::vector<int>& connI) const;
+    INTERPKERNEL_EXPORT void appendCrudeData(const std::map<INTERP_KERNEL::Node *,int>& mapp, int offset, std::vector<double>& addCoordsQuadratic, std::vector<int>& conn, std::vector<int>& connI) const;
     INTERPKERNEL_EXPORT void buildPartitionsAbs(QuadraticPolygon& other, std::set<INTERP_KERNEL::Edge *>& edgesThis, std::set<INTERP_KERNEL::Edge *>& edgesBoundaryOther, const std::map<INTERP_KERNEL::Node *,int>& mapp, int idThis, int idOther, int offset,
                                                 std::vector<double>& addCoordsQuadratic, std::vector<int>& conn, std::vector<int>& connI, std::vector<int>& nb1, std::vector<int>& nb2);
+    INTERPKERNEL_EXPORT static void BuildPartitionFromZipList(const QuadraticPolygon & pol1, const std::list<INTERP_KERNEL::QuadraticPolygon *> & zip_list,
+                                                              std::set<INTERP_KERNEL::Edge *> & edgesThis, std::set<INTERP_KERNEL::Edge *> & edgesBoundaryOther,
+                                                              const std::map<INTERP_KERNEL::Node *,int>& mapp,
+                                                              const int idThis, const std::vector<std::vector<int> > & mapZipTo2,
+                                                              int offset, std::vector<double>& addCoordsQuadratic,
+                                                              std::vector<int>& conn,std::vector<int>& connI,
+                                                              std::vector<int>& nbThis, std::vector<int>& nbOther, std::vector<int>& nbOtherI);
+    INTERPKERNEL_EXPORT void initLocationsWithSeveralOthers(const std::vector<QuadraticPolygon> & others) const;
     //
     INTERPKERNEL_EXPORT double intersectWith(const QuadraticPolygon& other) const;
     INTERPKERNEL_EXPORT double intersectWith(const QuadraticPolygon& other, double* barycenter) const;
@@ -89,23 +107,31 @@ namespace INTERP_KERNEL
     INTERPKERNEL_EXPORT void performLocatingOperation(QuadraticPolygon& pol2) const;
     INTERPKERNEL_EXPORT void performLocatingOperationSlow(QuadraticPolygon& pol2) const;
     INTERPKERNEL_EXPORT static void SplitPolygonsEachOther(QuadraticPolygon& pol1, QuadraticPolygon& pol2, int& nbOfSplits);
-    INTERPKERNEL_EXPORT std::vector<QuadraticPolygon *> buildIntersectionPolygons(const QuadraticPolygon& pol1, const QuadraticPolygon& pol2) const;
-    INTERPKERNEL_EXPORT bool amIAChanceToBeCompletedBy(const QuadraticPolygon& pol1Splitted, const QuadraticPolygon& pol2NotSplitted, bool& direction);
+    INTERPKERNEL_EXPORT static std::vector<QuadraticPolygon *> BuildIntersectionPolygons(const QuadraticPolygon& pol1, const QuadraticPolygon& pol2);
+    INTERPKERNEL_EXPORT bool haveIAChanceToBeCompletedBy(const QuadraticPolygon& pol1Splitted, const QuadraticPolygon& pol2NotSplitted, bool& direction);
     INTERPKERNEL_EXPORT static void ComputeResidual(const QuadraticPolygon& pol1, const std::set<Edge *>& notUsedInPol1, const std::set<Edge *>& edgesInPol2OnBoundary, const std::map<INTERP_KERNEL::Node *,int>& mapp, int offset, int idThis,
                                                     std::vector<double>& addCoordsQuadratic, std::vector<int>& conn, std::vector<int>& connI, std::vector<int>& nb1, std::vector<int>& nb2);
+    INTERPKERNEL_EXPORT static std::list<QuadraticPolygon *> ZipConsecutiveSegments2(const std::vector<int> & candidates2, const std::vector<QuadraticPolygon> & pol2s,
+                                                                                     std::vector<std::vector<int> > & mapZipTo2);
   protected:
     std::list<QuadraticPolygon *> zipConsecutiveInSegments() const;
     void dumpInXfigFile(std::ostream& stream, int resolution, const Bounds& box) const;
-    void closePolygons(std::list<QuadraticPolygon *>& pol2Zip, const QuadraticPolygon& pol1, std::vector<QuadraticPolygon *>& results) const;
+    static void ClosePolygons(std::list<QuadraticPolygon *>& pol2Zip, const QuadraticPolygon& pol1, const QuadraticPolygon& pol2, std::vector<QuadraticPolygon *>& results);
+    static void ClosePolygonsSimple(const QuadraticPolygon& pol1, const std::list<INTERP_KERNEL::QuadraticPolygon *> & zip_list,
+                                         std::vector<QuadraticPolygon *>& results, const std::vector<std::vector<int> > & mapZipTo2,
+                                         std::vector<int>& nbOther, std::vector<int>& nbOtherI);
     template<class EDGES>
     static void UpdateNeighbours(const MergePoints& merger, IteratorOnComposedEdge it1, IteratorOnComposedEdge it2,
                                  const EDGES *e1, const EDGES *e2);
+
     std::list<QuadraticPolygon *>::iterator fillAsMuchAsPossibleWith(const QuadraticPolygon& pol1Splitted,
                                                                      std::list<QuadraticPolygon *>::iterator iStart,
                                                                      std::list<QuadraticPolygon *>::iterator iEnd,
                                                                      bool direction);
     static std::list<QuadraticPolygon *>::iterator CheckInList(Node *n, std::list<QuadraticPolygon *>::iterator iStart,
                                                                std::list<QuadraticPolygon *>::iterator iEnd);
+    static std::list<QuadraticPolygon *>::const_iterator CheckInList2(Node *n, const std::list<QuadraticPolygon *> & zip_list,
+                                                                      bool & direction, int & index);
   };
 }
 
index e0113eba9aabb457c74698baa1eb9b6fa7664981..9842c1aa1f5c9a0360e83aeb651c9ad421cf3982 100644 (file)
@@ -4250,7 +4250,7 @@ namespace ParaMEDMEM
   }
 
   /**
-   * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
+   * Construct a mapping between set of Nodes and the standard MEDCoupling connectivity format (c, cI).
    */
   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
@@ -4271,6 +4271,27 @@ namespace ParaMEDMEM
           }
       }
   }
+
+  /**
+   * Same as above for a 1D cell made of a single segment
+   * TODO: factorize with the above
+   */
+  void MEDCouplingUMeshBuildQPFromMesh4(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
+                                          const int segId, const std::vector<std::vector<int> >& intesctEdges1,
+                                          /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
+    {
+      for(std::vector<int>::const_iterator it1=intesctEdges1[segId].begin();it1!=intesctEdges1[segId].end();it1++)
+        {
+          std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
+          if(it==mappRev.end())
+            {
+              INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
+              mapp[node]=*it1;
+              mappRev[*it1]=node;
+            }
+        }
+    }
+
 }
 
 /// @endcond
@@ -8685,7 +8706,7 @@ MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1
   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
-  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New();  c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
   ret->setConnectivity(conn,connI,true);
   ret->setCoords(coo);
@@ -8693,6 +8714,73 @@ MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1
   return ret.retn();
 }
 
+MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
+                                                              double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2, DataArrayInt *&cellNbI2)
+{
+  m1->checkFullyDefined();
+  m2->checkFullyDefined();
+  if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=1 || m2->getSpaceDimension()!=2)
+    throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works on unstructured meshes m1 with (meshdim, spacedim) = (2,2) and m2 with (meshdim, spacedim) = (1,2)!");
+
+  // Check that m2 is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
+  DataArrayInt * d = DataArrayInt::New(), * dI = DataArrayInt::New();
+  DataArrayInt *rD = DataArrayInt::New(), * rDI = DataArrayInt::New();
+  MEDCouplingUMesh * m_points;
+  m_points = m2->buildDescendingConnectivity(d, dI, rD, rDI);
+  DataArrayInt * dsi = rDI->deltaShiftIndex();
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dsii = dsi->getIdsNotInRange(0,3);
+  m_points->decrRef(); d->decrRef(); dI->decrRef(); rD->decrRef(); rDI->decrRef(); dsi->decrRef();
+  if (dsii->getNumberOfTuples())
+    throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine only work with mesh2 being a (piecewise) connected line!");
+
+  // Step 1: compute all edge intersections (new nodes)
+  std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
+  MEDCouplingUMesh *m1Desc=0;
+  DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0;
+  std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
+  INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
+  INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
+  IntersectDescending2DMeshWith1DMesh(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
+                              m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
+                              addCoo);
+  revDesc1->decrRef(); revDescIndx1->decrRef();
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1);
+  MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc);
+
+  // Step 2: re-order newly created nodes according to the ordering found in m2
+  std::vector< std::vector<int> > intersectEdge2;
+  BuildIntersectEdges(m1Desc,m2,addCoo,subDiv2,intersectEdge2);
+  subDiv2.clear(); dd5=0;
+
+  // Step 3: this is where we have a significant difference with Intersect2DMeshes
+  std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
+  std::vector<int> cNb1,cNb2,cNbI2; //no DataArrayInt because interface with Geometric2D
+  cNbI2.push_back(0);
+  Build2DCellsFrom1DCut(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,
+                        colinear2,m2,intersectEdge2,addCoo,
+                        /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2,cNbI2);
+
+  // Step 4: Prepare final result:
+  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
+  addCooDa->alloc((int)(addCoo.size())/2,2);
+  std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
+  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
+  addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
+  std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
+  std::vector<const DataArrayDouble *> coordss(4);
+  coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
+  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
+  MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI2=DataArrayInt::New(); cI2->alloc((int)cNbI2.size(),1); std::copy(cNbI2.begin(),cNbI2.end(),cI2->getPointer());
+  ret->setConnectivity(conn,connI,true);
+  ret->setCoords(coo);
+  cellNb1=c1.retn(); cellNb2=c2.retn();cellNbI2=cI2.retn();
+  return ret.retn();
+}
 
 /**
  * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
@@ -8735,7 +8823,7 @@ void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCo
       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
       // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
-      // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
+      // pol1 is the full cell from mesh1, in QP format, with all the additional intersecting nodes.
       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
           desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
       //
@@ -8753,7 +8841,8 @@ void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCo
           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
           // Complete mapping with elements coming from the current cell it2 in mesh2:
-          MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
+          MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],
+                                           desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
           // pol2 is the new QP in the final merged result.
           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
               pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
@@ -8785,6 +8874,119 @@ void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCo
     }
 }
 
+void MEDCouplingUMesh::Build2DCellsFrom1DCut(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1, const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
+                                                  const MEDCouplingUMesh *m2, const std::vector<std::vector<int> >& intesctEdges2,
+                                                  const std::vector<double>& addCoords,
+                                                  std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI,
+                                                  std::vector<int>& cNb1, std::vector<int>& cNb2, std::vector<int>& cNbI2)
+{
+  static const int SPACEDIM=2;
+  const double *coo1=m1->getCoords()->getConstPointer();
+  const int *conn1=m1->getNodalConnectivity()->getConstPointer();
+  const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
+  int offset1=m1->getNumberOfNodes();
+  const double *coo2=m2->getCoords()->getConstPointer();
+  const int *conn2=m2->getNodalConnectivity()->getConstPointer();
+  const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
+  int offset2=offset1+m2->getNumberOfNodes();
+  int offset3=offset2+((int)addCoords.size())/2;
+  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
+  const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
+  // Here a BBTree on 1D-segments from the tool mesh, not on segments:
+  BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
+  int ncell1=m1->getNumberOfCells();
+  crI.push_back(0);
+  // for all 2D cells in base mesh, find intersecting segments
+  for(int i=0;i<ncell1;i++)
+    {
+      std::vector<int> candidates2;
+      myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
+      // Sort the candidates: this will help reconstructing connected lines traversing cell(i) in m1.
+      std::sort( candidates2.begin(), candidates2.end() );
+      std::map<INTERP_KERNEL::Node *,int> mapp;
+      std::map<int,INTERP_KERNEL::Node *> mappRev;
+      // conversion to the geometric DS format:
+      INTERP_KERNEL::QuadraticPolygon pol1;
+      INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
+      const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
+      // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
+      MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,
+                                       /* output-->*/mapp,mappRev);
+      // pol1 is the full cell from mesh1, in QP format, with all the additional intersecting nodes.
+      pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
+          desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
+      //
+      std::set<INTERP_KERNEL::Edge *> edges1;// store all edges of pol1 that are NOT consumed by intersect cells.
+                      // If any after the for-loop over candidates2 -> it remains unhandled parts of pol1 which should appear in the result (sse computeResidual below)
+      std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
+      INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
+      for(it1.first();!it1.finished();it1.next())
+        edges1.insert(it1.current()->getPtr());
+      //
+      std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
+      std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
+      std::vector<int>::iterator it2; int ii=0;
+      for(it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
+        {
+          INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
+          const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
+          // Complete mapping with elements coming from the current segment it2 in linear mesh2:
+          MEDCouplingUMeshBuildQPFromMesh4(coo1,offset1,coo2,offset2,addCoords,*it2,intesctEdges2,
+                                           /* output */mapp,mappRev);
+          // pol2 is the new QP in the final merged result.
+          pol2s[ii].buildFromCrudeDataArray3(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,*it2,intesctEdges2,
+               pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
+        }
+      pol1.initLocationsWithSeveralOthers(pol2s);
+      for(it2 = candidates2.begin(), ii = 0; it2 != candidates2.end(); it2++, ii++)
+        {
+          pol2s[ii].updateLocOfEdgeFromCrudeDataArray(*it2 ,intesctEdges2,pol1, desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
+          double xBaryBB, yBaryBB;
+          double fact=pol1.normalizeExt(&pol2s[ii], xBaryBB, yBaryBB);
+          //Locate pol2s[ii] relative to pol1 (this is done the other way around in the 2D/2D intersection)
+          pol1.performLocatingOperationSlow(pol2s[ii]);
+          pol1.unApplyGlobalSimilarityExt(pol2s[ii],xBaryBB,yBaryBB,fact);
+        }
+      // At this point all edges in (all elements of) pol2s are fully localized.
+      // Zip consecutive IN segments from the list of candidates, and discard the pieces which are ending nowhere (e.g. an IN polyline
+      // with an end-point in the middle of the cell).
+      std::vector<std::vector<int> > mapZipTo2;
+      std::list<INTERP_KERNEL::QuadraticPolygon *> zip_list = INTERP_KERNEL::QuadraticPolygon::ZipConsecutiveSegments2(candidates2, pol2s, mapZipTo2);
+
+      // Now the core of the algo - main output is in cr, crI, cNb1, cNb2 and cNbI2.
+      INTERP_KERNEL::QuadraticPolygon::BuildPartitionFromZipList(pol1, zip_list, edges1, edgesBoundary2, mapp,
+                                                                 i, mapZipTo2,
+                                                                 offset3,addCoordsQuadratic,cr,crI, cNb1,cNb2, cNbI2);
+      // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
+      // by m2 but that we still want to keep in the final result.
+      if(!edges1.empty())
+        {
+          size_t oldSz = cNb2.size();
+          try
+          {
+              INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
+          }
+          catch(INTERP_KERNEL::Exception& e)
+          {
+              std::ostringstream oss; oss << "Error when computing residual of cell #" << i << " in source/m1 mesh ! Maybe the neighbours of this cell in mesh are not well connected !\n" << "The deep reason is the following : " << e.what();
+              throw INTERP_KERNEL::Exception(oss.str().c_str());
+          }
+          // ComputeResidual has pushed some -1 at the back of cNb2. Replace this with void entries in cNbI2:
+          // TODO: discuss the format with Anthony.
+          size_t newSz = cNb2.size();
+          cNb2.resize(oldSz);
+          int val = (oldSz == 0) ? 0 : cNbI2.back();
+          for(size_t sss=0; sss<newSz-oldSz; sss++, cNbI2.push_back(val));
+        }
+      // Memory clean-up
+      for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
+        (*it).second->decrRef();
+      for (std::list<INTERP_KERNEL::QuadraticPolygon *>::const_iterator itt = zip_list.begin(); itt != zip_list.end(); itt++)
+        delete(*itt);
+    }
+}
+
+
 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<INTERP_KERNEL::Node *,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
 {
   std::map<INTERP_KERNEL::Node *,int>::const_iterator it(m.find(n));
@@ -9080,7 +9282,7 @@ void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, c
   intersectEdge1.resize(nDescCell1);
   colinear2.resize(nDescCell2);
   subDiv2.resize(nDescCell2);
-  BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
+  BBTree<SPACEDIM,int> myTree(bbox2,0,0,nDescCell2,-eps);
 
   std::vector<int> candidates1(1);
   int offset1=m1->getNumberOfNodes();
@@ -9118,6 +9320,67 @@ void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, c
   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
 }
 
+void MEDCouplingUMesh::IntersectDescending2DMeshWith1DMesh(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
+                                                   std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
+                                                   MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
+                                                   std::vector<double>& addCoo)
+{
+  static const int SPACEDIM=2;
+  // Build desc connectivity of first mesh only
+  desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New();
+  revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
+  m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
+  MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc);
+  const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
+  const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
+
+  // Build BB tree of all edges in the tool mesh (second mesh)
+  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
+  const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
+  int nDescCell1=m1Desc->getNumberOfCells();
+  int nCell2=m2->getNumberOfCells();
+  intersectEdge1.resize(nDescCell1);
+  colinear2.resize(nCell2);
+  subDiv2.resize(nCell2);
+  BBTree<SPACEDIM,int> myTree(bbox2,0,0,nCell2,-eps);
+
+  std::vector<int> candidates1(1);
+  int offset1=m1->getNumberOfNodes();
+  int offset2=offset1+m2->getNumberOfNodes();
+  for(int i=0;i<nDescCell1;i++)  // for all edges in the first mesh
+    {
+      std::vector<int> candidates2; // edges of mesh2 candidate for intersection
+      myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
+      if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
+        {
+          std::map<INTERP_KERNEL::Node *,int> map1,map2;
+          // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
+          INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2,candidates2,map2);
+          candidates1[0]=i;
+          INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
+          // This following part is to avoid that some removed nodes (for example due to a merge between pol1 and pol2) are replaced by a newly created one
+          // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
+          std::set<INTERP_KERNEL::Node *> nodes;
+          pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
+          std::size_t szz(nodes.size());
+          std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
+          std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
+          for(std::size_t iii=0;iii<szz;iii++,itt++)
+            { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
+          // end of protection
+          // Performs egde cutting:
+          pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
+          delete pol2;
+          delete pol1;
+        }
+      else
+        intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
+    }
+  m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
+}
+
+
 /*!
  * This method performs the 2nd step of Partition of 2D mesh.
  * This method has 4 inputs :
index e45707c604b3a116fcbab90a79eb149c9acb9b3f..8a3c98a27c86d101ccf92031fae6e4b00453e65c 100644 (file)
@@ -240,6 +240,8 @@ namespace ParaMEDMEM
     MEDCOUPLING_EXPORT static void ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p);
     MEDCOUPLING_EXPORT static void TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords);
     MEDCOUPLING_EXPORT static MEDCouplingUMesh *Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2);
+    MEDCOUPLING_EXPORT static MEDCouplingUMesh *Intersect2DMeshWith1DLine(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
+                                                          double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2, DataArrayInt *&cellNbI2);
     MEDCOUPLING_EXPORT static bool BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut);
     MEDCOUPLING_EXPORT static bool RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval=0);
     MEDCOUPLING_EXPORT static void ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
@@ -311,11 +313,20 @@ namespace ParaMEDMEM
                                             MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
                                             std::vector<double>& addCoo,
                                             MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2);
+    static void IntersectDescending2DMeshWith1DMesh(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
+                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
+                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
+                                                    std::vector<double>& addCoo);
     static void BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, const std::vector<double>& addCoo, const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge);
     static void BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1, const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
                                                   const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
                                                   const std::vector<double>& addCoords,
                                                   std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2);
+    static void Build2DCellsFrom1DCut(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1, const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
+                                                      const MEDCouplingUMesh *m2, const std::vector<std::vector<int> >& intesctEdges2,
+                                                      const std::vector<double>& addCoords,
+                                                      std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI,
+                                                      std::vector<int>& cNb1, std::vector<int>& cNb2, std::vector<int>& cNbI2);
     static void AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
                                               const int *nodal3DCurve, const int *nodalIndx3DCurve,
                                               const int *desc, const int *descIndx, std::vector< std::pair<int,int> >& cut3DSurf);
index d262304631c8da01271fefedfb6f247b35d7a140..26b1ef7e76242623223815eaa6d22fa73a929fd5 100644 (file)
@@ -2057,3 +2057,79 @@ void MEDCouplingBasicsTest5::testSimplexize3()
   //
   m->decrRef();
 }
+
+/**
+ * Two square cells intersected by a vertical line crossing only one cell.
+ */
+void MEDCouplingBasicsTest5::testIntersect2DMeshWith1DLine1()
+{
+  MEDCouplingCMesh *m1c = MEDCouplingCMesh::New();
+  DataArrayDouble *coordX = DataArrayDouble::New();
+  const double arrX[3] = {-1., 1., 2};
+  coordX->alloc(3,1);
+  std::copy(arrX,arrX+3,coordX->getPointer());
+  m1c->setCoordsAt(0,coordX);
+  DataArrayDouble *coordY = DataArrayDouble::New();
+  const double arrY[4] = {0., 2.};
+  coordY->alloc(2,1);
+  std::copy(arrY,arrY+2,coordY->getPointer());
+  m1c->setCoordsAt(1,coordY);
+  MEDCouplingUMesh *m1 = m1c->buildUnstructured();
+
+  // A simple line:
+  MEDCouplingUMesh *m2 = MEDCouplingUMesh::New("bla", 1);
+  const int conn2A[7] = {INTERP_KERNEL::NORM_SEG2,0,1,INTERP_KERNEL::NORM_SEG3,1,2,3};
+  const int connI2A[3] = {0,3,7};
+  const double coo2A[8] = {0.,-1.0,  0.,1.,   0.,3.,  0.5,2.2};
+  DataArrayDouble *coord2 = DataArrayDouble::New();
+  DataArrayInt *conn2 = DataArrayInt::New();
+  DataArrayInt *connI2 = DataArrayInt::New();
+  coord2->alloc(4,2); conn2->alloc(7,1); connI2->alloc(3, 1);
+  std::copy(coo2A ,coo2A+8, coord2->getPointer());
+  std::copy(conn2A ,conn2A+7, conn2->getPointer());
+  std::copy(connI2A,connI2A+3, connI2->getPointer());
+  m2->setCoords(coord2);
+  m2->setConnectivity(conn2, connI2);
+
+  // End of construction of input meshes m1bis and m2 -> start of specific part of the test
+  DataArrayInt * map1 = 0, * map2 = 0, * mapI2 = 0;
+  MEDCouplingUMesh *m3 = MEDCouplingUMesh::Intersect2DMeshWith1DLine(m1, m2, 1e-10, map1, map2, mapI2);
+  bool areNodesMerged; int newNbNodes;
+  DataArrayInt * d_tmp = m3->mergeNodes(1.0e-8, areNodesMerged, newNbNodes);
+  d_tmp->decrRef();
+  CPPUNIT_ASSERT_EQUAL(3,m3->getNumberOfCells());
+  CPPUNIT_ASSERT_EQUAL(20,m3->getNumberOfNodes());
+  CPPUNIT_ASSERT_EQUAL(2,m3->getSpaceDimension());
+
+  const int exp1[3] = {0,0,1};
+  const int exp2[4] = {0,1,0,1};
+  const int expI2[4] = {0,2,4,4};
+  CPPUNIT_ASSERT_EQUAL(3, map1->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(4, map2->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(4, mapI2->getNumberOfTuples());
+  CPPUNIT_ASSERT(std::equal(exp1,exp1+3, map1->getConstPointer()));
+  CPPUNIT_ASSERT(std::equal(exp2,exp2+4, map2->getConstPointer()));
+  CPPUNIT_ASSERT(std::equal(expI2,expI2+4, mapI2->getConstPointer()));
+
+  const int expConn[27] = {32, 1, 10, 7, 11, 4, 12, 13, 14, 15, 16, 32, 10, 0, 3, 11, 7, 17, 18, 19, 14, 13, 5, 2, 1, 4, 5};
+  const int expConnI[4] = {0, 11, 22, 27};
+  CPPUNIT_ASSERT_EQUAL(27, m3->getNodalConnectivity()->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(4, m3->getNodalConnectivityIndex()->getNumberOfTuples());
+  CPPUNIT_ASSERT(std::equal(expConn,expConn+27, m3->getNodalConnectivity()->getConstPointer()));
+  CPPUNIT_ASSERT(std::equal(expConnI,expConnI+4, m3->getNodalConnectivityIndex()->getConstPointer()));
+
+  map1->decrRef();
+  map2->decrRef();
+  mapI2->decrRef();
+  m3->decrRef();
+  //
+  m2->decrRef();
+  m1->decrRef();
+  coordX->decrRef();
+  coordY->decrRef();
+  m1c->decrRef();
+  coord2->decrRef();
+  conn2->decrRef();
+  connI2->decrRef();
+}
+
index 14b222900224e8ce592ba7de2aa89b7407a3f5dd..87dcf1051f2f6e46fe904e0ef1e775f20c4f8e33 100644 (file)
@@ -76,6 +76,7 @@ namespace ParaMEDMEM
     CPPUNIT_TEST( testDAIBuildSubstractionOptimized1 );
     CPPUNIT_TEST( testDAIIsStrictlyMonotonic1 );
     CPPUNIT_TEST( testSimplexize3 );
+    CPPUNIT_TEST( testIntersect2DMeshWith1DLine1 );
     CPPUNIT_TEST_SUITE_END();
   public:
     void testUMeshTessellate2D1();
@@ -118,6 +119,7 @@ namespace ParaMEDMEM
     void testDAIBuildSubstractionOptimized1();
     void testDAIIsStrictlyMonotonic1();
     void testSimplexize3();
+    void testIntersect2DMeshWith1DLine1();
   };
 }
 
index 1f58aec188b11d5235783192f5522827bb61bc83..6cab661aa4646ae9861687ebc925022416d54e9b 100644 (file)
@@ -14724,9 +14724,99 @@ class MEDCouplingBasicsTest(unittest.TestCase):
         self.assertTrue(m.getNodalConnectivityIndex().isEqual(DataArrayInt([0,5])))
         pass
 
+    def testIntersect2DMeshWith1DLine1(self):
+        """ Basic test for Intersect2DMeshWith1DLine: a vertical line intersecting a square. """
+        m1c = MEDCouplingCMesh()
+        coordX = DataArrayDouble([-1., 1., 2])
+        m1c.setCoordsAt(0,coordX)
+        coordY = DataArrayDouble([0., 2.])
+        m1c.setCoordsAt(1,coordY);
+        m1 = m1c.buildUnstructured()
+
+        # A simple line:
+        m2 = MEDCouplingUMesh("bla", 1)
+        coord2 = DataArrayDouble([0.,-1.0,  0.,1.,  0.,3.,  0.5,2.2], 4, 2)
+        conn2 = DataArrayInt([NORM_SEG2,0,1,NORM_SEG3,1,2,3])
+        connI2 = DataArrayInt([0,3,7])
+        m2.setCoords(coord2)
+        m2.setConnectivity(conn2, connI2)
+
+        # End of construction of input meshes m1bis and m2 -> start of specific part of the test
+        m3, map1, map2, mapI2 = MEDCouplingUMesh.Intersect2DMeshWith1DLine(m1, m2, 1e-10)
+        m3.mergeNodes(1.0e-8)
+                
+        self.assertEqual(3,m3.getNumberOfCells())
+        self.assertEqual(20,m3.getNumberOfNodes())
+        self.assertEqual(2,m3.getSpaceDimension())
+        # Mapping
+        exp1, exp2, expI2 = [0,0,1], [0,1,0,1], [0,2,4,4]
+        self.assertEqual(3, map1.getNumberOfTuples())
+        self.assertEqual(4, map2.getNumberOfTuples())
+        self.assertEqual(4, mapI2.getNumberOfTuples())
+        self.assertEqual(exp1, map1.getValues())
+        self.assertEqual(exp2, map2.getValues())
+        self.assertEqual(expI2, mapI2.getValues())
+        
+        expConn = [32, 1, 10, 7, 11, 4, 12, 13, 14, 15, 16, 32, 10, 0, 3, 11, 7, 17, 18, 19, 14, 13, 5, 2, 1, 4, 5] # 27tpl
+        expConnI = [0, 11, 22, 27]
+        self.assertEqual(27, m3.getNodalConnectivity().getNumberOfTuples())
+        self.assertEqual(4, m3.getNodalConnectivityIndex().getNumberOfTuples())
+        self.assertEqual(expConn, m3.getNodalConnectivity().getValues())
+        self.assertEqual(expConnI, m3.getNodalConnectivityIndex().getValues())
+      
+    def testSwig2Intersect2DMeshWith1DLine2(self):
+        """ Star pattern (a triangle intersecting another one upside down) """
+        coords1 = DataArrayDouble([-2.,1.,   2.,1.,  0.,-2.], 3,2)
+        coords2 = DataArrayDouble([0.,2.,   2.,-1.,  -2.,-1.,  0.,3.], 4,2)
+        m1 = MEDCouplingUMesh("triangle", 2)
+        m2 = MEDCouplingUMesh("tri_line", 1)
+        m1.setCoords(coords1)
+        m2.setCoords(coords2)
+        m1.setConnectivity(DataArrayInt([NORM_TRI3, 0,1,2]), DataArrayInt([0,4]))
+        m2.setConnectivity(DataArrayInt([NORM_SEG2,0,1,NORM_SEG2,1,2,NORM_SEG2,2,3]), DataArrayInt([0,3,6,9]))
+
+        # End of construction of input meshes m1bis and m2 -> start of specific part of the test
+        m3, map1, map2, mapI2 = MEDCouplingUMesh.Intersect2DMeshWith1DLine(m1, m2, 1e-10)
+        # Mapping
+        exp1, exp2, expI2 = [0,0,0,0], [2, 0,1,2, 0, 1], [0,1,4,5,6]
+        self.assertEqual(exp1, map1.getValues())
+        self.assertEqual(exp2, map2.getValues())
+        self.assertEqual(expI2, mapI2.getValues())
+        expConn = [5, 0, 8, 12, 5, 8, 7, 9, 10, 11, 12, 5, 7, 1, 9, 5, 10, 2, 11]
+        expConnI = [0, 4, 11, 15, 19]
+        self.assertEqual(expConn, m3.getNodalConnectivity().getValues())
+        self.assertEqual(expConnI, m3.getNodalConnectivityIndex().getValues())
+      
+    def testSwig2Intersect2DMeshWith1DLine3(self):
+        """ Line pieces ending (or fully located) in the middle of a cell """
+        m1c = MEDCouplingCMesh()
+        m1c.setCoordsAt(0,DataArrayDouble([-1., 1.]))
+        m1c.setCoordsAt(1,DataArrayDouble([-1., 1.]));
+        m1 = m1c.buildUnstructured()
+        coords2 = DataArrayDouble([0.,0.,  0.,1.5, -1.5,0.,  0.6,1.1,  1.1,0.6,  0.5,0.0,  0.0,-0.5], 7,2)
+        m2 = MEDCouplingUMesh("piecewise_line", 1)
+        m2.setCoords(coords2)
+        c = DataArrayInt([NORM_SEG2,0,1, NORM_SEG2,1,2,  NORM_SEG2,3,4, NORM_SEG2,5,6])
+        cI = DataArrayInt([0,3,6,9,12])
+        m2.setConnectivity(c, cI)
+        
+        # End of construction of input meshes m1bis and m2 -> start of specific part of the test
+        m3, map1, map2, mapI2 = MEDCouplingUMesh.Intersect2DMeshWith1DLine(m1, m2, 1e-10)
+        self.assertEqual(3,m3.getNumberOfCells())
+        # Mapping
+        exp1, exp2, expI2 = [0,0,0], [1,2, 1, 2], [0,2,3,4]
+        self.assertEqual(exp1, map1.getValues())
+        self.assertEqual(exp2, map2.getValues())
+        self.assertEqual(expI2, mapI2.getValues())
+        expConn = [5, 1, 0, 11, 13, 12, 14, 15, 5, 11, 2, 13, 5, 14, 3, 15]
+        expConnI = [0, 8, 12, 16]
+        self.assertEqual(expConn, m3.getNodalConnectivity().getValues())
+        self.assertEqual(expConnI, m3.getNodalConnectivityIndex().getValues())
+      
     def setUp(self):
         pass
     pass
 
 if __name__ == '__main__':
     unittest.main()
+
index 1f6e195b27aeedc48d240b3a5c583b28d149aa6a..467474d251bc7685bdf3785888d571251b903714 100644 (file)
@@ -2392,6 +2392,18 @@ namespace ParaMEDMEM
         return ret;
       }
 
+      static PyObject *Intersect2DMeshWith1DLine(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps) throw(INTERP_KERNEL::Exception)
+      {
+        DataArrayInt *cellNb1=0,*cellNb2=0, *cellNbI2=0;
+        MEDCouplingUMesh *mret=MEDCouplingUMesh::Intersect2DMeshWith1DLine(m1,m2,eps,cellNb1,cellNb2, cellNbI2);
+        PyObject *ret=PyTuple_New(4);
+        PyTuple_SetItem(ret,0,SWIG_NewPointerObj(SWIG_as_voidptr(mret),SWIGTYPE_p_ParaMEDMEM__MEDCouplingUMesh, SWIG_POINTER_OWN | 0 ));
+        PyTuple_SetItem(ret,1,SWIG_NewPointerObj(SWIG_as_voidptr(cellNb1),SWIGTYPE_p_ParaMEDMEM__DataArrayInt, SWIG_POINTER_OWN | 0 ));
+        PyTuple_SetItem(ret,2,SWIG_NewPointerObj(SWIG_as_voidptr(cellNb2),SWIGTYPE_p_ParaMEDMEM__DataArrayInt, SWIG_POINTER_OWN | 0 ));
+        PyTuple_SetItem(ret,3,SWIG_NewPointerObj(SWIG_as_voidptr(cellNbI2),SWIGTYPE_p_ParaMEDMEM__DataArrayInt, SWIG_POINTER_OWN | 0 ));
+        return ret;
+      }
+
       PyObject *buildSlice3D(PyObject *origin, PyObject *vec, double eps) const throw(INTERP_KERNEL::Exception)
       {
         int spaceDim=self->getSpaceDimension();