File indexing completed on 2025-01-18 10:03:19
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
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:
0043
0044
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
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:
0072
0073
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
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:
0101
0102
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
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:
0124
0125
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
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:
0250
0251
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
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
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
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