File indexing completed on 2026-06-27 08:39:15
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
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
0024
0025
0026 template <class T, int N>
0027 class BVH_Tools
0028 {
0029 public:
0030 typedef typename BVH::VectorType<T, N>::Type BVH_VecNt;
0031
0032 public:
0033 enum BVH_PrjStateInTriangle
0034 {
0035 BVH_PrjStateInTriangle_VERTEX,
0036 BVH_PrjStateInTriangle_EDGE,
0037 BVH_PrjStateInTriangle_INNER
0038 };
0039
0040 public:
0041
0042 static T BoxBoxSquareDistance(const BVH_Box<T, N>& theBox1, const BVH_Box<T, N>& theBox2)
0043 {
0044 if (!theBox1.IsValid() || !theBox2.IsValid())
0045 {
0046 return static_cast<T>(0);
0047 }
0048 return BoxBoxSquareDistance(theBox1.CornerMin(),
0049 theBox1.CornerMax(),
0050 theBox2.CornerMin(),
0051 theBox2.CornerMax());
0052 }
0053
0054
0055 static T BoxBoxSquareDistance(const BVH_VecNt& theCMin1,
0056 const BVH_VecNt& theCMax1,
0057 const BVH_VecNt& theCMin2,
0058 const BVH_VecNt& theCMax2)
0059 {
0060 T aDist = 0;
0061 for (int i = 0; i < N; ++i)
0062 {
0063 if (theCMin1[i] > theCMax2[i])
0064 {
0065 T d = theCMin1[i] - theCMax2[i];
0066 d *= d;
0067 aDist += d;
0068 }
0069 else if (theCMax1[i] < theCMin2[i])
0070 {
0071 T d = theCMin2[i] - theCMax1[i];
0072 d *= d;
0073 aDist += d;
0074 }
0075 }
0076 return aDist;
0077 }
0078
0079 public:
0080
0081 static T PointBoxSquareDistance(const BVH_VecNt& thePoint, const BVH_Box<T, N>& theBox)
0082 {
0083 if (!theBox.IsValid())
0084 {
0085 return static_cast<T>(0);
0086 }
0087 return PointBoxSquareDistance(thePoint, theBox.CornerMin(), theBox.CornerMax());
0088 }
0089
0090
0091 static T PointBoxSquareDistance(const BVH_VecNt& thePoint,
0092 const BVH_VecNt& theCMin,
0093 const BVH_VecNt& theCMax)
0094 {
0095 T aDist = 0;
0096 for (int i = 0; i < N; ++i)
0097 {
0098 if (thePoint[i] < theCMin[i])
0099 {
0100 T d = theCMin[i] - thePoint[i];
0101 d *= d;
0102 aDist += d;
0103 }
0104 else if (thePoint[i] > theCMax[i])
0105 {
0106 T d = thePoint[i] - theCMax[i];
0107 d *= d;
0108 aDist += d;
0109 }
0110 }
0111 return aDist;
0112 }
0113
0114 public:
0115
0116 static BVH_VecNt PointBoxProjection(const BVH_VecNt& thePoint, const BVH_Box<T, N>& theBox)
0117 {
0118 if (!theBox.IsValid())
0119 {
0120 return thePoint;
0121 }
0122 return PointBoxProjection(thePoint, theBox.CornerMin(), theBox.CornerMax());
0123 }
0124
0125
0126 static BVH_VecNt PointBoxProjection(const BVH_VecNt& thePoint,
0127 const BVH_VecNt& theCMin,
0128 const BVH_VecNt& theCMax)
0129 {
0130 return thePoint.cwiseMax(theCMin).cwiseMin(theCMax);
0131 }
0132
0133 public:
0134
0135 static BVH_VecNt PointTriangleProjection(const BVH_VecNt& thePoint,
0136 const BVH_VecNt& theNode0,
0137 const BVH_VecNt& theNode1,
0138 const BVH_VecNt& theNode2,
0139 BVH_PrjStateInTriangle* thePrjState = nullptr,
0140 Standard_Integer* theNumberOfFirstNode = nullptr,
0141 Standard_Integer* theNumberOfLastNode = nullptr)
0142 {
0143 const BVH_VecNt aAB = theNode1 - theNode0;
0144 const BVH_VecNt aAC = theNode2 - theNode0;
0145 const BVH_VecNt aAP = thePoint - theNode0;
0146
0147 T aABdotAP = aAB.Dot(aAP);
0148 T aACdotAP = aAC.Dot(aAP);
0149
0150 if (aABdotAP <= 0. && aACdotAP <= 0.)
0151 {
0152 if (thePrjState != nullptr)
0153 {
0154 *thePrjState = BVH_PrjStateInTriangle_VERTEX;
0155 *theNumberOfFirstNode = 0;
0156 *theNumberOfLastNode = 0;
0157 }
0158 return theNode0;
0159 }
0160
0161 const BVH_VecNt aBC = theNode2 - theNode1;
0162 const BVH_VecNt aBP = thePoint - theNode1;
0163
0164 T aBAdotBP = -(aAB.Dot(aBP));
0165 T aBCdotBP = (aBC.Dot(aBP));
0166
0167 if (aBAdotBP <= 0. && aBCdotBP <= 0.)
0168 {
0169 if (thePrjState != nullptr)
0170 {
0171 *thePrjState = BVH_PrjStateInTriangle_VERTEX;
0172 *theNumberOfFirstNode = 1;
0173 *theNumberOfLastNode = 1;
0174 }
0175 return theNode1;
0176 }
0177
0178 const BVH_VecNt aCP = thePoint - theNode2;
0179
0180 T aCBdotCP = -(aBC.Dot(aCP));
0181 T aCAdotCP = -(aAC.Dot(aCP));
0182
0183 if (aCAdotCP <= 0. && aCBdotCP <= 0.)
0184 {
0185 if (thePrjState != nullptr)
0186 {
0187 *thePrjState = BVH_PrjStateInTriangle_VERTEX;
0188 *theNumberOfFirstNode = 2;
0189 *theNumberOfLastNode = 2;
0190 }
0191 return theNode2;
0192 }
0193
0194 T aACdotBP = (aAC.Dot(aBP));
0195
0196 T aVC = aABdotAP * aACdotBP + aBAdotBP * aACdotAP;
0197
0198 if (aVC <= 0. && aABdotAP > 0. && aBAdotBP > 0.)
0199 {
0200 if (thePrjState != nullptr)
0201 {
0202 *thePrjState = BVH_PrjStateInTriangle_EDGE;
0203 *theNumberOfFirstNode = 0;
0204 *theNumberOfLastNode = 1;
0205 }
0206 return theNode0 + aAB * (aABdotAP / (aABdotAP + aBAdotBP));
0207 }
0208
0209 T aABdotCP = (aAB.Dot(aCP));
0210
0211 T aVA = aBAdotBP * aCAdotCP - aABdotCP * aACdotBP;
0212
0213 if (aVA <= 0. && aBCdotBP > 0. && aCBdotCP > 0.)
0214 {
0215 if (thePrjState != nullptr)
0216 {
0217 *thePrjState = BVH_PrjStateInTriangle_EDGE;
0218 *theNumberOfFirstNode = 1;
0219 *theNumberOfLastNode = 2;
0220 }
0221 return theNode1 + aBC * (aBCdotBP / (aBCdotBP + aCBdotCP));
0222 }
0223
0224 T aVB = aABdotCP * aACdotAP + aABdotAP * aCAdotCP;
0225
0226 if (aVB <= 0. && aACdotAP > 0. && aCAdotCP > 0.)
0227 {
0228 if (thePrjState != nullptr)
0229 {
0230 *thePrjState = BVH_PrjStateInTriangle_EDGE;
0231 *theNumberOfFirstNode = 2;
0232 *theNumberOfLastNode = 0;
0233 }
0234 return theNode0 + aAC * (aACdotAP / (aACdotAP + aCAdotCP));
0235 }
0236
0237 T aNorm = aVA + aVB + aVC;
0238
0239 if (thePrjState != nullptr)
0240 {
0241 *thePrjState = BVH_PrjStateInTriangle_INNER;
0242 }
0243
0244 return (theNode0 * aVA + theNode1 * aVB + theNode2 * aVC) / aNorm;
0245 }
0246
0247
0248 static T PointTriangleSquareDistance(const BVH_VecNt& thePoint,
0249 const BVH_VecNt& theNode0,
0250 const BVH_VecNt& theNode1,
0251 const BVH_VecNt& theNode2)
0252 {
0253 const BVH_VecNt aProj = PointTriangleProjection(thePoint, theNode0, theNode1, theNode2);
0254 const BVH_VecNt aPP = aProj - thePoint;
0255 return aPP.Dot(aPP);
0256 }
0257
0258 public:
0259
0260 static Standard_Boolean RayBoxIntersection(const BVH_Ray<T, N>& theRay,
0261 const BVH_Box<T, N>& theBox,
0262 T& theTimeEnter,
0263 T& theTimeLeave)
0264 {
0265 if (!theBox.IsValid())
0266 {
0267 return Standard_False;
0268 }
0269 return RayBoxIntersection(theRay,
0270 theBox.CornerMin(),
0271 theBox.CornerMax(),
0272 theTimeEnter,
0273 theTimeLeave);
0274 }
0275
0276
0277 static Standard_Boolean RayBoxIntersection(const BVH_Ray<T, N>& theRay,
0278 const BVH_VecNt& theBoxCMin,
0279 const BVH_VecNt& theBoxCMax,
0280 T& theTimeEnter,
0281 T& theTimeLeave)
0282 {
0283 return RayBoxIntersection(theRay.Origin,
0284 theRay.Direct,
0285 theBoxCMin,
0286 theBoxCMax,
0287 theTimeEnter,
0288 theTimeLeave);
0289 }
0290
0291
0292 static Standard_Boolean RayBoxIntersection(const BVH_VecNt& theRayOrigin,
0293 const BVH_VecNt& theRayDirection,
0294 const BVH_Box<T, N>& theBox,
0295 T& theTimeEnter,
0296 T& theTimeLeave)
0297 {
0298 if (!theBox.IsValid())
0299 {
0300 return Standard_False;
0301 }
0302 return RayBoxIntersection(theRayOrigin,
0303 theRayDirection,
0304 theBox.CornerMin(),
0305 theBox.CornerMax(),
0306 theTimeEnter,
0307 theTimeLeave);
0308 }
0309
0310
0311 static Standard_Boolean RayBoxIntersection(const BVH_VecNt& theRayOrigin,
0312 const BVH_VecNt& theRayDirection,
0313 const BVH_VecNt& theBoxCMin,
0314 const BVH_VecNt& theBoxCMax,
0315 T& theTimeEnter,
0316 T& theTimeLeave)
0317 {
0318 BVH_VecNt aNodeMin, aNodeMax;
0319 for (int i = 0; i < N; ++i)
0320 {
0321 if (theRayDirection[i] == 0)
0322 {
0323 aNodeMin[i] = (theBoxCMin[i] - theRayOrigin[i]) <= 0 ? (std::numeric_limits<T>::min)()
0324 : (std::numeric_limits<T>::max)();
0325 aNodeMax[i] = (theBoxCMax[i] - theRayOrigin[i]) < 0 ? (std::numeric_limits<T>::min)()
0326 : (std::numeric_limits<T>::max)();
0327 }
0328 else
0329 {
0330 aNodeMin[i] = (theBoxCMin[i] - theRayOrigin[i]) / theRayDirection[i];
0331 aNodeMax[i] = (theBoxCMax[i] - theRayOrigin[i]) / theRayDirection[i];
0332 }
0333 }
0334
0335 BVH_VecNt aTimeMin, aTimeMax;
0336 for (int i = 0; i < N; ++i)
0337 {
0338 aTimeMin[i] = Min(aNodeMin[i], aNodeMax[i]);
0339 aTimeMax[i] = Max(aNodeMin[i], aNodeMax[i]);
0340 }
0341
0342 T aTimeEnter = Max(aTimeMin[0], Max(aTimeMin[1], aTimeMin[2]));
0343 T aTimeLeave = Min(aTimeMax[0], Min(aTimeMax[1], aTimeMax[2]));
0344
0345 Standard_Boolean hasIntersection = aTimeEnter <= aTimeLeave && aTimeLeave >= 0;
0346 if (hasIntersection)
0347 {
0348 theTimeEnter = aTimeEnter;
0349 theTimeLeave = aTimeLeave;
0350 }
0351
0352 return hasIntersection;
0353 }
0354 };
0355
0356 #endif