/*========================================================================= * * 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 itkRingBuffer_hxx #define itkRingBuffer_hxx #include "itkMath.h" #include "itkPrintHelper.h" namespace itk { template RingBuffer::RingBuffer() : m_PointerVector() { // Default to 3 buffers this->SetNumberOfBuffers(3); } template void RingBuffer::PrintSelf(std::ostream & os, Indent indent) const { using namespace print_helper; Superclass::PrintSelf(os, indent); os << indent << "PointerVector: " << m_PointerVector << std::endl; } template void RingBuffer::MoveHead(OffsetValueType offset) { // Compute the new Head index this->m_HeadIndex = this->GetOffsetBufferIndex(offset); // Mark as modified this->Modified(); } template void RingBuffer::MoveHeadForward() { this->MoveHead(1); } template void RingBuffer::MoveHeadBackward() { this->MoveHead(-1); } template bool RingBuffer::BufferIsFull(OffsetValueType offset) { auto bufferIndex = static_cast(this->GetOffsetBufferIndex(offset)); return !(this->m_PointerVector[bufferIndex].IsNull()); } template typename TElement::Pointer RingBuffer::GetBufferContents(OffsetValueType offset) { // Get the right buffer auto bufferIndex = static_cast(this->GetOffsetBufferIndex(offset)); // Return the resulting image return this->m_PointerVector[bufferIndex]; } template void RingBuffer::SetBufferContents(OffsetValueType offset, ElementPointer element) { // Get the right buffer auto bufferIndex = static_cast(this->GetOffsetBufferIndex(offset)); // Set the pointer this->m_PointerVector[bufferIndex] = element; // Mark as modified this->Modified(); } template auto RingBuffer::GetNumberOfBuffers() -> SizeValueType { return static_cast::SizeValueType>(this->m_PointerVector.size()); } template void RingBuffer::SetNumberOfBuffers(SizeValueType n) { size_t currentSize = this->m_PointerVector.size(); // If larger than current size, insert difference after tail if (n > currentSize) { for (size_t i = 0; i < n - currentSize; ++i) { ElementPointer newPointer = nullptr; this->m_PointerVector.insert(this->m_PointerVector.begin() + this->m_HeadIndex, newPointer); // Increment head index if this wasn't the first one added if (this->m_PointerVector.size() > 1) { this->m_HeadIndex++; } } } // If smaller than current size, remove difference starting at tail else if (n < currentSize) { for (size_t i = 0; i < currentSize - n; ++i) { const auto tailIndex = static_cast(this->GetOffsetBufferIndex(1)); this->m_PointerVector.erase(this->m_PointerVector.begin() + tailIndex); // Decrement head index if necessary if (this->m_HeadIndex > tailIndex) { this->m_HeadIndex--; } } } this->Modified(); } template auto RingBuffer::GetOffsetBufferIndex(OffsetValueType offset) -> OffsetValueType { OffsetValueType moddedOffset = itk::Math::abs(offset) % this->GetNumberOfBuffers(); auto signedHeadIndex = static_cast(m_HeadIndex); if (offset >= 0) { return (signedHeadIndex + moddedOffset) % this->GetNumberOfBuffers(); } else { return (signedHeadIndex + (this->GetNumberOfBuffers() - moddedOffset)) % this->GetNumberOfBuffers(); } } } // end namespace itk #endif