7fd59977 |
1 | // File: GeomConvert_CompCurveToBSplineCurve.cxx |
2 | // Created: Mon Sep 23 15:03:12 1996 |
3 | // Author: Philippe MANGIN |
4 | // <pmn@sgi29> |
5 | // Modified: Fri Jul 10 11:23:35 1998 |
6 | // JCT : Add WithRatio,MinM |
7 | |
8 | |
9 | #include <GeomConvert_CompCurveToBSplineCurve.ixx> |
10 | |
11 | #include <Geom_BSplineCurve.hxx> |
12 | #include <GeomConvert.hxx> |
13 | |
14 | #include <TColStd_Array1OfReal.hxx> |
15 | #include <TColStd_Array1OfInteger.hxx> |
16 | |
17 | #include <TColgp_Array1OfPnt.hxx> |
18 | #include <gp_Vec.hxx> |
19 | #include <gp_Pnt.hxx> |
20 | #include <Precision.hxx> |
21 | |
22 | |
23 | |
24 | GeomConvert_CompCurveToBSplineCurve:: |
25 | GeomConvert_CompCurveToBSplineCurve(const Handle(Geom_BoundedCurve)& BasisCurve, |
26 | const Convert_ParameterisationType Parameterisation) : |
27 | myTol(Precision::Confusion()), |
28 | myType(Parameterisation) |
29 | { |
30 | Handle(Geom_BSplineCurve) Bs = |
31 | Handle(Geom_BSplineCurve)::DownCast(BasisCurve); |
32 | if (!Bs.IsNull()) { |
33 | myCurve = Handle(Geom_BSplineCurve)::DownCast(BasisCurve->Copy()); |
34 | } |
35 | else { |
36 | myCurve = GeomConvert::CurveToBSplineCurve (BasisCurve, myType); |
37 | } |
38 | } |
39 | |
40 | //======================================================================= |
41 | //function : Add |
42 | //purpose : |
43 | //======================================================================= |
44 | |
45 | Standard_Boolean GeomConvert_CompCurveToBSplineCurve:: |
46 | Add(const Handle(Geom_BoundedCurve)& NewCurve, |
47 | const Standard_Real Tolerance, |
48 | const Standard_Boolean After, |
49 | const Standard_Boolean WithRatio, |
50 | const Standard_Integer MinM) |
51 | { |
52 | Standard_Boolean avant, apres; |
53 | myTol = Tolerance; |
54 | // Convertion |
55 | Handle(Geom_BSplineCurve) Bs = |
56 | Handle(Geom_BSplineCurve)::DownCast(NewCurve); |
57 | if (!Bs.IsNull() ) { |
58 | Bs = Handle(Geom_BSplineCurve)::DownCast(NewCurve->Copy()); |
59 | } |
60 | else { |
61 | Bs = GeomConvert::CurveToBSplineCurve (NewCurve, myType); |
62 | } |
63 | |
64 | Standard_Integer LBs = Bs->NbPoles(), LCb = myCurve->NbPoles(); |
65 | |
66 | avant = (( myCurve->Pole(1).Distance(Bs->Pole(1)) < myTol)|| |
67 | ( myCurve->Pole(1).Distance(Bs->Pole(LBs))< myTol)); |
68 | apres = (( myCurve->Pole(LCb).Distance(Bs->Pole(1)) < myTol) || |
69 | ( myCurve->Pole(LCb).Distance(Bs->Pole(LBs))< myTol)); |
70 | |
71 | // myCurve est (sera) elle fermee ? |
72 | if (avant && apres) { // On leve l'ambiguite |
73 | if (After) avant = Standard_False; |
74 | else apres = Standard_False; |
75 | } |
76 | |
77 | // Ajout Apres ? |
78 | if ( apres) { |
79 | if (myCurve->Pole(LCb).Distance(Bs->Pole(LBs)) < myTol) {Bs->Reverse();} |
80 | Add(myCurve, Bs, Standard_True, WithRatio, MinM); |
81 | return Standard_True; |
82 | } |
83 | // Ajout avant ? |
84 | else if (avant) { |
85 | if (myCurve->Pole(1).Distance(Bs->Pole(1)) < myTol) {Bs->Reverse();} |
86 | Add(Bs, myCurve, Standard_False, WithRatio, MinM); |
87 | return Standard_True; |
88 | } |
89 | |
90 | return Standard_False; |
91 | } |
92 | |
93 | void GeomConvert_CompCurveToBSplineCurve::Add( |
94 | Handle(Geom_BSplineCurve)& FirstCurve, |
95 | Handle(Geom_BSplineCurve)& SecondCurve, |
96 | const Standard_Boolean After, |
97 | const Standard_Boolean WithRatio, |
98 | const Standard_Integer MinM) |
99 | { |
100 | // Harmonisation des degres. |
101 | Standard_Integer Deg = Max(FirstCurve->Degree(), SecondCurve->Degree()); |
102 | if (FirstCurve->Degree() < Deg) { FirstCurve->IncreaseDegree(Deg); } |
103 | if (SecondCurve->Degree() < Deg) { SecondCurve->IncreaseDegree(Deg); } |
104 | |
105 | // Declarationd |
106 | Standard_Real L1, L2, U_de_raccord; |
107 | Standard_Integer ii, jj; |
108 | Standard_Real Ratio=1, Ratio1, Ratio2, Delta1, Delta2; |
109 | Standard_Integer NbP1 = FirstCurve->NbPoles(), NbP2 = SecondCurve->NbPoles(); |
110 | Standard_Integer NbK1 = FirstCurve->NbKnots(), NbK2 = SecondCurve->NbKnots(); |
111 | TColStd_Array1OfReal Noeuds (1, NbK1+NbK2-1); |
112 | TColgp_Array1OfPnt Poles (1, NbP1+ NbP2-1); |
113 | TColStd_Array1OfReal Poids (1, NbP1+ NbP2-1); |
114 | TColStd_Array1OfInteger Mults (1, NbK1+NbK2-1); |
115 | |
116 | // Ratio de reparametrisation (C1 si possible) |
117 | if (WithRatio) { |
118 | L1 = FirstCurve->DN(FirstCurve->LastParameter(), 1).Magnitude(); |
119 | L2 = SecondCurve->DN(SecondCurve->FirstParameter(), 1). Magnitude(); |
120 | |
121 | if ( (L1 > Precision::Confusion()) && (L2 > Precision::Confusion()) ) { |
122 | Ratio = L1 / L2; |
123 | } |
124 | if ( (Ratio < Precision::Confusion()) || (Ratio > 1/Precision::Confusion()) ) {Ratio = 1;} |
125 | } |
126 | |
127 | if (After) { |
128 | // On ne bouge pas la premiere courbe |
129 | Ratio1 = 1; |
130 | Delta1 = 0; |
131 | Ratio2 = 1/Ratio; |
132 | Delta2 = Ratio2*SecondCurve->Knot(1) - FirstCurve->Knot(NbK1); |
133 | U_de_raccord = FirstCurve->LastParameter(); |
134 | } |
135 | else { |
136 | // On ne bouge pas la seconde courbe |
137 | Ratio1 = Ratio; |
138 | Delta1 = Ratio1*FirstCurve->Knot(NbK1) - SecondCurve->Knot(1); |
139 | Ratio2 = 1; |
140 | Delta2 = 0; |
141 | U_de_raccord = SecondCurve->FirstParameter(); |
142 | } |
143 | |
144 | // Les Noeuds |
145 | Standard_Real eps; |
146 | for (ii=1; ii<NbK1; ii++) { |
147 | Noeuds(ii) = Ratio1*FirstCurve->Knot(ii) - Delta1; |
148 | if(ii > 1) { |
149 | eps = Epsilon (Abs(Noeuds(ii-1))); |
150 | if( eps < 5.e-10 ) eps = 5.e-10; |
151 | if(Noeuds(ii) - Noeuds(ii-1) <= eps) { |
152 | Noeuds(ii) += eps; |
153 | } |
154 | } |
155 | Mults(ii) = FirstCurve->Multiplicity(ii); |
156 | } |
157 | Noeuds(NbK1) = U_de_raccord; |
158 | eps = Epsilon (Abs(Noeuds(NbK1-1))); |
159 | if(Noeuds(NbK1) - Noeuds(NbK1-1) <= eps) { |
160 | Noeuds(NbK1) += eps; |
161 | } |
162 | Mults(NbK1) = FirstCurve->Degree(); |
163 | for (ii=2, jj=NbK1+1; ii<=NbK2; ii++, jj++) { |
164 | Noeuds(jj) = Ratio2*SecondCurve->Knot(ii) - Delta2; |
165 | eps = Epsilon (Abs(Noeuds(jj-1))); |
166 | if( eps < 5.e-10 ) eps = 5.e-10; |
167 | if(Noeuds(jj) - Noeuds(jj-1) <= eps) { |
168 | Noeuds(jj) += eps; |
169 | } |
170 | Mults(jj) = SecondCurve->Multiplicity(ii); |
171 | } |
172 | |
173 | Ratio = FirstCurve->Weight(NbP1) ; |
174 | Ratio /= SecondCurve->Weight(1) ; |
175 | // Les Poles et Poids |
176 | for (ii=1; ii<NbP1; ii++) { |
177 | Poles(ii) = FirstCurve->Pole(ii); |
178 | Poids(ii) = FirstCurve->Weight(ii); |
179 | } |
180 | for (ii=1, jj=NbP1; ii<=NbP2; ii++, jj++) { |
181 | Poles(jj) = SecondCurve->Pole(ii); |
182 | // |
183 | // attentiion les poids ne se raccord pas forcement C0 |
184 | // d'ou Ratio |
185 | // |
186 | Poids(jj) = Ratio * SecondCurve->Weight(ii); |
187 | } |
188 | |
189 | // Creation de la BSpline |
190 | myCurve = new (Geom_BSplineCurve) (Poles, Poids, Noeuds, Mults, Deg); |
191 | |
192 | // Reduction eventuelle de la multiplicite jusqu'a MinM |
193 | Standard_Boolean Ok = Standard_True; |
194 | Standard_Integer M = Mults(NbK1); |
195 | while ( (M>MinM) && Ok) { |
196 | M--; |
197 | Ok = myCurve->RemoveKnot(NbK1, M, myTol); |
198 | } |
199 | |
200 | |
201 | } |
202 | |
203 | |
204 | Handle(Geom_BSplineCurve) GeomConvert_CompCurveToBSplineCurve::BSplineCurve() const |
205 | { |
206 | return myCurve; |
207 | } |
208 | |
209 | |
210 | |
211 | |