0031939: Coding - correction of spelling errors in comments [part 10]
[occt.git] / src / ShapeUpgrade / ShapeUpgrade_ConvertCurve2dToBezier.cxx
1 // Created on: 1999-05-13
2 // Created by: data exchange team
3 // Copyright (c) 1999-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
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
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.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17
18 #include <Geom2d_BezierCurve.hxx>
19 #include <Geom2d_BSplineCurve.hxx>
20 #include <Geom2d_Conic.hxx>
21 #include <Geom2d_Line.hxx>
22 #include <Geom2d_TrimmedCurve.hxx>
23 #include <Geom2dConvert.hxx>
24 #include <Geom2dConvert_ApproxCurve.hxx>
25 #include <Geom2dConvert_BSplineCurveToBezierCurve.hxx>
26 #include <Geom_Curve.hxx>
27 #include <GeomTools.hxx>
28 #include <Precision.hxx>
29 #include <ShapeCustom_Curve2d.hxx>
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>
36
37 IMPLEMENT_STANDARD_RTTIEXT(ShapeUpgrade_ConvertCurve2dToBezier,ShapeUpgrade_SplitCurve2d)
38
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))) {
137       Handle(Geom2d_Curve) tcurve = new Geom2d_TrimmedCurve(myCurve,First,Last); //protection against parabols ets
138       Geom2dConvert_ApproxCurve approx (tcurve, Precision::Approximation(), 
139                                         GeomAbs_C1, 100, 6 );
140       if ( approx.HasResult() )
141         aBSpline2d = approx.Curve();
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){
162 #ifdef OCCT_DEBUG
163       std::cout <<"Warning: The range of the edge exceeds the pcurve domain" <<std::endl;
164 #endif
165       First = bf;
166       mySplitValues->SetValue(1,First);
167     }
168     if(Last > bl){
169 #ifdef OCCT_DEBUG
170       std::cout <<"Warning: The range of the edge exceeds the pcurve domain" <<std::endl;
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 }