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);
}
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();
//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:
default:
{
- myExtPS->Perform (thePoint);
+ myExtPS->Perform (thePoint, myLocUMin, myLocUMax, myLocVMin, myLocVMax);
myDone = myExtPS->IsDone();
if (myDone)
{
//! 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;
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;
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)
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");
//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
// 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
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)));
}
}
// Builder for low-level BVH sets
opencascade::handle<BVH_LinearBuilder<Standard_Real, 3> > aLBuilder = new BVH_LinearBuilder<Standard_Real, 3>();
- myBVHBoxSet = new BVH_IndexedBoxSet<Standard_Real, 3, Handle (Extrema_GenExtPS_GridCellBoxSet)> (
+ myBVHBoxSet = new BVH_IndexedBoxSet<Standard_Real, 3, Extrema_GenExtPS_LocalizedSurf> (
new BVH_LinearBuilder<Standard_Real, 3> (BVH_Constants_LeafNodeSizeSingle));
// create hierarchy of BVH trees
{
for (Standard_Integer iV = V1; iV <= V2; ++iV)
{
- aGridSet->Add (GridCell (iU, iV), BVH_Box<Standard_Real, 3>());
+ aGridSet->Add (Extrema_GenExtPS_GridCell (iU, iV), BVH_Box<Standard_Real, 3>());
}
}
V1 = V2 + 1;
- myBVHBoxSet->Add (aGridSet, BVH_Box<Standard_Real, 3>());
+ 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<Standard_Real, 3>());
}
U1 = U2 + 1;
V1 = 1;
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;
//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);
}
{
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);
}
else
{
- GridCell aCell = myBVHSet->Element (theIndex);
+ Extrema_GenExtPS_GridCell aCell = myBVHSet->Element (theIndex);
return FindSolution (aCell.UIndex, aCell.VIndex, myTarget);
}
}
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);
//! 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 <Standard_Real, 3, GridCell> Extrema_GenExtPS_GridCellBoxSet;
+typedef BVH_BoxSet <Standard_Real, 3, Extrema_GenExtPS_GridCell> Extrema_GenExtPS_GridCellBoxSet;
//! It calculates the extreme distances between a point and a surface.
//! 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.
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;
}
};
+ //! 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
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
Standard_Real mySqDistance; //!< Min/Max found square distance used in BVH tree traverse
opencascade::handle
- <BVH_IndexedBoxSet<Standard_Real, 3, Handle(Extrema_GenExtPS_GridCellBoxSet)> > myBVHBoxSet; //!< High-level BVH of BVH organized grid cells
+ <BVH_IndexedBoxSet<Standard_Real, 3, Extrema_GenExtPS_LocalizedSurf> > myBVHBoxSet; //!< High-level BVH of BVH organized grid cells
// Results
- std::vector <ExtPSResult> mySolutions; //!< Found solutions (sorted first by distance to target point,
- //! second by the ascending U,V coordinates)
+ std::vector <Extrema_GenExtPS_ExtPSResult> mySolutions; //!< Found solutions (sorted first by distance to target point,
+ //! second by the ascending U,V coordinates)
Standard_Boolean myIsDone; //!< Done/Not done flag
};
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;
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(<Surf>) 3D<Curve>
}
// 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)
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;
}
}
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() {}