Version: 8.3.0
LinkMatrix.cxx
Go to the documentation of this file.
1 // Copyright (C) 2006-2016 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 "LinkMatrix.hxx"
21 #include "Scene.hxx"
24 #include "SceneHeaderItem.hxx"
25 #include "SceneHeaderNodeItem.hxx"
26 #include "SceneCtrlPortItem.hxx"
27 #include "SceneLinkItem.hxx"
28 #include "QtGuiContext.hxx"
29 #include "InPort.hxx"
30 #include "OutPort.hxx"
31 #include "Resource.hxx"
32 
33 #include <cmath>
34 
35 //#define _DEVDEBUG_
36 #include "YacsTrace.hxx"
37 
38 using namespace std;
39 using namespace YACS::ENGINE;
40 using namespace YACS::HMI;
41 
42 double LNode::distance(const LNode& o) const
43 {
44  int dx = _x -o._x;
45  int dy = _y -o._y;
46  return sqrt(double(dx*dx +dy*dy));
47 }
48 
49 
50 LinkMatrix::LinkMatrix(SceneComposedNodeItem *bloc): _bloc(bloc)
51 {
52  _im=0;
53  _jm=0;
54  _pas=10;
55  _sxm.clear();
56  _sym.clear();
57  _xm.clear();
58  _ym.clear();
59  _x2i.clear();
60  _y2j.clear();
61  _cost.clear();
63 }
64 
66 {
67 }
68 
70 {
72  explore(_bloc); // --- define the boundaries _xm[i] and _ym[j]
74  _im = _sxm.size();
75  _xm.resize(_im);
76  DEBTRACE("_sxm.size()=" << _im);
77  int i =0;
78  for(std::set<double>::iterator it = _sxm.begin(); it != _sxm.end(); ++it)
79  {
80  _xm[i] = *it;
81  _x2i[*it] = i;
82  DEBTRACE("_xm[" << i << "] = " << _xm[i]);
83  i++;
84  }
85  _jm = _sym.size();
86  _ym.resize(_jm);
87  DEBTRACE("_sym.size()=" << _jm);
88  i =0;
89  for(std::set<double>::iterator it = _sym.begin(); it != _sym.end(); ++it)
90  {
91  _ym[i] = *it;
92  _y2j[*it] = i;
93  DEBTRACE("_ym[" << i << "] = " << _ym[i]);
94  i++;
95  }
96  _cost.resize(_im*_jm);
97  for (int ij=0; ij < _im*_jm; ij++)
98  _cost[ij] = 1; // --- set the _cost matrix open everywhere (no obstacles)
99  explore(_bloc, true); // --- fill the cells cost(i,j) with obstacles
100 
101  for (int j=0; j<_jm; j++)
102  {
103  char* m = new char[_im+1];
104  for (int i=0; i<_im; i++)
105  if (cost(i,j))
106  m[i] = ' ';
107  else
108  m[i] = 'X';
109  m[_im] = 0;
110  DEBTRACE(m);
111  delete [] m;
112  }
113 }
114 
116 {
118  SceneItem* item = _context->_mapOfSceneItem[subDP];
119  QRectF bb = (item->mapToScene(item->boundingRect())).boundingRect();
120  qreal xp = bb.right();
121  qreal yp = (bb.top() + bb.bottom())*0.5;
122  DEBTRACE("xp,yp:"<<xp<<","<<yp);
123  int ifrom = -1;
124  for (int i=0; i<_im-1; i++)
125  if (_xm[i+1] >= xp && xp > _xm[i])
126  {
127  ifrom = i;
128  break;
129  }
130  int jfrom = -1;
131  for (int j=0; j<_jm-1; j++)
132  if (_ym[j+1] >= yp && yp > _ym[j])
133  {
134  jfrom = j;
135  break;
136  }
137  //if ifrom or jfrom == -1 the port is outside the matrix
138  if(ifrom < 0 || jfrom < 0)return pair<int,int>(ifrom,jfrom);
139  while (ifrom < _im && !cost(ifrom,jfrom)) ifrom++; // --- from point is inside an obstacle
140 
141  return pair<int,int>(ifrom,jfrom);
142 }
143 
145 {
146  SubjectNode* subNode = _context->_mapOfSubjectNode[outp->getNode()];
147  SceneNodeItem* itemNode = dynamic_cast<SceneNodeItem*>(_context->_mapOfSceneItem[subNode]);
148  YASSERT(itemNode);
149  SceneHeaderNodeItem* itemHeader = dynamic_cast<SceneHeaderNodeItem*>(itemNode->getHeader());
150  YASSERT(itemHeader);
151  SceneCtrlPortItem *item = itemHeader->getCtrlOutPortItem();
152  YASSERT(item);
153  QRectF bb = (item->mapToScene(item->boundingRect())).boundingRect();
154  qreal xp = bb.right();
155  qreal yp = (bb.top() + bb.bottom())*0.5;
156  DEBTRACE("xp,yp:"<<xp<<","<<yp);
157  int ifrom = -1;
158  for (int i=0; i<_im-1; i++)
159  if (_xm[i+1] >= xp && xp > _xm[i])
160  {
161  ifrom = i;
162  break;
163  }
164  int jfrom = -1;
165  for (int j=0; j<_jm-1; j++)
166  if (_ym[j+1] >= yp && yp > _ym[j])
167  {
168  jfrom = j;
169  break;
170  }
171  //if ifrom or jfrom == -1 the port is outside the matrix
172  if(ifrom < 0 || jfrom < 0)return pair<int,int>(ifrom,jfrom);
173  while (ifrom < _im && !cost(ifrom,jfrom)) ifrom++; // --- from point is inside an obstacle
174 
175  return pair<int,int>(ifrom,jfrom);
176 }
177 
178 std::pair<int,int> LinkMatrix::cellTo(YACS::ENGINE::InPort* inp)
179 {
181  SceneItem* item = _context->_mapOfSceneItem[subDP];
182  QRectF bb = (item->mapToScene(item->boundingRect())).boundingRect();
183  qreal xp = bb.left();
184  qreal yp = (bb.top() + bb.bottom())*0.5;
185  DEBTRACE("xp,yp:"<<xp<<","<<yp);
186  int ito = -1;
187  for (int i=0; i<_im-1; i++)
188  if (_xm[i+1] >= xp && xp > _xm[i])
189  {
190  ito = i;
191  break;
192  }
193  int jto = -1;
194  for (int j=0; j<_jm-1; j++)
195  if (_ym[j+1] >= yp && yp > _ym[j])
196  {
197  jto = j;
198  break;
199  }
200  //if ito or jto == -1 the port is outside the matrix
201  if(ito < 0 || jto < 0)return pair<int,int>(ito,jto);
202  while (ito >0 && !cost(ito,jto)) ito--; // --- to point is inside an obstacle
203 
204  return pair<int,int>(ito,jto);
205 }
206 
207 std::pair<int,int> LinkMatrix::cellTo(YACS::ENGINE::InGate* inp)
208 {
209  SubjectNode* subNode = _context->_mapOfSubjectNode[inp->getNode()];
210  SceneNodeItem* itemNode = dynamic_cast<SceneNodeItem*>(_context->_mapOfSceneItem[subNode]);
211  YASSERT(itemNode);
212  SceneHeaderNodeItem* itemHeader = dynamic_cast<SceneHeaderNodeItem*>(itemNode->getHeader());
213  YASSERT(itemHeader);
214  SceneCtrlPortItem *item = itemHeader->getCtrlInPortItem();
215  YASSERT(item);
216  QRectF bb = (item->mapToScene(item->boundingRect())).boundingRect();
217  qreal xp = bb.left();
218  qreal yp = (bb.top() + bb.bottom())*0.5;
219  DEBTRACE("xp,yp:"<<xp<<","<<yp);
220  int ito = -1;
221  for (int i=0; i<_im-1; i++)
222  if (_xm[i+1] >= xp && xp > _xm[i])
223  {
224  ito = i;
225  break;
226  }
227  int jto = -1;
228  for (int j=0; j<_jm-1; j++)
229  if (_ym[j+1] >= yp && yp > _ym[j])
230  {
231  jto = j;
232  break;
233  }
234  //if ito or jto == -1 the port is outside the matrix
235  if(ito < 0 || jto < 0)return pair<int,int>(ito,jto);
236  while (ito > 0 && !cost(ito,jto)) ito--; // --- to point is inside an obstacle
237 
238  return pair<int,int>(ito,jto);
239 }
240 
242 {
243  list<linkdef> alist;
244  map<pair<Node*, Node*>, SubjectControlLink*>::const_iterator it;
245  for (it = _context->_mapOfSubjectControlLink.begin();
246  it != _context->_mapOfSubjectControlLink.end(); ++it)
247  {
248  linkdef ali;
249  pair<Node*, Node*> outin = it->first;
250  SubjectControlLink* sub = it->second;
251  ali.from = cellFrom(outin.first->getOutGate());
252  ali.to = cellTo(outin.second->getInGate());
253  ali.item = dynamic_cast<SceneLinkItem*>(_context->_mapOfSceneItem[sub]);
254  alist.push_back(ali);
255  DEBTRACE("from("<<ali.from.first<<","<<ali.from.second
256  <<") to ("<<ali.to.first<<","<<ali.to.second
257  <<") " << ali.item->getLabel().toStdString());
258  }
259  return alist;
260 }
261 
263 {
264  list<linkdef> alist;
265  map<pair<OutPort*, InPort*>, SubjectLink*>::const_iterator it;
266  for (it = _context->_mapOfSubjectLink.begin();
267  it != _context->_mapOfSubjectLink.end(); ++it)
268  {
269  linkdef ali;
270  pair<OutPort*, InPort*> outin = it->first;
271  SubjectLink* sub = it->second;
272  ali.from = cellFrom(outin.first);
273  ali.to = cellTo(outin.second);
274  ali.item = dynamic_cast<SceneLinkItem*>(_context->_mapOfSceneItem[sub]);
275  alist.push_back(ali);
276  DEBTRACE("from("<<ali.from.first<<","<<ali.from.second
277  <<") to ("<<ali.to.first<<","<<ali.to.second
278  <<") " << ali.item->getLabel().toStdString());
279  }
280  return alist;
281 }
282 
284 {
285  DEBTRACE("LinkMatrix::getPath " << lnp.size());
286  LinkPath lp;
287  lp.clear();
288  int dim = lnp.size();
289  //use a random coefficient between 0.25 and 0.75 to try to separate links
290  double coef=-0.25+rand()%101*0.005;
291  coef=0.5 + coef* Resource::link_separation_weight/10.;
292  LNodePath::const_iterator it = lnp.begin();
293  for (int k=0; k<dim; k++)
294  {
295  int i = it->getX();
296  int j = it->getY();
297  DEBTRACE("i, j: " << i << " " << j << " Xmax, Ymax: " << _im << " " << _jm);
298  linkPoint a;
299 
300  if ( (i+1)==_im ) {
301  a.x = _xm[i];
302  } else {
303  a.x = coef*_xm[i] + (1.-coef)*_xm[i+1];
304  };
305 
306  if ( (j+1)==_jm ) {
307  a.y = _ym[j];
308  } else {
309  a.y = coef*_ym[j] + (1.-coef)*_ym[j+1];
310  };
311 
312  lp.push_back(a);
313  DEBTRACE(a.x << " " << a.y);
314  ++it;
315  }
316  return lp;
317 }
318 
320 {
321  int dim = lnp.size();
322  LNodePath::const_iterator it = lnp.begin();
323  for (; it != lnp.end(); ++it)
324  {
325  int i = it->getX();
326  int j = it->getY();
327  int ij = i*_jm +j;
328  _cost[ij] += Resource::link_separation_weight; // --- big cost, because distance is x2+y2
329 
330  }
331 }
332 
333 
340 void LinkMatrix::explore(AbstractSceneItem *child, bool setObstacle)
341 {
342  SceneComposedNodeItem *cnItem = dynamic_cast<SceneComposedNodeItem*>(child);
343  if (cnItem)
344  {
345  SceneHeaderItem *obstacle = cnItem->getHeader();
346  if (obstacle) getBoundingBox(obstacle, 0, setObstacle);
347  list<AbstractSceneItem*> children = cnItem->getChildren();
348  for (list<AbstractSceneItem*>::const_iterator it = children.begin(); it != children.end(); ++it)
349  explore(*it, setObstacle);
350  }
351  SceneElementaryNodeItem *ceItem = dynamic_cast<SceneElementaryNodeItem*>(child);
352  if (ceItem)
353  {
354  getBoundingBox(ceItem, 1, setObstacle);
355  }
356 }
357 
364 void LinkMatrix::getBoundingBox(SceneItem *obstacle, int margin, bool setObstacle)
365 {
366  QRectF bb = (obstacle->mapToScene(obstacle->boundingRect())).boundingRect();
367  if (setObstacle)
368  {
369  int imin = _x2i[bb.left() + margin];
370  int imax = _x2i[bb.right() - margin];
371  int jmin = _y2j[bb.top() + margin];
372  int jmax = _y2j[bb.bottom() - margin];
373  DEBTRACE(bb.left() << " " << bb.right() << " " << bb.top() << " " << bb.bottom() );
374  DEBTRACE(imin << " " << imax << " " << jmin << " " << jmax);
375  for (int j=jmin; j<jmax; j++)
376  for (int i=imin; i<imax; i++)
377  {
378  int ij = i*_jm +j;
379  _cost[ij] = 0; // --- obstacle
380  }
381  }
382  else
383  {
384  _sxm.insert(bb.left() + margin);
385  _sxm.insert(bb.right() - margin);
386  _sym.insert(bb.top() + margin);
387  _sym.insert(bb.bottom() - margin);
388  }
389 }
390 
392 {
393  {
394  set<double> sxmCpy = _sxm;
395  if (sxmCpy.empty()) return;
396  set<double>::iterator itx = sxmCpy.begin();
397  double xmin = *itx;
398  double xmax = xmin;
399  itx++;
400  for (; itx != sxmCpy.end(); ++itx)
401  {
402  xmax = *itx;
403  int nbpas = floor((xmax -xmin)/_pas);
404 
405  if (nbpas >= 2)
406  {
407  double xpas = (xmax -xmin)/nbpas;
408  for (int i=1; i<nbpas; i++)
409  _sxm.insert(xmin +i*xpas);
410  }
411  xmin = xmax;
412  }
413  }
414  {
415  set<double> symCpy = _sym;
416  if (symCpy.empty()) return;
417  set<double>::iterator ity = symCpy.begin();
418  double ymin = *ity;
419  double ymax = ymin;
420  ity++;
421  for (; ity != symCpy.end(); ++ity)
422  {
423  ymax = *ity;
424  int nbpas = floor((ymax -ymin)/_pas);
425 
426  if (nbpas >= 2)
427  {
428  double ypas = (ymax -ymin)/nbpas;
429  for (int i=1; i<nbpas; i++)
430  _sym.insert(ymin +i*ypas);
431  }
432  ymin = ymax;
433  }
434  }
435 }