//import java.awt.*;
public class XYZ
 {
  static double m[][];
  static double sinr;
  static double cosr;
  static double d;
  double x,y,z;
  public XYZ()
   {
    x=0;
    y=0;
    z=0;
   }
  public XYZ(XYZ xyz)
   {
    x=xyz.x;
    y=xyz.y;
    z=xyz.z;
   }
  public XYZ(double x,double y,double z)
   {
    this.x=x;
    this.y=y;
    this.z=z;
   }
  public XYZ(double[] da)
   {
    x=da[0];
    y=da[1];
    z=da[2];
   }
  public static void  rotate(XYZ[] w,double a, double b, double c, double r)
   {
    m = new double [3][3];
    sinr = Math.sin(r);
    cosr = Math.cos(r);
    d = 1.0 - cosr;
    m[0][0]=a*a*d + cosr;
    m[1][0]=a*b*d - c*sinr;
    m[2][0]=a*c*d + b*sinr;
    m[0][1]=a*b*d + c*sinr;
    m[1][1]=b*b*d + cosr;
    m[2][1]=b*c*d - a*sinr;
    m[0][2]=a*c*d - b*sinr;
    m[1][2]=b*c*d + a*sinr;
    m[2][2]=c*c*d + cosr;
    int l=w.length;
    for(int i=0;i<l;i++)
     {
      w[i].x = w[i].x * m[0][0] + w[i].y * m[0][1] + w[i].z * m[0][2];
      w[i].y = w[i].x * m[1][0] + w[i].y * m[1][1] + w[i].z * m[1][2];
      w[i].z = w[i].x * m[2][0] + w[i].y * m[2][1] + w[i].z * m[2][2];
     }
   }
  public void setx(double a) { x=a; }
  public void sety(double a) { y=a; }
  public void setz(double a) { z=a; }
  static public double length(XYZ a) { return Math.sqrt(a.x*a.x+a.y*a.y+a.z*a.z); }
  public double length() { return length(this); }
  static public XYZ unitVector(XYZ a)
   {
    double l = length(a);
    return new XYZ(a.x/l,a.y/l,a.z/l);
   }
  public XYZ unitVector() { return unitVector(this); }
  public String toString() { return "[" +(int)x + "," +(int)y + "," +(int)z +"]"; }
  static public XYZ vadd(XYZ a,double x,double y,double z)  { return new XYZ(a.x+x,a.y+y,a.z+z); }
  static public XYZ vadd(XYZ a ,XYZ b)  { return new XYZ(a.x+b.x,a.y+b.y,a.z+b.z); }
  static public XYZ vmul(XYZ a,double x,double y,double z)  { return new XYZ(a.x*x,a.y*y,a.z*z); }
  static public XYZ vmul(XYZ a ,XYZ b)  { return new XYZ(a.x*b.x,a.y*b.y,a.z*b.z); }
  public XYZ vmul(XYZ b)  { return vmul(this,b); }
  static public XYZ xyzrot(XYZ a,XYZ b,double c)
   {
    double f=Math.cos(c); 
    double e=Math.sin(c); 
    return new XYZ(a.x*f+b.x*e,a.y*f+b.y*e,a.z*f+b.z*e);
   }
  static public XYZ vs(XYZ xyza ,double s)  { return new XYZ(xyza.x*s,xyza.y*s,xyza.z*s); }
  static public XYZ vinv(XYZ xyz)  { return new XYZ(-xyz.x,-xyz.y,-xyz.z); }
  static public XYZ vinv(double x,double y,double z)  { return new XYZ(-x,-y,-z); }
  XYZ add(double xx,double yy,double zz) { return new XYZ(x+xx,y+yy,z+zz); }
  public void  addto(XYZ xyz) 
   {
    x+=xyz.x;
    y+=xyz.y;
    z+=xyz.z;
   }
  XYZ nadd(double xx,double yy,double zz) { return new XYZ(-x+xx,-y+yy,-z+zz); }
  XYZ sub(double xx,double yy,double zz) { return new XYZ(x-xx,y-yy,z-zz); }
  boolean eq(XYZ abc) 
   {
    if(x==abc.x && y==abc.y && z==abc.z) return true;
    return false;
   }
  static XYZ getLine(XYZ a,XYZ b) { return (new XYZ(a.x-b.x,a.y-b.y,a.z-b.z)).unitVector(); }
  XYZ getLine(XYZ b) { return getLine(this,b); }
  public static XYZ snap(XYZ a,double d)
   {
    return new XYZ(d*Math.rint(a.x/d),d*Math.rint(a.y/d),d*Math.rint(a.z/d));
   }
  public static boolean equals(XYZ a,XYZ b)
   {
    if(a.x==b.x && a.y==b.y && a.z==b.z) return true;
    return false;
   }
  public static boolean nearlyequals(XYZ a,XYZ b)
   {
    if(Te.nearlyequals(a.x,b.x) && Te.nearlyequals(a.y,b.y)&& Te.nearlyequals(a.z,b.z)) return true;
    return false;
   }
  public static XYZ sum(XYZ a,XYZ b)
   {
    return new XYZ(a.x+b.x,a.y+b.y,a.z+b.z );
   }
  public static void sum(XYZ[] a,XYZ b)
   {
    for(int i=0;i<a.length;i++)
     {
      a[i].x+=b.x;
      a[i].y+=b.y;
      a[i].z+=b.z;
     }
   }
  public static boolean XYZac(XYZ[] a,XYZ xyz)
   {
    for(int i=0;i<a.length;i++)
     {
      if(XYZ.equals(a[i],xyz)) return true;
     }
    return false;
   }
  public static XYZ[] XYZarxyz(XYZ[] a,XYZ xyz)
   {
    for(int i=0;i<a.length;i++)
     {
      if(XYZ.equals(a[i],xyz)) return XYZari(a,i);
     }
    return a;
   }
  public static XYZ[] XYZari(XYZ[] a,int i)
   {
    int nl=a.length-1;
    XYZ[] b= new XYZ[nl];
    for(int j=0;j<i;j++) b[j]=a[j];
    for(int j=i;j<nl;j++) b[j]=a[j+1];
    return b;
   }
  public static XYZ[] XYZaie(XYZ[] a,int i,XYZ xyz)
   {
    int nl=a.length+1;
    XYZ[] b= new XYZ[nl];
    for(int j=0;j<i;j++) b[j]=a[j];
    b[i]=xyz;
    for(int j=i+1;j<nl;j++) b[j]=a[j-1];
    return b;
   }
  public static XYZ centroid(XYZ[] a)
   {
    int l=a.length;
    XYZ c=new XYZ(0,0,0);
    for(int i=0;i<l;i++) c.addto(a[i]);
    return XYZ.div(c,l);
   }
  public static XYZ normal(XYZ[] a)
   {
    int l=a.length;
    if(l==2) return null;
    XYZ normal=new XYZ();
    int i=0;
    for(i=0;i<l-1;i++) 
     {
      normal.x+=(a[i].y-a[i+1].y)*(a[i].z-a[i+1].z);
      normal.y+=(a[i].z-a[i+1].z)*(a[i].x-a[i+1].x);
      normal.z+=(a[i].x-a[i+1].x)*(a[i].y-a[i+1].y);
     }
    i=l-1;
    normal.x+=(a[i].y-a[0].y)*(a[i].z-a[0].z);
    normal.y+=(a[i].z-a[0].z)*(a[i].x-a[0].x);
    normal.z+=(a[i].x-a[0].x)*(a[i].y-a[0].y);
    return XYZ.unitVector(normal);
   }
  public static XYZ div(XYZ a,double d)
   {
    return new XYZ(a.x/d,a.y/d,a.z/d);
   }
 }
