45 typename std::pointer_traits<TNodePointer>::element_type>;
62 return this->_previousTraversal.size();
70 return this->_currentTraversal.size();
79 CESIUM_ASSERT(this->_parentIndices.empty());
81 this->_previousTraversal.swap(this->_currentTraversal);
82 this->_currentTraversal.clear();
83 this->_previousTraversalNextNodeIndex = 0;
96 int64_t currentTraversalIndex = int64_t(this->_currentTraversal.size());
97 int64_t previousTraversalIndex = this->_previousTraversalNextNodeIndex;
99 if (previousTraversalIndex >= 0 &&
100 size_t(previousTraversalIndex) < this->_previousTraversal.size()) {
101 const TraversalData& previousData =
102 this->_previousTraversal[size_t(previousTraversalIndex)];
103 if (previousData.pNode == pNode) {
104 ++this->_previousTraversalNextNodeIndex;
106 previousTraversalIndex = -1;
109 previousTraversalIndex = -1;
112 this->_parentIndices.emplace_back(TraversalIndices{
113 .previous = previousTraversalIndex,
114 .current = currentTraversalIndex});
116 this->_currentTraversal.emplace_back(TraversalData{pNode, -1, TState()});
129 if (this->_parentIndices.empty())
132 return this->currentData().pNode;
155 const TraversalData* pData = this->previousData();
156 return pData ? &pData->state :
nullptr;
168 TraversalData& data = this->currentData();
180 const TraversalData& data = this->currentData();
197 void finishNode([[maybe_unused]]
const TNodePointer& pNode) {
200 CESIUM_ASSERT(!this->_currentTraversal.empty());
201 CESIUM_ASSERT(!this->_parentIndices.empty());
202 CESIUM_ASSERT(this->currentData().pNode == pNode);
204 this->currentData().nextSiblingIndex =
205 int64_t(this->_currentTraversal.size());
210 const TraversalData* pPreviousData = this->previousData();
212 CESIUM_ASSERT(pPreviousData->nextSiblingIndex >= 0);
213 this->_previousTraversalNextNodeIndex = pPreviousData->nextSiblingIndex;
216 this->_parentIndices.pop_back();
231 int64_t parentPreviousIndex = this->previousDataIndex();
232 if (parentPreviousIndex < 0) {
237 const TraversalData& parentPreviousData =
238 this->_previousTraversal[size_t(parentPreviousIndex)];
240 for (
size_t i =
size_t(parentPreviousIndex + 1);
241 i < size_t(parentPreviousData.nextSiblingIndex);) {
242 CESIUM_ASSERT(i < this->_previousTraversal.size());
243 const TraversalData& data = this->_previousTraversal[i];
244 callback(data.pNode, data.state);
246 data.nextSiblingIndex >= 0 &&
size_t(data.nextSiblingIndex) > i);
247 i = size_t(data.nextSiblingIndex);
262 template <
typename Func>
264 int64_t parentPreviousIndex = this->previousDataIndex();
265 if (parentPreviousIndex < 0) {
270 const TraversalData& parentPreviousData =
271 this->_previousTraversal[size_t(parentPreviousIndex)];
273 for (
size_t i =
size_t(parentPreviousIndex + 1);
274 i < size_t(parentPreviousData.nextSiblingIndex);
276 CESIUM_ASSERT(i < this->_previousTraversal.size());
277 const TraversalData& data = this->_previousTraversal[i];
278 callback(data.pNode, data.state);
296 int64_t parentCurrentIndex = this->currentDataIndex();
297 CESIUM_ASSERT(parentCurrentIndex >= 0);
299 const TraversalData& parentCurrentData =
300 this->_currentTraversal[size_t(parentCurrentIndex)];
302 size_t endIndex = parentCurrentData.nextSiblingIndex >= 0
303 ? size_t(parentCurrentData.nextSiblingIndex)
304 : this->_currentTraversal.size();
306 for (
size_t i =
size_t(parentCurrentIndex + 1); i < endIndex; ++i) {
307 TraversalData& data = this->_currentTraversal[i];
308 callback(data.pNode, data.state);
320 std::unordered_map<TRawConstNodePointer, TState>
322 return this->slowlyGetStates(this->_currentTraversal);
333 std::unordered_map<TRawConstNodePointer, TState>
335 return this->slowlyGetStates(this->_previousTraversal);
339 struct TraversalData {
341 int64_t nextSiblingIndex;
345 struct TraversalIndices {
350 int64_t previousDataIndex()
const {
351 CESIUM_ASSERT(!this->_parentIndices.empty());
353 int64_t result = this->_parentIndices.back().previous;
357 (result >= 0 &&
size_t(result) < this->_previousTraversal.size()));
362 int64_t currentDataIndex()
const {
363 CESIUM_ASSERT(!this->_parentIndices.empty());
367 this->_parentIndices.back().current >= 0 &&
368 this->_parentIndices.back().current <
369 static_cast<int64_t
>(this->_currentTraversal.size()));
371 return this->_parentIndices.back().current;
374 const TraversalData* previousData()
const {
375 int64_t previousIndex = this->previousDataIndex();
376 if (previousIndex < 0)
379 const TraversalData& previousData =
380 this->_previousTraversal[size_t(previousIndex)];
382 CESIUM_ASSERT(previousData.pNode == this->currentData().pNode);
384 return &previousData;
387 TraversalData& currentData() {
388 int64_t currentIndex = this->currentDataIndex();
389 CESIUM_ASSERT(currentIndex >= 0);
390 return this->_currentTraversal[size_t(currentIndex)];
393 const TraversalData& currentData()
const {
394 int64_t currentIndex = this->currentDataIndex();
395 CESIUM_ASSERT(currentIndex >= 0);
396 return this->_currentTraversal[size_t(currentIndex)];
399 std::unordered_map<TRawConstNodePointer, TState>
400 slowlyGetStates(
const std::vector<TraversalData>& traversalData)
const {
401 std::unordered_map<TRawConstNodePointer, TState> result;
403 for (
const TraversalData& data : traversalData) {
404 result[data.pNode] = data.state;
410 std::vector<TraversalData> _previousTraversal;
411 std::vector<TraversalData> _currentTraversal;
420 std::vector<TraversalIndices> _parentIndices;
425 int64_t _previousTraversalNextNodeIndex = 0;