diff --git a/src/ChFi3d/ChFi3d_ChBuilder.cxx b/src/ChFi3d/ChFi3d_ChBuilder.cxx index 09abd3c73c..e50176204f 100644 --- a/src/ChFi3d/ChFi3d_ChBuilder.cxx +++ b/src/ChFi3d/ChFi3d_ChBuilder.cxx @@ -1332,8 +1332,11 @@ Standard_Boolean ChFi3d_ChBuilder::PerformFirstSection Standard_Real tol = tolesp*1.e2; // Standard_Real u,v; - Extrema_GenLocateExtPS proj1(pt1,S1->Surface(),SolDep(1),SolDep(2),tol,tol); - Extrema_GenLocateExtPS proj2(pt2,S2->Surface(),SolDep(3),SolDep(4),tol,tol); + Extrema_GenLocateExtPS proj1(S1->Surface(), tol, tol); + proj1.Perform(pt1, SolDep(1), SolDep(2)); + Extrema_GenLocateExtPS proj2(S2->Surface(), tol, tol); + proj2.Perform(pt2, SolDep(3), SolDep(4)); + if( proj1.IsDone() ){ (proj1.Point()).Parameter(SolDep(1),SolDep(2)); } @@ -1389,8 +1392,12 @@ Standard_Boolean ChFi3d_ChBuilder::PerformFirstSection Standard_Real tol = tolesp*1.e2; // Standard_Real u,v; - Extrema_GenLocateExtPS proj1(pt1,S1->Surface(),SolDep(1),SolDep(2),tol,tol); - Extrema_GenLocateExtPS proj2(pt2,S2->Surface(),SolDep(3),SolDep(4),tol,tol); + + Extrema_GenLocateExtPS proj1(S1->Surface(), tol, tol); + proj1.Perform(pt1, SolDep(1), SolDep(2)); + Extrema_GenLocateExtPS proj2(S2->Surface(), tol, tol); + proj2.Perform(pt2, SolDep(3), SolDep(4)); + if( proj1.IsDone() ){ (proj1.Point()).Parameter(SolDep(1),SolDep(2)); } @@ -1457,8 +1464,10 @@ Standard_Boolean ChFi3d_ChBuilder::PerformFirstSection Standard_Real tol = tolesp*1.e2; // Standard_Real u,v; - Extrema_GenLocateExtPS proj1(pt1,S1->Surface(),SolDep(1),SolDep(2),tol,tol); - Extrema_GenLocateExtPS proj2(pt2,S2->Surface(),SolDep(3),SolDep(4),tol,tol); + Extrema_GenLocateExtPS proj1(S1->Surface(), tol, tol); + proj1.Perform(pt1, SolDep(1), SolDep(2)); + Extrema_GenLocateExtPS proj2(S2->Surface(), tol, tol); + proj2.Perform(pt2, SolDep(3), SolDep(4)); if( proj1.IsDone() ){ (proj1.Point()).Parameter(SolDep(1),SolDep(2)); } @@ -1525,8 +1534,10 @@ Standard_Boolean ChFi3d_ChBuilder::PerformFirstSection Standard_Real tol = tolesp*1.e2; // Standard_Real u,v; - Extrema_GenLocateExtPS proj1(pt1,S2->Surface(),SolDep(1),SolDep(2),tol,tol); - Extrema_GenLocateExtPS proj2(pt2,S1->Surface(),SolDep(3),SolDep(4),tol,tol); + Extrema_GenLocateExtPS proj1(S2->Surface(), tol, tol); + proj1.Perform(pt1, SolDep(1), SolDep(2)); + Extrema_GenLocateExtPS proj2(S1->Surface(), tol, tol); + proj2.Perform(pt2, SolDep(3), SolDep(4)); if( proj1.IsDone() ) { (proj1.Point()).Parameter(SolDep(1),SolDep(2)); } diff --git a/src/Extrema/Extrema_ExtPExtS.hxx b/src/Extrema/Extrema_ExtPExtS.hxx index 426a41c47d..67b50a54f7 100644 --- a/src/Extrema/Extrema_ExtPExtS.hxx +++ b/src/Extrema/Extrema_ExtPExtS.hxx @@ -21,7 +21,7 @@ #include #include -#include +#include #include #include #include @@ -98,7 +98,7 @@ private: Standard_Real myvinf; Standard_Real myvsup; Standard_Real mytolv; - Extrema_FuncExtPS myF; + Extrema_FuncPSNorm myF; Handle(Adaptor3d_HCurve) myC; Handle(GeomAdaptor_HSurfaceOfLinearExtrusion) myS; gp_Vec myDirection; diff --git a/src/Extrema/Extrema_FuncPSDist.cxx b/src/Extrema/Extrema_FuncPSDist.cxx new file mode 100644 index 0000000000..e985785013 --- /dev/null +++ b/src/Extrema/Extrema_FuncPSDist.cxx @@ -0,0 +1,119 @@ +// Created on: 2016-05-10 +// Created by: Alexander MALYSHEV +// Copyright (c) 1995-1999 Matra Datavision +// Copyright (c) 1999-2016 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 + +//======================================================================= +//function : Extrema_FuncPSDist +//purpose : +//======================================================================= +Extrema_FuncPSDist::Extrema_FuncPSDist(const Adaptor3d_Surface& theS, + const gp_Pnt& theP) +: mySurf(theS), + myP(theP) +{ +} + +//======================================================================= +//function : NbVariables +//purpose : +//======================================================================= +Standard_Integer Extrema_FuncPSDist::NbVariables () const +{ + return 2; +} + +//======================================================================= +//function : Value +//purpose : +//======================================================================= +Standard_Boolean Extrema_FuncPSDist::Value(const math_Vector& X,Standard_Real& F) +{ + if (!IsInside(X)) + return Standard_False; + + F = mySurf.Value(X(1), X(2)).SquareDistance(myP); + + return Standard_True; +} + +//======================================================================= +//function : Gradient +//purpose : +//======================================================================= +Standard_Boolean Extrema_FuncPSDist::Gradient(const math_Vector& X,math_Vector& G) + +{ + if (!IsInside(X)) + return Standard_False; + + gp_Pnt aP; + gp_Vec Du1s, Dv1s; + mySurf.D1(X(1),X(2),aP,Du1s,Dv1s); + + gp_Vec P1P2 (aP, myP); + + G(1) = P1P2.Dot(Du1s); + G(2) = P1P2.Dot(Dv1s); + + return Standard_True; +} + +//======================================================================= +//function : Values +//purpose : +//======================================================================= +Standard_Boolean Extrema_FuncPSDist::Values(const math_Vector& X,Standard_Real& F,math_Vector& G) +{ + if (!IsInside(X)) + return Standard_False; + + gp_Pnt aP; + gp_Vec Du1s, Dv1s; + mySurf.D1(X(1),X(2),aP,Du1s,Dv1s); + + gp_Vec P1P2 (aP, myP); + + G(1) = P1P2.Dot(Du1s); + G(2) = P1P2.Dot(Dv1s); + + F = mySurf.Value(X(1), X(2)).SquareDistance(myP); + + return true; +} + +//======================================================================= +//function : IsInside +//purpose : +//======================================================================= +Standard_Boolean Extrema_FuncPSDist::IsInside(const math_Vector& X) +{ + if (X(1) < mySurf.FirstUParameter() || + X(1) > mySurf.LastUParameter() || + X(2) < mySurf.FirstUParameter() || + X(2) > mySurf.LastUParameter() ) + { + // Point out of borders. + return Standard_False; + } + + // Point is inside. + return Standard_True; +} diff --git a/src/Extrema/Extrema_FuncPSDist.hxx b/src/Extrema/Extrema_FuncPSDist.hxx new file mode 100644 index 0000000000..42e9d761ea --- /dev/null +++ b/src/Extrema/Extrema_FuncPSDist.hxx @@ -0,0 +1,82 @@ +// Created on: 2016-05-10 +// Created by: Alexander MALYSHEV +// Copyright (c) 1991-1999 Matra Datavision +// Copyright (c) 1999-2016 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. + +#ifndef _Extrema_FuncPSDsit_HeaderFile +#define _Extrema_FuncPSDsit_HeaderFile + +#include +#include + +#include +#include +#include + +#include +#include +#include + +class math_Vector; + +//! Functional for search of extremum of the square Euclidean distance between point P and +//! surface S, starting from approximate solution (u0, v0). +//! +//! The class inherits math_MultipleVarFunctionWithGradient and thus is intended +//! for use in math_BFGS algorithm. +//! +//! The criteria is: +//! F = SquareDist(P, S(u, v)) - > min +//! +//! The first derivative are: +//! F1(u,v) = (S(u,v) - P) * Su +//! F2(u,v) = (S(u,v) - P) * Sv +//! +//! Su and Sv are first derivatives of the surface, * symbol means dot product. +class Extrema_FuncPSDist : public math_MultipleVarFunctionWithGradient +{ +public: + + DEFINE_STANDARD_ALLOC + + //! Constructor. + Standard_EXPORT Extrema_FuncPSDist(const Adaptor3d_Surface& theS, + const gp_Pnt& theP); + + //! Number of variables. + Standard_EXPORT Standard_Integer NbVariables() const Standard_OVERRIDE; + + //! Value. + Standard_EXPORT Standard_Boolean Value(const math_Vector& X,Standard_Real& F) Standard_OVERRIDE; + + //! Gradient. + Standard_EXPORT Standard_Boolean Gradient(const math_Vector& X,math_Vector& G) Standard_OVERRIDE; + + //! Value and gradient. + Standard_EXPORT Standard_Boolean Values(const math_Vector& X,Standard_Real& F,math_Vector& G) Standard_OVERRIDE; + +private: + + + //! Check point is inside of the surface parameter space. + //! Returns true if inside and false otherwise. + Standard_Boolean IsInside(const math_Vector& X); + + const Extrema_FuncPSDist& operator=(const Extrema_FuncPSDist&); + Extrema_FuncPSDist(const Extrema_FuncPSDist&); + + const Adaptor3d_Surface &mySurf; + const gp_Pnt &myP; +}; +#endif // _Extrema_FuncPSDsit_HeaderFile diff --git a/src/Extrema/Extrema_FuncExtPS.cxx b/src/Extrema/Extrema_FuncPSNorm.cxx similarity index 81% rename from src/Extrema/Extrema_FuncExtPS.cxx rename to src/Extrema/Extrema_FuncPSNorm.cxx index 9700d22daa..06346cc710 100644 --- a/src/Extrema/Extrema_FuncExtPS.cxx +++ b/src/Extrema/Extrema_FuncPSNorm.cxx @@ -14,27 +14,25 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. -// Modified by skv - Thu Sep 30 15:21:07 2004 OCC593 +#include #include -#include #include #include #include #include #include #include -#include #include -Extrema_FuncExtPS::Extrema_FuncExtPS () +Extrema_FuncPSNorm::Extrema_FuncPSNorm () { myPinit = Standard_False; mySinit = Standard_False; } //============================================================================= -Extrema_FuncExtPS::Extrema_FuncExtPS (const gp_Pnt& P, +Extrema_FuncPSNorm::Extrema_FuncPSNorm (const gp_Pnt& P, const Adaptor3d_Surface& S) { myP = P; @@ -44,7 +42,7 @@ Extrema_FuncExtPS::Extrema_FuncExtPS (const gp_Pnt& P, } //============================================================================= -void Extrema_FuncExtPS::Initialize(const Adaptor3d_Surface& S) +void Extrema_FuncPSNorm::Initialize(const Adaptor3d_Surface& S) { myS = (Adaptor3d_SurfacePtr)&S; mySinit = Standard_True; @@ -54,7 +52,7 @@ void Extrema_FuncExtPS::Initialize(const Adaptor3d_Surface& S) //============================================================================= -void Extrema_FuncExtPS::SetPoint(const gp_Pnt& P) +void Extrema_FuncPSNorm::SetPoint(const gp_Pnt& P) { myP = P; myPinit = Standard_True; @@ -66,13 +64,13 @@ void Extrema_FuncExtPS::SetPoint(const gp_Pnt& P) //============================================================================= -Standard_Integer Extrema_FuncExtPS::NbVariables () const { return 2;} +Standard_Integer Extrema_FuncPSNorm::NbVariables () const { return 2;} //============================================================================= -Standard_Integer Extrema_FuncExtPS::NbEquations () const { return 2;} +Standard_Integer Extrema_FuncPSNorm::NbEquations () const { return 2;} //============================================================================= -Standard_Boolean Extrema_FuncExtPS::Value (const math_Vector& UV, +Standard_Boolean Extrema_FuncPSNorm::Value (const math_Vector& UV, math_Vector& F) { if (!myPinit || !mySinit) Standard_TypeMismatch::Raise(); @@ -90,7 +88,7 @@ Standard_Boolean Extrema_FuncExtPS::Value (const math_Vector& UV, } //============================================================================= -Standard_Boolean Extrema_FuncExtPS::Derivatives (const math_Vector& UV, +Standard_Boolean Extrema_FuncPSNorm::Derivatives (const math_Vector& UV, math_Matrix& Df) { math_Vector F(1,2); @@ -98,7 +96,7 @@ Standard_Boolean Extrema_FuncExtPS::Derivatives (const math_Vector& UV, } //============================================================================= -Standard_Boolean Extrema_FuncExtPS::Values (const math_Vector& UV, +Standard_Boolean Extrema_FuncPSNorm::Values (const math_Vector& UV, math_Vector& F, math_Matrix& Df) { @@ -123,7 +121,7 @@ Standard_Boolean Extrema_FuncExtPS::Values (const math_Vector& UV, } //============================================================================= -Standard_Integer Extrema_FuncExtPS::GetStateNumber () +Standard_Integer Extrema_FuncPSNorm::GetStateNumber () { if (!myPinit || !mySinit) Standard_TypeMismatch::Raise(); //comparison of solution with previous solutions @@ -145,20 +143,20 @@ Standard_Integer Extrema_FuncExtPS::GetStateNumber () } //============================================================================= -Standard_Integer Extrema_FuncExtPS::NbExt () const +Standard_Integer Extrema_FuncPSNorm::NbExt () const { return mySqDist.Length(); } //============================================================================= -Standard_Real Extrema_FuncExtPS::SquareDistance (const Standard_Integer N) const +Standard_Real Extrema_FuncPSNorm::SquareDistance (const Standard_Integer N) const { if (!myPinit || !mySinit) Standard_TypeMismatch::Raise(); return mySqDist.Value(N); } //============================================================================= -const Extrema_POnSurf& Extrema_FuncExtPS::Point (const Standard_Integer N) const +const Extrema_POnSurf& Extrema_FuncPSNorm::Point (const Standard_Integer N) const { if (!myPinit || !mySinit) Standard_TypeMismatch::Raise(); return myPoint.Value(N); diff --git a/src/Extrema/Extrema_FuncExtPS.hxx b/src/Extrema/Extrema_FuncPSNorm.hxx similarity index 90% rename from src/Extrema/Extrema_FuncExtPS.hxx rename to src/Extrema/Extrema_FuncPSNorm.hxx index 2dc9213588..275f0f249f 100644 --- a/src/Extrema/Extrema_FuncExtPS.hxx +++ b/src/Extrema/Extrema_FuncPSNorm.hxx @@ -14,12 +14,11 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. -#ifndef _Extrema_FuncExtPS_HeaderFile -#define _Extrema_FuncExtPS_HeaderFile +#ifndef _Extrema_FunctPSNorm_HeaderFile +#define _Extrema_FunctPSNorm_HeaderFile #include #include -#include #include #include @@ -58,16 +57,16 @@ class Extrema_POnSurf; //! Dvf2(u,v) = Sv^2 + (S-P) * Svv //! //! Here * denotes scalar product, and ^2 is square power. -class Extrema_FuncExtPS : public math_FunctionSetWithDerivatives +class Extrema_FuncPSNorm : public math_FunctionSetWithDerivatives { public: DEFINE_STANDARD_ALLOC - Standard_EXPORT Extrema_FuncExtPS(); + Standard_EXPORT Extrema_FuncPSNorm(); - Standard_EXPORT Extrema_FuncExtPS(const gp_Pnt& P, const Adaptor3d_Surface& S); + Standard_EXPORT Extrema_FuncPSNorm(const gp_Pnt& P, const Adaptor3d_Surface& S); //! sets the field mysurf of the function. Standard_EXPORT void Initialize (const Adaptor3d_Surface& S); @@ -100,19 +99,8 @@ public: //! Returns the Nth extremum. Standard_EXPORT const Extrema_POnSurf& Point (const Standard_Integer N) const; - - - -protected: - - - - - private: - - gp_Pnt myP; Adaptor3d_SurfacePtr myS; Standard_Real myU; @@ -122,14 +110,5 @@ private: Extrema_SequenceOfPOnSurf myPoint; Standard_Boolean myPinit; Standard_Boolean mySinit; - - }; - - - - - - - -#endif // _Extrema_FuncExtPS_HeaderFile +#endif // _Extrema_FunctPSNorm_HeaderFile diff --git a/src/Extrema/Extrema_GenExtPS.hxx b/src/Extrema/Extrema_GenExtPS.hxx index 31e0b78749..3ad87ef279 100644 --- a/src/Extrema/Extrema_GenExtPS.hxx +++ b/src/Extrema/Extrema_GenExtPS.hxx @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include @@ -148,7 +148,7 @@ private: Handle(Extrema_HArray2OfPOnSurfParams) myPoints; Extrema_HUBTreeOfSphere mySphereUBTree; Handle(Bnd_HArray1OfSphere) mySphereArray; - Extrema_FuncExtPS myF; + Extrema_FuncPSNorm myF; Adaptor3d_SurfacePtr myS; Extrema_ExtFlag myFlag; Extrema_ExtAlgo myAlgo; diff --git a/src/Extrema/Extrema_GenLocateExtPS.cxx b/src/Extrema/Extrema_GenLocateExtPS.cxx index 17b1468eef..b48ef0b1da 100644 --- a/src/Extrema/Extrema_GenLocateExtPS.cxx +++ b/src/Extrema/Extrema_GenLocateExtPS.cxx @@ -15,94 +15,117 @@ // commercial license or contractual agreement. -#include -#include #include + +#include +#include +#include #include -#include #include #include -#include +#include #include -#include #include -//============================================================================= -Extrema_GenLocateExtPS::Extrema_GenLocateExtPS () { myDone = Standard_False; } -//============================================================================= +//======================================================================= +//function : Extrema_GenLocateExtPS +//purpose : +//======================================================================= +Extrema_GenLocateExtPS::Extrema_GenLocateExtPS(const Adaptor3d_Surface& theS, + const Standard_Real theTolU, + const Standard_Real theTolV) +: mySurf(theS), + myTolU(theTolU), myTolV(theTolV), + myDone(Standard_False), + mySqDist(-1.0) +{ +} -Extrema_GenLocateExtPS::Extrema_GenLocateExtPS (const gp_Pnt& P, - const Adaptor3d_Surface& S, - const Standard_Real U0, - const Standard_Real V0, - const Standard_Real TolU, - const Standard_Real TolV) -/*----------------------------------------------------------------------------- -Function: - Find (U,V) close to (U0,V0) so that dist(S(U,V),P) was extreme. - -Method: - If (u,v) is a solution, it is possible to write: - { F1(u,v) = (S(u,v)-P).dS/du(u,v) = 0. - { F2(u,v) = (S(u,v)-P).dS/dv(u,v) = 0. - The problem consists in finding, in the interval of surface definition, - the root of the system closest to (U0,V0). - Use class math_FunctionSetRoot with the following construction arguments: - - F: Extrema_FuncExtPS created from P and S, - - U0V0: math_Vector (U0,V0), - - Tol: Min(TolU,TolV), - - - math_Vector (Uinf,Usup), - - math_Vector (Vinf,Vsup), - - 100. . ----------------------------------------------------------------------------*/ +//======================================================================= +//function : Perform +//purpose : +//======================================================================= +void Extrema_GenLocateExtPS::Perform(const gp_Pnt& theP, + const Standard_Real theU0, + const Standard_Real theV0, + const Standard_Boolean isDistanceCriteria) { myDone = Standard_False; - Standard_Real Uinf, Usup, Vinf, Vsup; - Uinf = S.FirstUParameter(); - Usup = S.LastUParameter(); - Vinf = S.FirstVParameter(); - Vsup = S.LastVParameter(); + // Prepare initial data structures. + math_Vector aTol(1, 2), aStart(1, 2), aBoundInf(1, 2), aBoundSup(1, 2); - Extrema_FuncExtPS F (P,S); - math_Vector Tol(1, 2), Start(1, 2), BInf(1, 2), BSup(1, 2); + // Tolerance. + aTol(1) = myTolU; + aTol(2) = myTolV; - Tol(1) = TolU; - Tol(2) = TolV; + // Initial solution approximation. + aStart(1) = theU0; + aStart(2) = theV0; - Start(1) = U0; - Start(2) = V0; + // Borders. + aBoundInf(1) = mySurf.FirstUParameter(); + aBoundInf(2) = mySurf.FirstVParameter(); + aBoundSup(1) = mySurf.LastUParameter(); + aBoundSup(2) = mySurf.LastVParameter(); - BInf(1) = Uinf; - BInf(2) = Vinf; - BSup(1) = Usup; - BSup(2) = Vsup; + if (isDistanceCriteria == Standard_False) + { + // Normal projection criteria. + Extrema_FuncPSNorm F(theP,mySurf); - math_FunctionSetRoot SR (F, Tol); - SR.Perform(F, Start, BInf, BSup); - if (!SR.IsDone()) - return; + math_FunctionSetRoot SR (F, aTol); + SR.Perform(F, aStart, aBoundInf, aBoundSup); + if (!SR.IsDone()) + return; - mySqDist = F.SquareDistance(1); - myPoint = F.Point(1); - myDone = Standard_True; + mySqDist = F.SquareDistance(1); + myPoint = F.Point(1); + myDone = Standard_True; + } + else + { + // Distance criteria. + Extrema_FuncPSDist F(mySurf, theP); + math_BFGS aSolver(2); + aSolver.Perform(F, aStart); + + if (!aSolver.IsDone()) + return; + + math_Vector aResPnt(1,2); + aSolver.Location(aResPnt); + mySqDist = aSolver.Minimum(); + myPoint.SetParameters(aResPnt(1), aResPnt(2), mySurf.Value(aResPnt(1), aResPnt(2))); + myDone = Standard_True; + } } -//============================================================================= -Standard_Boolean Extrema_GenLocateExtPS::IsDone () const { return myDone; } -//============================================================================= +//======================================================================= +//function : IsDone +//purpose : +//======================================================================= +Standard_Boolean Extrema_GenLocateExtPS::IsDone () const +{ + return myDone; +} +//======================================================================= +//function : SquareDistance +//purpose : +//======================================================================= Standard_Real Extrema_GenLocateExtPS::SquareDistance () const { if (!IsDone()) { StdFail_NotDone::Raise(); } return mySqDist; } -//============================================================================= +//======================================================================= +//function : Point +//purpose : +//======================================================================= const Extrema_POnSurf& Extrema_GenLocateExtPS::Point () const { if (!IsDone()) { StdFail_NotDone::Raise(); } return myPoint; } -//============================================================================= diff --git a/src/Extrema/Extrema_GenLocateExtPS.hxx b/src/Extrema/Extrema_GenLocateExtPS.hxx index 3245d6982f..07f0e5d343 100644 --- a/src/Extrema/Extrema_GenLocateExtPS.hxx +++ b/src/Extrema/Extrema_GenLocateExtPS.hxx @@ -19,7 +19,6 @@ #include #include -#include #include #include @@ -33,23 +32,27 @@ class Extrema_POnSurf; //! With a close point, it calculates the distance //! between a point and a surface. -//! This distance can be a minimum or a maximum. +//! Criteria type is defined in "Perform" method. class Extrema_GenLocateExtPS { public: DEFINE_STANDARD_ALLOC + //! Constructor. + Standard_EXPORT Extrema_GenLocateExtPS(const Adaptor3d_Surface& theS, + const Standard_Real theTolU = Precision::PConfusion(), + const Standard_Real theTolV = Precision::PConfusion()); - Standard_EXPORT Extrema_GenLocateExtPS(); - - //! Calculates the distance with a close point. - //! The close point is defined by the parameter values - //! U0 and V0. - //! The function F(u,v)=distance(S(u,v),p) has an - //! extremun when gradient(F)=0. The algorithm searchs - //! a zero near the close point. - Standard_EXPORT Extrema_GenLocateExtPS(const gp_Pnt& P, const Adaptor3d_Surface& S, const Standard_Real U0, const Standard_Real V0, const Standard_Real TolU, const Standard_Real TolV); + //! Calculates the extrema between the point and the surface using a close point. + //! The close point is defined by the parameter values theU0 and theV0. + //! Type of the algorithm depends on the isDistanceCriteria flag. + //! If flag value is false - normal projection criteria will be used. + //! If flag value is true - distance criteria will be used. + Standard_EXPORT void Perform(const gp_Pnt& theP, + const Standard_Real theU0, + const Standard_Real theV0, + const Standard_Boolean isDistanceCriteria = Standard_False); //! Returns True if the distance is found. Standard_EXPORT Standard_Boolean IsDone() const; @@ -60,20 +63,19 @@ public: //! Returns the point of the extremum distance. Standard_EXPORT const Extrema_POnSurf& Point() const; - - - -protected: - - - - - private: + const Extrema_GenLocateExtPS& operator=(const Extrema_GenLocateExtPS&); + Extrema_GenLocateExtPS(const Extrema_GenLocateExtPS&); + // Input. + const Adaptor3d_Surface& mySurf; + Standard_Real myTolU, myTolV; + // State. Standard_Boolean myDone; + + // Result. Standard_Real mySqDist; Extrema_POnSurf myPoint; diff --git a/src/Extrema/FILES b/src/Extrema/FILES index 33f2e0b3b4..3be6cd0ad4 100644 --- a/src/Extrema/FILES +++ b/src/Extrema/FILES @@ -72,8 +72,10 @@ Extrema_FuncExtCC.lxx Extrema_FuncExtCS.cxx Extrema_FuncExtCS.hxx Extrema_FuncExtPC.gxx -Extrema_FuncExtPS.cxx -Extrema_FuncExtPS.hxx +Extrema_FuncPSNorm.cxx +Extrema_FuncPSNorm.hxx +Extrema_FuncPSDist.cxx +Extrema_FuncPSDist.hxx Extrema_FuncExtSS.cxx Extrema_FuncExtSS.hxx Extrema_GenExtCC.gxx diff --git a/src/IntPatch/IntPatch_ImpPrmIntersection.cxx b/src/IntPatch/IntPatch_ImpPrmIntersection.cxx index 187ecc246e..3a9982d308 100644 --- a/src/IntPatch/IntPatch_ImpPrmIntersection.cxx +++ b/src/IntPatch/IntPatch_ImpPrmIntersection.cxx @@ -2782,9 +2782,8 @@ static Standard_Boolean DecomposeResult(const Handle(IntPatch_PointLine)& theLin theQSurf->D0(aUquad, aVquad, aPQuad); - Extrema_GenLocateExtPS anExtr(aPQuad, thePSurf->Surface(), aU0, aV0, - Precision::PConfusion(), - Precision::PConfusion()); + Extrema_GenLocateExtPS anExtr(thePSurf->Surface()); + anExtr.Perform(aPQuad, aU0, aV0); if(!anExtr.IsDone()) { @@ -2946,9 +2945,8 @@ static Standard_Boolean DecomposeResult(const Handle(IntPatch_PointLine)& theLin theQSurf->D0(aUquad, aVquad, aPQuad); - Extrema_GenLocateExtPS anExtr(aPQuad, thePSurf->Surface(), aU0, aV0, - Precision::PConfusion(), - Precision::PConfusion()); + Extrema_GenLocateExtPS anExtr(thePSurf->Surface()); + anExtr.Perform(aPQuad, aU0, aV0); if(!anExtr.IsDone()) { diff --git a/src/IntTools/IntTools_BeanFaceIntersector.cxx b/src/IntTools/IntTools_BeanFaceIntersector.cxx index bc879f520f..395b715904 100644 --- a/src/IntTools/IntTools_BeanFaceIntersector.cxx +++ b/src/IntTools/IntTools_BeanFaceIntersector.cxx @@ -1312,8 +1312,9 @@ void IntTools_BeanFaceIntersector::ComputeRangeFromStartPoint(const Standard_Boo // gp_Pnt aPoint = myCurve.Value(aCurPar); - Extrema_GenLocateExtPS anExtrema(aPoint, mySurface, U, V, 1.e-10, 1.e-10); - + Extrema_GenLocateExtPS anExtrema(mySurface, 1.e-10, 1.e-10); + anExtrema.Perform(aPoint, U, V); + if(anExtrema.IsDone()) { if(anExtrema.SquareDistance() < myCriteria * myCriteria) { Extrema_POnSurf aPOnSurf = anExtrema.Point(); diff --git a/src/IntWalk/IntWalk_PWalking.cxx b/src/IntWalk/IntWalk_PWalking.cxx index aa0c4921d3..bf57d64875 100644 --- a/src/IntWalk/IntWalk_PWalking.cxx +++ b/src/IntWalk/IntWalk_PWalking.cxx @@ -617,8 +617,9 @@ static Standard_Real SQDistPointSurface(const gp_Pnt &thePnt, const Standard_Real theU0, const Standard_Real theV0) { - const Extrema_GenLocateExtPS aExtPS(thePnt, theSurf, theU0, theV0, - Precision::PConfusion(), Precision::PConfusion()); + Extrema_GenLocateExtPS aExtPS(theSurf); + aExtPS.Perform(thePnt, theU0, theV0); + if(!aExtPS.IsDone()) return RealLast(); diff --git a/src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.cxx b/src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.cxx index 57cc349802..4b410a518d 100644 --- a/src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.cxx +++ b/src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.cxx @@ -367,7 +367,8 @@ static gp_Pnt2d Function_Value(const Standard_Real theU, } // Try to run simple search with initial point (U0, V0). - Extrema_GenLocateExtPS locext(p, SurfLittle, U0, V0, theData.myTolU, theData.myTolV); + Extrema_GenLocateExtPS locext(SurfLittle, theData.myTolU, theData.myTolV); + locext.Perform(p, U0, V0); if (locext.IsDone()) { locext.Point().Parameter(u, v); @@ -1218,9 +1219,9 @@ Handle(Adaptor2d_HCurve2d) myProjIsDone = Standard_False; Dist2Min = RealLast(); Curve->D0(Param.Value(i), pntproj); - Extrema_GenLocateExtPS aLocateExtPS - (pntproj, Surf->Surface(), U0, V0, TolU, TolV) ; - + Extrema_GenLocateExtPS aLocateExtPS(Surf->Surface(), TolU, TolV); + aLocateExtPS.Perform(pntproj, U0, V0); + if (aLocateExtPS.IsDone()) { if (aLocateExtPS.SquareDistance() < DistTol3d * DistTol3d) @@ -1315,9 +1316,10 @@ Handle(Adaptor2d_HCurve2d) Uaux = 2*aUinf - U0 + uperiod; else Uaux = 2*aUsup - U0 - uperiod; - Extrema_GenLocateExtPS locext(pntproj, - Surf->Surface(), - Uaux, V0, TolU, TolV); + + Extrema_GenLocateExtPS locext(Surf->Surface(), TolU, TolV); + locext.Perform(pntproj, Uaux, V0); + if (locext.IsDone()) if (locext.SquareDistance() < DistTol3d * DistTol3d) { //OCC217 //if (locext.SquareDistance() < Tol3d * Tol3d) { @@ -1341,9 +1343,10 @@ Handle(Adaptor2d_HCurve2d) Vaux = 2*aVinf - V0 + vperiod; else Vaux = 2*aVsup - V0 - vperiod; - Extrema_GenLocateExtPS locext(pntproj, - Surf->Surface(), - U0, Vaux, TolU, TolV) ; + + Extrema_GenLocateExtPS locext(Surf->Surface(), TolU, TolV); + locext.Perform(pntproj, U0, Vaux); + if (locext.IsDone()) if (locext.SquareDistance() < DistTol3d * DistTol3d) { //OCC217 //if (locext.SquareDistance() < Tol3d * Tol3d) { @@ -1369,9 +1372,10 @@ Handle(Adaptor2d_HCurve2d) Vaux = 2*Vinf - V0 + vperiod; else Vaux = 2*Vsup - V0 - vperiod; - Extrema_GenLocateExtPS locext(pntproj, - Surf->Surface(), - Uaux, Vaux, TolU, TolV); + + Extrema_GenLocateExtPS locext(Surf->Surface(), TolU, TolV); + locext.Perform(pntproj, Uaux, Vaux); + if (locext.IsDone()) if (locext.SquareDistance() < DistTol3d * DistTol3d) { //if (locext.SquareDistance() < Tol3d * Tol3d) { @@ -1584,8 +1588,10 @@ Handle(Geom2d_BSplineCurve) for(i = 1;i <= Curve->NbPoles();i++) { myProjIsDone = Standard_False; Dist2Min = IntegerLast(); - Extrema_GenLocateExtPS extrloc(BSC->Pole(i),Surf->Surface(),(p11.X()+p22.X())/2, - (p11.Y()+p22.Y())/2,TolU,TolV) ; + + Extrema_GenLocateExtPS extrloc(Surf->Surface(), TolU, TolV); + extrloc.Perform(BSC->Pole(i), (p11.X()+p22.X())/2, (p11.Y()+p22.Y())/2); + if (extrloc.IsDone()) { Dist2Min = (Standard_Integer ) extrloc.SquareDistance(); if (Dist2Min < DistTol3d * DistTol3d) { //OCC217 @@ -1622,8 +1628,10 @@ Handle(Geom2d_BSplineCurve) TColgp_Array1OfPnt2d Poles2d(1,Curve->NbPoles()); for(i = 1;i <= Curve->NbPoles();i++) { Dist2Min = IntegerLast(); - Extrema_GenLocateExtPS extrloc(BC->Pole(i),Surf->Surface(),0.5, - 0.5,TolU,TolV) ; + + Extrema_GenLocateExtPS extrloc(Surf->Surface(), TolU, TolV); + extrloc.Perform(BC->Pole(i), 0.5, 0.5); + if (extrloc.IsDone()) { Dist2Min = (Standard_Integer ) extrloc.SquareDistance(); if (Dist2Min < DistTol3d * DistTol3d) { //OCC217 @@ -1685,8 +1693,10 @@ Handle(Geom2d_BSplineCurve) for(i = 1;i <= Curve->NbPoles();i++) { myProjIsDone = Standard_False; Dist2Min = IntegerLast(); - Extrema_GenLocateExtPS extrloc(BSC->Pole(i),Surf->Surface(),(p11.X()+p22.X())/2, - (p11.Y()+p22.Y())/2,TolU,TolV) ; + + Extrema_GenLocateExtPS extrloc(Surf->Surface(), TolU, TolV); + extrloc.Perform(BSC->Pole(i), (p11.X()+p22.X())/2, (p11.Y()+p22.Y())/2); + if (extrloc.IsDone()) { Dist2Min = (Standard_Integer ) extrloc.SquareDistance(); if (Dist2Min < DistTol3d * DistTol3d) { //OCC217 @@ -1723,8 +1733,10 @@ Handle(Geom2d_BSplineCurve) TColgp_Array1OfPnt2d Poles2d(1,Curve->NbPoles()); for(i = 1;i <= Curve->NbPoles();i++) { Dist2Min = IntegerLast(); - Extrema_GenLocateExtPS extrloc(BC->Pole(i),Surf->Surface(),0.5, - 0.5,TolU,TolV) ; + + Extrema_GenLocateExtPS extrloc(Surf->Surface(), TolU, TolV); + extrloc.Perform(BC->Pole(i), 0.5, 0.5); + if (extrloc.IsDone()) { Dist2Min = (Standard_Integer ) extrloc.SquareDistance(); if (Dist2Min < DistTol3d * DistTol3d) { //OCC217 diff --git a/src/QABugs/QABugs_19.cxx b/src/QABugs/QABugs_19.cxx index 7bc686dfd5..a988e5c4ee 100644 --- a/src/QABugs/QABugs_19.cxx +++ b/src/QABugs/QABugs_19.cxx @@ -1364,7 +1364,7 @@ static Standard_Integer OCC24945 (Draw_Interpretor& di, Standard_Integer argc, c return 0; } -#include +#include #include #include #include @@ -1401,7 +1401,7 @@ static Standard_Integer OCC24137 (Draw_Interpretor& theDI, Standard_Integer theN gp_Pnt aPnt = BRep_Tool::Pnt (aVert), aRes; - Extrema_FuncExtPS anExtFunc; + Extrema_FuncPSNorm anExtFunc; math_FunctionSetRoot aRoot (anExtFunc, aNbIts); math_Vector aTolUV (1, 2), aUVinf (1, 2), aUVsup (1, 2), aFromUV (1, 2); diff --git a/src/QABugs/QABugs_20.cxx b/src/QABugs/QABugs_20.cxx index d4e48122d3..15e795787b 100644 --- a/src/QABugs/QABugs_20.cxx +++ b/src/QABugs/QABugs_20.cxx @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -36,6 +37,7 @@ #include #include #include +#include #include #include @@ -1571,6 +1573,55 @@ static Standard_Integer OCC26930(Draw_Interpretor& theDI, return 0; } +//======================================================================= +//function : OCC27466 +//purpose : +//======================================================================= +static Standard_Integer OCC27466(Draw_Interpretor& theDI, + Standard_Integer theNArg, + const char ** theArgVal) +{ + if (theNArg != 4) + { + cout << "Use: " << theArgVal[0] << " face point start_pnt2d" << endl; + return 1; + } + + TopoDS_Face aFace = TopoDS::Face(DBRep::Get(theArgVal[1], TopAbs_FACE, Standard_True)); + if (aFace.IsNull()) + return 1; + gp_Pnt aPnt; + if (!DrawTrSurf::GetPoint(theArgVal[2], aPnt)) + return 1; + gp_Pnt2d aUV; + if (!DrawTrSurf::GetPoint2d(theArgVal[3], aUV)) + return 1; + BRepAdaptor_Surface aSurf(aFace); + + Standard_Real aTolU = Precision::PConfusion(); + Standard_Real aTolV = Precision::PConfusion(); + + Extrema_GenLocateExtPS anExtrema(aSurf, aTolU, aTolV); + anExtrema.Perform(aPnt, aUV.X(), aUV.Y(), Standard_True); + + if (!anExtrema.IsDone()) + { + theDI << "Error: Extrema is not done"; + } + else + { + Standard_Real aSqDist = anExtrema.SquareDistance(); + gp_Pnt aResPnt = anExtrema.Point().Value(); + Standard_Real u, v; + anExtrema.Point().Parameter(u, v); + gp_Pnt2d aResUV(u, v); + DrawTrSurf::Set((TCollection_AsciiString(theArgVal[2]) + "_res").ToCString(), aResPnt); + DrawTrSurf::Set((TCollection_AsciiString(theArgVal[3]) + "_res").ToCString(), aResUV); + theDI << theArgVal[2] << "_res and " << theArgVal[3] << "_res are created, dist=" << sqrt(aSqDist); + } + return 0; +} + void QABugs::Commands_20(Draw_Interpretor& theCommands) { const char *group = "QABugs"; @@ -1579,6 +1630,7 @@ void QABugs::Commands_20(Draw_Interpretor& theCommands) { theCommands.Add("OCC27021", "OCC27021", __FILE__, OCC27021, group); theCommands.Add("OCC27235", "OCC27235", __FILE__, OCC27235, group); theCommands.Add("OCC26930", "OCC26930", __FILE__, OCC26930, group); + theCommands.Add("OCC27466", "OCC27466", __FILE__, OCC27466, group); return; } diff --git a/tests/bugs/moddata_3/bug27466 b/tests/bugs/moddata_3/bug27466 new file mode 100644 index 0000000000..3a784179bf --- /dev/null +++ b/tests/bugs/moddata_3/bug27466 @@ -0,0 +1,25 @@ +puts "================" +puts "OCC27466: " +puts "================" +puts "" +#################### +## The algorithm Extrema_GenLocateExtPS gives incorrect result +#################### + +pload QAcommands + +restore [locate_data_file bug27466.brep] a + +point pnt -5.909487750466874e-006 -0.1557578329355927 0.1298542821722014 +point uv0 0.748729882974883 0.5000000063028793 + +set out [OCC27466 a pnt uv0] +if [regexp {dist=([0-9.+-e]*)} $out dummy dist] { + if {$dist > 1e-7} { + puts "Error: distance of projection is too large ($dist)" + } else { + puts "Test passed" + } +} else { + puts "Error: projection failure" +}