// File:	BlendFunc.cxx
// Created:	Wed Oct  4 11:35:28 1995
// Author:	Jacques GOUSSARD
//		<jag@bravox>
// 09/09/1996 PMN Ajout des methodes GetCircle et GetTolerance.
// 30/12/1996 PMN Ajout de GetMinimalWeight
// 23/09/1997 PMN Supprimme GetCircle et GetTol (passe dans GeomFill)


#include <BlendFunc.ixx>

#include <gp_Circ.hxx>
#include <gp_Pnt.hxx>
#include <gp_Dir.hxx>
#include <gp_Ax2.hxx>

#include <Geom_TrimmedCurve.hxx>
#include <Geom_BSplineCurve.hxx>
#include <Geom_Circle.hxx>
#include <GeomConvert.hxx>
#include <Precision.hxx>
#include <Standard_ConstructionError.hxx>


//=======================================================================
//function : GetShape
//purpose  : 
//=======================================================================

void BlendFunc::GetShape (const BlendFunc_SectionShape SShape,
			  const Standard_Real MaxAng,
			  Standard_Integer& NbPoles,
			  Standard_Integer& NbKnots,
			  Standard_Integer& Degree,
			  Convert_ParameterisationType& TConv)
{
  switch (SShape) {
  case BlendFunc_Rational:
    {
      Standard_Integer NbSpan =
	(Standard_Integer)(Ceiling(3.*Abs(MaxAng)/2./PI));
      NbPoles = 2*NbSpan+1;
      NbKnots = NbSpan+1;
      Degree = 2;
      if (NbSpan == 1) {
	TConv = Convert_TgtThetaOver2_1;
      }
      else { // QuasiAngular affin d'etre C1 (et meme beaucoup plus)
	NbPoles = 7 ;
	NbKnots = 2 ;
	Degree  = 6 ;
	TConv = Convert_QuasiAngular;
      }
    }
    break;
  case BlendFunc_QuasiAngular:
    {
      NbPoles = 7 ;
      NbKnots = 2 ;
      Degree  = 6 ;
      TConv = Convert_QuasiAngular;
    }
    break;
  case BlendFunc_Polynomial:
    {
      NbPoles = 8;
      NbKnots = 2;
      Degree = 7;
      TConv = Convert_Polynomial;
    }
    break;
  case BlendFunc_Linear:
    {
      NbPoles = 2;
      NbKnots = 2;
      Degree = 1;
    }
    break;
  }

}

//=======================================================================
//function : GetMinimalWeights
//purpose  : On suppose les extremum de poids sont obtenus pour les
//           extremums d'angles (A verifier eventuelement pour Quasi-Angular)
//=======================================================================

void BlendFunc::GetMinimalWeights(const BlendFunc_SectionShape SShape,
				  const Convert_ParameterisationType  TConv,
				  const Standard_Real MinAng,
				  const Standard_Real MaxAng,
				  TColStd_Array1OfReal& Weights)

{
  switch (SShape) {
  case BlendFunc_Polynomial:
  case BlendFunc_Linear:
    {
      Weights.Init(1);
    }
    break;
  case BlendFunc_Rational:
  case BlendFunc_QuasiAngular:
    {
      gp_Ax2 popAx2(gp_Pnt(0, 0, 0), gp_Dir(0,0,1));
      gp_Circ C (popAx2, 1);
      Handle(Geom_TrimmedCurve) Sect1 = 
	new Geom_TrimmedCurve(new Geom_Circle(C), 0., MaxAng);
      Handle(Geom_BSplineCurve) CtoBspl = 
      GeomConvert::CurveToBSplineCurve(Sect1, TConv);
      CtoBspl->Weights(Weights);
      
      TColStd_Array1OfReal poids (Weights.Lower(),  Weights.Upper());
      Standard_Real angle_min = Max(Precision::PConfusion(), MinAng);
   
      Handle(Geom_TrimmedCurve) Sect2 = 
	new Geom_TrimmedCurve(new Geom_Circle(C), 0., angle_min);
      CtoBspl = GeomConvert::CurveToBSplineCurve(Sect2, TConv);
      CtoBspl->Weights(poids);

      for (Standard_Integer ii=Weights.Lower(); ii<=Weights.Upper(); ii++) {
	if (poids(ii) < Weights(ii)) {
	  Weights(ii) = poids(ii);
	}
      }
    }
    break;
  }
}


//=======================================================================
//function : IncrementeShape
//purpose  : 
//=======================================================================

GeomAbs_Shape BlendFunc::NextShape (const GeomAbs_Shape S)
{
  switch (S) {
  case GeomAbs_C0 :
    return  GeomAbs_C1;
  case GeomAbs_C1 :
    return  GeomAbs_C2;
  case GeomAbs_C2 :
    return  GeomAbs_C3;
  case GeomAbs_C3 :
    return  GeomAbs_CN;
  default :
    return  GeomAbs_CN;
  }
}
 
