polyvox/include/PolyVox/Impl/AStarPathfinderImpl.h

224 lines
5.1 KiB
C++

/*******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2015 David Williams and Matthew Williams
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*******************************************************************************/
#ifndef __PolyVox_AStarPathfinderImpl_H__
#define __PolyVox_AStarPathfinderImpl_H__
#include "../Vector.h"
#include <algorithm>
#include <limits> //For numeric_limits
#include <set>
#include <vector>
namespace PolyVox
{
class OpenNodesContainer;
class ClosedNodesContainer;
/// The Connectivity of a voxel determines how many neighbours it has.
enum Connectivity
{
/// Each voxel has six neighbours, which are those sharing a face.
SixConnected,
/// Each voxel has 18 neighbours, which are those sharing a face or an edge.
EighteenConnected,
/// Each voxel has 26 neighbours, which are those sharing a face, edge, or corner.
TwentySixConnected
};
struct Node
{
Node(int x, int y, int z)
:gVal(std::numeric_limits<float>::quiet_NaN()) //Initilise with NaNs so that we will
, hVal(std::numeric_limits<float>::quiet_NaN()) //know if we forget to set these properly.
, parent(0)
{
position.setX(x);
position.setY(y);
position.setZ(z);
}
bool operator==(const Node& rhs) const
{
return position == rhs.position;
}
bool operator<(const Node& rhs) const
{
if (position.getX() < rhs.position.getX())
return true;
if (rhs.position.getX() < position.getX())
return false;
if (position.getY() < rhs.position.getY())
return true;
if (rhs.position.getY() < position.getY())
return false;
if (position.getZ() < rhs.position.getZ())
return true;
if (rhs.position.getZ() < position.getZ())
return false;
return false;
}
PolyVox::Vector3DInt32 position;
float gVal;
float hVal;
Node* parent;
float f(void) const
{
return gVal + hVal;
}
};
typedef std::set<Node> AllNodesContainer;
class AllNodesContainerIteratorComparator
{
public:
bool operator() (const AllNodesContainer::iterator& lhs, const AllNodesContainer::iterator& rhs) const
{
return (&(*lhs)) < (&(*rhs));
}
};
class NodeSort
{
public:
bool operator() (const AllNodesContainer::iterator& lhs, const AllNodesContainer::iterator& rhs) const
{
return lhs->f() > rhs->f();
}
};
class OpenNodesContainer
{
public:
typedef std::vector<AllNodesContainer::iterator>::iterator iterator;
public:
void clear(void)
{
open.clear();
}
bool empty(void) const
{
return open.empty();
}
void insert(AllNodesContainer::iterator node)
{
open.push_back(node);
push_heap(open.begin(), open.end(), NodeSort());
}
AllNodesContainer::iterator getFirst(void)
{
return open[0];
}
void removeFirst(void)
{
pop_heap(open.begin(), open.end(), NodeSort());
open.pop_back();
}
void remove(iterator iterToRemove)
{
open.erase(iterToRemove);
make_heap(open.begin(), open.end(), NodeSort());
}
iterator begin(void)
{
return open.begin();
}
iterator end(void)
{
return open.end();
}
iterator find(AllNodesContainer::iterator node)
{
std::vector<AllNodesContainer::iterator>::iterator openIter = std::find(open.begin(), open.end(), node);
return openIter;
}
private:
std::vector<AllNodesContainer::iterator> open;
};
class ClosedNodesContainer
{
public:
typedef std::set<AllNodesContainer::iterator, AllNodesContainerIteratorComparator>::iterator iterator;
public:
void clear(void)
{
closed.clear();
}
void insert(AllNodesContainer::iterator node)
{
closed.insert(node);
}
void remove(iterator iterToRemove)
{
closed.erase(iterToRemove);
}
iterator begin(void)
{
return closed.begin();
}
iterator end(void)
{
return closed.end();
}
iterator find(AllNodesContainer::iterator node)
{
iterator iter = std::find(closed.begin(), closed.end(), node);
return iter;
}
private:
std::set<AllNodesContainer::iterator, AllNodesContainerIteratorComparator> closed;
};
//bool operator<(const AllNodesContainer::iterator& lhs, const AllNodesContainer::iterator& rhs);
}
#endif //__PolyVox_AStarPathfinderImpl_H__