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