1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-16 10:08:36 +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

@ -1332,8 +1332,11 @@ Standard_Boolean ChFi3d_ChBuilder::PerformFirstSection
Standard_Real tol = tolesp*1.e2; Standard_Real tol = tolesp*1.e2;
// Standard_Real u,v; // Standard_Real u,v;
Extrema_GenLocateExtPS proj1(pt1,S1->Surface(),SolDep(1),SolDep(2),tol,tol); Extrema_GenLocateExtPS proj1(S1->Surface(), tol, tol);
Extrema_GenLocateExtPS proj2(pt2,S2->Surface(),SolDep(3),SolDep(4),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() ){ if( proj1.IsDone() ){
(proj1.Point()).Parameter(SolDep(1),SolDep(2)); (proj1.Point()).Parameter(SolDep(1),SolDep(2));
} }
@ -1389,8 +1392,12 @@ Standard_Boolean ChFi3d_ChBuilder::PerformFirstSection
Standard_Real tol = tolesp*1.e2; Standard_Real tol = tolesp*1.e2;
// Standard_Real u,v; // 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() ){ if( proj1.IsDone() ){
(proj1.Point()).Parameter(SolDep(1),SolDep(2)); (proj1.Point()).Parameter(SolDep(1),SolDep(2));
} }
@ -1457,8 +1464,10 @@ Standard_Boolean ChFi3d_ChBuilder::PerformFirstSection
Standard_Real tol = tolesp*1.e2; Standard_Real tol = tolesp*1.e2;
// Standard_Real u,v; // Standard_Real u,v;
Extrema_GenLocateExtPS proj1(pt1,S1->Surface(),SolDep(1),SolDep(2),tol,tol); Extrema_GenLocateExtPS proj1(S1->Surface(), tol, tol);
Extrema_GenLocateExtPS proj2(pt2,S2->Surface(),SolDep(3),SolDep(4),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() ){ if( proj1.IsDone() ){
(proj1.Point()).Parameter(SolDep(1),SolDep(2)); (proj1.Point()).Parameter(SolDep(1),SolDep(2));
} }
@ -1525,8 +1534,10 @@ Standard_Boolean ChFi3d_ChBuilder::PerformFirstSection
Standard_Real tol = tolesp*1.e2; Standard_Real tol = tolesp*1.e2;
// Standard_Real u,v; // Standard_Real u,v;
Extrema_GenLocateExtPS proj1(pt1,S2->Surface(),SolDep(1),SolDep(2),tol,tol); Extrema_GenLocateExtPS proj1(S2->Surface(), tol, tol);
Extrema_GenLocateExtPS proj2(pt2,S1->Surface(),SolDep(3),SolDep(4),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() ) { if( proj1.IsDone() ) {
(proj1.Point()).Parameter(SolDep(1),SolDep(2)); (proj1.Point()).Parameter(SolDep(1),SolDep(2));
} }

View File

@ -21,7 +21,7 @@
#include <Standard_Type.hxx> #include <Standard_Type.hxx>
#include <Standard_Real.hxx> #include <Standard_Real.hxx>
#include <Extrema_FuncExtPS.hxx> #include <Extrema_FuncPSNorm.hxx>
#include <gp_Vec.hxx> #include <gp_Vec.hxx>
#include <gp_Ax2.hxx> #include <gp_Ax2.hxx>
#include <Extrema_GenExtPS.hxx> #include <Extrema_GenExtPS.hxx>
@ -98,7 +98,7 @@ private:
Standard_Real myvinf; Standard_Real myvinf;
Standard_Real myvsup; Standard_Real myvsup;
Standard_Real mytolv; Standard_Real mytolv;
Extrema_FuncExtPS myF; Extrema_FuncPSNorm myF;
Handle(Adaptor3d_HCurve) myC; Handle(Adaptor3d_HCurve) myC;
Handle(GeomAdaptor_HSurfaceOfLinearExtrusion) myS; Handle(GeomAdaptor_HSurfaceOfLinearExtrusion) myS;
gp_Vec myDirection; 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 // Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement. // 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 <Adaptor3d_Surface.hxx>
#include <Extrema_FuncExtPS.hxx>
#include <Extrema_POnSurf.hxx> #include <Extrema_POnSurf.hxx>
#include <GeomAbs_IsoType.hxx> #include <GeomAbs_IsoType.hxx>
#include <gp_Pnt.hxx> #include <gp_Pnt.hxx>
#include <gp_Vec.hxx> #include <gp_Vec.hxx>
#include <math_Matrix.hxx> #include <math_Matrix.hxx>
#include <Precision.hxx> #include <Precision.hxx>
#include <Standard_OutOfRange.hxx>
#include <Standard_TypeMismatch.hxx> #include <Standard_TypeMismatch.hxx>
Extrema_FuncExtPS::Extrema_FuncExtPS () Extrema_FuncPSNorm::Extrema_FuncPSNorm ()
{ {
myPinit = Standard_False; myPinit = Standard_False;
mySinit = 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) const Adaptor3d_Surface& S)
{ {
myP = P; 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; myS = (Adaptor3d_SurfacePtr)&S;
mySinit = Standard_True; 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; myP = P;
myPinit = Standard_True; 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) math_Vector& F)
{ {
if (!myPinit || !mySinit) Standard_TypeMismatch::Raise(); 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_Matrix& Df)
{ {
math_Vector F(1,2); 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_Vector& F,
math_Matrix& Df) 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(); if (!myPinit || !mySinit) Standard_TypeMismatch::Raise();
//comparison of solution with previous solutions //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(); 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(); if (!myPinit || !mySinit) Standard_TypeMismatch::Raise();
return mySqDist.Value(N); 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(); if (!myPinit || !mySinit) Standard_TypeMismatch::Raise();
return myPoint.Value(N); return myPoint.Value(N);

View File

@ -14,12 +14,11 @@
// Alternatively, this file may be used under the terms of Open CASCADE // Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement. // commercial license or contractual agreement.
#ifndef _Extrema_FuncExtPS_HeaderFile #ifndef _Extrema_FunctPSNorm_HeaderFile
#define _Extrema_FuncExtPS_HeaderFile #define _Extrema_FunctPSNorm_HeaderFile
#include <Standard.hxx> #include <Standard.hxx>
#include <Standard_DefineAlloc.hxx> #include <Standard_DefineAlloc.hxx>
#include <Standard_Handle.hxx>
#include <gp_Pnt.hxx> #include <gp_Pnt.hxx>
#include <Adaptor3d_SurfacePtr.hxx> #include <Adaptor3d_SurfacePtr.hxx>
@ -58,16 +57,16 @@ class Extrema_POnSurf;
//! Dvf2(u,v) = Sv^2 + (S-P) * Svv //! Dvf2(u,v) = Sv^2 + (S-P) * Svv
//! //!
//! Here * denotes scalar product, and ^2 is square power. //! Here * denotes scalar product, and ^2 is square power.
class Extrema_FuncExtPS : public math_FunctionSetWithDerivatives class Extrema_FuncPSNorm : public math_FunctionSetWithDerivatives
{ {
public: public:
DEFINE_STANDARD_ALLOC 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. //! sets the field mysurf of the function.
Standard_EXPORT void Initialize (const Adaptor3d_Surface& S); Standard_EXPORT void Initialize (const Adaptor3d_Surface& S);
@ -100,19 +99,8 @@ public:
//! Returns the Nth extremum. //! Returns the Nth extremum.
Standard_EXPORT const Extrema_POnSurf& Point (const Standard_Integer N) const; Standard_EXPORT const Extrema_POnSurf& Point (const Standard_Integer N) const;
protected:
private: private:
gp_Pnt myP; gp_Pnt myP;
Adaptor3d_SurfacePtr myS; Adaptor3d_SurfacePtr myS;
Standard_Real myU; Standard_Real myU;
@ -122,14 +110,5 @@ private:
Extrema_SequenceOfPOnSurf myPoint; Extrema_SequenceOfPOnSurf myPoint;
Standard_Boolean myPinit; Standard_Boolean myPinit;
Standard_Boolean mySinit; Standard_Boolean mySinit;
}; };
#endif // _Extrema_FunctPSNorm_HeaderFile
#endif // _Extrema_FuncExtPS_HeaderFile

View File

@ -27,7 +27,7 @@
#include <Extrema_HArray2OfPOnSurfParams.hxx> #include <Extrema_HArray2OfPOnSurfParams.hxx>
#include <Extrema_HUBTreeOfSphere.hxx> #include <Extrema_HUBTreeOfSphere.hxx>
#include <Bnd_HArray1OfSphere.hxx> #include <Bnd_HArray1OfSphere.hxx>
#include <Extrema_FuncExtPS.hxx> #include <Extrema_FuncPSNorm.hxx>
#include <Adaptor3d_SurfacePtr.hxx> #include <Adaptor3d_SurfacePtr.hxx>
#include <Extrema_ExtFlag.hxx> #include <Extrema_ExtFlag.hxx>
#include <Extrema_ExtAlgo.hxx> #include <Extrema_ExtAlgo.hxx>
@ -148,7 +148,7 @@ private:
Handle(Extrema_HArray2OfPOnSurfParams) myPoints; Handle(Extrema_HArray2OfPOnSurfParams) myPoints;
Extrema_HUBTreeOfSphere mySphereUBTree; Extrema_HUBTreeOfSphere mySphereUBTree;
Handle(Bnd_HArray1OfSphere) mySphereArray; Handle(Bnd_HArray1OfSphere) mySphereArray;
Extrema_FuncExtPS myF; Extrema_FuncPSNorm myF;
Adaptor3d_SurfacePtr myS; Adaptor3d_SurfacePtr myS;
Extrema_ExtFlag myFlag; Extrema_ExtFlag myFlag;
Extrema_ExtAlgo myAlgo; Extrema_ExtAlgo myAlgo;

View File

@ -15,72 +15,67 @@
// commercial license or contractual agreement. // commercial license or contractual agreement.
#include <Adaptor3d_Surface.hxx>
#include <Extrema_FuncExtPS.hxx>
#include <Extrema_GenLocateExtPS.hxx> #include <Extrema_GenLocateExtPS.hxx>
#include <Adaptor3d_Surface.hxx>
#include <Extrema_FuncPSNorm.hxx>
#include <Extrema_FuncPSDist.hxx>
#include <Extrema_POnSurf.hxx> #include <Extrema_POnSurf.hxx>
#include <gp.hxx>
#include <gp_Pnt.hxx> #include <gp_Pnt.hxx>
#include <math_FunctionSetRoot.hxx> #include <math_FunctionSetRoot.hxx>
#include <math_NewtonFunctionSetRoot.hxx> #include <math_BFGS.hxx>
#include <math_Vector.hxx> #include <math_Vector.hxx>
#include <Standard_DomainError.hxx>
#include <StdFail_NotDone.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, //function : Perform
const Standard_Real U0, //purpose :
const Standard_Real V0, //=======================================================================
const Standard_Real TolU, void Extrema_GenLocateExtPS::Perform(const gp_Pnt& theP,
const Standard_Real TolV) const Standard_Real theU0,
/*----------------------------------------------------------------------------- const Standard_Real theV0,
Function: const Standard_Boolean isDistanceCriteria)
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. .
---------------------------------------------------------------------------*/
{ {
myDone = Standard_False; myDone = Standard_False;
Standard_Real Uinf, Usup, Vinf, Vsup; // Prepare initial data structures.
Uinf = S.FirstUParameter(); math_Vector aTol(1, 2), aStart(1, 2), aBoundInf(1, 2), aBoundSup(1, 2);
Usup = S.LastUParameter();
Vinf = S.FirstVParameter();
Vsup = S.LastVParameter();
Extrema_FuncExtPS F (P,S); // Tolerance.
math_Vector Tol(1, 2), Start(1, 2), BInf(1, 2), BSup(1, 2); aTol(1) = myTolU;
aTol(2) = myTolV;
Tol(1) = TolU; // Initial solution approximation.
Tol(2) = TolV; aStart(1) = theU0;
aStart(2) = theV0;
Start(1) = U0; // Borders.
Start(2) = V0; aBoundInf(1) = mySurf.FirstUParameter();
aBoundInf(2) = mySurf.FirstVParameter();
aBoundSup(1) = mySurf.LastUParameter();
aBoundSup(2) = mySurf.LastVParameter();
BInf(1) = Uinf; if (isDistanceCriteria == Standard_False)
BInf(2) = Vinf; {
BSup(1) = Usup; // Normal projection criteria.
BSup(2) = Vsup; Extrema_FuncPSNorm F(theP,mySurf);
math_FunctionSetRoot SR (F, Tol); math_FunctionSetRoot SR (F, aTol);
SR.Perform(F, Start, BInf, BSup); SR.Perform(F, aStart, aBoundInf, aBoundSup);
if (!SR.IsDone()) if (!SR.IsDone())
return; return;
@ -88,21 +83,49 @@ Method:
myPoint = F.Point(1); myPoint = F.Point(1);
myDone = Standard_True; myDone = Standard_True;
} }
//============================================================================= else
{
// Distance criteria.
Extrema_FuncPSDist F(mySurf, theP);
math_BFGS aSolver(2);
aSolver.Perform(F, aStart);
Standard_Boolean Extrema_GenLocateExtPS::IsDone () const { return myDone; } 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;
}
}
//=======================================================================
//function : IsDone
//purpose :
//=======================================================================
Standard_Boolean Extrema_GenLocateExtPS::IsDone () const
{
return myDone;
}
//=======================================================================
//function : SquareDistance
//purpose :
//=======================================================================
Standard_Real Extrema_GenLocateExtPS::SquareDistance () const Standard_Real Extrema_GenLocateExtPS::SquareDistance () const
{ {
if (!IsDone()) { StdFail_NotDone::Raise(); } if (!IsDone()) { StdFail_NotDone::Raise(); }
return mySqDist; return mySqDist;
} }
//=============================================================================
//=======================================================================
//function : Point
//purpose :
//=======================================================================
const Extrema_POnSurf& Extrema_GenLocateExtPS::Point () const const Extrema_POnSurf& Extrema_GenLocateExtPS::Point () const
{ {
if (!IsDone()) { StdFail_NotDone::Raise(); } if (!IsDone()) { StdFail_NotDone::Raise(); }
return myPoint; return myPoint;
} }
//=============================================================================

View File

@ -19,7 +19,6 @@
#include <Standard.hxx> #include <Standard.hxx>
#include <Standard_DefineAlloc.hxx> #include <Standard_DefineAlloc.hxx>
#include <Standard_Handle.hxx>
#include <Standard_Boolean.hxx> #include <Standard_Boolean.hxx>
#include <Standard_Real.hxx> #include <Standard_Real.hxx>
@ -33,23 +32,27 @@ class Extrema_POnSurf;
//! With a close point, it calculates the distance //! With a close point, it calculates the distance
//! between a point and a surface. //! 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 class Extrema_GenLocateExtPS
{ {
public: public:
DEFINE_STANDARD_ALLOC 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 extrema between the point and the surface using a close point.
//! The close point is defined by the parameter values theU0 and theV0.
//! Calculates the distance with a close point. //! Type of the algorithm depends on the isDistanceCriteria flag.
//! The close point is defined by the parameter values //! If flag value is false - normal projection criteria will be used.
//! U0 and V0. //! If flag value is true - distance criteria will be used.
//! The function F(u,v)=distance(S(u,v),p) has an Standard_EXPORT void Perform(const gp_Pnt& theP,
//! extremun when gradient(F)=0. The algorithm searchs const Standard_Real theU0,
//! a zero near the close point. const Standard_Real theV0,
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); const Standard_Boolean isDistanceCriteria = Standard_False);
//! Returns True if the distance is found. //! Returns True if the distance is found.
Standard_EXPORT Standard_Boolean IsDone() const; Standard_EXPORT Standard_Boolean IsDone() const;
@ -60,20 +63,19 @@ public:
//! Returns the point of the extremum distance. //! Returns the point of the extremum distance.
Standard_EXPORT const Extrema_POnSurf& Point() const; Standard_EXPORT const Extrema_POnSurf& Point() const;
protected:
private: 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; Standard_Boolean myDone;
// Result.
Standard_Real mySqDist; Standard_Real mySqDist;
Extrema_POnSurf myPoint; Extrema_POnSurf myPoint;

View File

@ -72,8 +72,10 @@ Extrema_FuncExtCC.lxx
Extrema_FuncExtCS.cxx Extrema_FuncExtCS.cxx
Extrema_FuncExtCS.hxx Extrema_FuncExtCS.hxx
Extrema_FuncExtPC.gxx Extrema_FuncExtPC.gxx
Extrema_FuncExtPS.cxx Extrema_FuncPSNorm.cxx
Extrema_FuncExtPS.hxx Extrema_FuncPSNorm.hxx
Extrema_FuncPSDist.cxx
Extrema_FuncPSDist.hxx
Extrema_FuncExtSS.cxx Extrema_FuncExtSS.cxx
Extrema_FuncExtSS.hxx Extrema_FuncExtSS.hxx
Extrema_GenExtCC.gxx Extrema_GenExtCC.gxx

View File

@ -2782,9 +2782,8 @@ static Standard_Boolean DecomposeResult(const Handle(IntPatch_PointLine)& theLin
theQSurf->D0(aUquad, aVquad, aPQuad); theQSurf->D0(aUquad, aVquad, aPQuad);
Extrema_GenLocateExtPS anExtr(aPQuad, thePSurf->Surface(), aU0, aV0, Extrema_GenLocateExtPS anExtr(thePSurf->Surface());
Precision::PConfusion(), anExtr.Perform(aPQuad, aU0, aV0);
Precision::PConfusion());
if(!anExtr.IsDone()) if(!anExtr.IsDone())
{ {
@ -2946,9 +2945,8 @@ static Standard_Boolean DecomposeResult(const Handle(IntPatch_PointLine)& theLin
theQSurf->D0(aUquad, aVquad, aPQuad); theQSurf->D0(aUquad, aVquad, aPQuad);
Extrema_GenLocateExtPS anExtr(aPQuad, thePSurf->Surface(), aU0, aV0, Extrema_GenLocateExtPS anExtr(thePSurf->Surface());
Precision::PConfusion(), anExtr.Perform(aPQuad, aU0, aV0);
Precision::PConfusion());
if(!anExtr.IsDone()) if(!anExtr.IsDone())
{ {

View File

@ -1312,7 +1312,8 @@ void IntTools_BeanFaceIntersector::ComputeRangeFromStartPoint(const Standard_Boo
// //
gp_Pnt aPoint = myCurve.Value(aCurPar); 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.IsDone()) {
if(anExtrema.SquareDistance() < myCriteria * myCriteria) { if(anExtrema.SquareDistance() < myCriteria * myCriteria) {

View File

@ -617,8 +617,9 @@ static Standard_Real SQDistPointSurface(const gp_Pnt &thePnt,
const Standard_Real theU0, const Standard_Real theU0,
const Standard_Real theV0) const Standard_Real theV0)
{ {
const Extrema_GenLocateExtPS aExtPS(thePnt, theSurf, theU0, theV0, Extrema_GenLocateExtPS aExtPS(theSurf);
Precision::PConfusion(), Precision::PConfusion()); aExtPS.Perform(thePnt, theU0, theV0);
if(!aExtPS.IsDone()) if(!aExtPS.IsDone())
return RealLast(); return RealLast();

View File

@ -367,7 +367,8 @@ static gp_Pnt2d Function_Value(const Standard_Real theU,
} }
// Try to run simple search with initial point (U0, V0). // 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()) if (locext.IsDone())
{ {
locext.Point().Parameter(u, v); locext.Point().Parameter(u, v);
@ -1218,8 +1219,8 @@ Handle(Adaptor2d_HCurve2d)
myProjIsDone = Standard_False; myProjIsDone = Standard_False;
Dist2Min = RealLast(); Dist2Min = RealLast();
Curve->D0(Param.Value(i), pntproj); Curve->D0(Param.Value(i), pntproj);
Extrema_GenLocateExtPS aLocateExtPS Extrema_GenLocateExtPS aLocateExtPS(Surf->Surface(), TolU, TolV);
(pntproj, Surf->Surface(), U0, V0, TolU, TolV) ; aLocateExtPS.Perform(pntproj, U0, V0);
if (aLocateExtPS.IsDone()) if (aLocateExtPS.IsDone())
{ {
@ -1315,9 +1316,10 @@ Handle(Adaptor2d_HCurve2d)
Uaux = 2*aUinf - U0 + uperiod; Uaux = 2*aUinf - U0 + uperiod;
else else
Uaux = 2*aUsup - U0 - uperiod; Uaux = 2*aUsup - U0 - uperiod;
Extrema_GenLocateExtPS locext(pntproj,
Surf->Surface(), Extrema_GenLocateExtPS locext(Surf->Surface(), TolU, TolV);
Uaux, V0, TolU, TolV); locext.Perform(pntproj, Uaux, V0);
if (locext.IsDone()) if (locext.IsDone())
if (locext.SquareDistance() < DistTol3d * DistTol3d) { //OCC217 if (locext.SquareDistance() < DistTol3d * DistTol3d) { //OCC217
//if (locext.SquareDistance() < Tol3d * Tol3d) { //if (locext.SquareDistance() < Tol3d * Tol3d) {
@ -1341,9 +1343,10 @@ Handle(Adaptor2d_HCurve2d)
Vaux = 2*aVinf - V0 + vperiod; Vaux = 2*aVinf - V0 + vperiod;
else else
Vaux = 2*aVsup - V0 - vperiod; Vaux = 2*aVsup - V0 - vperiod;
Extrema_GenLocateExtPS locext(pntproj,
Surf->Surface(), Extrema_GenLocateExtPS locext(Surf->Surface(), TolU, TolV);
U0, Vaux, TolU, TolV) ; locext.Perform(pntproj, U0, Vaux);
if (locext.IsDone()) if (locext.IsDone())
if (locext.SquareDistance() < DistTol3d * DistTol3d) { //OCC217 if (locext.SquareDistance() < DistTol3d * DistTol3d) { //OCC217
//if (locext.SquareDistance() < Tol3d * Tol3d) { //if (locext.SquareDistance() < Tol3d * Tol3d) {
@ -1369,9 +1372,10 @@ Handle(Adaptor2d_HCurve2d)
Vaux = 2*Vinf - V0 + vperiod; Vaux = 2*Vinf - V0 + vperiod;
else else
Vaux = 2*Vsup - V0 - vperiod; Vaux = 2*Vsup - V0 - vperiod;
Extrema_GenLocateExtPS locext(pntproj,
Surf->Surface(), Extrema_GenLocateExtPS locext(Surf->Surface(), TolU, TolV);
Uaux, Vaux, TolU, TolV); locext.Perform(pntproj, Uaux, Vaux);
if (locext.IsDone()) if (locext.IsDone())
if (locext.SquareDistance() < DistTol3d * DistTol3d) { if (locext.SquareDistance() < DistTol3d * DistTol3d) {
//if (locext.SquareDistance() < Tol3d * Tol3d) { //if (locext.SquareDistance() < Tol3d * Tol3d) {
@ -1584,8 +1588,10 @@ Handle(Geom2d_BSplineCurve)
for(i = 1;i <= Curve->NbPoles();i++) { for(i = 1;i <= Curve->NbPoles();i++) {
myProjIsDone = Standard_False; myProjIsDone = Standard_False;
Dist2Min = IntegerLast(); 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()) { if (extrloc.IsDone()) {
Dist2Min = (Standard_Integer ) extrloc.SquareDistance(); Dist2Min = (Standard_Integer ) extrloc.SquareDistance();
if (Dist2Min < DistTol3d * DistTol3d) { //OCC217 if (Dist2Min < DistTol3d * DistTol3d) { //OCC217
@ -1622,8 +1628,10 @@ Handle(Geom2d_BSplineCurve)
TColgp_Array1OfPnt2d Poles2d(1,Curve->NbPoles()); TColgp_Array1OfPnt2d Poles2d(1,Curve->NbPoles());
for(i = 1;i <= Curve->NbPoles();i++) { for(i = 1;i <= Curve->NbPoles();i++) {
Dist2Min = IntegerLast(); 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()) { if (extrloc.IsDone()) {
Dist2Min = (Standard_Integer ) extrloc.SquareDistance(); Dist2Min = (Standard_Integer ) extrloc.SquareDistance();
if (Dist2Min < DistTol3d * DistTol3d) { //OCC217 if (Dist2Min < DistTol3d * DistTol3d) { //OCC217
@ -1685,8 +1693,10 @@ Handle(Geom2d_BSplineCurve)
for(i = 1;i <= Curve->NbPoles();i++) { for(i = 1;i <= Curve->NbPoles();i++) {
myProjIsDone = Standard_False; myProjIsDone = Standard_False;
Dist2Min = IntegerLast(); 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()) { if (extrloc.IsDone()) {
Dist2Min = (Standard_Integer ) extrloc.SquareDistance(); Dist2Min = (Standard_Integer ) extrloc.SquareDistance();
if (Dist2Min < DistTol3d * DistTol3d) { //OCC217 if (Dist2Min < DistTol3d * DistTol3d) { //OCC217
@ -1723,8 +1733,10 @@ Handle(Geom2d_BSplineCurve)
TColgp_Array1OfPnt2d Poles2d(1,Curve->NbPoles()); TColgp_Array1OfPnt2d Poles2d(1,Curve->NbPoles());
for(i = 1;i <= Curve->NbPoles();i++) { for(i = 1;i <= Curve->NbPoles();i++) {
Dist2Min = IntegerLast(); 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()) { if (extrloc.IsDone()) {
Dist2Min = (Standard_Integer ) extrloc.SquareDistance(); Dist2Min = (Standard_Integer ) extrloc.SquareDistance();
if (Dist2Min < DistTol3d * DistTol3d) { //OCC217 if (Dist2Min < DistTol3d * DistTol3d) { //OCC217

View File

@ -1364,7 +1364,7 @@ static Standard_Integer OCC24945 (Draw_Interpretor& di, Standard_Integer argc, c
return 0; return 0;
} }
#include <Extrema_FuncExtPS.hxx> #include <Extrema_FuncPSNorm.hxx>
#include <math_FunctionSetRoot.hxx> #include <math_FunctionSetRoot.hxx>
#include <math_Vector.hxx> #include <math_Vector.hxx>
#include <BRepBuilderAPI_MakeVertex.hxx> #include <BRepBuilderAPI_MakeVertex.hxx>
@ -1401,7 +1401,7 @@ static Standard_Integer OCC24137 (Draw_Interpretor& theDI, Standard_Integer theN
gp_Pnt aPnt = BRep_Tool::Pnt (aVert), aRes; gp_Pnt aPnt = BRep_Tool::Pnt (aVert), aRes;
Extrema_FuncExtPS anExtFunc; Extrema_FuncPSNorm anExtFunc;
math_FunctionSetRoot aRoot (anExtFunc, aNbIts); math_FunctionSetRoot aRoot (anExtFunc, aNbIts);
math_Vector aTolUV (1, 2), aUVinf (1, 2), aUVsup (1, 2), aFromUV (1, 2); math_Vector aTolUV (1, 2), aUVinf (1, 2), aUVsup (1, 2), aFromUV (1, 2);

View File

@ -16,6 +16,7 @@
#include <QABugs.hxx> #include <QABugs.hxx>
#include <gp_Ax2.hxx> #include <gp_Ax2.hxx>
#include <Extrema_GenLocateExtPS.hxx>
#include <Geom_Circle.hxx> #include <Geom_Circle.hxx>
#include <Geom_SurfaceOfLinearExtrusion.hxx> #include <Geom_SurfaceOfLinearExtrusion.hxx>
#include <NCollection_List.hxx> #include <NCollection_List.hxx>
@ -36,6 +37,7 @@
#include <TopoDS_Edge.hxx> #include <TopoDS_Edge.hxx>
#include <BRep_Builder.hxx> #include <BRep_Builder.hxx>
#include <BRepTools.hxx> #include <BRepTools.hxx>
#include <BRepAdaptor_Surface.hxx>
#include <TopoDS.hxx> #include <TopoDS.hxx>
#include <DBRep.hxx> #include <DBRep.hxx>
@ -1571,6 +1573,55 @@ static Standard_Integer OCC26930(Draw_Interpretor& theDI,
return 0; 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) { void QABugs::Commands_20(Draw_Interpretor& theCommands) {
const char *group = "QABugs"; const char *group = "QABugs";
@ -1579,6 +1630,7 @@ void QABugs::Commands_20(Draw_Interpretor& theCommands) {
theCommands.Add("OCC27021", "OCC27021", __FILE__, OCC27021, group); theCommands.Add("OCC27021", "OCC27021", __FILE__, OCC27021, group);
theCommands.Add("OCC27235", "OCC27235", __FILE__, OCC27235, group); theCommands.Add("OCC27235", "OCC27235", __FILE__, OCC27235, group);
theCommands.Add("OCC26930", "OCC26930", __FILE__, OCC26930, group); theCommands.Add("OCC26930", "OCC26930", __FILE__, OCC26930, group);
theCommands.Add("OCC27466", "OCC27466", __FILE__, OCC27466, group);
return; return;
} }

View File

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