// 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>.
//

#ifndef __NSPLINE_H
#define __NSPLINE_H


#include "nlagrange.h"
#include <vector>


class nspline_like : public nlagrange
{
protected:
  double card; //!< Parameter in [0, 1] for the cardinal spline type.
  enum {TypeUnknown,FiniteDifferences,Cardinal,Natural} type;
    //!< type of spline (defines the way derivatives are computed )
public:
  bool periodic;
  nspline_like(int nCP_) : nlagrange(nCP_),type(TypeUnknown),card(0),periodic(false) {}

  bool is_periodic() const {return periodic;}
  
  /// \brief Computes the finite-difference spline.
  virtual void compute_FD(void)=0;

  /// \brief Computes the cardinal spline.
  /// \param[in] c cardinal parameter in [0, 1].
  virtual void compute_cardinal(double c)=0;

  /// \brief Computes the natural spline.
  virtual void compute_natural(void)=0;
  /// \brief Recomputes internal data
  virtual void update()=0;
};

/// Spline class.
class nspline : public nspline_like
{
protected:
  std::vector<npoint> der;
public:
  /// \brief Constructor.
  /// \param[in] nCP_ number of points to interpolate.
  /// \warning Spline and interpolation points are unitialized.
  nspline(int nCP_) : nspline_like(nCP_),der(nCP_) {}

  /// \brief Computes the finite-difference spline.
  void compute_FD(void);

  /// \brief Computes the cardinal spline.
  /// \param[in] c cardinal parameter in [0, 1].
  void compute_cardinal(double c);

  /// \brief Computes the natural spline.
  void compute_natural(void);
  virtual int degree(void) const
  {
    return 3 ;
  }
  virtual void P(double u_,npoint& ret) const ;    // position along the curve
  virtual void set_CP(int which,const npoint& pt)  // sets a control point
  {
    val[which]=pt;
    update();
  }

  virtual void set_der(int which,const npoint& pt)  // sets a derivative
  {
    der[which]=pt;
    update();
  }

  /// \brief Recomputes derivatives from point positions.
  virtual void update();
  virtual nspline* clone() const
  {
    return new nspline(*this);
  }
private :
  void tridiagsolve(std::vector<double>& rhs);
  void tridiagsolve_circulant(LU_Matrix &LU,std::vector<double>& rhs);
};


#endif // __NSPLINE_H
