Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:03:19

0001 // Created by: Eugeny MALTCHIKOV
0002 // Created on: 2019-04-17
0003 // Copyright (c) 2019 OPEN CASCADE SAS
0004 //
0005 // This file is part of Open CASCADE Technology software library.
0006 //
0007 // This library is free software; you can redistribute it and/or modify it under
0008 // the terms of the GNU Lesser General Public License version 2.1 as published
0009 // by the Free Software Foundation, with special exception defined in the file
0010 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0011 // distribution for complete text of the license and disclaimer of any warranty.
0012 //
0013 // Alternatively, this file may be used under the terms of Open CASCADE
0014 // commercial license or contractual agreement.
0015 
0016 #ifndef _BVH_Tools_Header
0017 #define _BVH_Tools_Header
0018 
0019 #include <BVH_Box.hxx>
0020 #include <BVH_Ray.hxx>
0021 #include <BVH_Types.hxx>
0022 
0023 //! Defines a set of static methods operating with points and bounding boxes.
0024 //! \tparam T Numeric data type
0025 //! \tparam N Vector dimension
0026 template <class T, int N>
0027 class BVH_Tools
0028 {
0029 public: //! @name public types
0030 
0031   typedef typename BVH::VectorType<T, N>::Type BVH_VecNt;
0032 
0033 public:
0034 
0035   enum BVH_PrjStateInTriangle
0036   {
0037     BVH_PrjStateInTriangle_VERTEX,
0038     BVH_PrjStateInTriangle_EDGE,
0039     BVH_PrjStateInTriangle_INNER
0040   };
0041 
0042 public: //! @name Box-Box Square distance
0043 
0044   //! Computes Square distance between Axis aligned bounding boxes
0045   static T BoxBoxSquareDistance (const BVH_Box<T, N>& theBox1,
0046                                  const BVH_Box<T, N>& theBox2)
0047   {
0048     if (!theBox1.IsValid() || !theBox2.IsValid())
0049     {
0050       return static_cast<T>(0);
0051     }
0052     return BoxBoxSquareDistance (theBox1.CornerMin(), theBox1.CornerMax(),
0053                                  theBox2.CornerMin(), theBox2.CornerMax());
0054   }
0055 
0056   //! Computes Square distance between Axis aligned bounding boxes
0057   static T BoxBoxSquareDistance (const BVH_VecNt& theCMin1,
0058                                  const BVH_VecNt& theCMax1,
0059                                  const BVH_VecNt& theCMin2,
0060                                  const BVH_VecNt& theCMax2)
0061   {
0062     T aDist = 0;
0063     for (int i = 0; i < N; ++i)
0064     {
0065       if      (theCMin1[i] > theCMax2[i]) { T d = theCMin1[i] - theCMax2[i]; d *= d; aDist += d; }
0066       else if (theCMax1[i] < theCMin2[i]) { T d = theCMin2[i] - theCMax1[i]; d *= d; aDist += d; }
0067     }
0068     return aDist;
0069   }
0070 
0071 public: //! @name Point-Box Square distance
0072 
0073   //! Computes square distance between point and bounding box
0074   static T PointBoxSquareDistance (const BVH_VecNt& thePoint,
0075                                    const BVH_Box<T, N>& theBox)
0076   {
0077     if (!theBox.IsValid())
0078     {
0079       return static_cast<T>(0);
0080     }
0081     return PointBoxSquareDistance (thePoint,
0082                                    theBox.CornerMin(),
0083                                    theBox.CornerMax());
0084   }
0085 
0086   //! Computes square distance between point and bounding box
0087   static T PointBoxSquareDistance (const BVH_VecNt& thePoint,
0088                                    const BVH_VecNt& theCMin,
0089                                    const BVH_VecNt& theCMax)
0090   {
0091     T aDist = 0;
0092     for (int i = 0; i < N; ++i)
0093     {
0094       if      (thePoint[i] < theCMin[i]) { T d = theCMin[i] - thePoint[i]; d *= d; aDist += d; }
0095       else if (thePoint[i] > theCMax[i]) { T d = thePoint[i] - theCMax[i]; d *= d; aDist += d; }
0096     }
0097     return aDist;
0098   }
0099 
0100 public: //! @name Point-Box projection
0101 
0102   //! Computes projection of point on bounding box
0103   static BVH_VecNt PointBoxProjection (const BVH_VecNt& thePoint,
0104                                        const BVH_Box<T, N>& theBox)
0105   {
0106     if (!theBox.IsValid())
0107     {
0108       return thePoint;
0109     }
0110     return PointBoxProjection (thePoint,
0111                                theBox.CornerMin(),
0112                                theBox.CornerMax());
0113   }
0114 
0115   //! Computes projection of point on bounding box
0116   static BVH_VecNt PointBoxProjection (const BVH_VecNt& thePoint,
0117                                        const BVH_VecNt& theCMin,
0118                                        const BVH_VecNt& theCMax)
0119   {
0120     return thePoint.cwiseMax (theCMin).cwiseMin (theCMax);
0121   }
0122 
0123 public: //! @name Point-Triangle Square distance
0124 
0125   //! Find nearest point on a triangle for the given point
0126   static BVH_VecNt PointTriangleProjection (const BVH_VecNt& thePoint,
0127                                             const BVH_VecNt& theNode0,
0128                                             const BVH_VecNt& theNode1,
0129                                             const BVH_VecNt& theNode2,
0130                                             BVH_PrjStateInTriangle* thePrjState = nullptr,
0131                                             Standard_Integer* theNumberOfFirstNode = nullptr,
0132                                             Standard_Integer* theNumberOfLastNode = nullptr)
0133   {
0134     const BVH_VecNt aAB = theNode1 - theNode0;
0135     const BVH_VecNt aAC = theNode2 - theNode0;
0136     const BVH_VecNt aAP = thePoint - theNode0;
0137   
0138     T aABdotAP = aAB.Dot(aAP);
0139     T aACdotAP = aAC.Dot(aAP);
0140   
0141     if (aABdotAP <= 0. && aACdotAP <= 0.)
0142     {
0143       if (thePrjState != nullptr)
0144       {
0145         *thePrjState = BVH_PrjStateInTriangle_VERTEX;
0146         *theNumberOfFirstNode = 0;
0147         *theNumberOfLastNode = 0;
0148       }
0149       return theNode0;
0150     }
0151 
0152     const BVH_VecNt aBC = theNode2 - theNode1;
0153     const BVH_VecNt aBP = thePoint - theNode1;
0154 
0155     T aBAdotBP = -(aAB.Dot (aBP));
0156     T aBCdotBP = (aBC.Dot (aBP));
0157 
0158     if (aBAdotBP <= 0. && aBCdotBP <= 0.)
0159     {
0160       if (thePrjState != nullptr)
0161       {
0162         *thePrjState = BVH_PrjStateInTriangle_VERTEX;
0163         *theNumberOfFirstNode = 1;
0164         *theNumberOfLastNode = 1;
0165       }
0166       return theNode1;
0167     }
0168 
0169     const BVH_VecNt aCP = thePoint - theNode2;
0170 
0171     T aCBdotCP = -(aBC.Dot (aCP));
0172     T aCAdotCP = -(aAC.Dot (aCP));
0173 
0174     if (aCAdotCP <= 0. && aCBdotCP <= 0.)
0175     {
0176       if (thePrjState != nullptr)
0177       {
0178         *thePrjState = BVH_PrjStateInTriangle_VERTEX;
0179         *theNumberOfFirstNode = 2;
0180         *theNumberOfLastNode = 2;
0181       }
0182       return theNode2;
0183     }
0184 
0185     T aACdotBP = (aAC.Dot (aBP));
0186 
0187     T aVC = aABdotAP * aACdotBP + aBAdotBP * aACdotAP;
0188 
0189     if (aVC <= 0. && aABdotAP > 0. && aBAdotBP > 0.)
0190     {
0191       if (thePrjState != nullptr)
0192       {
0193         *thePrjState = BVH_PrjStateInTriangle_EDGE;
0194         *theNumberOfFirstNode = 0;
0195         *theNumberOfLastNode = 1;
0196       }
0197       return theNode0 + aAB * (aABdotAP / (aABdotAP + aBAdotBP));
0198     }
0199 
0200     T aABdotCP = (aAB.Dot (aCP));
0201 
0202     T aVA = aBAdotBP * aCAdotCP - aABdotCP * aACdotBP;
0203 
0204     if (aVA <= 0. && aBCdotBP > 0. && aCBdotCP > 0.)
0205     {
0206       if (thePrjState != nullptr)
0207       {
0208         *thePrjState = BVH_PrjStateInTriangle_EDGE;
0209         *theNumberOfFirstNode = 1;
0210         *theNumberOfLastNode = 2;
0211       }
0212       return theNode1 + aBC * (aBCdotBP / (aBCdotBP + aCBdotCP));
0213     }
0214 
0215     T aVB = aABdotCP * aACdotAP + aABdotAP * aCAdotCP;
0216 
0217     if (aVB <= 0. && aACdotAP > 0. && aCAdotCP > 0.)
0218     {
0219       if (thePrjState != nullptr)
0220       {
0221         *thePrjState = BVH_PrjStateInTriangle_EDGE;
0222         *theNumberOfFirstNode = 2;
0223         *theNumberOfLastNode = 0;
0224       }
0225       return theNode0 + aAC * (aACdotAP / (aACdotAP + aCAdotCP));
0226     }
0227 
0228     T aNorm = aVA + aVB + aVC;
0229 
0230     if (thePrjState != nullptr)
0231     {
0232       *thePrjState = BVH_PrjStateInTriangle_INNER;
0233     }
0234 
0235     return (theNode0 * aVA + theNode1 * aVB + theNode2 * aVC) / aNorm;
0236   }
0237 
0238   //! Computes square distance between point and triangle
0239   static T PointTriangleSquareDistance (const BVH_VecNt& thePoint,
0240                                         const BVH_VecNt& theNode0,
0241                                         const BVH_VecNt& theNode1,
0242                                         const BVH_VecNt& theNode2)
0243   {
0244     const BVH_VecNt aProj = PointTriangleProjection(thePoint, theNode0, theNode1, theNode2);
0245     const BVH_VecNt aPP = aProj - thePoint;
0246     return aPP.Dot(aPP);
0247   }
0248 
0249 public: //! @name Ray-Box Intersection
0250 
0251   //! Computes hit time of ray-box intersection
0252   static Standard_Boolean RayBoxIntersection (const BVH_Ray<T, N>& theRay,
0253                                               const BVH_Box<T, N>& theBox,
0254                                               T& theTimeEnter,
0255                                               T& theTimeLeave)
0256   {
0257     if (!theBox.IsValid())
0258     {
0259       return Standard_False;
0260     }
0261     return RayBoxIntersection (theRay, theBox.CornerMin(), theBox.CornerMax(), theTimeEnter, theTimeLeave);
0262   }
0263 
0264   //! Computes hit time of ray-box intersection
0265   static Standard_Boolean RayBoxIntersection (const BVH_Ray<T, N>& theRay,
0266                                               const BVH_VecNt& theBoxCMin,
0267                                               const BVH_VecNt& theBoxCMax,
0268                                               T& theTimeEnter,
0269                                               T& theTimeLeave)
0270   {
0271     return RayBoxIntersection (theRay.Origin, theRay.Direct,
0272                                theBoxCMin, theBoxCMax, theTimeEnter, theTimeLeave);
0273   }
0274 
0275   //! Computes hit time of ray-box intersection
0276   static Standard_Boolean RayBoxIntersection (const BVH_VecNt& theRayOrigin,
0277                                               const BVH_VecNt& theRayDirection,
0278                                               const BVH_Box<T, N>& theBox,
0279                                               T& theTimeEnter,
0280                                               T& theTimeLeave)
0281   {
0282     if (!theBox.IsValid())
0283     {
0284       return Standard_False;
0285     }
0286     return RayBoxIntersection (theRayOrigin, theRayDirection,
0287                                theBox.CornerMin(), theBox.CornerMax(),
0288                                theTimeEnter, theTimeLeave);
0289   }
0290 
0291   //! Computes hit time of ray-box intersection
0292   static Standard_Boolean RayBoxIntersection (const BVH_VecNt& theRayOrigin,
0293                                               const BVH_VecNt& theRayDirection,
0294                                               const BVH_VecNt& theBoxCMin,
0295                                               const BVH_VecNt& theBoxCMax,
0296                                               T& theTimeEnter,
0297                                               T& theTimeLeave)
0298   {
0299     BVH_VecNt aNodeMin, aNodeMax;
0300     for (int i = 0; i < N; ++i)
0301     {
0302       if (theRayDirection[i] == 0)
0303       {
0304         aNodeMin[i] = (theBoxCMin[i] - theRayOrigin[i]) <= 0 ?
0305                        (std::numeric_limits<T>::min)() : (std::numeric_limits<T>::max)();
0306         aNodeMax[i] = (theBoxCMax[i] - theRayOrigin[i]) < 0 ?
0307                        (std::numeric_limits<T>::min)() : (std::numeric_limits<T>::max)();
0308       }
0309       else
0310       {
0311         aNodeMin[i] = (theBoxCMin[i] - theRayOrigin[i]) / theRayDirection[i];
0312         aNodeMax[i] = (theBoxCMax[i] - theRayOrigin[i]) / theRayDirection[i];
0313       }
0314     }
0315 
0316     BVH_VecNt aTimeMin, aTimeMax;
0317     for (int i = 0; i < N; ++i)
0318     {
0319       aTimeMin[i] = Min (aNodeMin[i], aNodeMax[i]);
0320       aTimeMax[i] = Max (aNodeMin[i], aNodeMax[i]);
0321     }
0322 
0323     T aTimeEnter = Max (aTimeMin[0], Max (aTimeMin[1], aTimeMin[2]));
0324     T aTimeLeave = Min (aTimeMax[0], Min (aTimeMax[1], aTimeMax[2]));
0325 
0326     Standard_Boolean hasIntersection = aTimeEnter <= aTimeLeave && aTimeLeave >= 0;
0327     if (hasIntersection)
0328     {
0329       theTimeEnter = aTimeEnter;
0330       theTimeLeave = aTimeLeave;
0331     }
0332 
0333     return hasIntersection;
0334   }
0335 };
0336 
0337 #endif