// Created on: 1994-02-17 // Created by: Bruno DUMORTIER // Copyright (c) 1994-1999 Matra Datavision // Copyright (c) 1999-2014 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // // This library is free software; you can redistribute it and/or modify it under // the terms of the GNU Lesser General Public License version 2.1 as published // by the Free Software Foundation, with special exception defined in the file // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT // distribution for complete text of the license and disclaimer of any warranty. // // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. #include #include #include #include #include #include #include #include #include #include //======================================================================= //function : UnifyByInsertingAllKnots //purpose : //======================================================================= static void UnifyByInsertingAllKnots(TColGeom_SequenceOfCurve& theCurves, const Standard_Real PTol) { // inserting in the first curve the knot-vector of all the others. Handle(Geom_BSplineCurve) C = Handle(Geom_BSplineCurve)::DownCast(theCurves(1)); Standard_Integer i; for ( i = 2; i <= theCurves.Length(); i++) { Handle(Geom_BSplineCurve) Ci = Handle(Geom_BSplineCurve)::DownCast(theCurves(i)); TColStd_Array1OfReal Ki(1,Ci->NbKnots()); Ci->Knots(Ki); TColStd_Array1OfInteger Mi(1,Ci->NbKnots()); Ci->Multiplicities(Mi); C->InsertKnots( Ki, Mi, PTol, Standard_False); } TColStd_Array1OfReal NewKnots(1,C->NbKnots()); C->Knots(NewKnots); TColStd_Array1OfInteger NewMults(1,C->NbKnots()); C->Multiplicities(NewMults); for ( i = 2; i <= theCurves.Length(); i++) { Handle(Geom_BSplineCurve) Ci = Handle(Geom_BSplineCurve)::DownCast(theCurves(i)); Ci->InsertKnots(NewKnots, NewMults, PTol, Standard_False); } // essai : tentative mise des poids sur chaque section a une moyenne 1 for ( i = 1; i <= theCurves.Length(); i++) { Handle(Geom_BSplineCurve) Ci = Handle(Geom_BSplineCurve)::DownCast(theCurves(i)); if ( Ci->IsRational() ) { Standard_Integer np = Ci->NbPoles(); Standard_Real sigma = 0.; Standard_Integer j; for ( j = 1; j <= np; j++) { sigma += Ci->Weight(j); } sigma /= np; for ( j= 1; j<= np; j++) { Ci->SetWeight(j,Ci->Weight(j) / sigma); } } } // fin de l essai } //======================================================================= //function : UnifyBySettingMiddleKnots //purpose : //======================================================================= static void UnifyBySettingMiddleKnots(TColGeom_SequenceOfCurve& theCurves) { Standard_Integer i, j; Handle(Geom_BSplineCurve) C = Handle(Geom_BSplineCurve)::DownCast(theCurves(1)); Standard_Integer NbKnots = C->NbKnots(); Standard_Real ULast = C->Knot(C->LastUKnotIndex()); Standard_Real UFirst = C->Knot(C->FirstUKnotIndex()); //Set middle values of knots TColStd_Array1OfReal NewKnots(1, NbKnots); NewKnots(1) = UFirst; NewKnots(NbKnots) = ULast; for (j = 2; j < NbKnots; j++) { Standard_Real aMidKnot = 0.; for (i = 1; i <= theCurves.Length(); i++) { Handle(Geom_BSplineCurve) Ctemp = Handle(Geom_BSplineCurve)::DownCast(theCurves(i)); aMidKnot += Ctemp->Knot(j); } aMidKnot /= theCurves.Length(); NewKnots(j) = aMidKnot; } for (i = 1; i <= theCurves.Length(); i++) { Handle(Geom_BSplineCurve) Cres = Handle(Geom_BSplineCurve)::DownCast(theCurves(i)); Cres->SetKnots(NewKnots); } } //======================================================================= //function : GeomFill_Profiler //purpose : //======================================================================= GeomFill_Profiler::GeomFill_Profiler() { myIsDone = Standard_False; myIsPeriodic = Standard_True; } //======================================================================= GeomFill_Profiler::~GeomFill_Profiler() { } //======================================================================= //function : AddCurve //purpose : //======================================================================= void GeomFill_Profiler::AddCurve(const Handle(Geom_Curve)& Curve) { Handle(Geom_Curve) C; //// modified by jgv, 19.01.05 for OCC7354 //// Handle(Geom_Curve) theCurve = Curve; if (theCurve->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve))) theCurve = Handle(Geom_TrimmedCurve)::DownCast (theCurve)->BasisCurve(); if (theCurve->IsKind(STANDARD_TYPE(Geom_Conic))) { GeomConvert_ApproxCurve appr(Curve, Precision::Confusion(), GeomAbs_C1, 16, 14); if (appr.HasResult()) C = appr.Curve(); } if (C.IsNull()) C = GeomConvert::CurveToBSplineCurve(Curve); /* if ( Curve->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) { C = Handle(Geom_Curve)::DownCast(Curve->Copy()); } else { C = GeomConvert::CurveToBSplineCurve(Curve,Convert_QuasiAngular); } */ /////////////////////////////////////////////// mySequence.Append( C); if ( myIsPeriodic && !C->IsPeriodic()) myIsPeriodic = Standard_False; } //======================================================================= //function : Perform //purpose : //======================================================================= void GeomFill_Profiler::Perform(const Standard_Real PTol) { Standard_Integer i; // Standard_Integer myDegree = 0, myNbPoles = 0; Standard_Integer myDegree = 0; Handle(Geom_BSplineCurve) C; Standard_Real U1, U2, UFirst=0, ULast=0; Standard_Real EcartMax = 0.; for ( i = 1; i <= mySequence.Length(); i++) { C = Handle(Geom_BSplineCurve)::DownCast(mySequence(i)); // si non periodique, il faut deperiodiser toutes les courbes // on les segmente ensuite pour assurer K(1) et K(n) de multiplicite // degre + 1 U2 = C->Knot(C->LastUKnotIndex()); U1 = C->Knot(C->FirstUKnotIndex()); if ( !myIsPeriodic && C->IsPeriodic()) { C->SetNotPeriodic(); C->Segment( U1, U2); } // evaluate the max degree myDegree = Max( myDegree, C->Degree()); // Calcul de Max ( Ufin - Udeb) sur l ensemble des courbes. if ( ( U2 - U1) > EcartMax) { EcartMax = U2 - U1; UFirst = U1; ULast = U2; } } // increase the degree of the curves to my degree // reparametrize them in the range U1, U2. for ( i = 1; i <= mySequence.Length(); i++) { C = Handle(Geom_BSplineCurve)::DownCast(mySequence(i)); C->IncreaseDegree( myDegree); TColStd_Array1OfReal Knots(1,C->NbKnots()); C->Knots(Knots); BSplCLib::Reparametrize(UFirst,ULast,Knots); C->SetKnots(Knots); } TColGeom_SequenceOfCurve theCurves; for (i = 1; i <= mySequence.Length(); i++) theCurves.Append(Handle(Geom_Curve)::DownCast(mySequence(i)->Copy())); UnifyByInsertingAllKnots(theCurves, PTol); Standard_Boolean Unified = Standard_True; Standard_Integer theNbKnots = (Handle(Geom_BSplineCurve)::DownCast(theCurves(1)))->NbKnots(); for (i = 2; i <= theCurves.Length(); i++) if ((Handle(Geom_BSplineCurve)::DownCast(theCurves(i)))->NbKnots() != theNbKnots) { Unified = Standard_False; break; } if (Unified) mySequence = theCurves; else UnifyBySettingMiddleKnots(mySequence); myIsDone = Standard_True; } //======================================================================= //function : Degree //purpose : //======================================================================= Standard_Integer GeomFill_Profiler::Degree() const { if ( !myIsDone) throw StdFail_NotDone("GeomFill_Profiler::Degree"); Handle(Geom_BSplineCurve) C = Handle(Geom_BSplineCurve)::DownCast(mySequence(1)); return C->Degree(); } //======================================================================= //function : NbPoles //purpose : //======================================================================= Standard_Integer GeomFill_Profiler::NbPoles() const { if ( !myIsDone) throw StdFail_NotDone("GeomFill_Profiler::Degree"); Handle(Geom_BSplineCurve) C = Handle(Geom_BSplineCurve)::DownCast(mySequence(1)); return C->NbPoles(); } //======================================================================= //function : Poles //purpose : //======================================================================= void GeomFill_Profiler::Poles(const Standard_Integer Index, TColgp_Array1OfPnt& Poles) const { if ( !myIsDone) throw StdFail_NotDone("GeomFill_Profiler::Degree"); Standard_DomainError_Raise_if( Poles.Length() != NbPoles(), "GeomFill_Profiler::Poles"); Standard_DomainError_Raise_if( Index < 1 || Index > mySequence.Length(), "GeomFill_Profiler::Poles"); Handle(Geom_BSplineCurve) C = Handle(Geom_BSplineCurve)::DownCast(mySequence(Index)); C->Poles(Poles); } //======================================================================= //function : Weights //purpose : //======================================================================= void GeomFill_Profiler::Weights(const Standard_Integer Index, TColStd_Array1OfReal& Weights) const { if ( !myIsDone) throw StdFail_NotDone("GeomFill_Profiler::Degree"); Standard_DomainError_Raise_if( Weights.Length() != NbPoles(), "GeomFill_Profiler::Weights"); Standard_DomainError_Raise_if( Index < 1 || Index > mySequence.Length(), "GeomFill_Profiler::Weights"); Handle(Geom_BSplineCurve) C = Handle(Geom_BSplineCurve)::DownCast(mySequence(Index)); C->Weights(Weights); } //======================================================================= //function : NbKnots //purpose : //======================================================================= Standard_Integer GeomFill_Profiler::NbKnots() const { if ( !myIsDone) throw StdFail_NotDone("GeomFill_Profiler::Degree"); Handle(Geom_BSplineCurve) C = Handle(Geom_BSplineCurve)::DownCast(mySequence(1)); return C->NbKnots(); } //======================================================================= //function : KnotsAndMults //purpose : //======================================================================= void GeomFill_Profiler::KnotsAndMults(TColStd_Array1OfReal& Knots, TColStd_Array1OfInteger& Mults ) const { if ( !myIsDone) throw StdFail_NotDone("GeomFill_Profiler::Degree"); #ifndef No_Exception Standard_Integer n = NbKnots(); #endif Standard_DomainError_Raise_if( Knots.Length() != n || Mults.Length() != n, "GeomFill_Profiler::KnotsAndMults"); Handle(Geom_BSplineCurve) C = Handle(Geom_BSplineCurve)::DownCast(mySequence(1)); C->Knots(Knots); C->Multiplicities(Mults); }