Salome HOME
9bbe6ce5527972076ed35979623475828e6196d2
[tools/medcoupling.git] / src / INTERP_KERNEL / Geometric2D / InterpKernelGeo2DQuadraticPolygon.cxx
1 // Copyright (C) 2007-2013  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (CEA/DEN)
20
21 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
22 #include "InterpKernelGeo2DElementaryEdge.hxx"
23 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
24 #include "InterpKernelGeo2DAbstractEdge.hxx"
25 #include "InterpKernelGeo2DEdgeLin.hxx"
26 #include "InterpKernelGeo2DBounds.hxx"
27 #include "InterpKernelGeo2DEdge.txx"
28
29 #include "NormalizedUnstructuredMesh.hxx"
30
31 #include <fstream>
32 #include <sstream>
33 #include <iomanip>
34 #include <cstring>
35 #include <limits>
36
37 using namespace INTERP_KERNEL;
38
39 namespace INTERP_KERNEL
40 {
41   const unsigned MAX_SIZE_OF_LINE_XFIG_FILE=1024;
42 }
43
44 QuadraticPolygon::QuadraticPolygon(const char *file)
45 {
46   char currentLine[MAX_SIZE_OF_LINE_XFIG_FILE];
47   std::ifstream stream(file);
48   stream.exceptions(std::ios_base::eofbit);
49   try
50     {
51       do
52         stream.getline(currentLine,MAX_SIZE_OF_LINE_XFIG_FILE);
53       while(strcmp(currentLine,"1200 2")!=0);
54       do
55         {
56           Edge *newEdge=Edge::BuildFromXfigLine(stream);
57           if(!empty())
58             newEdge->changeStartNodeWith(back()->getEndNode());
59           pushBack(newEdge);
60         }
61       while(1);
62     }
63   catch(std::ifstream::failure&)
64     {
65     }
66   front()->changeStartNodeWith(back()->getEndNode());
67 }
68
69 QuadraticPolygon::~QuadraticPolygon()
70 {
71 }
72
73 QuadraticPolygon *QuadraticPolygon::BuildLinearPolygon(std::vector<Node *>& nodes)
74 {
75   QuadraticPolygon *ret(new QuadraticPolygon);
76   std::size_t size=nodes.size();
77   for(std::size_t i=0;i<size;i++)
78     {
79       ret->pushBack(new EdgeLin(nodes[i],nodes[(i+1)%size]));
80       nodes[i]->decrRef();
81     }
82   return ret;
83 }
84
85 QuadraticPolygon *QuadraticPolygon::BuildArcCirclePolygon(std::vector<Node *>& nodes)
86 {
87   QuadraticPolygon *ret(new QuadraticPolygon);
88   std::size_t size=nodes.size();
89   for(std::size_t i=0;i<size/2;i++)
90
91     {
92       EdgeLin *e1,*e2;
93       e1=new EdgeLin(nodes[i],nodes[i+size/2]);
94       e2=new EdgeLin(nodes[i+size/2],nodes[(i+1)%(size/2)]);
95       SegSegIntersector inters(*e1,*e2);
96       bool colinearity=inters.areColinears();
97       delete e1; delete e2;
98       if(colinearity)
99         ret->pushBack(new EdgeLin(nodes[i],nodes[(i+1)%(size/2)]));
100       else
101         ret->pushBack(new EdgeArcCircle(nodes[i],nodes[i+size/2],nodes[(i+1)%(size/2)]));
102       nodes[i]->decrRef(); nodes[i+size/2]->decrRef();
103     }
104   return ret;
105 }
106
107 Edge *QuadraticPolygon::BuildLinearEdge(std::vector<Node *>& nodes)
108 {
109   if(nodes.size()!=2)
110     throw INTERP_KERNEL::Exception("QuadraticPolygon::BuildLinearEdge : input vector is expected to be of size 2 !");
111   Edge *ret(new EdgeLin(nodes[0],nodes[1]));
112   nodes[0]->decrRef(); nodes[1]->decrRef();
113   return ret;
114 }
115
116 Edge *QuadraticPolygon::BuildArcCircleEdge(std::vector<Node *>& nodes)
117 {
118   if(nodes.size()!=3)
119     throw INTERP_KERNEL::Exception("QuadraticPolygon::BuildArcCircleEdge : input vector is expected to be of size 3 !");
120   EdgeLin *e1(new EdgeLin(nodes[0],nodes[2])),*e2(new EdgeLin(nodes[2],nodes[1]));
121   SegSegIntersector inters(*e1,*e2);
122   bool colinearity=inters.areColinears();
123   delete e1; delete e2;
124   Edge *ret(0);
125   if(colinearity)
126     ret=new EdgeLin(nodes[0],nodes[1]);
127   else
128     ret=new EdgeArcCircle(nodes[0],nodes[2],nodes[1]);
129   nodes[0]->decrRef(); nodes[1]->decrRef(); nodes[2]->decrRef();
130   return ret;
131 }
132
133 void QuadraticPolygon::BuildDbgFile(const std::vector<Node *>& nodes, const char *fileName)
134 {
135   std::ofstream file(fileName);
136   file << std::setprecision(16);
137   file << "  double coords[]=" << std::endl << "    { ";
138   for(std::vector<Node *>::const_iterator iter=nodes.begin();iter!=nodes.end();iter++)
139     {
140       if(iter!=nodes.begin())
141         file << "," << std::endl << "      ";
142       file << (*(*iter))[0] << ", " << (*(*iter))[1];
143     }
144   file << "};" << std::endl;
145 }
146
147 void QuadraticPolygon::closeMe() const
148 {
149   if(!front()->changeStartNodeWith(back()->getEndNode()))
150     throw(Exception("big error: not closed polygon..."));
151 }
152
153 void QuadraticPolygon::circularPermute()
154 {
155   if(_sub_edges.size()>1)
156     {
157       ElementaryEdge *first=_sub_edges.front();
158       _sub_edges.pop_front();
159       _sub_edges.push_back(first);
160     }
161 }
162
163 bool QuadraticPolygon::isButterflyAbs()
164 {
165   INTERP_KERNEL::Bounds b;
166   double xBary,yBary;
167   b.prepareForAggregation();
168   fillBounds(b); 
169   double dimChar=b.getCaracteristicDim();
170   b.getBarycenter(xBary,yBary);
171   applyGlobalSimilarity(xBary,yBary,dimChar);
172   //
173   return isButterfly();
174 }
175
176 bool QuadraticPolygon::isButterfly() const
177 {
178   for(std::list<ElementaryEdge *>::const_iterator it=_sub_edges.begin();it!=_sub_edges.end();it++)
179     {
180       Edge *e1=(*it)->getPtr();
181       std::list<ElementaryEdge *>::const_iterator it2=it;
182       it2++;
183       for(;it2!=_sub_edges.end();it2++)
184         {
185           MergePoints commonNode;
186           ComposedEdge *outVal1=new ComposedEdge;
187           ComposedEdge *outVal2=new ComposedEdge;
188           Edge *e2=(*it2)->getPtr();
189           if(e1->intersectWith(e2,commonNode,*outVal1,*outVal2))
190             {
191               Delete(outVal1);
192               Delete(outVal2);
193               return true;
194             }
195           Delete(outVal1);
196           Delete(outVal2);
197         }
198     }
199   return false;
200 }
201
202 void QuadraticPolygon::dumpInXfigFileWithOther(const ComposedEdge& other, const char *fileName) const
203 {
204   std::ofstream file(fileName);
205   const int resolution=1200;
206   Bounds box;
207   box.prepareForAggregation();
208   fillBounds(box);
209   other.fillBounds(box);
210   dumpInXfigFile(file,resolution,box);
211   other.ComposedEdge::dumpInXfigFile(file,resolution,box);
212 }
213
214 void QuadraticPolygon::dumpInXfigFile(const char *fileName) const
215 {
216   std::ofstream file(fileName);
217   const int resolution=1200;
218   Bounds box;
219   box.prepareForAggregation();
220   fillBounds(box);
221   dumpInXfigFile(file,resolution,box);
222 }
223
224 void QuadraticPolygon::dumpInXfigFile(std::ostream& stream, int resolution, const Bounds& box) const
225 {
226   stream << "#FIG 3.2  Produced by xfig version 3.2.5-alpha5" << std::endl;
227   stream << "Landscape" << std::endl;
228   stream << "Center" << std::endl;
229   stream << "Metric" << std::endl;
230   stream << "Letter" << std::endl;
231   stream << "100.00" << std::endl;
232   stream << "Single" << std::endl;
233   stream << "-2" << std::endl;
234   stream << resolution << " 2" << std::endl;
235   ComposedEdge::dumpInXfigFile(stream,resolution,box);
236 }
237
238 /*!
239  * Warning contrary to intersectWith method this method is \b NOT const. 'this' and 'other' are modified after call of this method.
240  */
241 double QuadraticPolygon::intersectWithAbs(QuadraticPolygon& other)
242 {
243   double ret=0.,xBaryBB,yBaryBB;
244   double fact=normalize(&other,xBaryBB,yBaryBB);
245   std::vector<QuadraticPolygon *> polygs=intersectMySelfWith(other);
246   for(std::vector<QuadraticPolygon *>::iterator iter=polygs.begin();iter!=polygs.end();iter++)
247     {
248       ret+=fabs((*iter)->getArea());
249       delete *iter;
250     }
251   return ret*fact*fact;
252 }
253
254 /*!
255  * This method splits 'this' with 'other' into smaller pieces localizable. 'mapThis' is a map that gives the correspondance
256  * between nodes contained in 'this' and node ids in a global mesh.
257  * In the same way, 'mapOther' gives the correspondance between nodes contained in 'other' and node ids in a
258  * global mesh from wich 'other' is extracted.
259  * This method has 1 out paramater : 'edgesThis', After the call of this method, it contains the nodal connectivity (including type)
260  * of 'this' into globlal "this mesh".
261  * This method has 2 in/out parameters : 'subDivOther' and 'addCoo'.'otherEdgeIds' is useful to put values in
262  * 'edgesThis', 'subDivOther' and 'addCoo'.
263  * Size of 'otherEdgeIds' has to be equal to number of ElementaryEdges in 'other'. No check of that will be done.
264  * The term 'abs' in the name recalls that we normalize the mesh (spatially) so that node coordinates fit into [0;1].
265  * @param offset1 is the number of nodes contained in global mesh from which 'this' is extracted.
266  * @param offset2 is the sum of nodes contained in global mesh from which 'this' is extracted and 'other' is extracted.
267  * @param edgesInOtherColinearWithThis will be appended at the end of the vector with colinear edge ids of other (if any)
268  * @param otherEdgeIds is a vector with the same size than other before calling this method. It gives in the same order
269  * the cell id in global other mesh.
270  */
271 void QuadraticPolygon::splitAbs(QuadraticPolygon& other,
272         const std::map<INTERP_KERNEL::Node *,int>& mapThis, const std::map<INTERP_KERNEL::Node *,int>& mapOther,
273         int offset1, int offset2 ,
274         const std::vector<int>& otherEdgeIds,
275         std::vector<int>& edgesThis, int cellIdThis,
276         std::vector< std::vector<int> >& edgesInOtherColinearWithThis, std::vector< std::vector<int> >& subDivOther,
277         std::vector<double>& addCoo)
278 {
279   double xBaryBB, yBaryBB;
280   double fact=normalizeExt(&other, xBaryBB, yBaryBB);
281   //
282   IteratorOnComposedEdge it1(this),it3(&other);
283   MergePoints merge;
284   ComposedEdge *c1=new ComposedEdge;
285   ComposedEdge *c2=new ComposedEdge;
286   int i=0;
287   std::map<INTERP_KERNEL::Node *,int> mapAddCoo;
288   for(it3.first();!it3.finished();it3.next(),i++)//iteration over 'other' _sub_edges
289     {
290       QuadraticPolygon otherTmp;
291       ElementaryEdge* curE3=it3.current();
292       otherTmp.pushBack(new ElementaryEdge(curE3->getPtr(),curE3->getDirection())); curE3->getPtr()->incrRef();
293       IteratorOnComposedEdge it2(&otherTmp);
294       for(it2.first();!it2.finished();it2.next())//iteration on subedges of 'other->_sub_edge'
295         {
296           ElementaryEdge* curE2=it2.current();
297           if(!curE2->isThereStartPoint())
298             it1.first();
299           else
300             it1=curE2->getIterator();
301           for(;!it1.finished();)//iteration over 'this' _sub_edges
302             {
303               ElementaryEdge* curE1=it1.current();
304               merge.clear();
305               if(curE1->getPtr()->intersectWith(curE2->getPtr(),merge,*c1,*c2))
306                 {
307                   if(!curE1->getDirection()) c1->reverse();
308                   if(!curE2->getDirection()) c2->reverse();
309                   UpdateNeighbours(merge,it1,it2,c1,c2);
310                   //Substitution of simple edge by sub-edges.
311                   delete curE1; // <-- destroying simple edge coming from pol1
312                   delete curE2; // <-- destroying simple edge coming from pol2
313                   it1.insertElemEdges(c1,true);// <-- 2nd param is true to go next.
314                   it2.insertElemEdges(c2,false);// <-- 2nd param is false to avoid to go next.
315                   curE2=it2.current();
316                   //
317                   it1.assignMySelfToAllElems(c2);//To avoid that others
318                   SoftDelete(c1);
319                   SoftDelete(c2);
320                   c1=new ComposedEdge;
321                   c2=new ComposedEdge;
322                 }
323               else
324                 {
325                   UpdateNeighbours(merge,it1,it2,curE1,curE2);
326                   it1.next();
327                 }
328             }
329         }
330       if(otherTmp.presenceOfOn())
331         edgesInOtherColinearWithThis[otherEdgeIds[i]].push_back(cellIdThis);
332       if(otherTmp._sub_edges.size()>1)
333         {
334           for(std::list<ElementaryEdge *>::const_iterator it=otherTmp._sub_edges.begin();it!=otherTmp._sub_edges.end();it++)
335             (*it)->fillGlobalInfoAbs2(mapThis,mapOther,offset1,offset2,/**/fact,xBaryBB,yBaryBB,/**/subDivOther[otherEdgeIds[i]],addCoo,mapAddCoo);
336         }
337     }
338   Delete(c1);
339   Delete(c2);
340   //
341   for(std::list<ElementaryEdge *>::const_iterator it=_sub_edges.begin();it!=_sub_edges.end();it++)
342     (*it)->fillGlobalInfoAbs(mapThis,mapOther,offset1,offset2,/**/fact,xBaryBB,yBaryBB,/**/edgesThis,addCoo,mapAddCoo);
343   //
344 }
345
346 /*!
347  * This method builds 'this' from its descending conn stored in crude mode (MEDCoupling).
348  * Descending conn is in FORTRAN relative mode in order to give the
349  * orientation of edge (see buildDescendingConnectivity2() method).
350  * See appendEdgeFromCrudeDataArray() for params description.
351  */
352 void QuadraticPolygon::buildFromCrudeDataArray(const std::map<int,INTERP_KERNEL::Node *>& mapp, bool isQuad, const int *nodalBg, const double *coords,
353                                                const int *descBg, const int *descEnd, const std::vector<std::vector<int> >& intersectEdges)
354 {
355   std::size_t nbOfSeg=std::distance(descBg,descEnd);
356   for(std::size_t i=0;i<nbOfSeg;i++)
357     {
358       appendEdgeFromCrudeDataArray(i,mapp,isQuad,nodalBg,coords,descBg,descEnd,intersectEdges);
359     }
360 }
361
362 void QuadraticPolygon::appendEdgeFromCrudeDataArray(std::size_t edgePos, const std::map<int,INTERP_KERNEL::Node *>& mapp, bool isQuad,
363                             const int *nodalBg, const double *coords,
364                             const int *descBg, const int *descEnd, const std::vector<std::vector<int> >& intersectEdges)
365 {
366   if(!isQuad)
367     {
368       bool direct=descBg[edgePos]>0;
369       int edgeId=abs(descBg[edgePos])-1; // back to C indexing mode
370       const std::vector<int>& subEdge=intersectEdges[edgeId];
371       std::size_t nbOfSubEdges=subEdge.size()/2;
372       for(std::size_t j=0;j<nbOfSubEdges;j++)
373         appendSubEdgeFromCrudeDataArray(0,j,direct,edgeId,subEdge,mapp);
374     }
375   else
376     {
377       std::size_t nbOfSeg=std::distance(descBg,descEnd);
378       const double *st=coords+2*(nodalBg[edgePos]); 
379       INTERP_KERNEL::Node *st0=new INTERP_KERNEL::Node(st[0],st[1]);
380       const double *endd=coords+2*(nodalBg[(edgePos+1)%nbOfSeg]);
381       INTERP_KERNEL::Node *endd0=new INTERP_KERNEL::Node(endd[0],endd[1]);
382       const double *middle=coords+2*(nodalBg[edgePos+nbOfSeg]);
383       INTERP_KERNEL::Node *middle0=new INTERP_KERNEL::Node(middle[0],middle[1]);
384       EdgeLin *e1,*e2;
385       e1=new EdgeLin(st0,middle0);
386       e2=new EdgeLin(middle0,endd0);
387       SegSegIntersector inters(*e1,*e2);
388       bool colinearity=inters.areColinears();
389       delete e1; delete e2;
390       //
391       bool direct=descBg[edgePos]>0;
392       int edgeId=abs(descBg[edgePos])-1;
393       const std::vector<int>& subEdge=intersectEdges[edgeId];
394       std::size_t nbOfSubEdges=subEdge.size()/2;
395       if(colinearity)
396         {   
397           for(std::size_t j=0;j<nbOfSubEdges;j++)
398             appendSubEdgeFromCrudeDataArray(0,j,direct,edgeId,subEdge,mapp);
399         }
400       else
401         {
402           Edge *e=new EdgeArcCircle(st0,middle0,endd0,true);
403           for(std::size_t j=0;j<nbOfSubEdges;j++)
404             appendSubEdgeFromCrudeDataArray(e,j,direct,edgeId,subEdge,mapp);
405           e->decrRef();
406         }
407       st0->decrRef(); endd0->decrRef(); middle0->decrRef();
408     }
409 }
410
411 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)
412 {
413   std::size_t nbOfSubEdges=subEdge.size()/2;
414   if(!baseEdge)
415     {//it is not a quadratic subedge
416       Node *start=(*mapp.find(direct?subEdge[2*j]:subEdge[2*nbOfSubEdges-2*j-1])).second;
417       Node *end=(*mapp.find(direct?subEdge[2*j+1]:subEdge[2*nbOfSubEdges-2*j-2])).second;
418       ElementaryEdge *e=ElementaryEdge::BuildEdgeFromCrudeDataArray(true,start,end);
419       pushBack(e);
420     }
421   else
422     {//it is a quadratic subedge
423       Node *start=(*mapp.find(direct?subEdge[2*j]:subEdge[2*nbOfSubEdges-2*j-1])).second;
424       Node *end=(*mapp.find(direct?subEdge[2*j+1]:subEdge[2*nbOfSubEdges-2*j-2])).second;
425       Edge *ee=baseEdge->buildEdgeLyingOnMe(start,end);
426       ElementaryEdge *eee=new ElementaryEdge(ee,true);
427       pushBack(eee);
428     }
429 }
430
431 /*!
432  * 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
433  * orientation of edge.
434  */
435 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,
436                                                 const INTERP_KERNEL::QuadraticPolygon& pol1, const int *descBg1, const int *descEnd1, const std::vector<std::vector<int> >& intersectEdges1,
437                                                 const std::vector< std::vector<int> >& colinear1,
438                                                 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> >& alreadyExistingIn2)
439 {
440   std::size_t nbOfSeg=std::distance(descBg,descEnd);
441   for(std::size_t i=0;i<nbOfSeg;i++)//loop over all edges of pol2
442     {
443       bool direct=descBg[i]>0;
444       int edgeId=abs(descBg[i])-1;//current edge id of pol2
445       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> >::const_iterator it1=alreadyExistingIn2.find(descBg[i]),it2=alreadyExistingIn2.find(-descBg[i]);
446       if(it1!=alreadyExistingIn2.end() || it2!=alreadyExistingIn2.end())
447         {
448           bool sameDir=(it1!=alreadyExistingIn2.end());
449           const std::vector<INTERP_KERNEL::ElementaryEdge *>& edgesAlreadyBuilt=sameDir?(*it1).second:(*it2).second;
450           if(sameDir)
451             {
452               for(std::vector<INTERP_KERNEL::ElementaryEdge *>::const_iterator it3=edgesAlreadyBuilt.begin();it3!=edgesAlreadyBuilt.end();it3++)
453                 {
454                   Edge *ee=(*it3)->getPtr(); ee->incrRef();
455                   pushBack(new ElementaryEdge(ee,(*it3)->getDirection()));
456                 }
457             }
458           else
459             {
460               for(std::vector<INTERP_KERNEL::ElementaryEdge *>::const_reverse_iterator it4=edgesAlreadyBuilt.rbegin();it4!=edgesAlreadyBuilt.rend();it4++)
461                 {
462                   Edge *ee=(*it4)->getPtr(); ee->incrRef();
463                   pushBack(new ElementaryEdge(ee,!(*it4)->getDirection()));
464                 }
465             }
466           continue;
467         }
468       bool directos=colinear1[edgeId].empty();
469       std::vector<std::pair<int,std::pair<bool,int> > > idIns1;
470       int offset1=0;
471       if(!directos)
472         {// if the current edge of pol2 has one or more colinear edges part into pol1
473           const std::vector<int>& c=colinear1[edgeId];
474           std::size_t nbOfEdgesIn1=std::distance(descBg1,descEnd1);
475           for(std::size_t j=0;j<nbOfEdgesIn1;j++)
476             {
477               int edgeId1=abs(descBg1[j])-1;
478               if(std::find(c.begin(),c.end(),edgeId1)!=c.end())
479                 {
480                   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
481                   //std::pair<edgeId1); direct1=descBg1[j]>0;
482                 }
483               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
484             }
485           directos=idIns1.empty();
486         }
487       if(directos)
488         {//no subpart of edge 'edgeId' of pol2 is in pol1 so let's operate the same thing that QuadraticPolygon::buildFromCrudeDataArray method
489           std::size_t oldSz=_sub_edges.size();
490           appendEdgeFromCrudeDataArray(i,mapp,isQuad,nodalBg,coords,descBg,descEnd,intersectEdges);
491           std::size_t newSz=_sub_edges.size();
492           std::size_t zeSz=newSz-oldSz;
493           alreadyExistingIn2[descBg[i]].resize(zeSz);
494           std::list<ElementaryEdge *>::const_reverse_iterator it5=_sub_edges.rbegin();
495           for(std::size_t p=0;p<zeSz;p++,it5++)
496             alreadyExistingIn2[descBg[i]][zeSz-p-1]=*it5;
497         }
498       else
499         {//there is subpart of edge 'edgeId' of pol2 inside pol1
500           const std::vector<int>& subEdge=intersectEdges[edgeId];
501           std::size_t nbOfSubEdges=subEdge.size()/2;
502           for(std::size_t j=0;j<nbOfSubEdges;j++)
503             {
504               int idBg=direct?subEdge[2*j]:subEdge[2*nbOfSubEdges-2*j-1];
505               int idEnd=direct?subEdge[2*j+1]:subEdge[2*nbOfSubEdges-2*j-2];
506               bool direction11,found=false;
507               bool direct1;//store if needed the direction in 1
508               int offset2;
509               std::size_t nbOfSubEdges1;
510               for(std::vector<std::pair<int,std::pair<bool,int> > >::const_iterator it=idIns1.begin();it!=idIns1.end() && !found;it++)
511                 {
512                   int idIn1=(*it).first;//store if needed the cell id in 1
513                   direct1=(*it).second.first;
514                   offset1=(*it).second.second;
515                   const std::vector<int>& subEdge1PossiblyAlreadyIn1=intersectEdges1[idIn1];
516                   nbOfSubEdges1=subEdge1PossiblyAlreadyIn1.size()/2;
517                   offset2=0;
518                   for(std::size_t k=0;k<nbOfSubEdges1 && !found;k++)
519                     {//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
520                       if(subEdge1PossiblyAlreadyIn1[2*k]==idBg && subEdge1PossiblyAlreadyIn1[2*k+1]==idEnd)
521                         { direction11=true; found=true; }
522                       else if(subEdge1PossiblyAlreadyIn1[2*k]==idEnd && subEdge1PossiblyAlreadyIn1[2*k+1]==idBg)
523                         { direction11=false; found=true; }
524                       else
525                         offset2++;
526                     }
527                 }
528               if(!found)
529                 {//the current subedge of edge 'edgeId' of pol2 is not a part of the colinear edge 'idIn1' of pol1 -> build new Edge instance
530                   //appendEdgeFromCrudeDataArray(j,mapp,isQuad,nodalBg,coords,descBg,descEnd,intersectEdges);
531                   Node *start=(*mapp.find(idBg)).second;
532                   Node *end=(*mapp.find(idEnd)).second;
533                   ElementaryEdge *e=ElementaryEdge::BuildEdgeFromCrudeDataArray(true,start,end);
534                   pushBack(e);
535                   alreadyExistingIn2[descBg[i]].push_back(e);
536                 }
537               else
538                 {//the current subedge of edge 'edgeId' of pol2 is part of the colinear edge 'idIn1' of pol1 -> reuse Edge instance of pol1
539                   ElementaryEdge *e=pol1[offset1+(direct1?offset2:nbOfSubEdges1-offset2-1)];
540                   Edge *ee=e->getPtr();
541                   ee->incrRef();
542                   ElementaryEdge *e2=new ElementaryEdge(ee,!(direct1^direction11));
543                   pushBack(e2);
544                   alreadyExistingIn2[descBg[i]].push_back(e2);
545                 }
546             }
547         }
548     }
549 }
550
551 /*!
552  * Method expected to be called on pol2. Every params not suffixed by numbered are supposed to refer to pol2 (this).
553  * Method to find edges that are ON.
554  */
555 void QuadraticPolygon::updateLocOfEdgeFromCrudeDataArray2(const int *descBg, const int *descEnd, const std::vector<std::vector<int> >& intersectEdges,
556       const INTERP_KERNEL::QuadraticPolygon& pol1, const int *descBg1, const int *descEnd1,
557       const std::vector<std::vector<int> >& intersectEdges1, const std::vector< std::vector<int> >& colinear1) const
558 {
559   std::size_t nbOfSeg=std::distance(descBg,descEnd);
560   for(std::size_t i=0;i<nbOfSeg;i++)//loop over all edges of pol2
561     {
562       bool direct=descBg[i]>0;
563       int edgeId=abs(descBg[i])-1;//current edge id of pol2
564       const std::vector<int>& c=colinear1[edgeId];
565       if(c.empty())
566         continue;
567       const std::vector<int>& subEdge=intersectEdges[edgeId];
568       std::size_t nbOfSubEdges=subEdge.size()/2;
569       //
570       std::size_t nbOfEdgesIn1=std::distance(descBg1,descEnd1);
571       int offset1=0;
572       for(std::size_t j=0;j<nbOfEdgesIn1;j++)
573         {
574           int edgeId1=abs(descBg1[j])-1;
575           if(std::find(c.begin(),c.end(),edgeId1)!=c.end())
576             {
577               for(std::size_t k=0;k<nbOfSubEdges;k++)
578                 {
579                   int idBg=direct?subEdge[2*k]:subEdge[2*nbOfSubEdges-2*k-1];
580                   int idEnd=direct?subEdge[2*k+1]:subEdge[2*nbOfSubEdges-2*k-2];
581                   int idIn1=edgeId1;
582                   bool direct1=descBg1[j]>0;
583                   const std::vector<int>& subEdge1PossiblyAlreadyIn1=intersectEdges1[idIn1];
584                   std::size_t nbOfSubEdges1=subEdge1PossiblyAlreadyIn1.size()/2;
585                   int offset2=0;
586                   bool found=false;
587                   for(std::size_t kk=0;kk<nbOfSubEdges1 && !found;kk++)
588                     {
589                       found=(subEdge1PossiblyAlreadyIn1[2*kk]==idBg && subEdge1PossiblyAlreadyIn1[2*kk+1]==idEnd) || (subEdge1PossiblyAlreadyIn1[2*kk]==idEnd && subEdge1PossiblyAlreadyIn1[2*kk+1]==idBg);
590                       if(!found)
591                         offset2++;
592                     }
593                   if(found)
594                     {
595                       ElementaryEdge *e=pol1[offset1+(direct1?offset2:nbOfSubEdges1-offset2-1)];
596                       e->getPtr()->declareOn();
597                     }
598                 }
599             }
600           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
601         }
602     }
603 }
604
605 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
606 {
607   int nbOfNodesInPg=0;
608   bool presenceOfQuadratic=presenceOfQuadraticEdge();
609   conn.push_back(presenceOfQuadratic?NORM_QPOLYG:NORM_POLYGON);
610   for(std::list<ElementaryEdge *>::const_iterator it=_sub_edges.begin();it!=_sub_edges.end();it++)
611     {
612       Node *tmp=0;
613       tmp=(*it)->getStartNode();
614       std::map<INTERP_KERNEL::Node *,int>::const_iterator it1=mapp.find(tmp);
615       conn.push_back((*it1).second);
616       nbOfNodesInPg++;
617     }
618   if(presenceOfQuadratic)
619     {
620       int j=0;
621       int off=offset+((int)addCoordsQuadratic.size())/2;
622       for(std::list<ElementaryEdge *>::const_iterator it=_sub_edges.begin();it!=_sub_edges.end();it++,j++,nbOfNodesInPg++)
623         {
624           INTERP_KERNEL::Node *node=(*it)->getPtr()->buildRepresentantOfMySelf();
625           node->unApplySimilarity(xBary,yBary,fact);
626           addCoordsQuadratic.push_back((*node)[0]);
627           addCoordsQuadratic.push_back((*node)[1]);
628           conn.push_back(off+j);
629           node->decrRef();
630         }
631     }
632   connI.push_back(connI.back()+nbOfNodesInPg+1);
633 }
634
635 /*!
636  * This method make the hypothesis that 'this' and 'other' are splited at the minimum into edges that are fully IN, OUT or ON.
637  * This method returns newly created polygons in 'conn' and 'connI' and the corresponding ids ('idThis','idOther') are stored respectively into 'nbThis' and 'nbOther'.
638  * @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
639  * @param [in,out] edgesBoundaryOther, parameter that strores all edges in result of intersection that are not 
640  */
641 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)
642 {
643   double xBaryBB, yBaryBB;
644   double fact=normalizeExt(&other, xBaryBB, yBaryBB);
645   //Locate 'this' relative to 'other'
646   other.performLocatingOperationSlow(*this);  // without any assumption
647   std::vector<QuadraticPolygon *> res=buildIntersectionPolygons(other,*this);
648   for(std::vector<QuadraticPolygon *>::iterator it=res.begin();it!=res.end();it++)
649     {
650       (*it)->appendCrudeData(mapp,xBaryBB,yBaryBB,fact,offset,addCoordsQuadratic,conn,connI);
651       INTERP_KERNEL::IteratorOnComposedEdge it1(*it);
652       for(it1.first();!it1.finished();it1.next())
653         {
654           Edge *e=it1.current()->getPtr();
655           if(edgesThis.find(e)!=edgesThis.end())
656             edgesThis.erase(e);
657           else
658             {
659               if(edgesBoundaryOther.find(e)!=edgesBoundaryOther.end())
660                 edgesBoundaryOther.erase(e);
661               else
662                 edgesBoundaryOther.insert(e);
663             }
664         }
665       nbThis.push_back(idThis);
666       nbOther.push_back(idOther);
667       delete *it;
668     }
669   unApplyGlobalSimilarityExt(other,xBaryBB,yBaryBB,fact);
670 }
671
672 /*!
673  * Warning This method is \b NOT const. 'this' and 'other' are modified after call of this method.
674  * 'other' is a QuadraticPolygon of \b non closed edges.
675  */
676 double QuadraticPolygon::intersectWithAbs1D(QuadraticPolygon& other, bool& isColinear)
677 {
678   double ret = 0., xBaryBB, yBaryBB;
679   double fact = normalize(&other, xBaryBB, yBaryBB);
680
681   QuadraticPolygon cpyOfThis(*this);
682   QuadraticPolygon cpyOfOther(other);
683   int nbOfSplits = 0;
684   SplitPolygonsEachOther(cpyOfThis, cpyOfOther, nbOfSplits);
685   //At this point cpyOfThis and cpyOfOther have been splited at maximum edge so that in/out can been done.
686   performLocatingOperation(cpyOfOther);
687   isColinear = false;
688   for(std::list<ElementaryEdge *>::const_iterator it=cpyOfOther._sub_edges.begin();it!=cpyOfOther._sub_edges.end();it++)
689     {
690       switch((*it)->getLoc())
691         {
692         case FULL_IN_1:
693           {
694             ret += fabs((*it)->getPtr()->getCurveLength());
695             break;
696           }
697         case FULL_ON_1:
698           {
699             isColinear=true;
700             ret += fabs((*it)->getPtr()->getCurveLength());
701             break;
702           }
703         default:
704           {
705           }
706         }
707     }
708   return ret * fact;
709 }
710
711 /*!
712  * Warning contrary to intersectWith method this method is \b NOT const. 'this' and 'other' are modified after call of this method.
713  */
714 double QuadraticPolygon::intersectWithAbs(QuadraticPolygon& other, double* barycenter)
715 {
716   double ret=0.,bary[2],area,xBaryBB,yBaryBB;
717   barycenter[0] = barycenter[1] = 0.;
718   double fact=normalize(&other,xBaryBB,yBaryBB);
719   std::vector<QuadraticPolygon *> polygs=intersectMySelfWith(other);
720   for(std::vector<QuadraticPolygon *>::iterator iter=polygs.begin();iter!=polygs.end();iter++)
721     {
722       area=fabs((*iter)->getArea());
723       (*iter)->getBarycenter(bary);
724       delete *iter;
725       ret+=area;
726       barycenter[0] += bary[0]*area;
727       barycenter[1] += bary[1]*area;
728     }
729   if ( ret > std::numeric_limits<double>::min() )
730     {
731       barycenter[0]=barycenter[0]/ret*fact+xBaryBB;
732       barycenter[1]=barycenter[1]/ret*fact+yBaryBB;
733       
734     }
735   return ret*fact*fact;
736 }
737
738 /*!
739  * \b WARNING this method is const and other is const too. \b BUT location of Edges in 'this' and 'other' are nevertheless modified.
740  * This is possible because loc attribute in Edge class is mutable.
741  * This implies that if 'this' or/and 'other' are reused for intersect* method initLocations has to be called on each of this/them.
742  */
743 double QuadraticPolygon::intersectWith(const QuadraticPolygon& other) const
744 {
745   double ret=0.;
746   std::vector<QuadraticPolygon *> polygs=intersectMySelfWith(other);
747   for(std::vector<QuadraticPolygon *>::iterator iter=polygs.begin();iter!=polygs.end();iter++)
748     {
749       ret+=fabs((*iter)->getArea());
750       delete *iter;
751     }
752   return ret;
753 }
754
755 /*!
756  * \b WARNING this method is const and other is const too. \b BUT location of Edges in 'this' and 'other' are nevertheless modified.
757  * This is possible because loc attribute in Edge class is mutable.
758  * This implies that if 'this' or/and 'other' are reused for intersect* method initLocations has to be called on each of this/them.
759  */
760 double QuadraticPolygon::intersectWith(const QuadraticPolygon& other, double* barycenter) const
761 {
762   double ret=0., bary[2];
763   barycenter[0] = barycenter[1] = 0.;
764   std::vector<QuadraticPolygon *> polygs=intersectMySelfWith(other);
765   for(std::vector<QuadraticPolygon *>::iterator iter=polygs.begin();iter!=polygs.end();iter++)
766     {
767       double area = fabs((*iter)->getArea());
768       (*iter)->getBarycenter(bary);
769       delete *iter;
770       ret+=area;
771       barycenter[0] += bary[0]*area;
772       barycenter[1] += bary[1]*area;
773     }
774   if ( ret > std::numeric_limits<double>::min() )
775     {
776       barycenter[0] /= ret;
777       barycenter[1] /= ret;
778     }
779   return ret;
780 }
781
782 /*!
783  * \b WARNING this method is const and other is const too. \b BUT location of Edges in 'this' and 'other' are nevertheless modified.
784  * This is possible because loc attribute in Edge class is mutable.
785  * This implies that if 'this' or/and 'other' are reused for intersect* method initLocations has to be called on each of this/them.
786  */
787 void QuadraticPolygon::intersectForPerimeter(const QuadraticPolygon& other, double& perimeterThisPart, double& perimeterOtherPart, double& perimeterCommonPart) const
788 {
789   perimeterThisPart=0.; perimeterOtherPart=0.; perimeterCommonPart=0.;
790   QuadraticPolygon cpyOfThis(*this);
791   QuadraticPolygon cpyOfOther(other); int nbOfSplits=0;
792   SplitPolygonsEachOther(cpyOfThis,cpyOfOther,nbOfSplits);
793   performLocatingOperation(cpyOfOther);
794   other.performLocatingOperation(cpyOfThis);
795   cpyOfThis.dispatchPerimeterExcl(perimeterThisPart,perimeterCommonPart);
796   cpyOfOther.dispatchPerimeterExcl(perimeterOtherPart,perimeterCommonPart);
797   perimeterCommonPart/=2.;
798 }
799
800 /*!
801  * \b WARNING this method is const and other is const too. \b BUT location of Edges in 'this' and 'other' are nevertheless modified.
802  * This is possible because loc attribute in Edge class is mutable.
803  * This implies that if 'this' or/and 'other' are reused for intersect* method initLocations has to be called on each of this/them.
804  *
805  * polThis.size()==this->size() and polOther.size()==other.size().
806  * For each ElementaryEdge of 'this', the corresponding contribution in resulting polygon is in 'polThis'.
807  * For each ElementaryEdge of 'other', the corresponding contribution in resulting polygon is in 'polOther'.
808  * As consequence common part are counted twice (in polThis \b and in polOther).
809  */
810 void QuadraticPolygon::intersectForPerimeterAdvanced(const QuadraticPolygon& other, std::vector< double >& polThis, std::vector< double >& polOther) const
811 {
812   polThis.resize(size());
813   polOther.resize(other.size());
814   IteratorOnComposedEdge it1(const_cast<QuadraticPolygon *>(this));
815   int edgeId=0;
816   for(it1.first();!it1.finished();it1.next(),edgeId++)
817     {
818       ElementaryEdge* curE1=it1.current();
819       QuadraticPolygon cpyOfOther(other);
820       QuadraticPolygon tmp;
821       tmp.pushBack(curE1->clone());
822       int tmp2;
823       SplitPolygonsEachOther(tmp,cpyOfOther,tmp2);
824       other.performLocatingOperation(tmp);
825       tmp.dispatchPerimeter(polThis[edgeId]);
826     }
827   //
828   IteratorOnComposedEdge it2(const_cast<QuadraticPolygon *>(&other));
829   edgeId=0;
830   for(it2.first();!it2.finished();it2.next(),edgeId++)
831     {
832       ElementaryEdge* curE2=it2.current();
833       QuadraticPolygon cpyOfThis(*this);
834       QuadraticPolygon tmp;
835       tmp.pushBack(curE2->clone());
836       int tmp2;
837       SplitPolygonsEachOther(tmp,cpyOfThis,tmp2);
838       performLocatingOperation(tmp);
839       tmp.dispatchPerimeter(polOther[edgeId]);
840     }
841 }
842
843
844 /*!
845  * numberOfCreatedPointsPerEdge is resized to the number of edges of 'this'.
846  * This method returns in ordered maner the number of newly created points per edge.
847  * This method performs a split process between 'this' and 'other' that gives the result PThis.
848  * Then for each edges of 'this' this method counts how many edges in Pthis have the same id.
849  */
850 void QuadraticPolygon::intersectForPoint(const QuadraticPolygon& other, std::vector< int >& numberOfCreatedPointsPerEdge) const
851 {
852   numberOfCreatedPointsPerEdge.resize(size());
853   IteratorOnComposedEdge it1(const_cast<QuadraticPolygon *>(this));
854   int edgeId=0;
855   for(it1.first();!it1.finished();it1.next(),edgeId++)
856     {
857       ElementaryEdge* curE1=it1.current();
858       QuadraticPolygon cpyOfOther(other);
859       QuadraticPolygon tmp;
860       tmp.pushBack(curE1->clone());
861       int tmp2;
862       SplitPolygonsEachOther(tmp,cpyOfOther,tmp2);
863       numberOfCreatedPointsPerEdge[edgeId]=tmp.recursiveSize()-1;
864     }
865 }
866
867 /*!
868  * \b WARNING this method is const and other is const too. \b BUT location of Edges in 'this' and 'other' are nevertheless modified.
869  * This is possible because loc attribute in Edge class is mutable.
870  * This implies that if 'this' or/and 'other' are reused for intersect* method initLocations has to be called on each of this/them.
871  */
872 std::vector<QuadraticPolygon *> QuadraticPolygon::intersectMySelfWith(const QuadraticPolygon& other) const
873 {
874   QuadraticPolygon cpyOfThis(*this);
875   QuadraticPolygon cpyOfOther(other); int nbOfSplits=0;
876   SplitPolygonsEachOther(cpyOfThis,cpyOfOther,nbOfSplits);
877   //At this point cpyOfThis and cpyOfOther have been splited at maximum edge so that in/out can been done.
878   performLocatingOperation(cpyOfOther);
879   return other.buildIntersectionPolygons(cpyOfThis,cpyOfOther);
880 }
881
882 /*!
883  * This method is typically the first step of boolean operations between pol1 and pol2.
884  * This method perform the minimal splitting so that at the end each edges constituting pol1 are fully either IN or OUT or ON.
885  * @param pol1 IN/OUT param that is equal to 'this' when called.
886  */
887 void QuadraticPolygon::SplitPolygonsEachOther(QuadraticPolygon& pol1, QuadraticPolygon& pol2, int& nbOfSplits)
888 {
889   IteratorOnComposedEdge it1(&pol1),it2(&pol2);
890   MergePoints merge;
891   ComposedEdge *c1=new ComposedEdge;
892   ComposedEdge *c2=new ComposedEdge;
893   for(it2.first();!it2.finished();it2.next())
894     {
895       ElementaryEdge* curE2=it2.current();
896       if(!curE2->isThereStartPoint())
897         it1.first();
898       else
899         it1=curE2->getIterator();
900       for(;!it1.finished();)
901         {
902           
903           ElementaryEdge* curE1=it1.current();
904           merge.clear(); nbOfSplits++;
905           if(curE1->getPtr()->intersectWith(curE2->getPtr(),merge,*c1,*c2))
906             {
907               if(!curE1->getDirection()) c1->reverse();
908               if(!curE2->getDirection()) c2->reverse();
909               UpdateNeighbours(merge,it1,it2,c1,c2);
910               //Substitution of simple edge by sub-edges.
911               delete curE1; // <-- destroying simple edge coming from pol1
912               delete curE2; // <-- destroying simple edge coming from pol2
913               it1.insertElemEdges(c1,true);// <-- 2nd param is true to go next.
914               it2.insertElemEdges(c2,false);// <-- 2nd param is false to avoid to go next.
915               curE2=it2.current();
916               //
917               it1.assignMySelfToAllElems(c2);//To avoid that others
918               SoftDelete(c1);
919               SoftDelete(c2);
920               c1=new ComposedEdge;
921               c2=new ComposedEdge;
922             }
923           else
924             {
925               UpdateNeighbours(merge,it1,it2,curE1,curE2);
926               it1.next();
927             }
928         }
929     }
930   Delete(c1);
931   Delete(c2);
932 }
933
934 void QuadraticPolygon::performLocatingOperation(QuadraticPolygon& pol2) const
935 {
936   IteratorOnComposedEdge it(&pol2);
937   TypeOfEdgeLocInPolygon loc=FULL_ON_1;
938   for(it.first();!it.finished();it.next())
939     {
940       ElementaryEdge *cur=it.current();
941       loc=cur->locateFullyMySelf(*this,loc);
942     }
943 }
944
945 void QuadraticPolygon::performLocatingOperationSlow(QuadraticPolygon& pol2) const
946 {
947   IteratorOnComposedEdge it(&pol2);
948   for(it.first();!it.finished();it.next())
949     {
950       ElementaryEdge *cur=it.current();
951       cur->locateFullyMySelfAbsolute(*this);
952     }
953 }
954
955 /*!
956  * Given 2 polygons 'pol1' and 'pol2' (localized) the resulting polygons are returned.
957  *
958  * this : pol2 simplified.
959  * @param pol1 pol1 split.
960  * @param pol2 pol2 split.
961  */
962 std::vector<QuadraticPolygon *> QuadraticPolygon::buildIntersectionPolygons(const QuadraticPolygon& pol1, const QuadraticPolygon& pol2) const
963 {
964   std::vector<QuadraticPolygon *> ret;
965   std::list<QuadraticPolygon *> pol2Zip=pol2.zipConsecutiveInSegments();
966   if(!pol2Zip.empty())
967     closePolygons(pol2Zip,pol1,ret);
968   else
969     {//borders of pol2 do not cross pol1,and pol2 borders are outside of pol1. That is to say, either pol2 and pol1
970       //do not overlap or  pol1 is fully inside pol2. So in the first case no intersection, in the other case
971       //the intersection is pol1.
972       ElementaryEdge *e1FromPol1=pol1[0];
973       TypeOfEdgeLocInPolygon loc=FULL_ON_1;
974       loc=e1FromPol1->locateFullyMySelf(*this,loc);
975       if(loc==FULL_IN_1)
976         ret.push_back(new QuadraticPolygon(pol1));
977     }
978   return ret;
979 }
980
981 /*!
982  * Returns parts of potentially non closed-polygons. Each returned polygons are not mergeable.
983  * this : pol2 split and locallized.
984  */
985 std::list<QuadraticPolygon *> QuadraticPolygon::zipConsecutiveInSegments() const
986 {
987   std::list<QuadraticPolygon *> ret;
988   IteratorOnComposedEdge it(const_cast<QuadraticPolygon *>(this));
989   int nbOfTurns=recursiveSize();
990   int i=0;
991   if(!it.goToNextInOn(false,i,nbOfTurns))
992     return ret;
993   i=0;
994   //
995   while(i<nbOfTurns)
996     {
997       QuadraticPolygon *tmp1=new QuadraticPolygon;
998       TypeOfEdgeLocInPolygon loc=it.current()->getLoc();
999       while(loc!=FULL_OUT_1 && i<nbOfTurns)
1000         {
1001           ElementaryEdge *tmp3=it.current()->clone();
1002           tmp1->pushBack(tmp3);
1003           it.nextLoop(); i++;
1004           loc=it.current()->getLoc();
1005         }
1006       if(tmp1->empty())
1007         {
1008           delete tmp1;
1009           continue;
1010         }
1011       ret.push_back(tmp1);
1012       it.goToNextInOn(true,i,nbOfTurns);
1013     }
1014   return ret;
1015 }
1016
1017 /*!
1018  * 'this' should be considered as pol2Simplified.
1019  * @param pol2zip is a list of set of edges (openned polygon) coming from split polygon 2.
1020  * @param pol1 is split pol1.
1021  * @param results the resulting \b CLOSED polygons.
1022  */
1023 void QuadraticPolygon::closePolygons(std::list<QuadraticPolygon *>& pol2Zip, const QuadraticPolygon& pol1,
1024                                      std::vector<QuadraticPolygon *>& results) const
1025 {
1026   bool directionKnownInPol1=false;
1027   bool directionInPol1;
1028   for(std::list<QuadraticPolygon *>::iterator iter=pol2Zip.begin();iter!=pol2Zip.end();)
1029     {
1030       if((*iter)->completed())
1031         {
1032           results.push_back(*iter);
1033           directionKnownInPol1=false;
1034           iter=pol2Zip.erase(iter);
1035           continue;
1036         }
1037       if(!directionKnownInPol1)
1038         {
1039           if(!(*iter)->amIAChanceToBeCompletedBy(pol1,*this,directionInPol1))
1040             { delete *iter; iter=pol2Zip.erase(iter); continue; }
1041           else
1042             directionKnownInPol1=true;
1043         }
1044       std::list<QuadraticPolygon *>::iterator iter2=iter; iter2++;
1045       std::list<QuadraticPolygon *>::iterator iter3=(*iter)->fillAsMuchAsPossibleWith(pol1,iter2,pol2Zip.end(),directionInPol1);
1046       if(iter3!=pol2Zip.end())
1047         {
1048           (*iter)->pushBack(*iter3);
1049           SoftDelete(*iter3);
1050           pol2Zip.erase(iter3);
1051         }
1052     }
1053 }
1054
1055 /*!
1056  * 'this' is expected to be set of edges (not closed) of pol2 split.
1057  */
1058 bool QuadraticPolygon::amIAChanceToBeCompletedBy(const QuadraticPolygon& pol1Splitted,const QuadraticPolygon& pol2NotSplitted, bool& direction)
1059 {
1060   IteratorOnComposedEdge it(const_cast<QuadraticPolygon *>(&pol1Splitted));
1061   bool found=false;
1062   Node *n=getEndNode();
1063   ElementaryEdge *cur=it.current();
1064   for(it.first();!it.finished() && !found;)
1065     {
1066       cur=it.current();
1067       found=(cur->getStartNode()==n);
1068       if(!found)
1069         it.next();
1070     }
1071   if(!found)
1072     throw Exception("Internal error : polygons uncompatible each others. Should never happend");
1073   //Ok we found correspondance between this and pol1. Searching for right direction to close polygon.
1074   ElementaryEdge *e=_sub_edges.back();
1075   if(e->getLoc()==FULL_ON_1)
1076     {
1077       if(e->getPtr()==cur->getPtr())
1078         {
1079           direction=false;
1080           it.previousLoop();
1081           cur=it.current();
1082           Node *repr=cur->getPtr()->buildRepresentantOfMySelf();
1083           bool ret=pol2NotSplitted.isInOrOut(repr);
1084           repr->decrRef();
1085           return ret;
1086         }
1087       else
1088         {
1089           direction=true;
1090           Node *repr=cur->getPtr()->buildRepresentantOfMySelf();
1091           bool ret=pol2NotSplitted.isInOrOut(repr);
1092           repr->decrRef();
1093           return ret;
1094         }
1095     }
1096   else
1097     direction=cur->locateFullyMySelfAbsolute(pol2NotSplitted)==FULL_IN_1;
1098   return true;
1099 }
1100
1101 /*!
1102  * This method fills as much as possible 'this' (part of pol2 split) with edges of 'pol1Splitted'.
1103  */
1104 std::list<QuadraticPolygon *>::iterator QuadraticPolygon::fillAsMuchAsPossibleWith(const QuadraticPolygon& pol1Splitted,
1105                                                                                    std::list<QuadraticPolygon *>::iterator iStart,
1106                                                                                    std::list<QuadraticPolygon *>::iterator iEnd,
1107                                                                                    bool direction)
1108 {
1109   IteratorOnComposedEdge it(const_cast<QuadraticPolygon *>(&pol1Splitted));
1110   bool found=false;
1111   Node *n=getEndNode();
1112   ElementaryEdge *cur;
1113   for(it.first();!it.finished() && !found;)
1114     {
1115       cur=it.current();
1116       found=(cur->getStartNode()==n);
1117       if(!found)
1118         it.next();
1119     }
1120   if(!direction)
1121     it.previousLoop();
1122   Node *nodeToTest;
1123   std::list<QuadraticPolygon *>::iterator ret;
1124   do
1125     {
1126       cur=it.current();
1127       ElementaryEdge *tmp=cur->clone();
1128       if(!direction)
1129         tmp->reverse();
1130       pushBack(tmp);
1131       nodeToTest=tmp->getEndNode();
1132       direction?it.nextLoop():it.previousLoop();
1133       ret=CheckInList(nodeToTest,iStart,iEnd);
1134       if(completed())
1135         return iEnd;
1136     }
1137   while(ret==iEnd);
1138   return ret;
1139 }
1140
1141 std::list<QuadraticPolygon *>::iterator QuadraticPolygon::CheckInList(Node *n, std::list<QuadraticPolygon *>::iterator iStart,
1142                                                                       std::list<QuadraticPolygon *>::iterator iEnd)
1143 {
1144   for(std::list<QuadraticPolygon *>::iterator iter=iStart;iter!=iEnd;iter++)
1145     if((*iter)->isNodeIn(n))
1146       return iter;
1147   return iEnd;
1148 }
1149
1150 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,
1151                                        std::vector<double>& addCoordsQuadratic, std::vector<int>& conn, std::vector<int>& connI, std::vector<int>& nb1, std::vector<int>& nb2)
1152 {
1153   pol1.initLocations();
1154   for(std::set<Edge *>::const_iterator it9=notUsedInPol1.begin();it9!=notUsedInPol1.end();it9++)
1155     { (*it9)->initLocs(); (*it9)->declareOn(); }
1156   for(std::set<Edge *>::const_iterator itA=edgesInPol2OnBoundary.begin();itA!=edgesInPol2OnBoundary.end();itA++)
1157     { (*itA)->initLocs(); (*itA)->declareIn(); }
1158   ////
1159   std::set<Edge *> notUsedInPol1L(notUsedInPol1);
1160   IteratorOnComposedEdge it(const_cast<QuadraticPolygon *>(&pol1));
1161   int sz=pol1.size();
1162   std::list<QuadraticPolygon *> pol1Zip;
1163   if(pol1.size()==(int)notUsedInPol1.size() && edgesInPol2OnBoundary.empty())
1164     {
1165       pol1.appendCrudeData(mapp,0.,0.,1.,offset,addCoordsQuadratic,conn,connI); nb1.push_back(idThis); nb2.push_back(-1);
1166       return ;
1167     }
1168   while(!notUsedInPol1L.empty())
1169     {
1170       for(int i=0;i<sz && (it.current()->getStartNode()->getLoc()!=IN_1 || it.current()->getLoc()!=FULL_ON_1);i++)
1171         it.nextLoop();
1172       if(it.current()->getStartNode()->getLoc()!=IN_1 || it.current()->getLoc()!=FULL_ON_1)
1173         throw INTERP_KERNEL::Exception("Presence of a target polygon fully included in source polygon ! The partition of this leads to a non simply connex cell (with hole) ! Impossible ! Such resulting cell cannot be stored in MED cell format !");
1174       QuadraticPolygon *tmp1=new QuadraticPolygon;
1175       do
1176         {
1177           Edge *ee=it.current()->getPtr();
1178           if(ee->getLoc()==FULL_ON_1)
1179             {
1180               ee->incrRef(); notUsedInPol1L.erase(ee);
1181               tmp1->pushBack(new ElementaryEdge(ee,it.current()->getDirection()));    
1182             }
1183           it.nextLoop();
1184         }
1185       while(it.current()->getStartNode()->getLoc()!=IN_1 && !notUsedInPol1L.empty());
1186       pol1Zip.push_back(tmp1);
1187     }
1188   ////
1189   std::list<QuadraticPolygon *> retPolsUnderContruction;
1190   std::list<Edge *> edgesInPol2OnBoundaryL(edgesInPol2OnBoundary.begin(),edgesInPol2OnBoundary.end());
1191   std::map<QuadraticPolygon *, std::list<QuadraticPolygon *> > pol1ZipConsumed;
1192   std::size_t maxNbOfTurn=edgesInPol2OnBoundaryL.size(),nbOfTurn=0,iiMNT=0;
1193   for(std::list<QuadraticPolygon *>::const_iterator itMNT=pol1Zip.begin();itMNT!=pol1Zip.end();itMNT++,iiMNT++)
1194     nbOfTurn+=(*itMNT)->size();
1195   maxNbOfTurn=maxNbOfTurn*nbOfTurn; maxNbOfTurn*=maxNbOfTurn;
1196   nbOfTurn=0;
1197   while(nbOfTurn<maxNbOfTurn && ((!pol1Zip.empty() || !edgesInPol2OnBoundaryL.empty())))
1198     {
1199       for(std::list<QuadraticPolygon *>::iterator it1=retPolsUnderContruction.begin();it1!=retPolsUnderContruction.end();)
1200         {
1201           if((*it1)->getStartNode()==(*it1)->getEndNode())
1202             {
1203               it1++;
1204               continue;
1205             }
1206           Node *curN=(*it1)->getEndNode();
1207           bool smthHappened=false;
1208           for(std::list<Edge *>::iterator it2=edgesInPol2OnBoundaryL.begin();it2!=edgesInPol2OnBoundaryL.end();)
1209             {
1210               if(curN==(*it2)->getStartNode())
1211                 { (*it2)->incrRef(); (*it1)->pushBack(new ElementaryEdge(*it2,true)); curN=(*it2)->getEndNode(); smthHappened=true; it2=edgesInPol2OnBoundaryL.erase(it2); }
1212               else if(curN==(*it2)->getEndNode())
1213                 { (*it2)->incrRef(); (*it1)->pushBack(new ElementaryEdge(*it2,false)); curN=(*it2)->getStartNode(); smthHappened=true; it2=edgesInPol2OnBoundaryL.erase(it2); }
1214               else
1215                 it2++;
1216             }
1217           if(smthHappened)
1218             {
1219               for(std::list<QuadraticPolygon *>::iterator it3=pol1Zip.begin();it3!=pol1Zip.end();)
1220                 {
1221                   if(curN==(*it3)->getStartNode())
1222                     {
1223                       for(std::list<ElementaryEdge *>::const_iterator it4=(*it3)->_sub_edges.begin();it4!=(*it3)->_sub_edges.end();it4++)
1224                         { (*it4)->getPtr()->incrRef(); bool dir=(*it4)->getDirection(); (*it1)->pushBack(new ElementaryEdge((*it4)->getPtr(),dir)); }
1225                       smthHappened=true;
1226                       pol1ZipConsumed[*it1].push_back(*it3);
1227                       curN=(*it3)->getEndNode();
1228                       it3=pol1Zip.erase(it3);
1229                     }
1230                   else
1231                     it3++;
1232                 }
1233             }
1234           if(!smthHappened)
1235             {
1236               for(std::list<ElementaryEdge *>::const_iterator it5=(*it1)->_sub_edges.begin();it5!=(*it1)->_sub_edges.end();it5++)
1237                 {
1238                   Edge *ee=(*it5)->getPtr();
1239                   if(edgesInPol2OnBoundary.find(ee)!=edgesInPol2OnBoundary.end())
1240                     edgesInPol2OnBoundaryL.push_back(ee);
1241                 }
1242               for(std::list<QuadraticPolygon *>::iterator it6=pol1ZipConsumed[*it1].begin();it6!=pol1ZipConsumed[*it1].end();it6++)
1243                 pol1Zip.push_front(*it6);
1244               pol1ZipConsumed.erase(*it1);
1245               delete *it1;
1246               it1=retPolsUnderContruction.erase(it1);
1247             }
1248         }
1249       if(!pol1Zip.empty())
1250         {
1251           QuadraticPolygon *tmp=new QuadraticPolygon;
1252           QuadraticPolygon *first=*(pol1Zip.begin());
1253           for(std::list<ElementaryEdge *>::const_iterator it4=first->_sub_edges.begin();it4!=first->_sub_edges.end();it4++)
1254             { (*it4)->getPtr()->incrRef(); bool dir=(*it4)->getDirection(); tmp->pushBack(new ElementaryEdge((*it4)->getPtr(),dir)); }
1255           pol1ZipConsumed[tmp].push_back(first);
1256           retPolsUnderContruction.push_back(tmp);
1257           pol1Zip.erase(pol1Zip.begin());
1258         }
1259       nbOfTurn++;
1260     }
1261   if(nbOfTurn==maxNbOfTurn)
1262     {
1263       std::ostringstream oss; oss << "Error during reconstruction of residual of cell ! It appears that either source or/and target mesh is/are not conform !";
1264       oss << " Number of turns is = " << nbOfTurn << " !";
1265       throw INTERP_KERNEL::Exception(oss.str().c_str());
1266     }
1267   for(std::list<QuadraticPolygon *>::iterator it1=retPolsUnderContruction.begin();it1!=retPolsUnderContruction.end();it1++)
1268     {
1269       if((*it1)->getStartNode()==(*it1)->getEndNode())
1270         {
1271           (*it1)->appendCrudeData(mapp,0.,0.,1.,offset,addCoordsQuadratic,conn,connI); nb1.push_back(idThis); nb2.push_back(-1);
1272           for(std::list<QuadraticPolygon *>::iterator it6=pol1ZipConsumed[*it1].begin();it6!=pol1ZipConsumed[*it1].end();it6++)
1273             delete *it6;
1274           delete *it1;
1275         }
1276     }
1277 }