parent
6a1105fd3e
commit
12c8638c15
@ -0,0 +1,238 @@ |
|||||||
|
/*
|
||||||
|
OneLoneCoder - Palette v1.00 |
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||||
|
Convenient tool for creating interpolated palettes, that can be |
||||||
|
sampled discretely or continuously |
||||||
|
|
||||||
|
|
||||||
|
License (OLC-3) |
||||||
|
~~~~~~~~~~~~~~~ |
||||||
|
|
||||||
|
Copyright 2018 - 2022 OneLoneCoder.com |
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without |
||||||
|
modification, are permitted provided that the following conditions |
||||||
|
are met: |
||||||
|
|
||||||
|
1. Redistributions or derivations of source code must retain the above |
||||||
|
copyright notice, this list of conditions and the following disclaimer. |
||||||
|
|
||||||
|
2. Redistributions or derivative works in binary form must reproduce |
||||||
|
the above copyright notice. This list of conditions and the following |
||||||
|
disclaimer must be reproduced in the documentation and/or other |
||||||
|
materials provided with the distribution. |
||||||
|
|
||||||
|
3. Neither the name of the copyright holder nor the names of its |
||||||
|
contributors may be used to endorse or promote products derived |
||||||
|
from this software without specific prior written permission. |
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
|
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
|
||||||
|
Links |
||||||
|
~~~~~ |
||||||
|
YouTube: https://www.youtube.com/javidx9
|
||||||
|
Discord: https://discord.gg/WhwHUMV
|
||||||
|
Twitter: https://www.twitter.com/javidx9
|
||||||
|
Twitch: https://www.twitch.tv/javidx9
|
||||||
|
GitHub: https://www.github.com/onelonecoder
|
||||||
|
Homepage: https://www.onelonecoder.com
|
||||||
|
|
||||||
|
Author |
||||||
|
~~~~~~ |
||||||
|
David Barr, aka javidx9, ©OneLoneCoder 2019, 2020, 2021, 2022 |
||||||
|
|
||||||
|
*/ |
||||||
|
|
||||||
|
/*
|
||||||
|
Example |
||||||
|
~~~~~~~ |
||||||
|
|
||||||
|
// Create palette object
|
||||||
|
olc::Palette pal; |
||||||
|
|
||||||
|
// Use a stock palette
|
||||||
|
pal = Palette(Stock::Spectrum); |
||||||
|
|
||||||
|
// Clearing a palete
|
||||||
|
pal.Clear(); |
||||||
|
|
||||||
|
// Custom palette - normalised index [0.0 ... 1.0], Colour
|
||||||
|
pal.SetColour(00.0 / 24.0, olc::Pixel(000, 000, 000)); |
||||||
|
pal.SetColour(03.0 / 24.0, olc::Pixel(000, 000, 030)); |
||||||
|
pal.SetColour(05.0 / 24.0, olc::Pixel(200, 240, 255)); |
||||||
|
pal.SetColour(12.0 / 24.0, olc::Pixel(200, 240, 255)); |
||||||
|
pal.SetColour(15.0 / 24.0, olc::Pixel(050, 100, 255)); |
||||||
|
pal.SetColour(20.0 / 24.0, olc::Pixel(245, 000, 146)); |
||||||
|
pal.SetColour(22.0 / 24.0, olc::Pixel(000, 000, 128)); |
||||||
|
pal.SetColour(24.0 / 24.0, olc::Pixel(000, 000, 000)); |
||||||
|
|
||||||
|
// Access palette via interpolation [0.0 ... 1.0]
|
||||||
|
// Continuous, Smooth, potentially slower
|
||||||
|
olc::Pixel p1 = pal.Sample(0.2); |
||||||
|
olc::Pixel p2 = pal.Sample(0.6); |
||||||
|
olc::Pixel p3 = pal.Sample(1.0); |
||||||
|
|
||||||
|
// Access palette via index [0 ... 255]
|
||||||
|
// Discrete, Not Smooth, very fast
|
||||||
|
olc::Pixel i1 = pal.Index(10);
|
||||||
|
*/ |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once |
||||||
|
|
||||||
|
#include "olcPixelGameEngine.h" |
||||||
|
|
||||||
|
namespace olc::utils |
||||||
|
{ |
||||||
|
class Palette |
||||||
|
{ |
||||||
|
public: |
||||||
|
enum class Stock |
||||||
|
{ |
||||||
|
Empty, |
||||||
|
Greyscale, |
||||||
|
ColdHot, |
||||||
|
Spectrum, |
||||||
|
}; |
||||||
|
|
||||||
|
public: |
||||||
|
// Construct empty palette (default) or populate with pre-defined
|
||||||
|
inline Palette(const Stock stock = Stock::Empty) |
||||||
|
{ |
||||||
|
switch (stock) |
||||||
|
{ |
||||||
|
case Stock::Empty: |
||||||
|
Clear(); |
||||||
|
break; |
||||||
|
case Stock::Greyscale: |
||||||
|
vColours = |
||||||
|
{ |
||||||
|
{0.0, olc::BLACK}, {1.0, olc::WHITE} |
||||||
|
}; |
||||||
|
break; |
||||||
|
case Stock::ColdHot: |
||||||
|
vColours = |
||||||
|
{ |
||||||
|
{0.0, olc::CYAN}, {0.5, olc::BLACK}, {1.0, olc::YELLOW} |
||||||
|
}; |
||||||
|
break; |
||||||
|
case Stock::Spectrum: |
||||||
|
vColours = |
||||||
|
{ |
||||||
|
{0.0 / 6.0, olc::RED}, |
||||||
|
{1.0 / 6.0, olc::YELLOW}, |
||||||
|
{2.0 / 6.0, olc::GREEN}, |
||||||
|
{3.0 / 6.0, olc::CYAN}, |
||||||
|
{4.0 / 6.0, olc::BLUE}, |
||||||
|
{5.0 / 6.0, olc::MAGENTA}, |
||||||
|
{6.0 / 6.0, olc::RED} |
||||||
|
}; |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
ReconstructIndex(); |
||||||
|
} |
||||||
|
|
||||||
|
public: |
||||||
|
// Sample continously from palette, where t is [0.0 ... 1.0]
|
||||||
|
inline olc::Pixel Sample(const double t) const |
||||||
|
{ |
||||||
|
// Return obvious sample values
|
||||||
|
if (vColours.empty()) |
||||||
|
return olc::BLACK; |
||||||
|
|
||||||
|
if (vColours.size() == 1) |
||||||
|
return vColours.front().second; |
||||||
|
|
||||||
|
// Iterate through colour entries until we find the first entry
|
||||||
|
// with a location greater than our sample point
|
||||||
|
double i = std::clamp(t, 0.0, 1.0); |
||||||
|
auto it = vColours.begin(); |
||||||
|
while (i > it->first) |
||||||
|
++it; |
||||||
|
|
||||||
|
// If that is the first entry, just return it
|
||||||
|
if (it == std::begin(vColours)) |
||||||
|
return it->second; |
||||||
|
else |
||||||
|
{ |
||||||
|
// else get the preceeding entry, and lerp between the two
|
||||||
|
// proportionally
|
||||||
|
auto it_p = std::prev(it); |
||||||
|
return olc::PixelLerp(it_p->second, it->second, |
||||||
|
float((i - it_p->first) / (it->first - it_p->first))); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Sample discretely from palette where idx is [0 ... 255]
|
||||||
|
inline olc::Pixel Index(const uint8_t idx) const |
||||||
|
{ |
||||||
|
return aIndexedPalette[idx]; |
||||||
|
} |
||||||
|
|
||||||
|
// Clear palette, defaulting to black
|
||||||
|
inline void Clear() |
||||||
|
{ |
||||||
|
vColours.clear(); |
||||||
|
aIndexedPalette.fill(olc::BLACK); |
||||||
|
} |
||||||
|
|
||||||
|
// Add a colour at a particular continuous location in palette
|
||||||
|
inline void SetColour(const double d, const olc::Pixel col) |
||||||
|
{ |
||||||
|
double i = std::clamp(d, 0.0, 1.0); |
||||||
|
|
||||||
|
// If d already exists, replace it
|
||||||
|
auto it = std::find_if(vColours.begin(), vColours.end(), |
||||||
|
[&i](const std::pair<double, olc::Pixel>& p) |
||||||
|
{ |
||||||
|
return p.first == i; |
||||||
|
}); |
||||||
|
|
||||||
|
if (it != std::end(vColours)) |
||||||
|
{ |
||||||
|
// Palette entry was found, so replace colour entry
|
||||||
|
it->second = col; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
// Palette entry not found, sp add it, and sort palette vector
|
||||||
|
vColours.push_back({ i, col }); |
||||||
|
std::sort(vColours.begin(), vColours.end(), |
||||||
|
[](const std::pair<double, olc::Pixel>& p1, std::pair<double, olc::Pixel>& p2) |
||||||
|
{ |
||||||
|
return p2.first > p1.first; |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
ReconstructIndex(); |
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
// Vector stores all palette milestones
|
||||||
|
std::vector<std::pair<double, olc::Pixel>> vColours; |
||||||
|
// Array stores fast LUT
|
||||||
|
std::array<olc::Pixel, 256> aIndexedPalette; |
||||||
|
|
||||||
|
inline void ReconstructIndex() |
||||||
|
{ |
||||||
|
// Reconstruct Indexed palette
|
||||||
|
for (int i = 0; i < 256; i++) |
||||||
|
{ |
||||||
|
double t = double(i) / 255.0; |
||||||
|
aIndexedPalette[i] = Sample(t); |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
} |
@ -0,0 +1,353 @@ |
|||||||
|
/*
|
||||||
|
OneLoneCoder - QuadTree v1.00 |
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||||
|
A Dynamic geom2d::rect<CTYPE>-Tree implementation to store objects in a 2D space |
||||||
|
with a fast retrieval. |
||||||
|
|
||||||
|
License (OLC-3) |
||||||
|
~~~~~~~~~~~~~~~ |
||||||
|
|
||||||
|
Copyright 2018 - 2022 OneLoneCoder.com |
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without |
||||||
|
modification, are permitted provided that the following conditions |
||||||
|
are met: |
||||||
|
|
||||||
|
1. Redistributions or derivations of source code must retain the above |
||||||
|
copyright notice, this list of conditions and the following disclaimer. |
||||||
|
|
||||||
|
2. Redistributions or derivative works in binary form must reproduce |
||||||
|
the above copyright notice. This list of conditions and the following |
||||||
|
disclaimer must be reproduced in the documentation and/or other |
||||||
|
materials provided with the distribution. |
||||||
|
|
||||||
|
3. Neither the name of the copyright holder nor the names of its |
||||||
|
contributors may be used to endorse or promote products derived |
||||||
|
from this software without specific prior written permission. |
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
|
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
|
||||||
|
Links |
||||||
|
~~~~~ |
||||||
|
YouTube: https://www.youtube.com/javidx9
|
||||||
|
Discord: https://discord.gg/WhwHUMV
|
||||||
|
Twitter: https://www.twitter.com/javidx9
|
||||||
|
Twitch: https://www.twitch.tv/javidx9
|
||||||
|
GitHub: https://www.github.com/onelonecoder
|
||||||
|
Homepage: https://www.onelonecoder.com
|
||||||
|
|
||||||
|
Author |
||||||
|
~~~~~~ |
||||||
|
David Barr, aka javidx9, ©OneLoneCoder 2019, 2020, 2021, 2022 |
||||||
|
|
||||||
|
*/ |
||||||
|
|
||||||
|
|
||||||
|
#pragma once |
||||||
|
|
||||||
|
#include "olcPixelGameEngine.h" |
||||||
|
#include "olcUTIL_Geometry2D.h" |
||||||
|
|
||||||
|
constexpr size_t MAX_DEPTH = 8; |
||||||
|
|
||||||
|
namespace olc::utils |
||||||
|
{ |
||||||
|
//struct geom2d::rect<CTYPE>
|
||||||
|
//{
|
||||||
|
// olc::vf2d pos;
|
||||||
|
// olc::vf2d size;
|
||||||
|
|
||||||
|
// geom2d::rect<CTYPE>(const olc::vf2d& p = { 0.0f, 0.0f }, const olc::vf2d& s = { 1.0f, 1.0f }) : pos(p), size(s)
|
||||||
|
// {
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
// constexpr bool contains(const olc::vf2d& p) const
|
||||||
|
// {
|
||||||
|
// return !(p.x < pos.x || p.y < pos.y || p.x >= (pos.x + size.x) || p.y >= (pos.y + size.y));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// constexpr bool contains(const geom2d::rect<CTYPE>& r) const
|
||||||
|
// {
|
||||||
|
// return (r.pos.x >= pos.x) && (r.pos.x + r.size.x < pos.x + size.x) &&
|
||||||
|
// (r.pos.y >= pos.y) && (r.pos.y + r.size.y < pos.y + size.y);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// constexpr bool overlaps(const geom2d::rect<CTYPE>& r) const
|
||||||
|
// {
|
||||||
|
// return (pos.x < r.pos.x + r.size.x && pos.x + size.x >= r.pos.x && pos.y < r.pos.y + r.size.y && pos.y + size.y >= r.pos.y);
|
||||||
|
// }
|
||||||
|
//};
|
||||||
|
|
||||||
|
template <typename T, typename CTYPE = float> |
||||||
|
struct QuadTreeItemLocation |
||||||
|
{ |
||||||
|
typename std::list<std::pair<geom2d::rect<CTYPE>, T>>* container = nullptr; |
||||||
|
typename std::list<std::pair<geom2d::rect<CTYPE>, T>>::iterator iterator; |
||||||
|
}; |
||||||
|
|
||||||
|
template <typename pT, typename CTYPE = float> |
||||||
|
class DynamicQuadTree |
||||||
|
{ |
||||||
|
public: |
||||||
|
DynamicQuadTree(const geom2d::rect<CTYPE>& size, const size_t nDepth = 0) |
||||||
|
{ |
||||||
|
m_depth = nDepth; |
||||||
|
m_rect = size; |
||||||
|
resize(m_rect); |
||||||
|
} |
||||||
|
|
||||||
|
// Insert a region into this area
|
||||||
|
QuadTreeItemLocation<pT> insert(const pT item, const geom2d::rect<CTYPE>& itemsize) |
||||||
|
{ |
||||||
|
for (int i = 0; i < 4; i++) |
||||||
|
{ |
||||||
|
if (geom2d::contains(m_rChild[i], itemsize)) |
||||||
|
{ |
||||||
|
// Have we reached depth limit?
|
||||||
|
if (m_depth + 1 < MAX_DEPTH) |
||||||
|
{ |
||||||
|
// No, so does child exist?
|
||||||
|
if (!m_pChild[i]) |
||||||
|
{ |
||||||
|
// No, so create it
|
||||||
|
m_pChild[i] = std::make_shared<DynamicQuadTree<pT>>(m_rChild[i], m_depth + 1); |
||||||
|
} |
||||||
|
|
||||||
|
// Yes, so add item to it
|
||||||
|
return m_pChild[i]->insert(item, itemsize); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// It didnt fit, so item must belong to this geom2d::rect<CTYPE>
|
||||||
|
m_pItems.push_back({ itemsize, item }); |
||||||
|
return { &m_pItems, std::prev(m_pItems.end()) }; |
||||||
|
} |
||||||
|
|
||||||
|
void relocate(pT item, const geom2d::rect<CTYPE>& rArea) |
||||||
|
{ |
||||||
|
// Remove it
|
||||||
|
remove(item); |
||||||
|
|
||||||
|
// Reinsert it with new location
|
||||||
|
insert(item, rArea); |
||||||
|
} |
||||||
|
|
||||||
|
size_t size() const |
||||||
|
{ |
||||||
|
size_t nCount = m_pItems.size(); |
||||||
|
for (int i = 0; i < 4; i++) |
||||||
|
if (m_pChild[i]) nCount += m_pChild[i]->size(); |
||||||
|
return nCount; |
||||||
|
} |
||||||
|
|
||||||
|
void search(const geom2d::rect<CTYPE>& rArea, std::list<pT>& listItems) const |
||||||
|
{ |
||||||
|
// First, check for items belonging to this area, add them to the list
|
||||||
|
// if there is overlap
|
||||||
|
for (const auto& p : m_pItems) |
||||||
|
{ |
||||||
|
if (geom2d::overlaps(rArea,p.first)) |
||||||
|
listItems.push_back(p.second); |
||||||
|
} |
||||||
|
|
||||||
|
// Second, recurse through children and see if they can
|
||||||
|
// add to the list
|
||||||
|
for (int i = 0; i < 4; i++) |
||||||
|
{ |
||||||
|
if (m_pChild[i]) |
||||||
|
{ |
||||||
|
// If child is entirely contained within area, recursively
|
||||||
|
// add all of its children, no need to check boundaries
|
||||||
|
if (geom2d::contains(rArea,m_rChild[i])) |
||||||
|
m_pChild[i]->items(listItems); |
||||||
|
|
||||||
|
// If child overlaps with search area then checks need
|
||||||
|
// to be made
|
||||||
|
else if (geom2d::overlaps(m_rChild[i],rArea)) |
||||||
|
m_pChild[i]->search(rArea, listItems); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
void items(std::list<pT>& listItems) const |
||||||
|
{ |
||||||
|
// No questions asked, just return child items
|
||||||
|
for (const auto& p : m_pItems) |
||||||
|
listItems.push_back(p.second); |
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++) |
||||||
|
if (m_pChild[i]) m_pChild[i]->items(listItems); |
||||||
|
} |
||||||
|
|
||||||
|
void clear() |
||||||
|
{ |
||||||
|
m_pItems.clear(); |
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++) |
||||||
|
{ |
||||||
|
if (m_pChild[i]) |
||||||
|
m_pChild[i]->clear(); |
||||||
|
else |
||||||
|
m_pChild[i].reset(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void resize(const geom2d::rect<CTYPE>& rArea) |
||||||
|
{ |
||||||
|
clear(); |
||||||
|
m_rect = rArea; |
||||||
|
olc::vf2d vChildSize = m_rect.size / 2.0f; |
||||||
|
m_rChild = |
||||||
|
{ |
||||||
|
geom2d::rect<CTYPE>(m_rect.pos, vChildSize), |
||||||
|
geom2d::rect<CTYPE>({m_rect.pos.x + vChildSize.x, m_rect.pos.y}, vChildSize), |
||||||
|
geom2d::rect<CTYPE>({m_rect.pos.x, m_rect.pos.y + vChildSize.y}, vChildSize), |
||||||
|
geom2d::rect<CTYPE>(m_rect.pos + vChildSize, vChildSize) |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
const geom2d::rect<CTYPE>& area() |
||||||
|
{ |
||||||
|
return m_rect; |
||||||
|
} |
||||||
|
|
||||||
|
protected: |
||||||
|
size_t m_depth = 0; |
||||||
|
|
||||||
|
// Area of this quadnode
|
||||||
|
geom2d::rect<CTYPE> m_rect; |
||||||
|
|
||||||
|
// 4 child areas of this quadnode
|
||||||
|
std::array<geom2d::rect<CTYPE>, 4> m_rChild{}; |
||||||
|
|
||||||
|
// 4 potential children of this quadnode
|
||||||
|
std::array<std::shared_ptr<DynamicQuadTree<pT>>, 4> m_pChild{}; |
||||||
|
|
||||||
|
// Items which belong to this quadnode
|
||||||
|
std::list<std::pair<geom2d::rect<CTYPE>, pT>> m_pItems; |
||||||
|
|
||||||
|
}; |
||||||
|
|
||||||
|
template<typename T, typename CTYPE = float> |
||||||
|
struct QuadTreeItem |
||||||
|
{ |
||||||
|
// The item Itself
|
||||||
|
T item; |
||||||
|
|
||||||
|
// A "locator" to the container/iterator that points to this item's iterator in the
|
||||||
|
// top level list - phew
|
||||||
|
QuadTreeItemLocation<typename std::list<QuadTreeItem<T, CTYPE>>::iterator> pItem; |
||||||
|
}; |
||||||
|
|
||||||
|
template <typename T, typename CTYPE = float> |
||||||
|
class QuadTreeContainer |
||||||
|
{ |
||||||
|
using IQuadtreeContainer = std::list<QuadTreeItem<T, CTYPE>>; |
||||||
|
|
||||||
|
public: |
||||||
|
QuadTreeContainer(const geom2d::rect<CTYPE>& size = { {0.0f, 0.0f}, { 100.0f, 100.0f } }, const size_t nDepth = 0) : root(size, nDepth) |
||||||
|
{ |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
// Sets the spatial coverage area of teh quadtree
|
||||||
|
void resize(const geom2d::rect<CTYPE>& rArea) |
||||||
|
{ |
||||||
|
root.resize(rArea); |
||||||
|
} |
||||||
|
|
||||||
|
// Inserts an item into the quadtree
|
||||||
|
void insert(const T& item, const geom2d::rect<CTYPE>& itemsize) |
||||||
|
{ |
||||||
|
QuadTreeItem<T> newItem; |
||||||
|
newItem.item = item; |
||||||
|
|
||||||
|
// Item i stored in container
|
||||||
|
m_allItems.emplace_back(newItem); |
||||||
|
|
||||||
|
// Pointer/Area of item is stored in geom2d::rect<CTYPE> tree
|
||||||
|
m_allItems.back().pItem = root.insert(std::prev(m_allItems.end()), itemsize); |
||||||
|
} |
||||||
|
|
||||||
|
// Returns a std::list of pointers to items within the search area
|
||||||
|
std::list<typename IQuadtreeContainer::iterator> search(const geom2d::rect<CTYPE>& rArea) const |
||||||
|
{ |
||||||
|
std::list<typename IQuadtreeContainer::iterator> listItemPointers; |
||||||
|
root.search(rArea, listItemPointers); |
||||||
|
return listItemPointers; |
||||||
|
} |
||||||
|
|
||||||
|
void remove(typename IQuadtreeContainer::iterator& item) |
||||||
|
{ |
||||||
|
// Iterator points to a QuadTreeItem
|
||||||
|
item->pItem.container->erase(item->pItem.iterator); |
||||||
|
|
||||||
|
// Remove actual item from container
|
||||||
|
m_allItems.erase(item); |
||||||
|
} |
||||||
|
|
||||||
|
void relocate(typename IQuadtreeContainer::iterator& item, const geom2d::rect<CTYPE>& itemsize) |
||||||
|
{ |
||||||
|
// Remove pointer to item from whichever container its stored in
|
||||||
|
item->pItem.container->erase(item->pItem.iterator); |
||||||
|
|
||||||
|
// Update the items pointer by reinsertion into geom2d::rect<CTYPE> tree
|
||||||
|
item->pItem = root.insert(item, itemsize); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
typename IQuadtreeContainer::iterator begin() |
||||||
|
{ |
||||||
|
return m_allItems.begin(); |
||||||
|
} |
||||||
|
|
||||||
|
typename IQuadtreeContainer::iterator end() |
||||||
|
{ |
||||||
|
return m_allItems.end(); |
||||||
|
} |
||||||
|
|
||||||
|
typename IQuadtreeContainer::const_iterator cbegin() |
||||||
|
{ |
||||||
|
return m_allItems.cbegin(); |
||||||
|
} |
||||||
|
|
||||||
|
typename IQuadtreeContainer::const_iterator cend() |
||||||
|
{ |
||||||
|
return m_allItems.cend(); |
||||||
|
} |
||||||
|
|
||||||
|
size_t size() const |
||||||
|
{ |
||||||
|
return root.size(); |
||||||
|
} |
||||||
|
|
||||||
|
void clear() |
||||||
|
{ |
||||||
|
root.clear(); |
||||||
|
} |
||||||
|
|
||||||
|
const geom2d::rect<CTYPE>& area() |
||||||
|
{ |
||||||
|
return root.area(); |
||||||
|
} |
||||||
|
|
||||||
|
protected: |
||||||
|
DynamicQuadTree<typename IQuadtreeContainer::iterator> root; |
||||||
|
IQuadtreeContainer m_allItems; |
||||||
|
}; |
||||||
|
} |
Loading…
Reference in new issue