Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-28 09:19:58

0001 // Copyright (c) 2025 OPEN CASCADE SAS
0002 //
0003 // This file is part of Open CASCADE Technology software library.
0004 //
0005 // This library is free software; you can redistribute it and/or modify it under
0006 // the terms of the GNU Lesser General Public License version 2.1 as published
0007 // by the Free Software Foundation, with special exception defined in the file
0008 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0009 // distribution for complete text of the license and disclaimer of any warranty.
0010 //
0011 // Alternatively, this file may be used under the terms of Open CASCADE
0012 // commercial license or contractual agreement.
0013 
0014 #ifndef _ExtremaPC_Line_HeaderFile
0015 #define _ExtremaPC_Line_HeaderFile
0016 
0017 #include <ExtremaPC.hxx>
0018 #include <gp_Lin.hxx>
0019 #include <gp_Pnt.hxx>
0020 #include <gp_Vec.hxx>
0021 #include <Standard_DefineAlloc.hxx>
0022 
0023 #include <algorithm>
0024 #include <optional>
0025 
0026 //! @brief Point-Line extrema computation.
0027 //!
0028 //! Computes the extremum (closest point) between a 3D point and a line.
0029 //! Uses direct analytical projection via dot product.
0030 //!
0031 //! For a line defined by origin O and direction D, the closest point
0032 //! to P is at parameter u = (P - O) . D, which gives the minimum distance.
0033 //!
0034 //! The domain is fixed at construction time for optimal performance.
0035 //! For unbounded line, construct without domain or with nullopt.
0036 //!
0037 //! @note Lines always have exactly one extremum (minimum) if within bounds.
0038 class ExtremaPC_Line
0039 {
0040 public:
0041   DEFINE_STANDARD_ALLOC
0042 
0043   //! Constructor with line geometry (unbounded).
0044   //! @param[in] theLine the line to compute extrema for
0045   explicit ExtremaPC_Line(const gp_Lin& theLine)
0046       : myLine(theLine),
0047         myDomain(std::nullopt)
0048   {
0049   }
0050 
0051   //! Constructor with line geometry and parameter domain.
0052   //! @param[in] theLine the line to compute extrema for
0053   //! @param[in] theDomain parameter domain (fixed for all queries)
0054   ExtremaPC_Line(const gp_Lin& theLine, const ExtremaPC::Domain1D& theDomain)
0055       : myLine(theLine),
0056         myDomain(theDomain.IsFinite() ? std::optional<ExtremaPC::Domain1D>(theDomain)
0057                                       : std::nullopt)
0058   {
0059   }
0060 
0061   //! Copy constructor is deleted.
0062   ExtremaPC_Line(const ExtremaPC_Line&) = delete;
0063 
0064   //! Copy assignment operator is deleted.
0065   ExtremaPC_Line& operator=(const ExtremaPC_Line&) = delete;
0066 
0067   //! Move constructor.
0068   ExtremaPC_Line(ExtremaPC_Line&&) = default;
0069 
0070   //! Move assignment operator.
0071   ExtremaPC_Line& operator=(ExtremaPC_Line&&) = default;
0072 
0073   //! Evaluates point on line at parameter.
0074   //! @param theU parameter
0075   //! @return point on line
0076   gp_Pnt Value(double theU) const
0077   {
0078     return myLine.Location().Translated(theU * gp_Vec(myLine.Direction()));
0079   }
0080 
0081   //! Returns true if domain is bounded.
0082   bool IsBounded() const { return myDomain.has_value(); }
0083 
0084   //! Returns the domain (only valid if IsBounded() is true).
0085   const ExtremaPC::Domain1D& Domain() const { return *myDomain; }
0086 
0087   //! Compute extrema between point P and the line.
0088   //! Uses domain specified at construction time.
0089   //! @param theP query point
0090   //! @param theTol tolerance for parameter comparison
0091   //! @param theMode search mode (unused for lines - always returns minimum)
0092   //! @return const reference to result containing the extremum
0093   [[nodiscard]] const ExtremaPC::Result& Perform(
0094     const gp_Pnt&         theP,
0095     double                theTol,
0096     ExtremaPC::SearchMode theMode = ExtremaPC::SearchMode::MinMax) const
0097   {
0098     (void)theMode; // Lines always have exactly one extremum (minimum)
0099 
0100     myResult.Clear();
0101 
0102     // Compute projection parameter: u = (P - O) . Direction
0103     const gp_Dir& aDir    = myLine.Direction();
0104     const gp_Pnt& aOrigin = myLine.Location();
0105     gp_Vec        aVec(aOrigin, theP);
0106     double        aU = aVec.Dot(gp_Vec(aDir));
0107 
0108     // Check bounds if domain is specified
0109     if (myDomain.has_value())
0110     {
0111       if (aU < myDomain->Min - theTol || aU > myDomain->Max + theTol)
0112       {
0113         // Projection is outside bounds - no interior extremum
0114         myResult.Status = ExtremaPC::Status::OK;
0115         return myResult;
0116       }
0117       // Clamp to bounds
0118       aU = std::clamp(aU, myDomain->Min, myDomain->Max);
0119     }
0120 
0121     // Compute point on line at projected parameter
0122     gp_Pnt aPtOnLine = aOrigin.Translated(aU * gp_Vec(aDir));
0123 
0124     // Store result
0125     ExtremaPC::ExtremumResult anExt;
0126     anExt.Parameter      = aU;
0127     anExt.Point          = aPtOnLine;
0128     anExt.SquareDistance = theP.SquareDistance(aPtOnLine);
0129     anExt.IsMinimum      = true;
0130 
0131     myResult.Extrema.Append(anExt);
0132     myResult.Status = ExtremaPC::Status::OK;
0133     return myResult;
0134   }
0135 
0136   //! Compute extrema between point P and the line segment including endpoints.
0137   //! Uses domain specified at construction time.
0138   //! @param theP query point
0139   //! @param theTol tolerance for parameter comparison
0140   //! @param theMode search mode (MinMax, Min, or Max)
0141   //! @return const reference to result containing interior + endpoint extrema
0142   [[nodiscard]] const ExtremaPC::Result& PerformWithEndpoints(
0143     const gp_Pnt&         theP,
0144     double                theTol,
0145     ExtremaPC::SearchMode theMode = ExtremaPC::SearchMode::MinMax) const
0146   {
0147     (void)Perform(theP, theTol, theMode);
0148 
0149     if (myResult.Status == ExtremaPC::Status::OK && myDomain.has_value())
0150     {
0151       ExtremaPC::AddEndpointExtrema(myResult, theP, *myDomain, *this, theTol, theMode);
0152     }
0153 
0154     return myResult;
0155   }
0156 
0157   //! Returns the line geometry.
0158   const gp_Lin& Line() const { return myLine; }
0159 
0160 private:
0161   gp_Lin                             myLine;   //!< Line geometry
0162   std::optional<ExtremaPC::Domain1D> myDomain; //!< Parameter domain (nullopt for unbounded)
0163   mutable ExtremaPC::Result          myResult; //!< Reusable result storage
0164 };
0165 
0166 #endif // _ExtremaPC_Line_HeaderFile