Salome HOME
Merge branch 'V9_2_2_BR'
[modules/yacs.git] / src / engine / AbstractPoint.cxx
1 // Copyright (C) 2015-2019  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
20 #include "AbstractPoint.hxx"
21 #include "LinkedBlocPoint.hxx"
22 #include "ForkBlocPoint.hxx"
23 #include "SetOfPoints.hxx"
24 #include "Node.hxx"
25
26 using namespace YACS::ENGINE;
27
28 AbstractPoint::~AbstractPoint()
29 {
30 }
31
32 AbstractPoint *AbstractPoint::getGodFather()
33 {
34   if(_father==0)
35     return this;
36   else
37     return _father->getGodFather();
38 }
39
40 bool AbstractPoint::isBegin()
41 {
42   Node *beg(getFirstNode());
43   InGate *ing(beg->getInGate());
44   return ing->getBackLinks().empty();
45 }
46
47 bool AbstractPoint::isLast()
48 {
49   Node *endd(getLastNode());
50   OutGate *oug(endd->getOutGate());
51   return oug->edSetInGate().empty();
52 }
53
54 bool AbstractPoint::isSimplyLinkedBeforeAfter(BlocPoint *sop)
55 {
56   Node *beg(getFirstNode()),*endd(getLastNode());
57   return isSimplyLinkedBefore(sop,beg) && isSimplyLinkedAfter(sop,endd);
58 }
59
60 bool AbstractPoint::isSimplyLinkedAfterNullBefore(BlocPoint *sop)
61 {
62   Node *beg(getFirstNode()),*endd(getLastNode());
63   return IsNoLinksBefore(beg) && isSimplyLinkedAfter(sop,endd);
64 }
65
66 bool AbstractPoint::isSimplyLinkedBeforeNullAfter(BlocPoint *sop)
67 {
68   Node *beg(getFirstNode()),*endd(getLastNode());
69   return IsNoLinksAfter(endd) && isSimplyLinkedBefore(sop,beg);
70 }
71
72 /*!
73  * precondition : isSimplyLinkedBeforeAfter must return true on \a this.
74  */
75 LinkedBlocPoint *AbstractPoint::tryAsLink(BlocPoint *sop)
76 {
77   Node *bb(getFirstNode()),*ee(getLastNode());
78   std::list<AbstractPoint *> l; l.push_back(this);
79   AbstractPoint *cur2(0);
80   //
81   cur2=sop->getNodeB4(bb);
82   while(cur2)
83     {
84       Node *cur3(cur2->getFirstNode());
85       if(cur2->isSimplyLinkedBeforeAfter(sop))
86         {
87           l.push_front(cur2);
88           cur2=sop->getNodeB4(cur3);
89           continue;
90         }
91       else if(IsGatherB4Ext(cur3) && isSimplyLinkedAfter(sop,cur2->getLastNode()))
92         {
93           l.push_front(cur2);
94           break;
95         }
96       else
97         break;
98     }
99   //
100   cur2=sop->getNodeAfter(ee);
101   while(cur2)
102     {
103       Node *cur3(cur2->getLastNode());
104       if(cur2->isSimplyLinkedBeforeAfter(sop))
105         {
106           l.push_back(cur2);
107           cur2=sop->getNodeAfter(cur3);
108           continue;
109         }
110       else if(IsScatterAfterExt(cur3) && isSimplyLinkedBefore(sop,cur2->getFirstNode()))
111         {
112           l.push_back(cur2);
113           break;
114         }
115       else
116         break;
117     }
118   if(l.size()>1)
119     {
120       return new LinkedBlocPoint(l,getFather());
121     }
122   else
123     return 0;
124 }
125
126 /*!
127  * precondition : isSimplyLinkedBeforeAfter must return true on \a this.
128  */
129 ForkBlocPoint *AbstractPoint::tryAsFork(BlocPoint *sop)
130 {
131   Node *bb(GetNodeB4(getFirstNode())),*ee(GetNodeAfter(getLastNode()));
132   AbstractPoint *bb2(sop->findPointWithNode(bb)),*ee2(sop->findPointWithNode(ee));
133   //
134   const std::list<AbstractPoint *>& lp(sop->getListOfPoints());
135   std::list<AbstractPoint *> l; l.push_back(this);
136   for(std::list<AbstractPoint *>::const_iterator it=lp.begin();it!=lp.end();it++)
137     {
138       if(*it==this)
139         continue;
140       Node *curFirst((*it)->getFirstNode()),*curEnd((*it)->getLastNode());
141       if(!IsSimplyLinkedBeforeExt(curFirst) || !IsSimplyLinkedAfterExt(curEnd))
142         continue;
143       Node *curbb(GetNodeB4(curFirst)),*curee(GetNodeAfter(curEnd));
144       AbstractPoint *bb3(sop->findPointWithNode(curbb)),*ee3(sop->findPointWithNode(curee));
145       if(bb2==bb3 && ee2==ee3)
146         l.push_back(*it);
147     }
148   if(l.size()>1)
149     {
150       return new ForkBlocPoint(l,getFather());
151     }
152   else
153     return 0;
154 }
155
156 ForkBlocPoint *AbstractPoint::tryAsForkBis(BlocPoint *sop)
157 {
158   Node *bb(GetNodeB4(getFirstNode())),*ee(GetNodeAfter(getLastNode()));
159   AbstractPoint *ee2(sop->findPointWithNode(ee));
160   //
161   const std::list<AbstractPoint *>& lp(sop->getListOfPoints());
162   std::list<AbstractPoint *> l; l.push_back(this);
163   for(std::list<AbstractPoint *>::const_iterator it=lp.begin();it!=lp.end();it++)
164     {
165       if(*it==this)
166         continue;
167       Node *curFirst((*it)->getFirstNode()),*curEnd((*it)->getLastNode());
168       if(!IsNoLinksBefore(curFirst) || !IsSimplyLinkedAfterExt(curEnd))
169         continue;
170       Node *curee(GetNodeAfter(curEnd));
171       AbstractPoint *ee3(sop->findPointWithNode(curee));
172       if(ee2==ee3)
173         l.push_back(*it);
174     }
175   if(l.size()>1)
176     {
177       return new ForkBlocPoint(l,getFather());
178     }
179   else
180     return 0;
181 }
182
183 ForkBlocPoint *AbstractPoint::tryAsForkTer(BlocPoint *sop)
184 {
185   Node *bb(GetNodeB4(getFirstNode())),*ee(GetNodeAfter(getLastNode()));
186   AbstractPoint *bb2(sop->findPointWithNode(bb));
187   //
188   const std::list<AbstractPoint *>& lp(sop->getListOfPoints());
189   std::list<AbstractPoint *> l; l.push_back(this);
190   for(std::list<AbstractPoint *>::const_iterator it=lp.begin();it!=lp.end();it++)
191     {
192       if(*it==this)
193         continue;
194       Node *curFirst((*it)->getFirstNode()),*curEnd((*it)->getLastNode());
195       if(!IsSimplyLinkedBeforeExt(curFirst) || !IsNoLinksAfter(curEnd))
196         continue;
197       Node *curbb(GetNodeB4(curFirst));
198       AbstractPoint *bb3(sop->findPointWithNode(curbb));
199       if(bb2==bb3)
200         l.push_back(*it);
201     }
202   if(l.size()>1)
203     {
204       return new ForkBlocPoint(l,getFather());
205     }
206   else
207     return 0;
208 }
209
210 bool AbstractPoint::IsGatherB4Ext(Node *node)
211 {
212   InGate *ing(node->getInGate());
213   return ing->getBackLinks().size()!=1;
214 }
215
216 bool AbstractPoint::isSimplyLinkedAfter(BlocPoint *sop, Node *node)
217 {
218   OutGate *oug(node->getOutGate());
219   std::list<InGate *> ings(oug->edSetInGate());
220   if(ings.size()==1)
221     return true;
222   if(ings.size()==0)
223     return false;
224   AbstractPoint *dummy=0;
225   return IsCommonDirectSonOf(sop,ings,dummy);
226 }
227
228 bool AbstractPoint::IsSimplyLinkedAfterExt(Node *node)
229 {
230   OutGate *oug(node->getOutGate());
231   return oug->edSetInGate().size()<=1;
232 }
233
234 bool AbstractPoint::IsScatterAfterExt(Node *node)
235 {
236   OutGate *oug(node->getOutGate());
237   return oug->edSetInGate().size()!=1;
238 }
239
240 bool AbstractPoint::isSimplyLinkedBefore(BlocPoint *sop, Node *node)
241 {
242   InGate *ing(node->getInGate());
243   std::list<OutGate *> outgs(ing->getBackLinks());
244   if(outgs.size()==1)
245     return true;
246   if(outgs.size()==0)
247     return false;
248   AbstractPoint *dummy=0;
249   return IsCommonDirectSonOf(sop,outgs,dummy);
250 }
251
252 bool AbstractPoint::IsSimplyLinkedBeforeExt(Node *node)
253 {
254   InGate *ing(node->getInGate());
255   return ing->getBackLinks().size()<=1;
256 }
257
258 bool AbstractPoint::IsNoLinksBefore(Node *node)
259 {
260   InGate *ing(node->getInGate());
261   return ing->getBackLinks().size()==0;
262 }
263
264 bool AbstractPoint::IsNoLinksAfter(Node *node)
265 {
266   OutGate *oug(node->getOutGate());
267   return oug->edSetInGate().size()==0;
268 }
269
270 Node *AbstractPoint::GetNodeB4(Node *node)
271 {
272   InGate *ing(node->getInGate());
273   std::list<OutGate *> bl(ing->getBackLinks());
274   if(bl.size()>1)
275     throw Exception("AbstractPoint::GetNodeB4 : precond not OK !");
276   if(bl.size()==0)
277     return 0;
278   return bl.front()->getNode();
279 }
280
281 Node *AbstractPoint::GetNodeAfter(Node *node)
282 {
283   OutGate *oug(node->getOutGate());
284   std::list<InGate *> fl(oug->edSetInGate());
285   if(fl.size()>1)
286     throw Exception("AbstractPoint::GetNodeAfter : precond not OK !");
287   if(fl.size()==0)
288     return 0;
289   return (*fl.begin())->getNode();
290 }
291
292 AbstractPoint *AbstractPoint::GetDirectSonOf(AbstractPoint *refFather, AbstractPoint *sonOrLittleSon)
293 {
294   AbstractPoint *curFath(sonOrLittleSon->getFather()),*cur(sonOrLittleSon);
295   while(curFath && curFath!=refFather)
296     {
297       cur=curFath;
298       curFath=cur->getFather();
299     }
300   if(!curFath)
301     throw YACS::Exception("AbstractPoint::GetDirectSonOf : not in the same family !");
302   return cur;
303 }
304
305 bool AbstractPoint::IsCommonDirectSonOf(AbstractPoint *refFather, const std::list<OutGate *>& outgs, AbstractPoint *&ret)
306 {
307   if(outgs.size()<1)
308     throw YACS::Exception("AbstractPoint::GetCommonDirectSonOf1 : not enough !");
309   std::list<OutGate *>::const_iterator it(outgs.begin());
310   OutGate *ref(*(it++));
311   AbstractPoint *ref2(GetDirectSonOf(refFather,refFather->findPointWithNode(ref->getNode())));
312   for(;it!=outgs.end();it++)
313     {
314       if(!ref2->contains((*it)->getNode()))
315         return false;
316     }
317   ret=ref2;
318   return true;
319 }
320
321 bool AbstractPoint::IsCommonDirectSonOf(AbstractPoint *refFather, const std::list<InGate *>& ings, AbstractPoint *&ret)
322 {
323   if(ings.size()<1)
324     throw YACS::Exception("AbstractPoint::GetCommonDirectSonOf2 : not enough !");
325   std::list<InGate *>::const_iterator it(ings.begin());
326   InGate *ref(*(it++));
327   AbstractPoint *ref2(GetDirectSonOf(refFather,refFather->findPointWithNode(ref->getNode())));
328   for(;it!=ings.end();it++)
329     {
330       if(!ref2->contains((*it)->getNode()))
331         return false;
332     }
333   ret=ref2;
334   return true;
335 }