import sk.uniba.fmph.pocprak.simplegraphics.*;
/**
 * Trieda popisujuca dvojrozmerny vektor
 * a staticke metody pre narabanie s vektormi
 * Pre odbornikov poznamanevame, ze sa tu trochu priecime ducho objektoveho programovania
 * lebo pouzivame skor proceduralny pristup cez staticke metody triedy namiesto toho
 * aby sme volali objekt a jeho metody.
 * Staticky pristup sa nam javi sympatickejsi najme pri scitani dvoch vektorov,
 * lebo je voci obom vektorom sysmetricky
 * Pri nasobeni vektora skalarom by uzx bol mozno prirodzenesji objektovy pristup,
 * ale pre zaciatocnikov je nazornejsi staticky pristup
 * Pri "jednovektorovych" funkciach abs a unit dodrziavame prirodzeny objektovy pristup
 */
public class vector {
  /**
   * xova zlozka vektora
   */
  public double x;
  /**
   * yova zlozka vektora
   */
  public double y;

  /**
   * staticka metoda scita dva vektory
   */
  public static vector plus(vector v1,vector v2){
    return new vector(v1.x+v2.x,v1.y+v2.y);
  }

  /**
   * staticka metoda vynasobi vektor skalarom
   */
  public static vector times(double c, vector v){
    return new vector(c*v.x,c*v.y);
  }

  /**
   * staticka metoda, vypocita skalarny sucin dvoch vektorov
   */
  public static double scalarproduct(vector v1, vector v2){
    return (v1.x*v2.x+v1.y*v2.y);
  }


  /**
   *  Skonstruuje vektor zo zadanych zloziek
   */
  public vector(double vx, double vy){
   this.x=vx;
   this.y=vy;
  }

  /**
   * Skonstruuje vektor smerujuci z druheho bodu do prveho
   */
  public vector(point B, point A){
    this(B.x-A.x,B.y-A.y);
  }

  /**
   * Vrati jednotkovy vektor smerujuci z bodu A do bodu B
   */
  public static vector direction(point B, point A){
    vector v = new vector(B,A);
    return v.unit();
  }

  /**
   * Vrati velkost vektora
   */
  public double abs(){
    return Math.sqrt(this.x*this.x+this.y*this.y);//this nemusime pisat, ale zvysuje to citatelnost
  }

  /**
   * Vrati jednotkovy vektor v smere vektora this
   * ak ma vektor nulovu dlzku, vrati nulovy vektor
   */
  public vector unit(){
    double length = abs();
    if (length == 0) return this; // pre nulovy vektor vrati ako jednotkovy vektor nulovy b\vektor
    return new vector(this.x/length, this.y/length); //this nemusime pisat, ale zvysuje to citatelnost
  }

  /**
   * Vrati jednotkovy vektor kolmy na vektor this
   * ak ma vektor nulovu dlzku, vrati nulovy vektor
   */
  public vector perpendicular(){
    double length = abs();
    if (length == 0) return this; // pre nulovy vektor vrati ako jednotkovy vektor nulovy b\vektor
    //Sem dolpne kod tak aby vratil jednotkovy vektor kolmy na this
    return new vector(this.y/length, -this.x/length); //this nemusime pisat, ale zvysuje to citatelnost
  }


  /**
   * Nakresli vektor v okne, ktoreho grafika je gr, umiestni ho do bodu R
   * a vektor nakresli ako usecku preskalovanu hodnotou scale, co znamena, ze ak je vektor
   * jednotkovy, bude mat usecka dlzku scale v "user jednotkach" obrazku, ku ktoremu patri grafika gr
   * @param gr GrGraphics  grafika obrazku, do ktoreho sa kresli
   * @param R point bod, do ktoreho sa umiestnuje pociatok vektora pri kresleni
   * @param scale double skalovaci koeficient
   */
  public void draw(GrGraphics gr, point R, double scale){
    vector tmp = vector.times(scale,this);
    gr.drawPoint(R.x,R.y,2);
    gr.drawLine2D(R.x,R.y,R.x+tmp.x,R.y+tmp.y);
  }
}
