0030686: Visualization, SelectMgr_ViewerSelector - sorting issues of transformation...
[occt.git] / src / ShapeUpgrade / ShapeUpgrade_ConvertCurve2dToBezier.cxx
CommitLineData
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 37IMPLEMENT_STANDARD_RTTIEXT(ShapeUpgrade_ConvertCurve2dToBezier,ShapeUpgrade_SplitCurve2d)
38
7fd59977 39ShapeUpgrade_ConvertCurve2dToBezier::ShapeUpgrade_ConvertCurve2dToBezier()
40{
41 mySegments = new TColGeom2d_HSequenceOfCurve;
42 mySplitParams = new TColStd_HSequenceOfReal;
43}
44
45static 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
62void 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
7fd59977 163 cout <<"Warning: The range of the edge exceeds the pcurve domain" <<endl;
164#endif
165 First = bf;
166 mySplitValues->SetValue(1,First);
167 }
168 if(Last > bl){
0797d9d3 169#ifdef OCCT_DEBUG
7fd59977 170 cout <<"Warning: The range of the edge exceeds the pcurve domain" <<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
235void 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
266Handle(TColGeom2d_HSequenceOfCurve) ShapeUpgrade_ConvertCurve2dToBezier::Segments() const
267{
268 return mySegments;
269}
270
271//=======================================================================
272//function : SplitParams
273//purpose :
274//=======================================================================
275
276Handle(TColStd_HSequenceOfReal) ShapeUpgrade_ConvertCurve2dToBezier::SplitParams() const
277{
278 return mySplitParams;
279}