/*========================================================================= * * 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 itkImageSpatialObject_hxx #define itkImageSpatialObject_hxx #include "itkSize.h" #include "itkDefaultConvertPixelTraits.h" namespace itk { template ImageSpatialObject::ImageSpatialObject() { this->SetTypeName("ImageSpatialObject"); this->Clear(); this->Update(); } template ImageSpatialObject::~ImageSpatialObject() = default; template void ImageSpatialObject::Clear() { Superclass::Clear(); m_Image = ImageType::New(); m_SliceNumber.Fill(0); #if !defined(ITK_LEGACY_REMOVE) this->SetPixelTypeName(static_cast(nullptr)); #endif m_Interpolator = NNInterpolatorType::New(); this->Modified(); } template void ImageSpatialObject::SetInterpolator(InterpolatorType * interpolator) { if (m_Interpolator != interpolator) { m_Interpolator = interpolator; if (m_Image && m_Interpolator) { m_Interpolator->SetInputImage(m_Image); } this->Modified(); } } template bool ImageSpatialObject::IsInsideInObjectSpace(const PointType & point) const { IndexType index; return m_Image->TransformPhysicalPointToIndex(point, index); } template bool ImageSpatialObject::ValueAtInObjectSpace(const PointType & point, double & value, unsigned int depth, const std::string & name) const { if (this->GetTypeName().find(name) != std::string::npos) { if (this->IsEvaluableAtInObjectSpace(point, 0, name)) { ContinuousIndexType cIndex; bool isInside = m_Image->TransformPhysicalPointToContinuousIndex(point, cIndex); if (isInside) { using InterpolatorOutputType = typename InterpolatorType::OutputType; value = static_cast(DefaultConvertPixelTraits::GetScalarValue( m_Interpolator->EvaluateAtContinuousIndex(cIndex))); return true; } } } if (depth > 0) { return Superclass::ValueAtChildrenInObjectSpace(point, value, depth - 1, name); } return false; } template void ImageSpatialObject::ComputeMyBoundingBox() { itkDebugMacro("Computing ImageSpatialObject bounding box"); IndexType index = m_Image->GetLargestPossibleRegion().GetIndex(); typename ImageType::SizeType size = m_Image->GetLargestPossibleRegion().GetSize(); IndexType index2; for (unsigned int i = 0; i < TDimension; ++i) { index2[i] = index[i] + size[i]; } PointType pnt1; PointType pnt2; m_Image->TransformIndexToPhysicalPoint(index, pnt1); m_Image->TransformIndexToPhysicalPoint(index2, pnt2); this->GetModifiableMyBoundingBoxInObjectSpace()->SetMinimum(pnt1); this->GetModifiableMyBoundingBoxInObjectSpace()->SetMaximum(pnt1); this->GetModifiableMyBoundingBoxInObjectSpace()->ConsiderPoint(pnt2); this->GetModifiableMyBoundingBoxInObjectSpace()->ComputeBoundingBox(); } template void ImageSpatialObject::SetImage(const ImageType * image) { if (m_Image != image) { if (!image) { itkDebugMacro("Image passed to ImageSpatialObject was null"); return; } m_Image = image; UpdateImageRegions(); if (m_Interpolator) { m_Interpolator->SetInputImage(m_Image); } this->Modified(); } } template auto ImageSpatialObject::GetImage() const -> const ImageType * { return m_Image.GetPointer(); } template typename LightObject::Pointer ImageSpatialObject::InternalClone() const { // Default implementation just copies the parameters from // this to new transform. typename LightObject::Pointer loPtr = Superclass::InternalClone(); typename Self::Pointer rval = dynamic_cast(loPtr.GetPointer()); if (rval.IsNull()) { itkExceptionMacro("downcast to type " << this->GetNameOfClass() << " failed."); } rval->SetImage(this->GetImage()->Clone()); rval->SetSliceNumber(this->GetSliceNumber()); rval->SetInterpolator(this->GetInterpolator()); return loPtr; } template void ImageSpatialObject::Update() { UpdateImageRegions(); // Call the Superclass Update() after (not before) updating the image regions! The effect of Superclass::Update() // may depend partially on the image regions. Superclass::Update(); } template void ImageSpatialObject::UpdateImageRegions() { if (m_Image) { Superclass::SetLargestPossibleRegion(m_Image->GetLargestPossibleRegion()); Superclass::SetBufferedRegion(m_Image->GetBufferedRegion()); Superclass::SetRequestedRegion(m_Image->GetRequestedRegion()); } } template void ImageSpatialObject::PrintSelf(std::ostream & os, Indent indent) const { Superclass::PrintSelf(os, indent); itkPrintSelfObjectMacro(Image); os << indent << "SliceNumber: " << static_cast::PrintType>(m_SliceNumber) << std::endl; #if !defined(ITK_LEGACY_REMOVE) os << indent << "PixelType: " << m_PixelType << std::endl; #endif itkPrintSelfObjectMacro(Interpolator); } template ModifiedTimeType ImageSpatialObject::GetMTime() const { ModifiedTimeType latestMTime = Superclass::GetMTime(); const ModifiedTimeType imageMTime = m_Image->GetMTime(); if (imageMTime > latestMTime) { latestMTime = imageMTime; } return latestMTime; } template void ImageSpatialObject::SetSliceNumber(unsigned int dimension, int position) { if (dimension < ObjectDimension && m_SliceNumber[dimension] != position) { m_SliceNumber[dimension] = position; this->Modified(); } } } // end namespace itk #endif //__ImageSpatialObject_hxx