Skip to content

Commit 93ef0a6

Browse files
committed
Simplify Point::Create()
1 parent 90c3ab3 commit 93ef0a6

File tree

1 file changed

+102
-70
lines changed

1 file changed

+102
-70
lines changed

octree.h

Lines changed: 102 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -316,13 +316,13 @@ namespace OrthoTree
316316
concept HasReserve = requires(TContainer container) { container.reserve(0); };
317317

318318
template<HasReserve TContainer>
319-
constexpr void reserve(TContainer& c, std::size_t n) noexcept
319+
inline constexpr void reserve(TContainer& c, std::size_t n) noexcept
320320
{
321321
c.reserve(n);
322322
};
323323

324324
template<typename TContainer>
325-
constexpr void reserve(TContainer& c, std::size_t n) noexcept {};
325+
inline constexpr void reserve(TContainer& c, std::size_t n) noexcept {};
326326

327327
template<uint8_t e, typename TOut = std::size_t>
328328
consteval TOut pow2_ce()
@@ -333,7 +333,7 @@ namespace OrthoTree
333333
}
334334

335335
template<typename TIn, typename TOut = std::size_t>
336-
constexpr TOut pow2(TIn e) noexcept
336+
inline constexpr TOut pow2(TIn e) noexcept
337337
{
338338
assert(e >= 0 && e < (sizeof(TOut) * CHAR_BIT));
339339
return TOut{ 1 } << e;
@@ -2021,11 +2021,13 @@ namespace OrthoTree
20212021
}
20222022

20232023
protected:
2024-
inline Node& CreateChild(Node& parentNode, MortonNodeIDCR childKey) noexcept
2024+
inline constexpr Node CreateChild(Node const& parentNode, MortonNodeIDCR childKey) const noexcept
20252025
{
2026-
auto& nodeChild = m_nodes[childKey];
2026+
#ifdef ORTHOTREE__DISABLED_NODECENTER
2027+
return Node{};
2028+
#else
2029+
Node nodeChild;
20272030

2028-
#ifndef ORTHOTREE__DISABLED_NODECENTER
20292031
auto const depthID = SI::GetDepthID(childKey);
20302032
auto const& halfSizes = this->GetNodeSize(depthID + 1);
20312033
auto const& parentCenter = parentNode.GetCenter();
@@ -2040,8 +2042,8 @@ namespace OrthoTree
20402042
}
20412043

20422044
nodeChild.SetCenter(std::move(childCenter));
2043-
#endif // ORTHOTREE__DISABLED_NODECENTER
20442045
return nodeChild;
2046+
#endif // ORTHOTREE__DISABLED_NODECENTER
20452047
}
20462048

20472049
template<bool HANDLE_OUT_OF_TREE_GEOMETRY = false>
@@ -2120,8 +2122,8 @@ namespace OrthoTree
21202122
auto const childNodeKey = childGenerator.GetChildNodeKey(childID);
21212123

21222124
parentNode.AddChildInOrder(childNodeKey);
2123-
auto& childNode = this->CreateChild(parentNode, childNodeKey);
2124-
childNode.AddEntity(newEntityID);
2125+
auto [childNode, _] = this->m_nodes.emplace(childNodeKey, this->CreateChild(parentNode, childNodeKey));
2126+
childNode->second.AddEntity(newEntityID);
21252127

21262128
break;
21272129
}
@@ -2135,8 +2137,8 @@ namespace OrthoTree
21352137
auto const childNodeKey = childGenerator.GetChildNodeKey(childID);
21362138

21372139
parentNode.AddChildInOrder(childNodeKey);
2138-
auto& childNode = this->CreateChild(parentNode, childNodeKey);
2139-
childNode.AddEntity(newEntityID);
2140+
auto [childNode, _] = this->m_nodes.emplace(childNodeKey, this->CreateChild(parentNode, childNodeKey));
2141+
childNode->second.AddEntity(newEntityID);
21402142
}
21412143

21422144
auto parentEntities = std::vector<TEntityID>{}; // Box entities could be stuck in the parent node.
@@ -2162,8 +2164,8 @@ namespace OrthoTree
21622164
else
21632165
{
21642166
parentNode.AddChildInOrder(childNodeKey);
2165-
auto& childNode = this->CreateChild(parentNode, childNodeKey);
2166-
childNode.AddEntity(entityID);
2167+
auto [childNode, _] = this->m_nodes.emplace(childNodeKey, this->CreateChild(parentNode, childNodeKey));
2168+
childNode->second.AddEntity(entityID);
21672169
}
21682170
}
21692171

@@ -2224,8 +2226,8 @@ namespace OrthoTree
22242226
auto const childNodeKey = childGenerator.GetChildNodeKey(childID);
22252227

22262228
parentNode.AddChildInOrder(childNodeKey);
2227-
auto& nodeChild = this->CreateChild(parentNode, childNodeKey);
2228-
nodeChild.AddEntity(entityID);
2229+
auto [childNode, _] = this->m_nodes.emplace(childNodeKey, this->CreateChild(parentNode, childNodeKey));
2230+
childNode->second.AddEntity(entityID);
22292231
}
22302232
else
22312233
parentNode.AddEntity(entityID);
@@ -2273,7 +2275,7 @@ namespace OrthoTree
22732275
auto const nElementInNodeAvg = static_cast<float>(elementNo) / static_cast<float>(maxElementNo);
22742276
auto const nDepthEstimated = std::min(maxDepthNo, static_cast<depth_t>(ceil((log2f(nElementInNodeAvg) + 1.0) / static_cast<float>(DIMENSION_NO))));
22752277
if (nDepthEstimated * DIMENSION_NO < 64)
2276-
return static_cast<std::size_t>(rMult * detail::pow2(nDepthEstimated * DIMENSION_NO));
2278+
return static_cast<std::size_t>(1.05 * detail::pow2(nDepthEstimated * std::min<depth_t>(6, DIMENSION_NO)));
22772279

22782280
return static_cast<std::size_t>(rMult * nElementInNodeAvg);
22792281
}
@@ -2965,46 +2967,6 @@ namespace OrthoTree
29652967
this->template Create<false>(*this, points, maxDepthNoIn, std::move(boxSpaceOptional), maxElementNoInNode);
29662968
}
29672969

2968-
private: // Aid functions
2969-
struct Location
2970-
{
2971-
TEntityID EntityID;
2972-
MortonLocationID LocationID;
2973-
};
2974-
2975-
using LocationIterator = typename std::vector<Location>::iterator;
2976-
void CreateChildNodes(
2977-
Node& parentNode, MortonNodeIDCR parentKey, LocationIterator& locationBeginIterator, LocationIterator const& locationEndIterator, depth_t remainingDepth) noexcept
2978-
{
2979-
std::size_t const elementNo = std::distance(locationBeginIterator, locationEndIterator);
2980-
if (elementNo < this->m_maxElementNo || remainingDepth == 0)
2981-
{
2982-
auto& entityIDs = parentNode.GetEntities();
2983-
entityIDs.resize(elementNo);
2984-
2985-
LOOPIVDEP
2986-
for (std::size_t i = 0; locationBeginIterator != locationEndIterator; ++locationBeginIterator, ++i)
2987-
entityIDs[i] = locationBeginIterator->EntityID;
2988-
2989-
return;
2990-
}
2991-
2992-
--remainingDepth;
2993-
auto const keyGenerator = typename SI::ChildKeyGenerator(parentKey);
2994-
2995-
while (locationBeginIterator != locationEndIterator)
2996-
{
2997-
auto const childChecker = typename SI::ChildCheckerFixedDepth(remainingDepth, locationBeginIterator->LocationID);
2998-
auto const actualEndIterator =
2999-
std::partition_point(locationBeginIterator, locationEndIterator, [&](auto const& location) { return childChecker.Test(location.LocationID); });
3000-
3001-
auto const childKey = keyGenerator.GetChildNodeKey(childChecker.GetChildID(remainingDepth));
3002-
parentNode.AddChild(childKey);
3003-
auto& childNode = this->CreateChild(parentNode, childKey);
3004-
this->CreateChildNodes(childNode, childKey, locationBeginIterator, actualEndIterator, remainingDepth);
3005-
}
3006-
}
3007-
30082970
public: // Create
30092971
// Create
30102972
template<bool IS_PARALLEL_EXEC = false>
@@ -3023,24 +2985,89 @@ namespace OrthoTree
30232985
if (points.empty())
30242986
return;
30252987

3026-
detail::reserve(tree.m_nodes, Base::EstimateNodeNumber(pointNo, maxDepthNo, maxElementNoInNode));
2988+
// Calculate and sort the Morton location ids
30272989

2990+
struct Location
2991+
{
2992+
TEntityID EntityID;
2993+
MortonLocationID LocationID;
2994+
};
30282995
auto pointLocations = std::vector<Location>(pointNo);
30292996
EXEC_POL_DEF(ept); // GCC 11.3
30302997
std::transform(EXEC_POL_ADD(ept) points.begin(), points.end(), pointLocations.begin(), [&](auto const& point) {
30312998
return Location{ detail::getKeyPart(points, point), tree.GetLocationID(detail::getValuePart(point)) };
30322999
});
30333000

3034-
EXEC_POL_DEF(eps); // GCC 11.3
3035-
std::sort(EXEC_POL_ADD(eps) pointLocations.begin(), pointLocations.end(), [&](auto const& leftLocation, auto const& rightLocation) {
3036-
return leftLocation.LocationID < rightLocation.LocationID;
3037-
});
3001+
if constexpr (IS_PARALLEL_EXEC)
3002+
{
3003+
EXEC_POL_DEF(eps); // GCC 11.3
3004+
std::sort(EXEC_POL_ADD(eps) pointLocations.begin(), pointLocations.end(), [&](auto const& leftLocation, auto const& rightLocation) {
3005+
return leftLocation.LocationID < rightLocation.LocationID;
3006+
});
3007+
}
30383008

3039-
auto constexpr rootKey = SI::GetRootKey();
3040-
auto& nodeRoot = detail::at(tree.m_nodes, rootKey);
3009+
// Build the tree in depth-first search order
3010+
3011+
struct NodeData
3012+
{
3013+
std::pair<MortonNodeID, Node> NodeInstance;
3014+
typename std::vector<Location>::iterator LocationEndIterator;
3015+
};
3016+
std::array<NodeData, SI::MAX_THEORETICAL_DEPTH> nodeStack;
3017+
nodeStack[0] = NodeData{ *tree.m_nodes.find(SI::GetRootKey()), pointLocations.end() };
3018+
tree.m_nodes.clear(); // Root will be inserted again via the nodeStack, unspecified behavior
3019+
3020+
auto locationBeginIterator = pointLocations.begin();
3021+
for (int depthID = 0; depthID >= 0;)
3022+
{
3023+
auto& [node, locationEndIterator] = nodeStack[depthID];
3024+
std::size_t const elementNo = std::distance(locationBeginIterator, locationEndIterator);
3025+
if (elementNo == 0)
3026+
{
3027+
tree.m_nodes.emplace(std::move(node));
3028+
--depthID;
3029+
continue;
3030+
}
3031+
3032+
if (((elementNo < tree.m_maxElementNo) && !node.second.IsAnyChildExist()) || depthID == maxDepthNo)
3033+
{
3034+
auto& entityIDs = node.second.GetEntities();
3035+
entityIDs.resize(elementNo);
3036+
3037+
LOOPIVDEP
3038+
for (std::size_t i = 0; i < elementNo; ++i)
3039+
{
3040+
entityIDs[i] = locationBeginIterator->EntityID;
3041+
++locationBeginIterator;
3042+
}
30413043

3042-
auto beginIterator = pointLocations.begin();
3043-
tree.CreateChildNodes(nodeRoot, rootKey, beginIterator, pointLocations.end(), maxDepthNo);
3044+
tree.m_nodes.emplace(std::move(node));
3045+
--depthID;
3046+
continue;
3047+
}
3048+
3049+
++depthID;
3050+
auto const examinedLevel = tree.GetDepthMax() - depthID;
3051+
auto const keyGenerator = typename SI::ChildKeyGenerator(node.first);
3052+
auto const childChecker = typename SI::ChildCheckerFixedDepth(examinedLevel, locationBeginIterator->LocationID);
3053+
auto childKey = keyGenerator.GetChildNodeKey(childChecker.GetChildID(examinedLevel));
3054+
if constexpr (IS_PARALLEL_EXEC)
3055+
{
3056+
nodeStack[depthID].LocationEndIterator = std::partition_point(locationBeginIterator, locationEndIterator, [&](auto const& location) {
3057+
return childChecker.Test(location.LocationID);
3058+
});
3059+
node.second.AddChild(childKey);
3060+
}
3061+
else
3062+
{
3063+
nodeStack[depthID].LocationEndIterator =
3064+
std::partition(locationBeginIterator, locationEndIterator, [&](auto const& location) { return childChecker.Test(location.LocationID); });
3065+
node.second.AddChildInOrder(childKey);
3066+
}
3067+
3068+
nodeStack[depthID].NodeInstance.first = std::move(childKey);
3069+
nodeStack[depthID].NodeInstance.second = tree.CreateChild(node.second, childKey);
3070+
}
30443071
}
30453072

30463073
public: // Edit functions
@@ -3496,9 +3523,11 @@ namespace OrthoTree
34963523
entityIDs.resize(elementNo);
34973524

34983525
LOOPIVDEP
3499-
for (std::size_t i = 0; beginLocationIterator != endLocationIterator; ++beginLocationIterator, ++i)
3526+
for (std::size_t i = 0; i < elementNo; ++i)
3527+
{
35003528
entityIDs[i] = beginLocationIterator->EntityID;
3501-
3529+
++beginLocationIterator;
3530+
}
35023531
return;
35033532
}
35043533

@@ -3515,8 +3544,11 @@ namespace OrthoTree
35153544
entityIDs.resize(stuckedElementNo);
35163545

35173546
LOOPIVDEP
3518-
for (std::size_t i = 0; beginLocationIterator != stuckedEndLocationIterator; ++beginLocationIterator, ++i)
3547+
for (std::size_t i = 0; i < stuckedElementNo; ++i)
3548+
{
35193549
entityIDs[i] = beginLocationIterator->EntityID;
3550+
++beginLocationIterator;
3551+
}
35203552
}
35213553

35223554
++currentDepthID;
@@ -3533,8 +3565,8 @@ namespace OrthoTree
35333565
auto const childKey = keyGenerator.GetChildNodeKey(childChecker.GetChildID(remainingDepthNo));
35343566

35353567
parentNode.AddChild(childKey);
3536-
auto& nodeChild = this->CreateChild(parentNode, childKey);
3537-
this->CreateChildNodes(nodeChild, childKey, beginLocationIterator, actualEndLocationIterator, remainingDepthNo);
3568+
auto [childNode, _] = this->m_nodes.emplace(childKey, this->CreateChild(parentNode, childKey));
3569+
this->CreateChildNodes(childNode->second, childKey, beginLocationIterator, actualEndLocationIterator, remainingDepthNo);
35383570
}
35393571
}
35403572

0 commit comments

Comments
 (0)