
/******************************************************************************
* MODULE     : point.cpp
* DESCRIPTION: points
* COPYRIGHT  : (C) 2003  Joris van der Hoeven
*******************************************************************************
* This software falls under the GNU general public license and comes WITHOUT
* ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details.
* If you don't have this file, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
******************************************************************************/

#include "point.hpp"
#include <math.h>
#include "math_util.hpp"

point
operator - (point p) {
  int i, n= N(p);
  point r (n);
  for (i=0; i<n; i++)
    r[i]= - p[i];
  return r;
}

point
operator + (point p1, point p2) {
  int i, n= min (N(p1), N(p2));
  point r (n);
  for (i=0; i<n; i++)
    r[i]= p1[i] + p2[i];
  return r;
}

point
operator - (point p1, point p2) {
  int i, n= min (N(p1), N(p2));
  point r (n);
  for (i=0; i<n; i++)
    r[i]= p1[i] - p2[i];
  return r;
}

point
operator * (double x, point p) {
  int i, n= N(p);
  point r (n);
  for (i=0; i<n; i++)
    r[i]= x * p[i];
  return r;
}

point
operator / (point p, double x) {
  int i, n= N(p);
  point r (n);
  for (i=0; i<n; i++)
    r[i]= p[i] / x;
  return r;
}

point
as_point (tree t) {
  if (!is_tuple (t)) return point ();
  else {
    int i, n= N(t);
    point p(n);
    for (i=0; i<n; i++)
      p[i]= as_double (t[i]);
    return p;
  }
}

tree
as_tree (point p) {
  int i, n= N(p);
  tree t (TUPLE, n);
  for (i=0; i<n; i++)
    t[i]= as_string (p[i]);
  return t;
}

double
operator * (point p1, point p2) {
  int i, n= min (N(p1), N(p2));
  double r= 0;
  for (i=0; i<n; i++)
    r+= p1[i] * p2[i];
  return r;
}

double
norm (point p) {
  return sqrt (p*p);
}

double
arg (point p) {
  double n= norm(p);
  p=p/n;
  if (p[1]<0) return 2*PI-acos(p[0]);
  else return acos(p[0]);
}

point
proj (axis ax, point p) {
  int i, n= min (N(ax[0]), N(ax[1]));
  point a (n), b (n);
  for (i=0; i<n ; i++) {
    a[i]= ax[1][i] - ax[0][i];
    b[i]= ax[0][i];
  }
  if (norm (a) < 1.0e-6)
    return ax[0];
  else
    return b + ((a*p - a*b) / (a*a)) * a;
}

double
dist (axis ax, point p) {
  return norm (p - proj (ax, p));
}

double
seg_dist (axis ax, point p) {
  point ab= ax[1] - ax[0];
  point ba= ax[0] - ax[1];
  point ap= p - ax[0];
  point bp= p - ax[1];
  if (ab * ap > 0 && ba * bp > 0)
    return dist (ax, p);
  else
    return min (norm (ap), norm (bp));
}
