Salome HOME
mergefrom branch BR_V511_PR tag mergeto_trunk_03feb09
[modules/yacs.git] / src / genericgui / LinkMatrix.cxx
1 //  Copyright (C) 2006-2008  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.
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 #include "LinkMatrix.hxx"
20 #include "SceneComposedNodeItem.hxx"
21 #include "SceneElementaryNodeItem.hxx"
22 #include "SceneHeaderItem.hxx"
23 #include "SceneLinkItem.hxx"
24 #include "QtGuiContext.hxx"
25 #include "InPort.hxx"
26 #include "OutPort.hxx"
27
28 #include <cmath>
29
30 //#define _DEVDEBUG_
31 #include "YacsTrace.hxx"
32
33 using namespace std;
34 using namespace YACS::ENGINE;
35 using namespace YACS::HMI;
36
37 double LNode::distance(const LNode& o) const
38 {
39   int dx = _x -o._x;
40   int dy = _y -o._y;
41   return sqrt(double(dx*dx +dy*dy));
42 }
43
44
45 LinkMatrix::LinkMatrix(SceneComposedNodeItem *bloc): _bloc(bloc)
46 {
47   _im=0;
48   _jm=0;
49   _sxm.clear();
50   _sym.clear();
51   _xm.clear();
52   _ym.clear();
53   _x2i.clear();
54   _y2j.clear();
55   _cost.clear();
56   _context = QtGuiContext::getQtCurrent();
57 }
58
59 LinkMatrix::~LinkMatrix()
60 {
61 }
62
63 void LinkMatrix::compute()
64 {
65   getBoundingBox(_bloc,0);
66   explore(_bloc);        // --- define the boundaries _xm[i] and _ym[j]
67   _im = _sxm.size();
68   _xm.reserve(_im);
69   DEBTRACE("_sxm.size()=" << _im);
70   int i =0;
71   for(std::set<double>::iterator it = _sxm.begin(); it != _sxm.end(); ++it)
72     {
73       _xm[i] = *it;
74       _x2i[*it] = i;
75       DEBTRACE("_xm[" << i << "] = " << _xm[i]);
76       i++;
77     }
78   _jm = _sym.size();
79   _ym.reserve(_jm);
80   DEBTRACE("_sym.size()=" << _jm);
81   i =0;
82   for(std::set<double>::iterator it = _sym.begin(); it != _sym.end(); ++it)
83     {
84       _ym[i] = *it;
85       _y2j[*it] = i;
86       DEBTRACE("_ym[" << i << "] = " << _ym[i]);
87       i++;
88     }
89   _cost.reserve(_im*_jm);
90   for (int ij=0; ij < _im*_jm; ij++)
91     _cost[ij] = 1;       // --- set the _cost matrix open everywhere (no obstacles)
92   explore(_bloc, true);  // --- fill the cells cost(i,j) with obstacles
93
94   for (int j=0; j<_jm; j++)
95     {
96       char m[_im+1];
97       for (int i=0; i<_im; i++)
98         if (cost(i,j))
99           m[i] = ' ';
100         else 
101           m[i] = 'X';
102       m[_im] = 0;
103       DEBTRACE(m);
104     }
105 }
106
107 std::pair<int,int> LinkMatrix::cellFrom(YACS::ENGINE::OutPort* outp)
108 {
109   SubjectDataPort* subDP = _context->_mapOfSubjectDataPort[outp];
110   SceneItem* item = _context->_mapOfSceneItem[subDP];
111   QRectF bb = (item->mapToScene(item->boundingRect())).boundingRect();
112   qreal xp = bb.right();
113   qreal yp = (bb.top() + bb.bottom())*0.5;
114   int ifrom = -1;
115   for (int i=0; i<_im-1; i++)
116     if (_xm[i+1] > xp)
117       {
118         ifrom = i;
119         break;
120       }
121   int jfrom = -1;
122   for (int j=0; j<_jm-1; j++)
123     if (_ym[j+1] > yp)
124       {
125         jfrom = j;
126         break;
127       }
128   while (!cost(ifrom,jfrom)) ifrom++;  // --- from point is inside an obstacle
129   //ifrom++;
130   return pair<int,int>(ifrom,jfrom);
131 }
132
133 std::pair<int,int> LinkMatrix::cellFrom(YACS::ENGINE::OutGate* outp)
134 {
135   SubjectNode* subNode = _context->_mapOfSubjectNode[outp->getNode()];
136   SceneItem* item = _context->_mapOfSceneItem[subNode];
137   QRectF bb = (item->mapToScene(item->boundingRect())).boundingRect();
138   qreal xp = bb.right();
139   qreal yp = (bb.top() + bb.bottom())*0.5;
140   int ifrom = -1;
141   for (int i=0; i<_im-1; i++)
142     if (_xm[i+1] > xp)
143       {
144         ifrom = i;
145         break;
146       }
147   int jfrom = -1;
148   for (int j=0; j<_jm-1; j++)
149     if (_ym[j+1] > yp)
150       {
151         jfrom = j;
152         break;
153       }
154   while (!cost(ifrom,jfrom)) ifrom++;  // --- from point is inside an obstacle
155   //ifrom++;
156   return pair<int,int>(ifrom,jfrom);
157 }
158
159 std::pair<int,int> LinkMatrix::cellTo(YACS::ENGINE::InPort* inp)
160 {
161   SubjectDataPort* subDP = _context->_mapOfSubjectDataPort[inp];
162   SceneItem* item = _context->_mapOfSceneItem[subDP];
163   QRectF bb = (item->mapToScene(item->boundingRect())).boundingRect();
164   qreal xp = bb.left();
165   qreal yp = (bb.top() + bb.bottom())*0.5;
166   int ito = -1;
167   for (int i=0; i<_im-1; i++)
168     if (_xm[i+1] > xp)
169       {
170         ito = i;
171         break;
172       }
173   int jto = -1;
174   for (int j=0; j<_jm-1; j++)
175     if (_ym[j+1] > yp)
176       {
177         jto = j;
178         break;
179       }
180   while (!cost(ito,jto)) ito--;  // --- from point is inside an obstacle
181   //ito--;
182   return pair<int,int>(ito,jto);
183 }
184
185 std::pair<int,int> LinkMatrix::cellTo(YACS::ENGINE::InGate* inp)
186 {
187   SubjectNode* subNode = _context->_mapOfSubjectNode[inp->getNode()];
188   SceneItem* item = _context->_mapOfSceneItem[subNode];
189   QRectF bb = (item->mapToScene(item->boundingRect())).boundingRect();
190   qreal xp = bb.left();
191   qreal yp = (bb.top() + bb.bottom())*0.5;
192   int ito = -1;
193   for (int i=0; i<_im-1; i++)
194     if (_xm[i+1] > xp)
195       {
196         ito = i;
197         break;
198       }
199   int jto = -1;
200   for (int j=0; j<_jm-1; j++)
201     if (_ym[j+1] > yp)
202       {
203         jto = j;
204         break;
205       }
206   while (!cost(ito,jto)) ito--;  // --- from point is inside an obstacle
207   //ito--;
208   return pair<int,int>(ito,jto);
209 }
210
211 std::list<linkdef> LinkMatrix::getListOfCtrlLinkDef()
212 {
213   list<linkdef> alist;
214   map<pair<Node*, Node*>, SubjectControlLink*>::const_iterator it;
215   for (it = _context->_mapOfSubjectControlLink.begin();
216        it != _context->_mapOfSubjectControlLink.end(); ++it)
217     {
218       linkdef ali;
219       pair<Node*, Node*> outin = it->first;
220       SubjectControlLink* sub = it->second;
221       ali.from = cellFrom(outin.first->getOutGate());
222       ali.to = cellTo(outin.second->getInGate());
223       ali.item = dynamic_cast<SceneLinkItem*>(_context->_mapOfSceneItem[sub]);
224       alist.push_back(ali);
225       DEBTRACE("from("<<ali.from.first<<","<<ali.from.second
226                <<") to ("<<ali.to.first<<","<<ali.to.second
227                <<") " << ali.item->getLabel().toStdString());
228     }
229   return alist;
230 }
231
232 std::list<linkdef> LinkMatrix::getListOfDataLinkDef()
233 {
234   list<linkdef> alist;
235   map<pair<OutPort*, InPort*>, SubjectLink*>::const_iterator it;
236   for (it = _context->_mapOfSubjectLink.begin();
237        it != _context->_mapOfSubjectLink.end(); ++it)
238     {
239       linkdef ali;
240       pair<OutPort*, InPort*> outin = it->first;
241       SubjectLink* sub = it->second;
242       ali.from = cellFrom(outin.first);
243       ali.to = cellTo(outin.second);
244       ali.item = dynamic_cast<SceneLinkItem*>(_context->_mapOfSceneItem[sub]);
245       alist.push_back(ali);
246       DEBTRACE("from("<<ali.from.first<<","<<ali.from.second
247                <<") to ("<<ali.to.first<<","<<ali.to.second
248                <<") " << ali.item->getLabel().toStdString());
249     }
250   return alist;
251 }
252
253 LinkPath LinkMatrix::getPath(LNodePath lnp)
254 {
255   DEBTRACE("LinkMatrix::getPath " << lnp.size());
256   LinkPath lp;
257   lp.clear();
258   int dim = lnp.size();  
259   LNodePath::const_iterator it = lnp.begin();
260   for (int k=0; k<dim; k++)
261     {
262       int i = it->getX();
263       int j = it->getY();
264       linkPoint a;
265       a.x = 0.5*(_xm[i] + _xm[i+1]);
266       a.y = 0.5*(_ym[j] + _ym[j+1]);
267       lp.push_back(a);
268       DEBTRACE(a.x << " " << a.y);
269       ++it;
270     }
271   return lp;
272 }
273
274 int LinkMatrix::cost(int i, int j) const
275 {
276   int ij = i*_jm +j;
277   return _cost[ij];
278 }
279
280
281 /*!
282  * find recursively elementary nodes and node headers and call getBoundingBox on each item.
283  * first pass with setObstacle = false stores the x and y coordinates of the mesh boundaries.
284  * second pass with setObstacle = true fills the mesh with obstacles i.e. elementary nodes or
285  * nodeHeaders.
286  */
287 void LinkMatrix::explore(AbstractSceneItem *child, bool setObstacle)
288 {
289   SceneComposedNodeItem *cnItem = dynamic_cast<SceneComposedNodeItem*>(child);
290   if (cnItem)
291     {
292       SceneHeaderItem *obstacle = cnItem->getHeader();
293       if (obstacle) getBoundingBox(obstacle, 0, setObstacle);
294       list<AbstractSceneItem*> children = cnItem->getChildren();
295       for (list<AbstractSceneItem*>::const_iterator it = children.begin(); it != children.end(); ++it)
296         explore(*it, setObstacle);
297     }
298   SceneElementaryNodeItem *ceItem = dynamic_cast<SceneElementaryNodeItem*>(child);
299   if (ceItem)
300     {
301       getBoundingBox(ceItem, 1, setObstacle);
302     }
303 }
304
305 /*!
306  * first pass with setObstacle = false stores the x and y coordinates of the mesh boundaries.
307  * second pass with setObstacle = true fills the mesh with obstacles i.e. elementary nodes or
308  * nodeHeaders. For elementary nodes, the bounding box is smaller to let a path between nodes
309  * that are stick together.
310  */
311 void LinkMatrix::getBoundingBox(SceneItem *obstacle, int margin, bool setObstacle)
312 {
313   QRectF bb = (obstacle->mapToScene(obstacle->boundingRect())).boundingRect();
314   if (setObstacle)
315     {
316       int imin = _x2i[bb.left()   + margin];
317       int imax = _x2i[bb.right()  - margin];
318       int jmin = _y2j[bb.top()    + margin];
319       int jmax = _y2j[bb.bottom() - margin];
320       DEBTRACE(bb.left() << " " << bb.right() << " " << bb.top() << " " << bb.bottom() );
321       DEBTRACE(imin << " " << imax << " " << jmin << " " << jmax);
322       for (int j=jmin; j<jmax; j++)
323         for (int i=imin; i<imax; i++)
324           {
325             int ij = i*_jm +j;
326             _cost[ij] = 0;       // --- obstacle
327           }
328     }
329   else
330     {
331       _sxm.insert(bb.left()   + margin);
332       _sxm.insert(bb.right()  - margin);
333       _sym.insert(bb.top()    + margin);
334       _sym.insert(bb.bottom() - margin);
335     }
336 }