/*========================================================================= * * 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 itkGaussianSpatialObject_hxx #define itkGaussianSpatialObject_hxx #include namespace itk { template GaussianSpatialObject::GaussianSpatialObject() { this->SetTypeName("GaussianSpatialObject"); this->Clear(); this->Update(); } template void GaussianSpatialObject::Clear() { Superclass::Clear(); m_CenterInObjectSpace.Fill(0.0); m_RadiusInObjectSpace = 1.0; m_SigmaInObjectSpace = 1.0; m_Maximum = 1.0; this->Modified(); } template auto GaussianSpatialObject::SquaredZScoreInObjectSpace(const PointType & point) const -> ScalarType { ScalarType r = 0; for (unsigned int i = 0; i < TDimension; ++i) { r += point[i] * point[i]; } return r / (m_SigmaInObjectSpace * m_SigmaInObjectSpace); } template auto GaussianSpatialObject::SquaredZScoreInWorldSpace(const PointType & point) const -> ScalarType { PointType transformedPoint = this->GetObjectToWorldTransformInverse()->TransformPoint(point); return this->SquaredZScoreInObjectSpace(transformedPoint); } template bool GaussianSpatialObject::IsInsideInObjectSpace(const PointType & point) const { if (m_RadiusInObjectSpace > itk::Math::eps) { if (this->GetMyBoundingBoxInObjectSpace()->IsInside(point)) { double r = 0; for (unsigned int i = 0; i < TDimension; ++i) { r += (point[i] - m_CenterInObjectSpace[i]) * (point[i] - m_CenterInObjectSpace[i]); } r /= (m_RadiusInObjectSpace * m_RadiusInObjectSpace); if (r <= 1.0) { return true; } } } return false; } template void GaussianSpatialObject::ComputeMyBoundingBox() { itkDebugMacro("Computing Gaussian bounding box"); PointType pnt1; PointType pnt2; for (unsigned int i = 0; i < TDimension; ++i) { pnt1[i] = m_CenterInObjectSpace[i] - m_RadiusInObjectSpace; pnt2[i] = m_CenterInObjectSpace[i] + m_RadiusInObjectSpace; } this->GetModifiableMyBoundingBoxInObjectSpace()->SetMinimum(pnt1); this->GetModifiableMyBoundingBoxInObjectSpace()->SetMaximum(pnt1); this->GetModifiableMyBoundingBoxInObjectSpace()->ConsiderPoint(pnt2); this->GetModifiableMyBoundingBoxInObjectSpace()->ComputeBoundingBox(); } template bool GaussianSpatialObject::ValueAtInObjectSpace(const PointType & point, double & value, unsigned int depth, const std::string & name) const { itkDebugMacro("Getting the value of the ellipse at " << point); if (this->GetTypeName().find(name) != std::string::npos) { if (IsInsideInObjectSpace(point)) { const double zsq = this->SquaredZScoreInObjectSpace(point); value = m_Maximum * (ScalarType)std::exp(-zsq / 2.0); return true; } } if (depth > 0) { if (Superclass::ValueAtChildrenInObjectSpace(point, value, depth - 1, name)) { return true; } } value = this->GetDefaultOutsideValue(); return false; } template typename EllipseSpatialObject::Pointer GaussianSpatialObject::GetEllipsoid() const { using EllipseType = itk::EllipseSpatialObject; auto ellipse = EllipseType::New(); ellipse->SetRadiusInObjectSpace(m_RadiusInObjectSpace); ellipse->SetCenterInObjectSpace(m_CenterInObjectSpace); ellipse->GetModifiableObjectToWorldTransform()->SetFixedParameters( this->GetObjectToWorldTransform()->GetFixedParameters()); ellipse->GetModifiableObjectToWorldTransform()->SetParameters(this->GetObjectToWorldTransform()->GetParameters()); ellipse->Update(); return ellipse; } template typename LightObject::Pointer GaussianSpatialObject::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->SetMaximum(this->GetMaximum()); rval->SetRadiusInObjectSpace(this->GetRadiusInObjectSpace()); rval->SetSigmaInObjectSpace(this->GetSigmaInObjectSpace()); rval->SetCenterInObjectSpace(this->GetCenterInObjectSpace()); return loPtr; } template void GaussianSpatialObject::PrintSelf(std::ostream & os, Indent indent) const { Superclass::PrintSelf(os, indent); os << indent << "Maximum: " << m_Maximum << std::endl; os << indent << "Radius: " << m_RadiusInObjectSpace << std::endl; os << indent << "Sigma: " << m_SigmaInObjectSpace << std::endl; os << indent << "Center: " << m_CenterInObjectSpace << std::endl; } } // end namespace itk #endif