File indexing completed on 2026-09-19 09:27:35
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef _Convert_CompBezierCurvesToBSplineCurveBase_HeaderFile
0015 #define _Convert_CompBezierCurvesToBSplineCurveBase_HeaderFile
0016
0017 #include <BSplCLib.hxx>
0018 #include <gp.hxx>
0019 #include <NCollection_Array1.hxx>
0020 #include <NCollection_Sequence.hxx>
0021 #include <type_traits>
0022
0023 class gp_Pnt;
0024 class gp_Pnt2d;
0025
0026
0027
0028
0029 template <typename PointType, typename VecType>
0030 class Convert_CompBezierCurvesToBSplineCurveBase
0031 {
0032 public:
0033
0034
0035
0036
0037 explicit Convert_CompBezierCurvesToBSplineCurveBase(const double theAngularTolerance = 1.0e-4)
0038 : myDegree(0),
0039 myAngular(theAngularTolerance)
0040 {
0041 }
0042
0043
0044
0045
0046 void AddCurve(const NCollection_Array1<PointType>& thePoles) { mySequence.Append(thePoles); }
0047
0048
0049
0050 void Perform()
0051 {
0052 myCurvePoles.Clear();
0053 myCurveKnots.Clear();
0054 myKnotsMults.Clear();
0055 if (mySequence.IsEmpty())
0056 {
0057 return;
0058 }
0059 const int aLowerI = 1;
0060 const int anUpperI = mySequence.Length();
0061 const int aNbrCurv = anUpperI - aLowerI + 1;
0062 NCollection_Array1<double> aCurveKnVals(1, aNbrCurv);
0063
0064 myDegree = 0;
0065 for (int i = 1; i <= mySequence.Length(); i++)
0066 {
0067 myDegree = std::max(myDegree, mySequence(i).Length() - 1);
0068 }
0069
0070 double aDet = 0;
0071 PointType aP1, aP2, aP3;
0072 const int aMaxDegree = myDegree;
0073 NCollection_Array1<PointType> aPoints(1, myDegree + 1);
0074
0075 for (int i = aLowerI; i <= anUpperI; i++)
0076 {
0077
0078 const int aDeg = mySequence(i).Length() - 1;
0079 const int anInc = myDegree - aDeg;
0080 if (anInc > 0)
0081 {
0082 BSplCLib::IncreaseDegree(myDegree,
0083 mySequence(i),
0084 BSplCLib::NoWeights(),
0085 aPoints,
0086 BSplCLib::NoWeights());
0087 }
0088 else
0089 {
0090 aPoints = mySequence(i);
0091 }
0092
0093
0094 if (i == aLowerI)
0095 {
0096
0097 for (int j = 1; j <= aMaxDegree; j++)
0098 {
0099 myCurvePoles.Append(aPoints(j));
0100 }
0101 aCurveKnVals(1) = 1.;
0102 myKnotsMults.Append(aMaxDegree + 1);
0103 aDet = 1.;
0104 }
0105
0106 if (i != aLowerI)
0107 {
0108 aP2 = aPoints(1);
0109 aP3 = aPoints(2);
0110 VecType aV1(aP1, aP2), aV2(aP2, aP3);
0111
0112
0113
0114 const double aD1 = aV1.SquareMagnitude();
0115 const double aD2 = aV2.SquareMagnitude();
0116 if (aMaxDegree > 1 && aD1 > gp::Resolution() && aD2 > gp::Resolution()
0117 && aV1.IsParallel(aV2, myAngular))
0118 {
0119 const double aLambda = std::sqrt(aD2 / aD1);
0120 if constexpr (std::is_same_v<PointType, gp_Pnt>)
0121 {
0122
0123
0124 if (aCurveKnVals(i - 1) * aLambda > 10. * Epsilon(aDet))
0125 {
0126 myKnotsMults.Append(aMaxDegree - 1);
0127 aCurveKnVals(i) = aCurveKnVals(i - 1) * aLambda;
0128 }
0129 else
0130 {
0131 myCurvePoles.Append(aPoints(1));
0132 myKnotsMults.Append(aMaxDegree);
0133 aCurveKnVals(i) = 1.0;
0134 }
0135 }
0136 else
0137 {
0138 myKnotsMults.Append(aMaxDegree - 1);
0139 aCurveKnVals(i) = aCurveKnVals(i - 1) * aLambda;
0140 }
0141 }
0142 else
0143 {
0144 myCurvePoles.Append(aPoints(1));
0145 myKnotsMults.Append(aMaxDegree);
0146 aCurveKnVals(i) = 1.0;
0147 }
0148 aDet += aCurveKnVals(i);
0149
0150
0151 for (int j = 2; j <= aMaxDegree; j++)
0152 {
0153 myCurvePoles.Append(aPoints(j));
0154 }
0155 }
0156
0157 if (i == anUpperI)
0158 {
0159
0160 myCurvePoles.Append(aPoints(aMaxDegree + 1));
0161 myKnotsMults.Append(aMaxDegree + 1);
0162 }
0163 aP1 = aPoints(aMaxDegree);
0164 }
0165
0166
0167 myCurveKnots.Append(0.0);
0168 for (int i = 2; i <= aNbrCurv; i++)
0169 {
0170 myCurveKnots.Append(myCurveKnots(i - 1) + (aCurveKnVals(i - 1) / aDet));
0171 }
0172 myCurveKnots.Append(1.0);
0173 }
0174
0175
0176 [[nodiscard]] int Degree() const { return myDegree; }
0177
0178
0179 [[nodiscard]] int NbPoles() const { return myCurvePoles.Length(); }
0180
0181
0182
0183 void Poles(NCollection_Array1<PointType>& thePoles) const
0184 {
0185 int k = 1;
0186 for (int i = thePoles.Lower(); i <= thePoles.Upper(); i++)
0187 {
0188 thePoles(i) = myCurvePoles(k++);
0189 }
0190 }
0191
0192
0193 [[nodiscard]] int NbKnots() const { return myCurveKnots.Length(); }
0194
0195
0196
0197
0198
0199 void KnotsAndMults(NCollection_Array1<double>& theKnots, NCollection_Array1<int>& theMults) const
0200 {
0201 int k = 1;
0202 for (int i = theKnots.Lower(); i <= theKnots.Upper(); i++)
0203 {
0204 theKnots(i) = myCurveKnots(k++);
0205 }
0206 k = 1;
0207 for (int i = theMults.Lower(); i <= theMults.Upper(); i++)
0208 {
0209 theMults(i) = myKnotsMults(k++);
0210 }
0211 }
0212
0213 private:
0214 NCollection_Sequence<NCollection_Array1<PointType>> mySequence;
0215 NCollection_Sequence<PointType> myCurvePoles;
0216 NCollection_Sequence<double> myCurveKnots;
0217 NCollection_Sequence<int> myKnotsMults;
0218 int myDegree;
0219 double myAngular;
0220 };
0221
0222 #endif