Salome HOME
Merge from V6_main (04/10/2012)
[modules/med.git] / src / INTERP_KERNEL / Geometric2D / InterpKernelGeo2DEdgeArcCircle.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 "InterpKernelGeo2DEdgeArcCircle.hxx"
22 #include "InterpKernelGeo2DEdgeLin.hxx"
23 #include "InterpKernelException.hxx"
24 #include "InterpKernelGeo2DNode.hxx"
25 #include "NormalizedUnstructuredMesh.hxx"
26
27 #include <sstream>
28 #include <algorithm>
29
30 using namespace INTERP_KERNEL;
31
32 ArcCArcCIntersector::ArcCArcCIntersector(const EdgeArcCircle& e1, const EdgeArcCircle& e2):SameTypeEdgeIntersector(e1,e2),_dist(0.)
33 {
34 }
35
36 bool ArcCArcCIntersector::haveTheySameDirection() const
37 {
38   return (getE1().getAngle()>0. &&  getE2().getAngle()>0.) || (getE1().getAngle()<0. &&  getE2().getAngle()<0.);
39 }
40
41 /*!
42  * Precondition 'start' and 'end' are on the same curve than this.
43  */
44 void ArcCArcCIntersector::getPlacements(Node *start, Node *end, TypeOfLocInEdge& whereStart, TypeOfLocInEdge& whereEnd, MergePoints& commonNode) const
45 {
46   bool obvious1,obvious2;
47   obviousCaseForCurvAbscisse(start,whereStart,commonNode,obvious1);
48   obviousCaseForCurvAbscisse(end,whereEnd,commonNode,obvious2);
49   if(obvious1 && obvious2)
50     return ;
51   double angleInRadStart=getAngle(start);
52   double angleInRadEnd=getAngle(end);
53   if(obvious1 || obvious2)
54     {
55       if(obvious1)
56         {
57           if(EdgeArcCircle::IsIn2Pi(getE1().getAngle0(),getE1().getAngle(),angleInRadEnd))
58             whereEnd=INSIDE;
59           else
60             whereEnd=OUT_AFTER;
61           return ;
62         }
63       else
64         {
65           if(EdgeArcCircle::IsIn2Pi(getE1().getAngle0(),getE1().getAngle(),angleInRadStart))
66             whereStart=INSIDE;
67           else
68             whereStart=OUT_BEFORE;
69           return ;
70         }
71     }
72   if(EdgeArcCircle::IsIn2Pi(getE1().getAngle0(),getE1().getAngle(),angleInRadStart))
73     {
74       whereStart=INSIDE;
75       if(EdgeArcCircle::IsIn2Pi(getE1().getAngle0(),getE1().getAngle(),angleInRadEnd))
76         whereEnd=INSIDE;
77       else
78         whereEnd=OUT_AFTER;
79     }
80   else
81     {//we are out in start.
82       if(EdgeArcCircle::IsIn2Pi(getE1().getAngle0(),getE1().getAngle(),angleInRadEnd))
83         {
84           whereStart=OUT_BEFORE;
85           whereEnd=INSIDE;
86         }
87       else
88         {
89           if(EdgeArcCircle::IsIn2Pi(getE2().getAngle0(),getE2().getAngle(),getE1().getAngle0()))
90             {//_e2 contains stictly _e1
91               whereStart=OUT_BEFORE;
92               whereEnd=OUT_AFTER;
93             }
94           else
95             {//_e2 is outside from _e1
96               whereStart=OUT_BEFORE;
97               whereEnd=OUT_BEFORE;
98             }
99         }
100     }
101 }
102
103 /*!
104  * Return angle between ]-Pi;Pi[
105  */
106 double ArcCArcCIntersector::getAngle(Node *node) const
107 {
108   return EdgeArcCircle::GetAbsoluteAngleOfNormalizedVect(((*node)[0]-getE1().getCenter()[0])/getE1().getRadius(),((*node)[1]-getE1().getCenter()[1])/getE1().getRadius());
109 }
110
111 bool ArcCArcCIntersector::areArcsOverlapped(const EdgeArcCircle& a1, const EdgeArcCircle& a2)
112 {
113   double centerL[2],radiusL,angle0L,angleL;
114   double centerB[2],radiusB;
115   double lgth1=fabs(a1.getAngle()*a1.getRadius());
116   double lgth2=fabs(a2.getAngle()*a2.getRadius());
117   if(lgth1<lgth2)
118     {//a1 is the little one ('L') and a2 the big one ('B')
119       a1.getCenter(centerL); radiusL=a1.getRadius(); angle0L=a1.getAngle0(); angleL=a1.getAngle();
120       a2.getCenter(centerB); radiusB=a2.getRadius();
121     }
122   else
123     {
124       a2.getCenter(centerL); radiusL=a2.getRadius(); angle0L=a2.getAngle0(); angleL=a2.getAngle();
125       a1.getCenter(centerB); radiusB=a1.getRadius();
126     }
127   // dividing from the begining by radiusB^2 to keep precision
128   double tmp=Node::distanceBtw2PtSq(centerL,centerB);
129   double cst=tmp/(radiusB*radiusB);
130   cst+=radiusL*radiusL/(radiusB*radiusB);
131   if(!Node::areDoubleEqualsWP(cst,1.,2.))
132     return false;
133   //
134   Bounds *merge=a1.getBounds().nearlyAmIIntersectingWith(a2.getBounds());
135   merge->getInterceptedArc(centerL,radiusL,angle0L,angleL);
136   delete merge;
137   //
138   tmp=sqrt(tmp);
139   if(Node::areDoubleEqualsWP(tmp,0.,1/(10*std::max(radiusL,radiusB))))
140     {
141       if(Node::areDoubleEquals(radiusL,radiusB))
142         return true;
143       else
144         return false;
145     }
146   double phi=EdgeArcCircle::GetAbsoluteAngleOfNormalizedVect((centerL[0]-centerB[0])/tmp,(centerL[1]-centerB[1])/tmp);
147   double cst2=2*radiusL*tmp/(radiusB*radiusB);
148   double cmpContainer[4];
149   int sizeOfCmpContainer=2;
150   cmpContainer[0]=cst+cst2*cos(phi-angle0L);
151   cmpContainer[1]=cst+cst2*cos(phi-angle0L+angleL);
152   double a=EdgeArcCircle::NormalizeAngle(phi-angle0L);
153   if(EdgeArcCircle::IsIn2Pi(angle0L,angleL,a))
154     cmpContainer[sizeOfCmpContainer++]=cst+cst2;
155   a=EdgeArcCircle::NormalizeAngle(phi-angle0L+M_PI);
156   if(EdgeArcCircle::IsIn2Pi(angle0L,angleL,a))
157     cmpContainer[sizeOfCmpContainer++]=cst-cst2;
158   a=*std::max_element(cmpContainer,cmpContainer+sizeOfCmpContainer);
159   return Node::areDoubleEqualsWP(a,1.,2.);
160 }
161
162 void ArcCArcCIntersector::areOverlappedOrOnlyColinears(const Bounds *whereToFind, bool& obviousNoIntersection, bool& areOverlapped)
163 {
164   _dist=Node::distanceBtw2Pt(getE1().getCenter(),getE2().getCenter());
165   double radius1=getE1().getRadius(); double radius2=getE2().getRadius();
166   if(_dist>radius1+radius2+QUADRATIC_PLANAR::_precision || _dist+std::min(radius1,radius2)+QUADRATIC_PLANAR::_precision<std::max(radius1,radius2))
167     {
168       obviousNoIntersection=true;
169       areOverlapped=false;
170       return ;
171     }
172   if(areArcsOverlapped(getE1(),getE2()))//(Node::areDoubleEquals(_dist,0.) && Node::areDoubleEquals(radius1,radius2))
173     {
174       obviousNoIntersection=false;
175       areOverlapped=true;
176     }
177   else
178     {
179       obviousNoIntersection=false;
180       areOverlapped=false;
181     }
182 }
183
184 std::list< IntersectElement > ArcCArcCIntersector::getIntersectionsCharacteristicVal() const
185 {
186   std::list< IntersectElement > ret;
187   const double *center1=getE1().getCenter();
188   const double *center2=getE2().getCenter();
189   double radius1=getE1().getRadius(); double radius2=getE2().getRadius();
190   double d1_1=(_dist*_dist-radius2*radius2+radius1*radius1)/(2.*_dist);
191   double u[2];//u is normalized vector from center1 to center2.
192   u[0]=(center2[0]-center1[0])/_dist; u[1]=(center2[1]-center1[1])/_dist;
193   double d1_1y=EdgeArcCircle::SafeSqrt(radius1*radius1-d1_1*d1_1);
194   double angleE1=EdgeArcCircle::NormalizeAngle(getE1().getAngle0()+getE1().getAngle());
195   double angleE2=EdgeArcCircle::NormalizeAngle(getE2().getAngle0()+getE2().getAngle());
196   if(!Node::areDoubleEquals(d1_1y,0))
197     {
198       //2 intersections
199       double v1[2],v2[2];
200       v1[0]=u[0]*d1_1-u[1]*d1_1y; v1[1]=u[1]*d1_1+u[0]*d1_1y;
201       v2[0]=u[0]*d1_1+u[1]*d1_1y; v2[1]=u[1]*d1_1-u[0]*d1_1y;
202       Node *node1=new Node(center1[0]+v1[0],center1[1]+v1[1]); node1->declareOn();
203       Node *node2=new Node(center1[0]+v2[0],center1[1]+v2[1]); node2->declareOn();
204       double angle1_1=EdgeArcCircle::GetAbsoluteAngleOfNormalizedVect(v1[0]/radius1,v1[1]/radius1);
205       double angle2_1=EdgeArcCircle::GetAbsoluteAngleOfNormalizedVect(v2[0]/radius1,v2[1]/radius1);
206       double v3[2],v4[2];
207       v3[0]=center1[0]-center2[0]+v1[0]; v3[1]=center1[1]-center2[1]+v1[1];
208       v4[0]=center1[0]-center2[0]+v2[0]; v4[1]=center1[1]-center2[1]+v2[1];
209       double angle1_2=EdgeArcCircle::GetAbsoluteAngleOfNormalizedVect(v3[0]/radius2,v3[1]/radius2);
210       double angle2_2=EdgeArcCircle::GetAbsoluteAngleOfNormalizedVect(v4[0]/radius2,v4[1]/radius2);
211       //
212       bool e1_1S=Node::areDoubleEqualsWP(angle1_1,getE1().getAngle0(),radius1);
213       bool e1_1E=Node::areDoubleEqualsWP(angle1_1,angleE1,radius1);
214       bool e1_2S=Node::areDoubleEqualsWP(angle1_2,getE2().getAngle0(),radius1);
215       bool e1_2E=Node::areDoubleEqualsWP(angle1_2,angleE2,radius1);
216       //
217       bool e2_1S=Node::areDoubleEqualsWP(angle2_1,getE1().getAngle0(),radius2);
218       bool e2_1E=Node::areDoubleEqualsWP(angle2_1,angleE1,radius2);
219       bool e2_2S=Node::areDoubleEqualsWP(angle2_2,getE2().getAngle0(),radius2);
220       bool e2_2E=Node::areDoubleEqualsWP(angle2_2,angleE2,radius2);
221       ret.push_back(IntersectElement(angle1_1,angle1_2,e1_1S,e1_1E,e1_2S,e1_2E,node1,_e1,_e2,keepOrder()));
222       ret.push_back(IntersectElement(angle2_1,angle2_2,e2_1S,e2_1E,e2_2S,e2_2E,node2,_e1,_e2,keepOrder()));
223     }
224   else
225     {
226       //tangent intersection
227       double v1[2],v2[2];
228       v1[0]=d1_1*u[0]; v1[1]=d1_1*u[1];
229       v2[0]=center1[0]-center2[0]+v1[0]; v2[1]=center1[1]-center2[1]+v1[1];
230       double angle0_1=EdgeArcCircle::GetAbsoluteAngleOfNormalizedVect(v1[0]/radius1,v1[1]/radius1);
231       double angle0_2=EdgeArcCircle::GetAbsoluteAngleOfNormalizedVect(v2[0]/radius2,v2[1]/radius2);
232       bool e0_1S=Node::areDoubleEqualsWP(angle0_1,getE1().getAngle0(),radius1);
233       bool e0_1E=Node::areDoubleEqualsWP(angle0_1,angleE1,radius1);
234       bool e0_2S=Node::areDoubleEqualsWP(angle0_2,getE2().getAngle0(),radius2);
235       bool e0_2E=Node::areDoubleEqualsWP(angle0_2,angleE2,radius2);
236       Node *node=new Node(center1[0]+d1_1*u[0],center1[1]+d1_1*u[1]); node->declareOnTangent();
237       ret.push_back(IntersectElement(angle0_1,angle0_2,e0_1S,e0_1E,e0_2S,e0_2E,node,_e1,_e2,keepOrder()));
238     }
239   return ret;
240 }
241 /*double angle0_2;
242   double signDeltaAngle2;
243   double d1_2;
244   if(u[1]<0.)
245   angle0_1=-angle0_1;
246   if(d1_1>=0.)
247   {
248   if(_dist>radius1)
249   {
250   angle0_2=angle0_1+M_PI;
251   signDeltaAngle2=-1.;
252   }
253   else
254   {
255   angle0_2=angle0_1;
256   signDeltaAngle2=1.;
257   }
258   }
259   else
260   {
261   angle0_1+=M_PI;
262   angle0_2=angle0_1;
263   signDeltaAngle2=1.;
264   }
265   angle0_1=NormalizeAngle(angle0_1);
266   angle0_2=NormalizeAngle(angle0_2);
267   double angleE1=NormalizeAngle(getE1().getAngle0()+getE1().getAngle());
268   double angleE2=NormalizeAngle(getE2().getAngle0()+getE2().getAngle());
269   if(!(Node::areDoubleEquals(d1_1,radius1) || Node::areDoubleEquals(d1_1,-radius1)) )
270   {
271   //2 intersections   
272   double deltaAngle1=EdgeArcCircle::SafeAcos(fabs(d1_1)/radius1); //owns to 0;Pi/2 by construction
273   double deltaAngle2=EdgeArcCircle::SafeAcos(fabs(d1_2)/radius2); //owns to 0;Pi/2 by construction
274   double angle1_1=NormalizeAngle(angle0_1+deltaAngle1);// Intersection 1 seen for _e1
275   double angle2_1=NormalizeAngle(angle0_1-deltaAngle1);// Intersection 2 seen for _e1
276   double angle1_2=NormalizeAngle(angle0_2+signDeltaAngle2*deltaAngle2);// Intersection 1 seen for _e2
277   double angle2_2=NormalizeAngle(angle0_2-signDeltaAngle2*deltaAngle2);// Intersection 2 seen for _e2
278   //
279   bool e1_1S=Node::areDoubleEqualsWP(angle1_1,getE1().getAngle0(),radius1);
280   bool e1_1E=Node::areDoubleEqualsWP(angle1_1,angleE1,radius1);
281   bool e1_2S=Node::areDoubleEqualsWP(angle1_2,getE2().getAngle0(),radius1);
282   bool e1_2E=Node::areDoubleEqualsWP(angle1_2,angleE2,radius1);
283   //
284   bool e2_1S=Node::areDoubleEqualsWP(angle2_1,getE1().getAngle0(),radius2);
285   bool e2_1E=Node::areDoubleEqualsWP(angle2_1,angleE1,radius2);
286   bool e2_2S=Node::areDoubleEqualsWP(angle2_2,getE2().getAngle0(),radius2);
287   bool e2_2E=Node::areDoubleEqualsWP(angle2_2,angleE2,radius2);
288   Node *node1=new Node(center1[0]+radius1*cos(angle1_1),center1[0]+radius1*sin(angle1_1)); node1->declareOn();
289   Node *node2=new Node(center1[0]+radius1*cos(angle2_1),center1[0]+radius1*sin(angle2_1)); node2->declareOn();
290   ret.push_back(IntersectElement(angle1_1,angle1_2,e1_1S,e1_1E,e1_2S,e1_2E,node1,_e1,_e2,keepOrder()));
291   ret.push_back(IntersectElement(angle2_1,angle2_2,e2_1S,e2_1E,e2_2S,e2_2E,node2,_e1,_e2,keepOrder()));
292   }
293   else
294   //tangent intersection
295   {
296   bool e0_1S=Node::areDoubleEqualsWP(angle0_1,getE1().getAngle0(),radius1);
297   bool e0_1E=Node::areDoubleEqualsWP(angle0_1,angleE1,radius1);
298   bool e0_2S=Node::areDoubleEqualsWP(angle0_2,getE2().getAngle0(),radius2);
299   bool e0_2E=Node::areDoubleEqualsWP(angle0_2,angleE2,radius2);
300   Node *node=new Node(center1[0]+radius1*cos(angle0_1),center1[0]+radius1*sin(angle0_1)); node->declareOnTangent();
301   ret.push_back(IntersectElement(angle0_1,angle0_2,e0_1S,e0_1E,e0_2S,e0_2E,node,_e1,_e2,keepOrder()));
302   }
303   return ret;*/
304
305 ArcCSegIntersector::ArcCSegIntersector(const EdgeArcCircle& e1, const EdgeLin& e2, bool reverse):CrossTypeEdgeIntersector(e1,e2,reverse)
306 {
307 }
308
309 void ArcCSegIntersector::areOverlappedOrOnlyColinears(const Bounds *whereToFind, bool& obviousNoIntersection, bool& areOverlapped)
310 {
311   areOverlapped=false;//No overlapping by contruction
312   const double *center=getE1().getCenter();
313   _dx=(*(_e2.getEndNode()))[0]-(*(_e2.getStartNode()))[0];
314   _dy=(*(_e2.getEndNode()))[1]-(*(_e2.getStartNode()))[1];
315   _drSq=_dx*_dx+_dy*_dy;
316   _cross=
317     ((*(_e2.getStartNode()))[0]-center[0])*((*(_e2.getEndNode()))[1]-center[1])-
318     ((*(_e2.getStartNode()))[1]-center[1])*((*(_e2.getEndNode()))[0]-center[0]);
319   _determinant=getE1().getRadius()*getE1().getRadius()/_drSq-_cross*_cross/(_drSq*_drSq);
320   if(_determinant>-2*QUADRATIC_PLANAR::_precision)//QUADRATIC_PLANAR::_precision*QUADRATIC_PLANAR::_precision*_drSq*_drSq/(2.*_dx*_dx))
321     obviousNoIntersection=false;
322   else
323     obviousNoIntersection=true;   
324 }
325
326 void ArcCSegIntersector::getPlacements(Node *start, Node *end, TypeOfLocInEdge& whereStart, TypeOfLocInEdge& whereEnd, MergePoints& commonNode) const
327 {
328   throw Exception("Internal error. Should never been called : no overlapping possible between arc of circle and a segment.");
329 }
330
331 std::list< IntersectElement > ArcCSegIntersector::getIntersectionsCharacteristicVal() const
332 {
333   std::list< IntersectElement > ret;
334   const double *center=getE1().getCenter();
335   if(!(fabs(_determinant)<(2.*QUADRATIC_PLANAR::_precision)))//QUADRATIC_PLANAR::_precision*QUADRATIC_PLANAR::_precision*_drSq*_drSq/(2.*_dx*_dx))
336     {
337       double determinant=EdgeArcCircle::SafeSqrt(_determinant);
338       double x1=(_cross*_dy/_drSq+Node::sign(_dy)*_dx*determinant)+center[0];
339       double y1=(-_cross*_dx/_drSq+fabs(_dy)*determinant)+center[1];
340       Node *intersect1=new Node(x1,y1); intersect1->declareOn();
341       bool i1_1S=_e1.getStartNode()->isEqual(*intersect1);
342       bool i1_1E=_e1.getEndNode()->isEqual(*intersect1);
343       bool i1_2S=_e2.getStartNode()->isEqual(*intersect1);
344       bool i1_2E=_e2.getEndNode()->isEqual(*intersect1);
345       ret.push_back(IntersectElement(getE1().getCharactValue(*intersect1),getE2().getCharactValue(*intersect1),i1_1S,i1_1E,i1_2S,i1_2E,intersect1,_e1,_e2,keepOrder()));
346       //
347       double x2=(_cross*_dy/_drSq-Node::sign(_dy)*_dx*determinant)+center[0];
348       double y2=(-_cross*_dx/_drSq-fabs(_dy)*determinant)+center[1];
349       Node *intersect2=new Node(x2,y2); intersect2->declareOn();
350       bool i2_1S=_e1.getStartNode()->isEqual(*intersect2);
351       bool i2_1E=_e1.getEndNode()->isEqual(*intersect2);
352       bool i2_2S=_e2.getStartNode()->isEqual(*intersect2);
353       bool i2_2E=_e2.getEndNode()->isEqual(*intersect2);
354       ret.push_back(IntersectElement(getE1().getCharactValue(*intersect2),getE2().getCharactValue(*intersect2),i2_1S,i2_1E,i2_2S,i2_2E,intersect2,_e1,_e2,keepOrder()));
355     }
356   else//tangent intersection
357     {
358       double x=(_cross*_dy)/_drSq+center[0];
359       double y=(-_cross*_dx)/_drSq+center[1];
360       Node *intersect3=new Node(x,y); intersect3->declareOnTangent();
361       bool i_1S=_e1.getStartNode()->isEqual(*intersect3);
362       bool i_1E=_e1.getEndNode()->isEqual(*intersect3);
363       bool i_2S=_e2.getStartNode()->isEqual(*intersect3);
364       bool i_2E=_e2.getEndNode()->isEqual(*intersect3);
365       ret.push_back(IntersectElement(_e1.getCharactValue(*intersect3),_e2.getCharactValue(*intersect3),i_1S,i_1E,i_2S,i_2E,intersect3,_e1,_e2,keepOrder()));
366     }
367   return ret;
368 }
369
370 EdgeArcCircle::EdgeArcCircle(std::istream& lineInXfig)
371 {
372   const unsigned NB_OF_SKIP_FIELDS=15;
373   std::string tmpS;
374   for(unsigned i=0;i<NB_OF_SKIP_FIELDS;i++)
375     lineInXfig >> tmpS;
376   _start=new Node(lineInXfig);
377   Node *middle=new Node(lineInXfig);
378   _end=new Node(lineInXfig);
379   GetArcOfCirclePassingThru(*_start,*middle,*_end,_center,_radius,_angle,_angle0);
380   middle->decrRef();
381   updateBounds();
382 }
383
384 EdgeArcCircle::EdgeArcCircle(Node *start, Node *middle, Node *end, bool direction):Edge(start,end, direction)
385 {
386   GetArcOfCirclePassingThru(*_start,*middle,*_end,_center,_radius,_angle,_angle0);
387   updateBounds();
388 }
389
390 EdgeArcCircle::EdgeArcCircle(double sX, double sY, double mX, double mY, double eX, double eY):Edge(sX,sY,eX,eY)
391 {
392   double middle[2]; middle[0]=mX; middle[1]=mY;
393   GetArcOfCirclePassingThru(*_start,middle,*_end,_center,_radius,_angle,_angle0);
394   updateBounds();
395 }
396
397 /*!
398  * @param angle0 in ]-Pi;Pi[
399  * @param deltaAngle in ]-2.*Pi;2.*Pi[
400  */
401 EdgeArcCircle::EdgeArcCircle(Node *start, Node *end, const double *center, double radius, double angle0, double deltaAngle, bool direction):Edge(start,end,direction),_angle(deltaAngle),
402                                                                                                                                             _angle0(angle0),_radius(radius)
403 {
404   _center[0]=center[0];
405   _center[1]=center[1];
406   updateBounds();
407 }
408
409 void EdgeArcCircle::changeMiddle(Node *newMiddle)
410 {
411   GetArcOfCirclePassingThru(*_start,*newMiddle,*_end,_center,_radius,_angle,_angle0);
412   updateBounds();
413 }
414
415 Edge *EdgeArcCircle::buildEdgeLyingOnMe(Node *start, Node *end, bool direction) const
416 {
417   double sx=((*start)[0]-_center[0])/_radius;
418   double sy=((*start)[1]-_center[1])/_radius;
419   double ex=((*end)[0]-_center[0])/_radius;
420   double ey=((*end)[1]-_center[1])/_radius;
421   double angle0=GetAbsoluteAngleOfNormalizedVect(direction?sx:ex,direction?sy:ey);
422   double deltaAngle=GetAbsoluteAngleOfNormalizedVect(sx*ex+sy*ey,sx*ey-sy*ex);
423   if(deltaAngle>0. && _angle<0.)
424     deltaAngle-=2.*M_PI;
425   else if(deltaAngle<0. && _angle>0.)
426     deltaAngle+=2.*M_PI;
427   deltaAngle=direction?deltaAngle:-deltaAngle;
428   return new EdgeArcCircle(start,end,_center,_radius,angle0,deltaAngle,direction);
429 }
430
431 void EdgeArcCircle::applySimilarity(double xBary, double yBary, double dimChar)
432 {
433   Edge::applySimilarity(xBary,yBary,dimChar);
434   _radius/=dimChar;
435   _center[0]=(_center[0]-xBary)/dimChar;
436   _center[1]=(_center[1]-yBary)/dimChar;
437 }
438
439 void EdgeArcCircle::unApplySimilarity(double xBary, double yBary, double dimChar)
440 {
441   Edge::unApplySimilarity(xBary,yBary,dimChar);
442   _radius*=dimChar;
443   _center[0]=_center[0]*dimChar+xBary;
444   _center[1]=_center[1]*dimChar+yBary;
445 }
446
447 /*!
448  * 'eps' is expected to be > 0.
449  * 'conn' is of size 3. conn[0] is start id, conn[1] is end id and conn[2] is middle id.
450  * 'offset' is typically the number of nodes already existing in global 2D curve mesh. Additionnal coords 'addCoo' ids will be put after the already existing.
451  */
452 void EdgeArcCircle::tesselate(const int *conn, int offset, double eps, std::vector<int>& newConn, std::vector<double>& addCoo) const
453 {
454   newConn.push_back(INTERP_KERNEL::NORM_POLYL);
455   int nbOfSubDiv=fabs(_angle)/eps;
456   if(nbOfSubDiv<=2)
457     {
458       newConn.push_back(conn[0]); newConn.push_back(conn[2]); newConn.push_back(conn[1]);
459       return ;
460     }
461   double signOfAngle=_angle>0.?1.:-1.;
462   int offset2=offset+((int)addCoo.size())/2;
463   newConn.push_back(conn[0]);
464   for(int i=1;i<nbOfSubDiv;i++,offset2++)
465     {
466       double angle=_angle0+i*eps*signOfAngle;
467       newConn.push_back(offset2);
468       addCoo.push_back(_center[0]+_radius*cos(angle)); addCoo.push_back(_center[1]+_radius*sin(angle));
469     }
470   newConn.push_back(conn[1]);
471 }
472
473 EdgeArcCircle *EdgeArcCircle::BuildFromNodes(Node *start, Node *middle, Node *end)
474 {
475   EdgeLin *e1,*e2;
476   e1=new EdgeLin(start,middle);
477   e2=new EdgeLin(middle,end);
478   SegSegIntersector inters(*e1,*e2);
479   bool colinearity=inters.areColinears();
480   delete e1; delete e2;
481   if(colinearity)
482     {
483       start->decrRef(); middle->decrRef(); end->decrRef();
484       return 0;
485     }
486   else
487     {
488       EdgeArcCircle *ret=new EdgeArcCircle(start,middle,end);
489       start->decrRef(); middle->decrRef(); end->decrRef();
490       return ret;
491     }
492 }
493
494 /*!
495  * Given an \b NON normalized vector 'vect', returns its norm 'normVect' and its
496  * angle in ]-Pi,Pi] relative to Ox axe.
497  */
498 double EdgeArcCircle::GetAbsoluteAngle(const double *vect, double& normVect)
499 {
500   normVect=Node::norm(vect);
501   return GetAbsoluteAngleOfNormalizedVect(vect[0]/normVect,vect[1]/normVect);
502 }
503
504 /*!
505  * Given a \b normalized vector defined by (ux,uy) returns its angle in ]-Pi;Pi].
506  * So before using this method ux*ux+uy*uy should as much as possible close to 1.
507  * This methods is quite time consuming in order to keep as much as possible precision.
508  * It is NOT ALWAYS possible to do that only in one call of acos. Sometimes call to asin is necessary
509  * due to imperfection of acos near 0. and Pi (cos x ~ 1-x*x/2.)
510  */
511 double EdgeArcCircle::GetAbsoluteAngleOfNormalizedVect(double ux, double uy)
512 {
513   //When arc is lower than 0.707 Using Asin 
514   if(fabs(ux)<0.707)
515     {
516       double ret=SafeAcos(ux);
517       if(uy>0.)
518         return ret;
519       ret=-ret;
520       return ret;
521     }
522   else
523     {
524       double ret=SafeAsin(uy);
525       if(ux>0.)
526         return ret;
527       if(ret>0.)
528         return M_PI-ret;
529       else
530         return -M_PI-ret;
531     }
532 }
533
534 void EdgeArcCircle::GetArcOfCirclePassingThru(const double *start, const double *middle, const double *end, 
535                                               double *center, double& radius, double& angleInRad, double& angleInRad0)
536 {
537   double delta=(middle[0]-start[0])*(end[1]-middle[1])-(end[0]-middle[0])*(middle[1]-start[1]);
538   double b1=(middle[1]*middle[1]+middle[0]*middle[0]-start[0]*start[0]-start[1]*start[1])/2;
539   double b2=(end[1]*end[1]+end[0]*end[0]-middle[0]*middle[0]-middle[1]*middle[1])/2;
540   center[0]=((end[1]-middle[1])*b1+(start[1]-middle[1])*b2)/delta;
541   center[1]=((middle[0]-end[0])*b1+(middle[0]-start[0])*b2)/delta;
542   radius=SafeSqrt((start[0]-center[0])*(start[0]-center[0])+(start[1]-center[1])*(start[1]-center[1]));
543   angleInRad0=GetAbsoluteAngleOfNormalizedVect((start[0]-center[0])/radius,(start[1]-center[1])/radius);
544   double angleInRadM=GetAbsoluteAngleOfNormalizedVect((middle[0]-center[0])/radius,(middle[1]-center[1])/radius);
545   angleInRad=GetAbsoluteAngleOfNormalizedVect(((start[0]-center[0])*(end[0]-center[0])+(start[1]-center[1])*(end[1]-center[1]))/(radius*radius),
546                                               ((start[0]-center[0])*(end[1]-center[1])-(start[1]-center[1])*(end[0]-center[0]))/(radius*radius));
547   if(IsAngleNotIn(angleInRad0,angleInRad,angleInRadM))
548     angleInRad=angleInRad<0?2*M_PI+angleInRad:angleInRad-2*M_PI;
549 }
550
551 void EdgeArcCircle::dumpInXfigFile(std::ostream& stream, bool direction, int resolution, const Bounds& box) const
552 {
553   stream << "5 1 0 1 ";
554   fillXfigStreamForLoc(stream);
555   stream << " 7 50 -1 -1 0.000 0 ";
556   if( (direction && (-_angle)>=0) || (!direction && (-_angle)<0))
557     stream << '0';//'0'
558   else
559     stream << '1';//'1'
560   stream << " 1 0 ";
561   stream << box.fitXForXFigD(_center[0],resolution) << " " << box.fitYForXFigD(_center[1],resolution) << " ";
562   direction?_start->dumpInXfigFile(stream,resolution,box):_end->dumpInXfigFile(stream,resolution,box);
563   Node *middle=buildRepresentantOfMySelf();
564   middle->dumpInXfigFile(stream,resolution,box);
565   middle->decrRef();
566   direction?_end->dumpInXfigFile(stream,resolution,box):_start->dumpInXfigFile(stream,resolution,box);
567   stream << std::endl << "1 1 2.00 120.00 180.00" << std::endl;
568 }
569
570 void EdgeArcCircle::update(Node *m)
571 {
572   GetArcOfCirclePassingThru(*_start,*m,*_end,_center,_radius,_angle,_angle0);
573   updateBounds();
574 }
575
576 /*!
577  * This methods computes :
578  * \f[
579  * \int_{Current Edge} -ydx
580  * \f]
581  */
582 double EdgeArcCircle::getAreaOfZone() const
583 {
584   return -_radius*_radius*(sin(_angle)-_angle)/2.+((*_start)[0]-(*_end)[0])*((*_start)[1]+(*_end)[1])/2.;
585 }
586
587 double EdgeArcCircle::getCurveLength() const
588 {
589   return fabs(_angle*_radius);
590 }
591
592 void EdgeArcCircle::getBarycenter(double *bary) const
593 {
594   bary[0]=_center[0]+_radius*cos(_angle0+_angle/2.);
595   bary[1]=_center[1]+_radius*sin(_angle0+_angle/2.);
596 }
597
598 /*!
599  * \f[
600  * bary[0]=\int_{Current Edge} -yxdx
601  * \f]
602  * \f[
603  * bary[1]=\int_{Current Edge} -\frac{y^{2}}{2}dx
604  * \f]
605  * To compute these 2 expressions in this class we have :
606  * \f[
607  * x=x_{0}+Radius \cdot cos(\theta)
608  * \f]
609  * \f[
610  * y=y_{0}+Radius \cdot sin(\theta)
611  * \f]
612  * \f[
613  * dx=-Radius \cdot sin(\theta) \cdot d\theta
614  * \f]
615  */
616 void EdgeArcCircle::getBarycenterOfZone(double *bary) const
617 {
618   double x0=_center[0];
619   double y0=_center[1];
620   double angle1=_angle0+_angle;
621   double tmp1=sin(angle1);
622   double tmp0=sin(_angle0);
623   double tmp2=_radius*_radius*_radius;
624   double tmp3=cos(angle1);
625   double tmp4=cos(_angle0);
626   bary[0]=_radius*x0*y0*(tmp4-tmp3)+_radius*_radius*(y0*(cos(2*_angle0)-cos(2*angle1))/4.+
627                                                      x0*(_angle/2.+(sin(2.*_angle0)-sin(2.*angle1))/4.))
628     +tmp2*(tmp1*tmp1*tmp1-tmp0*tmp0*tmp0)/3.;
629   bary[1]=y0*y0*_radius*(tmp4-tmp3)/2.+_radius*_radius*y0*(_angle/2.+(sin(2.*_angle0)-sin(2.*angle1))/4.)
630     +tmp2*(tmp4-tmp3+(tmp3*tmp3*tmp3-tmp4*tmp4*tmp4)/3.)/2.;
631 }
632
633 /*!
634  * Characteristic value used is angle in ]_Pi;Pi[ from axe 0x.
635  */
636 bool EdgeArcCircle::isIn(double characterVal) const
637 {
638   return IsIn2Pi(_angle0,_angle,characterVal);
639 }
640
641 Node *EdgeArcCircle::buildRepresentantOfMySelf() const
642 {
643   return new Node(_center[0]+_radius*cos(_angle0+_angle/2.),_center[1]+_radius*sin(_angle0+_angle/2.));
644 }
645
646 /*!
647  * Characteristic value used is angle in ]_Pi;Pi[ from axe 0x.
648  * 'val1' and 'val2' have been detected previously as owning to this.
649  */
650 bool EdgeArcCircle::isLower(double val1, double val2) const
651 {
652   double myDelta1=val1-_angle0;
653   double myDelta2=val2-_angle0;
654   if(_angle>0.)
655     {
656       myDelta1=myDelta1>-(_radius*QUADRATIC_PLANAR::_precision)?myDelta1:myDelta1+2.*M_PI;//in some cases val1 or val2 are so close to angle0 that myDelta is close to 0. but negative.
657       myDelta2=myDelta2>-(_radius*QUADRATIC_PLANAR::_precision)?myDelta2:myDelta2+2.*M_PI;
658       return myDelta1<myDelta2;
659     }
660   else
661     {
662       myDelta1=myDelta1<(_radius*QUADRATIC_PLANAR::_precision)?myDelta1:myDelta1-2.*M_PI;
663       myDelta2=myDelta2<(_radius*QUADRATIC_PLANAR::_precision)?myDelta2:myDelta2-2.*M_PI;
664       return myDelta2<myDelta1;
665     }
666 }
667
668 /*!
669  * For Arc circle the caract value is angle with Ox between -Pi and Pi.
670  */
671 double EdgeArcCircle::getCharactValue(const Node& node) const
672 {
673   double dx=(node[0]-_center[0])/_radius;
674   double dy=(node[1]-_center[1])/_radius;
675   return GetAbsoluteAngleOfNormalizedVect(dx,dy);
676 }
677
678 double EdgeArcCircle::getCharactValueBtw0And1(const Node& node) const
679 {
680   double dx=(node[0]-_center[0])/_radius;
681   double dy=(node[1]-_center[1])/_radius;
682   double angle=GetAbsoluteAngleOfNormalizedVect(dx,dy);
683   //
684   double myDelta=angle-_angle0;
685   if(_angle>0.)
686     myDelta=myDelta>=0.?myDelta:myDelta+2.*M_PI;
687   else
688     myDelta=myDelta<=0.?myDelta:myDelta-2.*M_PI;
689   return myDelta/_angle;
690 }
691
692 double EdgeArcCircle::getDistanceToPoint(const double *pt) const
693 {
694   double angle=Node::computeAngle(_center,pt);
695   if(IsIn2Pi(_angle0,_angle,angle))
696     return fabs(Node::distanceBtw2Pt(_center,pt)-_radius);
697   else
698     {
699       double dist1=Node::distanceBtw2Pt(*_start,pt);
700       double dist2=Node::distanceBtw2Pt(*_end,pt);
701       return std::min(dist1,dist2);
702     }
703 }
704
705 bool EdgeArcCircle::isNodeLyingOn(const double *coordOfNode) const
706 {
707   double dist=Node::distanceBtw2Pt(_center,coordOfNode);
708   if(Node::areDoubleEquals(dist,_radius))
709     {
710       double angle=Node::computeAngle(_center,coordOfNode);
711       return IsIn2Pi(_angle0,_angle,angle);
712     }
713   else
714     return false;
715 }
716
717 /*!
718  * Idem IsAngleNotIn except that here 'start' in ]-Pi;Pi[ and delta in ]-2*Pi;2Pi[. 
719  * @param angleIn in ]-Pi;Pi[.
720  */
721 bool EdgeArcCircle::IsIn2Pi(double start, double delta, double angleIn)
722 {
723   double myDelta=angleIn-start;
724   if(delta>0.)
725     {
726       myDelta=myDelta>=0.?myDelta:myDelta+2.*M_PI;
727       return myDelta>0. && myDelta<delta;
728     }
729   else
730     {
731       myDelta=myDelta<=0.?myDelta:myDelta-2.*M_PI;
732       return myDelta<0. && myDelta>delta;
733     }
734 }
735
736 /*!
737  * Given the arc 'a' defined by 'start' angle and a 'delta' [-Pi;Pi] states for the angle 'angleIn' [-Pi;Pi] if it owns or not 'a'.
738  */
739 bool EdgeArcCircle::IsAngleNotIn(double start, double delta, double angleIn)
740 {
741   double tmp=start;
742   if(tmp<0.)
743     tmp+=2*M_PI;
744   double tmp2=angleIn;
745   if(tmp2<0.)
746     tmp2+=2*M_PI;
747   if(tmp+delta>=2.*M_PI)
748     return (tmp2<tmp) && (tmp2>tmp+delta-2*M_PI);
749   else if(tmp+delta>=0.)
750     return (tmp2<std::min(tmp,tmp+delta) || tmp2>std::max(tmp,tmp+delta));
751   else
752     return (tmp2>tmp) && (tmp2<(tmp+delta+2.*M_PI));
753 }
754
755 void EdgeArcCircle::updateBounds()
756 {
757   _bounds.setValues(std::min((*_start)[0],(*_end)[0]),std::max((*_start)[0],(*_end)[0]),std::min((*_start)[1],(*_end)[1]),std::max((*_start)[1],(*_end)[1]));
758   if(IsIn2Pi(_angle0,_angle,M_PI/2))
759     _bounds[3]=_center[1]+_radius;
760   if(IsIn2Pi(_angle0,_angle,-M_PI/2))
761     _bounds[2]=_center[1]-_radius;
762   if(IsIn2Pi(_angle0,_angle,0.))
763     _bounds[1]=_center[0]+_radius;
764   if(IsIn2Pi(_angle0,_angle,M_PI))
765     _bounds[0]=_center[0]-_radius;
766 }
767
768 void EdgeArcCircle::fillGlobalInfoAbs(bool direction, const std::map<INTERP_KERNEL::Node *,int>& mapThis, const std::map<INTERP_KERNEL::Node *,int>& mapOther, int offset1, int offset2, double fact, double baryX, double baryY,
769                                       std::vector<int>& edgesThis, std::vector<double>& addCoo, std::map<INTERP_KERNEL::Node *,int> mapAddCoo) const
770 {
771   int tmp[2];
772   _start->fillGlobalInfoAbs(mapThis,mapOther,offset1,offset2,fact,baryX,baryY,addCoo,mapAddCoo,tmp);
773   _end->fillGlobalInfoAbs(mapThis,mapOther,offset1,offset2,fact,baryX,baryY,addCoo,mapAddCoo,tmp+1);
774   if(direction)
775     {
776       edgesThis.push_back(tmp[0]);
777       edgesThis.push_back(tmp[1]);
778     }
779   else
780     {
781       edgesThis.push_back(tmp[1]);
782       edgesThis.push_back(tmp[0]);
783     }
784 }
785
786 void EdgeArcCircle::fillGlobalInfoAbs2(const std::map<INTERP_KERNEL::Node *,int>& mapThis, const std::map<INTERP_KERNEL::Node *,int>& mapOther, int offset1, int offset2, double fact, double baryX, double baryY,
787                                        std::vector<int>& edgesOther, std::vector<double>& addCoo, std::map<INTERP_KERNEL::Node *,int>& mapAddCoo) const
788 {
789   _start->fillGlobalInfoAbs2(mapThis,mapOther,offset1,offset2,fact,baryX,baryY,addCoo,mapAddCoo,edgesOther);
790   _end->fillGlobalInfoAbs2(mapThis,mapOther,offset1,offset2,fact,baryX,baryY,addCoo,mapAddCoo,edgesOther);
791 }