Implemented collisions.

This commit is contained in:
2016-12-17 15:40:40 +02:00
parent 42f0d4125b
commit a7af100122
14 changed files with 651 additions and 11 deletions

View File

@@ -9,6 +9,7 @@
#define UTILS_QTREE_H_
#include <utils/Assert.h>
#include <utils/Exceptions.h>
#include <utils/INonAssignable.h>
#include <utils/Rect.h>
@@ -58,7 +59,7 @@ namespace utils {
/**
* Quad tree
*/
template <typename T, size_t Capacity>
template <typename T, size_t Capacity = 16>
class QTree : public INonAssignable
{
public:
@@ -74,11 +75,13 @@ namespace utils {
bool empty() const;
size_t size() const;
void insert(T element, float x, float y);
void insert(const T& element, float x, float y);
void move(iterator it, float newX, float newY);
void erase(iterator it);
void clear();
iterator find(T element);
iterator find(const T& element);
iterator find(const T& element, float x, float y);
iterator lower_bound(const RectF& area);
iterator upper_bound(const RectF& area);
@@ -312,7 +315,7 @@ namespace utils {
}
template<typename T, size_t Capacity>
void QTree<T, Capacity>::insert(T element, float x, float y)
void QTree<T, Capacity>::insert(const T& element, float x, float y)
{
Assert(m_bounds.contains(x, y), "Can't add element outside bounds.");
@@ -344,6 +347,54 @@ namespace utils {
}
}
template<typename T, size_t Capacity>
void QTree<T, Capacity>::move(iterator it, float newX, float newY)
{
Assert(!it.m_tree->m_isSplit, "Container modified.");
Assert(it.m_item < it.m_tree->m_itemsCount, "Container modified.");
// Find destination tree
QTree<T, Capacity>* destTree = this;
bool found = false;
do
{
// Go to parent
if (!destTree->m_bounds.contains(newX, newY))
destTree = destTree->m_parent;
// Go to child
else if (destTree->m_isSplit)
{
for (size_t i = 0; i < 4; i++)
if (destTree->m_children[i]->m_bounds.contains(newX, newY))
{
destTree = destTree->m_children[i];
break;
}
}
else
{
found = true;
}
} while (!found && destTree != nullptr);
if (destTree == nullptr)
THROW(InvalidArgumentException, "Iterator doesn't belong to this tree.");
// No need to move
if (destTree == it.m_tree)
{
it->x = newX;
it->y = newY;
}
// Need to move. Preform an 'erase' and an 'insert'
T dataTemp = it->data;
it.m_tree->erase(it);
destTree->insert(dataTemp, newX, newY);
}
template<typename T, size_t Capacity>
void QTree<T, Capacity>::erase(iterator it)
{
@@ -385,7 +436,7 @@ namespace utils {
}
template<typename T, size_t Capacity>
typename QTree<T, Capacity>::iterator QTree<T, Capacity>::find(T element)
typename QTree<T, Capacity>::iterator QTree<T, Capacity>::find(const T& element)
{
for (auto it = begin(); it != end(); it++)
if (it->data == element)
@@ -394,6 +445,31 @@ namespace utils {
return end();
}
template<typename T, size_t Capacity>
typename QTree<T, Capacity>::iterator QTree<T, Capacity>::find(const T& element, float x, float y)
{
if (!m_bounds.contains(x, y))
{
if (m_parent)
return m_parent->find(element, x, y);
return end();
}
if (m_isSplit)
{
for (size_t i = 0; i < 4; i++)
if (m_children[i]->m_bounds.contains(x, y))
return m_children[i]->find(element, x, y);
}
else
{
for (size_t i = 0; i < m_itemsCount; i++)
if (m_items[i].data == element && m_items[i].x == x && m_items[i].y == y)
return iterator(this, RectF(x, y, 0, 0), i);
}
return end();
}
template<typename T, size_t Capacity>
typename QTree<T, Capacity>::iterator QTree<T, Capacity>::lower_bound(const RectF& area)
{