1 // Copyright (C) 2007-2013 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // Author : Anthony Geay (CEA/DEN)
21 #include "InterpKernelGeo2DEdge.hxx"
22 #include "InterpKernelGeo2DEdgeLin.hxx"
23 #include "InterpKernelGeo2DEdgeInfLin.hxx"
24 //#include "EdgeParabol.hxx"
25 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
26 #include "InterpKernelException.hxx"
30 using namespace INTERP_KERNEL;
32 MergePoints::MergePoints():_ass1Start1(0),_ass1End1(0),_ass1Start2(0),_ass1End2(0),
33 _ass2Start1(0),_ass2End1(0),_ass2Start2(0),_ass2End2(0)
37 void MergePoints::start1Replaced()
39 unsigned nbOfAsso=getNumberOfAssociations();
46 void MergePoints::end1Replaced()
48 unsigned nbOfAsso=getNumberOfAssociations();
55 void MergePoints::start1OnStart2()
57 unsigned nbOfAsso=getNumberOfAssociations();
70 void MergePoints::start1OnEnd2()
72 unsigned nbOfAsso=getNumberOfAssociations();
85 void MergePoints::end1OnStart2()
87 unsigned nbOfAsso=getNumberOfAssociations();
100 void MergePoints::end1OnEnd2()
102 unsigned nbOfAsso=getNumberOfAssociations();
115 bool MergePoints::isStart1(unsigned rk) const
123 bool MergePoints::isEnd1(unsigned rk) const
131 bool MergePoints::isStart2(unsigned rk) const
139 bool MergePoints::isEnd2(unsigned rk) const
147 void MergePoints::clear()
149 _ass1Start1=0;_ass1End1=0;_ass1Start2=0;_ass1End2=0;
150 _ass2Start1=0;_ass2End1=0;_ass2Start2=0;_ass2End2=0;
153 unsigned MergePoints::getNumberOfAssociations() const
156 unsigned subTot=_ass1Start1+_ass1End1+_ass1Start2+_ass1End2;
159 subTot=_ass2Start1+_ass2End1+_ass2Start2+_ass2End2;
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),
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)
186 IntersectElement& IntersectElement::operator=(const IntersectElement& other)
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);
195 bool IntersectElement::operator<(const IntersectElement& other) const
197 return _e1.isLower(_chararct_val_for_e1,other._chararct_val_for_e1);
200 IntersectElement::~IntersectElement()
209 bool IntersectElement::isOnMergedExtremity() const
211 if( (_1S && _2S) || (_1S && _2E) || (_1E && _2S) || (_1E && _2E) )
217 * To call if isOnMergedExtremity returned true.
219 void IntersectElement::performMerging(MergePoints& commonNode) const
223 if(_e1.changeStartNodeWith(_e2.getStartNode()))
225 _e2.getStartNode()->declareOnLim();
226 commonNode.start1OnStart2();
231 if(_e1.changeStartNodeWith(_e2.getEndNode()))
233 _e2.getEndNode()->declareOnLim();
234 commonNode.start1OnEnd2();
239 if(_e1.changeEndNodeWith(_e2.getStartNode()))
241 _e2.getStartNode()->declareOnLim();
242 commonNode.end1OnStart2();
247 if(_e1.changeEndNodeWith(_e2.getEndNode()))
249 _e2.getEndNode()->declareOnLim();
250 commonNode.end1OnEnd2();
256 * This methode is const because 'node' is supposed to be equal geomitrically to _node.
258 void IntersectElement::setNode(Node *node) const
263 ((Node *)_node)->decrRef();
264 (const_cast<IntersectElement *>(this))->_node=node;
270 bool IntersectElement::isLowerOnOther(const IntersectElement& other) const
272 return _e2.isLower(_chararct_val_for_e2,other._chararct_val_for_e2);
275 unsigned IntersectElement::isOnExtrForAnEdgeAndInForOtherEdge() const
277 if(( _1S && !(_2S || _2E) ) || ( _1E && !(_2S || _2E) ))
279 if(_1S && !(_2S || _2E))
280 setNode(_e1.getStartNode());
282 setNode(_e1.getEndNode());
283 if(_e2.isIn(_chararct_val_for_e2))
287 if(( _2S && !(_1S || _1E) ) || ( _2E && !(_1S || _1E)))
289 if(_2S && !(_1S || _1E))
290 setNode(_e2.getStartNode());
292 setNode(_e2.getEndNode());
293 if(_e1.isIn(_chararct_val_for_e1))
300 bool IntersectElement::isIncludedByBoth() const
302 return _e1.isIn(_chararct_val_for_e1) && _e2.isIn(_chararct_val_for_e2);
305 bool EdgeIntersector::intersect(const Bounds *whereToFind, std::vector<Node *>& newNodes, bool& order, MergePoints& commonNode)
307 std::list< IntersectElement > listOfIntesc=getIntersectionsCharacteristicVal();
308 std::list< IntersectElement >::iterator iter;
309 for(iter=listOfIntesc.begin();iter!=listOfIntesc.end();)
311 if((*iter).isOnMergedExtremity())
313 (*iter).performMerging(commonNode);
314 iter=listOfIntesc.erase(iter);
317 unsigned tmp=(*iter).isOnExtrForAnEdgeAndInForOtherEdge();
318 if(tmp==IntersectElement::LIMIT_ALONE)
320 iter=listOfIntesc.erase(iter);
323 else if(tmp==IntersectElement::LIMIT_ON)
329 if(!(*iter).isIncludedByBoth())
331 iter=listOfIntesc.erase(iter);
337 if(listOfIntesc.size()==0)
339 if(listOfIntesc.size()==1)
342 newNodes.push_back(listOfIntesc.front().getNodeAndReleaseIt());
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());
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.
362 void EdgeIntersector::obviousCaseForCurvAbscisse(Node *node, TypeOfLocInEdge& where, MergePoints& commonNode, bool& obvious) const
365 if(node->isEqual(*_e1.getStartNode()))
368 if(_e1.changeStartNodeWith(node))
370 commonNode.start1Replaced();
371 node->declareOnLim();
375 if(node->isEqual(*_e1.getEndNode()))
378 if(_e1.changeEndNodeWith(node))
380 commonNode.end1Replaced();
381 node->declareOnLim();
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))
401 bool ret=(--_cnt==0);
407 void Edge::declareOn() const
409 if(_loc==FULL_UNKNOWN)
417 void Edge::declareIn() const
419 if(_loc==FULL_UNKNOWN)
427 void Edge::declareOut() const
429 if(_loc==FULL_UNKNOWN)
432 _start->declareOut();
437 void Edge::fillXfigStreamForLoc(std::ostream& stream) const
442 stream << '2';//Green
445 stream << '1';//Bleue
455 bool Edge::changeStartNodeWith(Node *otherStartNode) const
457 if(_start==otherStartNode)
459 if(_start->isEqual(*otherStartNode))
461 ((const_cast<Edge *>(this))->_start)->decrRef();//un-const cast Ok thanks to 2 lines above.
462 ((const_cast<Edge *>(this))->_start)=otherStartNode;
469 bool Edge::changeStartNodeWithAndKeepTrack(Node *otherStartNode, std::vector<Node *>& track) const
471 if(_start==otherStartNode)
473 if(_start->isEqualAndKeepTrack(*otherStartNode,track))
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();
483 bool Edge::changeEndNodeWith(Node *otherEndNode) const
485 if(_end==otherEndNode)
487 if(_end->isEqual(*otherEndNode))
489 ((const_cast<Edge *>(this))->_end)->decrRef();
490 ((const_cast<Edge *>(this))->_end)=otherEndNode;
497 bool Edge::changeEndNodeWithAndKeepTrack(Node *otherEndNode, std::vector<Node *>& track) const
499 if(_end==otherEndNode)
501 if(_end->isEqualAndKeepTrack(*otherEndNode,track))
503 ((const_cast<Edge *>(this))->_end)->decrRef();
504 ((const_cast<Edge *>(this))->_end)=otherEndNode;
505 otherEndNode->incrRef();
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.
518 void Edge::addSubEdgeInVector(Node *start, Node *end, ComposedEdge& vec) const
520 if((start==_start && end==_start) || (start==_end && end==_end))
522 if(start==_start && end==_end)
525 vec.pushBack(const_cast<Edge *>(this));
528 vec.pushBack(buildEdgeLyingOnMe(start,end,true));
532 * Retrieves a vector 'vectOutput' that is normal to 'this'. 'vectOutput' is normalized.
534 void Edge::getNormalVector(double *vectOutput) const
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];
545 Edge *Edge::BuildEdgeFrom3Points(const double *start, const double *middle, const double *end)
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;
552 ret=new EdgeLin(b,e);
554 ret=new EdgeArcCircle(b,m,e);
555 b->decrRef(); m->decrRef(); e->decrRef();
559 Edge *Edge::BuildEdgeFrom(Node *start, Node *end)
561 return new EdgeLin(start,end);
564 Edge *Edge::BuildFromXfigLine(std::istream& str)
569 return new EdgeLin(str);
571 return new EdgeArcCircle(str);
574 std::cerr << "Unknown line found...";
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.
586 bool Edge::intersectWith(const Edge *other, MergePoints& commonNode,
587 ComposedEdge& outVal1, ComposedEdge& outVal2) const
590 Bounds *merge=_bounds.nearlyAmIIntersectingWith(other->getBounds());
595 EdgeIntersector *intersector=BuildIntersectorWith(this,other);
596 ret=Intersect(this,other,intersector,merge,commonNode,outVal1,outVal2);
601 bool Edge::IntersectOverlapped(const Edge *f1, const Edge *f2, EdgeIntersector *intersector, MergePoints& commonNode,
602 ComposedEdge& outValForF1, ComposedEdge& outValForF2)
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);
614 * Perform 1D linear interpolation. Warning distrib1 and distrib2 are expected to be in ascending mode.
616 void Edge::Interpolate1DLin(const std::vector<double>& distrib1, const std::vector<double>& distrib2, std::map<int, std::map<int,double> >& result)
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++)
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())
628 for(int j=(iter-1)-distrib2.begin();j<nbOfV2;j++)
630 if(distrib2[j]<=distrib1[i+1])
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);
639 inters.areOverlappedOrOnlyColinears(0,b1,b2);
640 if(IntersectOverlapped(e1,e2,&inters,commonNode,*f1,*f2))
642 result[i][j]=f1->getCommonLengthWith(*f2)/e1->getCurveLength();
644 ComposedEdge::Delete(f1); ComposedEdge::Delete(f2);
645 e1->decrRef(); e2->decrRef();
650 n1->decrRef(); n2->decrRef(); n3->decrRef(); n4->decrRef();
653 EdgeIntersector *Edge::BuildIntersectorWith(const Edge *e1, const Edge *e2)
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);
665 case 1:// Intersection seg/seg
666 ret=new SegSegIntersector((const EdgeLin &)(*e1),(const EdgeLin &)(*e2));
668 case 5:// Intersection seg/arc of circle
669 ret=new ArcCSegIntersector(*tmp2,*tmp1,tmp2==e1);
671 case 4:// Intersection arc/arc of circle
672 ret=new ArcCArcCIntersector((const EdgeArcCircle &)(*e1),(const EdgeArcCircle &)(*e2));
675 //Should never happen
676 throw Exception("A non managed association of edge has been detected. Go work for intersection computation implementation.");
682 * See Node::applySimilarity to see signification of params.
684 void Edge::applySimilarity(double xBary, double yBary, double dimChar)
686 _bounds.applySimilarity(xBary,yBary,dimChar);
689 void Edge::unApplySimilarity(double xBary, double yBary, double dimChar)
691 _bounds.unApplySimilarity(xBary,yBary,dimChar);
694 bool Edge::Intersect(const Edge *f1, const Edge *f2, EdgeIntersector *intersector, const Bounds *whereToFind, MergePoints& commonNode,
695 ComposedEdge& outValForF1, ComposedEdge& outValForF2)
697 bool obviousNoIntersection;
699 intersector->areOverlappedOrOnlyColinears(whereToFind,obviousNoIntersection,areOverlapped);
701 return IntersectOverlapped(f1,f2,intersector,commonNode,outValForF1,outValForF2);
702 if(obviousNoIntersection)
704 std::vector<Node *> newNodes;
706 if(intersector->intersect(whereToFind,newNodes,order,commonNode))
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++)
716 if((iter2+1)==newNodes.end())
718 f1->addSubEdgeInVector(*iter2,f1->getEndNode(),outValForF1);
720 f2->addSubEdgeInVector(order?*iter2:*iterR,f2->getEndNode(),outValForF2);
724 f1->addSubEdgeInVector(*iter2,*(iter2+1),outValForF1);
726 f2->addSubEdgeInVector(order?*iter2:*iterR,order?*(iter2+1):*(iterR+1),outValForF2);
731 else//no intersection inside whereToFind
735 int Edge::CombineCodes(TypeOfLocInEdge code1, TypeOfLocInEdge code2)
738 ret*=OFFSET_FOR_TYPEOFLOCINEDGE;
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.
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.
752 bool Edge::SplitOverlappedEdges(const Edge *e1, const Edge *e2, Node *nS, Node *nE, bool direction, int code,
753 ComposedEdge& outVal1, ComposedEdge& outVal2)
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
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);
769 outVal2.setValueAt(direction?0:1,tmp,direction); tmp->declareOn();
770 outVal2.setValueAt(direction?1:0,e1->buildEdgeLyingOnMe(e1->getEndNode(),nE,direction));
772 case INSIDE*OFFSET_FOR_TYPEOFLOCINEDGE+INSIDE: // INSIDE - INSIDE
774 if(!e2->isIn(e2->getCharactValue(*(e1->getStartNode()))))
776 e2->incrRef(); e2->incrRef();
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();
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);
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()));
803 outVal2.setValueAt(direction?0:1,e1->buildEdgeLyingOnMe(nS,e1->getStartNode(),direction));
804 outVal2.setValueAt(direction?1:0,tmp,direction); tmp->declareOn();
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));
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));
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();
819 case START*OFFSET_FOR_TYPEOFLOCINEDGE+OUT_AFTER: // START - OUT_AFTER
820 e1->incrRef(); e1->incrRef();
821 outVal1.pushBack(const_cast<Edge*>(e1));
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));
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();
832 case OUT_BEFORE*OFFSET_FOR_TYPEOFLOCINEDGE+END: // OUT_BEFORE - END
833 e1->incrRef(); e1->incrRef();
834 outVal1.pushBack(const_cast<Edge*>(e1));
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();
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();
845 case INSIDE*OFFSET_FOR_TYPEOFLOCINEDGE+START: // INSIDE - START
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));
854 case END*OFFSET_FOR_TYPEOFLOCINEDGE+INSIDE: // END - INSIDE
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);
864 throw Exception("Unexpected situation of overlapping edges : internal error occurs ! ");
868 bool Edge::isEqual(const Edge& other) const
870 return _start->isEqual(*other._start) && _end->isEqual(*other._end);
873 inline bool eqpair(const std::pair<double,Node *>& p1, const std::pair<double,Node *>& p2)
875 return fabs(p1.first-p2.first)<QUADRATIC_PLANAR::_precision;
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)
881 b.prepareForAggregation();
882 b.aggregate(getBounds());
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++)
902 int idd=(*mapp2.find((*it).second)).second;
903 if((*it).first<QUADRATIC_PLANAR::_precision)
908 if((*it).first>1-QUADRATIC_PLANAR::_precision)
915 std::vector<int> tmpp2(tmpp.size()+2);
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++)
924 edgesThis.push_back(tmpp2[i]);
925 edgesThis.push_back(tmpp2[i+1]);