Salome HOME
Merge from V6_main (04/10/2012)
[modules/med.git] / src / INTERP_KERNEL / Geometric2D / InterpKernelGeo2DQuadraticPolygon.cxx
1 // Copyright (C) 2007-2012  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 <iomanip>
33 #include <cstring>
34 #include <limits>
35
36 using namespace INTERP_KERNEL;
37
38 namespace INTERP_KERNEL
39 {
40   const unsigned MAX_SIZE_OF_LINE_XFIG_FILE=1024;
41 }
42
43 QuadraticPolygon::QuadraticPolygon(const char *file)
44 {
45   char currentLine[MAX_SIZE_OF_LINE_XFIG_FILE];
46   std::ifstream stream(file);
47   stream.exceptions(std::ios_base::eofbit);
48   try
49     {
50       do
51         stream.getline(currentLine,MAX_SIZE_OF_LINE_XFIG_FILE);
52       while(strcmp(currentLine,"1200 2")!=0);
53       do
54         {
55           Edge *newEdge=Edge::BuildFromXfigLine(stream);
56           if(!empty())
57             newEdge->changeStartNodeWith(back()->getEndNode());
58           pushBack(newEdge);
59         }
60       while(1);
61     }
62   catch(std::ifstream::failure&)
63     {
64     }
65   front()->changeStartNodeWith(back()->getEndNode());
66 }
67
68 QuadraticPolygon::~QuadraticPolygon()
69 {
70 }
71
72 QuadraticPolygon *QuadraticPolygon::BuildLinearPolygon(std::vector<Node *>& nodes)
73 {
74   QuadraticPolygon *ret=new QuadraticPolygon;
75   std::size_t size=nodes.size();
76   for(std::size_t i=0;i<size;i++)
77     {
78       ret->pushBack(new EdgeLin(nodes[i],nodes[(i+1)%size]));
79       nodes[i]->decrRef();
80     }
81   return ret;
82 }
83
84 QuadraticPolygon *QuadraticPolygon::BuildArcCirclePolygon(std::vector<Node *>& nodes)
85 {
86   QuadraticPolygon *ret=new QuadraticPolygon;
87   std::size_t size=nodes.size();
88   for(std::size_t i=0;i<size/2;i++)
89     {
90       EdgeLin *e1,*e2;
91       e1=new EdgeLin(nodes[i],nodes[i+size/2]);
92       e2=new EdgeLin(nodes[i+size/2],nodes[(i+1)%(size/2)]);
93       SegSegIntersector inters(*e1,*e2);
94       bool colinearity=inters.areColinears();
95       delete e1; delete e2;
96       if(colinearity)
97         ret->pushBack(new EdgeLin(nodes[i],nodes[(i+1)%(size/2)]));
98       else
99         ret->pushBack(new EdgeArcCircle(nodes[i],nodes[i+size/2],nodes[(i+1)%(size/2)]));
100       nodes[i]->decrRef(); nodes[i+size/2]->decrRef();
101     }
102   return ret;
103 }
104
105 void QuadraticPolygon::BuildDbgFile(const std::vector<Node *>& nodes, const char *fileName)
106 {
107   std::ofstream file(fileName);
108   file << std::setprecision(16);
109   file << "  double coords[]=" << std::endl << "    { ";
110   for(std::vector<Node *>::const_iterator iter=nodes.begin();iter!=nodes.end();iter++)
111     {
112       if(iter!=nodes.begin())
113         file << "," << std::endl << "      ";
114       file << (*(*iter))[0] << ", " << (*(*iter))[1];
115     }
116   file << "};" << std::endl;
117 }
118
119 void QuadraticPolygon::closeMe() const
120 {
121   if(!front()->changeStartNodeWith(back()->getEndNode()))
122     throw(Exception("big error: not closed polygon..."));
123 }
124
125 void QuadraticPolygon::circularPermute()
126 {
127   if(_sub_edges.size()>1)
128     {
129       ElementaryEdge *first=_sub_edges.front();
130       _sub_edges.pop_front();
131       _sub_edges.push_back(first);
132     }
133 }
134
135 bool QuadraticPolygon::isButterflyAbs()
136 {
137   INTERP_KERNEL::Bounds b;
138   double xBary,yBary;
139   b.prepareForAggregation();
140   fillBounds(b); 
141   double dimChar=b.getCaracteristicDim();
142   b.getBarycenter(xBary,yBary);
143   applyGlobalSimilarity(xBary,yBary,dimChar);
144   //
145   return isButterfly();
146 }
147
148 bool QuadraticPolygon::isButterfly() const
149 {
150   for(std::list<ElementaryEdge *>::const_iterator it=_sub_edges.begin();it!=_sub_edges.end();it++)
151     {
152       Edge *e1=(*it)->getPtr();
153       std::list<ElementaryEdge *>::const_iterator it2=it;
154       it2++;
155       for(;it2!=_sub_edges.end();it2++)
156         {
157           MergePoints commonNode;
158           ComposedEdge *outVal1=new ComposedEdge;
159           ComposedEdge *outVal2=new ComposedEdge;
160           Edge *e2=(*it2)->getPtr();
161           if(e1->intersectWith(e2,commonNode,*outVal1,*outVal2))
162             {
163               Delete(outVal1);
164               Delete(outVal2);
165               return true;
166             }
167           Delete(outVal1);
168           Delete(outVal2);
169         }
170     }
171   return false;
172 }
173
174 void QuadraticPolygon::dumpInXfigFileWithOther(const ComposedEdge& other, const char *fileName) const
175 {
176   std::ofstream file(fileName);
177   const int resolution=1200;
178   Bounds box;
179   box.prepareForAggregation();
180   fillBounds(box);
181   other.fillBounds(box);
182   dumpInXfigFile(file,resolution,box);
183   other.ComposedEdge::dumpInXfigFile(file,resolution,box);
184 }
185
186 void QuadraticPolygon::dumpInXfigFile(const char *fileName) const
187 {
188   std::ofstream file(fileName);
189   const int resolution=1200;
190   Bounds box;
191   box.prepareForAggregation();
192   fillBounds(box);
193   dumpInXfigFile(file,resolution,box);
194 }
195
196 void QuadraticPolygon::dumpInXfigFile(std::ostream& stream, int resolution, const Bounds& box) const
197 {
198   stream << "#FIG 3.2  Produced by xfig version 3.2.5-alpha5" << std::endl;
199   stream << "Landscape" << std::endl;
200   stream << "Center" << std::endl;
201   stream << "Metric" << std::endl;
202   stream << "Letter" << std::endl;
203   stream << "100.00" << std::endl;
204   stream << "Single" << std::endl;
205   stream << "-2" << std::endl;
206   stream << resolution << " 2" << std::endl;
207   ComposedEdge::dumpInXfigFile(stream,resolution,box);
208 }
209
210 /*!
211  * Warning contrary to intersectWith method this method is \b NOT const. 'this' and 'other' are modified after call of this method.
212  */
213 double QuadraticPolygon::intersectWithAbs(QuadraticPolygon& other)
214 {
215   double ret=0.,xBaryBB,yBaryBB;
216   double fact=normalize(&other,xBaryBB,yBaryBB);
217   std::vector<QuadraticPolygon *> polygs=intersectMySelfWith(other);
218   for(std::vector<QuadraticPolygon *>::iterator iter=polygs.begin();iter!=polygs.end();iter++)
219     {
220       ret+=fabs((*iter)->getArea());
221       delete *iter;
222     }
223   return ret*fact*fact;
224 }
225
226 /*!
227  * This method splits 'this' with 'other' into smaller pieces localizable. 'mapThis' is a map that gives the correspondance between nodes contained in 'this' and node ids in a global mesh.
228  * In the same way, 'mapOther' gives the correspondance between nodes contained in 'other' and node ids in a global mesh from wich 'other' is extracted.
229  * This method has 1 out paramater : 'edgesThis', After the call of this method contains nodal connectivity (including type) of 'this' into globlal "this mesh".
230  * This method has 2 in/out parameters : 'subDivOther' and 'addCoo'.'otherEdgeIds' is useful to put values in 'edgesThis', 'subDivOther' and 'addCoo'.
231  * Size of 'otherEdgeIds' has to be equal to number of ElementaryEdges in 'other'. No check of that will be done.
232  * @param offset1 is the number of nodes contained in global mesh from which 'this' is extracted.
233  * @param offset2 is the sum of nodes contained in global mesh from which 'this' is extracted and 'other' is extracted.
234  * @param edgesInOtherColinearWithThis will be appended at the end of the vector with colinear edge ids of other (if any)
235  * @otherEdgeIds is a vector with the same size than other before calling this method. It gives in the same order the cell id in global other mesh.
236  */
237 void QuadraticPolygon::splitAbs(QuadraticPolygon& other, const std::map<INTERP_KERNEL::Node *,int>& mapThis, const std::map<INTERP_KERNEL::Node *,int>& mapOther, int offset1, int offset2 , const std::vector<int>& otherEdgeIds,
238                                 std::vector<int>& edgesThis, int cellIdThis, std::vector< std::vector<int> >& edgesInOtherColinearWithThis, std::vector< std::vector<int> >& subDivOther, std::vector<double>& addCoo)
239 {
240   double xBaryBB, yBaryBB;
241   double fact=normalizeExt(&other, xBaryBB, yBaryBB);
242   //
243   IteratorOnComposedEdge it1(this),it3(&other);
244   MergePoints merge;
245   ComposedEdge *c1=new ComposedEdge;
246   ComposedEdge *c2=new ComposedEdge;
247   int i=0;
248   std::map<INTERP_KERNEL::Node *,int> mapAddCoo;
249   for(it3.first();!it3.finished();it3.next(),i++)//iteration over 'other' _sub_edges
250     {
251       QuadraticPolygon otherTmp;
252       ElementaryEdge* curE3=it3.current();
253       otherTmp.pushBack(new ElementaryEdge(curE3->getPtr(),curE3->getDirection())); curE3->getPtr()->incrRef();
254       IteratorOnComposedEdge it2(&otherTmp);
255       for(it2.first();!it2.finished();it2.next())//iteration on subedges of 'other->_sub_edge'
256         {
257           ElementaryEdge* curE2=it2.current();
258           if(!curE2->isThereStartPoint())
259             it1.first();
260           else
261             it1=curE2->getIterator();
262           for(;!it1.finished();)//iteration over 'this' _sub_edges
263             {
264               ElementaryEdge* curE1=it1.current();
265               merge.clear();
266               if(curE1->getPtr()->intersectWith(curE2->getPtr(),merge,*c1,*c2))
267                 {
268                   if(!curE1->getDirection()) c1->reverse();
269                   if(!curE2->getDirection()) c2->reverse();
270                   UpdateNeighbours(merge,it1,it2,c1,c2);
271                   //Substitution of simple edge by sub-edges.
272                   delete curE1; // <-- destroying simple edge coming from pol1
273                   delete curE2; // <-- destroying simple edge coming from pol2
274                   it1.insertElemEdges(c1,true);// <-- 2nd param is true to go next.
275                   it2.insertElemEdges(c2,false);// <-- 2nd param is false to avoid to go next.
276                   curE2=it2.current();
277                   //
278                   it1.assignMySelfToAllElems(c2);//To avoid that others
279                   SoftDelete(c1);
280                   SoftDelete(c2);
281                   c1=new ComposedEdge;
282                   c2=new ComposedEdge;
283                 }
284               else
285                 {
286                   UpdateNeighbours(merge,it1,it2,curE1,curE2);
287                   it1.next();
288                 }
289             }
290         }
291       if(otherTmp.presenceOfOn())
292         edgesInOtherColinearWithThis[otherEdgeIds[i]].push_back(cellIdThis);
293       if(otherTmp._sub_edges.size()>1)
294         {
295           for(std::list<ElementaryEdge *>::const_iterator it=otherTmp._sub_edges.begin();it!=otherTmp._sub_edges.end();it++)
296             (*it)->fillGlobalInfoAbs2(mapThis,mapOther,offset1,offset2,/**/fact,xBaryBB,yBaryBB,/**/subDivOther[otherEdgeIds[i]],addCoo,mapAddCoo);
297         }
298     }
299   Delete(c1);
300   Delete(c2);
301   //
302   for(std::list<ElementaryEdge *>::const_iterator it=_sub_edges.begin();it!=_sub_edges.end();it++)
303     (*it)->fillGlobalInfoAbs(mapThis,mapOther,offset1,offset2,/**/fact,xBaryBB,yBaryBB,/**/edgesThis,addCoo,mapAddCoo);
304   //
305 }
306
307 /*!
308  * 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
309  * orientation of edge.
310  */
311 void QuadraticPolygon::buildFromCrudeDataArray(const std::map<int,INTERP_KERNEL::Node *>& mapp, bool isQuad, const int *nodalBg, const double *coords,
312                                                const int *descBg, const int *descEnd, const std::vector<std::vector<int> >& intersectEdges)
313 {
314   std::size_t nbOfSeg=std::distance(descBg,descEnd);
315   for(std::size_t i=0;i<nbOfSeg;i++)
316     {
317       appendEdgeFromCrudeDataArray(i,mapp,isQuad,nodalBg,coords,descBg,descEnd,intersectEdges);
318     }
319 }
320
321 void QuadraticPolygon::appendEdgeFromCrudeDataArray(std::size_t edgePos, const std::map<int,INTERP_KERNEL::Node *>& mapp, bool isQuad, const int *nodalBg, const double *coords,
322                                                     const int *descBg, const int *descEnd, const std::vector<std::vector<int> >& intersectEdges)
323 {
324   if(!isQuad)
325     {
326       bool direct=descBg[edgePos]>0;
327       int edgeId=abs(descBg[edgePos])-1;
328       const std::vector<int>& subEdge=intersectEdges[edgeId];
329       std::size_t nbOfSubEdges=subEdge.size()/2;
330       for(std::size_t j=0;j<nbOfSubEdges;j++)
331         appendSubEdgeFromCrudeDataArray(0,j,direct,edgeId,subEdge,mapp);
332     }
333   else
334     {
335       std::size_t nbOfSeg=std::distance(descBg,descEnd);
336       const double *st=coords+2*(nodalBg[edgePos]); 
337       INTERP_KERNEL::Node *st0=new INTERP_KERNEL::Node(st[0],st[1]);
338       const double *endd=coords+2*(nodalBg[(edgePos+1)%nbOfSeg]);
339       INTERP_KERNEL::Node *endd0=new INTERP_KERNEL::Node(endd[0],endd[1]);
340       const double *middle=coords+2*(nodalBg[edgePos+nbOfSeg]);
341       INTERP_KERNEL::Node *middle0=new INTERP_KERNEL::Node(middle[0],middle[1]);
342       EdgeLin *e1,*e2;
343       e1=new EdgeLin(st0,middle0);
344       e2=new EdgeLin(middle0,endd0);
345       SegSegIntersector inters(*e1,*e2);
346       bool colinearity=inters.areColinears();
347       delete e1; delete e2;
348       //
349       bool direct=descBg[edgePos]>0;
350       int edgeId=abs(descBg[edgePos])-1;
351       const std::vector<int>& subEdge=intersectEdges[edgeId];
352       std::size_t nbOfSubEdges=subEdge.size()/2;
353       if(colinearity)
354         {   
355           for(std::size_t j=0;j<nbOfSubEdges;j++)
356             appendSubEdgeFromCrudeDataArray(0,j,direct,edgeId,subEdge,mapp);
357         }
358       else
359         {
360           Edge *e=new EdgeArcCircle(st0,middle0,endd0,true);
361           for(std::size_t j=0;j<nbOfSubEdges;j++)
362             appendSubEdgeFromCrudeDataArray(e,j,direct,edgeId,subEdge,mapp);
363           e->decrRef();
364         }
365       st0->decrRef(); endd0->decrRef(); middle0->decrRef();
366     }
367 }
368
369 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)
370 {
371   std::size_t nbOfSubEdges=subEdge.size()/2;
372   if(!baseEdge)
373     {//it is not a quadratic subedge
374       Node *start=(*mapp.find(direct?subEdge[2*j]:subEdge[2*nbOfSubEdges-2*j-1])).second;
375       Node *end=(*mapp.find(direct?subEdge[2*j+1]:subEdge[2*nbOfSubEdges-2*j-2])).second;
376       ElementaryEdge *e=ElementaryEdge::BuildEdgeFromCrudeDataArray(true,start,end);
377       pushBack(e);
378     }
379   else
380     {//it is a quadratic subedge
381       Node *start=(*mapp.find(direct?subEdge[2*j]:subEdge[2*nbOfSubEdges-2*j-1])).second;
382       Node *end=(*mapp.find(direct?subEdge[2*j+1]:subEdge[2*nbOfSubEdges-2*j-2])).second;
383       Edge *ee=baseEdge->buildEdgeLyingOnMe(start,end);
384       ElementaryEdge *eee=new ElementaryEdge(ee,true);
385       pushBack(eee);
386     }
387 }
388
389 /*!
390  * 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
391  * orientation of edge.
392  */
393 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,
394                                                 const INTERP_KERNEL::QuadraticPolygon& pol1, const int *descBg1, const int *descEnd1, const std::vector<std::vector<int> >& intersectEdges1,
395                                                 const std::vector< std::vector<int> >& colinear1)
396 {
397   std::size_t nbOfSeg=std::distance(descBg,descEnd);
398   for(std::size_t i=0;i<nbOfSeg;i++)//loop over all edges of pol2
399     {
400       bool direct=descBg[i]>0;
401       int edgeId=abs(descBg[i])-1;//current edge id of pol2
402       bool directos=colinear1[edgeId].empty();
403       std::vector<std::pair<int,std::pair<bool,int> > > idIns1;
404       int offset1=0;
405       if(!directos)
406         {// if the current edge of pol2 has one or more colinear edges part into pol1
407           const std::vector<int>& c=colinear1[edgeId];
408           std::size_t nbOfEdgesIn1=std::distance(descBg1,descEnd1);
409           for(std::size_t j=0;j<nbOfEdgesIn1;j++)
410             {
411               int edgeId1=abs(descBg1[j])-1;
412               if(std::find(c.begin(),c.end(),edgeId1)!=c.end())
413                 {
414                   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
415                   //std::pair<edgeId1); direct1=descBg1[j]>0;
416                 }
417               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
418             }
419           directos=idIns1.empty();
420         }
421       if(directos)
422         {//no subpart of edge 'edgeId' of pol2 is in pol1 so let's operate the same thing that QuadraticPolygon::buildFromCrudeDataArray method
423           appendEdgeFromCrudeDataArray(i,mapp,isQuad,nodalBg,coords,descBg,descEnd,intersectEdges);
424         }
425       else
426         {//there is subpart of edge 'edgeId' of pol2 inside pol1
427           const std::vector<int>& subEdge=intersectEdges[edgeId];
428           std::size_t nbOfSubEdges=subEdge.size()/2;
429           for(std::size_t j=0;j<nbOfSubEdges;j++)
430             {
431               int idBg=direct?subEdge[2*j]:subEdge[2*nbOfSubEdges-2*j-1];
432               int idEnd=direct?subEdge[2*j+1]:subEdge[2*nbOfSubEdges-2*j-2];
433               bool direction11,found=false;
434               bool direct1;//store if needed the direction in 1
435               int offset2;
436               std::size_t nbOfSubEdges1;
437               for(std::vector<std::pair<int,std::pair<bool,int> > >::const_iterator it=idIns1.begin();it!=idIns1.end();it++)
438                 {
439                   int idIn1=(*it).first;//store if needed the cell id in 1
440                   direct1=(*it).second.first;
441                   offset1=(*it).second.second;
442                   const std::vector<int>& subEdge1PossiblyAlreadyIn1=intersectEdges1[idIn1];
443                   nbOfSubEdges1=subEdge1PossiblyAlreadyIn1.size()/2;
444                   offset2=0;
445                   for(std::size_t k=0;k<nbOfSubEdges1 && !found;k++)
446                     {//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
447                       if(subEdge1PossiblyAlreadyIn1[2*k]==idBg && subEdge1PossiblyAlreadyIn1[2*k+1]==idEnd)
448                         { direction11=true; found=true; }
449                       else if(subEdge1PossiblyAlreadyIn1[2*k]==idEnd && subEdge1PossiblyAlreadyIn1[2*k+1]==idBg)
450                         { direction11=false; found=true; }
451                       else
452                         offset2++;
453                     }
454                 }
455               if(!found)
456                 {//the current subedge of edge 'edgeId' of pol2 is not a part of the colinear edge 'idIn1' of pol1 -> build new Edge instance
457                   //appendEdgeFromCrudeDataArray(j,mapp,isQuad,nodalBg,coords,descBg,descEnd,intersectEdges);
458                   Node *start=(*mapp.find(idBg)).second;
459                   Node *end=(*mapp.find(idEnd)).second;
460                   ElementaryEdge *e=ElementaryEdge::BuildEdgeFromCrudeDataArray(true,start,end);
461                   pushBack(e);
462                 }
463               else
464                 {//the current subedge of edge 'edgeId' of pol2 is part of the colinear edge 'idIn1' of pol1 -> reuse Edge instance of pol1
465                   ElementaryEdge *e=pol1[offset1+(direct1?offset2:nbOfSubEdges1-offset2-1)];
466                   Edge *ee=e->getPtr();
467                   ee->incrRef(); ee->declareOn();
468                   pushBack(new ElementaryEdge(ee,!(direct1^direction11)));
469                 }
470             }
471         }
472     }
473 }
474
475 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
476 {
477   int nbOfNodesInPg=0;
478   bool presenceOfQuadratic=presenceOfQuadraticEdge();
479   conn.push_back(presenceOfQuadratic?NORM_QPOLYG:NORM_POLYGON);
480   for(std::list<ElementaryEdge *>::const_iterator it=_sub_edges.begin();it!=_sub_edges.end();it++)
481     {
482       Node *tmp=0;
483       tmp=(*it)->getStartNode();
484       std::map<INTERP_KERNEL::Node *,int>::const_iterator it1=mapp.find(tmp);
485       conn.push_back((*it1).second);
486       nbOfNodesInPg++;
487     }
488   if(presenceOfQuadratic)
489     {
490       int j=0;
491       int off=offset+((int)addCoordsQuadratic.size())/2;
492       for(std::list<ElementaryEdge *>::const_iterator it=_sub_edges.begin();it!=_sub_edges.end();it++,j++,nbOfNodesInPg++)
493         {
494           INTERP_KERNEL::Node *node=(*it)->getPtr()->buildRepresentantOfMySelf();
495           node->unApplySimilarity(xBary,yBary,fact);
496           addCoordsQuadratic.push_back((*node)[0]);
497           addCoordsQuadratic.push_back((*node)[1]);
498           conn.push_back(off+j);
499           node->decrRef();
500         }
501     }
502   connI.push_back(connI.back()+nbOfNodesInPg+1);
503 }
504
505 /*!
506  * This method make the hypothesis that 'this' and 'other' are splited at the minimum into edges that are fully IN, OUT or ON.
507  * This method returns newly created polygons in 'conn' and 'connI' and the corresponding ids ('idThis','idOther') are stored respectively into 'nbThis' and 'nbOther'.
508  */
509 void QuadraticPolygon::buildPartitionsAbs(QuadraticPolygon& other, 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)
510 {
511   double xBaryBB, yBaryBB;
512   double fact=normalizeExt(&other, xBaryBB, yBaryBB);
513   //Locate 'this' relative to 'other'
514   other.performLocatingOperation(*this);
515   std::vector<QuadraticPolygon *> res=buildIntersectionPolygons(other,*this);
516   for(std::vector<QuadraticPolygon *>::iterator it=res.begin();it!=res.end();it++)
517     {
518       (*it)->appendCrudeData(mapp,xBaryBB,yBaryBB,fact,offset,addCoordsQuadratic,conn,connI);
519       nbThis.push_back(idThis);
520       nbOther.push_back(idOther);
521       delete *it;
522     }
523   unApplyGlobalSimilarityExt(other,xBaryBB,yBaryBB,fact);
524 }
525
526 /*!
527  * Warning This method is \b NOT const. 'this' and 'other' are modified after call of this method.
528  * 'other' is a QuadraticPolygon of \b non closed edges.
529  */
530 double QuadraticPolygon::intersectWithAbs1D(QuadraticPolygon& other, bool& isColinear)
531 {
532   double ret = 0., xBaryBB, yBaryBB;
533   double fact = normalize(&other, xBaryBB, yBaryBB);
534
535   QuadraticPolygon cpyOfThis(*this);
536   QuadraticPolygon cpyOfOther(other);
537   int nbOfSplits = 0;
538   SplitPolygonsEachOther(cpyOfThis, cpyOfOther, nbOfSplits);
539   //At this point cpyOfThis and cpyOfOther have been splited at maximum edge so that in/out can been done.
540   performLocatingOperation(cpyOfOther);
541   isColinear = false;
542   for(std::list<ElementaryEdge *>::const_iterator it=cpyOfOther._sub_edges.begin();it!=cpyOfOther._sub_edges.end();it++)
543     {
544       switch((*it)->getLoc())
545         {
546         case FULL_IN_1:
547           {
548             ret += fabs((*it)->getPtr()->getCurveLength());
549             break;
550           }
551         case FULL_ON_1:
552           {
553             isColinear=true;
554             ret += fabs((*it)->getPtr()->getCurveLength());
555             break;
556           }
557         default:
558           {
559           }
560         }
561     }
562   return ret * fact;
563 }
564
565 /*!
566  * Warning contrary to intersectWith method this method is \b NOT const. 'this' and 'other' are modified after call of this method.
567  */
568 double QuadraticPolygon::intersectWithAbs(QuadraticPolygon& other, double* barycenter)
569 {
570   double ret=0.,bary[2],area,xBaryBB,yBaryBB;
571   barycenter[0] = barycenter[1] = 0.;
572   double fact=normalize(&other,xBaryBB,yBaryBB);
573   std::vector<QuadraticPolygon *> polygs=intersectMySelfWith(other);
574   for(std::vector<QuadraticPolygon *>::iterator iter=polygs.begin();iter!=polygs.end();iter++)
575     {
576       area=fabs((*iter)->getArea());
577       (*iter)->getBarycenter(bary);
578       delete *iter;
579       ret+=area;
580       barycenter[0] += bary[0]*area;
581       barycenter[1] += bary[1]*area;
582     }
583   if ( ret > std::numeric_limits<double>::min() )
584     {
585       barycenter[0]=barycenter[0]/ret*fact+xBaryBB;
586       barycenter[1]=barycenter[1]/ret*fact+yBaryBB;
587       
588     }
589   return ret*fact*fact;
590 }
591
592 /*!
593  * \b WARNING this method is const and other is const too. \b BUT location of Edges in 'this' and 'other' are nevertheless modified.
594  * This is possible because loc attribute in Edge class is mutable.
595  * This implies that if 'this' or/and 'other' are reused for intersect* method initLocations has to be called on each of this/them.
596  */
597 double QuadraticPolygon::intersectWith(const QuadraticPolygon& other) const
598 {
599   double ret=0.;
600   std::vector<QuadraticPolygon *> polygs=intersectMySelfWith(other);
601   for(std::vector<QuadraticPolygon *>::iterator iter=polygs.begin();iter!=polygs.end();iter++)
602     {
603       ret+=fabs((*iter)->getArea());
604       delete *iter;
605     }
606   return ret;
607 }
608
609 /*!
610  * \b WARNING this method is const and other is const too. \b BUT location of Edges in 'this' and 'other' are nevertheless modified.
611  * This is possible because loc attribute in Edge class is mutable.
612  * This implies that if 'this' or/and 'other' are reused for intersect* method initLocations has to be called on each of this/them.
613  */
614 double QuadraticPolygon::intersectWith(const QuadraticPolygon& other, double* barycenter) const
615 {
616   double ret=0., bary[2];
617   barycenter[0] = barycenter[1] = 0.;
618   std::vector<QuadraticPolygon *> polygs=intersectMySelfWith(other);
619   for(std::vector<QuadraticPolygon *>::iterator iter=polygs.begin();iter!=polygs.end();iter++)
620     {
621       double area = fabs((*iter)->getArea());
622       (*iter)->getBarycenter(bary);
623       delete *iter;
624       ret+=area;
625       barycenter[0] += bary[0]*area;
626       barycenter[1] += bary[1]*area;
627     }
628   if ( ret > std::numeric_limits<double>::min() )
629     {
630       barycenter[0] /= ret;
631       barycenter[1] /= ret;
632     }
633   return ret;
634 }
635
636 /*!
637  * \b WARNING this method is const and other is const too. \b BUT location of Edges in 'this' and 'other' are nevertheless modified.
638  * This is possible because loc attribute in Edge class is mutable.
639  * This implies that if 'this' or/and 'other' are reused for intersect* method initLocations has to be called on each of this/them.
640  */
641 void QuadraticPolygon::intersectForPerimeter(const QuadraticPolygon& other, double& perimeterThisPart, double& perimeterOtherPart, double& perimeterCommonPart) const
642 {
643   perimeterThisPart=0.; perimeterOtherPart=0.; perimeterCommonPart=0.;
644   QuadraticPolygon cpyOfThis(*this);
645   QuadraticPolygon cpyOfOther(other); int nbOfSplits=0;
646   SplitPolygonsEachOther(cpyOfThis,cpyOfOther,nbOfSplits);
647   performLocatingOperation(cpyOfOther);
648   other.performLocatingOperation(cpyOfThis);
649   cpyOfThis.dispatchPerimeterExcl(perimeterThisPart,perimeterCommonPart);
650   cpyOfOther.dispatchPerimeterExcl(perimeterOtherPart,perimeterCommonPart);
651   perimeterCommonPart/=2.;
652 }
653
654 /*!
655  * \b WARNING this method is const and other is const too. \b BUT location of Edges in 'this' and 'other' are nevertheless modified.
656  * This is possible because loc attribute in Edge class is mutable.
657  * This implies that if 'this' or/and 'other' are reused for intersect* method initLocations has to be called on each of this/them.
658  *
659  * polThis.size()==this->size() and polOther.size()==other.size().
660  * For each ElementaryEdge of 'this', the corresponding contribution in resulting polygon is in 'polThis'.
661  * For each ElementaryEdge of 'other', the corresponding contribution in resulting polygon is in 'polOther'.
662  * As consequence common part are counted twice (in polThis \b and in polOther).
663  */
664 void QuadraticPolygon::intersectForPerimeterAdvanced(const QuadraticPolygon& other, std::vector< double >& polThis, std::vector< double >& polOther) const
665 {
666   polThis.resize(size());
667   polOther.resize(other.size());
668   IteratorOnComposedEdge it1(const_cast<QuadraticPolygon *>(this));
669   int edgeId=0;
670   for(it1.first();!it1.finished();it1.next(),edgeId++)
671     {
672       ElementaryEdge* curE1=it1.current();
673       QuadraticPolygon cpyOfOther(other);
674       QuadraticPolygon tmp;
675       tmp.pushBack(curE1->clone());
676       int tmp2;
677       SplitPolygonsEachOther(tmp,cpyOfOther,tmp2);
678       other.performLocatingOperation(tmp);
679       tmp.dispatchPerimeter(polThis[edgeId]);
680     }
681   //
682   IteratorOnComposedEdge it2(const_cast<QuadraticPolygon *>(&other));
683   edgeId=0;
684   for(it2.first();!it2.finished();it2.next(),edgeId++)
685     {
686       ElementaryEdge* curE2=it2.current();
687       QuadraticPolygon cpyOfThis(*this);
688       QuadraticPolygon tmp;
689       tmp.pushBack(curE2->clone());
690       int tmp2;
691       SplitPolygonsEachOther(tmp,cpyOfThis,tmp2);
692       performLocatingOperation(tmp);
693       tmp.dispatchPerimeter(polOther[edgeId]);
694     }
695 }
696
697
698 /*!
699  * numberOfCreatedPointsPerEdge is resized to the number of edges of 'this'.
700  * This method returns in ordered maner the number of newly created points per edge.
701  * This method performs a split process between 'this' and 'other' that gives the result PThis.
702  * Then for each edges of 'this' this method counts how many edges in Pthis have the same id.
703  */
704 void QuadraticPolygon::intersectForPoint(const QuadraticPolygon& other, std::vector< int >& numberOfCreatedPointsPerEdge) const
705 {
706   numberOfCreatedPointsPerEdge.resize(size());
707   IteratorOnComposedEdge it1(const_cast<QuadraticPolygon *>(this));
708   int edgeId=0;
709   for(it1.first();!it1.finished();it1.next(),edgeId++)
710     {
711       ElementaryEdge* curE1=it1.current();
712       QuadraticPolygon cpyOfOther(other);
713       QuadraticPolygon tmp;
714       tmp.pushBack(curE1->clone());
715       int tmp2;
716       SplitPolygonsEachOther(tmp,cpyOfOther,tmp2);
717       numberOfCreatedPointsPerEdge[edgeId]=tmp.recursiveSize()-1;
718     }
719 }
720
721 /*!
722  * \b WARNING this method is const and other is const too. \b BUT location of Edges in 'this' and 'other' are nevertheless modified.
723  * This is possible because loc attribute in Edge class is mutable.
724  * This implies that if 'this' or/and 'other' are reused for intersect* method initLocations has to be called on each of this/them.
725  */
726 std::vector<QuadraticPolygon *> QuadraticPolygon::intersectMySelfWith(const QuadraticPolygon& other) const
727 {
728   QuadraticPolygon cpyOfThis(*this);
729   QuadraticPolygon cpyOfOther(other); int nbOfSplits=0;
730   SplitPolygonsEachOther(cpyOfThis,cpyOfOther,nbOfSplits);
731   //At this point cpyOfThis and cpyOfOther have been splited at maximum edge so that in/out can been done.
732   performLocatingOperation(cpyOfOther);
733   return other.buildIntersectionPolygons(cpyOfThis,cpyOfOther);
734 }
735
736 /*!
737  * This method is typically the first step of boolean operations between pol1 and pol2.
738  * This method perform the minimal splitting so that at the end each edges constituting pol1 are fully either IN or OUT or ON.
739  * @param pol1 IN/OUT param that is equal to 'this' when called.
740  */
741 void QuadraticPolygon::SplitPolygonsEachOther(QuadraticPolygon& pol1, QuadraticPolygon& pol2, int& nbOfSplits)
742 {
743   IteratorOnComposedEdge it1(&pol1),it2(&pol2);
744   MergePoints merge;
745   ComposedEdge *c1=new ComposedEdge;
746   ComposedEdge *c2=new ComposedEdge;
747   for(it2.first();!it2.finished();it2.next())
748     {
749       ElementaryEdge* curE2=it2.current();
750       if(!curE2->isThereStartPoint())
751         it1.first();
752       else
753         it1=curE2->getIterator();
754       for(;!it1.finished();)
755         {
756           
757           ElementaryEdge* curE1=it1.current();
758           merge.clear(); nbOfSplits++;
759           if(curE1->getPtr()->intersectWith(curE2->getPtr(),merge,*c1,*c2))
760             {
761               if(!curE1->getDirection()) c1->reverse();
762               if(!curE2->getDirection()) c2->reverse();
763               UpdateNeighbours(merge,it1,it2,c1,c2);
764               //Substitution of simple edge by sub-edges.
765               delete curE1; // <-- destroying simple edge coming from pol1
766               delete curE2; // <-- destroying simple edge coming from pol2
767               it1.insertElemEdges(c1,true);// <-- 2nd param is true to go next.
768               it2.insertElemEdges(c2,false);// <-- 2nd param is false to avoid to go next.
769               curE2=it2.current();
770               //
771               it1.assignMySelfToAllElems(c2);//To avoid that others
772               SoftDelete(c1);
773               SoftDelete(c2);
774               c1=new ComposedEdge;
775               c2=new ComposedEdge;
776             }
777           else
778             {
779               UpdateNeighbours(merge,it1,it2,curE1,curE2);
780               it1.next();
781             }
782         }
783     }
784   Delete(c1);
785   Delete(c2);
786 }
787
788 void QuadraticPolygon::performLocatingOperation(QuadraticPolygon& pol2) const
789 {
790   IteratorOnComposedEdge it(&pol2);
791   TypeOfEdgeLocInPolygon loc=FULL_ON_1;
792   for(it.first();!it.finished();it.next())
793     {
794       ElementaryEdge *cur=it.current();
795       loc=cur->locateFullyMySelf(*this,loc);
796     }
797 }
798
799 /*!
800  * Given 2 polygons 'pol1' and 'pol2' (localized) the resulting polygons are returned.
801  *
802  * this : pol2 simplified.
803  * @param pol1 pol1 split.
804  * @param pol2 pol2 split.
805  */
806 std::vector<QuadraticPolygon *> QuadraticPolygon::buildIntersectionPolygons(const QuadraticPolygon& pol1, const QuadraticPolygon& pol2) const
807 {
808   std::vector<QuadraticPolygon *> ret;
809   std::list<QuadraticPolygon *> pol2Zip=pol2.zipConsecutiveInSegments();
810   if(!pol2Zip.empty())
811     closePolygons(pol2Zip,pol1,ret);
812   else
813     {//borders of pol2 do not cross pol1,and pol2 borders are outside of pol1. That is to say, either pol2 and pol1
814       //do not overlap or  pol1 is fully inside pol2. So in the first case no intersection, in the other case
815       //the intersection is pol1.
816       ElementaryEdge *e1FromPol1=pol1[0];
817       TypeOfEdgeLocInPolygon loc=FULL_ON_1;
818       loc=e1FromPol1->locateFullyMySelf(*this,loc);
819       if(loc==FULL_IN_1)
820         ret.push_back(new QuadraticPolygon(pol1));
821     }
822   return ret;
823 }
824
825 /*!
826  * Returns parts of potentially non closed-polygons. Each returned polygons are not mergeable.
827  * this : pol2 split and locallized.
828  */
829 std::list<QuadraticPolygon *> QuadraticPolygon::zipConsecutiveInSegments() const
830 {
831   std::list<QuadraticPolygon *> ret;
832   IteratorOnComposedEdge it((ComposedEdge *)this);
833   int nbOfTurns=recursiveSize();
834   int i=0;
835   if(!it.goToNextInOn(false,i,nbOfTurns))
836     return ret;
837   i=0;
838   //
839   while(i<nbOfTurns)
840     {
841       QuadraticPolygon *tmp1=new QuadraticPolygon;
842       TypeOfEdgeLocInPolygon loc=it.current()->getLoc();
843       while(loc!=FULL_OUT_1 && i<nbOfTurns)
844         {
845           ElementaryEdge *tmp3=it.current()->clone();
846           tmp1->pushBack(tmp3);
847           it.nextLoop(); i++;
848           loc=it.current()->getLoc();
849         }
850       if(tmp1->empty())
851         {
852           delete tmp1;
853           continue;
854         }
855       ret.push_back(tmp1);
856       it.goToNextInOn(true,i,nbOfTurns);
857     }
858   return ret;
859 }
860
861 /*!
862  * 'this' should be considered as pol2Simplified.
863  * @param pol2zip is a list of set of edges (openned polygon) coming from split polygon 2.
864  * @param pol1 is split pol1.
865  * @param results the resulting \b CLOSED polygons.
866  */
867 void QuadraticPolygon::closePolygons(std::list<QuadraticPolygon *>& pol2Zip, const QuadraticPolygon& pol1,
868                                      std::vector<QuadraticPolygon *>& results) const
869 {
870   bool directionKnownInPol1=false;
871   bool directionInPol1;
872   for(std::list<QuadraticPolygon *>::iterator iter=pol2Zip.begin();iter!=pol2Zip.end();)
873     {
874       if((*iter)->completed())
875         {
876           results.push_back(*iter);
877           directionKnownInPol1=false;
878           iter=pol2Zip.erase(iter);
879           continue;
880         }
881       if(!directionKnownInPol1)
882         {
883           if(!(*iter)->amIAChanceToBeCompletedBy(pol1,*this,directionInPol1))
884             { delete *iter; iter=pol2Zip.erase(iter); continue; }
885           else
886             directionKnownInPol1=true;
887         }
888       std::list<QuadraticPolygon *>::iterator iter2=iter; iter2++;
889       std::list<QuadraticPolygon *>::iterator iter3=(*iter)->fillAsMuchAsPossibleWith(pol1,iter2,pol2Zip.end(),directionInPol1);
890       if(iter3!=pol2Zip.end())
891         {
892           (*iter)->pushBack(*iter3);
893           SoftDelete(*iter3);
894           pol2Zip.erase(iter3);
895         }
896     }
897 }
898
899 /*!
900  * 'this' is expected to be set of edges (not closed) of pol2 split.
901  */
902 bool QuadraticPolygon::amIAChanceToBeCompletedBy(const QuadraticPolygon& pol1Splitted,const QuadraticPolygon& pol2NotSplitted, bool& direction)
903 {
904   IteratorOnComposedEdge it(const_cast<QuadraticPolygon *>(&pol1Splitted));
905   bool found=false;
906   Node *n=getEndNode();
907   ElementaryEdge *cur=it.current();
908   for(it.first();!it.finished() && !found;)
909     {
910       cur=it.current();
911       found=(cur->getStartNode()==n);
912       if(!found)
913         it.next();
914     }
915   if(!found)
916     throw Exception("Internal error : polygons uncompatible each others. Should never happend");
917   //Ok we found correspondance between this and pol1. Searching for right direction to close polygon.
918   ElementaryEdge *e=_sub_edges.back();
919   if(e->getLoc()==FULL_ON_1)
920     {
921       if(e->getPtr()==cur->getPtr())
922         {
923           direction=false;
924           it.previousLoop();
925           cur=it.current();
926           Node *repr=cur->getPtr()->buildRepresentantOfMySelf();
927           bool ret=pol2NotSplitted.isInOrOut(repr);
928           repr->decrRef();
929           return ret;
930         }
931       else
932         {
933           direction=true;
934           Node *repr=cur->getPtr()->buildRepresentantOfMySelf();
935           bool ret=pol2NotSplitted.isInOrOut(repr);
936           repr->decrRef();
937           return ret;
938         }
939     }
940   else
941     direction=cur->locateFullyMySelfAbsolute(pol2NotSplitted)==FULL_IN_1;
942   return true;
943 }
944
945 /*!
946  * This method fills as much as possible 'this' (part of pol2 split) with edges of 'pol1Splitted'.
947  */
948 std::list<QuadraticPolygon *>::iterator QuadraticPolygon::fillAsMuchAsPossibleWith(const QuadraticPolygon& pol1Splitted,
949                                                                                    std::list<QuadraticPolygon *>::iterator iStart,
950                                                                                    std::list<QuadraticPolygon *>::iterator iEnd,
951                                                                                    bool direction)
952 {
953   IteratorOnComposedEdge it(const_cast<QuadraticPolygon *>(&pol1Splitted));
954   bool found=false;
955   Node *n=getEndNode();
956   ElementaryEdge *cur;
957   for(it.first();!it.finished() && !found;)
958     {
959       cur=it.current();
960       found=(cur->getStartNode()==n);
961       if(!found)
962         it.next();
963     }
964   if(!direction)
965     it.previousLoop();
966   Node *nodeToTest;
967   std::list<QuadraticPolygon *>::iterator ret;
968   do
969     {
970       cur=it.current();
971       ElementaryEdge *tmp=cur->clone();
972       if(!direction)
973         tmp->reverse();
974       pushBack(tmp);
975       nodeToTest=tmp->getEndNode();
976       direction?it.nextLoop():it.previousLoop();
977       ret=CheckInList(nodeToTest,iStart,iEnd);
978       if(completed())
979         return iEnd;
980     }
981   while(ret==iEnd);
982   return ret;
983 }
984
985 std::list<QuadraticPolygon *>::iterator QuadraticPolygon::CheckInList(Node *n, std::list<QuadraticPolygon *>::iterator iStart,
986                                                                       std::list<QuadraticPolygon *>::iterator iEnd)
987 {
988   for(std::list<QuadraticPolygon *>::iterator iter=iStart;iter!=iEnd;iter++)
989     if((*iter)->isNodeIn(n))
990       return iter;
991   return iEnd;
992 }