Skip to content

Commit

Permalink
Issue: #25 Remove nodes in Erase()
Browse files Browse the repository at this point in the history
  • Loading branch information
attcs committed Mar 25, 2024
1 parent 2b1e855 commit 75bd3e4
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 15 deletions.
77 changes: 64 additions & 13 deletions octree.h
Original file line number Diff line number Diff line change
Expand Up @@ -827,7 +827,7 @@ namespace OrthoTree
});
}

constexpr void DisableChild(MortonNodeIDCR childKey) noexcept
constexpr void RemoveChild(MortonNodeIDCR childKey) noexcept
{
auto it = std::end(m_children);
if constexpr (IS_LINEAR_TREE)
Expand Down Expand Up @@ -1211,6 +1211,20 @@ namespace OrthoTree
m.reserve(n);
};

void removeNodeIfPossible(MortonNodeIDCR nodeKey, Node const& node) noexcept
{
if (nodeKey == GetRootKey())
return;

if (node.IsAnyChildExist() || !node.Entities.empty())
return;

autoc parentKey = nodeKey >> DIMENSION_NO;
auto& parentNode = this->m_nodes.at(parentKey);
parentNode.RemoveChild(nodeKey);
this->m_nodes.erase(nodeKey);
}

public: // Static aid functions
static constexpr std::size_t EstimateNodeNumber(std::size_t elementNo, depth_t maxDepthNo, std::size_t maxElementNo) noexcept
{
Expand Down Expand Up @@ -2115,7 +2129,17 @@ namespace OrthoTree
template<bool DO_UPDATE_ENTITY_IDS = true>
constexpr bool EraseId(std::size_t entityID) noexcept
{
autoc isErased = std::ranges::any_of(this->m_nodes, [&](auto& pairNode) { return erase(pairNode.second.Entities, entityID); });
bool isErased = false;
for (auto&[nodeKey, node] : this->m_nodes)
{
if (std::erase(node.Entities, entityID))
{
this->removeNodeIfPossible(nodeKey, node);
isErased = true;
break;
}
}

if (!isErased)
return false;

Expand All @@ -2134,16 +2158,16 @@ namespace OrthoTree
template<bool DO_UPDATE_ENTITY_IDS = true>
bool Erase(std::size_t entitiyID, TVector const& entityOriginalPoint) noexcept
{
autoc oldKey = this->FindSmallestNode(entityOriginalPoint);
if (!Base::IsValidKey(oldKey))
autoc nodeKey = this->FindSmallestNode(entityOriginalPoint);
if (!Base::IsValidKey(nodeKey))
return false; // old box is not in the handled space domain

auto& idList = cont_at(this->m_nodes, oldKey).Entities;
autoc endIteratorAfterRemove = std::remove(idList.begin(), idList.end(), entitiyID);
if (endIteratorAfterRemove == idList.end())
auto& node = this->m_nodes.at(nodeKey);
autoc endIteratorAfterRemove = std::remove(node.Entities.begin(), node.Entities.end(), entitiyID);
if (endIteratorAfterRemove == node.Entities.end())
return false; // id was not registered previously.

idList.erase(endIteratorAfterRemove, idList.end());
node.Entities.erase(endIteratorAfterRemove, node.Entities.end());

if constexpr (DO_UPDATE_ENTITY_IDS)
{
Expand All @@ -2153,6 +2177,8 @@ namespace OrthoTree
});
}

this->removeNodeIfPossible(nodeKey, node);

return true;
}

Expand Down Expand Up @@ -2744,7 +2770,7 @@ namespace OrthoTree
template<depth_t REMAINING_DEPTH>
bool doEraseRec(MortonNodeIDCR nodeKey, std::size_t entityID) noexcept
{
auto& node = cont_at(this->m_nodes, nodeKey);
auto& node = this->m_nodes.at(nodeKey);
auto ret = this->doErase(node, entityID);
if constexpr (REMAINING_DEPTH > 0)
{
Expand All @@ -2753,6 +2779,8 @@ namespace OrthoTree
ret |= doEraseRec<REMAINING_DEPTH - 1>(childKey, entityID);
}

this->removeNodeIfPossible(nodeKey, node);

return ret;
}

Expand Down Expand Up @@ -2785,13 +2813,36 @@ namespace OrthoTree
template<bool DO_UPDATE_ENTITY_IDS = true>
constexpr bool EraseId(std::size_t idErase) noexcept
{
bool bErased = false;
bool isErased = false;
if constexpr (SPLIT_DEPTH_INCREASEMENT == 0)
bErased = std::ranges::any_of(this->m_nodes, [&](auto& pairNode) { return erase(pairNode.second.Entities, idErase); });
{
for (auto&[nodeKey, node] : this->m_nodes)
{
if (std::erase(node.Entities, idErase) > 0)
{
this->removeNodeIfPossible(nodeKey, node);
isErased = true;
break;
}
}
}
else
std::ranges::for_each(this->m_nodes, [&](auto& pairNode) { bErased |= erase(pairNode.second.Entities, idErase) > 0; });
{
auto erasableNodes = std::vector<MortonNodeID>{};
for (auto&[nodeKey, node] : this->m_nodes)
{
autoc isErasedInCurrent = std::erase(node.Entities, idErase) > 0;
if (isErasedInCurrent)
erasableNodes.emplace_back(nodeKey);

isErased |= isErasedInCurrent;
}

if (!bErased)
for (MortonNodeIDCR nodeKey : erasableNodes)
this->removeNodeIfPossible(nodeKey, this->GetNode(nodeKey));
}

if (!isErased)
return false;

if constexpr (DO_UPDATE_ENTITY_IDS)
Expand Down
4 changes: 2 additions & 2 deletions unittests/general.tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ namespace GeneralTest
Assert::AreEqual<size_t>(1, vChild.size());
Assert::AreEqual(kChild, vChild[0]);

node.DisableChild(kChild);
node.RemoveChild(kChild);
autoc vChild2 = node.GetChildren();
Assert::AreEqual<size_t>(0, vChild2.size());
}
Expand Down Expand Up @@ -262,7 +262,7 @@ namespace GeneralTest
{
autoc kChild = MortonNodeID(idChild);

node.DisableChild(kChild);
node.RemoveChild(kChild);
autoc vChildActual = node.GetChildren();
auto vChildExpected = vector<ChildID>(static_cast<size_t>(nChild - idChild) - 1);
std::iota(begin(vChildExpected), end(vChildExpected), idChild + 1);
Expand Down

0 comments on commit 75bd3e4

Please sign in to comment.