b311480e |
1 | // Created on: 1999-05-13 |
2 | // Created by: data exchange team |
3 | // Copyright (c) 1999-1999 Matra Datavision |
973c2be1 |
4 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
b311480e |
5 | // |
973c2be1 |
6 | // This file is part of Open CASCADE Technology software library. |
b311480e |
7 | // |
d5f74e42 |
8 | // This library is free software; you can redistribute it and/or modify it under |
9 | // the terms of the GNU Lesser General Public License version 2.1 as published |
973c2be1 |
10 | // by the Free Software Foundation, with special exception defined in the file |
11 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
12 | // distribution for complete text of the license and disclaimer of any warranty. |
b311480e |
13 | // |
973c2be1 |
14 | // Alternatively, this file may be used under the terms of Open CASCADE |
15 | // commercial license or contractual agreement. |
7fd59977 |
16 | |
42cf5bc1 |
17 | |
7fd59977 |
18 | #include <Geom2d_BezierCurve.hxx> |
7fd59977 |
19 | #include <Geom2d_BSplineCurve.hxx> |
20 | #include <Geom2d_Conic.hxx> |
42cf5bc1 |
21 | #include <Geom2d_Line.hxx> |
22 | #include <Geom2d_TrimmedCurve.hxx> |
7fd59977 |
23 | #include <Geom2dConvert.hxx> |
42cf5bc1 |
24 | #include <Geom2dConvert_ApproxCurve.hxx> |
7fd59977 |
25 | #include <Geom2dConvert_BSplineCurveToBezierCurve.hxx> |
42cf5bc1 |
26 | #include <Geom_Curve.hxx> |
7fd59977 |
27 | #include <GeomTools.hxx> |
42cf5bc1 |
28 | #include <Precision.hxx> |
7fd59977 |
29 | #include <ShapeCustom_Curve2d.hxx> |
42cf5bc1 |
30 | #include <ShapeExtend.hxx> |
31 | #include <ShapeUpgrade_ConvertCurve2dToBezier.hxx> |
32 | #include <Standard_Type.hxx> |
33 | #include <TColGeom2d_HArray1OfCurve.hxx> |
34 | #include <TColgp_Array1OfPnt2d.hxx> |
35 | #include <TColStd_Array1OfReal.hxx> |
7fd59977 |
36 | |
37 | ShapeUpgrade_ConvertCurve2dToBezier::ShapeUpgrade_ConvertCurve2dToBezier() |
38 | { |
39 | mySegments = new TColGeom2d_HSequenceOfCurve; |
40 | mySplitParams = new TColStd_HSequenceOfReal; |
41 | } |
42 | |
43 | static Handle(Geom2d_BezierCurve) MakeBezier2d(const Handle(Geom2d_Curve)& theCurve2d, |
44 | const Standard_Real theFirst, |
45 | const Standard_Real theLast) |
46 | { |
47 | TColgp_Array1OfPnt2d poles(1,2); |
48 | poles(1) = theCurve2d->Value(theFirst); |
49 | poles(2) = theCurve2d->Value(theLast); |
50 | Handle(Geom2d_BezierCurve) bezier = new Geom2d_BezierCurve(poles); |
51 | return bezier; |
52 | } |
53 | |
54 | |
55 | //======================================================================= |
56 | //function : Compute |
57 | //purpose : |
58 | //======================================================================= |
59 | |
60 | void ShapeUpgrade_ConvertCurve2dToBezier::Compute() |
61 | { |
62 | mySegments->Clear(); |
63 | mySplitParams->Clear(); |
64 | Standard_Real precision = Precision::PConfusion(); |
65 | Standard_Real First = mySplitValues->Value(1); |
66 | Standard_Real Last = mySplitValues->Value(mySplitValues->Length()); |
67 | |
68 | // PTV Try to create line2d from myCurve |
69 | if ( myCurve->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve)) || |
70 | myCurve->IsKind(STANDARD_TYPE(Geom2d_BezierCurve)) ) |
71 | { |
72 | // static function`s code getted from ShapeConvert |
73 | Standard_Real tmpF, tmpL, aDeviation; |
74 | Handle(Geom2d_Line) aTmpLine2d = |
75 | ShapeCustom_Curve2d::ConvertToLine2d(myCurve, First, Last, Precision::Approximation(), |
76 | tmpF, tmpL, aDeviation); |
77 | if (!aTmpLine2d.IsNull() && (aDeviation <= Precision::Approximation()) ) |
78 | { |
79 | Handle(Geom2d_BezierCurve) bezier = MakeBezier2d(aTmpLine2d, tmpF, tmpL); |
80 | mySegments->Append(bezier); |
81 | mySplitParams->Append(First); |
82 | mySplitParams->Append(Last); |
83 | myNbCurves = mySplitValues->Length()-1; |
84 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE1); |
85 | return; |
86 | } |
87 | } |
88 | |
89 | if(myCurve->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) { |
90 | Handle(Geom2d_TrimmedCurve) tmp = Handle(Geom2d_TrimmedCurve)::DownCast (myCurve); |
91 | Handle(Geom2d_Curve) BasCurve = tmp->BasisCurve(); |
92 | ShapeUpgrade_ConvertCurve2dToBezier converter; |
93 | //converter.Init(BasCurve,Max(First,BasCurve->FirstParameter()),Min(Last,BasCurve->LastParameter())); //??? |
94 | converter.Init(BasCurve,First,Last); |
95 | converter.SetSplitValues(mySplitValues); |
96 | converter.Compute(); |
97 | mySplitValues->Clear(); |
98 | mySplitValues->ChangeSequence() = converter.SplitValues()->Sequence(); |
99 | myNbCurves = mySplitValues->Length()-1; |
100 | myStatus |= converter.myStatus; |
101 | mySegments->ChangeSequence() = converter.Segments()->Sequence(); |
102 | mySplitParams->ChangeSequence() = converter.SplitParams()->Sequence(); |
103 | return; |
104 | } |
105 | else if(myCurve->IsKind(STANDARD_TYPE(Geom2d_BezierCurve))) { |
106 | Handle(Geom2d_BezierCurve) bezier = Handle(Geom2d_BezierCurve)::DownCast (myCurve); |
107 | myNbCurves = mySplitValues->Length()-1; |
108 | mySplitParams->Append(First); |
109 | mySplitParams->Append(Last); |
110 | if(First < precision && Last > 1 - precision) { |
111 | mySegments->Append(bezier); |
112 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK); |
113 | } else { |
114 | Handle(Geom2d_BezierCurve) besNew = Handle(Geom2d_BezierCurve)::DownCast(bezier->Copy()); |
115 | besNew->Segment(First,Last); |
116 | mySegments->Append(besNew); |
117 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE2); |
118 | } |
119 | return; |
120 | } |
121 | else if(myCurve->IsKind(STANDARD_TYPE(Geom2d_Line))) { |
122 | Handle(Geom2d_Line) aLine2d = Handle(Geom2d_Line)::DownCast(myCurve); |
123 | Handle(Geom2d_BezierCurve) bezier = MakeBezier2d(aLine2d, First, Last); |
124 | mySegments->Append(bezier); |
125 | mySplitParams->Append(First); |
126 | mySplitParams->Append(Last); |
127 | myNbCurves = mySplitValues->Length()-1; |
128 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE1); |
129 | return; |
130 | } |
131 | else { |
132 | Handle(Geom2d_BSplineCurve) aBSpline2d; |
133 | Standard_Real Shift = 0.; |
134 | if(myCurve->IsKind(STANDARD_TYPE(Geom2d_Conic))) { |
543a9964 |
135 | Handle(Geom2d_Curve) tcurve = new Geom2d_TrimmedCurve(myCurve,First,Last); //protection agains parabols ets |
7fd59977 |
136 | Geom2dConvert_ApproxCurve approx (tcurve, Precision::Approximation(), |
137 | GeomAbs_C1, 100, 6 ); |
138 | if ( approx.HasResult() ) |
139 | aBSpline2d = Handle(Geom2d_BSplineCurve)::DownCast(approx.Curve()); |
140 | else |
141 | aBSpline2d = Geom2dConvert::CurveToBSplineCurve(tcurve,Convert_QuasiAngular); |
142 | |
143 | Shift = First - aBSpline2d->FirstParameter(); |
144 | First = aBSpline2d->FirstParameter(); |
145 | Last = aBSpline2d->LastParameter(); |
146 | } |
147 | else if(!myCurve->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))) { |
148 | aBSpline2d = Geom2dConvert::CurveToBSplineCurve(myCurve,Convert_QuasiAngular); |
149 | } |
150 | else |
151 | aBSpline2d = Handle(Geom2d_BSplineCurve)::DownCast(myCurve); |
152 | |
153 | Standard_Real bf = aBSpline2d->FirstParameter(); |
154 | Standard_Real bl = aBSpline2d->LastParameter(); |
155 | if(Abs(First-bf) < precision) |
156 | First = bf; |
157 | if(Abs(Last-bl) < precision) |
158 | Last = bl; |
159 | if(First < bf){ |
0797d9d3 |
160 | #ifdef OCCT_DEBUG |
7fd59977 |
161 | cout <<"Warning: The range of the edge exceeds the pcurve domain" <<endl; |
162 | #endif |
163 | First = bf; |
164 | mySplitValues->SetValue(1,First); |
165 | } |
166 | if(Last > bl){ |
0797d9d3 |
167 | #ifdef OCCT_DEBUG |
7fd59977 |
168 | cout <<"Warning: The range of the edge exceeds the pcurve domain" <<endl; |
169 | #endif |
170 | Last = bl; |
171 | mySplitValues->SetValue(mySplitValues->Length(),Last); |
172 | } |
173 | |
174 | // PTV 20.12.2001 Try to simpify BSpline Curve |
175 | ShapeCustom_Curve2d::SimplifyBSpline2d (aBSpline2d, Precision::Approximation()); |
176 | |
177 | Geom2dConvert_BSplineCurveToBezierCurve tool(aBSpline2d,First,Last,precision); |
178 | Standard_Integer nbArcs = tool.NbArcs(); |
179 | TColStd_Array1OfReal knots(1,nbArcs+1); |
180 | tool.Knots(knots); |
181 | mySplitParams->Append(First+Shift); |
182 | Standard_Integer j; // svv Jan 10 2000 : porting on DEC |
183 | |
184 | Standard_Real newFirst = First+Shift; |
185 | Standard_Real newLast = First+Shift; |
186 | |
187 | for(j = 1; j <=nbArcs; j++) { |
188 | Standard_Real nextKnot = knots(j+1)+Shift; |
189 | if(nextKnot - mySplitParams->Value(mySplitParams->Length()) > precision) { |
190 | Handle(Geom2d_Curve) aCrv2d = tool.Arc(j); |
191 | if ( aCrv2d->IsKind(STANDARD_TYPE(Geom2d_BezierCurve)) ) |
192 | { |
193 | newFirst = newLast; |
194 | newLast = nextKnot; |
195 | Standard_Real tmpF, tmpL, aDeviation; |
196 | Handle(Geom2d_Line) aTmpLine2d = |
197 | ShapeCustom_Curve2d::ConvertToLine2d(aCrv2d, newFirst, newLast, Precision::Approximation(), |
198 | tmpF, tmpL, aDeviation); |
199 | if (!aTmpLine2d.IsNull() && (aDeviation <= Precision::Approximation()) ) |
200 | { |
201 | Handle(Geom2d_BezierCurve) bezier = MakeBezier2d(aBSpline2d, newFirst, newLast); |
202 | mySegments->Append(bezier); |
203 | mySplitParams->Append(newLast); |
204 | continue; |
205 | } |
206 | } |
207 | mySegments->Append(aCrv2d); |
208 | mySplitParams->Append(nextKnot); |
209 | } |
210 | } |
211 | |
212 | First = mySplitValues->Value(1); |
213 | for(j = 2; j <= mySplitValues->Length(); j++) { |
214 | Last = mySplitValues->Value(j); |
215 | for(Standard_Integer i = 2; i <= nbArcs+1; i++) { |
216 | Standard_Real valknot = knots(i)+Shift; |
217 | if(valknot <= First + precision) continue; |
218 | if(valknot >= Last - precision) break; |
219 | mySplitValues->InsertBefore(j++,valknot); |
220 | } |
221 | First = Last; |
222 | } |
223 | myNbCurves = mySplitValues->Length()-1; |
224 | } |
225 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE1); |
226 | } |
227 | |
228 | //======================================================================= |
229 | //function : Build |
230 | //purpose : |
231 | //======================================================================= |
232 | |
233 | void ShapeUpgrade_ConvertCurve2dToBezier::Build(const Standard_Boolean /*Segment*/) |
234 | { |
235 | Standard_Real prec = Precision::PConfusion(); |
236 | Standard_Integer nb = mySplitValues->Length(); |
237 | myResultingCurves = new TColGeom2d_HArray1OfCurve (1,nb-1); |
238 | Standard_Real prevPar =0.; |
239 | Standard_Integer j=2; |
240 | for(Standard_Integer i = 2; i <= nb; i++) { |
241 | Standard_Real par = mySplitValues->Value(i); |
242 | for(; j<= mySplitParams->Length(); j++) |
243 | if(mySplitParams->Value(j)+prec > par) |
244 | break; |
245 | else |
246 | prevPar = 0.; |
247 | |
248 | Handle(Geom2d_BezierCurve) bes = Handle(Geom2d_BezierCurve) |
249 | ::DownCast(mySegments->Value(j-1)->Copy()); |
250 | Standard_Real uFact = mySplitParams->Value(j) - mySplitParams->Value(j-1); |
251 | Standard_Real pp = mySplitValues->Value(i-1); |
252 | Standard_Real length = (par - pp)/uFact; |
253 | bes->Segment(prevPar, prevPar+length); |
254 | prevPar += length; |
255 | myResultingCurves->SetValue(i-1,bes); |
256 | } |
257 | } |
258 | |
259 | //======================================================================= |
260 | //function : Segments |
261 | //purpose : |
262 | //======================================================================= |
263 | |
264 | Handle(TColGeom2d_HSequenceOfCurve) ShapeUpgrade_ConvertCurve2dToBezier::Segments() const |
265 | { |
266 | return mySegments; |
267 | } |
268 | |
269 | //======================================================================= |
270 | //function : SplitParams |
271 | //purpose : |
272 | //======================================================================= |
273 | |
274 | Handle(TColStd_HSequenceOfReal) ShapeUpgrade_ConvertCurve2dToBezier::SplitParams() const |
275 | { |
276 | return mySplitParams; |
277 | } |