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