// 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 "ndisplay.h"
#define pi (3.1415926536)


void init_lagrange(nlagrange &courbe,double DX,double DY, bool cheb=false)
{
//  std::ofstream of("cp.txt");
  for (int i=0;i< courbe.nb_CP();i++)
  {
    double angle=i*pi/ (courbe.nb_CP()-1);
    double random=0* (randr()-0.5) /100;
 //   random=(2*i<courbe.nb_CP())?-0.00025:+0.00025;
    npoint val;
    val[0]=cos(angle) * (1+random) +DX;
    val[1]=sin(angle) * (1+random) +DY;
    val[2]=0.;
    val[3]=1.;
    double uu=(2*(i+1.)-1.)/(2*courbe.nb_CP())*n_pi;
    if (cheb) courbe.u(i) = 0.5-0.5*cos(uu)*1./cos(n_pi/(2.*courbe.nb_CP())); // chebyshev nodes
    else courbe.u(i) = (i*1.)/(courbe.nb_CP()-1); // constant interval
//    std::cout << courbe.u(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*pi/ (courbe.nb_CP()-1);
    double random=0* (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.);
  courbe.compute_natural();
}


void init_bezier(nbeziercurve &courbe,double DX,double DY)
{
  for (int i=0;i< courbe.nb_CP();i++)
  {
    double angle=i*pi/ (courbe.nb_CP()-1);
    double random=0* (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*pi/ (courbe.nb_CP()-1);
    double random=0* (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;
  }
}






void init_bspline_periodic(nbspline &courbe,double DX,double DY)
{
  int cps=courbe.nb_CP();
  int degree=courbe.degree();
  int cps2=cps-3;
  for (int i=0;i<cps;++i)
  {
    double angle=i*2*pi/ ((double)(cps2));
    double random=0* (randr() +randr()-0.5) /7;
    random=cos(angle*6) /6;
//  if (i<(degree-1)/2) random=0.05; else random=0;
//  if (i>(degree-1)/2) random=-0.05;
//  if (i==0) random=-1;
//  if (i==cps) random=-1;
    npoint val;
    val[0]=cos(angle) * (0.5+random) +DX;
    val[1]=sin(angle) * (0.5+random) +DY;
    val[2]=0.;
    val[3]=1.;
    courbe.CP(i) =val;
  }

  for (int i=-degree;i<cps+degree-2;++i)
  {
    courbe.u(i+degree) = (i) /10.;
  }

  /* for (int i=0;i<=cps+degree+1;++i)
      cout << pos[i] << " ";
    cout << endl;*/
}







#include "nutil.h"
#include "gnurbscallbacks.h"
#include <iostream>


int main(void)
{

  data_container data;
  ndisplay display;
//  display.interaction(false);
  int nCP=21;

  nlagrange courbe1(nCP);
  nlagrange courbe11(nCP);
  nspline courbe2(nCP);
  nbeziercurve courbe3(nCP);
  nbeziercurve courbe31(nCP),courbe32(nCP);
  nbspline courbe4(nCP,3);
  nbspline courbe5(nCP,3);
  nbspline courbe6;
  init_lagrange(courbe1,-1.5,+1.5);
  init_lagrange(courbe11,+1.5,+1.5,true);
//  init_lagrange(courbe11,0,0,true);
  init_spline(courbe2,+4.5,+1.5);
  init_bezier(courbe3,+1.5,-1.5);
  init_bspline(courbe4,+4.5,-1.5);
  init_bspline_periodic(courbe5,-1.5,-1.5);
  courbe6=courbe4;
  npoint np;
  courbe3.cut(0.5,np,courbe31,courbe32);
  gnurbscallbacks CB;
//  courbe4.degree_elevation();
  CB.add_entity(&courbe1);
  CB.add_entity(&courbe11);
  CB.add_entity(&courbe2);
  CB.add_entity(&courbe3);
  CB.add_entity(&courbe4);
  CB.add_entity(&courbe5);
//  CB.add_entity(&courbe6);
 // courbe1.Display(data);
//  courbe2.Display(data);
//  courbe3.Display(data);
//  courbe4.Display(data);
//  courbe5.Display(data);
//  courbe6.Display(data);
  nmesh pts;
  nmesh bnd;
//  courbe4.Discretize(pts,bnd,0.,0.,0.,0.001);
//  for (int i=0;i<pts.nb_nodes();++i) std::cout << pts.get_node(i).xyz.x() << " " <<  pts.get_node(i).xyz.y() << " " <<  pts.get_node(i).xyz.z() << std::endl;
/*  std::ofstream of("test.txt");
  nlagrange &s=courbe11;
  double eps=(s.u(s.nb_CP()-1)-s.u(0))/(10*(s.nb_CP()-1));
  for (double u=s.u(0);u<=(s.u(s.nb_CP()-1)+eps/2);u+=eps)
  {
  npoint ret;
  s.P(u,ret);
//  evalspline(pos, val2, der2, u,nbpts, ret2);
  of << u << " "<< ret[0] << " "<< ret[1] ; // << " " << ret2[0] << " "<< ret2[1] << " " << (ret[0]*sin(pi/4)-ret[1]*cos(pi/4))/2 +0.25<< " "<< ret[0]*cos(pi/4)+ret[1]*sin(pi/4) << " ";
  of << endl;
  }
  of.close();*/
  display.setcallbacks(&CB);
  CB.draw();
  display.init_data(CB.datas);
  display.display();
  return 0;
}


