// Gnurbs - A curve and surface library
// Copyright (C) 2008-2026 Eric Bechet
//
// See the LICENSE file for contributions and license information.
// Please report all bugs and problems to <bechet@cadxfem.org>.
//

#include <iostream>
#include <fstream>
#include "nlagrange.h"
#include "nspline.h"
#include "nbspline.h"
#include "nbeziercurve.h"
#include "nvtkdisplay.h"

// Initialization function prototype
// the complete implementation can be found at the end of the file
// DX and DY are the offsets with respect to the origin

void init_lagrange(nlagrange &courbe,double DX,double DY);
void init_spline(nspline &courbe,double DX,double DY);
void init_bezier(nbeziercurve &courbe,double DX,double DY);
void init_bspline(nbspline &courbe,double DX,double DY);

// main function

int main(void)
{
  data_container data;                // Contains data to display
  nvtkdisplay display;                // Display window
  int nCP=7;                          // Number of control points
  nlagrange courbe1(nCP);             // Lagrange curve with nCP control points
  nspline courbe2(nCP);               // Spline curve "" ""
  nbeziercurve courbe3(nCP);          // Bezier curve "" ""
  nbspline courbe4(nCP,3);            // BSpline curve "" ""
  init_lagrange(courbe1,-1.5,+1.5);   // Curves initialization
  init_spline(courbe2,+1.5,+1.5);
  init_bezier(courbe3,-1.5,-1.5);
  init_bspline(courbe4,-1.5,-4.5);

  nbeziercurve courbe3_elev(nCP);                // New Bezier curve with nCP control points
	init_bezier(courbe3_elev,-1.5,-1.5);           // courbe3_elev is initialized with the same control points as courbe3
  courbe3_elev.degree_elevation();               // Degree elevation for courbe3_elev
  courbe3_elev.translate(npoint(3.,0.,0.,0.));   // then courbe3_elev is translated

  color red (255,0,0);                //Create basic Colors
  color yellow (255,255,0);

  display.add_curve(&courbe1,red,yellow);     // Display of the curve and allow to interact with the curve in the display window
  display.add_curve(&courbe2);
  display.add_curve(&courbe3);
  display.add_curve(&courbe3_elev);
  display.add_curve(&courbe4);

  display.init_data(data);
  display.display();              // Display and interaction loop
  return 0;
}

void init_lagrange(nlagrange &courbe,double DX,double DY)
{
//  std::ofstream of("cp.txt");
  for (int i=0;i< courbe.nb_CP();i++)
  {
    double angle=i*n_pi/(courbe.nb_CP()-1);
    double random=2*(randr()-0.5)/100;
    npoint val;
    val[0]=cos(angle)*(1+random)+DX;
    val[1]=sin(angle)*(1+random)+DY;
    val[2]=0;
    val[3]=1;
    courbe.u(i)=i;
    courbe.CP(i)=val;
//     of << courbe.u(i) << " " << val[0] << " " << val[1]  << endl;
  }
//  of.close();
}

void init_spline(nspline &courbe,double DX,double DY)
{
  for (int i=0;i< courbe.nb_CP();i++)
  {
    double angle=i*n_pi/(courbe.nb_CP()-1);
    double random=2*(randr()-0.5)/100;
    npoint val;
    val[0]=cos(angle)*(1+random)+DX;
    val[1]=sin(angle)*(1+random)+DY;
    val[2]=0;
    val[3]=1;
    courbe.u(i)=i;
    courbe.CP(i)=val;
  }
  courbe.compute_cardinal(0.);
}


void init_bezier(nbeziercurve &courbe,double DX,double DY)
{
  for (int i=0;i< courbe.nb_CP();i++)
  {
    double angle=i*n_pi/(courbe.nb_CP()-1);
    double random=2*(randr()-0.5)/100;
    npoint val;
    val[0]=cos(angle)*(1+random)+DX;
    val[1]=sin(angle)*(1+random)+DY;
    val[2]=0;
    val[3]=1;
    courbe.CP(i)=val;
  }
}


void init_bspline(nbspline &courbe,double DX,double DY)
{
  for (int i=0;i< courbe.nb_CP();i++)
  {
    double angle=i*n_pi/(courbe.nb_CP()-1);
    double random=2*(randr()-0.5)/100;
    npoint val;
    val[0]=cos(angle)*(1+random)+DX;
    val[1]=sin(angle)*(1+random)+DY;
    val[2]=0;
    val[3]=1;
    courbe.CP(i)=val;
  }
  int ends=courbe.degree()+1;
  int i;
  for (i=1;i<=(courbe.nb_CP()-1+courbe.degree()+2-2*ends);++i)
  {
    courbe.u(i+ends-1)=i;
  }
  for (int j=0;j<ends;++j)
  {
    courbe.u(j)=0.0;
    courbe.u(courbe.nb_CP()+courbe.degree()-j)=i;
  }
}
