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 | |
92efcf78 |
37 | IMPLEMENT_STANDARD_RTTIEXT(ShapeUpgrade_ConvertCurve2dToBezier,ShapeUpgrade_SplitCurve2d) |
38 | |
7fd59977 |
39 | ShapeUpgrade_ConvertCurve2dToBezier::ShapeUpgrade_ConvertCurve2dToBezier() |
40 | { |
41 | mySegments = new TColGeom2d_HSequenceOfCurve; |
42 | mySplitParams = new TColStd_HSequenceOfReal; |
43 | } |
44 | |
45 | static Handle(Geom2d_BezierCurve) MakeBezier2d(const Handle(Geom2d_Curve)& theCurve2d, |
46 | const Standard_Real theFirst, |
47 | const Standard_Real theLast) |
48 | { |
49 | TColgp_Array1OfPnt2d poles(1,2); |
50 | poles(1) = theCurve2d->Value(theFirst); |
51 | poles(2) = theCurve2d->Value(theLast); |
52 | Handle(Geom2d_BezierCurve) bezier = new Geom2d_BezierCurve(poles); |
53 | return bezier; |
54 | } |
55 | |
56 | |
57 | //======================================================================= |
58 | //function : Compute |
59 | //purpose : |
60 | //======================================================================= |
61 | |
62 | void ShapeUpgrade_ConvertCurve2dToBezier::Compute() |
63 | { |
64 | mySegments->Clear(); |
65 | mySplitParams->Clear(); |
66 | Standard_Real precision = Precision::PConfusion(); |
67 | Standard_Real First = mySplitValues->Value(1); |
68 | Standard_Real Last = mySplitValues->Value(mySplitValues->Length()); |
69 | |
70 | // PTV Try to create line2d from myCurve |
71 | if ( myCurve->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve)) || |
72 | myCurve->IsKind(STANDARD_TYPE(Geom2d_BezierCurve)) ) |
73 | { |
74 | // static function`s code getted from ShapeConvert |
75 | Standard_Real tmpF, tmpL, aDeviation; |
76 | Handle(Geom2d_Line) aTmpLine2d = |
77 | ShapeCustom_Curve2d::ConvertToLine2d(myCurve, First, Last, Precision::Approximation(), |
78 | tmpF, tmpL, aDeviation); |
79 | if (!aTmpLine2d.IsNull() && (aDeviation <= Precision::Approximation()) ) |
80 | { |
81 | Handle(Geom2d_BezierCurve) bezier = MakeBezier2d(aTmpLine2d, tmpF, tmpL); |
82 | mySegments->Append(bezier); |
83 | mySplitParams->Append(First); |
84 | mySplitParams->Append(Last); |
85 | myNbCurves = mySplitValues->Length()-1; |
86 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE1); |
87 | return; |
88 | } |
89 | } |
90 | |
91 | if(myCurve->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) { |
92 | Handle(Geom2d_TrimmedCurve) tmp = Handle(Geom2d_TrimmedCurve)::DownCast (myCurve); |
93 | Handle(Geom2d_Curve) BasCurve = tmp->BasisCurve(); |
94 | ShapeUpgrade_ConvertCurve2dToBezier converter; |
95 | //converter.Init(BasCurve,Max(First,BasCurve->FirstParameter()),Min(Last,BasCurve->LastParameter())); //??? |
96 | converter.Init(BasCurve,First,Last); |
97 | converter.SetSplitValues(mySplitValues); |
98 | converter.Compute(); |
99 | mySplitValues->Clear(); |
100 | mySplitValues->ChangeSequence() = converter.SplitValues()->Sequence(); |
101 | myNbCurves = mySplitValues->Length()-1; |
102 | myStatus |= converter.myStatus; |
103 | mySegments->ChangeSequence() = converter.Segments()->Sequence(); |
104 | mySplitParams->ChangeSequence() = converter.SplitParams()->Sequence(); |
105 | return; |
106 | } |
107 | else if(myCurve->IsKind(STANDARD_TYPE(Geom2d_BezierCurve))) { |
108 | Handle(Geom2d_BezierCurve) bezier = Handle(Geom2d_BezierCurve)::DownCast (myCurve); |
109 | myNbCurves = mySplitValues->Length()-1; |
110 | mySplitParams->Append(First); |
111 | mySplitParams->Append(Last); |
112 | if(First < precision && Last > 1 - precision) { |
113 | mySegments->Append(bezier); |
114 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK); |
115 | } else { |
116 | Handle(Geom2d_BezierCurve) besNew = Handle(Geom2d_BezierCurve)::DownCast(bezier->Copy()); |
117 | besNew->Segment(First,Last); |
118 | mySegments->Append(besNew); |
119 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE2); |
120 | } |
121 | return; |
122 | } |
123 | else if(myCurve->IsKind(STANDARD_TYPE(Geom2d_Line))) { |
124 | Handle(Geom2d_Line) aLine2d = Handle(Geom2d_Line)::DownCast(myCurve); |
125 | Handle(Geom2d_BezierCurve) bezier = MakeBezier2d(aLine2d, First, Last); |
126 | mySegments->Append(bezier); |
127 | mySplitParams->Append(First); |
128 | mySplitParams->Append(Last); |
129 | myNbCurves = mySplitValues->Length()-1; |
130 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE1); |
131 | return; |
132 | } |
133 | else { |
134 | Handle(Geom2d_BSplineCurve) aBSpline2d; |
135 | Standard_Real Shift = 0.; |
136 | if(myCurve->IsKind(STANDARD_TYPE(Geom2d_Conic))) { |
543a9964 |
137 | Handle(Geom2d_Curve) tcurve = new Geom2d_TrimmedCurve(myCurve,First,Last); //protection agains parabols ets |
7fd59977 |
138 | Geom2dConvert_ApproxCurve approx (tcurve, Precision::Approximation(), |
139 | GeomAbs_C1, 100, 6 ); |
140 | if ( approx.HasResult() ) |
a9dde4a3 |
141 | aBSpline2d = approx.Curve(); |
7fd59977 |
142 | else |
143 | aBSpline2d = Geom2dConvert::CurveToBSplineCurve(tcurve,Convert_QuasiAngular); |
144 | |
145 | Shift = First - aBSpline2d->FirstParameter(); |
146 | First = aBSpline2d->FirstParameter(); |
147 | Last = aBSpline2d->LastParameter(); |
148 | } |
149 | else if(!myCurve->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))) { |
150 | aBSpline2d = Geom2dConvert::CurveToBSplineCurve(myCurve,Convert_QuasiAngular); |
151 | } |
152 | else |
153 | aBSpline2d = Handle(Geom2d_BSplineCurve)::DownCast(myCurve); |
154 | |
155 | Standard_Real bf = aBSpline2d->FirstParameter(); |
156 | Standard_Real bl = aBSpline2d->LastParameter(); |
157 | if(Abs(First-bf) < precision) |
158 | First = bf; |
159 | if(Abs(Last-bl) < precision) |
160 | Last = bl; |
161 | if(First < bf){ |
0797d9d3 |
162 | #ifdef OCCT_DEBUG |
04232180 |
163 | std::cout <<"Warning: The range of the edge exceeds the pcurve domain" <<std::endl; |
7fd59977 |
164 | #endif |
165 | First = bf; |
166 | mySplitValues->SetValue(1,First); |
167 | } |
168 | if(Last > bl){ |
0797d9d3 |
169 | #ifdef OCCT_DEBUG |
04232180 |
170 | std::cout <<"Warning: The range of the edge exceeds the pcurve domain" <<std::endl; |
7fd59977 |
171 | #endif |
172 | Last = bl; |
173 | mySplitValues->SetValue(mySplitValues->Length(),Last); |
174 | } |
175 | |
176 | // PTV 20.12.2001 Try to simpify BSpline Curve |
177 | ShapeCustom_Curve2d::SimplifyBSpline2d (aBSpline2d, Precision::Approximation()); |
178 | |
179 | Geom2dConvert_BSplineCurveToBezierCurve tool(aBSpline2d,First,Last,precision); |
180 | Standard_Integer nbArcs = tool.NbArcs(); |
181 | TColStd_Array1OfReal knots(1,nbArcs+1); |
182 | tool.Knots(knots); |
183 | mySplitParams->Append(First+Shift); |
184 | Standard_Integer j; // svv Jan 10 2000 : porting on DEC |
185 | |
186 | Standard_Real newFirst = First+Shift; |
187 | Standard_Real newLast = First+Shift; |
188 | |
189 | for(j = 1; j <=nbArcs; j++) { |
190 | Standard_Real nextKnot = knots(j+1)+Shift; |
191 | if(nextKnot - mySplitParams->Value(mySplitParams->Length()) > precision) { |
192 | Handle(Geom2d_Curve) aCrv2d = tool.Arc(j); |
193 | if ( aCrv2d->IsKind(STANDARD_TYPE(Geom2d_BezierCurve)) ) |
194 | { |
195 | newFirst = newLast; |
196 | newLast = nextKnot; |
197 | Standard_Real tmpF, tmpL, aDeviation; |
198 | Handle(Geom2d_Line) aTmpLine2d = |
199 | ShapeCustom_Curve2d::ConvertToLine2d(aCrv2d, newFirst, newLast, Precision::Approximation(), |
200 | tmpF, tmpL, aDeviation); |
201 | if (!aTmpLine2d.IsNull() && (aDeviation <= Precision::Approximation()) ) |
202 | { |
203 | Handle(Geom2d_BezierCurve) bezier = MakeBezier2d(aBSpline2d, newFirst, newLast); |
204 | mySegments->Append(bezier); |
205 | mySplitParams->Append(newLast); |
206 | continue; |
207 | } |
208 | } |
209 | mySegments->Append(aCrv2d); |
210 | mySplitParams->Append(nextKnot); |
211 | } |
212 | } |
213 | |
214 | First = mySplitValues->Value(1); |
215 | for(j = 2; j <= mySplitValues->Length(); j++) { |
216 | Last = mySplitValues->Value(j); |
217 | for(Standard_Integer i = 2; i <= nbArcs+1; i++) { |
218 | Standard_Real valknot = knots(i)+Shift; |
219 | if(valknot <= First + precision) continue; |
220 | if(valknot >= Last - precision) break; |
221 | mySplitValues->InsertBefore(j++,valknot); |
222 | } |
223 | First = Last; |
224 | } |
225 | myNbCurves = mySplitValues->Length()-1; |
226 | } |
227 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE1); |
228 | } |
229 | |
230 | //======================================================================= |
231 | //function : Build |
232 | //purpose : |
233 | //======================================================================= |
234 | |
235 | void ShapeUpgrade_ConvertCurve2dToBezier::Build(const Standard_Boolean /*Segment*/) |
236 | { |
237 | Standard_Real prec = Precision::PConfusion(); |
238 | Standard_Integer nb = mySplitValues->Length(); |
239 | myResultingCurves = new TColGeom2d_HArray1OfCurve (1,nb-1); |
240 | Standard_Real prevPar =0.; |
241 | Standard_Integer j=2; |
242 | for(Standard_Integer i = 2; i <= nb; i++) { |
243 | Standard_Real par = mySplitValues->Value(i); |
244 | for(; j<= mySplitParams->Length(); j++) |
245 | if(mySplitParams->Value(j)+prec > par) |
246 | break; |
247 | else |
248 | prevPar = 0.; |
249 | |
250 | Handle(Geom2d_BezierCurve) bes = Handle(Geom2d_BezierCurve) |
251 | ::DownCast(mySegments->Value(j-1)->Copy()); |
252 | Standard_Real uFact = mySplitParams->Value(j) - mySplitParams->Value(j-1); |
253 | Standard_Real pp = mySplitValues->Value(i-1); |
254 | Standard_Real length = (par - pp)/uFact; |
255 | bes->Segment(prevPar, prevPar+length); |
256 | prevPar += length; |
257 | myResultingCurves->SetValue(i-1,bes); |
258 | } |
259 | } |
260 | |
261 | //======================================================================= |
262 | //function : Segments |
263 | //purpose : |
264 | //======================================================================= |
265 | |
266 | Handle(TColGeom2d_HSequenceOfCurve) ShapeUpgrade_ConvertCurve2dToBezier::Segments() const |
267 | { |
268 | return mySegments; |
269 | } |
270 | |
271 | //======================================================================= |
272 | //function : SplitParams |
273 | //purpose : |
274 | //======================================================================= |
275 | |
276 | Handle(TColStd_HSequenceOfReal) ShapeUpgrade_ConvertCurve2dToBezier::SplitParams() const |
277 | { |
278 | return mySplitParams; |
279 | } |