2009-08-21 22:21:05 +02:00
|
|
|
/*
|
|
|
|
* This file is part of OpenTTD.
|
|
|
|
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
|
|
|
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2008-05-06 17:11:33 +02:00
|
|
|
/** @file nodelist.hpp List of nodes used for the A-star pathfinder. */
|
2007-02-23 09:37:33 +01:00
|
|
|
|
2010-12-22 12:24:38 +01:00
|
|
|
#ifndef NODELIST_HPP
|
|
|
|
#define NODELIST_HPP
|
2006-05-27 18:12:16 +02:00
|
|
|
|
2009-12-01 23:45:39 +01:00
|
|
|
#include "../../misc/hashtable.hpp"
|
|
|
|
#include "../../misc/binaryheap.hpp"
|
2006-05-27 18:12:16 +02:00
|
|
|
|
2010-08-01 21:22:34 +02:00
|
|
|
/**
|
|
|
|
* Hash table based node list multi-container class.
|
2006-09-04 22:40:33 +02:00
|
|
|
* Implements open list, closed list and priority queue for A-star
|
2010-08-01 21:44:49 +02:00
|
|
|
* path finder.
|
|
|
|
*/
|
2006-05-27 18:12:16 +02:00
|
|
|
template <class Titem_, int Thash_bits_open_, int Thash_bits_closed_>
|
|
|
|
class CNodeList_HashTableT {
|
|
|
|
public:
|
2015-08-08 15:19:38 +02:00
|
|
|
typedef Titem_ Titem; ///< Make #Titem_ visible from outside of class.
|
2018-10-28 03:17:36 +01:00
|
|
|
typedef typename Titem_::Key Key; ///< Make Titem_::Key a property of this class.
|
2024-04-01 18:18:18 +02:00
|
|
|
using CItemArray = std::deque<Titem_>; ///< Type that we will use as item container.
|
2015-08-08 15:19:38 +02:00
|
|
|
typedef CHashTableT<Titem_, Thash_bits_open_ > COpenList; ///< How pointers to open nodes will be stored.
|
|
|
|
typedef CHashTableT<Titem_, Thash_bits_closed_> CClosedList; ///< How pointers to closed nodes will be stored.
|
|
|
|
typedef CBinaryHeapT<Titem_> CPriorityQueue; ///< How the priority queue will be managed.
|
2006-05-27 18:12:16 +02:00
|
|
|
|
|
|
|
protected:
|
2015-08-08 15:19:38 +02:00
|
|
|
CItemArray m_arr; ///< Here we store full item data (Titem_).
|
|
|
|
COpenList m_open; ///< Hash table of pointers to open item data.
|
|
|
|
CClosedList m_closed; ///< Hash table of pointers to closed item data.
|
|
|
|
CPriorityQueue m_open_queue; ///< Priority queue of pointers to open item data.
|
|
|
|
Titem *m_new_node; ///< New open node under construction.
|
|
|
|
|
2006-05-27 18:12:16 +02:00
|
|
|
public:
|
|
|
|
/** default constructor */
|
2015-08-08 15:19:38 +02:00
|
|
|
CNodeList_HashTableT() : m_open_queue(2048)
|
2006-05-27 18:12:16 +02:00
|
|
|
{
|
2019-04-10 23:07:06 +02:00
|
|
|
m_new_node = nullptr;
|
2006-05-27 18:12:16 +02:00
|
|
|
}
|
2009-03-04 09:02:16 +01:00
|
|
|
|
2006-05-27 18:12:16 +02:00
|
|
|
/** destructor */
|
|
|
|
~CNodeList_HashTableT()
|
|
|
|
{
|
|
|
|
}
|
2009-03-04 09:02:16 +01:00
|
|
|
|
2006-05-27 18:12:16 +02:00
|
|
|
/** return number of open nodes */
|
2011-12-20 18:57:56 +01:00
|
|
|
inline int OpenCount()
|
2009-03-04 09:02:16 +01:00
|
|
|
{
|
|
|
|
return m_open.Count();
|
|
|
|
}
|
|
|
|
|
2006-05-27 18:12:16 +02:00
|
|
|
/** return number of closed nodes */
|
2011-12-20 18:57:56 +01:00
|
|
|
inline int ClosedCount()
|
2009-03-04 09:02:16 +01:00
|
|
|
{
|
|
|
|
return m_closed.Count();
|
|
|
|
}
|
|
|
|
|
2006-05-27 18:12:16 +02:00
|
|
|
/** allocate new data item from m_arr */
|
2011-12-20 18:57:56 +01:00
|
|
|
inline Titem_ *CreateNewNode()
|
2006-05-27 18:12:16 +02:00
|
|
|
{
|
2024-04-01 18:18:18 +02:00
|
|
|
if (m_new_node == nullptr) m_new_node = &m_arr.emplace_back();
|
2006-05-27 18:12:16 +02:00
|
|
|
return m_new_node;
|
|
|
|
}
|
2009-03-04 09:02:16 +01:00
|
|
|
|
2010-10-30 19:51:07 +02:00
|
|
|
/** Notify the nodelist that we don't want to discard the given node. */
|
2015-08-08 12:06:24 +02:00
|
|
|
inline void FoundBestNode(Titem_ &item)
|
2006-05-27 18:12:16 +02:00
|
|
|
{
|
2009-03-15 01:32:18 +01:00
|
|
|
/* for now it is enough to invalidate m_new_node if it is our given node */
|
2009-03-04 09:02:16 +01:00
|
|
|
if (&item == m_new_node) {
|
2019-04-10 23:07:06 +02:00
|
|
|
m_new_node = nullptr;
|
2009-03-04 09:02:16 +01:00
|
|
|
}
|
2009-03-15 01:32:18 +01:00
|
|
|
/* TODO: do we need to store best nodes found in some extra list/array? Probably not now. */
|
2006-05-27 18:12:16 +02:00
|
|
|
}
|
2009-03-04 09:02:16 +01:00
|
|
|
|
2006-05-27 18:12:16 +02:00
|
|
|
/** insert given item as open node (into m_open and m_open_queue) */
|
2015-08-08 12:06:24 +02:00
|
|
|
inline void InsertOpenNode(Titem_ &item)
|
2006-05-27 18:12:16 +02:00
|
|
|
{
|
2019-04-10 23:07:06 +02:00
|
|
|
assert(m_closed.Find(item.GetKey()) == nullptr);
|
2006-05-27 18:12:16 +02:00
|
|
|
m_open.Push(item);
|
2010-02-25 12:52:04 +01:00
|
|
|
m_open_queue.Include(&item);
|
2009-03-04 09:02:16 +01:00
|
|
|
if (&item == m_new_node) {
|
2019-04-10 23:07:06 +02:00
|
|
|
m_new_node = nullptr;
|
2009-03-04 09:02:16 +01:00
|
|
|
}
|
2006-05-27 18:12:16 +02:00
|
|
|
}
|
2009-03-04 09:02:16 +01:00
|
|
|
|
2006-05-27 18:12:16 +02:00
|
|
|
/** return the best open node */
|
2011-12-20 18:57:56 +01:00
|
|
|
inline Titem_ *GetBestOpenNode()
|
2006-05-27 18:12:16 +02:00
|
|
|
{
|
|
|
|
if (!m_open_queue.IsEmpty()) {
|
2010-02-25 12:48:50 +01:00
|
|
|
return m_open_queue.Begin();
|
2006-05-27 18:12:16 +02:00
|
|
|
}
|
2019-04-10 23:07:06 +02:00
|
|
|
return nullptr;
|
2006-05-27 18:12:16 +02:00
|
|
|
}
|
2009-03-04 09:02:16 +01:00
|
|
|
|
2006-05-27 18:12:16 +02:00
|
|
|
/** remove and return the best open node */
|
2011-12-20 18:57:56 +01:00
|
|
|
inline Titem_ *PopBestOpenNode()
|
2006-05-27 18:12:16 +02:00
|
|
|
{
|
|
|
|
if (!m_open_queue.IsEmpty()) {
|
2010-02-25 12:48:50 +01:00
|
|
|
Titem_ *item = m_open_queue.Shift();
|
|
|
|
m_open.Pop(*item);
|
|
|
|
return item;
|
2006-05-27 18:12:16 +02:00
|
|
|
}
|
2019-04-10 23:07:06 +02:00
|
|
|
return nullptr;
|
2006-05-27 18:12:16 +02:00
|
|
|
}
|
2009-03-04 09:02:16 +01:00
|
|
|
|
2019-04-10 23:07:06 +02:00
|
|
|
/** return the open node specified by a key or nullptr if not found */
|
2015-08-08 12:06:24 +02:00
|
|
|
inline Titem_ *FindOpenNode(const Key &key)
|
2006-05-27 18:12:16 +02:00
|
|
|
{
|
2009-01-10 01:31:47 +01:00
|
|
|
Titem_ *item = m_open.Find(key);
|
2006-05-27 18:12:16 +02:00
|
|
|
return item;
|
|
|
|
}
|
2009-03-04 09:02:16 +01:00
|
|
|
|
2006-05-27 18:12:16 +02:00
|
|
|
/** remove and return the open node specified by a key */
|
2024-01-03 22:33:38 +01:00
|
|
|
inline Titem_ &PopOpenNode(const Key &key)
|
2006-05-27 18:12:16 +02:00
|
|
|
{
|
2015-08-08 12:06:24 +02:00
|
|
|
Titem_ &item = m_open.Pop(key);
|
2010-02-25 12:52:04 +01:00
|
|
|
uint idxPop = m_open_queue.FindIndex(item);
|
|
|
|
m_open_queue.Remove(idxPop);
|
2006-05-27 18:12:16 +02:00
|
|
|
return item;
|
|
|
|
}
|
2009-03-04 09:02:16 +01:00
|
|
|
|
2006-05-27 18:12:16 +02:00
|
|
|
/** close node */
|
2015-08-08 12:06:24 +02:00
|
|
|
inline void InsertClosedNode(Titem_ &item)
|
2006-05-27 18:12:16 +02:00
|
|
|
{
|
2019-04-10 23:07:06 +02:00
|
|
|
assert(m_open.Find(item.GetKey()) == nullptr);
|
2006-05-27 18:12:16 +02:00
|
|
|
m_closed.Push(item);
|
|
|
|
}
|
2009-03-04 09:02:16 +01:00
|
|
|
|
2019-04-10 23:07:06 +02:00
|
|
|
/** return the closed node specified by a key or nullptr if not found */
|
2015-08-08 12:06:24 +02:00
|
|
|
inline Titem_ *FindClosedNode(const Key &key)
|
2006-05-27 18:12:16 +02:00
|
|
|
{
|
2009-01-10 01:31:47 +01:00
|
|
|
Titem_ *item = m_closed.Find(key);
|
2006-05-27 18:12:16 +02:00
|
|
|
return item;
|
|
|
|
}
|
|
|
|
|
2011-05-02 18:14:23 +02:00
|
|
|
/** The number of items. */
|
2015-08-08 15:19:38 +02:00
|
|
|
inline int TotalCount()
|
|
|
|
{
|
|
|
|
return m_arr.Length();
|
|
|
|
}
|
|
|
|
|
2011-05-02 18:14:23 +02:00
|
|
|
/** Get a particular item. */
|
2024-01-03 22:33:38 +01:00
|
|
|
inline Titem_ &ItemAt(int idx)
|
2015-08-08 15:19:38 +02:00
|
|
|
{
|
|
|
|
return m_arr[idx];
|
|
|
|
}
|
2007-06-30 01:45:13 +02:00
|
|
|
|
2011-05-02 18:14:23 +02:00
|
|
|
/** Helper for creating output of this array. */
|
2007-06-30 01:45:13 +02:00
|
|
|
template <class D> void Dump(D &dmp) const
|
|
|
|
{
|
|
|
|
dmp.WriteStructT("m_arr", &m_arr);
|
|
|
|
}
|
2006-05-27 18:12:16 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif /* NODELIST_HPP */
|