text: /****************************************************************************
  **
  ** Copyright (c) 2009-2019 C.B. Barber. All rights reserved.
  ** $Id: //main/2019/qhull/src/libqhullcpp/QhullPoint.cpp#3 $$Change: 2673 $
  ** $DateTime: 2019/06/07 16:27:53 $$Author: bbarber $
  **
  ****************************************************************************/
  
  #include "libqhullcpp/QhullPoint.h"
  
  #include "libqhullcpp/QhullError.h"
  #include "libqhullcpp/Qhull.h"
  
  #include <iostream>
  #include <algorithm>
  
  #ifdef _MSC_VER  // Microsoft Visual C++ -- warning level 4
  #endif
  
  namespace orgQhull {
  
  #//!\name Constructors
  
  
  QhullPoint::
  QhullPoint(const Qhull &q)
  : point_coordinates(0)
  , qh_qh(q.qh())
  , point_dimension(q.hullDimension())
  {
  }//QhullPoint
  
  QhullPoint::
  QhullPoint(const Qhull &q, coordT *c)
  : point_coordinates(c)
  , qh_qh(q.qh())
  , point_dimension(q.hullDimension())
  {
      QHULL_ASSERT(q.hullDimension()>0);
  }//QhullPoint dim, coordT
  
  QhullPoint::
  QhullPoint(const Qhull &q, int pointDimension, coordT *c)
  : point_coordinates(c)
  , qh_qh(q.qh())
  , point_dimension(pointDimension)
  {
  }//QhullPoint dim, coordT
  
  //! QhullPoint of Coordinates with point_dimension==c.count()
  QhullPoint::
  QhullPoint(const Qhull &q, Coordinates &c)
  : point_coordinates(c.data())
  , qh_qh(q.qh())
  , point_dimension(c.count())
  {
  }//QhullPoint Coordinates
  
  #//!\name Conversions
  
  // See qt-qhull.cpp for QList conversion
  
  #ifndef QHULL_NO_STL
  std::vector<coordT> QhullPoint::
  toStdVector() const
  {
      QhullPointIterator i(*this);
      std::vector<coordT> vs;
      while(i.hasNext()){
          vs.push_back(i.next());
      }
      return vs;
  }//toStdVector
  #endif //QHULL_NO_STL
  
  #//!\name GetSet
  
  //! QhullPoint is equal if it has the same address and dimension
  //! If !qh_qh, returns true if dimension and coordinates are equal
  //! If qh_qh, returns true if the distance between points is less than qh_qh->distanceEpsilon()
  //!\todo Compares distance with distance-to-hyperplane (distanceEpsilon).   Is that correct?
  bool QhullPoint::
  operator==(const QhullPoint &other) const
  {
      if(point_dimension!=other.point_dimension){
          return false;
      }
      const coordT *c= point_coordinates;
      const coordT *c2= other.point_coordinates;
      if(c==c2){
          return true;
      }
      if(!c || !c2){
          return false;
      }
      if(!qh_qh || qh_qh->hull_dim==0){
          for(int k= point_dimension; k--; ){
              if(*c++ != *c2++){
                  return false;
              }
          }
          return true;
      }
      double dist2= 0.0;
      for(int k= point_dimension; k--; ){
          double diff= *c++ - *c2++;
          dist2 += diff*diff;
      }
      dist2= sqrt(dist2);
      return (dist2 < qh_qh->distanceEpsilon());
  }//operator==
  
  #//!\name Methods
  
  //! Return distance between two points.
  double QhullPoint::
  distance(const QhullPoint &p) const
  {
      const coordT *c= point_coordinates;
      const coordT *c2= p.point_coordinates;
      int dim= point_dimension;
      if(dim!=p.point_dimension){
          throw QhullError(10075, "QhullPoint error: Expecting dimension %d for distance().  Got %d", dim, p.point_dimension);
      }
      if(!c || !c2){
          throw QhullError(10076, "QhullPoint error: Cannot compute distance() for undefined point");
      }
      double dist;
  
      switch(dim){
    case 2:
        dist= (c[0]-c2[0])*(c[0]-c2[0]) + (c[1]-c2[1])*(c[1]-c2[1]);
        break;
    case 3:
        dist= (c[0]-c2[0])*(c[0]-c2[0]) + (c[1]-c2[1])*(c[1]-c2[1]) + (c[2]-c2[2])*(c[2]-c2[2]);
        break;
    case 4:
        dist= (c[0]-c2[0])*(c[0]-c2[0]) + (c[1]-c2[1])*(c[1]-c2[1]) + (c[2]-c2[2])*(c[2]-c2[2]) + (c[3]-c2[3])*(c[3]-c2[3]);
        break;
    case 5:
        dist= (c[0]-c2[0])*(c[0]-c2[0]) + (c[1]-c2[1])*(c[1]-c2[1]) + (c[2]-c2[2])*(c[2]-c2[2]) + (c[3]-c2[3])*(c[3]-c2[3]) + (c[4]-c2[4])*(c[4]-c2[4]);
        break;
    case 6:
        dist= (c[0]-c2[0])*(c[0]-c2[0]) + (c[1]-c2[1])*(c[1]-c2[1]) + (c[2]-c2[2])*(c[2]-c2[2]) + (c[3]-c2[3])*(c[3]-c2[3]) + (c[4]-c2[4])*(c[4]-c2[4]) + (c[5]-c2[5])*(c[5]-c2[5]);
        break;
    case 7:
        dist= (c[0]-c2[0])*(c[0]-c2[0]) + (c[1]-c2[1])*(c[1]-c2[1]) + (c[2]-c2[2])*(c[2]-c2[2]) + (c[3]-c2[3])*(c[3]-c2[3]) + (c[4]-c2[4])*(c[4]-c2[4]) + (c[5]-c2[5])*(c[5]-c2[5]) + (c[6]-c2[6])*(c[6]-c2[6]);
        break;
    case 8:
        dist= (c[0]-c2[0])*(c[0]-c2[0]) + (c[1]-c2[1])*(c[1]-c2[1]) + (c[2]-c2[2])*(c[2]-c2[2]) + (c[3]-c2[3])*(c[3]-c2[3]) + (c[4]-c2[4])*(c[4]-c2[4]) + (c[5]-c2[5])*(c[5]-c2[5]) + (c[6]-c2[6])*(c[6]-c2[6]) + (c[7]-c2[7])*(c[7]-c2[7]);
        break;
    default:
        dist= 0.0;
        for(int k=dim; k--; ){
            dist += (*c - *c2) * (*c - *c2);
            ++c;
            ++c2;
        }
        break;
      }
      return sqrt(dist);
  }//distance
  
  }//namespace orgQhull
  
  #//!\name Global functions
  
  using std::ostream;
  using orgQhull::QhullPoint;
  
  //! Same as qh_printpointid [io.c]
  ostream &
  operator<<(ostream &os, const QhullPoint::PrintPoint &pr)
  {
      QhullPoint p= *pr.point;
      countT i= p.id();
      if(pr.point_message){
          if(*pr.point_message){
              os << pr.point_message << " ";
          }
          if(pr.with_identifier && (i!=qh_IDunknown) && (i!=qh_IDnone)){
              os << "p" << i << ": ";
          }
      }
      const realT *c= p.coordinates();
      for(int k=p.dimension(); k--; ){
          realT r= *c++;
          os << " " << r; // QH11010 FIX: %8.4g  qh_REAL_1
      }
      os << std::endl;
      return os;
  }//printPoint
  
  ostream &
  operator<<(ostream &os, const QhullPoint &p)
  {
      os << p.print("");
      return os;
  }//operator<<
  