quad tree: moving definitions after class declaration

master
dmatetelki 8 years ago
parent 3ae7d3812e
commit d54c349b2c

@ -27,34 +27,86 @@ struct AABB
const P m_center; const P m_center;
const typename P::value_type m_halfDimension; const typename P::value_type m_halfDimension;
constexpr AABB(const P& center, typename P::value_type halfDimension) constexpr AABB(const P& center, typename P::value_type halfDimension);
bool containsPoint(const P& p) const;
bool intersectsAABB(const AABB& other) const;
};
template <typename P>
class QuadTree {
public:
QuadTree(const AABB<P>& boundary);
QuadTree(const QuadTree& other);
QuadTree(QuadTree&& other);
QuadTree& operator=(const QuadTree other) { swap(other); return *this; }
void swap(QuadTree& other);
~QuadTree();
bool insert(const P& p);
std::vector<P> queryRange(const AABB<P>& range) const;
std::vector<P> points() const;
private:
void subdivide();
// Arbitrary constant to indicate how many elements can be stored in this quad tree node
static const std::size_t m_node_capacity = 4;
// Axis-aligned bounding box stored as a center with half-dimensions
// to represent the boundaries of this quad tree
const AABB<P> m_boundary;
// Points in this quad tree node
std::vector<P> m_points;
// Children
QuadTree* m_northWest;
QuadTree* m_northEast;
QuadTree* m_southWest;
QuadTree* m_southEast;
};
// AABB implementation
template <typename P>
constexpr AABB<P>::AABB(const P& center, typename P::value_type halfDimension)
: m_center(center) : m_center(center)
, m_halfDimension(halfDimension) {} , m_halfDimension(halfDimension) {}
bool containsPoint(const P& p) const { template <typename P>
bool AABB<P>::containsPoint(const P& p) const {
return (std::fabs(m_center.x - p.x) <= m_halfDimension) && return (std::fabs(m_center.x - p.x) <= m_halfDimension) &&
(std::fabs(m_center.y - p.y) <= m_halfDimension); (std::fabs(m_center.y - p.y) <= m_halfDimension);
} }
bool intersectsAABB(const AABB& other) const { template <typename P>
bool AABB<P>::intersectsAABB(const AABB& other) const {
return (std::fabs(m_center.x - other.m_center.x) <= m_halfDimension + other.m_halfDimension) && return (std::fabs(m_center.x - other.m_center.x) <= m_halfDimension + other.m_halfDimension) &&
(std::fabs(m_center.y - other.m_center.y) <= m_halfDimension + other.m_halfDimension); (std::fabs(m_center.y - other.m_center.y) <= m_halfDimension + other.m_halfDimension);
} }
};
template <typename P>
class QuadTree {
public:
QuadTree(const AABB<P>& boundary)
// QuadTree implementation
template <typename P>
QuadTree<P>::QuadTree(const AABB<P>& boundary)
: m_boundary(boundary) : m_boundary(boundary)
, m_points() , m_points()
, m_northWest(0) , m_northWest(0)
, m_northEast(0) , m_northEast(0)
, m_southWest(0) , m_southWest(0)
, m_southEast(0) { m_points.reserve(m_node_capacity); } , m_southEast(0) {
m_points.reserve(m_node_capacity);
}
QuadTree(const QuadTree& other) template <typename P>
QuadTree<P>::QuadTree(const QuadTree& other)
: m_boundary (other.m_boundary) : m_boundary (other.m_boundary)
, m_points (other.m_points) , m_points (other.m_points)
, m_northWest(other.m_northWest) , m_northWest(other.m_northWest)
@ -62,7 +114,8 @@ public:
, m_southWest(other.m_southWest) , m_southWest(other.m_southWest)
, m_southEast(other.m_southEast) {} , m_southEast(other.m_southEast) {}
QuadTree(QuadTree&& other) template <typename P>
QuadTree<P>::QuadTree(QuadTree&& other)
: m_boundary (std::move(other.m_boundary)) : m_boundary (std::move(other.m_boundary))
, m_points (std::move(other.m_points)) , m_points (std::move(other.m_points))
, m_northWest(std::move(other.m_northWest)) , m_northWest(std::move(other.m_northWest))
@ -70,24 +123,26 @@ public:
, m_southWest(std::move(other.m_southWest)) , m_southWest(std::move(other.m_southWest))
, m_southEast(std::move(other.m_southEast)) {} , m_southEast(std::move(other.m_southEast)) {}
QuadTree& operator=(const QuadTree other) { swap(other); return *this; } template <typename P>
void swap(QuadTree& other) { void QuadTree<P>::swap(QuadTree& other) {
std::swap(m_boundary, other.m_boundary); std::swap(m_boundary, other.m_boundary);
std::swap(m_points, other.m_points); std::swap(m_points, other.m_points);
std::swap(m_northWest, other.m_northWest); std::swap(m_northWest, other.m_northWest);
std::swap(m_northEast, other.m_northEast); std::swap(m_northEast, other.m_northEast);
std::swap(m_southWest, other.m_southWest); std::swap(m_southWest, other.m_southWest);
std::swap(m_southEast, other.m_southEast); std::swap(m_southEast, other.m_southEast);
} }
~QuadTree() { template <typename P>
QuadTree<P>::~QuadTree() {
delete m_northWest; delete m_northWest;
delete m_northEast; delete m_northEast;
delete m_southWest; delete m_southWest;
delete m_southEast; delete m_southEast;
} }
bool insert(const P& p) { template <typename P>
bool QuadTree<P>::insert(const P& p) {
// Ignore objects that do not belong in this quad tree // Ignore objects that do not belong in this quad tree
if (!m_boundary.containsPoint(p)) if (!m_boundary.containsPoint(p))
return false; // object cannot be added return false; // object cannot be added
@ -110,10 +165,11 @@ public:
// Otherwise, the point cannot be inserted for some unknown reason (this should never happen) // Otherwise, the point cannot be inserted for some unknown reason (this should never happen)
assert(!"Programming error"); assert(!"Programming error");
return false; return false;
} }
// create four children that fully divide this quad into four quads of equal area // create four children that fully divide this quad into four quads of equal area
void subdivide() { template <typename P>
void QuadTree<P>:: subdivide() {
const typename P::value_type h = m_boundary.m_halfDimension / 2; const typename P::value_type h = m_boundary.m_halfDimension / 2;
const typename P::value_type x = m_boundary.m_center.x; const typename P::value_type x = m_boundary.m_center.x;
const typename P::value_type y = m_boundary.m_center.y; const typename P::value_type y = m_boundary.m_center.y;
@ -121,9 +177,10 @@ public:
m_northEast = new QuadTree<P>(AABB<P>(P(x + h, y - h), h)); m_northEast = new QuadTree<P>(AABB<P>(P(x + h, y - h), h));
m_southWest = new QuadTree<P>(AABB<P>(P(x - h, y + h), h)); m_southWest = new QuadTree<P>(AABB<P>(P(x - h, y + h), h));
m_southEast = new QuadTree<P>(AABB<P>(P(x + h, y + h), h)); m_southEast = new QuadTree<P>(AABB<P>(P(x + h, y + h), h));
} }
std::vector<P> queryRange(const AABB<P>& range) const { template <typename P>
std::vector<P> QuadTree<P>::queryRange(const AABB<P>& range) const {
// Prepare an array of results // Prepare an array of results
std::vector<P> pointsInRange; std::vector<P> pointsInRange;
@ -152,10 +209,10 @@ public:
pointsInRange.insert(pointsInRange.end(), se.begin(), se.end()); pointsInRange.insert(pointsInRange.end(), se.begin(), se.end());
return pointsInRange; return pointsInRange;
} }
std::vector<P> points() const {
template <typename P>
std::vector<P> QuadTree<P>::points() const {
std::vector<P> retval(m_points.begin(), m_points.end()); std::vector<P> retval(m_points.begin(), m_points.end());
// Terminate here, if there are no children // Terminate here, if there are no children
@ -173,27 +230,7 @@ public:
retval.insert(retval.end(), se.begin(), se.end()); retval.insert(retval.end(), se.begin(), se.end());
return retval; return retval;
} }
private:
// Arbitrary constant to indicate how many elements can be stored in this quad tree node
static const std::size_t m_node_capacity = 4;
// Axis-aligned bounding box stored as a center with half-dimensions
// to represent the boundaries of this quad tree
const AABB<P> m_boundary;
// Points in this quad tree node
std::vector<P> m_points;
// Children
QuadTree* m_northWest;
QuadTree* m_northEast;
QuadTree* m_southWest;
QuadTree* m_southEast;
};
#endif // QUAD_TREE_HPP #endif // QUAD_TREE_HPP

Loading…
Cancel
Save