// Copyright (c) 1995-1999 Matra Datavision // Copyright (c) 1999-2014 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_GCurveLocator_HeaderFile #define _Extrema_GCurveLocator_HeaderFile #include "Standard.hxx" #include "Standard_Real.hxx" #include "Standard_DefineAlloc.hxx" #include "Standard_OutOfRange.hxx" #include //! Template class for locating the closest point on a curve to a given point. //! Among a set of sampled points on the curve, finds the one closest to the target. //! //! @tparam TheCurve the curve type //! @tparam TheCurveTool the curve tool providing curve operations //! @tparam ThePOnC the point-on-curve type //! @tparam ThePoint the point type (gp_Pnt or gp_Pnt2d) template class Extrema_GCurveLocator { public: DEFINE_STANDARD_ALLOC //! Among a set of points {C(ui), i=1,NbU}, locate the point //! P=C(uj) such that: //! distance(P,C) = Min{distance(P,C(ui))} //! @param theP the target point //! @param theC the curve to sample //! @param theNbU the number of sample points //! @param thePapp the result point on curve static void Locate(const ThePoint& theP, const TheCurve& theC, const int theNbU, ThePOnC& thePapp) { if (theNbU < 2) { throw Standard_OutOfRange(); } double aU = TheCurveTool::FirstParameter(theC); double aPasU = (TheCurveTool::LastParameter(theC) - aU) / (theNbU - 1); double aDist2Min = RealLast(); double aUMin = 0; ThePoint aPntMin; double aDist2; ThePoint aPt; for (int aNoSample = 1; aNoSample < theNbU; aNoSample++, aU += aPasU) { aPt = TheCurveTool::Value(theC, aU); aDist2 = aPt.SquareDistance(theP); if (aDist2 < aDist2Min) { aDist2Min = aDist2; aUMin = aU; aPntMin = aPt; } } thePapp.SetValues(aUMin, aPntMin); } //! Among a set of points {C(ui), i=1,NbU}, locate the point //! P=C(uj) such that: //! distance(P,C) = Min{distance(P,C(ui))} //! The search is done between theUmin and theUsup. //! @param theP the target point //! @param theC the curve to sample //! @param theNbU the number of sample points //! @param theUmin the minimum parameter value //! @param theUsup the maximum parameter value //! @param thePapp the result point on curve static void Locate(const ThePoint& theP, const TheCurve& theC, const int theNbU, const double theUmin, const double theUsup, ThePOnC& thePapp) { if (theNbU < 2) { throw Standard_OutOfRange(); } double aUinf = TheCurveTool::FirstParameter(theC); double aUlast = TheCurveTool::LastParameter(theC); double aU1 = std::min(aUinf, aUlast); double aU2 = std::max(aUinf, aUlast); double aU11 = std::min(theUmin, theUsup); double aU12 = std::max(theUmin, theUsup); if (aU11 < aU1 - RealEpsilon()) aU11 = aU1; if (aU12 > aU2 + RealEpsilon()) aU12 = aU2; double aU = aU11; double aPasU = (aU12 - aU) / (theNbU - 1); double aDist2Min = RealLast(); double aUMin = 0; ThePoint aPntMin; double aDist2; ThePoint aPt; for (int aNoSample = 1; aNoSample < theNbU; aNoSample++, aU += aPasU) { aPt = TheCurveTool::Value(theC, aU); aDist2 = aPt.SquareDistance(theP); if (aDist2 < aDist2Min) { aDist2Min = aDist2; aUMin = aU; aPntMin = aPt; } } thePapp.SetValues(aUMin, aPntMin); } }; #endif // _Extrema_GCurveLocator_HeaderFile