summaryrefslogtreecommitdiff
path: root/AudioManagerCore/include/CAmGraph.h
diff options
context:
space:
mode:
Diffstat (limited to 'AudioManagerCore/include/CAmGraph.h')
-rw-r--r--AudioManagerCore/include/CAmGraph.h1329
1 files changed, 695 insertions, 634 deletions
diff --git a/AudioManagerCore/include/CAmGraph.h b/AudioManagerCore/include/CAmGraph.h
index 45043f7..9d9f082 100644
--- a/AudioManagerCore/include/CAmGraph.h
+++ b/AudioManagerCore/include/CAmGraph.h
@@ -37,643 +37,704 @@
#include <cstring>
#include <set>
-
namespace am
{
- /**
- * Graph element status.
- */
- typedef enum:uint8_t
- {
- GES_NOT_VISITED,
- GES_IN_PROGRESS,
- GES_VISITED
- }am_GraphElementStatus_e;
-
- /**
- * Callback parameter telling on which position in the path we are.
- */
- typedef enum:uint8_t
- {
- GRAPH_PATH_START, //at the beginning of the path
- GRAPH_PATH_MIDDLE, //in middle of the path
- GRAPH_PATH_END //at the end of the path
- }am_GraphPathPosition_e;
-
-
- /**
- * This class is base class for nodes and vertices.
- */
- class CAmGraphElement
- {
- am_GraphElementStatus_e mStatus; //!< item status
- public:
- CAmGraphElement(): mStatus(GES_NOT_VISITED) { };
- ~CAmGraphElement() { };
- /**
- * Setter and getter.
- */
- void setStatus(const am_GraphElementStatus_e s) { mStatus = s; };
- am_GraphElementStatus_e getStatus() const { return mStatus; };
- };
-
- template <class NodeData> class CAmNode : public CAmGraphElement
- {
- uint16_t mIndex; //!< uint16_t index used for direct access
- NodeData mData; //!< NodeData user data
- public:
- CAmNode(const NodeData & in):CAmGraphElement(), mIndex(0), mData(in) { };
- CAmNode(const NodeData & in, const uint16_t index):CAmGraphElement(), mIndex(index), mData(in) { };
- ~CAmNode() { };
- /**
- * Setters and getters.
- */
- NodeData & getData() { return mData; }
- const NodeData & getData() const { return mData; }
- uint16_t getIndex() const { return mIndex; }
- void setIndex(uint16_t index) { mIndex = index; }
- };
-
- template <class NodeData, class VertexData> class CAmVertex : public CAmGraphElement
- {
- CAmNode<NodeData>* mpNode; //!< CAmNode<NodeData>* pointer to a node
- VertexData mVertexData; //!< VertexData vertex user data
- uint16_t mWeight; //!< uint16_t a positive value used in the shortest path algorithms
- public:
- CAmVertex(CAmNode<NodeData> *aNode, const VertexData & vertexData, const uint16_t weight):CAmGraphElement(),
- mpNode(aNode), mVertexData(vertexData), mWeight(weight) { };
- ~CAmVertex() { };
- /**
- * Setters and getters.
- */
- CAmNode<NodeData>* getNode() const { return mpNode; }
- VertexData & getData() { return mVertexData; }
- uint16_t getWeight() const { return mWeight; }
- void setWeight(const uint16_t weight) { mWeight=weight; }
- };
-
- /**
- * Class representing a directed or undirected graph. It contains nodes and connections.
- * T, V are types for custom user data.
- */
- template <class T, class V> class CAmGraph
- {
- typedef typename std::vector<CAmNode<T>*> CAmListNodePtrs;
- typedef typename std::list<CAmVertex<T,V>> CAmListVertices;
- typedef typename std::list<CAmVertex<T,V>>::iterator CAmListVerticesItr;
- typedef typename std::list<CAmVertex<T,V>>::const_iterator CAmListVerticesItrConst;
- typedef typename std::list<CAmListVertices> CAmNodesAdjList;
- typedef typename std::list<CAmListVertices>::iterator CAmNodesAdjListItr;
- typedef typename std::list<CAmListVertices>::const_iterator CAmNodesAdjListItrConst;
- typedef typename std::list<CAmNode<T>> CAmListNodes;
- typedef typename std::list<CAmNode<T>>::iterator CAmListNodesItr;
- typedef typename std::list<CAmNode<T>>::const_iterator CAmListNodesItrConst;
- typedef typename std::vector<CAmNode<T>*> CAmNodeReferenceList;
- typedef typename std::vector<CAmListVertices*> CAmVertexReferenceList;
-
- CAmListNodes mStoreNodes; //!< CAmListNodes list with all nodes
- CAmNodesAdjList mStoreAdjList; //!< CAmNodesAdjList adjacency list
- CAmNodeReferenceList mPointersNodes; //!< CAmNodeReferenceList vector with pointers to nodes for direct access
- CAmVertexReferenceList mPointersAdjList; //!< CAmVertexReferenceList vector with pointers to vertices for direct access
- bool mIsCyclic; //!< bool the graph has cycles or not
-
- struct IterateThroughAllNodesDelegate
- {
- CAmNode<T> * source;
- CAmNode<T> * destination;
- CAmNodeReferenceList visited;
- std::function<bool(const CAmNode<T> * )> shouldVisitNode;
- std::function<void(const CAmNode<T> *)> willVisitNode;
- std::function<void(const CAmNode<T> *)> didVisitNode;
- std::function<void(const CAmNodeReferenceList & path)> didFindPath;
- };
-
- struct VisitNodeDelegate
- {
- CAmNode<T> * source;
- CAmNode<T> * destination;
- std::function<void(const am_GraphPathPosition_e, CAmNode<T> &)> visitedNode;
- };
-
- /**
- * Updates the node indexes after adding or removing nodes.
- *
- * @param fromIndex updates all nodes from given index.
- */
- void updateIndexes(const int16_t fromIndex)
- {
- if( fromIndex<mPointersNodes.size() )
- {
- for(auto iter = mPointersNodes.begin()+fromIndex; iter!=mPointersNodes.end(); iter++)
- (*iter)->setIndex(iter-mPointersNodes.begin());
- }
- }
-
-
- /**
- * Finds the shortest path and the minimal weights from given node.
- *
- * @param node start node.
- * @param minDistance vector with all result distances.
- * @param previous vector with previous nodes.
- */
-
- typedef uint16_t vertex_t;
- typedef uint16_t weight_t;
-
- void findShortestPathsFromNode(const CAmNode<T> & node, std::vector<weight_t> &minDistance, std::vector<CAmNode<T> *> &previous)
- {
- typename CAmListVertices::const_iterator nIter;
- CAmListVertices * neighbors;
- weight_t dist, weight, v, distanceThroughU;
- CAmNode<T>* pU;
- CAmVertex<T,V> * pVertex;
- CAmNode<T> *pDstNode;
-
- size_t n = mPointersAdjList.size();
- std::set<std::pair<weight_t, CAmNode<T>*> > vertexQueue;
-
- minDistance.clear();
- minDistance.resize(n, std::numeric_limits<weight_t>::max());
- minDistance[node.getIndex()] = 0;
- previous.clear();
- previous.resize(n, NULL);
-
- vertexQueue.insert(std::make_pair(minDistance[node.getIndex()], (CAmNode<T>*)&node));
-
- while (!vertexQueue.empty())
- {
- dist = vertexQueue.begin()->first;
- pU = vertexQueue.begin()->second;
- vertexQueue.erase(vertexQueue.begin());
- //todo: terminate the search at this position if you want the path to a target node ( if(pU==target)break; )
-
- // Visit each edge exiting u
- neighbors = mPointersAdjList[pU->getIndex()];
- nIter = neighbors->begin();
- for (; nIter != neighbors->end(); nIter++)
- {
- pVertex = (CAmVertex<T,V> *)&(*nIter);
- pDstNode = pVertex->getNode();
-
- v = pDstNode->getIndex();
- weight = pVertex->getWeight();
- distanceThroughU = dist + weight;
- if (distanceThroughU < minDistance[pDstNode->getIndex()])
- {
- vertexQueue.erase(std::make_pair(minDistance[v], pDstNode));
- minDistance[v] = distanceThroughU;
- previous[v] = pU;
- vertexQueue.insert(std::make_pair(minDistance[v], pDstNode));
- }
- }
- }
- }
-
- /**
- * Constructs a path to given node after findShortestsPathsFromNode has been called.
- *
- * @param node end node.
- * @param previous vector with previous nodes.
- * @param result result path.
- */
- void constructShortestPathTo(const CAmNode<T> & node, const std::vector<CAmNode<T> *> &previous, CAmListNodePtrs & result)
- {
- CAmNode<T> * vertex = (CAmNode<T> *)&node;
-
- int i=0;
- while ( (vertex = previous[vertex->getIndex()])!=NULL )
- {
- result.insert(result.begin(), vertex);
- i++;
- }
- if(i)
- result.push_back((CAmNode<T> *)&node);
- }
-
- /**
- * Calls a function with every node from this path after findShortestsPathsFromNode has been called.
- * The construction of the path is delegated to the caller.
- *
- * @param node end node.
- * @param previous vector with previous nodes.
- * @param cb callback which is mostly used for constructing.
- */
- void constructShortestPathTo(const CAmNode<T> & node, const std::vector<CAmNode<T> *> &previous, std::function<void(const am_GraphPathPosition_e pos, CAmNode<T> &)> cb)
- {
- CAmNode<T> * vertex = (CAmNode<T> *)&node;
- CAmNode<T> * prev = vertex;
- int i=0;
- while ( (vertex = previous[vertex->getIndex()])!=NULL )
- {
- cb(i==0?GRAPH_PATH_START:GRAPH_PATH_MIDDLE, *prev);
- prev = vertex;
- i++;
- }
- if(i)
- cb(GRAPH_PATH_END, *prev);
- }
-
- /**
- * Iterate through the nodes and generate all paths to given node.
- *
- * @param dst end node.
- * @param visited vector with current path.
- * @param delegate enumeration delegate.
- */
- void findAllPaths(IterateThroughAllNodesDelegate & delegate)
- {
- CAmListVertices * nodes = mPointersAdjList[delegate.visited.back()->getIndex()];
- CAmListVerticesItrConst vItr(nodes->begin());
-
- CAmVertex<T,V> * pNextVertex;
- CAmNode<T> * pNextNode;
- for (; vItr != nodes->end(); ++vItr)
- {
- pNextVertex = (CAmVertex<T,V> *)&(*vItr);
- pNextNode = pNextVertex->getNode();
- if(
- pNextNode->getStatus()!=GES_NOT_VISITED ||
- !delegate.shouldVisitNode(pNextNode)
- )
- continue;
- if (pNextNode==delegate.destination)
- {
- delegate.willVisitNode(pNextNode);
- pNextNode->setStatus(GES_IN_PROGRESS);
- delegate.visited.push_back(pNextNode);
- //notify observer
- delegate.didFindPath(delegate.visited);
- //remove last node from the list
- auto last = delegate.visited.end()-1;
- delegate.visited.erase(last);
- pNextNode->setStatus(GES_NOT_VISITED);
- delegate.didVisitNode(pNextNode);
- break;
- }
- }
- vItr = nodes->begin();
- //bfs like loop
- for (; vItr != nodes->end(); ++vItr)
- {
- pNextVertex = (CAmVertex<T,V> *)&(*vItr);
- pNextNode = pNextVertex->getNode();
-
- if(pNextNode->getStatus()!=GES_NOT_VISITED ||
- pNextNode==delegate.destination ||
- !delegate.shouldVisitNode(pNextNode)
- )
- continue;
- delegate.willVisitNode(pNextNode);
- pNextNode->setStatus(GES_IN_PROGRESS);
- delegate.visited.push_back(pNextNode);
- findAllPaths(delegate);
- //remove last node from the list
- auto last = delegate.visited.end()-1;
- delegate.visited.erase(last);
- pNextNode->setStatus(GES_NOT_VISITED);
- delegate.didVisitNode(pNextNode);
- }
- }
-
- public:
-
- explicit CAmGraph(const std::vector<T> &v):mStoreNodes(), mStoreAdjList(), mPointersNodes(), mPointersAdjList()
- {
- typedef typename std::vector<T>::const_iterator inItr;
- inItr itr(v.begin());
-
- for (; itr != v.end(); ++itr)
- {
- addNode(*itr);
- }
-
- mIsCyclic = false;
- };
- CAmGraph():mStoreNodes(), mStoreAdjList(), mPointersNodes(), mPointersAdjList(), mIsCyclic(false){};
- ~CAmGraph(){}
-
- const CAmListNodes & getNodes() const
- {
- return mStoreNodes;
- }
-
- const CAmVertexReferenceList & getVertexList() const
- {
- return mPointersAdjList;
- }
-
- /**
- * Returns pointer to a node which data is equal to the given.
- * @return pointer to a node or NULL.
- */
- const CAmNode<T>* findNode(const T & in)
- {
- typename CAmNodeReferenceList::const_iterator itr (mPointersNodes.begin());
-
- for (; itr != mPointersNodes.end(); ++itr)
- {
- if ((*itr)->getData() == in) {
- return (*itr);
- }
- }
- return NULL;
- }
-
- /**
- * Returns pointer to a vertex which two ends are equal to the given nodes.
- * @return pointer to a vertex or NULL.
- */
- const CAmVertex<T,V>* findVertex(const CAmNode<T> & edge1, const CAmNode<T> & edge2) const
- {
- const CAmNode<T> * pEdge2 = (CAmNode<T> *)&edge2;
- const CAmListVertices * list = mPointersAdjList[edge1.getIndex()];
- CAmListVerticesItrConst result = std::find_if(list->begin(), list->end(), [&](const CAmVertex<T,V> & refObject){
- return refObject.getNode()==pEdge2;
- });
- if(result!=list->end())
- return (CAmVertex<T,V>*)&(*result);
-
- return NULL;
- }
-
- bool hasCycles() const
- {
- return mIsCyclic;
- }
-
-
- /**
- * Adds a new node to the graph with given user data.
- * @return reference to the newly inserted node.
- */
- CAmNode<T> & addNode(const T & in)
- {
- size_t index = mStoreNodes.size();
- mStoreNodes.emplace_back(in, index);
- mStoreAdjList.emplace_back();
- mPointersNodes.push_back(&mStoreNodes.back());
- mPointersAdjList.push_back(&mStoreAdjList.back());
- return mStoreNodes.back();
- }
-
- /**
- * Removes a vertex with two ends equal to the given nodes .
- */
- void removeVertex(const CAmNode<T> & edge1, const CAmNode<T> & edge2)
- {
- const CAmListVertices * list = mPointersAdjList[edge1.getIndex()];
- CAmListVerticesItr iter = std::find_if(list->begin(), list->end(), [&edge2](const CAmVertex<T,V> & refVertex){
- return (refVertex.getNode()==&edge2);
- });
- if(iter!=list->end())
- list->erase(iter);
- }
-
- /**
- * Removes all vertices to given node .
- */
- void removeAllVerticesToNode(const CAmNode<T> & node)
- {
- auto comparator = [&node](const CAmVertex<T,V> & refVertex){
- return (refVertex.getNode()==&node);
- };
- auto itr = mPointersAdjList.begin();
- for(;itr!=mPointersAdjList.end();itr++)
- {
- CAmListVertices * vertices = *itr;
- auto iterVert = std::find_if(vertices->begin(), vertices->end(), comparator);
- if(iterVert!=vertices->end())
- vertices->erase(iterVert);
- }
- }
-
- /**
- * Removes a node with given user data .
- */
- void removeNode(const T & in)
- {
- CAmNode<T> * node = findNode(in);
- if(node!=NULL)
- removeNode(*node);
- }
-
- /**
- * Removes the given node from the graph .
- */
- void removeNode(const CAmNode<T> & node)
- {
- uint16_t index = node.getIndex();
- removeAllVerticesToNode(node);
- mPointersAdjList.erase(mPointersAdjList.begin()+index);
- mPointersNodes.erase(mPointersNodes.begin()+index);
- auto iter = std::find_if(mStoreNodes.begin(), mStoreNodes.end(), [&node](const CAmNode<T> & otherNode){
- return &otherNode==&node;
+/**
+ * Graph element status.
+ */
+typedef enum : uint8_t
+{
+ GES_NOT_VISITED,
+ GES_IN_PROGRESS,
+ GES_VISITED
+} am_GraphElementStatus_e;
+
+/**
+ * Callback parameter telling on which position in the path we are.
+ */
+typedef enum : uint8_t
+{
+ GRAPH_PATH_START, // at the beginning of the path
+ GRAPH_PATH_MIDDLE, // in middle of the path
+ GRAPH_PATH_END // at the end of the path
+} am_GraphPathPosition_e;
+
+/**
+ * This class is base class for nodes and vertices.
+ */
+class CAmGraphElement
+{
+ am_GraphElementStatus_e mStatus; //!< item status
+public:
+ CAmGraphElement()
+ : mStatus(GES_NOT_VISITED) { }
+ ~CAmGraphElement() { }
+ /**
+ * Setter and getter.
+ */
+ void setStatus(const am_GraphElementStatus_e s) { mStatus = s; }
+ am_GraphElementStatus_e getStatus() const { return mStatus; }
+};
+
+template <class NodeData>
+class CAmNode : public CAmGraphElement
+{
+ uint16_t mIndex; //!< uint16_t index used for direct access
+ NodeData mData; //!< NodeData user data
+public:
+ CAmNode(const NodeData &in)
+ : CAmGraphElement()
+ , mIndex(0)
+ , mData(in) { }
+ CAmNode(const NodeData &in, const uint16_t index)
+ : CAmGraphElement()
+ , mIndex(index)
+ , mData(in) { }
+ ~CAmNode() { }
+ /**
+ * Setters and getters.
+ */
+ NodeData &getData() { return mData; }
+ const NodeData &getData() const { return mData; }
+ uint16_t getIndex() const { return mIndex; }
+ void setIndex(uint16_t index) { mIndex = index; }
+};
+
+template <class NodeData, class VertexData>
+class CAmVertex : public CAmGraphElement
+{
+ CAmNode<NodeData> *mpNode; //!< CAmNode<NodeData>* pointer to a node
+ VertexData mVertexData; //!< VertexData vertex user data
+ uint16_t mWeight; //!< uint16_t a positive value used in the shortest path algorithms
+public:
+ CAmVertex(CAmNode<NodeData> *aNode, const VertexData &vertexData, const uint16_t weight)
+ : CAmGraphElement()
+ , mpNode(aNode)
+ , mVertexData(vertexData)
+ , mWeight(weight) { }
+ ~CAmVertex() { }
+ /**
+ * Setters and getters.
+ */
+ CAmNode<NodeData> *getNode() const { return mpNode; }
+ VertexData &getData() { return mVertexData; }
+ uint16_t getWeight() const { return mWeight; }
+ void setWeight(const uint16_t weight) { mWeight = weight; }
+};
+
+/**
+ * Class representing a directed or undirected graph. It contains nodes and connections.
+ * T, V are types for custom user data.
+ */
+template <class T, class V>
+class CAmGraph
+{
+ typedef typename std::vector<CAmNode<T> *> CAmListNodePtrs;
+ typedef typename std::list<CAmVertex<T, V> > CAmListVertices;
+ typedef typename std::list<CAmVertex<T, V> >::iterator CAmListVerticesItr;
+ typedef typename std::list<CAmVertex<T, V> >::const_iterator CAmListVerticesItrConst;
+ typedef typename std::list<CAmListVertices> CAmNodesAdjList;
+ typedef typename std::list<CAmListVertices>::iterator CAmNodesAdjListItr;
+ typedef typename std::list<CAmListVertices>::const_iterator CAmNodesAdjListItrConst;
+ typedef typename std::list<CAmNode<T> > CAmListNodes;
+ typedef typename std::list<CAmNode<T> >::iterator CAmListNodesItr;
+ typedef typename std::list<CAmNode<T> >::const_iterator CAmListNodesItrConst;
+ typedef typename std::vector<CAmNode<T> *> CAmNodeReferenceList;
+ typedef typename std::vector<CAmListVertices *> CAmVertexReferenceList;
+
+ CAmListNodes mStoreNodes; //!< CAmListNodes list with all nodes
+ CAmNodesAdjList mStoreAdjList; //!< CAmNodesAdjList adjacency list
+ CAmNodeReferenceList mPointersNodes; //!< CAmNodeReferenceList vector with pointers to nodes for direct access
+ CAmVertexReferenceList mPointersAdjList; //!< CAmVertexReferenceList vector with pointers to vertices for direct access
+ bool mIsCyclic; //!< bool the graph has cycles or not
+
+ struct IterateThroughAllNodesDelegate
+ {
+ CAmNode<T> *source;
+ CAmNode<T> *destination;
+ CAmNodeReferenceList visited;
+ std::function<bool(const CAmNode<T> *)> shouldVisitNode;
+ std::function<void(const CAmNode<T> *)> willVisitNode;
+ std::function<void(const CAmNode<T> *)> didVisitNode;
+ std::function<void(const CAmNodeReferenceList &path)> didFindPath;
+ };
+
+ struct VisitNodeDelegate
+ {
+ CAmNode<T> *source;
+ CAmNode<T> *destination;
+ std::function<void(const am_GraphPathPosition_e, CAmNode<T> &)> visitedNode;
+ };
+
+ /**
+ * Updates the node indexes after adding or removing nodes.
+ *
+ * @param fromIndex updates all nodes from given index.
+ */
+ void updateIndexes(const int16_t fromIndex)
+ {
+ if ( fromIndex < mPointersNodes.size())
+ {
+ for (auto iter = mPointersNodes.begin() + fromIndex; iter != mPointersNodes.end(); iter++)
+ {
+ (*iter)->setIndex(iter - mPointersNodes.begin());
+ }
+ }
+ }
+
+ /**
+ * Finds the shortest path and the minimal weights from given node.
+ *
+ * @param node start node.
+ * @param minDistance vector with all result distances.
+ * @param previous vector with previous nodes.
+ */
+
+ typedef uint16_t vertex_t;
+ typedef uint16_t weight_t;
+
+ void findShortestPathsFromNode(const CAmNode<T> &node, std::vector<weight_t> &minDistance, std::vector<CAmNode<T> *> &previous)
+ {
+ typename CAmListVertices::const_iterator nIter;
+ CAmListVertices *neighbors;
+ weight_t dist, weight, v, distanceThroughU;
+ CAmNode<T> *pU;
+ CAmVertex<T, V> *pVertex;
+ CAmNode<T> *pDstNode;
+
+ size_t n = mPointersAdjList.size();
+ std::set<std::pair<weight_t, CAmNode<T> *> > vertexQueue;
+
+ minDistance.clear();
+ minDistance.resize(n, std::numeric_limits<weight_t>::max());
+ minDistance[node.getIndex()] = 0;
+ previous.clear();
+ previous.resize(n, NULL);
+
+ vertexQueue.insert(std::make_pair(minDistance[node.getIndex()], (CAmNode<T> *) & node));
+
+ while (!vertexQueue.empty())
+ {
+ dist = vertexQueue.begin()->first;
+ pU = vertexQueue.begin()->second;
+ vertexQueue.erase(vertexQueue.begin());
+ // todo: terminate the search at this position if you want the path to a target node ( if(pU==target)break; )
+
+ // Visit each edge exiting u
+ neighbors = mPointersAdjList[pU->getIndex()];
+ nIter = neighbors->begin();
+ for (; nIter != neighbors->end(); nIter++)
+ {
+ pVertex = (CAmVertex<T, V> *) & (*nIter);
+ pDstNode = pVertex->getNode();
+
+ v = pDstNode->getIndex();
+ weight = pVertex->getWeight();
+ distanceThroughU = dist + weight;
+ if (distanceThroughU < minDistance[pDstNode->getIndex()])
+ {
+ vertexQueue.erase(std::make_pair(minDistance[v], pDstNode));
+ minDistance[v] = distanceThroughU;
+ previous[v] = pU;
+ vertexQueue.insert(std::make_pair(minDistance[v], pDstNode));
+ }
+ }
+ }
+ }
+
+ /**
+ * Constructs a path to given node after findShortestsPathsFromNode has been called.
+ *
+ * @param node end node.
+ * @param previous vector with previous nodes.
+ * @param result result path.
+ */
+ void constructShortestPathTo(const CAmNode<T> &node, const std::vector<CAmNode<T> *> &previous, CAmListNodePtrs &result)
+ {
+ CAmNode<T> *vertex = (CAmNode<T> *) & node;
+
+ int i = 0;
+ while ((vertex = previous[vertex->getIndex()]) != NULL )
+ {
+ result.insert(result.begin(), vertex);
+ i++;
+ }
+
+ if (i)
+ {
+ result.push_back((CAmNode<T> *) & node);
+ }
+ }
+
+ /**
+ * Calls a function with every node from this path after findShortestsPathsFromNode has been called.
+ * The construction of the path is delegated to the caller.
+ *
+ * @param node end node.
+ * @param previous vector with previous nodes.
+ * @param cb callback which is mostly used for constructing.
+ */
+ void constructShortestPathTo(const CAmNode<T> &node, const std::vector<CAmNode<T> *> &previous, std::function<void(const am_GraphPathPosition_e pos, CAmNode<T> &)> cb)
+ {
+ CAmNode<T> *vertex = (CAmNode<T> *) & node;
+ CAmNode<T> *prev = vertex;
+ int i = 0;
+ while ((vertex = previous[vertex->getIndex()]) != NULL )
+ {
+ cb(i == 0 ? GRAPH_PATH_START : GRAPH_PATH_MIDDLE, *prev);
+ prev = vertex;
+ i++;
+ }
+
+ if (i)
+ {
+ cb(GRAPH_PATH_END, *prev);
+ }
+ }
+
+ /**
+ * Iterate through the nodes and generate all paths to given node.
+ *
+ * @param dst end node.
+ * @param visited vector with current path.
+ * @param delegate enumeration delegate.
+ */
+ void findAllPaths(IterateThroughAllNodesDelegate &delegate)
+ {
+ CAmListVertices *nodes = mPointersAdjList[delegate.visited.back()->getIndex()];
+ CAmListVerticesItrConst vItr(nodes->begin());
+
+ CAmVertex<T, V> *pNextVertex;
+ CAmNode<T> *pNextNode;
+ for (; vItr != nodes->end(); ++vItr)
+ {
+ pNextVertex = (CAmVertex<T, V> *) & (*vItr);
+ pNextNode = pNextVertex->getNode();
+ if (
+ pNextNode->getStatus() != GES_NOT_VISITED ||
+ !delegate.shouldVisitNode(pNextNode)
+ )
+ {
+ continue;
+ }
+
+ if (pNextNode == delegate.destination)
+ {
+ delegate.willVisitNode(pNextNode);
+ pNextNode->setStatus(GES_IN_PROGRESS);
+ delegate.visited.push_back(pNextNode);
+ // notify observer
+ delegate.didFindPath(delegate.visited);
+ // remove last node from the list
+ auto last = delegate.visited.end() - 1;
+ delegate.visited.erase(last);
+ pNextNode->setStatus(GES_NOT_VISITED);
+ delegate.didVisitNode(pNextNode);
+ break;
+ }
+ }
+
+ vItr = nodes->begin();
+ // bfs like loop
+ for (; vItr != nodes->end(); ++vItr)
+ {
+ pNextVertex = (CAmVertex<T, V> *) & (*vItr);
+ pNextNode = pNextVertex->getNode();
+
+ if (pNextNode->getStatus() != GES_NOT_VISITED ||
+ pNextNode == delegate.destination ||
+ !delegate.shouldVisitNode(pNextNode)
+ )
+ {
+ continue;
+ }
+
+ delegate.willVisitNode(pNextNode);
+ pNextNode->setStatus(GES_IN_PROGRESS);
+ delegate.visited.push_back(pNextNode);
+ findAllPaths(delegate);
+ // remove last node from the list
+ auto last = delegate.visited.end() - 1;
+ delegate.visited.erase(last);
+ pNextNode->setStatus(GES_NOT_VISITED);
+ delegate.didVisitNode(pNextNode);
+ }
+ }
+
+public:
+
+ explicit CAmGraph(const std::vector<T> &v)
+ : mStoreNodes()
+ , mStoreAdjList()
+ , mPointersNodes()
+ , mPointersAdjList()
+ {
+ typedef typename std::vector<T>::const_iterator inItr;
+ inItr itr(v.begin());
+
+ for (; itr != v.end(); ++itr)
+ {
+ addNode(*itr);
+ }
+
+ mIsCyclic = false;
+ }
+
+ CAmGraph()
+ : mStoreNodes()
+ , mStoreAdjList()
+ , mPointersNodes()
+ , mPointersAdjList()
+ , mIsCyclic(false){}
+ ~CAmGraph(){}
+
+ const CAmListNodes &getNodes() const
+ {
+ return mStoreNodes;
+ }
+
+ const CAmVertexReferenceList &getVertexList() const
+ {
+ return mPointersAdjList;
+ }
+
+ /**
+ * Returns pointer to a node which data is equal to the given.
+ * @return pointer to a node or NULL.
+ */
+ const CAmNode<T> *findNode(const T &in)
+ {
+ typename CAmNodeReferenceList::const_iterator itr(mPointersNodes.begin());
+
+ for (; itr != mPointersNodes.end(); ++itr)
+ {
+ if ((*itr)->getData() == in)
+ {
+ return (*itr);
+ }
+ }
+
+ return NULL;
+ }
+
+ /**
+ * Returns pointer to a vertex which two ends are equal to the given nodes.
+ * @return pointer to a vertex or NULL.
+ */
+ const CAmVertex<T, V> *findVertex(const CAmNode<T> &edge1, const CAmNode<T> &edge2) const
+ {
+ const CAmNode<T> *pEdge2 = (CAmNode<T> *) & edge2;
+ const CAmListVertices *list = mPointersAdjList[edge1.getIndex()];
+ CAmListVerticesItrConst result = std::find_if(list->begin(), list->end(), [&](const CAmVertex<T, V> &refObject){
+ return refObject.getNode() == pEdge2;
+ });
+ if (result != list->end())
+ {
+ return (CAmVertex<T, V> *) & (*result);
+ }
+
+ return NULL;
+ }
+
+ bool hasCycles() const
+ {
+ return mIsCyclic;
+ }
+
+ /**
+ * Adds a new node to the graph with given user data.
+ * @return reference to the newly inserted node.
+ */
+ CAmNode<T> &addNode(const T &in)
+ {
+ size_t index = mStoreNodes.size();
+ mStoreNodes.emplace_back(in, index);
+ mStoreAdjList.emplace_back();
+ mPointersNodes.push_back(&mStoreNodes.back());
+ mPointersAdjList.push_back(&mStoreAdjList.back());
+ return mStoreNodes.back();
+ }
+
+ /**
+ * Removes a vertex with two ends equal to the given nodes .
+ */
+ void removeVertex(const CAmNode<T> &edge1, const CAmNode<T> &edge2)
+ {
+ const CAmListVertices *list = mPointersAdjList[edge1.getIndex()];
+ CAmListVerticesItr iter = std::find_if(list->begin(), list->end(), [&edge2](const CAmVertex<T, V> &refVertex){
+ return (refVertex.getNode() == &edge2);
+ });
+ if (iter != list->end())
+ {
+ list->erase(iter);
+ }
+ }
+
+ /**
+ * Removes all vertices to given node .
+ */
+ void removeAllVerticesToNode(const CAmNode<T> &node)
+ {
+ auto comparator = [&node](const CAmVertex<T, V> &refVertex){
+ return (refVertex.getNode() == &node);
+ };
+ auto itr = mPointersAdjList.begin();
+ for (; itr != mPointersAdjList.end(); itr++)
+ {
+ CAmListVertices *vertices = *itr;
+ auto iterVert = std::find_if(vertices->begin(), vertices->end(), comparator);
+ if (iterVert != vertices->end())
+ {
+ vertices->erase(iterVert);
+ }
+ }
+ }
+
+ /**
+ * Removes a node with given user data .
+ */
+ void removeNode(const T &in)
+ {
+ CAmNode<T> *node = findNode(in);
+ if (node != NULL)
+ {
+ removeNode(*node);
+ }
+ }
+
+ /**
+ * Removes the given node from the graph .
+ */
+ void removeNode(const CAmNode<T> &node)
+ {
+ uint16_t index = node.getIndex();
+ removeAllVerticesToNode(node);
+ mPointersAdjList.erase(mPointersAdjList.begin() + index);
+ mPointersNodes.erase(mPointersNodes.begin() + index);
+ auto iter = std::find_if(mStoreNodes.begin(), mStoreNodes.end(), [&node](const CAmNode<T> &otherNode){
+ return &otherNode == &node;
+ });
+ if (iter != mStoreNodes.end())
+ {
+ mStoreNodes.erase(iter);
+ }
+
+ updateIndexes(index);
+ }
+
+ /**
+ * Connect first with last node and set user data and weight to the vertex.
+ */
+ void connectNodes(const CAmNode<T> &first, const CAmNode<T> &last, const V &vertexData, const int16_t weight = 1)
+ {
+ CAmListVertices *list = mPointersAdjList[first.getIndex()];
+ CAmNode<T> *node = mPointersNodes[last.getIndex()];
+ list->emplace_back(node, vertexData, weight);
+ }
+
+ /**
+ * Exists any vertex with two given ends.
+ * @return TRUE on successfully changed ID.
+ */
+ bool isAnyVertex(const CAmNode<T> &edge1, const CAmNode<T> &edge2) const
+ {
+ return findVertex(edge1, edge2) != NULL;
+ }
+
+ /**
+ * Sets the status of all nodes and vertices to GES_NOT_VISITED.
+ */
+ void reset()
+ {
+ // set all nodes to GES_NOT_VISITED
+ std::for_each(mPointersNodes.begin(), mPointersNodes.end(), [](CAmNode<T> *refNode){
+ if (refNode->getStatus() != GES_NOT_VISITED)
+ {
+ refNode->setStatus(GES_NOT_VISITED);
+ }
+ });
+ // set all vertices to GES_NOT_VISITED
+ auto action = [](CAmVertex<T, V> &refVertex){
+ if (refVertex.getStatus() != GES_NOT_VISITED)
+ {
+ refVertex.setStatus(GES_NOT_VISITED);
+ }
+ };
+ auto itr1(mPointersAdjList.begin());
+ for (; itr1 != mPointersAdjList.end(); ++itr1)
+ {
+ CAmListVertices *vertices = *itr1;
+ std::for_each(vertices->begin(), vertices->end(), action);
+ }
+ }
+
+ /**
+ * Clears all nodes and vertices.
+ */
+ void clear()
+ {
+ mStoreNodes.clear();
+ mStoreAdjList.clear();
+ mPointersAdjList.clear();
+ mPointersNodes.clear();
+ mPointersAdjList.clear();
+ }
+
+ /**
+ * Goes through all nodes and vertices and calls the callback.
+ */
+ void trace(std::function<void(const CAmNode<T> &, const std::vector<CAmVertex<T, V> *> &)> cb)
+ {
+ std::for_each(mPointersNodes.begin(), mPointersNodes.end(), [&](CAmNode<T> *refNode){
+ CAmListVertices *vertices = this->mPointersAdjList[refNode->getIndex()];
+ std::vector<CAmVertex<T, V> *> list;
+ std::for_each(vertices->begin(), vertices->end(), [&list](CAmVertex<T, V> &refVertex){
+ list.push_back(&refVertex);
});
- if(iter!=mStoreNodes.end())
- mStoreNodes.erase(iter);
- updateIndexes(index);
- }
-
- /**
- * Connect first with last node and set user data and weight to the vertex.
- */
- void connectNodes(const CAmNode<T> & first, const CAmNode<T> & last, const V & vertexData, const int16_t weight = 1)
- {
- CAmListVertices * list = mPointersAdjList[first.getIndex()];
- CAmNode<T> * node = mPointersNodes[last.getIndex()];
- list->emplace_back(node, vertexData, weight);
- }
-
- /**
- * Exists any vertex with two given ends.
- * @return TRUE on successfully changed ID.
- */
- bool isAnyVertex(const CAmNode<T> & edge1, const CAmNode<T> & edge2) const
- {
- return findVertex(edge1, edge2)!=NULL;
- }
-
- /**
- * Sets the status of all nodes and vertices to GES_NOT_VISITED.
- */
- void reset()
- {
- // set all nodes to GES_NOT_VISITED
- std::for_each(mPointersNodes.begin(), mPointersNodes.end(), [](CAmNode<T> * refNode){
- if(refNode->getStatus()!= GES_NOT_VISITED)
- refNode->setStatus(GES_NOT_VISITED);
- });
- // set all vertices to GES_NOT_VISITED
- auto action = [](CAmVertex<T,V> & refVertex){
- if(refVertex.getStatus()!= GES_NOT_VISITED)
- refVertex.setStatus(GES_NOT_VISITED);
- };
- auto itr1(mPointersAdjList.begin());
- for (; itr1 != mPointersAdjList.end(); ++itr1)
- {
- CAmListVertices * vertices = *itr1;
- std::for_each(vertices->begin(), vertices->end(), action);
- }
- }
-
- /**
- * Clears all nodes and vertices.
- */
- void clear()
- {
- mStoreNodes.clear();
- mStoreAdjList.clear();
- mPointersAdjList.clear();
- mPointersNodes.clear();
- mPointersAdjList.clear();
- }
-
- /**
- * Goes through all nodes and vertices and calls the callback.
- */
- void trace(std::function<void(const CAmNode<T> &, const std::vector<CAmVertex<T,V>*> &)> cb)
- {
- std::for_each(mPointersNodes.begin(), mPointersNodes.end(), [&](CAmNode<T> * refNode){
- CAmListVertices * vertices = this->mPointersAdjList[refNode->getIndex()];
- std::vector<CAmVertex<T,V>*> list;
- std::for_each(vertices->begin(), vertices->end(), [&list](CAmVertex<T,V> & refVertex){
- list.push_back(&refVertex);
- });
- cb(*refNode, list);
- });
- }
-
- /**
- * Finds the shortest path from given node to all nodes in listTargets.
- *
- * @param source start node.
- * @param listTargets destination nodes.
- * @param resultPath list with all shortest paths.
- */
- void getShortestPath(const CAmNode<T> & source, const CAmListNodePtrs & listTargets, std::vector<CAmListNodePtrs> & resultPath )
- {
- const size_t numberOfNodes = mPointersNodes.size();
- if(numberOfNodes==0)
- return;
-
- std::vector<weight_t> min_distance;
- std::vector<CAmNode<T>*> previous;
- findShortestPathsFromNode(source, min_distance, previous);
-
- for(auto it=listTargets.begin(); it!=listTargets.end(); it++)
- {
- CAmNode<T> *node = *it;
- resultPath.emplace_back();
- CAmListNodePtrs & path = resultPath.back();
- constructShortestPathTo(*node, previous, path);
- if(path.empty())
- {
- typename std::vector<CAmListNodePtrs>::iterator iter = resultPath.end();
- resultPath.erase(--iter);
- }
- }
- }
-
- /**
- * Finds the shortest path between two nodes.
- *
- * @param source start node.
- * @param destination destination node.
- * @param resultPath list with the found shortest paths.
- */
- void getShortestPath(const CAmNode<T> & source, const CAmNode<T> & destination, CAmListNodePtrs & resultPath )
- {
- const size_t numberOfNodes = mPointersNodes.size();
- if(numberOfNodes==0)
- return;
- std::vector<weight_t> min_distance;
- std::vector<CAmNode<T>*> previous;
- findShortestPathsFromNode(source, min_distance, previous);
- constructShortestPathTo(destination, previous, resultPath);
- }
-
- /**
- * Finds the shortest path from given node to all nodes in listTargets.
- * Delegates the construction of the path to the caller.
- *
- * @param source start node.
- * @param listTargets destination nodes.
- * @param cb callabck.
- */
- void getShortestPath(const CAmNode<T> & source,
- const CAmListNodePtrs & listTargets,
- std::function<void(const am_GraphPathPosition_e, CAmNode<T> &)> cb )
- {
- const size_t numberOfNodes = mPointersNodes.size();
- if(numberOfNodes==0)
- return;
-
- std::vector<weight_t> min_distance;
- std::vector<CAmNode<T>*> previous;
- findShortestPathsFromNode(source, min_distance, previous);
-
- for(auto it=listTargets.begin(); it!=listTargets.end(); it++)
- {
- CAmNode<T>* node = *it;
- constructShortestPathTo(*node, previous, cb);
- }
- }
-
- /**
- * Finds the shortest path between two given nodes.
- * Delegates the construction of the path to the caller.
- *
- * @param source start node.
- * @param destination destination node.
- * @param cb callabck.
- */
- void getShortestPath(const CAmNode<T> & source,
- const CAmNode<T> & destination,
- std::function<void(const am_GraphPathPosition_e, CAmNode<T> &)> cb )
- {
- const size_t numberOfNodes = mPointersNodes.size();
- if(numberOfNodes==0)
- return;
-
- std::vector<weight_t> min_distance;
- std::vector<CAmNode<T>*> previous;
- findShortestPathsFromNode(source, min_distance, previous);
- constructShortestPathTo(destination, previous, cb);
- }
-
- /**
- * Finds all possible paths between two given nodes.
- * Delegates the construction of the path to the caller.
- *
- * @param src start node.
- * @param dst destination node.
- * @param cbShouldVisitNode ask the delegate if we should proceed with the current node.
- * @param cbWillVisitNode tell the delegate the current node will be visited.
- * @param cbDidVisitNode tell the delegate the current node was visited.
- * @param cbDidFindPath return the path to the delegate.
- */
- void getAllPaths(CAmNode<T> & src,
- CAmNode<T> & dst,
- std::function<bool(const CAmNode<T> * )> cbShouldVisitNode,
- std::function<void(const CAmNode<T> *)> cbWillVisitNode,
- std::function<void(const CAmNode<T> *)> cbDidVisitNode,
- std::function<void(const CAmNodeReferenceList & path)> cbDidFindPath)
- {
- IterateThroughAllNodesDelegate delegate;
- delegate.source = &src;
- delegate.destination = &dst;
- delegate.shouldVisitNode = cbShouldVisitNode;
- delegate.willVisitNode = cbWillVisitNode;
- delegate.didVisitNode = cbDidVisitNode;
- delegate.didFindPath = cbDidFindPath;
- delegate.visited.push_back((CAmNode<T>*)&src);
- ((CAmNode<T>*)&src)->setStatus(GES_VISITED);
- findAllPaths(delegate);
- ((CAmNode<T>*)&src)->setStatus(GES_NOT_VISITED);
- }
- };
+ cb(*refNode, list);
+ });
+ }
+
+ /**
+ * Finds the shortest path from given node to all nodes in listTargets.
+ *
+ * @param source start node.
+ * @param listTargets destination nodes.
+ * @param resultPath list with all shortest paths.
+ */
+ void getShortestPath(const CAmNode<T> &source, const CAmListNodePtrs &listTargets, std::vector<CAmListNodePtrs> &resultPath)
+ {
+ const size_t numberOfNodes = mPointersNodes.size();
+ if (numberOfNodes == 0)
+ {
+ return;
+ }
+
+ std::vector<weight_t> min_distance;
+ std::vector<CAmNode<T> *> previous;
+ findShortestPathsFromNode(source, min_distance, previous);
+
+ for (auto it = listTargets.begin(); it != listTargets.end(); it++)
+ {
+ CAmNode<T> *node = *it;
+ resultPath.emplace_back();
+ CAmListNodePtrs &path = resultPath.back();
+ constructShortestPathTo(*node, previous, path);
+ if (path.empty())
+ {
+ typename std::vector<CAmListNodePtrs>::iterator iter = resultPath.end();
+ resultPath.erase(--iter);
+ }
+ }
+ }
+
+ /**
+ * Finds the shortest path between two nodes.
+ *
+ * @param source start node.
+ * @param destination destination node.
+ * @param resultPath list with the found shortest paths.
+ */
+ void getShortestPath(const CAmNode<T> &source, const CAmNode<T> &destination, CAmListNodePtrs &resultPath)
+ {
+ const size_t numberOfNodes = mPointersNodes.size();
+ if (numberOfNodes == 0)
+ {
+ return;
+ }
+
+ std::vector<weight_t> min_distance;
+ std::vector<CAmNode<T> *> previous;
+ findShortestPathsFromNode(source, min_distance, previous);
+ constructShortestPathTo(destination, previous, resultPath);
+ }
+
+ /**
+ * Finds the shortest path from given node to all nodes in listTargets.
+ * Delegates the construction of the path to the caller.
+ *
+ * @param source start node.
+ * @param listTargets destination nodes.
+ * @param cb callabck.
+ */
+ void getShortestPath(const CAmNode<T> &source,
+ const CAmListNodePtrs &listTargets,
+ std::function<void(const am_GraphPathPosition_e, CAmNode<T> &)> cb)
+ {
+ const size_t numberOfNodes = mPointersNodes.size();
+ if (numberOfNodes == 0)
+ {
+ return;
+ }
+
+ std::vector<weight_t> min_distance;
+ std::vector<CAmNode<T> *> previous;
+ findShortestPathsFromNode(source, min_distance, previous);
+
+ for (auto it = listTargets.begin(); it != listTargets.end(); it++)
+ {
+ CAmNode<T> *node = *it;
+ constructShortestPathTo(*node, previous, cb);
+ }
+ }
+
+ /**
+ * Finds the shortest path between two given nodes.
+ * Delegates the construction of the path to the caller.
+ *
+ * @param source start node.
+ * @param destination destination node.
+ * @param cb callabck.
+ */
+ void getShortestPath(const CAmNode<T> &source,
+ const CAmNode<T> &destination,
+ std::function<void(const am_GraphPathPosition_e, CAmNode<T> &)> cb)
+ {
+ const size_t numberOfNodes = mPointersNodes.size();
+ if (numberOfNodes == 0)
+ {
+ return;
+ }
+
+ std::vector<weight_t> min_distance;
+ std::vector<CAmNode<T> *> previous;
+ findShortestPathsFromNode(source, min_distance, previous);
+ constructShortestPathTo(destination, previous, cb);
+ }
+
+ /**
+ * Finds all possible paths between two given nodes.
+ * Delegates the construction of the path to the caller.
+ *
+ * @param src start node.
+ * @param dst destination node.
+ * @param cbShouldVisitNode ask the delegate if we should proceed with the current node.
+ * @param cbWillVisitNode tell the delegate the current node will be visited.
+ * @param cbDidVisitNode tell the delegate the current node was visited.
+ * @param cbDidFindPath return the path to the delegate.
+ */
+ void getAllPaths(CAmNode<T> &src,
+ CAmNode<T> &dst,
+ std::function<bool(const CAmNode<T> *)> cbShouldVisitNode,
+ std::function<void(const CAmNode<T> *)> cbWillVisitNode,
+ std::function<void(const CAmNode<T> *)> cbDidVisitNode,
+ std::function<void(const CAmNodeReferenceList &path)> cbDidFindPath)
+ {
+ IterateThroughAllNodesDelegate delegate;
+ delegate.source = &src;
+ delegate.destination = &dst;
+ delegate.shouldVisitNode = cbShouldVisitNode;
+ delegate.willVisitNode = cbWillVisitNode;
+ delegate.didVisitNode = cbDidVisitNode;
+ delegate.didFindPath = cbDidFindPath;
+ delegate.visited.push_back((CAmNode<T> *) & src);
+ ((CAmNode<T> *) & src)->setStatus(GES_VISITED);
+ findAllPaths(delegate);
+ ((CAmNode<T> *) & src)->setStatus(GES_NOT_VISITED);
+ }
+
+};
}
-#endif
+#endif // ifndef GRAPH_H