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