Salome HOME
Merge branch 'master' of https://git.salome-platform.org/git/modules/med
[tools/medcoupling.git] / src / INTERP_KERNEL / Geometric2D / InterpKernelGeo2DComposedEdge.cxx
1 // Copyright (C) 2007-2015  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 "InterpKernelGeo2DComposedEdge.hxx"
22 #include "InterpKernelGeo2DElementaryEdge.hxx"
23 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
24 #include "InterpKernelGeo2DEdgeInfLin.hxx"
25 #include "InterpKernelException.hxx"
26
27 #include <algorithm>
28 #include <memory>
29 #include <iterator>
30 #include <set>
31
32 using namespace INTERP_KERNEL;
33
34 ComposedEdge::ComposedEdge(const ComposedEdge& other)
35 {
36   for(std::list<ElementaryEdge *>::const_iterator iter=other._sub_edges.begin();iter!=other._sub_edges.end();iter++)
37     _sub_edges.push_back((*iter)->clone());
38 }
39
40 ComposedEdge::~ComposedEdge()
41 {
42   clearAll(_sub_edges.begin());
43 }
44
45 void ComposedEdge::setValueAt(int i, Edge *e, bool direction)
46 {
47   std::list<ElementaryEdge*>::iterator it=_sub_edges.begin();
48   for(int j=0;j<i;j++)
49     it++;
50   delete *it;
51   *it=new ElementaryEdge(e,direction);
52 }
53
54 struct AbsEdgeCmp
55 {
56   AbsEdgeCmp(ElementaryEdge *b):_b1(b) { }
57   bool operator()(ElementaryEdge *a) { return a->getPtr()==_b1->getPtr();}
58
59   ElementaryEdge *_b1;
60 };
61
62 double ComposedEdge::getCommonLengthWith(const ComposedEdge& other) const
63 {
64   double ret=0.;
65   for(std::list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
66     {
67       if(find_if(other._sub_edges.begin(),other._sub_edges.end(),AbsEdgeCmp(*iter))!=other._sub_edges.end())
68         {
69           const ElementaryEdge *tmp=static_cast<const ElementaryEdge *>(*iter);
70           ret+=tmp->getCurveLength();
71         }
72     }
73   return ret;
74 }
75
76 void ComposedEdge::clear()
77 {
78   clearAll(_sub_edges.begin());
79   _sub_edges.clear();
80 }
81
82 void ComposedEdge::pushBack(Edge *edge, bool direction)
83 {
84   _sub_edges.push_back(new ElementaryEdge(edge,direction));
85 }
86
87 void ComposedEdge::pushBack(ElementaryEdge *elem)
88 {
89   _sub_edges.push_back(elem);
90 }
91
92 void ComposedEdge::pushBack(ComposedEdge *elem)
93 {
94   std::list<ElementaryEdge *> *elemsOfElem=elem->getListBehind();
95   _sub_edges.insert(_sub_edges.end(),elemsOfElem->begin(),elemsOfElem->end());
96 }
97
98 ElementaryEdge *ComposedEdge::operator[](int i) const
99 {
100   std::list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();
101   for(int ii=0;ii<i;ii++)
102     iter++;
103   return *iter;
104 }
105
106 void ComposedEdge::reverse()
107 {
108   _sub_edges.reverse();
109   for(std::list<ElementaryEdge *>::iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
110     (*iter)->reverse();
111 }
112
113 bool ComposedEdge::presenceOfOn() const
114 {
115   bool ret=false;
116   for(std::list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end() && !ret;iter++)
117     ret=((*iter)->getLoc()==FULL_ON_1);
118   return ret;
119 }
120
121 bool ComposedEdge::presenceOfQuadraticEdge() const
122 {
123   bool ret=false;
124   for(std::list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end() && !ret;iter++)
125     {
126       Edge *e=(*iter)->getPtr();
127       if(e)
128         ret=dynamic_cast<EdgeArcCircle*>(e)!=0;
129     }
130   return ret;
131 }
132
133 void ComposedEdge::initLocations() const
134 {
135   for(std::list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
136     (*iter)->initLocations();
137 }
138
139 /**
140  * Reset the status of all edges (OUT, IN, ON) because they were potentially assigned
141  * by the previous candidate processing.
142  */
143 void ComposedEdge::InitLocationsWithOther(const ComposedEdge& first, const ComposedEdge& other)
144 {
145   std::set<Edge *> s1,s2;
146   for(std::list<ElementaryEdge *>::const_iterator it1=first._sub_edges.begin();it1!=first._sub_edges.end();it1++)
147     s1.insert((*it1)->getPtr());
148   for(std::list<ElementaryEdge *>::const_iterator it2=other._sub_edges.begin();it2!=other._sub_edges.end();it2++)
149     s2.insert((*it2)->getPtr());
150   first.initLocations();
151   other.initLocations();
152   std::vector<Edge *> s3;
153   std::set_intersection(s1.begin(),s1.end(),s2.begin(),s2.end(),std::back_insert_iterator< std::vector<Edge *> >(s3));
154   for(std::vector<Edge *>::const_iterator it3=s3.begin();it3!=s3.end();it3++)
155     (*it3)->declareOn();
156 }
157
158 ComposedEdge *ComposedEdge::clone() const
159 {
160   return new ComposedEdge(*this);
161 }
162
163 bool ComposedEdge::isNodeIn(Node *n) const
164 {
165   bool ret=false;
166   for(std::list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end() && !ret;iter++)
167     ret=(*iter)->isNodeIn(n);
168   return ret;
169 }
170
171 /*!
172  * This method computes the area of 'this'.
173  * By definition :
174  * \f[
175  * Area=\int_{Polygon} dS
176  * \f]
177  * Thanks to Green's theorem we have.
178  * \f[
179  * \int_{Polygon} x \cdot dS=\sum_{0 \leq i < nb of edges} -\int_{Edge_{i}}ydx=\sum_{0 \leq i < nb of edges} AreaOfZone_{Edge_{i}}
180  * \f]
181  * Where \f$ AreaOfZone_{i} \f$ is computed virtually by INTERP_KERNEL::Edge::getAreaOfZone with following formula :
182  * \f[
183  * AreaOfZone_{i}=\int_{Edge_{i}} -ydx
184  * \f]
185  */
186 double ComposedEdge::getArea() const
187 {
188   double ret=0.;
189   for(std::list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
190     ret+=(*iter)->getAreaOfZone();
191   return ret;
192 }
193
194 double ComposedEdge::getPerimeter() const
195 {
196   double ret=0.;
197   for(std::list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
198     ret+=(*iter)->getCurveLength();
199   return ret;
200 }
201
202 double ComposedEdge::getHydraulicDiameter() const
203 {
204   return 4*fabs(getArea())/getPerimeter();
205 }
206
207 /*!
208  * This method computes barycenter of 'this' by returning xG in bary[0] and yG in bary[1].
209  * By definition :
210  * \f[
211  * Area \cdot x_{G}=\int_{Polygon} x \cdot dS
212  * \f]
213  * \f[
214  * Area \cdot y_{G}=\int_{Polygon} y \cdot dS
215  * \f]
216  * Thanks to Green's theorem we have.
217  * \f[
218  * \int_{Polygon} x \cdot dS=\sum_{0 \leq i < nb of edges} -\int_{Edge_{i}}yxdx
219  * \f]
220  * \f[
221  * \int_{Polygon} y \cdot dS=\sum_{0 \leq i < nb of edges} -\int_{Edge_{i}}\frac{y^{2}}{2}dx
222  * \f]
223  * Area is computed using the same principle than described in INTERP_KERNEL::ComposedEdge::getArea method.
224  * \f$ -\int_{Edge_{i}}yxdx \f$ and \f$ -\int_{Edge_{i}}\frac{y^{2}}{2}dx \f$ are computed virtually with INTERP_KERNEL::Edge::getBarycenterOfZone.
225  */
226 void ComposedEdge::getBarycenter(double *bary) const
227 {
228   bary[0]=0.;
229   bary[1]=0.;
230   double area=0.;
231   for(std::list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
232     {
233       (*iter)->getBarycenterOfZone(bary);
234       area+=(*iter)->getAreaOfZone();
235     }
236   bary[0]/=area;
237   bary[1]/=area;
238 }
239
240 /*!
241  * Idem ComposedEdge::getBarycenter except that the special case where _sub_edges==1 is dealt here.
242  */
243 void ComposedEdge::getBarycenterGeneral(double *bary) const
244 {
245   if(_sub_edges.empty())
246     throw INTERP_KERNEL::Exception("ComposedEdge::getBarycenterGeneral called on an empty polygon !");
247   if(_sub_edges.size()>2)
248     return getBarycenter(bary);
249   double w;
250   _sub_edges.back()->getBarycenter(bary,w);
251 }
252
253 double ComposedEdge::normalizeMe(double& xBary, double& yBary)
254 {
255   Bounds b;
256   b.prepareForAggregation();
257   fillBounds(b);
258   double dimChar=b.getCaracteristicDim();
259   b.getBarycenter(xBary,yBary);
260   applyGlobalSimilarity(xBary,yBary,dimChar);
261   return dimChar;
262 }
263
264 double ComposedEdge::normalize(ComposedEdge *other, double& xBary, double& yBary)
265 {
266   Bounds b;
267   b.prepareForAggregation();
268   fillBounds(b); 
269   other->fillBounds(b);
270   double dimChar=b.getCaracteristicDim();
271   b.getBarycenter(xBary,yBary);
272   applyGlobalSimilarity(xBary,yBary,dimChar);
273   other->applyGlobalSimilarity(xBary,yBary,dimChar);
274   return dimChar;
275 }
276
277 /*!
278  * This method operates the opposite operation than ComposedEdge::applyGlobalSimilarity.
279  */
280 void ComposedEdge::unApplyGlobalSimilarityExt(ComposedEdge& other, double xBary, double yBary, double fact)
281 {
282   initNodeHitStatus();
283   other.initNodeHitStatus();
284   unApplySimilarityOnMyNodes(xBary,yBary,fact);
285   other.unApplySimilarityOnMyNodesIfNotAlreadyHit(xBary,yBary,fact);
286   initEdgeHitStatus();
287   other.initEdgeHitStatus();
288   unApplySimilarityOnMyEdges(xBary,yBary,fact);
289   other.unApplySimilarityOnMyEdgesIfNotAlreadyHit(xBary,yBary,fact);
290 }
291
292 double ComposedEdge::normalizeExt(ComposedEdge *other, double& xBary, double& yBary)
293 {
294   Bounds b;
295   b.prepareForAggregation();
296   fillBounds(b); 
297   other->fillBounds(b);
298   double dimChar=b.getCaracteristicDim();
299   b.getBarycenter(xBary,yBary);
300   applyGlobalSimilarity2(other,xBary,yBary,dimChar);
301   return dimChar;
302 }
303
304 void ComposedEdge::dumpInXfigFile(std::ostream& stream, int resolution, const Bounds& box) const
305 {
306   stream.precision(10);
307   for(std::list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
308     (*iter)->dumpInXfigFile(stream,resolution,box);
309 }
310
311 Node *ComposedEdge::getEndNode() const
312 {
313   return _sub_edges.back()->getEndNode();
314 }
315
316 Node *ComposedEdge::getStartNode() const
317 {
318   return _sub_edges.front()->getStartNode();
319 }
320
321 bool ComposedEdge::changeEndNodeWith(Node *node) const
322 {
323   return _sub_edges.back()->changeEndNodeWith(node);
324 }
325
326 bool ComposedEdge::changeStartNodeWith(Node *node) const
327 {
328   return _sub_edges.front()->changeStartNodeWith(node);
329 }
330
331 void ComposedEdge::fillBounds(Bounds& output) const
332 {
333   for(std::list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
334     (*iter)->fillBounds(output);
335 }
336
337 /*!
338  * \b WARNING : applies similarity \b ONLY on edges without any change on Nodes. To perform a global similarity call applyGlobalSimilarity.
339  */
340 void ComposedEdge::applySimilarity(double xBary, double yBary, double dimChar)
341 {
342   for(std::list<ElementaryEdge *>::iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
343     (*iter)->applySimilarity(xBary,yBary,dimChar);
344 }
345
346 /*!
347  * Perform Similarity transformation on all elements of this Nodes and Edges.
348  */
349 void ComposedEdge::applyGlobalSimilarity(double xBary, double yBary, double dimChar)
350 {
351   std::set<Node *> allNodes;
352   getAllNodes(allNodes);
353   for(std::set<Node *>::iterator iter=allNodes.begin();iter!=allNodes.end();iter++)
354     (*iter)->applySimilarity(xBary,yBary,dimChar);
355   for(std::list<ElementaryEdge *>::iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
356     (*iter)->applySimilarity(xBary,yBary,dimChar);
357 }
358
359 /*!
360  * Perform Similarity transformation on all elements of this Nodes and Edges on 'this' and 'other'.
361  * Nodes can be shared between 'this' and 'other'.
362  */
363 void ComposedEdge::applyGlobalSimilarity2(ComposedEdge *other, double xBary, double yBary, double dimChar)
364 {
365   initNodeHitStatus();
366   other->initNodeHitStatus();
367   applySimilarityOnMyNodes(xBary,yBary,dimChar);
368   other->applySimilarityOnMyNodesIfNotAlreadyHit(xBary,yBary,dimChar);
369   initEdgeHitStatus();
370   other->initEdgeHitStatus();
371   applySimilarityOnMyEdges(xBary,yBary,dimChar);
372   other->applySimilarityOnMyEdgesIfNotAlreadyHit(xBary,yBary,dimChar);
373 }
374
375 /*!
376  * This method append to param 'partConsidered' the part of length of subedges IN or ON.
377  * @param partConsidered INOUT param.
378  */
379 void ComposedEdge::dispatchPerimeter(double& partConsidered) const
380 {
381   for(std::list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
382     {
383       TypeOfEdgeLocInPolygon loc=(*iter)->getLoc();
384       if(loc==FULL_IN_1 || loc==FULL_ON_1)
385         partConsidered+=(*iter)->getCurveLength();
386     }
387 }
388
389 /*!
390  * Idem dispatchPerimeterExcl except that when a subedge is declared as ON this subedge is counted in commonPart.
391  */
392 void ComposedEdge::dispatchPerimeterExcl(double& partConsidered, double& commonPart) const
393 {
394   for(std::list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
395     {
396       TypeOfEdgeLocInPolygon loc=(*iter)->getLoc();
397       if(loc==FULL_IN_1)
398         partConsidered+=(*iter)->getCurveLength();
399       if(loc==FULL_ON_1)
400         commonPart+=(*iter)->getCurveLength();
401     }
402 }
403
404 void ComposedEdge::getAllNodes(std::set<Node *>& output) const
405 {
406   std::list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();
407   for(;iter!=_sub_edges.end();iter++)
408     (*iter)->getAllNodes(output);
409 }
410
411 void ComposedEdge::initNodeHitStatus() const
412 {
413   for(std::list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
414     {
415       (*iter)->getStartNode()->initHitStatus();
416       (*iter)->getEndNode()->initHitStatus();
417     }
418 }
419
420 void ComposedEdge::applySimilarityOnMyNodes(double xBary, double yBary, double dimChar) const
421 {
422   for(std::list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
423     {
424       (*iter)->getStartNode()->hitMeAlone(xBary,yBary,dimChar);
425       (*iter)->getEndNode()->hitMeAlone(xBary,yBary,dimChar);
426     }
427 }
428
429 void ComposedEdge::unApplySimilarityOnMyNodes(double xBary, double yBary, double dimChar) const
430 {
431   for(std::list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
432     {
433       (*iter)->getStartNode()->unHitMeAlone(xBary,yBary,dimChar);
434       (*iter)->getEndNode()->unHitMeAlone(xBary,yBary,dimChar);
435     }
436 }
437
438 void ComposedEdge::applySimilarityOnMyNodesIfNotAlreadyHit(double xBary, double yBary, double dimChar) const
439 {
440   for(std::list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
441     {
442       (*iter)->getStartNode()->hitMeAfter(xBary,yBary,dimChar);
443       (*iter)->getEndNode()->hitMeAfter(xBary,yBary,dimChar);
444     }
445 }
446
447 void ComposedEdge::unApplySimilarityOnMyNodesIfNotAlreadyHit(double xBary, double yBary, double dimChar) const
448 {
449   for(std::list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
450     {
451       (*iter)->getStartNode()->unHitMeAfter(xBary,yBary,dimChar);
452       (*iter)->getEndNode()->unHitMeAfter(xBary,yBary,dimChar);
453     }
454 }
455
456 void ComposedEdge::initEdgeHitStatus() const
457 {
458   for(std::list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
459     (*iter)->getPtr()->initHitStatus();
460 }
461
462 void ComposedEdge::applySimilarityOnMyEdges(double xBary, double yBary, double dimChar) const
463 {
464   for(std::list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
465     (*iter)->getPtr()->hitMeAlone(xBary,yBary,dimChar);
466 }
467
468 void ComposedEdge::unApplySimilarityOnMyEdges(double xBary, double yBary, double dimChar) const
469 {
470   for(std::list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
471     (*iter)->getPtr()->unHitMeAlone(xBary,yBary,dimChar);
472 }
473
474 void ComposedEdge::applySimilarityOnMyEdgesIfNotAlreadyHit(double xBary, double yBary, double dimChar) const
475 {
476   for(std::list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
477     (*iter)->getPtr()->hitMeAfter(xBary,yBary,dimChar);
478 }
479
480 void ComposedEdge::unApplySimilarityOnMyEdgesIfNotAlreadyHit(double xBary, double yBary, double dimChar) const
481 {
482   for(std::list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
483     (*iter)->getPtr()->unHitMeAfter(xBary,yBary,dimChar);
484 }
485
486 void ComposedEdge::getBarycenter(double *bary, double& weigh) const
487 {
488   weigh=0.; bary[0]=0.; bary[1]=0.;
489   double tmp1,tmp2[2];
490   for(std::list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
491     {
492       (*iter)->getBarycenter(tmp2,tmp1);
493       weigh+=tmp1;
494       bary[0]+=tmp1*tmp2[0];
495       bary[1]+=tmp1*tmp2[1];
496     }
497   bary[0]/=weigh;
498   bary[1]/=weigh;
499 }
500
501 /*!
502  * This method makes the hypothesis that \a nodeToTest can be either IN or OUT.
503  * 
504  * \sa ComposedEdge::isInOrOut2
505  */
506 bool ComposedEdge::isInOrOut(Node *nodeToTest) const
507 {
508   Bounds b; b.prepareForAggregation();
509   fillBounds(b);
510   if(b.nearlyWhere((*nodeToTest)[0],(*nodeToTest)[1])==OUT)
511     return false;
512   std::set< IntersectElement > inOutSwitch;
513   double ref(isInOrOutAlg(nodeToTest,inOutSwitch));
514   bool ret(false);
515   for(std::set< IntersectElement >::iterator iter4=inOutSwitch.begin();iter4!=inOutSwitch.end();iter4++)
516     {
517       if((*iter4).getVal1()<ref)
518         {
519           if((*iter4).getNodeOnly()->getLoc()==ON_1)
520             ret=!ret;
521         }
522       else
523         break;
524     }
525   return ret;
526 }
527
528 /*!
529  * This method is close to ComposedEdge::isInOrOut behaviour except that here EPSILON is taken into account to detect if it is IN or OUT.
530  * If \a nodeToTest is close to an edge in \a this, true will be returned even if it is outside informatically from \a this.
531  *
532  * \sa ComposedEdge::isInOrOut
533  */
534 bool ComposedEdge::isInOrOut2(Node *nodeToTest) const
535 {
536   std::set< IntersectElement > inOutSwitch;
537   double ref(isInOrOutAlg(nodeToTest,inOutSwitch));
538   bool ret(false);
539   for(std::set< IntersectElement >::iterator iter4=inOutSwitch.begin();iter4!=inOutSwitch.end();iter4++)
540     {
541       double val((*iter4).getVal1());
542       if(fabs(val-ref)>=QUADRATIC_PLANAR::_precision)
543         {
544           if(val<ref)
545             {
546               if((*iter4).getNodeOnly()->getLoc()==ON_1)
547                 ret=!ret;
548             }
549           else
550             break;
551         }
552       else
553         return true;
554     }
555   return ret;
556 }
557
558 double ComposedEdge::isInOrOutAlg(Node *nodeToTest, std::set< IntersectElement >& inOutSwitch) const
559 {
560   // searching for e1
561   std::set<Node *> nodes;
562   getAllNodes(nodes);
563   std::set<double> radialDistributionOfNodes;
564   std::set<Node *>::const_iterator iter;
565   for(iter=nodes.begin();iter!=nodes.end();iter++)
566     radialDistributionOfNodes.insert(nodeToTest->getSlope(*(*iter)));
567   std::vector<double> radialDistrib(radialDistributionOfNodes.begin(),radialDistributionOfNodes.end());
568   radialDistributionOfNodes.clear();
569   std::vector<double> radialDistrib2(radialDistrib.size());
570   copy(radialDistrib.begin()+1,radialDistrib.end(),radialDistrib2.begin());
571   radialDistrib2.back()=M_PI+radialDistrib.front();
572   std::vector<double> radialDistrib3(radialDistrib.size());
573   std::transform(radialDistrib2.begin(),radialDistrib2.end(),radialDistrib.begin(),radialDistrib3.begin(),std::minus<double>());
574   std::vector<double>::iterator iter3=max_element(radialDistrib3.begin(),radialDistrib3.end());
575   int i=iter3-radialDistrib3.begin();
576   // ok for e1 - Let's go.
577   EdgeInfLin *e1=new EdgeInfLin(nodeToTest,radialDistrib[i]+radialDistrib3[i]/2.);
578   double ref=e1->getCharactValue(*nodeToTest);
579   for(std::list<ElementaryEdge *>::const_iterator iter4=_sub_edges.begin();iter4!=_sub_edges.end();iter4++)
580     {
581       ElementaryEdge *val=(*iter4);
582       if(val)
583         {
584           Edge *e=val->getPtr();
585           std::auto_ptr<EdgeIntersector> intersc(Edge::BuildIntersectorWith(e1,e));
586           bool obviousNoIntersection,areOverlapped;
587           intersc->areOverlappedOrOnlyColinears(0,obviousNoIntersection,areOverlapped);  // first parameter never used
588           if(obviousNoIntersection)
589             {
590               continue;
591             }
592           if(!areOverlapped)
593             {
594               std::list< IntersectElement > listOfIntesc=intersc->getIntersectionsCharacteristicVal();
595               for(std::list< IntersectElement >::iterator iter2=listOfIntesc.begin();iter2!=listOfIntesc.end();iter2++)
596                 if((*iter2).isIncludedByBoth())
597                   inOutSwitch.insert(*iter2);
598             }
599           //if overlapped we can forget
600         }
601       else
602         throw Exception("Invalid use of ComposedEdge::isInOrOutAlg : only one level supported !");
603     }
604   e1->decrRef();
605   return ref;
606 }
607
608 /*bool ComposedEdge::isInOrOut(Node *aNodeOn, Node *nodeToTest) const
609 {
610
611   EdgeInfLin *e1=new EdgeInfLin(aNodeOn,nodeToTest);
612   double ref=e1->getCharactValue(*nodeToTest);
613   set< IntersectElement > inOutSwitch;
614   for(vector<AbstractEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
615     {
616       ElementaryEdge *val=dynamic_cast<ElementaryEdge *>(*iter);
617       if(val)
618         {
619           Edge *e=val->getPtr();
620           auto_ptr<Intersector> intersc(Edge::buildIntersectorWith(e1,e));
621           bool obviousNoIntersection,areOverlapped;
622           intersc->areOverlappedOrOnlyColinears(0,obviousNoIntersection,areOverlapped);
623           if(obviousNoIntersection)
624             {
625               continue;
626             }
627           if(!areOverlapped)
628             {
629               list< IntersectElement > listOfIntesc=intersc->getIntersectionsCharacteristicVal();
630               for(list< IntersectElement >::iterator iter2=listOfIntesc.begin();iter2!=listOfIntesc.end();iter2++)
631                 if((*iter2).isIncludedByBoth())
632                   inOutSwitch.insert(*iter2);
633               }
634           //if overlapped we can forget
635         }
636       else
637         throw Exception("Invalid use of ComposedEdge::isInOrOut : only one level supported !");
638     }
639   e1->decrRef();
640   bool ret=false;
641   for(set< IntersectElement >::iterator iter=inOutSwitch.begin();iter!=inOutSwitch.end();iter++)
642     {
643       if((*iter).getVal1()<ref)
644         {
645           if((*iter).getNodeOnly()->getLoc()==ON_1)
646             ret=!ret;
647         }
648       else
649         break;
650     }
651   return ret;
652 }*/
653
654 bool ComposedEdge::getDirection() const
655 {
656   throw Exception("ComposedEdge::getDirection : no sense");
657 }
658
659 bool ComposedEdge::intresincEqCoarse(const Edge *other) const
660 {
661   if(_sub_edges.size()!=1)
662     return false;
663   return _sub_edges.front()->intresincEqCoarse(other);
664 }
665
666 void ComposedEdge::clearAll(std::list<ElementaryEdge *>::iterator startToDel)
667 {
668   for(std::list<ElementaryEdge *>::iterator iter=startToDel;iter!=_sub_edges.end();iter++)
669     delete (*iter);
670 }