import sk.uniba.fmph.pocprak.simplegraphics.*;

/**
 * Trieda reprezentujuca strunu upevnenu v koncovych bodoch
 * kmitajucu priecne. Pre zjednodusenie uvazuje len staticke pociatocne podmienky
 * teda nulovu pociatocnu rychlost vsetkych bodov. Pociatocny stav je
 * teda reprezentovany len funkciou charakterizujucou pociatocnu vychylku
 */
public class Struna {
  /**
   * Dlzka struny, struna je natiahnuta na usecku (0,L)
   */
  public double L;
  /**
   * objekt reprezentujuci Fourierov rad pomocou ktoreho reprezentujeme vychylky struny
   */
  public Fourier fou;
  /**
   * zakladna frekvencia kmitov stuny (frekvencia najnizsieho stacionarneho modu)
   */
  public double f;

  /**
   * pocet normalnych modov uvazovanych pri popise kmitov struny (defaultova hodonota 10)
   */
  public static int nmax = 10;

  /**
   * Privatne pole obsahujuce kruhove frekvenciu jednotlivych normalnych modov struny
   */
  private double om[];

  /**
   * Pocet bodov pouzivanych na vykreslenie vychylky struny
   */
  public static int ndrawpoints = 1000;

  public Struna(double L, double f) {
    this.L = L;
    this.f = f;
    fou = new Fourier(nmax, L);
    om = new double[nmax + 1];
    for (int i = 1; i < nmax + 1; i++) {
      fou.coef[i] = 0;
      om[i] = 2. * Math.PI * f*i;
    }
  }

  /**
   * Metoda zadavajuca pociatocnu vychylku struny ako funkciu reprezentovanu
   * interface-objektom typu Integrable
   * @param y0 Integrable objekt definujuci pociatocny stav struny
   */
  public void initState(Integrable y0) {
    fou.makeTransform(y0);
  }

  /**
   * Funkcia reprezentujuca okamzitu priecnu vychylku strunny v mieste x v case t
   * @param x double suradnica bodu, kotreho vychylku pocitame
   * @param t double cas v ktorom pocitame vychylku
   * @return double vychylka
   */
  public double y(double x, double t) {
    double sum = 0;
    for (int i = 1; i < nmax + 1; i++) {
      sum = sum + fou.coef[i] * Math.cos(om[i] * t) * fou.F(i, x);
    }
    return sum;
  }

  /**
   * Funkcia vykreslujuca tvar vychylky v case t
   * @param gr GrGraphics grafika okna, v ktorom sa bude vykreslovat
   * @param t double okamih v ktorom sa vykresluje tvar srtuny
   */
  public void draw(GrGraphics gr, double t) {
    double x = 0;
    double dx = L / ndrawpoints;
    for (int i = 0; i < ndrawpoints; i++) {
      gr.drawPoint(x, y(x, t));
      x = x + dx;
    }
  }
}
