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