From 03a1dbbdf290ecd78ff1d6b1c938e5db019bd906 Mon Sep 17 00:00:00 2001 From: emv Date: Wed, 27 May 2020 16:42:36 +0300 Subject: [PATCH] # Perform localized extrema search in ComputeApproxOnPolarSurface --- src/Extrema/Extrema_ExtPS.cxx | 42 +++++-- src/Extrema/Extrema_ExtPS.hxx | 13 ++ src/Extrema/Extrema_GenExtPS.cxx | 82 +++++++++--- src/Extrema/Extrema_GenExtPS.hxx | 60 +++++++-- .../ProjLib_ComputeApproxOnPolarSurface.cxx | 119 ++++++++++++++---- 5 files changed, 255 insertions(+), 61 deletions(-) diff --git a/src/Extrema/Extrema_ExtPS.cxx b/src/Extrema/Extrema_ExtPS.cxx index 94b486d71a..b38ab1215d 100644 --- a/src/Extrema/Extrema_ExtPS.cxx +++ b/src/Extrema/Extrema_ExtPS.cxx @@ -112,25 +112,25 @@ void Extrema_ExtPS::TreatSolution (const Extrema_POnSurf& PS, Standard_Real U, V; PS.Parameter(U, V); if (myS->IsUPeriodic()) { - U = ElCLib::InPeriod(U, myuinf, myuinf + myS->UPeriod()); + U = ElCLib::InPeriod(U, myLocUMin, myLocUMin + myS->UPeriod()); // Handle trimmed surfaces. - if (U > myusup + mytolu) + if (U > myLocUMax + mytolu) U -= myS->UPeriod(); - if (U < myuinf - mytolu) + if (U < myLocUMin - mytolu) U += myS->UPeriod(); } if (myS->IsVPeriodic()) { - V = ElCLib::InPeriod(V, myvinf, myvinf + myS->VPeriod()); + V = ElCLib::InPeriod(V, myLocVMin, myLocVMin + myS->VPeriod()); // Handle trimmed surfaces. - if (V > myvsup + mytolv) + if (V > myLocVMax + mytolv) V -= myS->VPeriod(); - if (V < myvinf - mytolv) + if (V < myLocVMin - mytolv) V += myS->VPeriod(); } - if ((myuinf-U) <= mytolu && (U-myusup) <= mytolu && - (myvinf-V) <= mytolv && (V-myvsup) <= mytolv) { + if ((myLocUMin-U) <= mytolu && (U-myLocUMax) <= mytolu && + (myLocVMin-V) <= mytolv && (V-myLocVMax) <= mytolv) { myPoints.Append(Extrema_POnSurf (U, V, PS.Value())); mySqDist.Append(Val); } @@ -237,6 +237,11 @@ void Extrema_ExtPS::Initialize (const Adaptor3d_Surface& theS, if (Precision::IsNegativeInfinite(myvinf)) myvinf = -1e10; if (Precision::IsPositiveInfinite(myvsup)) myvsup = 1e10; + myLocUMin = myuinf; + myLocUMax = myusup; + myLocVMin = myvinf; + myLocVMax = myvsup; + mytolu = theTolU; mytolv = theTolV; mytype = myS->GetType(); @@ -272,12 +277,29 @@ void Extrema_ExtPS::Initialize (const Adaptor3d_Surface& theS, //function : Perform //purpose : //======================================================================= +void Extrema_ExtPS::Perform (const gp_Pnt& thePoint) +{ + Perform (thePoint, myuinf, myusup, myvinf, myvsup); +} -void Extrema_ExtPS::Perform(const gp_Pnt& thePoint) +//======================================================================= +//function : Perform +//purpose : +//======================================================================= +void Extrema_ExtPS::Perform (const gp_Pnt& thePoint, + const Standard_Real theLocUMin, + const Standard_Real theLocUMax, + const Standard_Real theLocVMin, + const Standard_Real theLocVMax) { myPoints.Clear(); mySqDist.Clear(); + myLocUMin = Max (theLocUMin, myuinf); + myLocUMax = Min (theLocUMax, myusup); + myLocVMin = Max (theLocVMin, myvinf); + myLocVMax = Min (theLocVMax, myvsup); + switch (mytype) { case GeomAbs_Cylinder: @@ -350,7 +372,7 @@ void Extrema_ExtPS::Perform(const gp_Pnt& thePoint) default: { - myExtPS->Perform (thePoint); + myExtPS->Perform (thePoint, myLocUMin, myLocUMax, myLocVMin, myLocVMax); myDone = myExtPS->IsDone(); if (myDone) { diff --git a/src/Extrema/Extrema_ExtPS.hxx b/src/Extrema/Extrema_ExtPS.hxx index 722938471c..41837021a0 100644 --- a/src/Extrema/Extrema_ExtPS.hxx +++ b/src/Extrema/Extrema_ExtPS.hxx @@ -100,6 +100,15 @@ public: //! initialized. Standard_EXPORT void Perform (const gp_Pnt& P); + //! Performs localized extrema search. + //! The solution to be found in the given parametric space, which + //! is required to be inside the initialized parametric space. + Standard_EXPORT void Perform (const gp_Pnt& P, + const Standard_Real theLocUMin, + const Standard_Real theLocUMax, + const Standard_Real theLocVMin, + const Standard_Real theLocVMax); + //! Returns True if the distances are found. Standard_EXPORT Standard_Boolean IsDone() const; @@ -152,6 +161,10 @@ private: Standard_Real myvsup; Standard_Real mytolu; Standard_Real mytolv; + Standard_Real myLocUMin; //!< Localized parametric space boundary (required to be inside the main parametric space) + Standard_Real myLocUMax; //!< Localized parametric space boundary (required to be inside the main parametric space) + Standard_Real myLocVMin; //!< Localized parametric space boundary (required to be inside the main parametric space) + Standard_Real myLocVMax; //!< Localized parametric space boundary (required to be inside the main parametric space) Standard_Real d11; Standard_Real d12; Standard_Real d21; diff --git a/src/Extrema/Extrema_GenExtPS.cxx b/src/Extrema/Extrema_GenExtPS.cxx index e038d17b7a..15fd6153f4 100644 --- a/src/Extrema/Extrema_GenExtPS.cxx +++ b/src/Extrema/Extrema_GenExtPS.cxx @@ -108,6 +108,10 @@ Extrema_GenExtPS::Extrema_GenExtPS() myNbVSamples (0), myTolU (Precision::PConfusion()), myTolV (Precision::PConfusion()), + myLocUMin (RealLast()), + myLocUMax (RealFirst()), + myLocVMin (RealLast()), + myLocVMax (RealFirst()), myTarget (Extrema_ExtFlag_MINMAX), mySqDistance (-1), myIsDone (Standard_False) @@ -211,6 +215,11 @@ void Extrema_GenExtPS::Initialize (const Adaptor3d_Surface& theS, myTolU = theTolU; myTolV = theTolV; + myLocUMin = myUMin; + myLocUMax = myUMax; + myLocVMin = myVMin; + myLocVMax = myVMax; + if (myNbUSamples < 2 || myNbVSamples < 2) { throw Standard_OutOfRange ("Extrema_GenExtPS::Initialize - number of samples is too small"); @@ -228,12 +237,30 @@ void Extrema_GenExtPS::Initialize (const Adaptor3d_Surface& theS, //purpose : //======================================================================= void Extrema_GenExtPS::Perform (const gp_Pnt& thePoint) +{ + Perform (thePoint, myUMin, myUMax, myVMin, myVMax); +} + +//======================================================================= +//function : Perform +//purpose : +//======================================================================= +void Extrema_GenExtPS::Perform (const gp_Pnt& thePoint, + const Standard_Real theUMin, + const Standard_Real theUMax, + const Standard_Real theVMin, + const Standard_Real theVMax) { myIsDone = Standard_False; myPoint = BVH_Vec3d (thePoint.X(), thePoint.Y(), thePoint.Z()); myF.SetPoint (thePoint, myTarget); mySolutions.clear(); + myLocUMin = Max (theUMin, myUMin); + myLocUMax = Min (theUMax, myUMax); + myLocVMin = Max (theVMin, myVMin); + myLocVMax = Min (theVMax, myVMax); + if (myUParams.IsNull() || myVParams.IsNull()) { // Prepare surface sampling @@ -318,7 +345,7 @@ void Extrema_GenExtPS::Perform (const gp_Pnt& thePoint) // Copy solutions for (Standard_Integer i = 1; i <= myF.NbExt(); ++i) { - mySolutions.push_back (Extrema_GenExtPS::ExtPSResult (myF.Point (i), myF.SquareDistance (i))); + mySolutions.push_back (Extrema_GenExtPS_ExtPSResult (myF.Point (i), myF.SquareDistance (i))); } } else @@ -331,7 +358,7 @@ void Extrema_GenExtPS::Perform (const gp_Pnt& thePoint) for (Standard_Integer i = 1; i <= myF.NbExt(); ++i) { if (Abs (mySqDistance - myF.SquareDistance (i)) < Precision::SquareConfusion()) - mySolutions.push_back (Extrema_GenExtPS::ExtPSResult (myF.Point (i), myF.SquareDistance (i))); + mySolutions.push_back (Extrema_GenExtPS_ExtPSResult (myF.Point (i), myF.SquareDistance (i))); } } @@ -406,7 +433,7 @@ void Extrema_GenExtPS::BuildTree() // Builder for low-level BVH sets opencascade::handle > aLBuilder = new BVH_LinearBuilder(); - myBVHBoxSet = new BVH_IndexedBoxSet ( + myBVHBoxSet = new BVH_IndexedBoxSet ( new BVH_LinearBuilder (BVH_Constants_LeafNodeSizeSingle)); // create hierarchy of BVH trees @@ -433,12 +460,27 @@ void Extrema_GenExtPS::BuildTree() { for (Standard_Integer iV = V1; iV <= V2; ++iV) { - aGridSet->Add (GridCell (iU, iV), BVH_Box()); + aGridSet->Add (Extrema_GenExtPS_GridCell (iU, iV), BVH_Box()); } } V1 = V2 + 1; - myBVHBoxSet->Add (aGridSet, BVH_Box()); + Extrema_GenExtPS_GridCell aMinCell = aGridSet->Element (0); + Extrema_GenExtPS_GridCell aMaxCell = aGridSet->Element (aGridSet->Size() - 1); + + Standard_Integer aUCoeff = (aMaxCell.UIndex < myNbUSamples) ? 1 : 0; + Standard_Integer aVCoeff = (aMaxCell.VIndex < myNbVSamples) ? 1 : 0; + + const Extrema_POnSurf& aPMin = myPoints->Value (aMinCell.UIndex, aMinCell.VIndex); + const Extrema_POnSurf& aPMax = myPoints->Value (aMaxCell.UIndex + aUCoeff, aMaxCell.VIndex + aVCoeff); + + Standard_Real aUMin, aUMax, aVMin, aVMax; + aPMin.Parameter (aUMin, aVMin); + aPMax.Parameter (aUMax, aVMax); + + myBVHBoxSet->Add ( + Extrema_GenExtPS_LocalizedSurf (aUMin, aUMax, aVMin, aVMax, aGridSet), + BVH_Box()); } U1 = U2 + 1; V1 = 1; @@ -451,14 +493,14 @@ void Extrema_GenExtPS::BuildTree() const Standard_Integer aNbSets = myBVHBoxSet->Size(); for (Standard_Integer iSet = 0; iSet < aNbSets; ++iSet) { - Handle (Extrema_GenExtPS_GridCellBoxSet) aGridSet = myBVHBoxSet->Element (iSet); + Extrema_GenExtPS_LocalizedSurf aGridSet = myBVHBoxSet->Element (iSet); // Box of the set Bnd_Box aSetBox; - const Standard_Integer aNbCells = aGridSet->Size(); + const Standard_Integer aNbCells = aGridSet.CellBoxSet->Size(); for (Standard_Integer iCell = 0; iCell < aNbCells; ++iCell) { - const GridCell& aCell = aGridSet->Element (iCell); + const Extrema_GenExtPS_GridCell& aCell = aGridSet.CellBoxSet->Element (iCell); Standard_Integer iU = aCell.UIndex, iV = aCell.VIndex; Standard_Integer aUCoeff = (iU < myNbUSamples) ? 1 : 0; @@ -496,7 +538,7 @@ void Extrema_GenExtPS::BuildTree() //Standard_Real anAvSqExt = aSetBox.SquareExtent() / (aGridSet->Size() - 1); //aGridBox.Enlarge (Sqrt (anAvSqExt)); } - aGridSet->UpdateBox (iCell, Bnd_Tools::Bnd2BVH (aGridBox)); + aGridSet.CellBoxSet->UpdateBox (iCell, Bnd_Tools::Bnd2BVH (aGridBox)); aSetBox.Add (aGridBox); } @@ -653,10 +695,14 @@ Standard_Boolean Extrema_GenExtPS::Accept (const Standard_Integer theIndex, { if (myBVHSet == NULL) { - Handle (Extrema_GenExtPS_GridCellBoxSet) aGridSet = myBVHBoxSet->Element (theIndex); - aGridSet->Build(); + Extrema_GenExtPS_LocalizedSurf aGridSet = myBVHBoxSet->Element (theIndex); + if ((aGridSet.UMax < myLocUMin || aGridSet.UMin > myLocUMax) && + (aGridSet.VMax < myLocVMin || aGridSet.VMin > myLocVMax)) + return 0; + + aGridSet.CellBoxSet->Build(); // Set low-level BVH set for inner selection - SetBVHSet (aGridSet.get()); + SetBVHSet (aGridSet.CellBoxSet.get()); Standard_Integer aNb = Select(); // Unset the inner set and continue with high level BVH traverse SetBVHSet (NULL); @@ -664,7 +710,7 @@ Standard_Boolean Extrema_GenExtPS::Accept (const Standard_Integer theIndex, } else { - GridCell aCell = myBVHSet->Element (theIndex); + Extrema_GenExtPS_GridCell aCell = myBVHSet->Element (theIndex); return FindSolution (aCell.UIndex, aCell.VIndex, myTarget); } } @@ -677,13 +723,21 @@ Standard_Boolean Extrema_GenExtPS::FindSolution (const Standard_Integer theNU, const Standard_Integer theNV, const Extrema_ExtFlag theTarget) { - // Fill corner points with square distance to myPoint Extrema_POnSurfParams& aParam00 = myPoints->ChangeValue (theNU, theNV); Extrema_POnSurfParams& aParam01 = myPoints->ChangeValue (theNU, theNV + 1); Extrema_POnSurfParams& aParam10 = myPoints->ChangeValue (theNU + 1, theNV); Extrema_POnSurfParams& aParam11 = myPoints->ChangeValue (theNU + 1, theNV + 1); + { + Standard_Real U1, U2, V1, V2; + aParam00.Parameter (U1, V1); + aParam11.Parameter (U2, V2); + if ((U2 < myLocUMin || U1 > myLocUMax) && + (V2 < myLocVMin || V1 > myLocVMax)) + return Standard_False; + } + gp_Pnt aPoint (myPoint.x(), myPoint.y(), myPoint.z()); fillSqDist (aParam00, aPoint); diff --git a/src/Extrema/Extrema_GenExtPS.hxx b/src/Extrema/Extrema_GenExtPS.hxx index b6b49e7602..795602c980 100644 --- a/src/Extrema/Extrema_GenExtPS.hxx +++ b/src/Extrema/Extrema_GenExtPS.hxx @@ -45,18 +45,18 @@ class Extrema_POnSurfParams; //! Grid cell defined by (U, V) indices of the minimal //! corner of the cell -struct GridCell +struct Extrema_GenExtPS_GridCell { Standard_Integer UIndex; //!< U index of the minimal corner Standard_Integer VIndex; //!< V index of the minimal corner - GridCell (Standard_Integer theUInd = -1, Standard_Integer theVInd = -1) + Extrema_GenExtPS_GridCell (Standard_Integer theUInd = -1, Standard_Integer theVInd = -1) : UIndex (theUInd), VIndex (theVInd) {} }; //! typedef to BVH tree of the grid cells -typedef BVH_BoxSet Extrema_GenExtPS_GridCellBoxSet; +typedef BVH_BoxSet Extrema_GenExtPS_GridCellBoxSet; //! It calculates the extreme distances between a point and a surface. @@ -219,7 +219,15 @@ public: //! @name Performing projection //! Allows multiple points be projected on the same surface. Standard_EXPORT void Perform (const gp_Pnt& theP); - + //! Performs localized extrema search. + //! The localized boundaries are required to be inside the + //! main (initialized) surface parametric space. + Standard_EXPORT void Perform (const gp_Pnt& theP, + const Standard_Real theUMin, + const Standard_Real theUMax, + const Standard_Real theVMin, + const Standard_Real theVMax); + public: //! @name Getting the results //! Returns True if the distances are found. @@ -308,23 +316,23 @@ protected: //! @name Rules for BVH traverse protected: //! @name Auxiliary types //! Structure to keep and sort the results - struct ExtPSResult + struct Extrema_GenExtPS_ExtPSResult { Extrema_POnSurf UV; //! UV coordinates of extrema solution Standard_Real SqDistance; //! Square distance to target point - ExtPSResult() + Extrema_GenExtPS_ExtPSResult() : SqDistance (-1) {} - ExtPSResult (const Extrema_POnSurf& theUV, - const Standard_Real theSqDist) + Extrema_GenExtPS_ExtPSResult (const Extrema_POnSurf& theUV, + const Standard_Real theSqDist) : UV (theUV), SqDistance (theSqDist) {} //! IsLess operator - Standard_Boolean operator< (const ExtPSResult& Other) const + Standard_Boolean operator< (const Extrema_GenExtPS_ExtPSResult& Other) const { if (SqDistance != Other.SqDistance) return SqDistance < Other.SqDistance; @@ -336,6 +344,29 @@ protected: //! @name Auxiliary types } }; + //! Localized parametric space of surface on which the single + //! BVH tree is built + struct Extrema_GenExtPS_LocalizedSurf + { + Standard_Real UMin; + Standard_Real UMax; + Standard_Real VMin; + Standard_Real VMax; + Handle(Extrema_GenExtPS_GridCellBoxSet) CellBoxSet; + + Extrema_GenExtPS_LocalizedSurf () + : UMin (0.0), UMax (0.0), VMin (0.0), VMax (0.0), CellBoxSet (NULL) + {} + + Extrema_GenExtPS_LocalizedSurf (const Standard_Real theUMin, + const Standard_Real theUMax, + const Standard_Real theVMin, + const Standard_Real theVMax, + const Handle(Extrema_GenExtPS_GridCellBoxSet)& theCellBoxSet) + : UMin (theUMin), UMax (theUMax), VMin (theVMin), VMax (theVMax), CellBoxSet (theCellBoxSet) + {} + }; + protected: //! @name Fields // Inputs @@ -354,6 +385,11 @@ protected: //! @name Fields Standard_Real myTolU; //!< U parametric tolerance Standard_Real myTolV; //!< V parametric tolerance + Standard_Real myLocUMin; //!< Localized surface parametric range: UMin + Standard_Real myLocUMax; //!< Localized surface parametric range: UMax + Standard_Real myLocVMin; //!< Localized surface parametric range: VMin + Standard_Real myLocVMax; //!< Localized surface parametric range: VMax + Extrema_ExtFlag myTarget; //!< Extrema objective // Intermediate data @@ -368,11 +404,11 @@ protected: //! @name Fields Standard_Real mySqDistance; //!< Min/Max found square distance used in BVH tree traverse opencascade::handle - > myBVHBoxSet; //!< High-level BVH of BVH organized grid cells + > myBVHBoxSet; //!< High-level BVH of BVH organized grid cells // Results - std::vector mySolutions; //!< Found solutions (sorted first by distance to target point, - //! second by the ascending U,V coordinates) + std::vector mySolutions; //!< Found solutions (sorted first by distance to target point, + //! second by the ascending U,V coordinates) Standard_Boolean myIsDone; //!< Done/Not done flag }; diff --git a/src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.cxx b/src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.cxx index 491e88380e..ca8d02ee3b 100644 --- a/src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.cxx +++ b/src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.cxx @@ -95,6 +95,7 @@ struct aFuncStruct Handle(Adaptor3d_HSurface) mySurf; // Surface where to project. Handle(Adaptor3d_HCurve) myCurve; // Curve to project. Handle(Adaptor2d_HCurve2d) myInitCurve2d; // Initial 2dcurve projection. + mutable Extrema_ExtPS myGlobExtPS; // Extrema initialized on whole parameter space of the surface Standard_Real mySqProjOrtTol; // Used to filter non-orthogonal projected point. Standard_Real myTolU; Standard_Real myTolV; @@ -190,6 +191,73 @@ static Standard_Real anOrthogSqValue(const gp_Pnt& aBasePnt, return (aFirstPart * aFirstPart + aSecondPart * aSecondPart); } +//======================================================================= +//function : checkSolution +//purpose : checks if the current solution is better than initial point +//======================================================================= +static Standard_Boolean checkSolution (const Extrema_POnSurf& theSol, + const Standard_Real theProjSqDist, + const Handle(Adaptor3d_HSurface)& theSurf, + const Standard_Real theUPeriod, + const Standard_Real theVPeriod, + const Standard_Integer theNbU, + const Standard_Integer theNbV, + const gp_Pnt& thePoint, + const Standard_Real theProjTol, + const Standard_Real theDist, + gp_Pnt2d& thePOnSurf) +{ + Standard_Real U, V; + theSol.Parameter (U, V); + Standard_Real Dist2Min = anOrthogSqValue (thePoint, theSurf, U, V); + if (Dist2Min < theProjTol && // Point is projection. + theProjSqDist < theDist + Precision::SquareConfusion()) // Point better than initial. + { + thePOnSurf.SetXY (gp_XY (U - theNbU * theUPeriod, V - theNbV * theVPeriod)); + return Standard_True; + } + return Standard_False; +} + +//======================================================================= +//function : checkSolution +//purpose : checks solutions found by extrema +//======================================================================= +static Standard_Boolean checkSolution (const Extrema_ExtPS& theExtrema, + const Handle(Adaptor3d_HSurface)& theSurf, + const Standard_Real theUPeriod, + const Standard_Real theVPeriod, + const Standard_Integer theNbU, + const Standard_Integer theNbV, + const gp_Pnt& thePoint, + const Standard_Real theProjTol, + const Standard_Real theDist, + gp_Pnt2d& theSolution) +{ + if (!theExtrema.IsDone() || !theExtrema.NbExt()) + return Standard_False; + + Standard_Real aDist2Min = RealLast(); + Standard_Integer iGoodValue = -1; + + for (Standard_Integer i = 1; i <= theExtrema.NbExt(); i++) + { + if (aDist2Min > theExtrema.SquareDistance(i)) + { + aDist2Min = theExtrema.SquareDistance(i); + iGoodValue = i; + } + } + + if (iGoodValue < 1) + return Standard_False; + + return checkSolution (theExtrema.Point (iGoodValue), theExtrema.SquareDistance (iGoodValue), + theSurf, theUPeriod, theVPeriod, theNbU, theNbV, + thePoint, theProjTol, theDist, theSolution); +} + + //======================================================================= //function : Value //purpose : (OCC217 - apo)- Compute Point2d that project on polar surface() 3D @@ -298,10 +366,8 @@ static gp_Pnt2d Function_Value(const Standard_Real theU, } // Non-analytical case. - Standard_Real Dist2Min = RealLast(); Standard_Real uperiod = theData.myPeriod[0], - vperiod = theData.myPeriod[1], - u, v; + vperiod = theData.myPeriod[1]; // U0 and V0 are the points within the initialized period. if(U0 < Uinf) @@ -379,36 +445,31 @@ static gp_Pnt2d Function_Value(const Standard_Real theU, locext.Perform(p, U0, V0); if (locext.IsDone()) { - locext.Point().Parameter(u, v); - Dist2Min = anOrthogSqValue(p, theData.mySurf, u, v); - if (Dist2Min < theData.mySqProjOrtTol && // Point is projection. - locext.SquareDistance() < aSurfPntDist + Precision::SquareConfusion()) // Point better than initial. + gp_Pnt2d pnt; + if (checkSolution (locext.Point(), locext.SquareDistance(), + theData.mySurf, uperiod, vperiod, decalU, decalV, + p, theData.mySqProjOrtTol, aSurfPntDist, pnt)) { - gp_Pnt2d pnt(u - decalU*uperiod,v - decalV*vperiod); return pnt; } } - // Perform whole param space search. - Extrema_ExtPS ext(p, SurfLittle, theData.myTolU, theData.myTolV); + // Perform search on the whole parametric space using preinitialized extrema. + theData.myGlobExtPS.Perform (p, uInfLi, uSupLi, vInfLi, vSupLi); + gp_Pnt2d pnt; + if (checkSolution (theData.myGlobExtPS, theData.mySurf, uperiod, vperiod, decalU, decalV, + p, theData.mySqProjOrtTol, aSurfPntDist, pnt)) + { + return pnt; + } + + // Perform search on the decreased parametric space. + Extrema_ExtPS ext(p, SurfLittle, theData.myTolU, theData.myTolV, Extrema_ExtFlag_MIN); if (ext.IsDone() && ext.NbExt() >= 1) { - Dist2Min = ext.SquareDistance(1); - Standard_Integer GoodValue = 1; - for (Standard_Integer i = 2 ; i <= ext.NbExt() ; i++ ) + if (checkSolution (ext, theData.mySurf, uperiod, vperiod, decalU, decalV, + p, theData.mySqProjOrtTol, aSurfPntDist, pnt)) { - if( Dist2Min > ext.SquareDistance(i)) - { - Dist2Min = ext.SquareDistance(i); - GoodValue = i; - } - } - ext.Point(GoodValue).Parameter(u, v); - Dist2Min = anOrthogSqValue(p, theData.mySurf, u, v); - if (Dist2Min < theData.mySqProjOrtTol && // Point is projection. - ext.SquareDistance(GoodValue) < aSurfPntDist + Precision::SquareConfusion()) // Point better than initial. - { - gp_Pnt2d pnt(u - decalU*uperiod,v - decalV*vperiod); return pnt; } } @@ -445,6 +506,14 @@ class ProjLib_PolarFunction : public AppCont_Function myStruct.mySqProjOrtTol = 10000.0 * Tol3d * Tol3d; myStruct.myTolU = Surf->UResolution(Tol3d); myStruct.myTolV = Surf->VResolution(Tol3d); + + Standard_Real Uinf, Usup, Vinf, Vsup; + Uinf = Surf->Surface().FirstUParameter(); + Usup = Surf->Surface().LastUParameter(); + Vinf = Surf->Surface().FirstVParameter(); + Vsup = Surf->Surface().LastVParameter(); + myStruct.myGlobExtPS.Initialize (Surf->Surface(), Uinf, Usup, Vinf, Vsup, myStruct.myTolU, myStruct.myTolV); + myStruct.myGlobExtPS.SetFlag (Extrema_ExtFlag_MIN); } ~ProjLib_PolarFunction() {} -- 2.39.5