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
6 // This file is part of Open CASCADE Technology software library.
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 #include <ShapeUpgrade_ConvertCurve2dToBezier.ixx>
18 #include <Precision.hxx>
19 #include <Geom2d_TrimmedCurve.hxx>
20 #include <Geom2d_BezierCurve.hxx>
21 #include <ShapeExtend.hxx>
22 #include <Geom2d_Line.hxx>
23 #include <TColgp_Array1OfPnt2d.hxx>
24 #include <Geom2d_BSplineCurve.hxx>
25 #include <Geom2d_Conic.hxx>
26 #include <Geom_Curve.hxx>
27 #include <Geom2dConvert_ApproxCurve.hxx>
28 #include <Geom2dConvert.hxx>
29 #include <Geom2dConvert_BSplineCurveToBezierCurve.hxx>
30 #include <TColStd_Array1OfReal.hxx>
31 #include <TColGeom2d_HArray1OfCurve.hxx>
32 #include <GeomTools.hxx>
33 #include <ShapeCustom_Curve2d.hxx>
35 ShapeUpgrade_ConvertCurve2dToBezier::ShapeUpgrade_ConvertCurve2dToBezier()
37 mySegments = new TColGeom2d_HSequenceOfCurve;
38 mySplitParams = new TColStd_HSequenceOfReal;
41 static Handle(Geom2d_BezierCurve) MakeBezier2d(const Handle(Geom2d_Curve)& theCurve2d,
42 const Standard_Real theFirst,
43 const Standard_Real theLast)
45 TColgp_Array1OfPnt2d poles(1,2);
46 poles(1) = theCurve2d->Value(theFirst);
47 poles(2) = theCurve2d->Value(theLast);
48 Handle(Geom2d_BezierCurve) bezier = new Geom2d_BezierCurve(poles);
53 //=======================================================================
56 //=======================================================================
58 void ShapeUpgrade_ConvertCurve2dToBezier::Compute()
61 mySplitParams->Clear();
62 Standard_Real precision = Precision::PConfusion();
63 Standard_Real First = mySplitValues->Value(1);
64 Standard_Real Last = mySplitValues->Value(mySplitValues->Length());
66 // PTV Try to create line2d from myCurve
67 if ( myCurve->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve)) ||
68 myCurve->IsKind(STANDARD_TYPE(Geom2d_BezierCurve)) )
70 // static function`s code getted from ShapeConvert
71 Standard_Real tmpF, tmpL, aDeviation;
72 Handle(Geom2d_Line) aTmpLine2d =
73 ShapeCustom_Curve2d::ConvertToLine2d(myCurve, First, Last, Precision::Approximation(),
74 tmpF, tmpL, aDeviation);
75 if (!aTmpLine2d.IsNull() && (aDeviation <= Precision::Approximation()) )
77 Handle(Geom2d_BezierCurve) bezier = MakeBezier2d(aTmpLine2d, tmpF, tmpL);
78 mySegments->Append(bezier);
79 mySplitParams->Append(First);
80 mySplitParams->Append(Last);
81 myNbCurves = mySplitValues->Length()-1;
82 myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE1);
87 if(myCurve->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) {
88 Handle(Geom2d_TrimmedCurve) tmp = Handle(Geom2d_TrimmedCurve)::DownCast (myCurve);
89 Handle(Geom2d_Curve) BasCurve = tmp->BasisCurve();
90 ShapeUpgrade_ConvertCurve2dToBezier converter;
91 //converter.Init(BasCurve,Max(First,BasCurve->FirstParameter()),Min(Last,BasCurve->LastParameter())); //???
92 converter.Init(BasCurve,First,Last);
93 converter.SetSplitValues(mySplitValues);
95 mySplitValues->Clear();
96 mySplitValues->ChangeSequence() = converter.SplitValues()->Sequence();
97 myNbCurves = mySplitValues->Length()-1;
98 myStatus |= converter.myStatus;
99 mySegments->ChangeSequence() = converter.Segments()->Sequence();
100 mySplitParams->ChangeSequence() = converter.SplitParams()->Sequence();
103 else if(myCurve->IsKind(STANDARD_TYPE(Geom2d_BezierCurve))) {
104 Handle(Geom2d_BezierCurve) bezier = Handle(Geom2d_BezierCurve)::DownCast (myCurve);
105 myNbCurves = mySplitValues->Length()-1;
106 mySplitParams->Append(First);
107 mySplitParams->Append(Last);
108 if(First < precision && Last > 1 - precision) {
109 mySegments->Append(bezier);
110 myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
112 Handle(Geom2d_BezierCurve) besNew = Handle(Geom2d_BezierCurve)::DownCast(bezier->Copy());
113 besNew->Segment(First,Last);
114 mySegments->Append(besNew);
115 myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE2);
119 else if(myCurve->IsKind(STANDARD_TYPE(Geom2d_Line))) {
120 Handle(Geom2d_Line) aLine2d = Handle(Geom2d_Line)::DownCast(myCurve);
121 Handle(Geom2d_BezierCurve) bezier = MakeBezier2d(aLine2d, First, Last);
122 mySegments->Append(bezier);
123 mySplitParams->Append(First);
124 mySplitParams->Append(Last);
125 myNbCurves = mySplitValues->Length()-1;
126 myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE1);
130 Handle(Geom2d_BSplineCurve) aBSpline2d;
131 Standard_Real Shift = 0.;
132 if(myCurve->IsKind(STANDARD_TYPE(Geom2d_Conic))) {
133 Handle(Geom2d_TrimmedCurve) tcurve = new Geom2d_TrimmedCurve(myCurve,First,Last); //protection agains parabols ets
134 Geom2dConvert_ApproxCurve approx (tcurve, Precision::Approximation(),
135 GeomAbs_C1, 100, 6 );
136 if ( approx.HasResult() )
137 aBSpline2d = Handle(Geom2d_BSplineCurve)::DownCast(approx.Curve());
139 aBSpline2d = Geom2dConvert::CurveToBSplineCurve(tcurve,Convert_QuasiAngular);
141 Shift = First - aBSpline2d->FirstParameter();
142 First = aBSpline2d->FirstParameter();
143 Last = aBSpline2d->LastParameter();
145 else if(!myCurve->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))) {
146 aBSpline2d = Geom2dConvert::CurveToBSplineCurve(myCurve,Convert_QuasiAngular);
149 aBSpline2d = Handle(Geom2d_BSplineCurve)::DownCast(myCurve);
151 Standard_Real bf = aBSpline2d->FirstParameter();
152 Standard_Real bl = aBSpline2d->LastParameter();
153 if(Abs(First-bf) < precision)
155 if(Abs(Last-bl) < precision)
159 cout <<"Warning: The range of the edge exceeds the pcurve domain" <<endl;
162 mySplitValues->SetValue(1,First);
166 cout <<"Warning: The range of the edge exceeds the pcurve domain" <<endl;
169 mySplitValues->SetValue(mySplitValues->Length(),Last);
172 // PTV 20.12.2001 Try to simpify BSpline Curve
173 ShapeCustom_Curve2d::SimplifyBSpline2d (aBSpline2d, Precision::Approximation());
175 Geom2dConvert_BSplineCurveToBezierCurve tool(aBSpline2d,First,Last,precision);
176 Standard_Integer nbArcs = tool.NbArcs();
177 TColStd_Array1OfReal knots(1,nbArcs+1);
179 mySplitParams->Append(First+Shift);
180 Standard_Integer j; // svv Jan 10 2000 : porting on DEC
182 Standard_Real newFirst = First+Shift;
183 Standard_Real newLast = First+Shift;
185 for(j = 1; j <=nbArcs; j++) {
186 Standard_Real nextKnot = knots(j+1)+Shift;
187 if(nextKnot - mySplitParams->Value(mySplitParams->Length()) > precision) {
188 Handle(Geom2d_Curve) aCrv2d = tool.Arc(j);
189 if ( aCrv2d->IsKind(STANDARD_TYPE(Geom2d_BezierCurve)) )
193 Standard_Real tmpF, tmpL, aDeviation;
194 Handle(Geom2d_Line) aTmpLine2d =
195 ShapeCustom_Curve2d::ConvertToLine2d(aCrv2d, newFirst, newLast, Precision::Approximation(),
196 tmpF, tmpL, aDeviation);
197 if (!aTmpLine2d.IsNull() && (aDeviation <= Precision::Approximation()) )
199 Handle(Geom2d_BezierCurve) bezier = MakeBezier2d(aBSpline2d, newFirst, newLast);
200 mySegments->Append(bezier);
201 mySplitParams->Append(newLast);
205 mySegments->Append(aCrv2d);
206 mySplitParams->Append(nextKnot);
210 First = mySplitValues->Value(1);
211 for(j = 2; j <= mySplitValues->Length(); j++) {
212 Last = mySplitValues->Value(j);
213 for(Standard_Integer i = 2; i <= nbArcs+1; i++) {
214 Standard_Real valknot = knots(i)+Shift;
215 if(valknot <= First + precision) continue;
216 if(valknot >= Last - precision) break;
217 mySplitValues->InsertBefore(j++,valknot);
221 myNbCurves = mySplitValues->Length()-1;
223 myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE1);
226 //=======================================================================
229 //=======================================================================
231 void ShapeUpgrade_ConvertCurve2dToBezier::Build(const Standard_Boolean /*Segment*/)
233 Standard_Real prec = Precision::PConfusion();
234 Standard_Integer nb = mySplitValues->Length();
235 myResultingCurves = new TColGeom2d_HArray1OfCurve (1,nb-1);
236 Standard_Real prevPar =0.;
237 Standard_Integer j=2;
238 for(Standard_Integer i = 2; i <= nb; i++) {
239 Standard_Real par = mySplitValues->Value(i);
240 for(; j<= mySplitParams->Length(); j++)
241 if(mySplitParams->Value(j)+prec > par)
246 Handle(Geom2d_BezierCurve) bes = Handle(Geom2d_BezierCurve)
247 ::DownCast(mySegments->Value(j-1)->Copy());
248 Standard_Real uFact = mySplitParams->Value(j) - mySplitParams->Value(j-1);
249 Standard_Real pp = mySplitValues->Value(i-1);
250 Standard_Real length = (par - pp)/uFact;
251 bes->Segment(prevPar, prevPar+length);
253 myResultingCurves->SetValue(i-1,bes);
257 //=======================================================================
258 //function : Segments
260 //=======================================================================
262 Handle(TColGeom2d_HSequenceOfCurve) ShapeUpgrade_ConvertCurve2dToBezier::Segments() const
267 //=======================================================================
268 //function : SplitParams
270 //=======================================================================
272 Handle(TColStd_HSequenceOfReal) ShapeUpgrade_ConvertCurve2dToBezier::SplitParams() const
274 return mySplitParams;