//     ____   ______ __
//    / __ \ / ____// /
//   / /_/ // /    / /
//  / ____// /___ / /___   PixInsight Class Library
// /_/     \____//_____/   PCL 2.4.23
// ----------------------------------------------------------------------------
// pcl/Point.h - Released 2022-03-12T18:59:29Z
// ----------------------------------------------------------------------------
// This file is part of the PixInsight Class Library (PCL).
// PCL is a multiplatform C++ framework for development of PixInsight modules.
//
// Copyright (c) 2003-2022 Pleiades Astrophoto S.L. All Rights Reserved.
//
// Redistribution and use in both source and binary forms, with or without
// modification, is permitted provided that the following conditions are met:
//
// 1. All redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
//
// 2. All redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.
//
// 3. Neither the names "PixInsight" and "Pleiades Astrophoto", nor the names
//    of their contributors, may be used to endorse or promote products derived
//    from this software without specific prior written permission. For written
//    permission, please contact info@pixinsight.com.
//
// 4. All products derived from this software, in any form whatsoever, must
//    reproduce the following acknowledgment in the end-user documentation
//    and/or other materials provided with the product:
//
//    "This product is based on software from the PixInsight project, developed
//    by Pleiades Astrophoto and its contributors (https://pixinsight.com/)."
//
//    Alternatively, if that is where third-party acknowledgments normally
//    appear, this acknowledgment must be reproduced in the product itself.
//
// THIS SOFTWARE IS PROVIDED BY PLEIADES ASTROPHOTO AND ITS CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PLEIADES ASTROPHOTO OR ITS
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, BUSINESS
// INTERRUPTION; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; AND LOSS OF USE,
// DATA OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
// ----------------------------------------------------------------------------

#ifndef __PCL_Point_h
#define __PCL_Point_h

/// \file pcl/Point.h

#include <pcl/Defs.h>

#include <pcl/Math.h>
#include <pcl/Relational.h>

#ifdef __PCL_QT_INTERFACE
#  include <QtCore/QPoint>
#endif

namespace pcl
{

// ----------------------------------------------------------------------------

/*
 * ### NB: Template class GenericPoint cannot have virtual member functions.
 *         This is because internal PCL and core routines rely on
 *         GenericPoint<int>, GenericPoint<float> and GenericPoint<double> to
 *         be directly castable to int*, float* and double*, respectively. See
 *         also the PCL_ASSERT_POINT_SIZE() macro.
 */

#define PCL_ASSERT_POINT_SIZE() \
   static_assert( sizeof( *this ) == 2*sizeof( T ), "Invalid sizeof( GenericPoint<> )" )

/*!
 * \class GenericPoint
 * \brief A generic point in the two-dimensional space.
 *
 * %GenericPoint implements a point in the plane, specified by its \a x and
 * \a y coordinates. The type T represents scalar point coordinates and can be
 * any real or integer numerical type.
 *
 * The coordinates of %GenericPoint are accessed directly by its x and y data
 * members. Given a %GenericPoint instance \a p, you can use \a p.x and \a p.y
 * directly to get or set coordinate values.
 *
 * \sa \ref point_types_2d "2-D Point Types",
 * \ref point_functions_2d "2-D Point Operators and Functions",
 * GenericRectangle
 */
template <typename T>
class PCL_CLASS GenericPoint
{
public:

   /*!
    * Represents the type of a point component.
    */
   typedef T   component;

   /*
    * Point coordinates
    */
   component x; //!< Abscissa (horizontal, or X-axis coordinate).
   component y; //!< Ordinate (vertical, or Y-axis coordinate).

   /*!
    * Constructs a default %GenericPoint instance. Point coordinates are not
    * initialized, so they'll have unpredictable garbage values.
    */
   constexpr GenericPoint()
   {
      PCL_ASSERT_POINT_SIZE();
   }

   /*!
    * Constructs a %GenericPoint instance given its coordinates \a xPos and
    * \a yPos in the plane.
    *
    * The type T1 can be any suitable real or integer numerical type, or a type
    * with numeric conversion semantics.
    */
   template <typename T1>
   constexpr GenericPoint( T1 xPos, T1 yPos )
      : x( component( xPos ) )
      , y( component( yPos ) )
   {
      PCL_ASSERT_POINT_SIZE();
   }

   /*!
    * Constructs a %GenericPoint instance with both point coordinates equal to
    * the specified scalar \a d.
    */
   constexpr GenericPoint( component d )
      : GenericPoint( d, d )
   {
      PCL_ASSERT_POINT_SIZE();
   }

   /*!
    * Constructs a %GenericPoint instance from coordinates taken from the
    * specified initializer list \a l.
    *
    * This constructor will copy 2, 1 or zero point coordinates, depending on
    * the number of values in the initializer list. Coordinates that cannot be
    * initialized from list values will be set to zero. For example, the
    * following code:
    *
    * \code
    *    Point p1 = {};
    *    Point p2 = { 1 };
    *    Point p3 = { 1, 2 };
    * \endcode
    *
    * is functionally equivalent to:
    *
    * \code
    *    Point p1( 0, 0 );
    *    Point p2( 1, 0 );
    *    Point p3( 1, 2 );
    * \endcode
    */
   template <typename T1>
   GenericPoint( std::initializer_list<T1> l )
   {
      PCL_ASSERT_POINT_SIZE();
      switch ( l.size() )
      {
      default:
      case 2: y = component( l.begin()[1] );
      case 1: x = component( l.begin()[0] );
      case 0: break;
      }
      switch ( l.size() )
      {
      case 0: x = component( 0 );
      case 1: y = component( 0 );
      default:
      case 2: break;
      }
   }

   /*!
    * Nontrivial copy constructor. Constructs a %GenericPoint instance as a
    * copy (possibly involving a conversion between different numerical types)
    * of another point \a p with different template argument.
    */
   template <typename T1>
   GenericPoint( const GenericPoint<T1>& p )
      : GenericPoint( component( p.x ), component( p.y ) )
   {
      PCL_ASSERT_POINT_SIZE();
   }

#ifdef __PCL_QT_INTERFACE
   GenericPoint( const QPoint& p )
      : GenericPoint( component( p.x() ), component( p.y() ) )
   {
      PCL_ASSERT_POINT_SIZE();
   }
#endif

   /*!
    * Returns the square of the Euclidian distance between this point and
    * another point \a p in the plane.
    *
    * The Euclidian distance between two points p and q is the length of the
    * straight line between both points: Sqrt( (p.x - q.x)^2 + (p.y - q.y)^2 ).
    *
    * This function returns just the radicand (p.x - q.x)^2 + (p.y - q.y)^2.
    * This is useful because saves calculation of a square root, which is
    * unnecessary in some practical cases. One of them is ordering of
    * distances: Sqrt(A) < Sqrt(B) implies A < B.
    *
    * \sa DistanceTo(), ManhattanDistanceTo()
    */
   template <typename T1>
   double SquaredDistanceTo( const GenericPoint<T1>& p ) const noexcept
   {
      double dx = double( p.x ) - double( x );
      double dy = double( p.y ) - double( y );
      return dx*dx + dy*dy;
   }

   /*!
    * Returns the Euclidian distance between this point and another point \a p
    * in the plane.
    *
    * The Euclidian distance between two points p and q is the length of the
    * straight line between both points: Sqrt( (p.x - q.x)^2 + (p.y - q.y)^2 ).
    *
    * \sa SquaredDistanceTo(), ManhattanDistanceTo()
    */
   template <typename T1>
   double DistanceTo( const GenericPoint<T1>& p ) const noexcept
   {
      return pcl::Sqrt( SquaredDistanceTo( p ) );
   }

   /*!
    * Returns the square of the Euclidian distance between this point and the
    * origin of coordinates in the plane. In other words, this function returns
    * the squared length of the two-dimensional vector represented by this
    * point object.
    *
    * This function is equivalent to:
    *
    * \code SquaredDistanceTo( GenericPoint<double>( 0 ) ) \endcode
    *
    * but potentially faster, depending mainly on compiler optimizations.
    *
    * \sa DistanceToOrigin()
    */
   double SquaredDistanceToOrigin() const noexcept
   {
      return double( x )*double( x ) + double( y )*double( y );
   }

   /*!
    * Returns the Euclidian distance between this point and the origin of
    * coordinates in the plane. In other words, this function returns the
    * length of the two-dimensional vector represented by this point object.
    *
    * This function is equivalent to:
    *
    * \code DistanceTo( GenericPoint<double>( 0 ) ) \endcode
    *
    * but potentially faster, depending mainly on compiler optimizations.
    *
    * \sa SquaredDistanceToOrigin(), ManhattanDistanceToOrigin()
    */
   double DistanceToOrigin() const noexcept
   {
      return pcl::Sqrt( SquaredDistanceToOrigin() );
   }

   /*!
    * Returns the Manhattan distance between this point and another point \a p
    * in the plane.
    *
    * The Manhattan distance between two points p and q is the sum of distances
    * measured along axes at right angles: |p.x - q.x| + |p.y - q.y|.
    *
    * \sa DistanceTo(), ManhattanDistanceToOrigin()
    */
   template <typename T1>
   double ManhattanDistanceTo( const GenericPoint<T1>& p ) const noexcept
   {
      return Abs( double( p.x ) - double( x ) ) + Abs( double( p.y ) - double( y ) );
   }

   /*!
    * Returns the Manhattan distance between this point and the origin of
    * coordinates in the plane. In other words, this function returns the sum
    * of the absolute values of this point's x and y coordinates.
    *
    * This function is equivalent to:
    *
    * \code ManhattanDistanceTo( GenericPoint<double>( 0 ) ) \endcode
    *
    * but potentially faster, depending mainly on compiler optimizations.
    *
    * \sa ManhattanDistanceTo(), DistanceToOrigin()
    */
   double ManhattanDistanceToOrigin() const noexcept
   {
      return Abs( double( x ) ) + Abs( double( y ) );
   }

   /*!
    * Moves this point to the location of another point \a p.
    *
    * \sa MoveBy()
    */
   template <typename T1>
   void MoveTo( const GenericPoint<T1>& p ) noexcept
   {
      MoveTo( p.x, p.y );
   }

   /*!
    * Moves this point to the specified absolute coordinates \a xPos and
    * \a yPos in the plane.
    *
    * \sa MoveBy()
    */
   template <typename T1>
   void MoveTo( T1 xPos, T1 yPos ) noexcept
   {
      x = component( xPos ); y = component( yPos );
   }

#ifdef __PCL_QT_INTERFACE
   void MoveTo( const QPoint& p ) noexcept
   {
      MoveTo( p.x(), p.y() );
   }
#endif

   /*!
    * Returns a point whose coordinates are equal to the coordinates of the
    * specified point \a d.
    */
   template <typename T1>
   GenericPoint MovedTo( const GenericPoint<T1>& p ) const noexcept
   {
      return GenericPoint( component( p.x ), component( p.y ) );
   }

   /*!
    * Returns a point at the specified \a xPos and \a yPos coordinates.
    */
   template <typename T1>
   GenericPoint MovedTo( T1 xPos, T1 yPos ) const noexcept
   {
      return GenericPoint( component( xPos ), component( yPos ) );
   }

   /*!
    * Moves this point by equal increments in the X and Y directions, relative
    * to its current position.
    *
    * \param d    Increments in the X and Y directions, given by \a d.x and
    *             \a d.y, respectively.
    *
    * \sa MoveTo()
    */
   template <typename T1>
   void MoveBy( const GenericPoint<T1>& d ) noexcept
   {
      MoveBy( d.x, d.y );
   }

   /*!
    * Moves this point by increments \a dx and \a dy in the X and Y directions,
    * respectively, relative to its current position.
    *
    * For example, given the declaration:
    *
    * \code GenericPoint<float> p; \endcode
    *
    * These two expressions are equivalent:
    *
    * \code
    * p.MoveBy( -3, 7 );
    * p.MoveTo( p.x-3, p.y+7 );
    * \endcode
    *
    * \sa MoveTo()
    */
   template <typename T1>
   void MoveBy( T1 dx, T1 dy ) noexcept
   {
      x += component( dx ); y += component( dy );
   }

   /*!
    * Moves this point by the same increment \a dxy in the X and Y directions,
    * relative to its current position.
    *
    * This function is functionally equivalent to:
    *
    * \code MoveBy( dxy, dxy ); \endcode
    *
    * \sa MoveTo()
    */
   template <typename T1>
   void MoveBy( T1 dxy ) noexcept
   {
      x += component( dxy ); y += component( dxy );
   }

#ifdef __PCL_QT_INTERFACE
   void MoveBy( const QPoint& p )
   {
      MoveBy( p.x(), p.y() );
   }
#endif

   /*!
    * Returns a point whose coordinates are the coordinates of this point
    * displaced by the increments specified as the point \a d.
    */
   template <typename T1>
   GenericPoint MovedBy( const GenericPoint<T1>& d ) const noexcept
   {
      return GenericPoint( x + component( d.x ), y + component( d.y ) );
   }

   /*!
    * Returns a point whose coordinates are the coordinates of this point
    * displaced by the specified increments \a dx and \a dy.
    */
   template <typename T1>
   GenericPoint MovedBy( T1 dx, T1 dy ) const noexcept
   {
      return GenericPoint( x + component( dx ), y + component( dy ) );
   }

   /*!
    * Rotates this point in the plane by the specified \a angle in radians,
    * with respect to a center of rotation given by its coordinates \a xc and
    * \a yc.
    */
   template <typename T1, typename T2>
   void Rotate( T1 angle, T2 xc, T2 yc ) noexcept
   {
      pcl::Rotate( x, y, angle, xc, yc );
   }

   /*!
    * Rotates this point in the plane by the specified \a angle in radians,
    * with respect to the specified \a center of rotation.
    */
   template <typename T1, typename T2>
   void Rotate( T1 angle, const GenericPoint<T2>& center ) noexcept
   {
      Rotate( angle, center.x, center.y );
   }

   /*!
    * Rotates this point in the plane by the specified angle, given by its sine
    * and cosine, \a sa and \a ca respectively, with respect to a center of
    * rotation given by its coordinates \a xc and \a yc.
    */
   template <typename T1, typename T2>
   void Rotate( T1 sa, T1 ca, T2 xc, T2 yc ) noexcept
   {
      pcl::Rotate( x, y, sa, ca, xc, yc );
   }

   /*!
    * Rotates this point in the plane by the specified angle, given by its sine
    * and cosine, \a sa and \a ca respectively, with respect to the specified
    * \a center of rotation.
    */
   template <typename T1, typename T2>
   void Rotate( T1 sa, T1 ca, const GenericPoint<T2>& center ) noexcept
   {
      Rotate( sa, ca, center.x, center.y );
   }

   /*!
    * Returns a point whose coordinates are the coordinates of this point
    * rotated in the plane by the specified \a angle in radians, with respect
    * to a center of rotation given by its coordinates \a xc and \a yc.
    */
   template <typename T1, typename T2>
   GenericPoint Rotated( T1 angle, T2 xc, T2 yc ) const noexcept
   {
      GenericPoint p( *this );
      p.Rotate( angle, xc, yc );
      return p;
   }

   /*!
    * Returns a point whose coordinates are the coordinates of this point
    * rotated in the plane by the specified \a angle in radians, with respect
    * to the specified \a center of rotation.
    */
   template <typename T1, typename T2>
   GenericPoint Rotated( T1 angle, const GenericPoint<T2>& center ) const noexcept
   {
      GenericPoint p( *this );
      p.Rotate( angle, center );
      return p;
   }

   /*!
    * Returns a point whose coordinates are the coordinates of this point
    * rotated in the plane by the specified angle given by its sine and cosine,
    * \a sa and \a ca respectively, with respect to a center of rotation given
    * by its coordinates \a xc and \a yc.
    */
   template <typename T1, typename T2>
   GenericPoint Rotated( T1 sa, T1 ca, T2 xc, T2 yc ) const noexcept
   {
      GenericPoint p( *this );
      p.Rotate( sa, ca, xc, yc );
      return p;
   }

   /*!
    * Returns a point whose coordinates are the coordinates of this point
    * rotated in the plane by the specified angle given by its sine and cosine,
    * \a sa and \a ca respectively, with respect to the specified \a center of
    * rotation.
    */
   template <typename T1, typename T2>
   GenericPoint Rotated( T1 sa, T1 ca, const GenericPoint<T2>& center ) const noexcept
   {
      GenericPoint p( *this );
      p.Rotate( sa, ca, center );
      return p;
   }

   /*!
    * Rounds the coordinates of this point to their corresponding nearest
    * integer coordinates.
    *
    * \sa Round( int ), Rounded(), Truncate(), RoundedToInt(), TruncatedToInt()
    */
   void Round() noexcept
   {
      x = component( pcl::Round( double( x ) ) );
      y = component( pcl::Round( double( y ) ) );
   }

   /*!
    * Rounds the coordinates of this point to \a n fractional digits (\a n >= 0).
    *
    * \sa Round(), Rounded( int ), Truncate(), RoundedToInt(), TruncatedToInt()
    */
   void Round( int n ) noexcept
   {
      PCL_PRECONDITION( n >= 0 )
      x = component( pcl::Round( double( x ), n ) );
      y = component( pcl::Round( double( y ), n ) );
   }

   /*!
    * Returns a point whose coordinates are the coordinates of this point
    * rounded to their nearest integers.
    *
    * \sa Round(), Rounded( int ), Truncated(), RoundedToInt(), TruncatedToInt()
    */
   GenericPoint Rounded() const noexcept
   {
      return GenericPoint( component( pcl::Round( double( x ) ) ), component( pcl::Round( double( y ) ) ) );
   }

   /*!
    * Returns a point whose coordinates are the coordinates of this point
    * rounded to \a n fractional digits (\a n >= 0).
    *
    * \sa Round( int ), Rounded(), Truncated(), RoundedToInt(), TruncatedToInt()
    */
   GenericPoint Rounded( int n ) const noexcept
   {
      PCL_PRECONDITION( n >= 0 )
      return GenericPoint( component( pcl::Round( double( x ), n ) ), component( pcl::Round( double( y ), n ) ) );
   }

   /*!
    * Returns a point of integer template type whose coordinates are the
    * coordinates of this point rounded to their nearest integers.
    *
    * \sa Round(), Rounded(), Truncated(), TruncatedToInt()
    */
   GenericPoint<int> RoundedToInt() const noexcept
   {
      return GenericPoint<int>( pcl::RoundInt( double( x ) ), pcl::RoundInt( double( y ) ) );
   }

   /*!
    * Integer truncation of coordinates. Sets the coordinates x, y of this
    * point to the corresponding nearest integer coordinates i, j, such that
    * i <= x and j <= y.
    *
    * \sa Truncated(), Round(), RoundedToInt(), TruncatedToInt()
    */
   void Truncate() noexcept
   {
      x = component( pcl::Trunc( double( x ) ) );
      y = component( pcl::Trunc( double( y ) ) );
   }

   /*!
    * Integer truncation of coordinates. Returns a point whose coordinates are
    * the coordinates x, y of this point truncated to their corresponding
    * nearest integer coordinates i, j, such that i <= x and j <= y.
    *
    * \sa Truncate(), Rounded(), RoundedToInt(), TruncatedToInt()
    */
   GenericPoint Truncated() const noexcept
   {
      return GenericPoint( component( pcl::Trunc( double( x ) ) ), component( pcl::Trunc( double( y ) ) ) );
   }

   /*!
    * Integer truncation of coordinates. Returns a point of integer template
    * type whose coordinates are the coordinates x, y of this point truncated
    * to the nearest integer coordinates i, j, such that i <= x and j <= y.
    *
    * \sa Truncate(), Truncated(), Rounded(), RoundedToInt()
    */
   GenericPoint<int> TruncatedToInt() const noexcept
   {
      return GenericPoint<int>( pcl::TruncInt( double( x ) ), pcl::TruncInt( double( y ) ) );
   }

   /*!
    * Assignment operator. Moves this point to the location specified as a
    * point \a p. Returns a reference to this point.
    *
    * \sa MoveTo()
    */
   template <typename T1>
   GenericPoint& operator =( const GenericPoint<T1>& p ) noexcept
   {
      x = component( p.x );
      y = component( p.y );
      return *this;
   }

   /*!
    * Assignment operator. Given a coordinate \a v, moves this point to a
    * location x = y = \a v. Returns a reference to this point.
    *
    * \sa MoveTo()
    */
   GenericPoint& operator =( component v ) noexcept
   {
      x = y = v;
      return *this;
   }

#ifdef __PCL_QT_INTERFACE
   GenericPoint& operator =( const QPoint& p ) noexcept
   {
      x = component( p.x() );
      y = component( p.y() );
      return *this;
   }
#endif

   /*!
    * Adds each coordinate of a given point \a p to its homonym coordinate in
    * this point. Returns a reference to this point.
    *
    * \sa MoveBy(), operator -=()
    */
   template <typename T1>
   GenericPoint& operator +=( const GenericPoint<T1>& p ) noexcept
   {
      x += component( p.x );
      y += component( p.y );
      return *this;
   }

   /*!
    * Adds a scalar \a d to both coordinates of this point. Returns a reference
    * to this point.
    *
    * \sa MoveBy(), operator -=()
    */
   GenericPoint& operator +=( component d ) noexcept
   {
      x += d;
      y += d;
      return *this;
   }

#ifdef __PCL_QT_INTERFACE
   GenericPoint& operator +=( const QPoint& p ) noexcept
   {
      x += component( p.x() );
      y += component( p.y() );
      return *this;
   }
#endif

   /*!
    * Subtracts each coordinate of a given point \a p from its homonym
    * coordinate in this point. Returns a reference to this point.
    *
    * \sa MoveBy(), operator +=()
    */
   template <typename T1>
   GenericPoint& operator -=( const GenericPoint<T1>& p ) noexcept
   {
      x -= component( p.x );
      y -= component( p.y );
      return *this;
   }

   /*!
    * Subtracts a scalar \a d from both coordinates of this point. Returns a
    * reference to this point.
    *
    * \sa MoveBy(), operator +=()
    */
   GenericPoint& operator -=( component d ) noexcept
   {
      x -= d;
      y -= d;
      return *this;
   }

#ifdef __PCL_QT_INTERFACE
   GenericPoint& operator -=( const QPoint& p ) noexcept
   {
      x -= component( p.x() );
      y -= component( p.y() );
      return *this;
   }
#endif

   /*!
    * Multiplies each coordinate of this point by its homonym coordinate of a
    * given point \a p. Returns a reference to this point.
    *
    * \sa operator /=(), operator +=()
    */
   template <typename T1>
   GenericPoint& operator *=( const GenericPoint<T1>& p ) noexcept
   {
      x *= component( p.x );
      y *= component( p.y );
      return *this;
   }

   /*!
    * Multiplies both coordinates of this point by a scalar \a d. Returns a
    * reference to this point.
    *
    * \sa operator /=(), operator +=()
    */
   GenericPoint& operator *=( component d ) noexcept
   {
      x *= d;
      y *= d;
      return *this;
   }

#ifdef __PCL_QT_INTERFACE
   GenericPoint& operator *=( const QPoint& p ) noexcept
   {
      x *= component( p.x() );
      y *= component( p.y() );
      return *this;
   }
#endif

   /*!
    * Divides each coordinate of this point by its homonym coordinate of a
    * given point \a p. Returns a reference to this point.
    *
    * \sa operator *=(), operator -=()
    */
   template <typename T1>
   GenericPoint& operator /=( const GenericPoint<T1>& p ) noexcept
   {
      PCL_PRECONDITION( component( p.x ) != component( 0 ) && component( p.y ) != component( 0 ) )
      x /= component( p.x );
      y /= component( p.y );
      return *this;
   }

   /*!
    * Divides both coordinates of this point by a scalar \a d. Returns a
    * reference to this point.
    *
    * \sa operator *=(), operator -=()
    */
   GenericPoint& operator /=( component d ) noexcept
   {
      PCL_PRECONDITION( d != component( 0 ) )
      x /= d;
      y /= d;
      return *this;
   }

#ifdef __PCL_QT_INTERFACE
   GenericPoint& operator /=( const QPoint& p ) noexcept
   {
      PCL_PRECONDITION( component( p.x() ) != component( 0 ) && component( p.y() ) != component( 0 ) )
      x /= component( p.x() );
      y /= component( p.y() );
      return *this;
   }
#endif

   /*!
    * Returns a copy of this point.
    */
   GenericPoint operator +() const noexcept
   {
      return *this;
   }

   /*!
    * Returns a point whose coordinates have the same magnitudes as the
    * coordinates of this point, but opposite signs. The returned point so
    * defined represents a vector diametrically opposed to this one.
    */
   GenericPoint operator -() const noexcept
   {
      return GenericPoint( -x, -y );
   }

   /*!
    * Reflects this point in the origin. This transformation changes the signs
    * of both point coordinates.
    */
   void Reflect() noexcept
   {
      x = -x;
      y = -y;
   }

   /*!
    * Reflects this point across the X axis. This transformation changes the
    * sign of this point's y-coordinate.
    */
   void ReflectX() noexcept
   {
      y = -y;
   }

   /*!
    * Reflects this point across the Y axis. This transformation changes the
    * sign of this point's x-coordinate.
    */
   void ReflectY() noexcept
   {
      x = -x;
   }

   /*!
    * Returns the reflexion of this point in the origin. The returned point has
    * the coordinates of this point with inverse signs.
    */
   GenericPoint Reflected() const noexcept
   {
      return GenericPoint( -x, -y );
   }

   /*!
    * Returns the reflexion of this point across the X axis. The returned point
    * has the same x-coordinate as this point and the y-coordinate of this
    * point with inverse sign.
    */
   GenericPoint ReflectedX() const noexcept
   {
      return GenericPoint( x, -y );
   }

   /*!
    * Returns the reflexion of this point across the Y axis. The returned point
    * has the x-coordinate of this point with inverse sign and the same
    * y-coordinate as this point.
    */
   GenericPoint ReflectedY() const noexcept
   {
      return GenericPoint( -x, y );
   }

   /*
    * Returns a point whose coordinates are the coordinates of this point
    * converted to radians, assuming that this point has coordinates expressed
    * in degrees.
    */
   GenericPoint Rad() const noexcept
   {
      return GenericPoint( pcl::Rad( x ), pcl::Rad( y ) );
   }

   /*!
    * Returns a point whose coordinates are the coordinates of this point
    * converted to degrees, assuming that this point has coordinates expressed
    * in radians.
    */
   GenericPoint Deg() const noexcept
   {
      return GenericPoint( pcl::Deg( x ), pcl::Deg( y ) );
   }

   /*!
    * Converts the coordinates of this point to radians, assuming that they are
    * expressed in degrees before calling this function. Returns a reference to
    * this object.
    */
   GenericPoint& ToRad() noexcept
   {
      x = pcl::Rad( x );
      y = pcl::Rad( y );
      return *this;
   }

   /*!
    * Converts the coordinates of this point to degrees, assuming that they are
    * expressed in radians before calling this function. Returns a reference to
    * this object.
    */
   GenericPoint& ToDeg() noexcept
   {
      x = pcl::Deg( x );
      y = pcl::Deg( y );
      return *this;
   }

   /*!
    * Returns a reference to a point component. Returns a reference to the X
    * point coordinate if the specified index \a i is zero, or a reference to
    * the Y coordinate otherwise.
    */
   component& operator []( int i ) noexcept
   {
      return (i == 0) ? x : y;
   }

   /*!
    * Returns a copy of a point component. Returns the X point coordinate if
    * the specified index \a i is zero, or the Y coordinate otherwise.
    */
   component operator []( int i ) const noexcept
   {
      return (i == 0) ? x : y;
   }

   /*!
    * Returns the dot product of this point and another point given by its
    * coordinates \a px and \a py.
    */
   template <typename T1, typename T2>
   double Dot( T1 px, T2 py ) const noexcept
   {
      return double( x )*double( px ) + double( y )*double( py );
   }

   /*!
    * Returns the dot product of this point and another point \a p.
    */
   template <typename T1>
   double Dot( const GenericPoint<T1>& p ) const noexcept
   {
      return Dot( p.x, p.y );
   }

#ifdef __PCL_QT_INTERFACE
   operator QPoint() const noexcept
   {
      return QPoint( int( x ), int( y ) );
   }
#endif
};

#undef PCL_ASSERT_POINT_SIZE

// ----------------------------------------------------------------------------

/*!
 * \defgroup point_functions_2d Point Operators and Functions
 */

/*!
 * Returns true iff two points \a p1 and \a p2 are equal. Two points are equal
 * if their homonym coordinates are equal.
 * \ingroup point_functions_2d
 */
template <typename T1, typename T2> inline
bool operator ==( const GenericPoint<T1>& p1, const GenericPoint<T2>& p2 ) noexcept
{
   return p1.x == p2.x && p1.y == p2.y;
}

/*!
 * Returns true iff a point \a p1 is equal to a scalar \a d2. A point \p is
 * equal to a scalar \a d if both coordinates of \a p are equal to \a d.
 * \ingroup point_functions_2d
 */
template <typename T> inline
bool operator ==( const GenericPoint<T>& p1, T d2 ) noexcept
{
   return p1.x == d2 && p1.y == d2;
}

/*!
 * Returns true iff a scalar \a d1 is equal to a point \a p2. A scalar \a d is
 * equal to a point \a p if both coordinates of \a p are equal to \a d.
 * \ingroup point_functions_2d
 */
template <typename T> inline
bool operator ==( T d1, const GenericPoint<T>& p2 ) noexcept
{
   return d1 == p2.x && d1 == p2.y;
}

/*!
 * Returns true iff a point \a p1 is less than another point \a p2.
 *
 * Points in the plane are sorted by ordinates in PCL. Given two points \a p
 * and \a q in the plane, it holds that:
 *
 * \a p < \a q if \a p.y < \a q.y or \a p.y == \a q.y and \a p.x < \a q.x
 *
 * \ingroup point_functions_2d
 */
template <typename T1, typename T2> inline
bool operator <( const GenericPoint<T1>& p1, const GenericPoint<T2>& p2 ) noexcept
{
   return p1.y < p2.y || p1.y == p2.y && p1.x < p2.x;
}

/*!
 * Returns true iff a point \a p1 is less than a scalar \a d2.
 *
 * Given a point \a p in the plane and a scalar \a d, it holds that:
 *
 * \a p < \a d if \a p.y < \a d or \a p.y == \a d and \a p.x < \a d
 *
 * \ingroup point_functions_2d
 */
template <typename T> inline
bool operator <( const GenericPoint<T>& p1, T d2 ) noexcept
{
   return p1.y < d2 || p1.y == d2 && p1.x < d2;
}

/*!
 * Returns true iff a scalar \a d1 is less than a point \a p2.
 *
 * Given a point \a p in the plane and a scalar \a d, it holds that:
 *
 * \a d < \a p if \a d < \a p.y or \a d == \a p.y and \a d < \a p.x
 *
 * \ingroup point_functions_2d
 */
template <typename T> inline
bool operator <( T d1, const GenericPoint<T>& p2 ) noexcept
{
   return d1 < p2.y || d1 == p2.y && d1 < p2.x;
}

/*!
 * Adds two points \a p1 and \a p2, and returns the resulting sum point.
 *
 * Point addition consists in adding homonym coordinates. Given two points
 * \a p and \a q in the plane, the sum point \a s = \a p + \a q is given by:
 *
 * \a s.x = \a p.x + \a q.x \n
 * \a s.y = \a p.y + \a q.y
 *
 * \ingroup point_functions_2d
 */
template <typename T1, typename T2> inline
GenericPoint<T1> operator +( const GenericPoint<T1>& p1, const GenericPoint<T2>& p2 ) noexcept
{
   return GenericPoint<T1>( T1( p1.x + p2.x ), T1( p1.y + p2.y ) );
}

/*!
 * Adds a point \a p1 and a scalar \a d2, and returns the resulting sum point.
 *
 * Given a point \a p in the plane and a scalar \a d, the sum point
 * \a s = \a p + \a d is given by:
 *
 * \a s.x = \a p.x + \a d \n
 * \a s.y = \a p.y + \a d
 *
 * \ingroup point_functions_2d
 */
template <typename T> inline
GenericPoint<T> operator +( const GenericPoint<T>& p1, T d2 ) noexcept
{
   return GenericPoint<T>( p1.x+d2, p1.y+d2 );
}

/*!
 * Adds a scalar \a d1 and a point \a p2, and returns the resulting sum point.
 *
 * Point addition is a commutative operation, thus see
 * pcl::operator +( const GenericPoint<T>&, T ).
 *
 * \ingroup point_functions_2d
 */
template <typename T> inline
GenericPoint<T> operator +( T d1, const GenericPoint<T>& p2 ) noexcept
{
   return GenericPoint<T>( p2.x+d1, p2.y+d1 );
}

/*!
 * Subtracts two points \a p1 and \a p2, and returns the resulting difference
 * point.
 *
 * Point subtraction consists in subtracting homonym coordinates. Given two
 * points \a p and \a q in the plane, the difference point \a r = \a p - \a q
 * is given by:
 *
 * \a r.x = \a p.x - \a q.x \n
 * \a r.y = \a p.y - \a q.y
 *
 * \ingroup point_functions_2d
 */
template <typename T1, typename T2> inline
GenericPoint<T1> operator -( const GenericPoint<T1>& p1, const GenericPoint<T2>& p2 ) noexcept
{
   return GenericPoint<T1>( T1( p1.x - p2.x ), T1( p1.y - p2.y ) );
}

/*!
 * Subtracts a scalar \a d2 from a point \a p1, and returns the resulting
 * difference point.
 *
 * Given a point \a p in the plane and a scalar \a d, the difference point
 * \a r = \a p - \a d is given by:
 *
 * \a r.x = \a p.x - \a d \n
 * \a r.y = \a p.y - \a d
 *
 * \ingroup point_functions_2d
 */
template <typename T> inline
GenericPoint<T> operator -( const GenericPoint<T>& p1, T d2 ) noexcept
{
   return GenericPoint<T>( p1.x-d2, p1.y-d2 );
}

/*!
 * Subtracts a point \a p2 from a scalar \a d1, and returns the resulting
 * difference point.
 *
 * Given a point \a p in the plane and a scalar \a d, the difference point
 * \a r = \a d - \a p is given by:
 *
 * \a r.x = \a d - \a p.x \n
 * \a r.y = \a d - \a p.y
 *
 * \ingroup point_functions_2d
 */
template <typename T> inline
GenericPoint<T> operator -( T d1, const GenericPoint<T>& p2 ) noexcept
{
   return GenericPoint<T>( d1-p2.x, d1-p2.y );
}

/*!
 * Multiplies two points \a p1 and \a p2, and returns the resulting product
 * point.
 *
 * Point multiplication consists in multiplying homonym coordinates. Given two
 * points \a p and \a q in the plane, the product point \a P = \a p * \a q is
 * given by:
 *
 * \a P.x = \a p.x * \a q.x \n
 * \a P.y = \a p.y * \a q.y
 *
 * \ingroup point_functions_2d
 */
template <typename T1, typename T2> inline
GenericPoint<T1> operator *( const GenericPoint<T1>& p1, const GenericPoint<T2>& p2 ) noexcept
{
   return GenericPoint<T1>( T1( p1.x * p2.x ), T1( p1.y * p2.y ) );
}

/*!
 * Multiplies a point \a p1 by a scalar \a d2, and returns the resulting
 * product point.
 *
 * Given a point \a p in the plane and a scalar \a d, the product point
 * \a P = \a p * \a d is given by:
 *
 * \a P.x = \a p.x * \a d \n
 * \a P.y = \a p.y * \a d
 *
 * \ingroup point_functions_2d
 */
template <typename T> inline
GenericPoint<T> operator *( const GenericPoint<T>& p1, T d2 ) noexcept
{
   return GenericPoint<T>( p1.x*d2, p1.y*d2 );
}

/*!
 * Multiplies a scalar \a d1 by a point \a p2, and returns the resulting
 * product point.
 *
 * Point multiplication is a commutative operation, thus see
 * pcl::operator *( const GenericPoint<T>&, T ).
 *
 * \ingroup point_functions_2d
 */
template <typename T> inline
GenericPoint<T> operator *( T d1, const GenericPoint<T>& p2 ) noexcept
{
   return GenericPoint<T>( p2.x*d1, p2.y*d1 );
}

/*!
 * Divides two points \a p1 and \a p2, and returns the resulting quotient point.
 *
 * Given two points \a p and \a q in the plane, the quotient point
 * \a Q = \a p / \a q is given by:
 *
 * \a Q.x = \a p.x / \a q.x \n
 * \a Q.y = \a p.y / \a q.y
 *
 * \ingroup point_functions_2d
 */
template <typename T1, typename T2> inline
GenericPoint<T1> operator /( const GenericPoint<T1>& p1, const GenericPoint<T2>& p2 ) noexcept
{
   PCL_PRECONDITION( p2.x != T2( 0 ) && p2.y != T2( 0 ) )
   return GenericPoint<T1>( T1( p1.x / p2.x ), T1( p1.y / p2.y ) );
}

/*!
 * Divides a point \a p1 by a scalar \a d2, and returns the resulting
 * quotient point.
 *
 * Given a point \a p in the plane and a scalar \a d, the quotient point
 * \a Q = \a p / \a d is given by:
 *
 * \a Q.x = \a p.x / \a d \n
 * \a Q.y = \a p.y / \a d
 *
 * \ingroup point_functions_2d
 */
template <typename T> inline
GenericPoint<T> operator /( const GenericPoint<T>& p1, T d2 ) noexcept
{
   PCL_PRECONDITION( d2 != T( 0 ) )
   return GenericPoint<T>( p1.x/d2, p1.y/d2 );
}

/*!
 * Divides a scalar \a d1 by a point \a p2, and returns the resulting
 * quotient point.
 *
 * Given a point \a p in the plane and a scalar \a d, the quotient point
 * \a Q = \a d / \a q is given by:
 *
 * \a Q.x = \a d / \a p.x \n
 * \a Q.y = \a d / \a p.y
 *
 * \ingroup point_functions_2d
 */
template <typename T> inline
GenericPoint<T> operator /( T d1, const GenericPoint<T>& p2 ) noexcept
{
   PCL_PRECONDITION( p2.x != T( 0 ) && p2.y != T( 0 ) )
   return GenericPoint<T>( d1/p2.x, d1/p2.y );
}

/*!
 * Returns the distance between two points \a p1 and \a p2 in the plane.
 * \ingroup point_functions_2d
 */
// ### FIXME: We cannot use two template arguments here due to a conflict with
//            Distance( FI, FI ) defined in Iterator.h
//template <typename T1, typename T2> inline
template <typename T> inline
double Distance( const GenericPoint<T>& p1, const GenericPoint<T>& p2 ) noexcept
{
   double dx = double( p2.x ) - double( p1.x );
   double dy = double( p2.y ) - double( p1.y );
   return pcl::Sqrt( dx*dx + dy*dy );
}

/*!
 * Returns the Manhattan distance between two points \a p1 and \a p2 in the
 * plane.
 * \ingroup point_functions_2d
 */
template <typename T1, typename T2> inline
double ManhattanDistance( const GenericPoint<T1>& p1, const GenericPoint<T2>& p2 ) noexcept
{
   return Abs( double( p2.x ) - double( p1.x ) ) + Abs( double( p2.y ) - double( p1.y ) );
}

/*!
 * Rotates a point in the plane, given a rotation angle and the coordinates of
 * a center of rotation.
 *
 * \param p    Reference to a point that will be rotated.
 * \param a    Rotation angle in radians. Positive angles are measured
 *             counter-clockwise.
 * \param xc   Abscissa (x coordinate) of the center of rotation.
 * \param yc   Ordinate (y coordinate) of the center of rotation.
 *
 * The coordinates \a p.x and \a p.y are replaced by their corresponding
 * rotated values.
 *
 * \ingroup point_functions_2d
 */
template <typename T, typename T1, typename T2> inline
void Rotate( GenericPoint<T>& p, T1 a, T2 xc, T2 yc ) noexcept
{
   pcl::Rotate( p.x, p.y, a, xc, yc );
}

/*!
 * Rotates a point in the plane, given a rotation angle and a rotation center
 * point.
 *
 * \param p    Reference to a point that will be rotated.
 * \param a    Rotation angle in radians. Positive angles are measured
 *             counter-clockwise.
 * \param c    Reference to a point that will be taken as the center of
 *             rotation.
 *
 * The coordinates \a p.x and \a p.y are replaced by their corresponding
 * rotated values.
 *
 * \ingroup point_functions_2d
 */
template <typename T, typename T1, typename T2> inline
void Rotate( GenericPoint<T>& p, T1 a, const GenericPoint<T2>& c ) noexcept
{
   pcl::Rotate( p, a, c.x, c.y );
}

/*!
 * Rotates a point in the plane, given a rotation angle by its sine and
 * cosine, and the coordinates of a center of rotation.
 *
 * \param p    Reference to a point that will be rotated.
 * \param sa   Sine of the rotation angle.
 * \param ca   Cosine of the rotation angle.
 * \param xc   Abscissa (x coordinate) of the center of rotation.
 * \param yc   Ordinate (y coordinate) of the center of rotation.
 *
 * The coordinates \a p.x and \a p.y are replaced by their corresponding
 * rotated values.
 *
 * \ingroup point_functions_2d
 */
template <typename T, typename T1, typename T2> inline
void Rotate( GenericPoint<T>& p, T1 sa, T1 ca, T2 xc, T2 yc ) noexcept
{
   pcl::Rotate( p.x, p.y, sa, ca, xc, yc );
}

/*!
 * Rotates a point in the plane, given a rotation angle by its sine and
 * cosine, and a rotation center point.
 *
 * \param p    Reference to a point that will be rotated.
 * \param sa   Sine of the rotation angle.
 * \param ca   Cosine of the rotation angle.
 * \param c    Reference to a point that will be taken as the center of
 *             rotation.
 *
 * The coordinates \a p.x and \a p.y are replaced by their corresponding
 * rotated values.
 *
 * \ingroup point_functions_2d
 */
template <typename T, typename T1, typename T2> inline
void Rotate( GenericPoint<T>& p, T1 sa, T1 ca, const GenericPoint<T2>& c ) noexcept
{
   pcl::Rotate( p, sa, ca, c.x, c.y );
}

/*!
 * Exchanges two points \a p1 and \a p2 in the plane. Calling this function is
 * equivalent to:
 *
 * \code Swap( p1.x, p2.x ); Swap( p1.y, p2.y ); \endcode
 *
 * \ingroup point_functions_2d
 */
template <typename T> inline
void Swap( GenericPoint<T>& p1, GenericPoint<T>& p2 ) noexcept
{
   pcl::Swap( p1.x, p2.x );
   pcl::Swap( p1.y, p2.y );
}

// ----------------------------------------------------------------------------

#ifndef __PCL_NO_POINT_INSTANTIATE

/*!
 * \defgroup point_types_2d Point Types
 */

/*!
 * \class pcl::I32Point
 * \ingroup point_types_2d
 * \brief 32-bit integer point on the plane.
 *
 * %I32Point is a template instantiation of GenericPoint for the \c int32 type.
 */
typedef GenericPoint<int32>         I32Point;

/*!
 * \class pcl::Point
 * \ingroup point_types_2d
 * \brief 32-bit integer point on the plane.
 *
 * %Point is an alias for I32Point. It is a template instantiation of
 * GenericPoint for \c int32.
 */
typedef I32Point                    Point;

/*!
 * \class pcl::F32Point
 * \ingroup point_types_2d
 * \brief 32-bit floating-point point in the R^2 space.
 *
 * %F32Point is a template instantiation of GenericPoint for the \c float type.
 */
typedef GenericPoint<float>         F32Point;

/*!
 * \class pcl::FPoint
 * \ingroup point_types_2d
 * \brief 32-bit floating-point point in the R^2 space.
 *
 * %FPoint is an alias for F32Point. It is a template instantiation of
 * GenericPoint for \c float.
 */
typedef F32Point                    FPoint;

/*!
 * \class pcl::F64Point
 * \ingroup point_types_2d
 * \brief 64-bit floating-point point in the R^2 space.
 *
 * %F64Point is a template instantiation of GenericPoint for \c double.
 */
typedef GenericPoint<double>        F64Point;

/*!
 * \class pcl::DPoint
 * \ingroup point_types_2d
 * \brief 64-bit floating-point point in the R^2 space.
 *
 * %DPoint is an alias for F64Point. It is a template instantiation of
 * GenericPoint for \c double.
 */
typedef F64Point                    DPoint;

#endif   // !__PCL_NO_POINT_INSTANTIATE

// ----------------------------------------------------------------------------

} // pcl

#endif  // __PCL_Point_h

// ----------------------------------------------------------------------------
// EOF pcl/Point.h - Released 2022-03-12T18:59:29Z
