/*========================================================================= * * 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 itkParametricPath_hxx #define itkParametricPath_hxx #include "itkMath.h" namespace itk { template ParametricPath::ParametricPath() { m_DefaultInputStepSize = 0.3; } template auto ParametricPath::EvaluateToIndex(const InputType & input) const -> IndexType { ContinuousIndexType continuousIndex; IndexType index; continuousIndex = this->Evaluate(input); // Round each coordinate to the nearest integer value for (unsigned int i = 0; i < VDimension; ++i) { index[i] = static_cast(continuousIndex[i] + 0.5); } return index; } template auto ParametricPath::IncrementInput(InputType & input) const -> OffsetType { int iterationCount; bool tooSmall; bool tooBig; InputType inputStepSize; InputType finalInputValue; OffsetType offset; IndexType currentImageIndex; IndexType nextImageIndex; IndexType finalImageIndex; iterationCount = 0; inputStepSize = m_DefaultInputStepSize; // Are we already at (or past) the end of the input? finalInputValue = this->EndOfInput(); currentImageIndex = this->EvaluateToIndex(input); finalImageIndex = this->EvaluateToIndex(finalInputValue); offset = finalImageIndex - currentImageIndex; if ((offset == this->GetZeroOffset() && Math::NotExactlyEquals(input, this->StartOfInput())) || (input >= finalInputValue)) { return this->GetZeroOffset(); } do { if (iterationCount++ > 10000) { itkExceptionMacro("Too many iterations"); } nextImageIndex = this->EvaluateToIndex(input + inputStepSize); offset = nextImageIndex - currentImageIndex; tooBig = false; tooSmall = (offset == this->GetZeroOffset()); if (tooSmall) { // double the input step size, but don't go past the end of the input inputStepSize *= 2; if ((input + inputStepSize) >= finalInputValue) { inputStepSize = finalInputValue - input; } } else { // Search for an offset dimension that is too big for (unsigned int i = 0; i < VDimension && !tooBig; ++i) { tooBig = (offset[i] >= 2 || offset[i] <= -2); } if (tooBig) { inputStepSize /= 1.5; } } } while (tooSmall || tooBig); input += inputStepSize; return offset; } template auto ParametricPath::EvaluateDerivative(const InputType & input) const -> VectorType { InputType inputStepSize; inputStepSize = m_DefaultInputStepSize; if ((input + inputStepSize) >= this->EndOfInput()) { inputStepSize = this->EndOfInput() - input; } return (this->Evaluate(input + inputStepSize) - this->Evaluate(input)) / inputStepSize; } template void ParametricPath::PrintSelf(std::ostream & os, Indent indent) const { Superclass::PrintSelf(os, indent); os << indent << "DefaultInputStepSize: " << static_cast::PrintType>(m_DefaultInputStepSize) << std::endl; } } // namespace itk #endif