File indexing completed on 2026-09-19 09:28:32
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef _LProp_CurveUtils_HeaderFile
0015 #define _LProp_CurveUtils_HeaderFile
0016
0017 #include <LProp_NotDefined.hxx>
0018 #include <LProp_Status.hxx>
0019 #include <Standard_Handle.hxx>
0020
0021 #include <cmath>
0022
0023
0024
0025
0026 namespace LProp_CurveUtils
0027 {
0028
0029
0030
0031
0032 template <typename T>
0033 T& Deref(T& theObj)
0034 {
0035 return theObj;
0036 }
0037
0038
0039 template <typename T>
0040 T& Deref(occ::handle<T>& theHandle)
0041 {
0042 return *theHandle;
0043 }
0044
0045
0046 template <typename T>
0047 const T& Deref(const occ::handle<T>& theHandle)
0048 {
0049 return *theHandle;
0050 }
0051
0052
0053
0054
0055
0056 struct DirectAccess
0057 {
0058 template <typename C, typename P>
0059 static void D0(C& theCurve, double theU, P& thePnt)
0060 {
0061 Deref(theCurve).D0(theU, thePnt);
0062 }
0063
0064 template <typename C, typename P, typename V>
0065 static void D1(C& theCurve, double theU, P& thePnt, V& theV1)
0066 {
0067 Deref(theCurve).D1(theU, thePnt, theV1);
0068 }
0069
0070 template <typename C, typename P, typename V>
0071 static void D2(C& theCurve, double theU, P& thePnt, V& theV1, V& theV2)
0072 {
0073 Deref(theCurve).D2(theU, thePnt, theV1, theV2);
0074 }
0075
0076 template <typename C, typename P, typename V>
0077 static void D3(C& theCurve, double theU, P& thePnt, V& theV1, V& theV2, V& theV3)
0078 {
0079 Deref(theCurve).D3(theU, thePnt, theV1, theV2, theV3);
0080 }
0081
0082 template <typename C>
0083 static double FirstParameter(C& theCurve)
0084 {
0085 return Deref(theCurve).FirstParameter();
0086 }
0087
0088 template <typename C>
0089 static double LastParameter(C& theCurve)
0090 {
0091 return Deref(theCurve).LastParameter();
0092 }
0093 };
0094
0095
0096
0097 template <typename Tool>
0098 struct ToolAccess
0099 {
0100 template <typename C, typename P>
0101 static void D0(C& theCurve, double theU, P& thePnt)
0102 {
0103 Tool::Value(theCurve, theU, thePnt);
0104 }
0105
0106 template <typename C, typename P, typename V>
0107 static void D1(C& theCurve, double theU, P& thePnt, V& theV1)
0108 {
0109 Tool::D1(theCurve, theU, thePnt, theV1);
0110 }
0111
0112 template <typename C, typename P, typename V>
0113 static void D2(C& theCurve, double theU, P& thePnt, V& theV1, V& theV2)
0114 {
0115 Tool::D2(theCurve, theU, thePnt, theV1, theV2);
0116 }
0117
0118 template <typename C, typename P, typename V>
0119 static void D3(C& theCurve, double theU, P& thePnt, V& theV1, V& theV2, V& theV3)
0120 {
0121 Tool::D3(theCurve, theU, thePnt, theV1, theV2, theV3);
0122 }
0123
0124 template <typename C>
0125 static double FirstParameter(C& theCurve)
0126 {
0127 return Tool::FirstParameter(theCurve);
0128 }
0129
0130 template <typename C>
0131 static double LastParameter(C& theCurve)
0132 {
0133 return Tool::LastParameter(theCurve);
0134 }
0135 };
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145 template <typename Access, typename Curve, typename Pnt, typename Vec>
0146 void EvalDerivatives(Curve& theCurve, double theU, int theOrder, Pnt& thePnt, Vec* theDerivArr)
0147 {
0148 switch (theOrder)
0149 {
0150 case 0:
0151 Access::D0(theCurve, theU, thePnt);
0152 break;
0153 case 1:
0154 Access::D1(theCurve, theU, thePnt, theDerivArr[0]);
0155 break;
0156 case 2:
0157 Access::D2(theCurve, theU, thePnt, theDerivArr[0], theDerivArr[1]);
0158 break;
0159 case 3:
0160 Access::D3(theCurve, theU, thePnt, theDerivArr[0], theDerivArr[1], theDerivArr[2]);
0161 break;
0162 }
0163 }
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174 template <typename Access, typename Curve, typename Vec, typename Pnt, typename Dir>
0175 void ComputeTangent(Curve& theCurve,
0176 double theU,
0177 const Vec* theDerivArr,
0178 const Pnt& ,
0179 int theSigOrder,
0180 Dir& theDir)
0181 {
0182 if (theSigOrder == 1)
0183 {
0184 theDir = Dir(theDerivArr[0]);
0185 return;
0186 }
0187
0188 constexpr double THE_DIVISION_FACTOR = 1.0e-3;
0189 constexpr double THE_MIN_STEP = 1.0e-7;
0190
0191 const double anUsupremum = Access::LastParameter(theCurve);
0192 const double anUinfimum = Access::FirstParameter(theCurve);
0193
0194 double aDu;
0195 if ((anUsupremum >= RealLast()) || (anUinfimum <= RealFirst()))
0196 aDu = 0.0;
0197 else
0198 aDu = anUsupremum - anUinfimum;
0199
0200 const double aDelta = std::max(aDu * THE_DIVISION_FACTOR, THE_MIN_STEP);
0201
0202 Vec aV = theDerivArr[theSigOrder - 1];
0203
0204 double anOtherU;
0205 if (theU - anUinfimum < aDelta)
0206 anOtherU = theU + aDelta;
0207 else
0208 anOtherU = theU - aDelta;
0209
0210 Pnt aP1, aP2;
0211 Access::D0(theCurve, std::min(theU, anOtherU), aP1);
0212 Access::D0(theCurve, std::max(theU, anOtherU), aP2);
0213
0214 Vec aChord(aP1, aP2);
0215 if (aV.Dot(aChord) < 0.0)
0216 aV = -aV;
0217
0218 theDir = Dir(aV);
0219 }
0220
0221
0222
0223
0224
0225
0226
0227 template <typename Vec>
0228 double ComputeCurvature(const Vec& theD1, const Vec& theD2, double theTolSq)
0229 {
0230 const double aDD1 = theD1.SquareMagnitude();
0231 const double aDD2 = theD2.SquareMagnitude();
0232
0233 if (aDD2 <= theTolSq)
0234 return 0.0;
0235
0236 const double aN = theD1.CrossSquareMagnitude(theD2);
0237 const double aT = aN / aDD1 / aDD2;
0238 if (aT <= theTolSq)
0239 return 0.0;
0240
0241 return sqrt(aN) / aDD1 / sqrt(aDD1);
0242 }
0243
0244
0245
0246
0247
0248
0249 template <typename Vec, typename Dir>
0250 void ComputeNormal(const Vec& theD1, const Vec& theD2, Dir& theDir)
0251 {
0252 Vec aNorm = theD2 * (theD1 * theD1) - theD1 * (theD1 * theD2);
0253 theDir = Dir(aNorm);
0254 }
0255
0256
0257
0258
0259
0260
0261
0262
0263 template <typename Vec, typename Pnt>
0264 void ComputeCentreOfCurvature(const Pnt& thePnt,
0265 const Vec& theD1,
0266 const Vec& theD2,
0267 double theCurvature,
0268 Pnt& theCentre)
0269 {
0270 Vec aNorm = theD2 * (theD1 * theD1) - theD1 * (theD1 * theD2);
0271 aNorm.Normalize();
0272 aNorm.Divide(theCurvature);
0273 theCentre = thePnt.Translated(aNorm);
0274 }
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286 template <typename Access, typename Curve, typename Pnt, typename Vec>
0287 void SetParameter(Curve& theCurve,
0288 double theU,
0289 double& theStoredU,
0290 int theDerOrder,
0291 Pnt& thePnt,
0292 Vec* theDerivArr,
0293 LProp_Status& theTanStatus)
0294 {
0295 theStoredU = theU;
0296 EvalDerivatives<Access>(theCurve, theU, theDerOrder, thePnt, theDerivArr);
0297 theTanStatus = LProp_Undecided;
0298 }
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308 template <typename Access, typename Curve, typename Pnt, typename Vec>
0309 const Vec& EnsureDeriv(Curve& theCurve,
0310 double theU,
0311 int& theDerOrder,
0312 int theRequired,
0313 Pnt& thePnt,
0314 Vec* theDerivArr)
0315 {
0316 if (theDerOrder < theRequired)
0317 {
0318 theDerOrder = theRequired;
0319 EvalDerivatives<Access>(theCurve, theU, theDerOrder, thePnt, theDerivArr);
0320 }
0321 return theDerivArr[theRequired - 1];
0322 }
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332 template <typename Vec, typename Props>
0333 bool IsTangentDefined(Props& theProps,
0334 int theCN,
0335 double theLinTol,
0336 int& theSigOrder,
0337 LProp_Status& theTanStatus)
0338 {
0339 if (theTanStatus == LProp_Undefined)
0340 return false;
0341 if (theTanStatus >= LProp_Defined)
0342 return true;
0343
0344 const double aTolSq = theLinTol * theLinTol;
0345 int anOrder = 0;
0346 while (anOrder++ < 4)
0347 {
0348 if (theCN >= anOrder)
0349 {
0350 Vec aV;
0351 switch (anOrder)
0352 {
0353 case 1:
0354 aV = theProps.D1();
0355 break;
0356 case 2:
0357 aV = theProps.D2();
0358 break;
0359 case 3:
0360 aV = theProps.D3();
0361 break;
0362 default:
0363 theTanStatus = LProp_Undefined;
0364 return false;
0365 }
0366 if (aV.SquareMagnitude() > aTolSq)
0367 {
0368 theSigOrder = anOrder;
0369 theTanStatus = LProp_Defined;
0370 return true;
0371 }
0372 }
0373 else
0374 {
0375 theTanStatus = LProp_Undefined;
0376 return false;
0377 }
0378 }
0379 return false;
0380 }
0381
0382
0383
0384
0385
0386
0387
0388
0389
0390 template <typename Access, typename Props, typename Curve, typename Vec, typename Pnt, typename Dir>
0391 void Tangent(Props& theProps,
0392 Curve& theCurve,
0393 double theU,
0394 const Vec* theDerivArr,
0395 const Pnt& theRefPnt,
0396 const int& theSigOrder,
0397 Dir& theDir)
0398 {
0399 if (!theProps.IsTangentDefined())
0400 throw LProp_NotDefined();
0401 ComputeTangent<Access>(theCurve, theU, theDerivArr, theRefPnt, theSigOrder, theDir);
0402 }
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412 template <typename Props, typename Vec>
0413 double Curvature(Props& theProps,
0414 const Vec& theD1,
0415 const Vec& theD2,
0416 double theLinTol,
0417 const int& theSigOrder,
0418 double& theCurvature)
0419 {
0420 const bool anIsDefined = theProps.IsTangentDefined();
0421 (void)anIsDefined;
0422 LProp_NotDefined_Raise_if(!anIsDefined, "CLProps::Curvature()");
0423 if (theSigOrder > 1)
0424 return RealLast();
0425 theCurvature = ComputeCurvature(theD1, theD2, theLinTol * theLinTol);
0426 return theCurvature;
0427 }
0428
0429
0430
0431
0432
0433
0434
0435 template <typename Props, typename Vec, typename Dir>
0436 void Normal(Props& theProps, const Vec& theD1, const Vec& theD2, double theLinTol, Dir& theDir)
0437 {
0438 const double aCurvature = theProps.Curvature();
0439 if (aCurvature == RealLast() || std::abs(aCurvature) <= theLinTol)
0440 throw LProp_NotDefined("CLProps::Normal(): Curvature is null or infinity");
0441 ComputeNormal(theD1, theD2, theDir);
0442 }
0443
0444
0445
0446
0447
0448
0449
0450
0451
0452 template <typename Props, typename Vec, typename Pnt>
0453 void CentreOfCurvature(Props& theProps,
0454 const Pnt& thePnt,
0455 const Vec& theD1,
0456 const Vec& theD2,
0457 double theLinTol,
0458 double& theCurvature,
0459 Pnt& theCentre)
0460 {
0461 if (std::abs(theProps.Curvature()) <= theLinTol)
0462 throw LProp_NotDefined();
0463 ComputeCentreOfCurvature(thePnt, theD1, theD2, theCurvature, theCentre);
0464 }
0465
0466 }
0467
0468 #endif