// Created on: 1998-12-14 // Created by: Joelle CHAUVET // Copyright (c) 1998-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. // Modified: Fri Jan 8 15:47:20 1999 // enfin un calcul exact pour D1 et D2 // le calcul par differ. finies est garde dans verifD1 et verifD2 // Modified: Mon Jan 18 11:06:46 1999 // mise au point de D1, D2 et IsConstant #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include IMPLEMENT_STANDARD_RTTIEXT(GeomFill_NSections,GeomFill_SectionLaw) #ifdef OCCT_DEBUG # ifdef DRAW # include #include # endif static Standard_Boolean Affich = 0; static Standard_Integer NbSurf = 0; #endif #ifdef OCCT_DEBUG // verification des fonctions de derivation D1 et D2 par differences finies Standard_Boolean verifD1(const TColgp_Array1OfPnt& P1, const TColStd_Array1OfReal& W1, const TColgp_Array1OfPnt& P2, const TColStd_Array1OfReal& W2, const TColgp_Array1OfVec& DPoles, const TColStd_Array1OfReal& DWeights, const Standard_Real pTol, const Standard_Real wTol, const Standard_Real pas) { Standard_Boolean ok = Standard_True; Standard_Integer ii, L = P1.Length(); Standard_Real dw; gp_Vec dP; for (ii=1; ii<=L; ii++) { dw = (W2(ii)-W1(ii)) / pas; if (Abs(dw-DWeights(ii))>wTol) { if (Affich) { cout<<"erreur dans la derivee 1ere du poids pour l'indice "<pTol) { if (Affich) { cout<<"erreur dans la derivee 1ere du pole pour l'indice "<wTol) { if (Affich) { cout<<"erreur dans la derivee 2nde du poids pour l'indice "<pTol) { if (Affich) { cout<<"erreur dans la derivee 2nde du pole pour l'indice "<IsVRational() ; Standard_Integer gap = 3; if ( rational ) gap++; Standard_Integer Cdeg = surf->VDegree(), Cdim = surf->NbUPoles() * gap, NbP = surf->NbVPoles(); // les noeuds plats Standard_Integer Ksize = NbP + Cdeg + 1; TColStd_Array1OfReal FKnots(1,Ksize); surf->VKnotSequence(FKnots); // les poles Standard_Integer Psize = Cdim * NbP; TColStd_Array1OfReal SPoles(1,Psize); Standard_Integer ii, jj, ipole=1; for (jj=1;jj<=NbP;jj++) { for (ii=1;ii<=surf->NbUPoles();ii++) { SPoles(ipole) = surf->Pole(ii,jj).X(); SPoles(ipole+1) = surf->Pole(ii,jj).Y(); SPoles(ipole+2) = surf->Pole(ii,jj).Z(); if (rational) { SPoles(ipole+3) = surf->Weight(ii,jj); SPoles(ipole) *= SPoles(ipole+3); SPoles(ipole+1) *= SPoles(ipole+3); SPoles(ipole+2) *= SPoles(ipole+3); } ipole+=gap; } } Standard_Real * Padr = (Standard_Real *) &SPoles(1); Standard_Boolean periodic_flag = Standard_False ; Standard_Integer extrap_mode[2]; extrap_mode[0] = extrap_mode[1] = Cdeg; TColStd_Array1OfReal EvalBS(1, Cdim * (deriv+1)) ; Standard_Real * Eadr = (Standard_Real *) &EvalBS(1) ; BSplCLib::Eval(V,periodic_flag,deriv,extrap_mode[0], Cdeg,FKnots,Cdim,*Padr,*Eadr); for (ii=1;ii<=Cdim;ii++) { Result(ii) = EvalBS(ii+deriv*Cdim); } } //======================================================================= //function : GeomFill_NSections //purpose : //======================================================================= GeomFill_NSections::GeomFill_NSections(const TColGeom_SequenceOfCurve& NC) { mySections = NC; UFirst = 0.; ULast = 1.; VFirst = 0.; VLast = 1.; myRefSurf.Nullify(); ComputeSurface(); } //======================================================================= //function : GeomFill_NSections //purpose : //======================================================================= GeomFill_NSections::GeomFill_NSections(const TColGeom_SequenceOfCurve& NC, const TColStd_SequenceOfReal& NP) { mySections = NC; myParams = NP; UFirst = 0.; ULast = 1.; VFirst = 0.; VLast = 1.; myRefSurf.Nullify(); ComputeSurface(); } //======================================================================= //function : GeomFill_NSections //purpose : //======================================================================= GeomFill_NSections::GeomFill_NSections(const TColGeom_SequenceOfCurve& NC, const TColStd_SequenceOfReal& NP, const Standard_Real UF, const Standard_Real UL, const Standard_Real VF, const Standard_Real VL) { mySections = NC; myParams = NP; UFirst = UF; ULast = UL; VFirst = VF; VLast = VL; myRefSurf.Nullify(); ComputeSurface(); } //======================================================================= //function : GeomFill_NSections //purpose : //======================================================================= GeomFill_NSections::GeomFill_NSections(const TColGeom_SequenceOfCurve& NC, const GeomFill_SequenceOfTrsf& Trsfs, const TColStd_SequenceOfReal& NP, const Standard_Real UF, const Standard_Real UL, const Standard_Real VF, const Standard_Real VL, const Handle(Geom_BSplineSurface)& Surf) { mySections = NC; myTrsfs = Trsfs; myParams = NP; UFirst = UF; ULast = UL; VFirst = VF; VLast = VL; myRefSurf = Surf; ComputeSurface(); } //======================================================= // Purpose :D0 //======================================================= Standard_Boolean GeomFill_NSections::D0(const Standard_Real V, TColgp_Array1OfPnt& Poles, TColStd_Array1OfReal& Weights) { if (mySurface.IsNull()) { return Standard_False; } else { Handle(Geom_BSplineCurve) Curve = Handle(Geom_BSplineCurve)::DownCast(mySurface->VIso( V, Standard_False )); TColgp_Array1OfPnt poles(1,mySurface->NbUPoles()); TColStd_Array1OfReal weights(1,mySurface->NbUPoles()); Curve->Poles(poles); Curve->Weights(weights); Standard_Integer ii, L = Poles.Length(); for (ii=1; ii<=L; ii++) { Poles(ii).SetXYZ(poles(ii).XYZ()); Weights(ii) = weights(ii); } } return Standard_True; } //======================================================= // Purpose :D1 //======================================================= Standard_Boolean GeomFill_NSections::D1(const Standard_Real V, TColgp_Array1OfPnt& Poles, TColgp_Array1OfVec& DPoles, TColStd_Array1OfReal& Weights, TColStd_Array1OfReal& DWeights) { if (mySurface.IsNull() ) return Standard_False; Standard_Boolean ok = D0(V,Poles,Weights); if (!ok) return Standard_False; Standard_Integer L = Poles.Length(), derivative_request = 1; Standard_Boolean rational = mySurface->IsVRational() ; Standard_Integer gap = 3; if (rational) gap++; Standard_Integer dimResult = mySurface->NbUPoles() * gap; Handle(Geom_BSplineSurface) surf_deper; if (mySurface->IsVPeriodic()) { surf_deper = Handle(Geom_BSplineSurface)::DownCast(mySurface->Copy()); surf_deper->SetVNotPeriodic(); dimResult = surf_deper->NbUPoles() * gap; } TColStd_Array1OfReal Result(1,dimResult); if (mySurface->IsVPeriodic()) { ResultEval(surf_deper,V,derivative_request,Result); } else { ResultEval(mySurface,V,derivative_request,Result); } Standard_Real ww, EpsW = 10*Precision::PConfusion(); Standard_Boolean NullWeight = Standard_False; if (!rational) DWeights.Init(0.); Standard_Integer indice = 1, ii; // recopie des poles du resultat sous forme de points 3D et de poids for (ii=1; ii<=L && (!NullWeight) ; ii++) { DPoles(ii).SetX( Result(indice) ); DPoles(ii).SetY( Result(indice+1) ); DPoles(ii).SetZ( Result(indice+2) ); if (rational) { ww = Weights(ii); if (ww < EpsW) { NullWeight = Standard_True; } else { DWeights(ii) = Result(indice+3); DPoles(ii) .SetXYZ( ( DPoles(ii).XYZ()-DWeights(ii)*Poles(ii).Coord() ) / ww ); } } indice += gap; } if (NullWeight) return Standard_False; // verif par diff finies sous debug sauf pour les surfaces periodiques #ifdef OCCT_DEBUG if (!mySurface->IsVPeriodic()) { Standard_Real pas = 1.e-6, wTol = 1.e-4, pTol = 1.e-3; Standard_Real V1,V2; Standard_Boolean ok1,ok2; TColStd_Array1OfReal W1(1,L),W2(1,L); TColgp_Array1OfPnt P1(1,L),P2(1,L); gp_Pnt nul(0.,0.,0.); W1.Init(0.); W2.Init(0.); P1.Init(nul); P2.Init(nul); V1 = V; V2 = V+pas; ok1 = D0(V1,P1,W1); ok2 = D0(V2,P2,W2); if (!ok1 || !ok2) cout<<"probleme en D0"<NbUPoles(); NbKnots = mySurface->NbUKnots(); Degree = mySurface->UDegree(); } //======================================================= // Purpose :Knots //======================================================= void GeomFill_NSections::Knots(TColStd_Array1OfReal& TKnots) const { mySurface->UKnots(TKnots); } //======================================================= // Purpose :Mults //======================================================= void GeomFill_NSections::Mults(TColStd_Array1OfInteger& TMults) const { mySurface->UMultiplicities(TMults); } //======================================================= // Purpose :IsRational //======================================================= Standard_Boolean GeomFill_NSections::IsRational() const { return mySurface->IsURational(); } //======================================================= // Purpose :IsUPeriodic //======================================================= Standard_Boolean GeomFill_NSections::IsUPeriodic() const { return mySurface->IsUPeriodic(); } //======================================================= // Purpose :IsVPeriodic //======================================================= Standard_Boolean GeomFill_NSections::IsVPeriodic() const { return mySurface->IsVPeriodic(); } //======================================================= // Purpose :NbIntervals //======================================================= Standard_Integer GeomFill_NSections::NbIntervals(const GeomAbs_Shape S) const { GeomAdaptor_Surface AdS(mySurface); return AdS.NbVIntervals(S); } //======================================================= // Purpose :Intervals //======================================================= void GeomFill_NSections::Intervals(TColStd_Array1OfReal& T, const GeomAbs_Shape S) const { GeomAdaptor_Surface AdS(mySurface); AdS.VIntervals(T,S); } //======================================================= // Purpose : SetInterval //======================================================= // void GeomFill_NSections::SetInterval(const Standard_Real F, void GeomFill_NSections::SetInterval(const Standard_Real , // const Standard_Real L) const Standard_Real ) { // rien a faire : mySurface est supposee Cn en V } //======================================================= // Purpose : GetInterval //======================================================= void GeomFill_NSections::GetInterval(Standard_Real& F, Standard_Real& L) const { F = VFirst; L = VLast; } //======================================================= // Purpose : GetDomain //======================================================= void GeomFill_NSections::GetDomain(Standard_Real& F, Standard_Real& L) const { F = VFirst; L = VLast; } //======================================================= // Purpose : GetTolerance //======================================================= void GeomFill_NSections::GetTolerance(const Standard_Real BoundTol, const Standard_Real SurfTol, // const Standard_Real AngleTol, const Standard_Real , TColStd_Array1OfReal& Tol3d) const { Tol3d.Init(SurfTol); if (BoundTolBounds(U0,U1,V0,V1); Standard_Real V = V0, DeltaV = ( V1 - V0 ) / 20; Standard_Real U = U0, DeltaU = ( U1 - U0 ) / 20; for(jj=0;jj<=20;jj++,V+=DeltaV) { for (ii=0 ; ii <=20; ii++, U+=DeltaU) { P = mySurface->Value(U,V); Bary.ChangeCoord() += P.XYZ(); } } Bary.ChangeCoord() /= (21*21); return Bary; } //======================================================= // Purpose : MaximalSection //======================================================= Standard_Real GeomFill_NSections::MaximalSection() const { Standard_Real L, Lmax=0.; Standard_Integer ii; for (ii=1; ii <=mySections.Length(); ii++) { GeomAdaptor_Curve AC (mySections(ii)); L = GCPnts_AbscissaPoint::Length(AC); if (L>Lmax) Lmax = L; } return Lmax; } //======================================================= // Purpose : GetMinimalWeight //======================================================= void GeomFill_NSections::GetMinimalWeight(TColStd_Array1OfReal& Weights) const { if (mySurface->IsURational()) { Standard_Integer NbU = mySurface->NbUPoles(), NbV = mySurface->NbVPoles(); TColStd_Array2OfReal WSurf(1,NbU,1,NbV); mySurface->Weights(WSurf); Standard_Integer i,j; for (i=1;i<=NbU;i++) { Standard_Real min = WSurf(i,1); for (j=2;j<=NbV;j++) { if (min> WSurf(i,j)) min = WSurf(i,j); } Weights.SetValue(i,min); } } else { Weights.Init(1); } } //======================================================= // Purpose : IsConstant //======================================================= Standard_Boolean GeomFill_NSections::IsConstant(Standard_Real& Error) const { // on se limite a 2 sections Standard_Boolean isconst = (mySections.Length()==2); Standard_Real Err = 0.; if (isconst) { GeomAdaptor_Curve AC1(mySections(1)); GeomAbs_CurveType CType = AC1.GetType(); GeomAdaptor_Curve AC2(mySections(2)); // les sections doivent avoir le meme type isconst = ( AC2.GetType() == CType); if (isconst) { if (CType == GeomAbs_Circle) { gp_Circ C1 = AC1.Circle(); gp_Circ C2 = AC2.Circle(); Standard_Real Tol = 1.e-7; Standard_Boolean samedir, samerad, samepos; samedir = (C1.Axis().IsParallel(C2.Axis(),1.e-4)); samerad = (Abs(C1.Radius()-C2.Radius())Copy()); return C; } //======================================================= // Purpose : IsConicalLaw //======================================================= Standard_Boolean GeomFill_NSections::IsConicalLaw(Standard_Real& Error) const { Standard_Boolean isconic = (mySections.Length()==2); Standard_Real Err = 0.; if (isconic) { GeomAdaptor_Curve AC1(mySections(1)); GeomAdaptor_Curve AC2(mySections(2)); isconic = ( AC1.GetType() == GeomAbs_Circle ) && ( AC2.GetType() == GeomAbs_Circle ) ; if (isconic) { gp_Circ C1 = AC1.Circle(); if (!myTrsfs.IsEmpty()) C1.Transform(myTrsfs(1).Inverted()); gp_Circ C2 = AC2.Circle(); if (!myTrsfs.IsEmpty()) C2.Transform(myTrsfs(2).Inverted()); Standard_Real Tol = 1.e-7; //Standard_Boolean samedir, linearrad, sameaxis; isconic = (C1.Axis().IsParallel(C2.Axis(),1.e-4)); // pour 2 sections, la variation du rayon est forcement lineaire //linearrad = Standard_True; // formule plus generale pour 3 sections au moins // Standard_Real param0 = C2.Radius()*myParams(1) - C1.Radius()*myParams(2); // param0 = param0 / (C2.Radius()-C1.Radius()) ; // linearrad = ( Abs( C3.Radius()*myParams(1)-C1.Radius()*myParams(3) // - param0*(C3.Radius()-C1.Radius()) ) < Tol); if (isconic) { gp_Lin Line1(C1.Axis()); isconic = (Line1.Distance(C2.Location()) < Tol); /* sameaxis = (C1.Location().Distance(C2.Location())