text: /*
   * Copyright (C) 2015 Open Source Robotics Foundation
   *
   * 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
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * 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 IGNITION_MATH_FRUSTUM_HH_
  #define IGNITION_MATH_FRUSTUM_HH_
  
  #include <ignition/math/Angle.hh>
  #include <ignition/math/AxisAlignedBox.hh>
  #include <ignition/math/Plane.hh>
  #include <ignition/math/Pose3.hh>
  #include <ignition/math/config.hh>
  
  namespace ignition
  {
    namespace math
    {
      // Inline bracket to help doxygen filtering.
      inline namespace IGNITION_MATH_VERSION_NAMESPACE {
      //
      // Forward declaration of private data
      class FrustumPrivate;
  
      /// \brief Mathematical representation of a frustum and related functions.
      /// This is also known as a view frustum.
      class IGNITION_MATH_VISIBLE Frustum
      {
        /// \brief Planes that define the boundaries of the frustum.
        public: enum FrustumPlane
        {
          /// \brief Near plane
          FRUSTUM_PLANE_NEAR   = 0,
  
          /// \brief Far plane
          FRUSTUM_PLANE_FAR    = 1,
  
          /// \brief Left plane
          FRUSTUM_PLANE_LEFT   = 2,
  
          /// \brief Right plane
          FRUSTUM_PLANE_RIGHT  = 3,
  
          /// \brief Top plane
          FRUSTUM_PLANE_TOP    = 4,
  
          /// \brief Bottom plane
          FRUSTUM_PLANE_BOTTOM = 5
        };
  
        /// \brief Default constructor. With the following default values:
        ///
        /// * near: 0.0
        /// * far: 1.0
        /// * fov: 0.78539 radians (45 degrees)
        /// * aspect ratio: 1.0
        /// * pose: Pose3d::Zero
        public: Frustum();
  
        /// \brief Constructor
        /// \param[in] _near Near plane distance. This is the distance from
        /// the frustum's vertex to the closest plane
        /// \param[in] _far Far plane distance. This is the distance from the
        /// frustum's vertex to the farthest plane.
        /// \param[in] _fov Field of view. The field of view is the
        /// angle between the frustum's vertex and the edges of the near or far
        /// plane. This value represents the horizontal angle.
        /// \param[in] _aspectRatio The aspect ratio, which is the width divided
        /// by height of the near or far planes.
        /// \param[in] _pose Pose of the frustum, which is the vertex (top of
        /// the pyramid).
        public: Frustum(const double _near,
                        const double _far,
                        const math::Angle &_fov,
                        const double _aspectRatio,
                        const math::Pose3d &_pose = math::Pose3d::Zero);
  
        /// \brief Copy Constructor
        /// \param[in] _p Frustum to copy.
        public: Frustum(const Frustum &_p);
  
        /// \brief Destructor
        public: virtual ~Frustum();
  
        /// \brief Get the near distance. This is the distance from the
        /// frustum's vertex to the closest plane.
        /// \return Near distance.
        /// \sa SetNear
        public: double Near() const;
  
        /// \brief Set the near distance. This is the distance from the
        /// frustum's vertex to the closest plane.
        /// \param[in] _near Near distance.
        /// \sa Near
        public: void SetNear(const double _near);
  
        /// \brief Get the far distance. This is the distance from the
        /// frustum's vertex to the farthest plane.
        /// \return Far distance.
        /// \sa SetFar
        public: double Far() const;
  
        /// \brief Set the far distance. This is the distance from the
        /// frustum's vertex to the farthest plane.
        /// \param[in] _far Far distance.
        /// \sa Far
        public: void SetFar(const double _far);
  
        /// \brief Get the horizontal field of view. The field of view is the
        /// angle between the frustum's vertex and the edges of the near or far
        /// plane. This value represents the horizontal angle.
        /// \return The field of view.
        /// \sa SetFOV
        public: math::Angle FOV() const;
  
        /// \brief Set the horizontal field of view. The field of view is the
        /// angle between the frustum's vertex and the edges of the near or far
        /// plane. This value represents the horizontal angle.
        /// \param[in] _fov The field of view.
        /// \sa FOV
        public: void SetFOV(const math::Angle &_fov);
  
        /// \brief Get the aspect ratio, which is the width divided by height
        /// of the near or far planes.
        /// \return The frustum's aspect ratio.
        /// \sa SetAspectRatio
        public: double AspectRatio() const;
  
        /// \brief Set the aspect ratio, which is the width divided by height
        /// of the near or far planes.
        /// \param[in] _aspectRatio The frustum's aspect ratio.
        /// \sa AspectRatio
        public: void SetAspectRatio(const double _aspectRatio);
  
        /// \brief Get a plane of the frustum.
        /// \param[in] _plane The plane to return.
        /// \return Plane of the frustum.
        public: Planed Plane(const FrustumPlane _plane) const;
  
        /// \brief Check if a box lies inside the pyramid frustum.
        /// \param[in] _b Box to check.
        /// \return True if the box is inside the pyramid frustum.
        public: bool Contains(const AxisAlignedBox &_b) const;
  
        /// \brief Check if a point lies inside the pyramid frustum.
        /// \param[in] _p Point to check.
        /// \return True if the point is inside the pyramid frustum.
        public: bool Contains(const Vector3d &_p) const;
  
        /// \brief Get the pose of the frustum
        /// \return Pose of the frustum
        /// \sa SetPose
        public: Pose3d Pose() const;
  
        /// \brief Set the pose of the frustum
        /// \param[in] _pose Pose of the frustum, top vertex.
        /// \sa Pose
        public: void SetPose(const Pose3d &_pose);
  
        /// \brief Assignment operator. Set this frustum to the parameter.
        /// \param[in] _f Frustum to copy
        /// \return The new frustum.
        public: Frustum &operator=(const Frustum &_f);
  
        /// \brief Compute the planes of the frustum. This is called whenever
        /// a property of the frustum is changed.
        private: void ComputePlanes();
  
        /// \internal
        /// \brief Private data pointer
        private: FrustumPrivate *dataPtr;
      };
      }
    }
  }
  #endif
  