/*========================================================================= * * 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 itkFrustumSpatialFunction_hxx #define itkFrustumSpatialFunction_hxx namespace itk { template auto FrustumSpatialFunction::Evaluate(const InputType & position) const -> OutputType { using PointType = InputType; using VectorType = typename PointType::VectorType; static_assert(VDimension > 2, "VDimension must be greater than 2"); static_assert(PointType::PointDimension > 2, "PointDimension of TInput must be greater than 2"); VectorType relativePosition = position - m_Apex; const double distanceToApex = relativePosition.GetNorm(); // Check Top and Bottom planes. If the angle is negative, the top plane // value may be less than the bottom plane, which is still correct. if (m_TopPlane <= m_BottomPlane) { if (distanceToApex < m_TopPlane || distanceToApex > m_BottomPlane) { return 0; } } else { if (distanceToApex > m_TopPlane || distanceToApex < m_BottomPlane) { return 0; } } if (m_RotationPlane == RotationPlaneEnum::RotateInXZPlane) { const double dx = relativePosition[0]; const double dy = relativePosition[1]; const double dz = relativePosition[2]; const double distanceXZ = std::sqrt(dx * dx + dz * dz); const double deg2rad = std::atan(1.0) / 45.0; // Check planes along Y const double angleY = std::atan2(dy, distanceXZ); if (itk::Math::abs(angleY) > m_ApertureAngleY * deg2rad) { return 0; } // Check planes along X const double angleX = std::atan2(dx, dz); if (std::cos(angleX + (180.0 + m_AngleZ) * deg2rad) < std::cos(deg2rad * m_ApertureAngleX)) { return 0; } return 1; } else if (m_RotationPlane == RotationPlaneEnum::RotateInYZPlane) { const double dx = relativePosition[0]; const double dy = relativePosition[1]; const double dz = relativePosition[2]; const double distanceYZ = std::sqrt(dy * dy + dz * dz); const double deg2rad = std::atan(1.0) / 45.0; // Check planes along X const double angleX = std::atan2(dx, distanceYZ); if (itk::Math::abs(angleX) > m_ApertureAngleX * deg2rad) { return 0; } // Check planes along Y const double angleY = std::atan2(dy, dz); if (std::cos(angleY + (180.0 + m_AngleZ) * deg2rad) < std::cos(deg2rad * m_ApertureAngleY)) { return 0; } return 1; } else { itkExceptionMacro("Rotation plane not set or set to an unsupported value!"); } } template void FrustumSpatialFunction::PrintSelf(std::ostream & os, Indent indent) const { Superclass::PrintSelf(os, indent); os << indent << "Apex: " << m_Apex << std::endl; os << indent << "AngleZ: " << m_AngleZ << std::endl; os << indent << "ApertureAngleX: " << m_ApertureAngleX << std::endl; os << indent << "ApertureAngleY: " << m_ApertureAngleY << std::endl; os << indent << "TopPlane: " << m_TopPlane << std::endl; os << indent << "BottomPlane: " << m_BottomPlane << std::endl; os << indent << "RotationPlane: " << m_RotationPlane << std::endl; } } // end namespace itk #endif