/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef itkLevelOrderTreeIterator_hxx #define itkLevelOrderTreeIterator_hxx namespace itk { template LevelOrderTreeIterator::LevelOrderTreeIterator(TTreeType * tree, int endLevel, const TreeNodeType * start) : TreeIteratorBase(tree, start) { m_StartLevel = -1; m_EndLevel = endLevel; if (start != nullptr) { m_Queue.push(start); this->m_Position = const_cast(start); } else { if (tree->GetRoot()) { m_Queue.push(dynamic_cast(tree->GetRoot())); this->m_Position = const_cast(dynamic_cast(tree->GetRoot())); } } this->m_Begin = this->m_Position; } template LevelOrderTreeIterator::LevelOrderTreeIterator(TTreeType * tree, int startLevel, int endLevel, const TreeNodeType * start) : TreeIteratorBase(tree, start) { m_StartLevel = startLevel; m_EndLevel = endLevel; if (start != nullptr) { m_Queue.push(start); this->m_Position = const_cast(start); } else { if (tree->GetRoot()) { m_Queue.push(dynamic_cast(tree->GetRoot())); this->m_Position = const_cast(dynamic_cast(tree->GetRoot())); } } this->m_Begin = this->m_Position; } template auto LevelOrderTreeIterator::GetType() const -> NodeType { return TreeIteratorBaseEnums::TreeIteratorBaseNode::LEVELORDER; } template bool LevelOrderTreeIterator::HasNext() const { if (const_cast(FindNextNode())) { return true; } return false; } template auto LevelOrderTreeIterator::Next() -> const ValueType & { this->m_Position = const_cast(FindNextNode()); if (this->m_Position == nullptr) { return this->m_Root->Get(); // value irrelevant, but we have to return something } return this->m_Position->Get(); } template int LevelOrderTreeIterator::GetStartLevel() const { return m_StartLevel; } template int LevelOrderTreeIterator::GetEndLevel() const { return m_EndLevel; } template auto LevelOrderTreeIterator::FindNextNode() const -> const TreeNodeType * { int level; const TreeNodeType * node; do { node = FindNextNodeHelp(); if (node == nullptr) { return nullptr; } level = GetLevel(node); if (level > m_EndLevel) { return nullptr; } } while (level < m_StartLevel); return node; } template int LevelOrderTreeIterator::GetLevel() const { if (this->m_Position == nullptr) { return -1; } int level = 0; TreeNodeType * node = this->m_Position; while (node->HasParent() && node != this->m_Root) { node = dynamic_cast(node->GetParent()); ++level; } return level; } template int LevelOrderTreeIterator::GetLevel(const TreeNodeType * node) const { if (node == nullptr) { return -1; } int level = 0; while (node->HasParent() && node != this->m_Root) { node = dynamic_cast(node->GetParent()); ++level; } return level; } template auto LevelOrderTreeIterator::FindNextNodeHelp() const -> const TreeNodeType * { if (m_Queue.empty()) { return nullptr; } const TreeNodeType * currentNode = m_Queue.front(); m_Queue.pop(); if (currentNode == nullptr) { return nullptr; } int size = currentNode->CountChildren(); for (int i = 0; i < size; ++i) { auto * child = dynamic_cast(currentNode->GetChild(i)); if (child != nullptr) { m_Queue.push(child); } } // If the current node is the root we try again if (currentNode == this->m_Root) { currentNode = const_cast(FindNextNodeHelp()); } return currentNode; } template TreeIteratorBase * LevelOrderTreeIterator::Clone() { auto * clone = new LevelOrderTreeIterator(const_cast(this->m_Tree), m_StartLevel, m_EndLevel); *clone = *this; return clone; } } // end namespace itk #endif