Salome HOME
Merge from V6_main_20120808 08Aug12
[tools/medcoupling.git] / src / INTERP_KERNEL / Geometric2D / InterpKernelGeo2DEdge.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
20 #include "InterpKernelGeo2DEdge.hxx"
21 #include "InterpKernelGeo2DEdgeLin.hxx"
22 #include "InterpKernelGeo2DEdgeInfLin.hxx"
23 //#include "EdgeParabol.hxx"
24 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
25 #include "InterpKernelException.hxx"
26
27 #include <algorithm>
28
29 using namespace INTERP_KERNEL;
30
31 MergePoints::MergePoints():_ass1Start1(0),_ass1End1(0),_ass1Start2(0),_ass1End2(0),
32                            _ass2Start1(0),_ass2End1(0),_ass2Start2(0),_ass2End2(0)
33 {
34 }
35
36 void MergePoints::start1Replaced()
37 {
38   unsigned nbOfAsso=getNumberOfAssociations();
39   if(nbOfAsso==0)
40     _ass1Start1=1;
41   else
42     _ass2Start1=1;
43 }
44
45 void MergePoints::end1Replaced()
46 {
47   unsigned nbOfAsso=getNumberOfAssociations();
48   if(nbOfAsso==0)
49     _ass1End1=1;
50   else
51     _ass2End1=1;
52 }
53
54 void MergePoints::start1OnStart2()
55 {
56   unsigned nbOfAsso=getNumberOfAssociations();
57   if(nbOfAsso==0)
58     {
59       _ass1Start1=1;
60       _ass1Start2=1;
61     }
62   else
63     {
64       _ass2Start1=1;
65       _ass2Start2=1;
66     }
67 }
68
69 void MergePoints::start1OnEnd2()
70 {
71   unsigned nbOfAsso=getNumberOfAssociations();
72   if(nbOfAsso==0)
73     {
74       _ass1Start1=1;
75       _ass1End2=1;
76     }
77   else
78     {
79       _ass2Start1=1;
80       _ass2End2=1;
81     }
82 }
83
84 void MergePoints::end1OnStart2()
85 {
86   unsigned nbOfAsso=getNumberOfAssociations();
87   if(nbOfAsso==0)
88     {
89       _ass1End1=1;
90       _ass1Start2=1;
91     }
92   else
93     {
94       _ass2End1=1;
95       _ass2Start2=1;
96     }
97 }
98
99 void MergePoints::end1OnEnd2()
100 {
101   unsigned nbOfAsso=getNumberOfAssociations();
102   if(nbOfAsso==0)
103     {
104       _ass1End1=1;
105       _ass1End2=1;
106     }
107   else
108     {
109       _ass2End1=1;
110       _ass2End2=1;
111     }
112 }
113
114 bool MergePoints::isStart1(unsigned rk) const
115 {
116   if(rk==0)
117     return _ass1Start1;
118   else
119     return _ass2Start1;
120 }
121
122 bool MergePoints::isEnd1(unsigned rk) const
123 {
124   if(rk==0)
125     return _ass1End1;
126   else
127     return _ass2End1;
128 }
129
130 bool MergePoints::isStart2(unsigned rk) const
131 {
132   if(rk==0)
133     return _ass1Start2;
134   else
135     return _ass2Start2;
136 }
137
138 bool MergePoints::isEnd2(unsigned rk) const
139 {
140   if(rk==0)
141     return _ass1End2;
142   else
143     return _ass2End2;
144 }
145
146 void MergePoints::clear()
147 {
148   _ass1Start1=0;_ass1End1=0;_ass1Start2=0;_ass1End2=0;
149   _ass2Start1=0;_ass2End1=0;_ass2Start2=0;_ass2End2=0;
150 }
151
152 unsigned MergePoints::getNumberOfAssociations() const
153 {
154   unsigned ret=0;
155   unsigned subTot=_ass1Start1+_ass1End1+_ass1Start2+_ass1End2;
156   if(subTot!=0)
157     ret++;
158   subTot=_ass2Start1+_ass2End1+_ass2Start2+_ass2End2;
159   if(subTot!=0)
160     ret++;
161   return ret;
162 }
163
164 IntersectElement::IntersectElement(double val1, double val2, bool start1, bool end1, bool start2, bool end2, Node *node
165                                    , const Edge& e1, const Edge& e2, bool keepOrder):_1S(keepOrder?start1:start2),
166                                                                                      _1E(keepOrder?end1:end2),
167                                                                                      _2S(keepOrder?start2:start1),
168                                                                                      _2E(keepOrder?end2:end1),
169                                                                                      _chararct_val_for_e1(keepOrder?val1:val2),
170                                                                                      _chararct_val_for_e2(keepOrder?val2:val1),
171                                                                                      _node(node),_loc_of_node(node->getLoc()),_e1(keepOrder?e1:e2),
172                                                                                      _e2(keepOrder?e2:e1)
173 {
174 }
175
176 IntersectElement::IntersectElement(const IntersectElement& other):_1S(other._1S),_1E(other._1E),_2S(other._2S),_2E(other._2E),
177                                                                   _chararct_val_for_e1(other._chararct_val_for_e1),
178                                                                   _chararct_val_for_e2(other._chararct_val_for_e2),_node(other._node),
179                                                                   _loc_of_node(other._loc_of_node),_e1(other._e1), _e2(other._e2)
180 {
181   if(_node)
182     _node->incrRef();
183 }
184
185 IntersectElement& IntersectElement::operator=(const IntersectElement& other)
186 {
187   _1S=other._1S;_1E=other._1E; _2S=other._2S; _2E=other._2E;
188   _chararct_val_for_e1=other._chararct_val_for_e1;
189   _chararct_val_for_e2=other._chararct_val_for_e2;
190   setNode(other._node);
191   return *this;
192 }
193
194 bool IntersectElement::operator<(const IntersectElement& other) const
195 {
196   return _e1.isLower(_chararct_val_for_e1,other._chararct_val_for_e1);
197 }
198
199 IntersectElement::~IntersectElement()
200 {
201   if(_node)
202     _node->decrRef();
203 }
204
205 /*!
206  * Returns 0 or 1.
207  */
208 bool IntersectElement::isOnMergedExtremity() const
209 {
210   if( (_1S && _2S) || (_1S && _2E) || (_1E && _2S) || (_1E && _2E) )
211     return true;
212   return false;
213 }
214
215 /*!
216  * To call if isOnMergedExtremity returned true.
217  */
218 void IntersectElement::performMerging(MergePoints& commonNode) const
219 {
220   if(_1S && _2S)
221     {
222       if(_e1.changeStartNodeWith(_e2.getStartNode()))
223         {
224           _e2.getStartNode()->declareOnLim();
225           commonNode.start1OnStart2();
226         }
227     }
228   else if(_1S && _2E)
229     {
230       if(_e1.changeStartNodeWith(_e2.getEndNode()))
231         {
232           _e2.getEndNode()->declareOnLim();
233           commonNode.start1OnEnd2();
234         }
235     }
236   else if(_1E && _2S)
237     {
238       if(_e1.changeEndNodeWith(_e2.getStartNode()))
239         {
240           _e2.getStartNode()->declareOnLim();
241           commonNode.end1OnStart2();
242         }
243     }
244   else if(_1E && _2E)
245     {
246       if(_e1.changeEndNodeWith(_e2.getEndNode()))
247         {
248           _e2.getEndNode()->declareOnLim();
249           commonNode.end1OnEnd2();
250         }
251     }
252 }
253
254 /*!
255  * This methode is const because 'node' is supposed to be equal geomitrically to _node.
256  */
257 void IntersectElement::setNode(Node *node) const
258 {
259   if(node!=_node)
260     {
261       if(_node)
262         ((Node *)_node)->decrRef();
263       (const_cast<IntersectElement *>(this))->_node=node;
264       if(_node)
265         _node->incrRef();
266     }
267 }
268
269 bool IntersectElement::isLowerOnOther(const IntersectElement& other) const
270 {
271   return _e2.isLower(_chararct_val_for_e2,other._chararct_val_for_e2);
272 }
273
274 unsigned IntersectElement::isOnExtrForAnEdgeAndInForOtherEdge() const
275 {
276   if(( _1S && !(_2S || _2E) ) || ( _1E && !(_2S || _2E) ))
277     {
278       if(_1S && !(_2S || _2E))
279         setNode(_e1.getStartNode());
280       else
281         setNode(_e1.getEndNode());
282       if(_e2.isIn(_chararct_val_for_e2))
283         return LIMIT_ON;
284       return LIMIT_ALONE;
285     }
286   if(( _2S && !(_1S || _1E) ) || ( _2E && !(_1S || _1E)))
287     {
288       if(_2S && !(_1S || _1E))
289         setNode(_e2.getStartNode());
290       else
291         setNode(_e2.getEndNode());
292       if(_e1.isIn(_chararct_val_for_e1))
293         return LIMIT_ON;
294       return LIMIT_ALONE;
295     }
296   return NO_LIMIT;
297 }
298
299 bool IntersectElement::isIncludedByBoth() const
300 {
301   return _e1.isIn(_chararct_val_for_e1) && _e2.isIn(_chararct_val_for_e2);
302 }
303   
304 bool EdgeIntersector::intersect(const Bounds *whereToFind, std::vector<Node *>& newNodes, bool& order, MergePoints& commonNode)
305 {
306   std::list< IntersectElement > listOfIntesc=getIntersectionsCharacteristicVal();
307   std::list< IntersectElement >::iterator iter;
308   for(iter=listOfIntesc.begin();iter!=listOfIntesc.end();)
309     {
310       if((*iter).isOnMergedExtremity())
311         {
312           (*iter).performMerging(commonNode);
313           iter=listOfIntesc.erase(iter);
314           continue;
315         }
316       unsigned tmp=(*iter).isOnExtrForAnEdgeAndInForOtherEdge();
317       if(tmp==IntersectElement::LIMIT_ALONE)
318         {
319           iter=listOfIntesc.erase(iter);
320           continue;
321         }
322       else if(tmp==IntersectElement::LIMIT_ON)
323         {
324           (*iter).attachLoc();
325           iter++;
326           continue;
327         }
328       if(!(*iter).isIncludedByBoth())
329         {
330           iter=listOfIntesc.erase(iter);
331           continue;
332         }
333       (*iter).attachLoc();
334       iter++;
335     }
336   if(listOfIntesc.size()==0)
337     return false;
338   if(listOfIntesc.size()==1)
339     {
340       order=true;//useless
341       newNodes.push_back(listOfIntesc.front().getNodeAndReleaseIt());
342     }
343   else
344     {
345       std::vector<IntersectElement> vecOfIntesc(listOfIntesc.begin(),listOfIntesc.end());
346       listOfIntesc.clear();
347       sort(vecOfIntesc.begin(),vecOfIntesc.end());
348       for(std::vector<IntersectElement>::iterator iterV=vecOfIntesc.begin();iterV!=vecOfIntesc.end();iterV++)
349         newNodes.push_back((*iterV).getNodeAndReleaseIt());
350       order=vecOfIntesc.front().isLowerOnOther(vecOfIntesc.back());
351     }
352   return true;
353 }
354
355 /*!
356  * Locates 'node' regarding edge this->_e1. If node is located close to (with distant lt epsilon) start or end point of _e1,
357  * 'node' takes its place. In this case 'obvious' is set to true and 'commonNode' stores information of merge point and finally 'where' is set.
358  * Furthermore 'node' is declared as ON LIMIT to indicate in locating process that an absolute location computation will have to be done.
359  * If 'node' is not close to start or end point of _e1, 'obvious' is set to false and 'commonNode' and 'where' are let unchanged. 
360  */
361 void EdgeIntersector::obviousCaseForCurvAbscisse(Node *node, TypeOfLocInEdge& where, MergePoints& commonNode, bool& obvious) const
362 {
363   obvious=true;
364   if(node->isEqual(*_e1.getStartNode()))
365     {
366       where=START;
367       if(_e1.changeStartNodeWith(node))
368         {
369           commonNode.start1Replaced();
370           node->declareOnLim();
371         }
372       return ;
373     }
374   if(node->isEqual(*_e1.getEndNode()))
375     {
376       where=END;
377       if(_e1.changeEndNodeWith(node))
378         {
379           commonNode.end1Replaced();
380           node->declareOnLim();
381         }
382       return ;
383     }
384   obvious=false;
385 }
386
387 Edge::Edge(double sX, double sY, double eX, double eY):_cnt(1),_loc(FULL_UNKNOWN),_start(new Node(sX,sY)),_end(new Node(eX,eY))
388 {
389 }
390
391 Edge::~Edge()
392 {
393   _start->decrRef();
394   if(_end)
395     _end->decrRef();
396 }
397
398 bool Edge::decrRef()
399 {
400   bool ret=(--_cnt==0);
401   if(ret)
402     delete this;
403   return ret;
404 }
405
406 void Edge::declareOn() const
407 {
408   if(_loc==FULL_UNKNOWN)
409     {
410       _loc=FULL_ON_1;
411       _start->declareOn();
412       _end->declareOn();
413     }
414 }
415
416 void Edge::declareIn() const
417 {
418   if(_loc==FULL_UNKNOWN)
419     {
420       _loc=FULL_IN_1;
421       _start->declareIn();
422       _end->declareIn();
423     }
424 }
425
426 void Edge::declareOut() const
427 {
428   if(_loc==FULL_UNKNOWN)
429     {
430       _loc=FULL_OUT_1;
431       _start->declareOut();
432       _end->declareOut();
433     }
434 }
435
436 void Edge::fillXfigStreamForLoc(std::ostream& stream) const
437 {
438   switch(_loc)
439     {
440     case FULL_IN_1:
441       stream << '2';//Green
442       break;
443     case FULL_OUT_1:
444       stream << '1';//Bleue
445       break;
446     case FULL_ON_1:
447       stream << '4';//Red
448       break;
449     default:
450       stream << '0';
451     }
452 }
453
454 bool Edge::changeStartNodeWith(Node *otherStartNode) const
455 {
456   if(_start==otherStartNode)
457     return true;
458   if(_start->isEqual(*otherStartNode))
459     {
460       ((const_cast<Edge *>(this))->_start)->decrRef();//un-const cast Ok thanks to 2 lines above.
461       ((const_cast<Edge *>(this))->_start)=otherStartNode;
462       _start->incrRef();
463       return true;
464     }
465   return false;
466 }
467
468 bool Edge::changeStartNodeWithAndKeepTrack(Node *otherStartNode, std::vector<Node *>& track) const
469 {
470   if(_start==otherStartNode)
471     return true;
472   if(_start->isEqualAndKeepTrack(*otherStartNode,track))
473     {
474       ((const_cast<Edge *>(this))->_start)->decrRef();//un-const cast Ok thanks to 2 lines above.
475       ((const_cast<Edge *>(this))->_start)=otherStartNode;
476       otherStartNode->incrRef();
477       return true;
478     }
479   return false;
480 }
481
482 bool Edge::changeEndNodeWith(Node *otherEndNode) const
483 {
484   if(_end==otherEndNode)
485     return true;
486   if(_end->isEqual(*otherEndNode))
487     {
488       ((const_cast<Edge *>(this))->_end)->decrRef();
489       ((const_cast<Edge *>(this))->_end)=otherEndNode;
490       _end->incrRef();
491       return true;
492     }
493   return false;
494 }
495
496 bool Edge::changeEndNodeWithAndKeepTrack(Node *otherEndNode, std::vector<Node *>& track) const
497 {
498   if(_end==otherEndNode)
499     return true;
500   if(_end->isEqualAndKeepTrack(*otherEndNode,track))
501     {
502       ((const_cast<Edge *>(this))->_end)->decrRef();
503       ((const_cast<Edge *>(this))->_end)=otherEndNode;
504       otherEndNode->incrRef();
505       return true;
506     }
507   return false;
508 }
509
510 /*!
511  * Precondition : 'start' and 'end' are lying on the same curve than 'this'.
512  * Add in vec the sub edge lying on this.
513  * If 'start' is equal (by pointer) to '_end' and 'end' is equal to '_end' too nothing is added.
514  * If 'start' is equal (by pointer) to '_start' and 'end' is equal to '_start' too nothing is added.
515  * If 'start' is equal (by pointer) to '_start' and 'end' is equal to '_end' this is added in vec.
516  */
517 void Edge::addSubEdgeInVector(Node *start, Node *end, ComposedEdge& vec) const
518 {
519   if((start==_start && end==_start) || (start==_end && end==_end))
520     return ;
521   if(start==_start && end==_end)
522     {
523       incrRef();
524       vec.pushBack(const_cast<Edge *>(this));
525       return ;
526     }
527   vec.pushBack(buildEdgeLyingOnMe(start,end,true));
528 }
529
530 /*!
531  * Retrieves a vector 'vectOutput' that is normal to 'this'. 'vectOutput' is normalized.
532  */
533 void Edge::getNormalVector(double *vectOutput) const
534 {
535   std::copy((const double *)(*_end),(const double *)(*_end)+2,vectOutput);
536   std::transform(vectOutput,vectOutput+2,(const double *)(*_start),vectOutput,std::minus<double>());
537   double norm=1./Node::norm(vectOutput);
538   std::transform(vectOutput,vectOutput+2,vectOutput,bind2nd(std::multiplies<double>(),norm));
539   double tmp=vectOutput[0];
540   vectOutput[0]=vectOutput[1];
541   vectOutput[1]=-tmp;
542 }
543
544 Edge *Edge::BuildEdgeFrom(Node *start, Node *end)
545 {
546   return new EdgeLin(start,end);
547 }
548
549 Edge *Edge::BuildFromXfigLine(std::istream& str)
550 {
551   unsigned char type;
552   str >> type;
553   if(type=='2')
554     return new EdgeLin(str);
555   else if(type=='5')
556     return new EdgeArcCircle(str);
557   else
558     {
559       std::cerr << "Unknown line found...";
560       return 0;
561     }
562 }
563
564 /*!
565  * \param other The Edge with which we are going to intersect.
566  * \param commonNode Output. The common nodes found during operation of intersecting.
567  * \param outVal1 Output filled in case true is returned. It specifies the new or not new edges by which 'this' is replaced after intersecting op.
568  * \param outVal2 Output filled in case true is returned. It specifies the new or not new edges by which 'other' is replaced after intersecting op.
569  * return true if the intersection between this.
570  */
571 bool Edge::intersectWith(const Edge *other, MergePoints& commonNode,
572                          ComposedEdge& outVal1, ComposedEdge& outVal2) const
573 {
574   bool ret=true;
575   Bounds *merge=_bounds.nearlyAmIIntersectingWith(other->getBounds());
576   if(!merge)
577     return false;
578   delete merge;
579   merge=0;
580   EdgeIntersector *intersector=BuildIntersectorWith(this,other);
581   ret=Intersect(this,other,intersector,merge,commonNode,outVal1,outVal2);
582   delete intersector;
583   return ret;
584 }
585
586 bool Edge::IntersectOverlapped(const Edge *f1, const Edge *f2, EdgeIntersector *intersector, MergePoints& commonNode,
587                                ComposedEdge& outValForF1, ComposedEdge& outValForF2)
588 {
589   bool rev=intersector->haveTheySameDirection();
590   Node *f2Start=f2->getNode(rev?START:END);
591   Node *f2End=f2->getNode(rev?END:START);
592   TypeOfLocInEdge place1, place2;
593   intersector->getPlacements(f2Start,f2End,place1,place2,commonNode);
594   int codeForIntersectionCase=CombineCodes(place1,place2);
595   return SplitOverlappedEdges(f1,f2,f2Start,f2End,rev,codeForIntersectionCase,outValForF1,outValForF2);
596 }
597
598 /*!
599  * Perform 1D linear interpolation. Warning distrib1 and distrib2 are expected to be in ascending mode.
600  */
601 void Edge::Interpolate1DLin(const std::vector<double>& distrib1, const std::vector<double>& distrib2, std::map<int, std::map<int,double> >& result)
602 {
603   int nbOfV1=distrib1.size()-1;
604   int nbOfV2=distrib2.size()-1;
605   Node *n1=new Node(0.,0.); Node *n3=new Node(0.,0.);
606   Node *n2=new Node(0.,0.); Node *n4=new Node(0.,0.);
607   MergePoints commonNode;
608   for(int i=0;i<nbOfV1;i++)
609     {
610       std::vector<double>::const_iterator iter=find_if(distrib2.begin()+1,distrib2.end(),bind2nd(std::greater_equal<double>(),distrib1[i]));
611       if(iter!=distrib2.end())
612         {
613           for(int j=(iter-1)-distrib2.begin();j<nbOfV2;j++)
614             {
615               if(distrib2[j]<=distrib1[i+1])
616                 {
617                   EdgeLin *e1=new EdgeLin(n1,n2); EdgeLin *e2=new EdgeLin(n3,n4);
618                   n1->setNewCoords(distrib1[i],0.); n2->setNewCoords(distrib1[i+1],0.);
619                   n3->setNewCoords(distrib2[j],0.); n4->setNewCoords(distrib2[j+1],0.);
620                   ComposedEdge *f1=new ComposedEdge;
621                   ComposedEdge *f2=new ComposedEdge;
622                   SegSegIntersector inters(*e1,*e2);
623                   bool b1,b2;
624                   inters.areOverlappedOrOnlyColinears(0,b1,b2);
625                   if(IntersectOverlapped(e1,e2,&inters,commonNode,*f1,*f2))
626                     {
627                       result[i][j]=f1->getCommonLengthWith(*f2)/e1->getCurveLength();
628                     }
629                   ComposedEdge::Delete(f1); ComposedEdge::Delete(f2);
630                   e1->decrRef(); e2->decrRef();
631                 }
632             }
633         }
634     }
635   n1->decrRef(); n2->decrRef(); n3->decrRef(); n4->decrRef();
636 }
637
638 EdgeIntersector *Edge::BuildIntersectorWith(const Edge *e1, const Edge *e2)
639 {
640   EdgeIntersector *ret=0;
641   const EdgeLin *tmp1=0;
642   const EdgeArcCircle *tmp2=0;
643   unsigned char type1=e1->getTypeOfFunc();
644   e1->dynCastFunction(tmp1,tmp2);
645   unsigned char type2=e2->getTypeOfFunc();
646   e2->dynCastFunction(tmp1,tmp2);
647   type1|=type2;
648   switch(type1)
649     {
650     case 1:// Intersection seg/seg
651       ret=new SegSegIntersector((const EdgeLin &)(*e1),(const EdgeLin &)(*e2));
652       break;
653     case 5:// Intersection seg/arc of circle
654       ret=new ArcCSegIntersector(*tmp2,*tmp1,tmp2==e1);
655       break;
656     case 4:// Intersection arc/arc of circle
657       ret=new ArcCArcCIntersector((const EdgeArcCircle &)(*e1),(const EdgeArcCircle &)(*e2));
658       break;
659     default:
660       //Should never happen
661       throw Exception("A non managed association of edge has been detected. Go work for intersection computation implementation.");
662     }
663   return ret;
664 }
665
666 /*!
667  * See Node::applySimilarity to see signification of params.
668  */
669 void Edge::applySimilarity(double xBary, double yBary, double dimChar)
670 {
671   _bounds.applySimilarity(xBary,yBary,dimChar);
672 }
673
674 void Edge::unApplySimilarity(double xBary, double yBary, double dimChar)
675 {
676   _bounds.unApplySimilarity(xBary,yBary,dimChar);
677 }
678
679 bool Edge::Intersect(const Edge *f1, const Edge *f2, EdgeIntersector *intersector, const Bounds *whereToFind, MergePoints& commonNode,
680                      ComposedEdge& outValForF1, ComposedEdge& outValForF2)
681 {
682   bool obviousNoIntersection;
683   bool areOverlapped;
684   intersector->areOverlappedOrOnlyColinears(whereToFind,obviousNoIntersection,areOverlapped);
685   if(areOverlapped)
686     return IntersectOverlapped(f1,f2,intersector,commonNode,outValForF1,outValForF2);
687   if(obviousNoIntersection)
688     return false;
689   std::vector<Node *> newNodes;
690   bool order;
691   if(intersector->intersect(whereToFind,newNodes,order,commonNode))
692     {
693       if(newNodes.empty())
694         throw Exception("Internal error occured - error in intersector implementation!");// This case should never happen
695       std::vector<Node *>::iterator iter=newNodes.begin();
696       std::vector<Node *>::reverse_iterator iterR=newNodes.rbegin();
697       f1->addSubEdgeInVector(f1->getStartNode(),*iter,outValForF1);
698       f2->addSubEdgeInVector(f2->getStartNode(),order?*iter:*iterR,outValForF2);
699       for(std::vector<Node *>::iterator iter2=newNodes.begin();iter2!=newNodes.end();iter2++,iterR++)
700         {
701           if((iter2+1)==newNodes.end())
702             {
703               f1->addSubEdgeInVector(*iter2,f1->getEndNode(),outValForF1);
704               (*iter2)->decrRef();
705               f2->addSubEdgeInVector(order?*iter2:*iterR,f2->getEndNode(),outValForF2);
706             }
707           else
708             {
709               f1->addSubEdgeInVector(*iter2,*(iter2+1),outValForF1);
710               (*iter2)->decrRef();
711               f2->addSubEdgeInVector(order?*iter2:*iterR,order?*(iter2+1):*(iterR+1),outValForF2);
712             }
713         }
714       return true;
715     }
716   else//no intersection inside whereToFind
717     return false;
718 }
719
720 int Edge::CombineCodes(TypeOfLocInEdge code1, TypeOfLocInEdge code2)
721 {
722   int ret=(int)code1;
723   ret*=OFFSET_FOR_TYPEOFLOCINEDGE;
724   ret+=(int)code2;
725   return ret;
726 }
727
728 /*!
729  * This method splits e1 and e2 into pieces as much sharable as possible. The precondition to the call of this method
730  * is that e1 and e2 have been declared as overlapped by corresponding intersector built from e1 and e2 type.
731  *
732  * @param nS start node of e2 with the SAME DIRECTION as e1. The pointer nS should be equal to start node of e2 or to its end node.
733  * @param nE end node of e2 with the SAME DIRECTION as e1. The pointer nE should be equal to start node of e2 or to its end node.
734  * @param direction is param that specifies if e2 and e1 have same directions (true) or opposed (false).
735  * @param code is the code returned by method Edge::combineCodes.
736  */
737 bool Edge::SplitOverlappedEdges(const Edge *e1, const Edge *e2, Node *nS, Node *nE, bool direction, int code,
738                                 ComposedEdge& outVal1, ComposedEdge& outVal2)
739 {
740   Edge *tmp;
741   switch(code)
742     {
743     case OUT_BEFORE*OFFSET_FOR_TYPEOFLOCINEDGE+START:      // OUT_BEFORE - START
744     case OUT_BEFORE*OFFSET_FOR_TYPEOFLOCINEDGE+OUT_BEFORE: // OUT_BEFORE - OUT_BEFORE
745     case OUT_AFTER*OFFSET_FOR_TYPEOFLOCINEDGE+OUT_AFTER:   // OUT_AFTER - OUT_AFTER
746     case END*OFFSET_FOR_TYPEOFLOCINEDGE+OUT_AFTER:         // END - OUT_AFTER
747     case END*OFFSET_FOR_TYPEOFLOCINEDGE+START:             // END - START
748       return false;
749     case INSIDE*OFFSET_FOR_TYPEOFLOCINEDGE+OUT_AFTER:      // INSIDE - OUT_AFTER
750       outVal1.pushBack(e1->buildEdgeLyingOnMe(e1->getStartNode(),nS,true));
751       tmp=e1->buildEdgeLyingOnMe(nS,e1->getEndNode()); tmp->incrRef();
752       outVal1.pushBack(tmp);
753       outVal2.resize(2);
754       outVal2.setValueAt(direction?0:1,tmp,direction); tmp->declareOn();
755       outVal2.setValueAt(direction?1:0,e1->buildEdgeLyingOnMe(e1->getEndNode(),nE,direction));
756       return true;
757     case INSIDE*OFFSET_FOR_TYPEOFLOCINEDGE+INSIDE:         // INSIDE - INSIDE
758       {
759         if(!e2->isIn(e2->getCharactValue(*(e1->getStartNode()))))
760           {
761             e2->incrRef(); e2->incrRef();
762             outVal1.resize(3);
763             outVal1.setValueAt(0,e1->buildEdgeLyingOnMe(e1->getStartNode(),nS));
764             outVal1.setValueAt(1,const_cast<Edge*>(e2),direction);
765             outVal1.setValueAt(2,e1->buildEdgeLyingOnMe(nE,e1->getEndNode()));
766             outVal2.pushBack(const_cast<Edge*>(e2)); e2->declareOn();
767             return true;
768           }
769         else
770           {
771             outVal1.resize(3);
772             outVal2.resize(3);
773             tmp=e1->buildEdgeLyingOnMe(e1->getStartNode(),nE); tmp->incrRef(); tmp->declareOn();
774             outVal1.setValueAt(0,tmp,true); outVal2.setValueAt(direction?2:0,tmp,direction);
775             outVal1.setValueAt(1,e1->buildEdgeLyingOnMe(nE,nS));
776             tmp=e1->buildEdgeLyingOnMe(nS,e1->getEndNode()); tmp->incrRef(); tmp->declareOn();
777             outVal1.setValueAt(2,tmp,true); outVal2.setValueAt(direction?0:2,tmp,direction);
778             tmp=e1->buildEdgeLyingOnMe(e1->getEndNode(),e1->getStartNode());
779             outVal2.setValueAt(1,tmp,direction);
780             return true;
781           }
782       }
783     case OUT_BEFORE*OFFSET_FOR_TYPEOFLOCINEDGE+INSIDE:     // OUT_BEFORE - INSIDE
784       tmp=e1->buildEdgeLyingOnMe(e1->getStartNode(),nE); tmp->incrRef();
785       outVal1.pushBack(tmp);
786       outVal1.pushBack(e1->buildEdgeLyingOnMe(nE,e1->getEndNode()));
787       outVal2.resize(2);
788       outVal2.setValueAt(direction?0:1,e1->buildEdgeLyingOnMe(nS,e1->getStartNode(),direction));
789       outVal2.setValueAt(direction?1:0,tmp,direction); tmp->declareOn();
790       return true;
791     case OUT_BEFORE*OFFSET_FOR_TYPEOFLOCINEDGE+OUT_AFTER:  // OUT_BEFORE - OUT_AFTER
792       e1->incrRef(); e1->incrRef();
793       outVal1.pushBack(const_cast<Edge*>(e1));
794       outVal2.resize(3);
795       outVal2.setValueAt(direction?0:2,e1->buildEdgeLyingOnMe(nS,e1->getStartNode(),direction));
796       outVal2.setValueAt(1,const_cast<Edge*>(e1),direction); e1->declareOn();
797       outVal2.setValueAt(direction?2:0,e1->buildEdgeLyingOnMe(e1->getEndNode(),nE,direction));
798       return true;
799     case START*OFFSET_FOR_TYPEOFLOCINEDGE+END:             // START - END
800       e1->incrRef(); e1->incrRef();
801       outVal1.pushBack(const_cast<Edge*>(e1));
802       outVal2.pushBack(const_cast<Edge*>(e1),direction); e1->declareOn();
803       return true;
804     case START*OFFSET_FOR_TYPEOFLOCINEDGE+OUT_AFTER:       // START - OUT_AFTER
805       e1->incrRef(); e1->incrRef();
806       outVal1.pushBack(const_cast<Edge*>(e1));
807       outVal2.resize(2);
808       outVal2.setValueAt(direction?0:1,const_cast<Edge*>(e1),direction); e1->declareOn();
809       outVal2.setValueAt(direction?1:0,e1->buildEdgeLyingOnMe(e1->getEndNode(),nE,direction));
810       return true;
811     case INSIDE*OFFSET_FOR_TYPEOFLOCINEDGE+END:            // INSIDE - END
812       e2->incrRef(); e2->incrRef();
813       outVal1.pushBack(e1->buildEdgeLyingOnMe(e1->getStartNode(),nS,true));
814       outVal1.pushBack(const_cast<Edge*>(e2),direction);
815       outVal2.pushBack(const_cast<Edge*>(e2)); e2->declareOn();
816       return true;
817     case OUT_BEFORE*OFFSET_FOR_TYPEOFLOCINEDGE+END:        // OUT_BEFORE - END
818       e1->incrRef(); e1->incrRef();
819       outVal1.pushBack(const_cast<Edge*>(e1));
820       outVal2.resize(2);
821       outVal2.setValueAt(direction?0:1,e1->buildEdgeLyingOnMe(nS,e1->getStartNode(),direction));
822       outVal2.setValueAt(direction?1:0,const_cast<Edge*>(e1),direction); e1->declareOn();
823       return true;
824     case START*OFFSET_FOR_TYPEOFLOCINEDGE+INSIDE:          // START - INSIDE
825       e2->incrRef(); e2->incrRef();
826       outVal1.pushBack(const_cast<Edge*>(e2),direction);
827       outVal1.pushBack(e1->buildEdgeLyingOnMe(nE,e1->getEndNode()));
828       outVal2.pushBack(const_cast<Edge*>(e2)); e2->declareOn();
829       return true;
830     case INSIDE*OFFSET_FOR_TYPEOFLOCINEDGE+START:          // INSIDE - START
831       outVal1.resize(2);
832       outVal2.resize(2);
833       tmp=e1->buildEdgeLyingOnMe(nS,e1->getEndNode()); tmp->incrRef(); tmp->declareOn();
834       outVal1.setValueAt(0,e1->buildEdgeLyingOnMe(e1->getStartNode(),nS));
835       outVal1.setValueAt(1,tmp);
836       outVal2.setValueAt(direction?0:1,tmp,direction);
837       outVal2.setValueAt(direction?1:0,e1->buildEdgeLyingOnMe(e1->getEndNode(),nE,direction));
838       return true;
839     case END*OFFSET_FOR_TYPEOFLOCINEDGE+INSIDE:            // END - INSIDE
840       outVal1.resize(2);
841       outVal2.resize(2);
842       tmp=e1->buildEdgeLyingOnMe(e1->getStartNode(),nE); tmp->incrRef(); tmp->declareOn();
843       outVal1.setValueAt(0,tmp);
844       outVal1.setValueAt(1,e1->buildEdgeLyingOnMe(nE,e1->getEndNode()));
845       outVal2.setValueAt(direction?0:1,e1->buildEdgeLyingOnMe(e1->getEndNode(),e1->getStartNode(),direction));
846       outVal2.setValueAt(direction?1:0,tmp,direction);
847       return true;
848     default:
849       throw Exception("Unexpected situation of overlapping edges : internal error occurs ! ");
850     }
851 }
852
853 bool Edge::isEqual(const Edge& other) const
854 {
855   return _start->isEqual(*other._start) && _end->isEqual(*other._end);
856 }
857
858 inline bool eqpair(const std::pair<double,Node *>& p1, const std::pair<double,Node *>& p2)
859 {
860   return fabs(p1.first-p2.first)<QUADRATIC_PLANAR::_precision;
861 }
862
863 void Edge::sortIdsAbs(const std::vector<INTERP_KERNEL::Node *>& addNodes, const std::map<INTERP_KERNEL::Node *, int>& mapp1, const std::map<INTERP_KERNEL::Node *, int>& mapp2, std::vector<int>& edgesThis)
864 {
865   Bounds b;
866   b.prepareForAggregation();
867   b.aggregate(getBounds());
868   double xBary,yBary;
869   double dimChar=b.getCaracteristicDim();
870   b.getBarycenter(xBary,yBary);
871   for(std::vector<Node *>::const_iterator iter=addNodes.begin();iter!=addNodes.end();iter++)
872     (*iter)->applySimilarity(xBary,yBary,dimChar);
873   applySimilarity(xBary,yBary,dimChar);
874   _start->applySimilarity(xBary,yBary,dimChar);
875   _end->applySimilarity(xBary,yBary,dimChar);
876   std::size_t sz=addNodes.size();
877   std::vector< std::pair<double,Node *> > an2(sz);
878   for(std::size_t i=0;i<sz;i++)
879     an2[i]=std::pair<double,Node *>(getCharactValueBtw0And1(*addNodes[i]),addNodes[i]);
880   std::sort(an2.begin(),an2.end());
881   int startId=(*mapp1.find(_start)).second;
882   int endId=(*mapp1.find(_end)).second;
883   std::vector<int> tmpp;
884   std::vector< std::pair<double,Node *> >::const_iterator itend=std::unique(an2.begin(),an2.end(),eqpair);
885   for(std::vector< std::pair<double,Node *> >::const_iterator it=an2.begin();it!=itend;it++)
886     {
887       int idd=(*mapp2.find((*it).second)).second;
888       if((*it).first<QUADRATIC_PLANAR::_precision)
889         {
890           startId=idd;
891           continue;
892         }
893       if((*it).first>1-QUADRATIC_PLANAR::_precision)
894         {
895           endId=idd;
896           continue;
897         }
898       tmpp.push_back(idd);
899     }
900   std::vector<int> tmpp2(tmpp.size()+2);
901   tmpp2[0]=startId;
902   std::copy(tmpp.begin(),tmpp.end(),tmpp2.begin()+1);
903   tmpp2[tmpp.size()+1]=endId;
904   std::vector<int>::iterator itt=std::unique(tmpp2.begin(),tmpp2.end());
905   tmpp2.resize(std::distance(tmpp2.begin(),itt));
906   int nbOfEdges=tmpp2.size()-1;
907   for(int i=0;i<nbOfEdges;i++)
908     {
909       edgesThis.push_back(tmpp2[i]);
910       edgesThis.push_back(tmpp2[i+1]);
911     }
912 }