1 // Copyright (C) 2015-2019 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, or (at your option) any later version.
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
20 #include "AbstractPoint.hxx"
21 #include "LinkedBlocPoint.hxx"
22 #include "ForkBlocPoint.hxx"
23 #include "NotSimpleCasePoint.hxx"
24 #include "SetOfPoints.hxx"
25 #include "BagPoint.hxx"
26 #include "ElementaryPoint.hxx"
32 using namespace YACS::ENGINE;
34 AbstractPoint::~AbstractPoint()
38 AbstractPoint *AbstractPoint::getGodFather()
43 return _father->getGodFather();
46 bool AbstractPoint::isBegin()
48 Node *beg(getFirstNode());
49 InGate *ing(beg->getInGate());
50 return ing->getBackLinks().empty();
53 bool AbstractPoint::isLast()
55 Node *endd(getLastNode());
56 OutGate *oug(endd->getOutGate());
57 return oug->edSetInGate().empty();
60 bool AbstractPoint::isSimplyLinkedBeforeAfter(BlocPoint *sop)
62 Node *beg(getFirstNode()),*endd(getLastNode());
63 return isSimplyLinkedBefore(sop,beg) && isSimplyLinkedAfter(sop,endd);
66 bool AbstractPoint::isSimplyLinkedAfterNullBefore(BlocPoint *sop)
68 Node *beg(getFirstNode()),*endd(getLastNode());
69 return IsNoLinksBefore(beg) && isSimplyLinkedAfter(sop,endd);
72 bool AbstractPoint::isSimplyLinkedBeforeNullAfter(BlocPoint *sop)
74 Node *beg(getFirstNode()),*endd(getLastNode());
75 return IsNoLinksAfter(endd) && isSimplyLinkedBefore(sop,beg);
79 * precondition : isSimplyLinkedBeforeAfter must return true on \a this.
81 LinkedBlocPoint *AbstractPoint::tryAsLink(BlocPoint *sop)
83 Node *bb(getFirstNode()),*ee(getLastNode());
84 std::list<AbstractPoint *> l; l.push_back(this);
85 AbstractPoint *cur2(0);
87 cur2=sop->getNodeB4(bb);
90 if(dynamic_cast<NotSimpleCasePoint *>(cur2))
92 Node *cur3(cur2->getFirstNode());
93 if(cur2->isSimplyLinkedBeforeAfter(sop))
96 cur2=sop->getNodeB4(cur3);
99 else if(IsGatherB4Ext(cur3) && isSimplyLinkedAfter(sop,cur2->getLastNode()))
108 cur2=sop->getNodeAfter(ee);
111 if(dynamic_cast<NotSimpleCasePoint *>(cur2))
113 Node *cur3(cur2->getLastNode());
114 if(cur2->isSimplyLinkedBeforeAfter(sop))
117 cur2=sop->getNodeAfter(cur3);
120 else if(IsScatterAfterExt(cur3) && isSimplyLinkedBefore(sop,cur2->getFirstNode()))
130 return new LinkedBlocPoint(l,getFather());
137 * precondition : isSimplyLinkedBeforeAfter must return true on \a this.
139 ForkBlocPoint *AbstractPoint::tryAsFork(BlocPoint *sop)
141 Node *bb(GetNodeB4(getFirstNode())),*ee(GetNodeAfter(getLastNode()));
142 AbstractPoint *bb2(sop->findPointWithNode(bb)),*ee2(sop->findPointWithNode(ee));
144 const std::list<AbstractPoint *>& lp(sop->getListOfPoints());
145 std::list<AbstractPoint *> l; l.push_back(this);
146 for(std::list<AbstractPoint *>::const_iterator it=lp.begin();it!=lp.end();it++)
150 if(dynamic_cast<NotSimpleCasePoint *>(*it))
152 Node *curFirst((*it)->getFirstNode()),*curEnd((*it)->getLastNode());
153 if(!IsSimplyLinkedBeforeExt(curFirst) || !IsSimplyLinkedAfterExt(curEnd))
155 Node *curbb(GetNodeB4(curFirst)),*curee(GetNodeAfter(curEnd));
156 AbstractPoint *bb3(sop->findPointWithNode(curbb)),*ee3(sop->findPointWithNode(curee));
157 if(bb2==bb3 && ee2==ee3)
162 return new ForkBlocPoint(l,getFather());
168 ForkBlocPoint *AbstractPoint::tryAsForkBis(BlocPoint *sop)
170 Node *bb(GetNodeB4(getFirstNode())),*ee(GetNodeAfter(getLastNode()));
171 AbstractPoint *ee2(sop->findPointWithNode(ee));
173 const std::list<AbstractPoint *>& lp(sop->getListOfPoints());
174 std::list<AbstractPoint *> l; l.push_back(this);
175 for(std::list<AbstractPoint *>::const_iterator it=lp.begin();it!=lp.end();it++)
179 if(dynamic_cast<NotSimpleCasePoint *>(*it))
181 Node *curFirst((*it)->getFirstNode()),*curEnd((*it)->getLastNode());
182 if(!IsNoLinksBefore(curFirst) || !IsSimplyLinkedAfterExt(curEnd))
184 Node *curee(GetNodeAfter(curEnd));
185 AbstractPoint *ee3(sop->findPointWithNode(curee));
191 return new ForkBlocPoint(l,getFather());
197 ForkBlocPoint *AbstractPoint::tryAsForkTer(BlocPoint *sop)
199 Node *bb(GetNodeB4(getFirstNode())),*ee(GetNodeAfter(getLastNode()));
200 AbstractPoint *bb2(sop->findPointWithNode(bb));
202 const std::list<AbstractPoint *>& lp(sop->getListOfPoints());
203 std::list<AbstractPoint *> l; l.push_back(this);
204 for(std::list<AbstractPoint *>::const_iterator it=lp.begin();it!=lp.end();it++)
208 if(dynamic_cast<NotSimpleCasePoint *>(*it))
210 Node *curFirst((*it)->getFirstNode()),*curEnd((*it)->getLastNode());
211 if(!IsSimplyLinkedBeforeExt(curFirst) || !IsNoLinksAfter(curEnd))
213 Node *curbb(GetNodeB4(curFirst));
214 AbstractPoint *bb3(sop->findPointWithNode(curbb));
220 return new ForkBlocPoint(l,getFather());
228 class Visitor1 : public YACS::ENGINE::PointVisitor
231 Visitor1(std::map< std::string, std::tuple< ElementaryPoint *, Node *, std::shared_ptr<Bloc> > > *m):_m(m) { }
232 void beginForkBlocPoint(ForkBlocPoint *pt) { }
233 void endForkBlocPoint(ForkBlocPoint *pt) { }
234 void beginLinkedBlocPoint(LinkedBlocPoint *pt) { }
235 void endLinkedBlocPoint(LinkedBlocPoint *pt) { }
236 void beginElementaryPoint(ElementaryPoint *pt)
238 std::string nodeName(pt->getNodeName());
239 auto it(_m->find(nodeName));
242 (*_m)[nodeName] = std::tuple< ElementaryPoint *, Node *, std::shared_ptr<Bloc> >(pt,pt->getNode(),std::make_shared<Bloc>(nodeName));
245 void endElementaryPoint(ElementaryPoint *pt) { }
246 void beginNotSimpleCasePoint(NotSimpleCasePoint *pt) { }
247 void endNotSimpleCasePoint(NotSimpleCasePoint *pt) { }
249 std::map< std::string, std::tuple< ElementaryPoint *, Node *, std::shared_ptr<Bloc> > > *_m;
253 * Feed m with all ElementaryPoints inside \a ptToBeRewired.
255 void AbstractPoint::FeedData(AbstractPoint *ptToBeRewired, std::map< std::string, std::tuple< ElementaryPoint *, Node *, std::shared_ptr<Bloc> > > *m)
258 ptToBeRewired->accept(&vis);
262 * Feed m with all ElementaryPoints inside \a ptsToBeRewired.
264 void AbstractPoint::FeedData(const std::list<AbstractPoint *>& ptsToBeRewired, std::map< std::string, std::tuple< ElementaryPoint *, Node *, std::shared_ptr<Bloc> > > *m)
266 for(auto it : ptsToBeRewired)
270 bool containsPtsToKill(const std::vector<AbstractPoint *>& ptsToKill, Node *node)
272 for(auto it : ptsToKill)
273 if(it->contains(node))
279 * This method go throw all ElementaryPoints of \a m.
280 * For each ElementaryPoint change the Node instance underneath. And then create links between those new Node by excluding all links going whose destination :
281 * - is inside \a ptToKill
282 * - is not refered by \a m
284 * CF links of old nodes are NOT touched for unrewire phase.
285 * Typically all ElementaryPoints inside \a ptToKill are NOT into \a m.
287 void AbstractPoint::Rewire(const std::vector<AbstractPoint *>& ptsToKill, std::map< std::string, std::tuple< ElementaryPoint *, Node *, std::shared_ptr<Bloc> > > *m)
291 ElementaryPoint *pt(std::get<0>(it.second));
292 Node *node(std::get<1>(it.second));
293 auto newNode(std::get<2>(it.second).get());
294 pt->setNode(newNode);
298 ElementaryPoint *pt(std::get<0>(it.second));
299 Node *node(std::get<1>(it.second));
300 auto newNode(std::get<2>(it.second).get());
301 if(containsPtsToKill(ptsToKill,newNode))
303 for(auto it2 : node->getOutGate()->edSetInGate())
305 Node *nodeFwd(it2->getNode());
306 std::string nodeFwdName(nodeFwd->getName());
307 auto it3(m->find(nodeFwdName));
310 Node *nodeFwdNew = std::get<2>(it3->second).get();
311 if(!containsPtsToKill(ptsToKill,newNode))
313 newNode->getOutGate()->edAddInGate(nodeFwdNew->getInGate());
316 // node after nodeFwd is not in m fall into \a ptToKill
320 // node after nodeFwd is not in m. Typically because nodeFwd has not been put in m
321 // concretely : do not link incoming links to Node * inside ptToKill
327 * Unrewire consists into replacing newly created nodes into old one in ElementaryPoints contained in m.
328 * As CF links of old ENGINE::Node * has not be touched the CF graph is the same.
330 void AbstractPoint::UnRewire(std::map< std::string, std::tuple< ElementaryPoint *, Node *, std::shared_ptr<Bloc> > >& m)
334 ElementaryPoint *pt(std::get<0>(it.second));
335 Node *node(std::get<1>(it.second));
340 void AbstractPoint::Display(std::map< std::string, std::tuple< ElementaryPoint *, Node *, std::shared_ptr<Bloc> > > *m)
344 ElementaryPoint *pt(std::get<0>(it.second));
345 auto newNode(pt->getNode());
346 for(auto it2 : newNode->getOutGate()->edSetInGate())
348 std::cerr << pt->getNodeName() << " -> " << it2->getNode()->getName() << " " << newNode->typeName() << std::endl;
354 * This methods tries to deal with \a sop that can t be considered as a composite of Link, Fork.
356 * Do do so, this methods tries to exclude \a this from \a sop and then analyze if the graph can be decomposited into Links and Forks. If yes \a somethingDone is set to true and \a nodes is updated in consequence.
358 * If the algorithm fails \a nodes are let untouched and \a somethingDone is let false.
361 void AbstractPoint::TryAsNotSimpleCase(AbstractPoint *father, const std::vector<AbstractPoint *>& ptsToKill, std::list<AbstractPoint *>& nodes, bool& somethingDone)
363 std::list<AbstractPoint *> lp2;
366 if(std::find(ptsToKill.cbegin(),ptsToKill.cend(),it)==ptsToKill.cend())
367 lp2.push_back(it->deepCopy(nullptr));
369 BagPoint *tmp(new BagPoint(lp2,nullptr));
372 SetOfPoints sopTest(tmp);
373 std::map< std::string, std::tuple< ElementaryPoint *, Node *, std::shared_ptr<Bloc> > > m;
375 Rewire(ptsToKill,&m);
378 sopTest.basicSimplify();
380 catch(YACS::Exception& ex)
381 {// By removing elements in ptsToKill from this impossible to have a classical case -> un rewire to rollback nodes state
385 AbstractPoint *pt(sopTest.getUniqueAndReleaseIt());
386 pt->setFather(father);
389 if(std::find(ptsToKill.cbegin(),ptsToKill.cend(),it)==ptsToKill.cend())
393 for(auto it : ptsToKill)
395 std::list<AbstractPoint *> l; l.push_back(it);
396 nodes.push_back( new NotSimpleCasePoint(l,father) );
398 somethingDone = true;
401 bool AbstractPoint::IsGatherB4Ext(Node *node)
403 InGate *ing(node->getInGate());
404 return ing->getBackLinks().size()!=1;
407 bool AbstractPoint::isSimplyLinkedAfter(BlocPoint *sop, Node *node)
409 OutGate *oug(node->getOutGate());
410 std::list<InGate *> ings(oug->edSetInGate());
415 AbstractPoint *dummy=0;
416 return IsCommonDirectSonOf(sop,ings,dummy);
419 bool AbstractPoint::IsSimplyLinkedAfterExt(Node *node)
421 OutGate *oug(node->getOutGate());
422 return oug->edSetInGate().size()<=1;
425 bool AbstractPoint::IsScatterAfterExt(Node *node)
427 OutGate *oug(node->getOutGate());
428 return oug->edSetInGate().size()!=1;
431 bool AbstractPoint::isSimplyLinkedBefore(BlocPoint *sop, Node *node)
433 InGate *ing(node->getInGate());
434 std::list<OutGate *> outgs(ing->getBackLinks());
439 AbstractPoint *dummy=0;
440 return IsCommonDirectSonOf(sop,outgs,dummy);
443 bool AbstractPoint::IsSimplyLinkedBeforeExt(Node *node)
445 InGate *ing(node->getInGate());
446 return ing->getBackLinks().size()<=1;
449 bool AbstractPoint::IsNoLinksBefore(Node *node)
451 InGate *ing(node->getInGate());
452 return ing->getBackLinks().size()==0;
455 bool AbstractPoint::IsNoLinksAfter(Node *node)
457 OutGate *oug(node->getOutGate());
458 return oug->edSetInGate().size()==0;
461 Node *AbstractPoint::GetNodeB4(Node *node)
463 InGate *ing(node->getInGate());
464 std::list<OutGate *> bl(ing->getBackLinks());
466 throw Exception("AbstractPoint::GetNodeB4 : precond not OK !");
469 return bl.front()->getNode();
472 Node *AbstractPoint::GetNodeAfter(Node *node)
474 OutGate *oug(node->getOutGate());
475 std::list<InGate *> fl(oug->edSetInGate());
477 throw Exception("AbstractPoint::GetNodeAfter : precond not OK !");
480 return (*fl.begin())->getNode();
483 AbstractPoint *AbstractPoint::GetDirectSonOf(AbstractPoint *refFather, AbstractPoint *sonOrLittleSon)
486 throw YACS::Exception("AbstractPoint::GetDirectSonOf : sonOrLittleSon is null !");
487 AbstractPoint *curFath(sonOrLittleSon->getFather()),*cur(sonOrLittleSon);
488 while(curFath && curFath!=refFather)
491 curFath=cur->getFather();
494 throw YACS::Exception("AbstractPoint::GetDirectSonOf : not in the same family !");
498 bool AbstractPoint::IsCommonDirectSonOf(AbstractPoint *refFather, const std::list<OutGate *>& outgs, AbstractPoint *&ret)
501 throw YACS::Exception("AbstractPoint::GetCommonDirectSonOf1 : not enough !");
502 std::list<OutGate *>::const_iterator it(outgs.begin());
503 OutGate *ref(*(it++));
504 AbstractPoint *ref2(GetDirectSonOf(refFather,refFather->findPointWithNode(ref->getNode())));
505 for(;it!=outgs.end();it++)
507 if(!ref2->contains((*it)->getNode()))
514 bool AbstractPoint::IsCommonDirectSonOf(AbstractPoint *refFather, const std::list<InGate *>& ings, AbstractPoint *&ret)
517 throw YACS::Exception("AbstractPoint::GetCommonDirectSonOf2 : not enough !");
518 std::list<InGate *>::const_iterator it(ings.begin());
519 InGate *ref(*(it++));
520 AbstractPoint *ref2(GetDirectSonOf(refFather,refFather->findPointWithNode(ref->getNode())));
521 for(;it!=ings.end();it++)
523 if(!ref2->contains((*it)->getNode()))