1 // Copyright (C) 2006-2016 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 "LinkMatrix.hxx"
22 #include "SceneComposedNodeItem.hxx"
23 #include "SceneElementaryNodeItem.hxx"
24 #include "SceneHeaderItem.hxx"
25 #include "SceneHeaderNodeItem.hxx"
26 #include "SceneCtrlPortItem.hxx"
27 #include "SceneLinkItem.hxx"
28 #include "QtGuiContext.hxx"
30 #include "OutPort.hxx"
31 #include "Resource.hxx"
36 #include "YacsTrace.hxx"
39 using namespace YACS::ENGINE;
40 using namespace YACS::HMI;
42 double LNode::distance(const LNode& o) const
46 return sqrt(double(dx*dx +dy*dy));
50 LinkMatrix::LinkMatrix(SceneComposedNodeItem *bloc): _bloc(bloc)
62 _context = QtGuiContext::getQtCurrent();
65 LinkMatrix::~LinkMatrix()
69 void LinkMatrix::compute()
71 getBoundingBox(_bloc,0);
72 explore(_bloc); // --- define the boundaries _xm[i] and _ym[j]
73 if (Scene::_addRowCols) addRowCols();
76 DEBTRACE("_sxm.size()=" << _im);
78 for(std::set<double>::iterator it = _sxm.begin(); it != _sxm.end(); ++it)
82 DEBTRACE("_xm[" << i << "] = " << _xm[i]);
87 DEBTRACE("_sym.size()=" << _jm);
89 for(std::set<double>::iterator it = _sym.begin(); it != _sym.end(); ++it)
93 DEBTRACE("_ym[" << i << "] = " << _ym[i]);
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
101 for (int j=0; j<_jm; j++)
103 char* m = new char[_im+1];
104 for (int i=0; i<_im; i++)
115 std::pair<int,int> LinkMatrix::cellFrom(YACS::ENGINE::OutPort* outp)
117 SubjectDataPort* subDP = _context->_mapOfSubjectDataPort[outp];
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);
124 for (int i=0; i<_im-1; i++)
125 if (_xm[i+1] >= xp && xp > _xm[i])
131 for (int j=0; j<_jm-1; j++)
132 if (_ym[j+1] >= yp && yp > _ym[j])
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
141 return pair<int,int>(ifrom,jfrom);
144 std::pair<int,int> LinkMatrix::cellFrom(YACS::ENGINE::OutGate* outp)
146 SubjectNode* subNode = _context->_mapOfSubjectNode[outp->getNode()];
147 SceneNodeItem* itemNode = dynamic_cast<SceneNodeItem*>(_context->_mapOfSceneItem[subNode]);
149 SceneHeaderNodeItem* itemHeader = dynamic_cast<SceneHeaderNodeItem*>(itemNode->getHeader());
151 SceneCtrlPortItem *item = itemHeader->getCtrlOutPortItem();
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);
158 for (int i=0; i<_im-1; i++)
159 if (_xm[i+1] >= xp && xp > _xm[i])
165 for (int j=0; j<_jm-1; j++)
166 if (_ym[j+1] >= yp && yp > _ym[j])
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
175 return pair<int,int>(ifrom,jfrom);
178 std::pair<int,int> LinkMatrix::cellTo(YACS::ENGINE::InPort* inp)
180 SubjectDataPort* subDP = _context->_mapOfSubjectDataPort[inp];
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);
187 for (int i=0; i<_im-1; i++)
188 if (_xm[i+1] >= xp && xp > _xm[i])
194 for (int j=0; j<_jm-1; j++)
195 if (_ym[j+1] >= yp && yp > _ym[j])
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
204 return pair<int,int>(ito,jto);
207 std::pair<int,int> LinkMatrix::cellTo(YACS::ENGINE::InGate* inp)
209 SubjectNode* subNode = _context->_mapOfSubjectNode[inp->getNode()];
210 SceneNodeItem* itemNode = dynamic_cast<SceneNodeItem*>(_context->_mapOfSceneItem[subNode]);
212 SceneHeaderNodeItem* itemHeader = dynamic_cast<SceneHeaderNodeItem*>(itemNode->getHeader());
214 SceneCtrlPortItem *item = itemHeader->getCtrlInPortItem();
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);
221 for (int i=0; i<_im-1; i++)
222 if (_xm[i+1] >= xp && xp > _xm[i])
228 for (int j=0; j<_jm-1; j++)
229 if (_ym[j+1] >= yp && yp > _ym[j])
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
238 return pair<int,int>(ito,jto);
241 std::list<linkdef> LinkMatrix::getListOfCtrlLinkDef()
244 map<pair<Node*, Node*>, SubjectControlLink*>::const_iterator it;
245 for (it = _context->_mapOfSubjectControlLink.begin();
246 it != _context->_mapOfSubjectControlLink.end(); ++it)
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());
262 std::list<linkdef> LinkMatrix::getListOfDataLinkDef()
265 map<pair<OutPort*, InPort*>, SubjectLink*>::const_iterator it;
266 for (it = _context->_mapOfSubjectLink.begin();
267 it != _context->_mapOfSubjectLink.end(); ++it)
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());
283 LinkPath LinkMatrix::getPath(LNodePath lnp)
285 DEBTRACE("LinkMatrix::getPath " << lnp.size());
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++)
297 DEBTRACE("i, j: " << i << " " << j << " Xmax, Ymax: " << _im << " " << _jm);
303 a.x = coef*_xm[i] + (1.-coef)*_xm[i+1];
309 a.y = coef*_ym[j] + (1.-coef)*_ym[j+1];
313 DEBTRACE(a.x << " " << a.y);
319 void LinkMatrix::incrementCost(LNodePath lnp)
321 int dim = lnp.size();
322 LNodePath::const_iterator it = lnp.begin();
323 for (; it != lnp.end(); ++it)
328 _cost[ij] += Resource::link_separation_weight; // --- big cost, because distance is x2+y2
335 * find recursively elementary nodes and node headers and call getBoundingBox on each item.
336 * first pass with setObstacle = false stores the x and y coordinates of the mesh boundaries.
337 * second pass with setObstacle = true fills the mesh with obstacles i.e. elementary nodes or
340 void LinkMatrix::explore(AbstractSceneItem *child, bool setObstacle)
342 SceneComposedNodeItem *cnItem = dynamic_cast<SceneComposedNodeItem*>(child);
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);
351 SceneElementaryNodeItem *ceItem = dynamic_cast<SceneElementaryNodeItem*>(child);
354 getBoundingBox(ceItem, 1, setObstacle);
359 * first pass with setObstacle = false stores the x and y coordinates of the mesh boundaries.
360 * second pass with setObstacle = true fills the mesh with obstacles i.e. elementary nodes or
361 * nodeHeaders. For elementary nodes, the bounding box is smaller to let a path between nodes
362 * that are stick together.
364 void LinkMatrix::getBoundingBox(SceneItem *obstacle, int margin, bool setObstacle)
366 QRectF bb = (obstacle->mapToScene(obstacle->boundingRect())).boundingRect();
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++)
379 _cost[ij] = 0; // --- obstacle
384 _sxm.insert(bb.left() + margin);
385 _sxm.insert(bb.right() - margin);
386 _sym.insert(bb.top() + margin);
387 _sym.insert(bb.bottom() - margin);
391 void LinkMatrix::addRowCols()
394 set<double> sxmCpy = _sxm;
395 if (sxmCpy.empty()) return;
396 set<double>::iterator itx = sxmCpy.begin();
400 for (; itx != sxmCpy.end(); ++itx)
403 int nbpas = floor((xmax -xmin)/_pas);
407 double xpas = (xmax -xmin)/nbpas;
408 for (int i=1; i<nbpas; i++)
409 _sxm.insert(xmin +i*xpas);
415 set<double> symCpy = _sym;
416 if (symCpy.empty()) return;
417 set<double>::iterator ity = symCpy.begin();
421 for (; ity != symCpy.end(); ++ity)
424 int nbpas = floor((ymax -ymin)/_pas);
428 double ypas = (ymax -ymin)/nbpas;
429 for (int i=1; i<nbpas; i++)
430 _sym.insert(ymin +i*ypas);