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