1 // Copyright (C) 2006-2008 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.
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
19 #include "LinkAStar.hxx"
26 #include "YacsTrace.hxx"
29 //using namespace YACS::ENGINE;
30 using namespace YACS::HMI;
33 LCostNode::LCostNode() : _gCost(0), _hCost(0), _fCost(0),
34 _parent( std::pair<int,int>(0,0) )
36 //DEBTRACE("LCostNode::LCostNode()");
39 LCostNode::LCostNode(std::pair<int,int> parent) : _gCost(0), _hCost(0), _fCost(0),
42 //DEBTRACE("LCostNode::LCostNode(std::pair<int,int> parent)");
47 LinkAStar::LinkAStar(const LinkMatrix& linkMatrix) : _linkMatrix(linkMatrix), _from(0,0), _to(0,0)
54 LinkAStar::~LinkAStar()
58 bool LinkAStar::computePath(LNode from, LNode to)
66 //pair<int, int> curPos(0, 0);
67 //LCostNode startCost(curPos);
69 pair<int, int> curPos = _from.getPos();
70 LCostNode startCost(curPos);
71 _openList[curPos] = startCost;
72 moveToClosedList(curPos);
73 addNeighbours(curPos);
75 while (! ((curPos.first == _to.getX()) && (curPos.second == _to.getY()))
76 && (!_openList.empty()))
78 curPos = bestNode(_openList);
79 moveToClosedList(curPos);
80 DEBTRACE("curPos(" << curPos.first << "," << curPos.second << ")");
81 addNeighbours(curPos);
84 if ((curPos.first == _to.getX()) && (curPos.second == _to.getY()))
90 LNodePath LinkAStar::givePath()
94 aPath.push_front(_to);
97 while (! current.isEqual(_from))
99 current = LNode(_closedList[current.getPos()].getParent());
100 aPath.push_front(current);
101 DEBTRACE("(" << current.getX() << "," << current.getY() << ")");
103 // aPath.push_front(_from);
104 // DEBTRACE("(" << _from.getX() << "," << _from.getY() << ")");
108 bool LinkAStar::isAlreadyInList(std::pair<int,int> n, const LNodeMap& aList)
110 LNodeMap::const_iterator it = aList.find(n);
111 if (it == aList.end())
117 void LinkAStar::addNeighbours(std::pair<int,int> currentNode)
119 LCostNode tmp(currentNode);
120 int x = currentNode.first;
121 int y = currentNode.second;
122 for (int i = x-1; i <= x+1; i++)
124 if ((i<0) || (i >= _linkMatrix.imax()))
125 continue; // --- skip: outside matrix
126 for (int j = y-1; j <= y+1; j++)
128 if ((j<0) || (j >= _linkMatrix.jmax()))
129 continue; // --- skip: outside matrix
131 if ((i == x) && (j == y))
132 continue; // --- skip: current node
134 if ((i != x) && (j != y))
135 continue; // --- skip: diagonals (move only vertical or horizontal)
137 int cost = _linkMatrix.cost(i,j);
139 continue; // --- skip: blocked
141 pair<int,int> pos(i,j);
142 if (isAlreadyInList(pos, _closedList))
143 continue; // --- skip: already in closed list
145 tmp.setGCost(_closedList[currentNode].getGCost() + cost*distance(x, y, i, j));
146 tmp.setHCost(distance(i, j, _to.getX(), _to.getY()));
147 tmp.setFCost(tmp.getGCost() + tmp.getHCost());
148 if (isAlreadyInList(pos, _openList))
150 if (tmp.getFCost() < _openList[pos].getFCost())
152 _openList[pos] = tmp; // --- new path better, update node
157 _openList[pos] = tmp; // --- add node
163 std::pair<int,int> LinkAStar::bestNode(const LNodeMap& aList)
165 double fCost = (aList.begin()->second).getFCost();
166 pair<int, int> pos = aList.begin()->first;
167 for (LNodeMap::const_iterator it = aList.begin(); it != aList.end(); ++it)
168 if ((it->second).getFCost() < fCost)
170 fCost = (it->second).getFCost();
176 void LinkAStar::moveToClosedList(std::pair<int,int> pos)
178 _closedList[pos] = _openList[pos];
179 if (_openList.erase(pos) == 0)
180 DEBTRACE("node not in open list, can't delete");
183 double LinkAStar::distance(int i1, int j1, int i2, int j2)
185 return sqrt(double((i1-i2)*(i1-i2) + (j1-j2)*(j1-j2)));