// File:	StepToGeom_MakeBoundedSurface.cxx
// Created:	Fri Jul  2 16:04:19 1993
// Author:	Martine LANGLOIS
//		<mla@mastox>
//:p0 abv 19.02.99: management of 'done' flag improved
//:j7 abv 05.04.99: S4136: ass-tol2.stp #9861: avoid using CheckSurfaceClosure
//    rln 02.06.99 removing #include <StepToGeom_CheckSurfaceClosure.hxx>

#include <StepToGeom_MakeBoundedSurface.ixx>
#include <StdFail_NotDone.hxx>

#include <Geom_BSplineSurface.hxx>

//rln 02.06.99 #include <StepToGeom_CheckSurfaceClosure.hxx>

#include <StepToGeom_MakeBoundedSurface.hxx>
#include <StepToGeom_MakeBSplineSurface.hxx>
#include <StepToGeom_MakeRectangularTrimmedSurface.hxx>

#include <StepGeom_RectangularTrimmedSurface.hxx>
#include <StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface.hxx>
#include <StepGeom_BSplineSurfaceWithKnots.hxx>

#include <TColStd_HArray1OfInteger.hxx>
#include <TColStd_HArray1OfReal.hxx>

#include <StepGeom_BezierSurface.hxx>
#include <StepGeom_UniformSurface.hxx>
#include <StepGeom_QuasiUniformSurface.hxx>
#include <StepGeom_UniformSurfaceAndRationalBSplineSurface.hxx>
#include <StepGeom_QuasiUniformSurfaceAndRationalBSplineSurface.hxx>
#include <StepGeom_KnotType.hxx>

//=============================================================================
// Creation d' une BoundedSurface de Geom a partir d' une BoundedSurface
// de Step
//=============================================================================

StepToGeom_MakeBoundedSurface::StepToGeom_MakeBoundedSurface
  ( const Handle(StepGeom_BoundedSurface)& S)
{
  done = Standard_False;

  Handle(StepGeom_BSplineSurfaceWithKnots) BSPL = new StepGeom_BSplineSurfaceWithKnots;
  Handle(StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface) RBSPL = 
    new StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface;

  if (S->IsKind(STANDARD_TYPE(StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface))) { 
    Handle(StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface) BS= Handle(StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface)::DownCast(S);
    StepToGeom_MakeBSplineSurface MkBSplineS(BS);
    if ( MkBSplineS.IsDone() ) theBoundedSurface = MkBSplineS.Value();
  }
  else if (S->IsKind(STANDARD_TYPE(StepGeom_BSplineSurfaceWithKnots))) {
    Handle(StepGeom_BSplineSurfaceWithKnots) BS
      = Handle(StepGeom_BSplineSurfaceWithKnots)::DownCast(S);
    StepToGeom_MakeBSplineSurface MkBSplineS(BS);
    if ( MkBSplineS.IsDone() ) theBoundedSurface = MkBSplineS.Value();
  }
  else if (S->IsKind(STANDARD_TYPE(StepGeom_RectangularTrimmedSurface))) {
    Handle(StepGeom_RectangularTrimmedSurface) Sur = 
      Handle(StepGeom_RectangularTrimmedSurface)::DownCast(S);
    StepToGeom_MakeRectangularTrimmedSurface MkRTSurf(Sur);
    if ( MkRTSurf.IsDone() ) theBoundedSurface = MkRTSurf.Value();
  }
  // STEP BezierSurface, UniformSurface and QuasiUniformSurface are transformed
  // into STEP BSplineSurface before being mapped onto CAS.CADE/SF
  else if (S->IsKind(STANDARD_TYPE(StepGeom_BezierSurface))) {
    Handle(StepGeom_BezierSurface) BzS = Handle(StepGeom_BezierSurface)::DownCast(S);
    BSPL->SetUDegree(BzS->UDegree());
    BSPL->SetVDegree(BzS->VDegree());
    BSPL->SetControlPointsList(BzS->ControlPointsList());
    BSPL->SetSurfaceForm(BzS->SurfaceForm());
    BSPL->SetUClosed(BzS->UClosed());
    BSPL->SetVClosed(BzS->VClosed());
    BSPL->SetSelfIntersect(BzS->SelfIntersect());
    // Compute Knots and KnotsMultiplicity
    Handle(TColStd_HArray1OfInteger) UKmult = new TColStd_HArray1OfInteger(1,2);
    Handle(TColStd_HArray1OfInteger) VKmult = new TColStd_HArray1OfInteger(1,2);
    Handle(TColStd_HArray1OfReal) UKnots = new TColStd_HArray1OfReal(1,2);
    Handle(TColStd_HArray1OfReal) VKnots = new TColStd_HArray1OfReal(1,2);
    UKmult->SetValue(1, BzS->UDegree() + 1);
    UKmult->SetValue(2, BzS->UDegree() + 1);
    VKmult->SetValue(1, BzS->VDegree() + 1);
    VKmult->SetValue(2, BzS->VDegree() + 1);
    UKnots->SetValue(1, 0.);
    UKnots->SetValue(2, 1.);
    VKnots->SetValue(1, 0.);
    VKnots->SetValue(2, 1.);
    BSPL->SetUMultiplicities(UKmult);
    BSPL->SetVMultiplicities(VKmult);
    BSPL->SetUKnots(UKnots);
    BSPL->SetVKnots(VKnots);
    StepToGeom_MakeBSplineSurface MkSurface(BSPL);
    if ( MkSurface.IsDone() ) theBoundedSurface = MkSurface.Value();
  }
  else if (S->IsKind(STANDARD_TYPE(StepGeom_UniformSurface))) {
#ifdef DEBUG
    cout << "Warning : converting UniformSurface onto BSplineSurfaceWithKnots" << endl;
#endif
    Handle(StepGeom_UniformSurface) US = Handle(StepGeom_UniformSurface)::DownCast(S);
    BSPL->SetUDegree(US->UDegree());
    BSPL->SetVDegree(US->VDegree());
    BSPL->SetControlPointsList(US->ControlPointsList());
    BSPL->SetSurfaceForm(US->SurfaceForm());
    BSPL->SetUClosed(US->UClosed());
    BSPL->SetVClosed(US->VClosed());
    BSPL->SetSelfIntersect(US->SelfIntersect());
    // Compute Knots and KnotsMultiplicity for U Direction
    Standard_Integer nbKU = BSPL->NbControlPointsListI() + BSPL->UDegree() + 1;
    Handle(TColStd_HArray1OfInteger) UKmult = new TColStd_HArray1OfInteger(1,nbKU);
    Handle(TColStd_HArray1OfReal) UKnots = new TColStd_HArray1OfReal(1,nbKU);
    for (Standard_Integer iU = 1 ; iU <= nbKU ; iU ++) {
      UKmult->SetValue(iU, 1);
      UKnots->SetValue(iU, iU - 1.);
    }
    BSPL->SetUMultiplicities(UKmult);
    BSPL->SetUKnots(UKnots);
    // Compute Knots and KnotsMultiplicity for V Direction
    Standard_Integer nbKV = BSPL->NbControlPointsListJ() + BSPL->VDegree() + 1;
    Handle(TColStd_HArray1OfInteger) VKmult = new TColStd_HArray1OfInteger(1,nbKV);
    Handle(TColStd_HArray1OfReal) VKnots = new TColStd_HArray1OfReal(1,nbKV);
    for (Standard_Integer iV = 1 ; iV <= nbKV ; iV ++) {
      VKmult->SetValue(iV, 1);
      VKnots->SetValue(iV, iV - 1.);
    }
    BSPL->SetVMultiplicities(VKmult);
    BSPL->SetVKnots(VKnots);

    StepToGeom_MakeBSplineSurface MkSurface(BSPL);
    if ( MkSurface.IsDone() ) theBoundedSurface = MkSurface.Value();
  }
  else if (S->IsKind(STANDARD_TYPE(StepGeom_QuasiUniformSurface))) {
#ifdef DEBUG
    cout << "Warning : converting QuasiUniformSurface onto BSplineSurfaceWithKnots" << endl;
#endif
    Handle(StepGeom_QuasiUniformSurface) QUS = 
      Handle(StepGeom_QuasiUniformSurface)::DownCast(S);
    BSPL->SetUDegree(QUS->UDegree());
    BSPL->SetVDegree(QUS->VDegree());
    BSPL->SetControlPointsList(QUS->ControlPointsList());
    BSPL->SetSurfaceForm(QUS->SurfaceForm());
    BSPL->SetUClosed(QUS->UClosed());
    BSPL->SetVClosed(QUS->VClosed());
    BSPL->SetSelfIntersect(QUS->SelfIntersect());
    // Compute Knots and KnotsMultiplicity for U Direction
    Standard_Integer nbKU = BSPL->NbControlPointsListI() - BSPL->UDegree() + 1;
    Handle(TColStd_HArray1OfInteger) UKmult = new TColStd_HArray1OfInteger(1,nbKU);
    Handle(TColStd_HArray1OfReal) UKnots = new TColStd_HArray1OfReal(1,nbKU);
    for (Standard_Integer iU = 1 ; iU <= nbKU ; iU ++) {
      UKmult->SetValue(iU, 1);
      UKnots->SetValue(iU, iU - 1.);
    }
    UKmult->SetValue(1, BSPL->UDegree() + 1);
    UKmult->SetValue(nbKU, BSPL->UDegree() + 1);
    BSPL->SetUMultiplicities(UKmult);
    BSPL->SetUKnots(UKnots);
    // Compute Knots and KnotsMultiplicity for V Direction
    Standard_Integer nbKV = BSPL->NbControlPointsListJ() - BSPL->VDegree() + 1;
    Handle(TColStd_HArray1OfInteger) VKmult = new TColStd_HArray1OfInteger(1,nbKV);
    Handle(TColStd_HArray1OfReal) VKnots = new TColStd_HArray1OfReal(1,nbKV);
    for (Standard_Integer iV = 1 ; iV <= nbKV ; iV ++) {
      VKmult->SetValue(iV, 1);
      VKnots->SetValue(iV, iV - 1.);
    }
    VKmult->SetValue(1, BSPL->VDegree() + 1);
    VKmult->SetValue(nbKV, BSPL->VDegree() + 1);
    BSPL->SetVMultiplicities(VKmult);
    BSPL->SetVKnots(VKnots);

    StepToGeom_MakeBSplineSurface MkSurface(BSPL);
    if ( MkSurface.IsDone() ) theBoundedSurface = MkSurface.Value();
  }
  else if (S->IsKind(STANDARD_TYPE(StepGeom_UniformSurfaceAndRationalBSplineSurface))) {
#ifdef DEBUG
    cout << "Warning : converting Rational UniformSurface onto BSplineSurfaceWithKnots" << endl;
#endif
    Handle(StepGeom_UniformSurfaceAndRationalBSplineSurface) RUS = 
      Handle(StepGeom_UniformSurfaceAndRationalBSplineSurface)::DownCast(S);
    // Compute Knots and KnotsMultiplicity for U Direction
    Standard_Integer nbKU = RUS->NbControlPointsListI() + RUS->UDegree() + 1;
    Handle(TColStd_HArray1OfInteger) UKmult = new TColStd_HArray1OfInteger(1,nbKU);
    Handle(TColStd_HArray1OfReal) UKnots = new TColStd_HArray1OfReal(1,nbKU);
    for (Standard_Integer iU = 1 ; iU <= nbKU ; iU ++) {
      UKmult->SetValue(iU, 1);
      UKnots->SetValue(iU, iU - 1.);
    }
    // Compute Knots and KnotsMultiplicity for V Direction
    Standard_Integer nbKV = RUS->NbControlPointsListJ() + RUS->VDegree() + 1;
    Handle(TColStd_HArray1OfInteger) VKmult = new TColStd_HArray1OfInteger(1,nbKV);
    Handle(TColStd_HArray1OfReal) VKnots = new TColStd_HArray1OfReal(1,nbKV);
    for (Standard_Integer iV = 1 ; iV <= nbKV ; iV ++) {
      VKmult->SetValue(iV, 1);
      VKnots->SetValue(iV, iV - 1.);
    }
    // Initialize the BSplineSurfaceWithKnotsAndRationalBSplineSurface
    StepGeom_KnotType TypeKnots = StepGeom_ktUnspecified;
    RBSPL->Init(RUS->Name(), RUS->UDegree(), RUS->VDegree(), 
		RUS->ControlPointsList(), RUS->SurfaceForm(),
		RUS->UClosed(), RUS->VClosed(), RUS->SelfIntersect(), 
		UKmult, VKmult, UKnots, VKnots, TypeKnots,
		RUS->WeightsData());
    StepToGeom_MakeBSplineSurface MkSurface(RBSPL);
    if ( MkSurface.IsDone() ) theBoundedSurface = MkSurface.Value();
  }
  else if (S->IsKind(STANDARD_TYPE(StepGeom_QuasiUniformSurfaceAndRationalBSplineSurface))) {
#ifdef DEBUG
    cout << "Warning : converting Rational QuasiUniformSurface onto BSplineSurfaceWithKnots" << endl;
#endif
    Handle(StepGeom_QuasiUniformSurfaceAndRationalBSplineSurface) RQUS = 
      Handle(StepGeom_QuasiUniformSurfaceAndRationalBSplineSurface)::DownCast(S);
    // Compute Knots and KnotsMultiplicity for U Direction
    Standard_Integer nbKU = RQUS->NbControlPointsListI() - RQUS->UDegree() + 1;
    Handle(TColStd_HArray1OfInteger) UKmult = new TColStd_HArray1OfInteger(1,nbKU);
    Handle(TColStd_HArray1OfReal) UKnots = new TColStd_HArray1OfReal(1,nbKU);
    for (Standard_Integer iU = 1 ; iU <= nbKU ; iU ++) {
      UKmult->SetValue(iU, 1);
      UKnots->SetValue(iU, iU - 1.);
    }
    UKmult->SetValue(1, RQUS->UDegree() + 1);
    UKmult->SetValue(nbKU, RQUS->UDegree() + 1);
    // Compute Knots and KnotsMultiplicity for V Direction
    Standard_Integer nbKV = RQUS->NbControlPointsListJ() - RQUS->VDegree() + 1;
    Handle(TColStd_HArray1OfInteger) VKmult = new TColStd_HArray1OfInteger(1,nbKV);
    Handle(TColStd_HArray1OfReal) VKnots = new TColStd_HArray1OfReal(1,nbKV);
    for (Standard_Integer iV = 1 ; iV <= nbKV ; iV ++) {
      VKmult->SetValue(iV, 1);
      VKnots->SetValue(iV, iV - 1.);
    }
    VKmult->SetValue(1, RQUS->VDegree() + 1);
    VKmult->SetValue(nbKV, RQUS->VDegree() + 1);
    // Initialize the BSplineSurfaceWithKnotsAndRationalBSplineSurface
    StepGeom_KnotType TypeKnots = StepGeom_ktUnspecified;
    RBSPL->Init(RQUS->Name(), RQUS->UDegree(), RQUS->VDegree(), RQUS->ControlPointsList(), 
		RQUS->SurfaceForm(), RQUS->UClosed(), RQUS->VClosed(), 
		RQUS->SelfIntersect(), UKmult, VKmult, UKnots, VKnots, TypeKnots,
		RQUS->WeightsData());
    StepToGeom_MakeBSplineSurface MkSurface(RBSPL);
    if ( MkSurface.IsDone() ) theBoundedSurface = MkSurface.Value();
  }
  done = ! theBoundedSurface.IsNull();

/* //:S4136: ass-tol2.stp #9861
  // UPDATE FMA 15-03-96
  // For BSplineSurface, the surface could be U and/or VClosed within the 
  // file tolerance. In this case, the closure flag is enforced
  
  if (done && //:i6
      theBoundedSurface->IsKind(STANDARD_TYPE(Geom_BSplineSurface))) {

    Handle(Geom_BSplineSurface) theBSP = 
      Handle(Geom_BSplineSurface)::DownCast(theBoundedSurface);
    if (!theBSP->IsURational() &&
	!theBSP->IsVRational()) {
      StepToGeom_CheckSurfaceClosure CheckClose(theBSP);
      theBoundedSurface = CheckClose.Surface();
    }
  }
*/  
}	 


//=============================================================================
// renvoi des valeurs
//=============================================================================

const Handle(Geom_BoundedSurface) &
      StepToGeom_MakeBoundedSurface::Value() const
{
  StdFail_NotDone_Raise_if(!done == Standard_True,"");
  return theBoundedSurface;
}
