1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-09 13:22:24 +03:00

0027466: The algorithm Extrema_GenLocateExtPS gives incorrect result

Euclidean distance criteria is added for local point / surface extrema.
Classes representing objective criteria are renamed to be consistent.
Local extrema usage is updated according to new behavior.
Test case is added.

Misprint correction.
This commit is contained in:
msv
2016-05-04 19:18:12 +03:00
committed by bugmaster
parent e1c1b6b9f4
commit e5260e1dfa
17 changed files with 475 additions and 170 deletions

View File

@@ -21,7 +21,7 @@
#include <Standard_Type.hxx>
#include <Standard_Real.hxx>
#include <Extrema_FuncExtPS.hxx>
#include <Extrema_FuncPSNorm.hxx>
#include <gp_Vec.hxx>
#include <gp_Ax2.hxx>
#include <Extrema_GenExtPS.hxx>
@@ -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;

View File

@@ -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 <Extrema_FuncPSDist.hxx>
#include <gp_Pnt.hxx>
#include <gp_Vec.hxx>
#include <math_Vector.hxx>
//=======================================================================
//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;
}

View File

@@ -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 <Standard.hxx>
#include <Standard_DefineAlloc.hxx>
#include <math_MultipleVarFunctionWithGradient.hxx>
#include <gp_Pnt.hxx>
#include <Adaptor3d_Surface.hxx>
#include <Standard_Real.hxx>
#include <Standard_Boolean.hxx>
#include <Standard_Integer.hxx>
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

View File

@@ -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 <Extrema_FuncPSNorm.hxx>
#include <Adaptor3d_Surface.hxx>
#include <Extrema_FuncExtPS.hxx>
#include <Extrema_POnSurf.hxx>
#include <GeomAbs_IsoType.hxx>
#include <gp_Pnt.hxx>
#include <gp_Vec.hxx>
#include <math_Matrix.hxx>
#include <Precision.hxx>
#include <Standard_OutOfRange.hxx>
#include <Standard_TypeMismatch.hxx>
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);

View File

@@ -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 <Standard.hxx>
#include <Standard_DefineAlloc.hxx>
#include <Standard_Handle.hxx>
#include <gp_Pnt.hxx>
#include <Adaptor3d_SurfacePtr.hxx>
@@ -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

View File

@@ -27,7 +27,7 @@
#include <Extrema_HArray2OfPOnSurfParams.hxx>
#include <Extrema_HUBTreeOfSphere.hxx>
#include <Bnd_HArray1OfSphere.hxx>
#include <Extrema_FuncExtPS.hxx>
#include <Extrema_FuncPSNorm.hxx>
#include <Adaptor3d_SurfacePtr.hxx>
#include <Extrema_ExtFlag.hxx>
#include <Extrema_ExtAlgo.hxx>
@@ -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;

View File

@@ -15,94 +15,117 @@
// commercial license or contractual agreement.
#include <Adaptor3d_Surface.hxx>
#include <Extrema_FuncExtPS.hxx>
#include <Extrema_GenLocateExtPS.hxx>
#include <Adaptor3d_Surface.hxx>
#include <Extrema_FuncPSNorm.hxx>
#include <Extrema_FuncPSDist.hxx>
#include <Extrema_POnSurf.hxx>
#include <gp.hxx>
#include <gp_Pnt.hxx>
#include <math_FunctionSetRoot.hxx>
#include <math_NewtonFunctionSetRoot.hxx>
#include <math_BFGS.hxx>
#include <math_Vector.hxx>
#include <Standard_DomainError.hxx>
#include <StdFail_NotDone.hxx>
//=============================================================================
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;
}
//=============================================================================

View File

@@ -19,7 +19,6 @@
#include <Standard.hxx>
#include <Standard_DefineAlloc.hxx>
#include <Standard_Handle.hxx>
#include <Standard_Boolean.hxx>
#include <Standard_Real.hxx>
@@ -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;

View File

@@ -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