|
26 | 26 | #include <Precision.hxx> |
27 | 27 | #include <NCollection_Vector.hxx> |
28 | 28 | #include <TColgp_Array1OfPnt.hxx> |
| 29 | +#include <GeomInt_WLApprox.hxx> |
| 30 | +#include <GeomInt_TheMultiLineOfWLApprox.hxx> |
29 | 31 |
|
30 | 32 | // (Sqrt(5.0) - 1.0) / 4.0 |
31 | 33 | //static const Standard_Real aSinCoeff = 0.30901699437494742410229341718282; |
@@ -89,86 +91,109 @@ static Standard_Real EvalCurv(const Standard_Real dim, |
89 | 91 | } |
90 | 92 |
|
91 | 93 | //======================================================================= |
92 | | -//function : ComputeKnotInds |
| 94 | +//function : BuildCurvature |
93 | 95 | //purpose : |
94 | 96 | //======================================================================= |
95 | | -void ApproxInt_KnotTools::ComputeKnotInds(const NCollection_LocalArray<Standard_Real>& theCoords, |
96 | | - const Standard_Integer theDim, |
97 | | - const math_Vector& thePars, |
98 | | - NCollection_Sequence<Standard_Integer>& theInds) |
| 97 | + |
| 98 | +void ApproxInt_KnotTools::BuildCurvature( |
| 99 | + const NCollection_LocalArray<Standard_Real>& theCoords, |
| 100 | + const Standard_Integer theDim, |
| 101 | + const math_Vector& thePars, |
| 102 | + TColStd_Array1OfReal& theCurv, |
| 103 | + Standard_Real& theMaxCurv) |
99 | 104 | { |
100 | | - //I: Create discrete curvature. |
101 | | - NCollection_Sequence<Standard_Integer> aFeatureInds; |
102 | | - TColStd_Array1OfReal aCurv(thePars.Lower(), thePars.Upper()); |
103 | 105 | // Arrays are allocated for max theDim = 7: 1 3d curve + 2 2d curves. |
104 | 106 | Standard_Real Val[21], Par[3], Res[21]; |
105 | 107 | Standard_Integer i, j, m, ic; |
106 | | - Standard_Real aMaxCurv = 0.; |
107 | 108 | Standard_Integer dim = theDim; |
108 | 109 | // |
109 | | - i = aCurv.Lower(); |
110 | | - for(j = 0; j < 3; ++j) |
| 110 | + theMaxCurv = 0.; |
| 111 | + if (theCurv.Length() < 3) |
| 112 | + { |
| 113 | + theCurv.Init(0.); |
| 114 | + return; |
| 115 | + } |
| 116 | + i = theCurv.Lower(); |
| 117 | + for (j = 0; j < 3; ++j) |
111 | 118 | { |
112 | | - Standard_Integer k = i+j; |
113 | | - ic = (k - aCurv.Lower()) * dim; |
| 119 | + Standard_Integer k = i + j; |
| 120 | + ic = (k - theCurv.Lower()) * dim; |
114 | 121 | Standard_Integer l = dim*j; |
115 | | - for(m = 0; m < dim; ++m) |
| 122 | + for (m = 0; m < dim; ++m) |
116 | 123 | { |
117 | 124 | Val[l + m] = theCoords[ic + m]; |
118 | 125 | } |
119 | 126 | Par[j] = thePars(k); |
120 | 127 | } |
121 | 128 | PLib::EvalLagrange(Par[0], 2, 2, dim, *Val, *Par, *Res); |
122 | 129 | // |
123 | | - aCurv(i) = EvalCurv(dim, &Res[dim], &Res[2*dim]); |
| 130 | + theCurv(i) = EvalCurv(dim, &Res[dim], &Res[2 * dim]); |
124 | 131 | // |
125 | | - if(aCurv(i) > aMaxCurv) |
| 132 | + if (theCurv(i) > theMaxCurv) |
126 | 133 | { |
127 | | - aMaxCurv = aCurv(i); |
| 134 | + theMaxCurv = theCurv(i); |
128 | 135 | } |
129 | 136 | // |
130 | | - for(i = aCurv.Lower()+1; i < aCurv.Upper(); ++i) |
| 137 | + for (i = theCurv.Lower() + 1; i < theCurv.Upper(); ++i) |
131 | 138 | { |
132 | | - for(j = 0; j < 3; ++j) |
| 139 | + for (j = 0; j < 3; ++j) |
133 | 140 | { |
134 | | - Standard_Integer k = i+j-1; |
135 | | - ic = (k - aCurv.Lower()) * dim; |
| 141 | + Standard_Integer k = i + j - 1; |
| 142 | + ic = (k - theCurv.Lower()) * dim; |
136 | 143 | Standard_Integer l = dim*j; |
137 | | - for(m = 0; m < dim; ++m) |
| 144 | + for (m = 0; m < dim; ++m) |
138 | 145 | { |
139 | 146 | Val[l + m] = theCoords[ic + m]; |
140 | 147 | } |
141 | 148 | Par[j] = thePars(k); |
142 | 149 | } |
143 | 150 | PLib::EvalLagrange(Par[1], 2, 2, dim, *Val, *Par, *Res); |
144 | 151 | // |
145 | | - aCurv(i) = EvalCurv(dim, &Res[dim], &Res[2*dim]); |
146 | | - if(aCurv(i) > aMaxCurv) |
| 152 | + theCurv(i) = EvalCurv(dim, &Res[dim], &Res[2 * dim]); |
| 153 | + if (theCurv(i) > theMaxCurv) |
147 | 154 | { |
148 | | - aMaxCurv = aCurv(i); |
| 155 | + theMaxCurv = theCurv(i); |
149 | 156 | } |
150 | 157 | } |
151 | 158 | // |
152 | | - i = aCurv.Upper(); |
153 | | - for(j = 0; j < 3; ++j) |
| 159 | + i = theCurv.Upper(); |
| 160 | + for (j = 0; j < 3; ++j) |
154 | 161 | { |
155 | | - Standard_Integer k = i+j-2; |
156 | | - ic = (k - aCurv.Lower()) * dim; |
| 162 | + Standard_Integer k = i + j - 2; |
| 163 | + ic = (k - theCurv.Lower()) * dim; |
157 | 164 | Standard_Integer l = dim*j; |
158 | | - for(m = 0; m < dim; ++m) |
| 165 | + for (m = 0; m < dim; ++m) |
159 | 166 | { |
160 | 167 | Val[l + m] = theCoords[ic + m]; |
161 | 168 | } |
162 | 169 | Par[j] = thePars(k); |
163 | 170 | } |
164 | 171 | PLib::EvalLagrange(Par[2], 2, 2, dim, *Val, *Par, *Res); |
165 | 172 | // |
166 | | - aCurv(i) = EvalCurv(dim, &Res[dim], &Res[2*dim]); |
167 | | - if(aCurv(i) > aMaxCurv) |
| 173 | + theCurv(i) = EvalCurv(dim, &Res[dim], &Res[2 * dim]); |
| 174 | + if (theCurv(i) > theMaxCurv) |
168 | 175 | { |
169 | | - aMaxCurv = aCurv(i); |
| 176 | + theMaxCurv = theCurv(i); |
170 | 177 | } |
171 | 178 |
|
| 179 | +} |
| 180 | + |
| 181 | +//======================================================================= |
| 182 | +//function : ComputeKnotInds |
| 183 | +//purpose : |
| 184 | +//======================================================================= |
| 185 | +void ApproxInt_KnotTools::ComputeKnotInds(const NCollection_LocalArray<Standard_Real>& theCoords, |
| 186 | + const Standard_Integer theDim, |
| 187 | + const math_Vector& thePars, |
| 188 | + NCollection_Sequence<Standard_Integer>& theInds) |
| 189 | +{ |
| 190 | + //I: Create discrete curvature. |
| 191 | + NCollection_Sequence<Standard_Integer> aFeatureInds; |
| 192 | + TColStd_Array1OfReal aCurv(thePars.Lower(), thePars.Upper()); |
| 193 | + Standard_Real aMaxCurv = 0.; |
| 194 | + BuildCurvature(theCoords, theDim, thePars, aCurv, aMaxCurv); |
| 195 | + // |
| 196 | + Standard_Integer i, j, dim = theDim; |
172 | 197 | #ifdef APPROXINT_KNOTTOOLS_DEBUG |
173 | 198 | std::cout << "Discrete curvature array is" << std::endl; |
174 | 199 | for(i = aCurv.Lower(); i <= aCurv.Upper(); ++i) |
@@ -627,3 +652,172 @@ void ApproxInt_KnotTools::BuildKnots(const TColgp_Array1OfPnt& thePntsXYZ, |
627 | 652 | #endif |
628 | 653 |
|
629 | 654 | } |
| 655 | +//======================================================================= |
| 656 | +//function : MaxParamRatio |
| 657 | +//purpose : |
| 658 | +//======================================================================= |
| 659 | +static Standard_Real MaxParamRatio(const math_Vector& thePars) |
| 660 | +{ |
| 661 | + Standard_Integer i; |
| 662 | + Standard_Real aMaxRatio = 0.; |
| 663 | + // |
| 664 | + for (i = thePars.Lower() + 1; i < thePars.Upper(); ++i) |
| 665 | + { |
| 666 | + Standard_Real aRat = (thePars(i + 1) - thePars(i)) / (thePars(i) - thePars(i - 1)); |
| 667 | + if (aRat < 1.) |
| 668 | + aRat = 1. / aRat; |
| 669 | + |
| 670 | + aMaxRatio = Max(aMaxRatio, aRat); |
| 671 | + } |
| 672 | + return aMaxRatio; |
| 673 | +} |
| 674 | +//======================================================================= |
| 675 | +//function : DefineParType |
| 676 | +//purpose : |
| 677 | +//======================================================================= |
| 678 | +Approx_ParametrizationType ApproxInt_KnotTools::DefineParType( |
| 679 | + const Handle(IntPatch_WLine)& theWL, |
| 680 | + const Standard_Integer theFpar, const Standard_Integer theLpar, |
| 681 | + const Standard_Boolean theApproxXYZ, |
| 682 | + const Standard_Boolean theApproxU1V1, |
| 683 | + const Standard_Boolean theApproxU2V2 |
| 684 | +) |
| 685 | +{ |
| 686 | + if (theLpar - theFpar == 1) |
| 687 | + return Approx_IsoParametric; |
| 688 | + |
| 689 | + const Standard_Integer nbp3d = theApproxXYZ ? 1 : 0, |
| 690 | + nbp2d = (theApproxU1V1 ? 1 : 0) + (theApproxU2V2 ? 1 : 0); |
| 691 | + |
| 692 | + GeomInt_TheMultiLineOfWLApprox aTestLine(theWL, nbp3d, nbp2d, theApproxU1V1, theApproxU2V2, |
| 693 | + 0., 0., 0., 0., 0., 0., 0., theApproxU1V1, theFpar, theLpar); |
| 694 | + |
| 695 | + TColgp_Array1OfPnt aTabPnt3d(1, Max(1, nbp3d)); |
| 696 | + TColgp_Array1OfPnt2d aTabPnt2d(1, Max(1, nbp2d)); |
| 697 | + TColgp_Array1OfPnt aPntXYZ(theFpar, theLpar); |
| 698 | + TColgp_Array1OfPnt2d aPntU1V1(theFpar, theLpar); |
| 699 | + TColgp_Array1OfPnt2d aPntU2V2(theFpar, theLpar); |
| 700 | + |
| 701 | + Standard_Integer i, j; |
| 702 | + |
| 703 | + for (i = theFpar; i <= theLpar; ++i) |
| 704 | + { |
| 705 | + if (nbp3d != 0 && nbp2d != 0) aTestLine.Value(i, aTabPnt3d, aTabPnt2d); |
| 706 | + else if (nbp2d != 0) aTestLine.Value(i, aTabPnt2d); |
| 707 | + else if (nbp3d != 0) aTestLine.Value(i, aTabPnt3d); |
| 708 | + // |
| 709 | + if (nbp3d > 0) |
| 710 | + { |
| 711 | + aPntXYZ(i) = aTabPnt3d(1); |
| 712 | + } |
| 713 | + if (nbp2d > 1) |
| 714 | + { |
| 715 | + aPntU1V1(i) = aTabPnt2d(1); |
| 716 | + aPntU2V2(i) = aTabPnt2d(2); |
| 717 | + } |
| 718 | + else if (nbp2d > 0) |
| 719 | + { |
| 720 | + if (theApproxU1V1) |
| 721 | + { |
| 722 | + aPntU1V1(i) = aTabPnt2d(1); |
| 723 | + } |
| 724 | + else |
| 725 | + { |
| 726 | + aPntU2V2(i) = aTabPnt2d(1); |
| 727 | + } |
| 728 | + } |
| 729 | + } |
| 730 | + |
| 731 | + Standard_Integer aDim = 0; |
| 732 | + |
| 733 | + if (theApproxXYZ) |
| 734 | + aDim += 3; |
| 735 | + if (theApproxU1V1) |
| 736 | + aDim += 2; |
| 737 | + if (theApproxU2V2) |
| 738 | + aDim += 2; |
| 739 | + |
| 740 | + Standard_Integer aLength = theLpar - theFpar + 1; |
| 741 | + NCollection_LocalArray<Standard_Real> aCoords(aLength * aDim); |
| 742 | + for (i = theFpar; i <= theLpar; ++i) |
| 743 | + { |
| 744 | + j = (i - theFpar) * aDim; |
| 745 | + if (theApproxXYZ) |
| 746 | + { |
| 747 | + aCoords[j] = aPntXYZ.Value(i).X(); |
| 748 | + ++j; |
| 749 | + aCoords[j] = aPntXYZ.Value(i).Y(); |
| 750 | + ++j; |
| 751 | + aCoords[j] = aPntXYZ.Value(i).Z(); |
| 752 | + ++j; |
| 753 | + } |
| 754 | + if (theApproxU1V1) |
| 755 | + { |
| 756 | + aCoords[j] = aPntU1V1.Value(i).X(); |
| 757 | + ++j; |
| 758 | + aCoords[j] = aPntU1V1.Value(i).Y(); |
| 759 | + ++j; |
| 760 | + } |
| 761 | + if (theApproxU2V2) |
| 762 | + { |
| 763 | + aCoords[j] = aPntU2V2.Value(i).X(); |
| 764 | + ++j; |
| 765 | + aCoords[j] = aPntU2V2.Value(i).Y(); |
| 766 | + ++j; |
| 767 | + } |
| 768 | + } |
| 769 | + |
| 770 | + //Analysis of curvature |
| 771 | + const Standard_Real aCritRat = 500.; |
| 772 | + const Standard_Real aCritParRat = 100.; |
| 773 | + math_Vector aPars(theFpar, theLpar); |
| 774 | + Approx_ParametrizationType aParType = Approx_ChordLength; |
| 775 | + GeomInt_WLApprox::Parameters(aTestLine, theFpar, theLpar, aParType, aPars); |
| 776 | + TColStd_Array1OfReal aCurv(aPars.Lower(), aPars.Upper()); |
| 777 | + Standard_Real aMaxCurv = 0.; |
| 778 | + BuildCurvature(aCoords, aDim, aPars, aCurv, aMaxCurv); |
| 779 | + |
| 780 | + if (aMaxCurv < Precision::PConfusion() |
| 781 | + || Precision::IsPositiveInfinite(aMaxCurv)) |
| 782 | + { |
| 783 | + //Linear case |
| 784 | + return aParType; |
| 785 | + } |
| 786 | + |
| 787 | + Standard_Real aMidCurv = 0.; |
| 788 | + Standard_Real eps = Epsilon(1.); |
| 789 | + j = 0; |
| 790 | + for (i = aCurv.Lower(); i <= aCurv.Upper(); ++i) |
| 791 | + { |
| 792 | + if (aMaxCurv - aCurv(i) < eps) |
| 793 | + { |
| 794 | + continue; |
| 795 | + } |
| 796 | + ++j; |
| 797 | + aMidCurv += aCurv(i); |
| 798 | + } |
| 799 | + |
| 800 | + if (j > 1) |
| 801 | + { |
| 802 | + aMidCurv /= j; |
| 803 | + } |
| 804 | + |
| 805 | + if (aMidCurv <= eps) |
| 806 | + return aParType; |
| 807 | + |
| 808 | + Standard_Real aRat = aMaxCurv / aMidCurv; |
| 809 | + |
| 810 | + if (aRat > aCritRat) |
| 811 | + { |
| 812 | + if(aRat > 5.*aCritRat) |
| 813 | + aParType = Approx_Centripetal; |
| 814 | + else |
| 815 | + { |
| 816 | + Standard_Real aParRat = MaxParamRatio(aPars); |
| 817 | + if (aParRat > aCritParRat) |
| 818 | + aParType = Approx_Centripetal; |
| 819 | + } |
| 820 | + } |
| 821 | + |
| 822 | + return aParType; |
| 823 | +} |
0 commit comments