/*========================================================================= * * 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 itkScaleTransform_hxx #define itkScaleTransform_hxx #include "itkMath.h" namespace itk { template ScaleTransform::ScaleTransform() : Superclass(ParametersDimension) { m_Scale.Fill(NumericTraits::OneValue()); } template void ScaleTransform::SetParameters(const ParametersType & parameters) { for (unsigned int i = 0; i < SpaceDimension; ++i) { m_Scale[i] = parameters[i]; } // Save parameters. Needed for proper operation of TransformUpdateParameters. if (¶meters != &(this->m_Parameters)) { this->m_Parameters = parameters; } this->ComputeMatrix(); this->ComputeOffset(); // Modified is always called since we just have a pointer to the // parameters and cannot know if the parameters have changed. this->Modified(); } template auto ScaleTransform::GetParameters() const -> const ParametersType & { itkDebugMacro("Getting parameters "); // Transfer the translation part for (unsigned int i = 0; i < SpaceDimension; ++i) { this->m_Parameters[i] = m_Scale[i]; } itkDebugMacro("After getting parameters " << this->m_Parameters); return this->m_Parameters; } template void ScaleTransform::PrintSelf(std::ostream & os, Indent indent) const { Superclass::PrintSelf(os, indent); os << indent << "Scale: " << m_Scale << std::endl; } template void ScaleTransform::Compose(const Self * other, bool) { for (unsigned int i = 0; i < SpaceDimension; ++i) { m_Scale[i] *= other->m_Scale[i]; } } template void ScaleTransform::Scale(const ScaleType & scale, bool) { for (unsigned int i = 0; i < SpaceDimension; ++i) { m_Scale[i] *= scale[i]; } } template auto ScaleTransform::TransformPoint(const InputPointType & point) const -> OutputPointType { OutputPointType result; const InputPointType & center = this->GetCenter(); for (unsigned int i = 0; i < SpaceDimension; ++i) { result[i] = (point[i] - center[i]) * m_Scale[i] + center[i]; } return result; } template auto ScaleTransform::TransformVector(const InputVectorType & vect) const -> OutputVectorType { OutputVectorType result; for (unsigned int i = 0; i < SpaceDimension; ++i) { result[i] = vect[i] * m_Scale[i]; } return result; } template auto ScaleTransform::TransformVector(const InputVnlVectorType & vect) const -> OutputVnlVectorType { OutputVnlVectorType result; for (unsigned int i = 0; i < SpaceDimension; ++i) { result[i] = vect[i] * m_Scale[i]; } return result; } template auto ScaleTransform::TransformCovariantVector(const InputCovariantVectorType & vect) const -> OutputCovariantVectorType { // Covariant Vectors are scaled by the inverse OutputCovariantVectorType result; for (unsigned int i = 0; i < SpaceDimension; ++i) { result[i] = vect[i] / m_Scale[i]; } return result; } template bool ScaleTransform::GetInverse(Self * inverse) const { if (!inverse) { return false; } inverse->SetFixedParameters(this->GetFixedParameters()); for (unsigned int i = 0; i < SpaceDimension; ++i) { inverse->m_Scale[i] = 1.0 / m_Scale[i]; } return true; } template auto ScaleTransform::GetInverseTransform() const -> InverseTransformBasePointer { return Superclass::InvertTransform(*this); } template void ScaleTransform::SetIdentity() { Superclass::SetIdentity(); ScaleType i; i.Fill(1.0); this->SetScale(i); } template void ScaleTransform::ComputeJacobianWithRespectToParameters(const InputPointType & p, JacobianType & j) const { j.SetSize(SpaceDimension, this->GetNumberOfLocalParameters()); j.Fill(0.0); const InputPointType & center = this->GetCenter(); for (unsigned int dim = 0; dim < SpaceDimension; ++dim) { j(dim, dim) = p[dim] - center[dim]; } } template void ScaleTransform::ComputeJacobianWithRespectToPosition(const InputPointType &, JacobianPositionType & jac) const { jac.fill(0.0); for (unsigned int dim = 0; dim < VDimension; ++dim) { jac[dim][dim] = m_Scale[dim]; } } template void ScaleTransform::SetScale(const ScaleType & scale) { m_Scale = scale; this->ComputeMatrix(); this->ComputeOffset(); this->Modified(); } template void ScaleTransform::ComputeMatrix() { MatrixType matrix; matrix.SetIdentity(); for (unsigned int dim = 0; dim < SpaceDimension; ++dim) { matrix[dim][dim] = m_Scale[dim]; } this->SetVarMatrix(matrix); } // Back transform a point template inline auto ScaleTransform::BackTransform(const OutputPointType & point) const -> InputPointType { InputPointType result; const InputPointType & center = this->GetCenter(); for (unsigned int i = 0; i < SpaceDimension; ++i) { result[i] = (point[i] + center[i]) / m_Scale[i] - center[i]; } return result; } // Back transform a vector template inline auto ScaleTransform::BackTransform(const OutputVectorType & vect) const -> InputVectorType { InputVectorType result; for (unsigned int i = 0; i < SpaceDimension; ++i) { result[i] = vect[i] / m_Scale[i]; } return result; } // Back transform a vnl_vector template inline auto ScaleTransform::BackTransform(const OutputVnlVectorType & vect) const -> InputVnlVectorType { InputVnlVectorType result; for (unsigned int i = 0; i < SpaceDimension; ++i) { result[i] = vect[i] / m_Scale[i]; } return result; } // Back Transform a CovariantVector template inline auto ScaleTransform::BackTransform(const OutputCovariantVectorType & vect) const -> InputCovariantVectorType { // Covariant Vectors are scaled by the inverse InputCovariantVectorType result; for (unsigned int i = 0; i < SpaceDimension; ++i) { result[i] = vect[i] * m_Scale[i]; } return result; } } // end namespace itk #endif