// 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 __NLAGRANGE_H
#define __NLAGRANGE_H


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

/// Lagrange polynomials.
class nlagrange : public nparametriccurve
{
protected:
  std::vector<double> pos; //!< Values of u.
  std::vector<npoint> val; //!< Interpolation positions for each value u.
  int nCP; //!< Number of interpolation positions.
public:
  /// \brief Constructor.
  /// \param[in] nCP_ number of interpolation positions.
  /// \warning Values of u and interpolation positions are not initialized.
  nlagrange(int nCP_) : pos(nCP_),val(nCP_),nCP(nCP_) {}

  /// \brief Returns the polynomial degree.
  /// \return Degree.
  virtual int degree(void) const
  {
    return nCP-1 ;
  }

  /// \brief returns the number of interpolation points.
  /// \return Number of interpolation points.
  virtual int nb_CP(void) const
  {
    return nCP ;
  }

  /// \brief Add an interpolation points.
  /// \param[in] u_ u value of interpolation point.
  /// \param[in] val_ interpolation point.
  virtual void add_CP(double u_,const npoint &val_)
  {
    pos.push_back(u_);     // to be done in increasing u values...
    val.push_back(val_);
    nCP++;
  }

  /// \brief Returns minimal value of u.
  /// \return Minimal value.
  virtual double min_u(void) const
  {
    if (nCP) return pos[0];
    else return 0;
  }

  /// \brief Return maximal value of u.
  /// \return Maximal value of u.
  virtual double max_u(void) const
  {
    if (nCP) return pos[nCP-1];
    else return 0;
  }

  /// \brief Basis functions.
  /// \param[in] which number of the wanted basis function.
  /// \param[in] u evaluation paremeter.
  /// \return Value of the basis function number "which" evaluated at u.
  double Basis(int which,double u) const;

  /// \brief Position of a point.
  /// \param[in] u_ curve parameter.
  /// \param[out] ret point at u_.
  virtual void P(double u_,npoint& ret) const;

  /// \brief Returns a control point (interpolated point) - const version.
  /// \param[in] which wanted control point.
  /// \return Control/interpolated point.
  virtual npoint CP(int which) const
  {
    return val[which];
  }

  /// \brief Returns a control point (interpolated point) - non-const version.
  /// \param[in] which wanted control point.
  /// \return Control/interpolated point.
  virtual npoint& CP(int which)
  {
    return val[which];
  }

  /// \brief Changes a control point.
  /// \param[in] which control point number to change.
  /// \param[in] pt new control point.
  virtual void set_CP(int which,const npoint& pt)
  {
    val[which]=pt;
  }

  /// \brief Translates the curve by vector vec.
  /// \param[in] vec translation vector.
  void translate(npoint vec);

  /// \brief Returns u for a given position - const version.
  /// \param[in] which position number.
  /// \return u for the given position.
  virtual double u(int which) const
  {
    return pos[which];
  }

  /// \brief Returns u for a given position - non-const version.
  /// \param[in] which position number.
  /// \return u for the given position.
  virtual double& u(int which)
  {
    return pos[which];
  }

  /// \brief Returns a clone (allocated on the heap).
  /// \return Cloned curve.
  virtual nlagrange* clone() const
  {
    return new nlagrange(*this);
  }
};

#endif // __NLAGRANGE_H

