/*========================================================================= * * 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 itkPreOrderTreeIterator_h #define itkPreOrderTreeIterator_h #include "itkTreeIteratorBase.h" namespace itk { // Forward reference because of circular dependencies template class ITK_TEMPLATE_EXPORT LeafTreeIterator; template class ITK_TEMPLATE_EXPORT PreOrderTreeIterator : public TreeIteratorBase { public: /** Typedefs */ using ValueType = typename TTreeType::ValueType; using Superclass = TreeIteratorBase; using typename Superclass::TreeNodeType; using typename Superclass::NodeType; /** Constructor */ PreOrderTreeIterator(const TTreeType * tree, const TreeNodeType * start = nullptr); /** Get the type of the iterator */ NodeType GetType() const override; /** Clone function */ TreeIteratorBase * Clone() override; protected: /** Return the next node */ const ValueType & Next() override; /** Return true if the next node exists */ bool HasNext() const override; private: /** Find the next node */ const TreeNodeType * FindNextNode() const; /** LeafTreeIterator uses PreOrderTreeIterator in its implementation, but it * needs to adjust its root. A friend designation is added to correct * behavior and retain backwards compatible behavior. */ friend class LeafTreeIterator; }; /** Constructor */ template PreOrderTreeIterator::PreOrderTreeIterator(const TTreeType * tree, const TreeNodeType * start) : TreeIteratorBase(tree, start) {} /** Return the type of the iterator */ template auto PreOrderTreeIterator::GetType() const -> NodeType { return TreeIteratorBaseEnums::TreeIteratorBaseNode::PREORDER; } /** Return true if the next node exists */ template bool PreOrderTreeIterator::HasNext() const { if (const_cast(FindNextNode()) != nullptr) { return true; } return false; } /** Return the next node */ template const typename PreOrderTreeIterator::ValueType & PreOrderTreeIterator::Next() { 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(); } /** Find the next node */ template const typename PreOrderTreeIterator::TreeNodeType * PreOrderTreeIterator::FindNextNode() const { if (this->m_Position == nullptr) { return nullptr; } if (this->m_Position->HasChildren()) { return dynamic_cast(this->m_Position->GetChild(0)); } if (!this->m_Position->HasParent()) { return nullptr; } TreeNodeType * child = this->m_Position; TreeNodeType * parent = this->m_Position; while (parent->HasParent()) { child = parent; parent = dynamic_cast(parent->GetParent()); // Subtree if (parent->ChildPosition(this->m_Root) >= 0) { return nullptr; } int childPosition = parent->ChildPosition(child); int lastChildPosition = parent->CountChildren() - 1; while (childPosition < lastChildPosition) { auto * help = dynamic_cast(parent->GetChild(childPosition + 1)); if (help != nullptr) { return help; } ++childPosition; } } return nullptr; } /** Clone function */ template TreeIteratorBase * PreOrderTreeIterator::Clone() { auto * clone = new PreOrderTreeIterator(this->m_Tree, this->m_Position); *clone = *this; return clone; } } // end namespace itk #endif