// 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 "ncoons.h"

#include <iostream>
#include <fstream>
#include <cmath>

ncoons::ncoons(nparametriccurve &u1_,nparametriccurve &u2_,nparametriccurve &v1_,nparametriccurve &v2_) : u1(u1_),u2(u2_),v1(v1_),v2(v2_)
{
  npoint A1,A2;
  npoint B1,B2;
  npoint C1,C2;
  npoint D1,D2;
  u1.P(min_u(),A1);
  v1.P(min_v(),A2);
  A= (A1+A2) /2.;
  u1.P(max_u(),B1);
  v2.P(min_v(),B2);
  B= (B1+B2) /2.;
  u2.P(max_u(),C1);
  v2.P(max_v(),C2);
  C= (C1+C2) /2.;
  u2.P(min_u(),D1);
  v1.P(max_v(),D2);
  D= (D1+D2) /2.;
}

int ncoons::degree_u(void) const
{
  int deg1=u1.degree(),deg2=u2.degree();
  if ((deg1<0) || (deg1<0)) return -1;
  if (deg1>deg2) return deg1;
  else return deg2;
}

int ncoons::degree_v(void) const
{
  int deg1=v1.degree(),deg2=v2.degree();
  if ((deg1<0) || (deg1<0)) return -1;
  if (deg1>deg2) return deg1;
  else return deg2;
}

int ncoons::degree(void) const
{
  int degu=degree_u(),degv=degree_v(),deg;
  if ((degu<0) || (degv<0)) return -1;
  if (degu>degv) deg=degu;
  else deg=degv;
  if (deg<2) deg=2;
  return deg;
}

double ncoons::min_u() const  // minimum absolu du parametre u
{
  double minu1=u1.min_u();
  double minu2=u2.min_u();
  if (minu2>minu1) return minu2;
  else return minu1;
}

double ncoons::max_u() const // maximum absolu du parametre u
{
  double maxu1=u1.max_u();
  double maxu2=u2.max_u();
  if (maxu2>maxu1) return maxu1;
  else return maxu2;
}

double ncoons::min_v() const // minimum absolu du parametre v
{
  double minv1=v1.min_u();
  double minv2=v2.min_u();
  if (minv2>minv1) return minv2;
  else return minv1;
}

double ncoons::max_v() const // maximum absolu du parametre v
{
  double maxv1=v1.max_u();
  double maxv2=v2.max_u();
  if (maxv2>maxv1) return maxv1;
  else return maxv2;
}



void ncoons::P(double u,double v, npoint& ret) const     // point correspondant a la valeur des parametres u,v
{
  npoint retu1;
  npoint retu2;
  npoint retv1;
  npoint retv2;
  u1.P(u,retu1);
  u2.P(u,retu2);
  v1.P(v,retv1);
  v2.P(v,retv2);
  ret=retu1* (1-v) +retu2*v+retv1* (1-u) +retv2*u- (A* (1-u) * (1-v) +B*u* (1-v) +D*v* (1-u) +C*u*v);
}
