0027234: Code duplication: Convert_CompBezierCurvesToBSplineCurve* in ShapeConstruct
[occt.git] / src / ShapeConstruct / ShapeConstruct_Curve.cxx
CommitLineData
973c2be1 1// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 2//
973c2be1 3// This file is part of Open CASCADE Technology software library.
b311480e 4//
d5f74e42 5// This library is free software; you can redistribute it and/or modify it under
6// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 7// by the Free Software Foundation, with special exception defined in the file
8// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9// distribution for complete text of the license and disclaimer of any warranty.
b311480e 10//
973c2be1 11// Alternatively, this file may be used under the terms of Open CASCADE
12// commercial license or contractual agreement.
b311480e 13
7fd59977 14
42cf5bc1 15#include <Approx_Curve2d.hxx>
16#include <Approx_Curve3d.hxx>
7fd59977 17#include <ElCLib.hxx>
7fd59977 18#include <Geom2d_BezierCurve.hxx>
42cf5bc1 19#include <Geom2d_BSplineCurve.hxx>
20#include <Geom2d_Curve.hxx>
7fd59977 21#include <Geom2d_Line.hxx>
42cf5bc1 22#include <Geom2d_TrimmedCurve.hxx>
7fd59977 23#include <Geom2dAdaptor_HCurve.hxx>
42cf5bc1 24#include <Geom2dConvert.hxx>
25#include <Geom_BezierCurve.hxx>
26#include <Geom_BSplineCurve.hxx>
27#include <Geom_Curve.hxx>
28#include <Geom_Line.hxx>
29#include <Geom_TrimmedCurve.hxx>
30#include <GeomAdaptor_HCurve.hxx>
31#include <GeomConvert.hxx>
32#include <gp_Dir.hxx>
33#include <gp_Lin.hxx>
34#include <gp_Pnt.hxx>
35#include <gp_Pnt2d.hxx>
36#include <gp_Vec.hxx>
37#include <Precision.hxx>
38#include <ShapeConstruct_Curve.hxx>
39#include <Standard_ErrorHandler.hxx>
40#include <Standard_Failure.hxx>
7fd59977 41
42//sln 29.12.2001 OCC90 : Method FixKnots was added
7fd59977 43//=======================================================================
44//function : AdjustCurve
45//purpose :
46//=======================================================================
7fd59977 47Standard_Boolean ShapeConstruct_Curve::AdjustCurve(const Handle(Geom_Curve)& C3D,const gp_Pnt& P1,const gp_Pnt& P2,const Standard_Boolean take1,const Standard_Boolean take2) const
48{
49 if (!take1 && !take2) return Standard_True;
50
51 if (C3D->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) {
52 Handle(Geom_BSplineCurve) BSPL = Handle(Geom_BSplineCurve)::DownCast(C3D);
53 if (take1) BSPL->SetPole (1,P1);
54 if (take2) BSPL->SetPole (BSPL->NbPoles(),P2);
55 return Standard_True;
56 }
57
58 if (C3D->IsKind(STANDARD_TYPE(Geom_Line))) {
59 Handle(Geom_Line) L3D = Handle(Geom_Line)::DownCast(C3D);
60// ATTENTION, P1 et P2 sont supposes tous deux pertinents ...
61 gp_Vec avec (P1,P2); gp_Dir adir (avec); gp_Lin alin (P1,adir);
62 Standard_Real theParam = ElCLib::Parameter(alin, L3D->Lin().Location());
63 alin.SetLocation (ElCLib::Value(theParam, alin));
64 L3D->SetLin (alin);
65 return Standard_True;
66 }
67
68 return Standard_False;
69}
70
71//=======================================================================
72//function : AdjustCurveSegment
73//purpose :
74//=======================================================================
75
76Standard_Boolean ShapeConstruct_Curve::AdjustCurveSegment(const Handle(Geom_Curve)& C3D,const gp_Pnt& P1,const gp_Pnt& P2,const Standard_Real U1,const Standard_Real U2) const
77{
78 if (C3D->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) {
79 Handle(Geom_BSplineCurve) BSPL = Handle(Geom_BSplineCurve)::DownCast(C3D);
80// Forcer l extremite c est bien
81// Propager sur le reste, c est pas mal non plus
82 if (U1 >= U2) return Standard_False;
83 Standard_Real UU1 = Max (U1,BSPL->FirstParameter());
84 Standard_Real UU2 = Min (U2,BSPL->LastParameter());
85 BSPL->Segment (UU1,UU2);
86 BSPL->SetPole (1,P1);
87 BSPL->SetPole (BSPL->NbPoles(),P2);
88 return Standard_True;
89 }
90
91 if (C3D->IsKind(STANDARD_TYPE(Geom_Line))) {
92 Handle(Geom_Line) L3D = Handle(Geom_Line)::DownCast(C3D);
93// ATTENTION, P1 et P2 sont supposes tous deux pertinents ...
94// NB : on ne s aide pas de U1 et U2
95 gp_Vec avec (P1,P2); gp_Dir adir (avec); gp_Lin alin (P1,adir);
96 Standard_Real theParam = ElCLib::Parameter(alin, L3D->Lin().Location());
97 alin.SetLocation (ElCLib::Value(theParam, alin));
98 L3D->SetLin (alin);
99 return Standard_True;
100 }
101
102 return Standard_False;
103}
104
105//=======================================================================
106//function : AdjustCurve2d
107//purpose :
108//=======================================================================
109
110Standard_Boolean ShapeConstruct_Curve::AdjustCurve2d(const Handle(Geom2d_Curve)& C2D,const gp_Pnt2d& P1,const gp_Pnt2d& P2,const Standard_Boolean take1,const Standard_Boolean take2) const
111{
112 if (!take1 && !take2) return Standard_True;
113
114 if (C2D->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))) {
115 Handle(Geom2d_BSplineCurve) BSPL = Handle(Geom2d_BSplineCurve)::DownCast(C2D);
116 if (take1) BSPL->SetPole (1,P1);
117 if (take2) BSPL->SetPole (BSPL->NbPoles(),P2);
118 return Standard_True;
119 }
120
121 if (C2D->IsKind(STANDARD_TYPE(Geom2d_Line))) {
122 Handle(Geom2d_Line) L2D = Handle(Geom2d_Line)::DownCast(C2D);
123// ATTENTION, P1 et P2 sont supposes tous deux pertinents ...
124 gp_Vec2d avec (P1,P2); gp_Dir2d adir (avec); gp_Lin2d alin (P1,adir);
125 Standard_Real theParam = ElCLib::Parameter(alin, L2D->Lin2d().Location());
126 alin.SetLocation (ElCLib::Value(theParam, alin));
127 L2D->SetLin2d (alin);
128 return Standard_True;
129 }
130
131 return Standard_False;
132}
133
134//=======================================================================
135//function : ConvertToBSpline
136//purpose :
137//=======================================================================
138
139Handle(Geom_BSplineCurve) ShapeConstruct_Curve::ConvertToBSpline (const Handle(Geom_Curve) &C,
140 const Standard_Real first,
141 const Standard_Real last,
142 const Standard_Real prec) const
143{
144 Handle(Geom_BSplineCurve) bspl;
145
146 if ( C->IsKind(STANDARD_TYPE(Geom_BSplineCurve)) ) {
147 bspl = Handle(Geom_BSplineCurve)::DownCast ( C );
148 }
149 else if ( C->IsKind(STANDARD_TYPE(Geom_BezierCurve)) ||
150 C->IsKind(STANDARD_TYPE(Geom_Line)) ) {
151 Handle(Geom_Curve) tc = new Geom_TrimmedCurve ( C, first, last );
152 try {
153 OCC_CATCH_SIGNALS
154 bspl = GeomConvert::CurveToBSplineCurve(tc);
155 }
156 catch ( Standard_Failure ) {
0797d9d3 157#ifdef OCCT_DEBUG
7fd59977 158 cout << "Warning: ShapeConstruct_Curve::ConvertToBSpline(): Exception in GeomConvert: ";
159 Standard_Failure::Caught()->Print(cout); cout << endl;
160#endif
161 }
162 }
163
164 if ( ! bspl.IsNull() ) {
165 // take segment if trim and range differ
166 Standard_Real fbsp = bspl->FirstParameter(), lbsp = bspl->LastParameter();
167 Standard_Boolean segment = Standard_False;
168 if ( first > fbsp + Precision::PConfusion() ) { fbsp = first; segment = Standard_True; }
169 if ( last < lbsp - Precision::PConfusion() ) { lbsp = last; segment = Standard_True; }
170 if ( ! segment ) return bspl;
171 try {
172 OCC_CATCH_SIGNALS
173 bspl = Handle(Geom_BSplineCurve)::DownCast ( bspl->Copy() );
174 bspl->Segment ( fbsp, lbsp );
175 return bspl;
176 }
177 catch ( Standard_Failure ) {
0797d9d3 178#ifdef OCCT_DEBUG
7fd59977 179 cout << "Warning: ShapeConstruct_Curve::ConvertToBSpline(): Exception in Segment: ";
180 Standard_Failure::Caught()->Print(cout); cout << endl;
181#endif
182 }
183 }
184
185 // Approx is used for conics and when ordinary methods fail
186 Handle(Geom_Curve) newc = C;
187 if ( ! bspl.IsNull() ) { newc = bspl; bspl.Nullify(); }
188 try {
189 OCC_CATCH_SIGNALS
190 Approx_Curve3d Conv ( new GeomAdaptor_HCurve(newc,first,last),
191 prec, GeomAbs_C1, 9, 1000 );
192 if ( Conv.IsDone() || Conv.HasResult() )
193 bspl = Conv.Curve();
194 }
195 catch ( Standard_Failure ) {
0797d9d3 196#ifdef OCCT_DEBUG
7fd59977 197 cout << "Warning: ShapeConstruct_Curve::ConvertToBSpline(): Exception in Approx_Curve3d: ";
198 Standard_Failure::Caught()->Print(cout); cout << endl;
199#endif
200 }
201 return bspl;
202}
203
204//=======================================================================
205//function : ConvertToBSpline
206//purpose :
207//=======================================================================
208
209Handle(Geom2d_BSplineCurve) ShapeConstruct_Curve::ConvertToBSpline (const Handle(Geom2d_Curve) &C,
210 const Standard_Real first,
211 const Standard_Real last,
212 const Standard_Real prec) const
213{
214 Handle(Geom2d_BSplineCurve) bspl;
215
216 if ( C->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve)) ) {
217 bspl = Handle(Geom2d_BSplineCurve)::DownCast ( C );
218 }
219 else if ( C->IsKind(STANDARD_TYPE(Geom2d_BezierCurve)) ||
220 C->IsKind(STANDARD_TYPE(Geom2d_Line)) ) {
221 Handle(Geom2d_Curve) tc = new Geom2d_TrimmedCurve ( C, first, last );
222 try {
223 OCC_CATCH_SIGNALS
224 bspl = Geom2dConvert::CurveToBSplineCurve(tc);
225 }
226 catch ( Standard_Failure ) {
0797d9d3 227#ifdef OCCT_DEBUG
7fd59977 228 cout << "Warning: ShapeConstruct_Curve::ConvertToBSpline(): Exception in Geom2dConvert: ";
229 Standard_Failure::Caught()->Print(cout); cout << endl;
230#endif
231 }
232 }
233
234 if ( ! bspl.IsNull() ) {
235 // take segment if trim and range differ
236 Standard_Real fbsp = bspl->FirstParameter(), lbsp = bspl->LastParameter();
237 Standard_Boolean segment = Standard_False;
238 if ( first > fbsp + Precision::PConfusion() ) { fbsp = first; segment = Standard_True; }
239 if ( last < lbsp - Precision::PConfusion() ) { lbsp = last; segment = Standard_True; }
240 if ( ! segment ) return bspl;
241 try {
242 OCC_CATCH_SIGNALS
243 bspl = Handle(Geom2d_BSplineCurve)::DownCast ( bspl->Copy() );
244 bspl->Segment ( fbsp, lbsp );
245 return bspl;
246 }
247 catch ( Standard_Failure ) {
0797d9d3 248#ifdef OCCT_DEBUG
7fd59977 249 cout << "Warning: ShapeConstruct_Curve::ConvertToBSpline(): Exception in Segment: ";
250 Standard_Failure::Caught()->Print(cout); cout << endl;
251#endif
252 }
253 }
254
255 // Approx is used for conics and when ordinary methods fail
256 Handle(Geom2d_Curve) newc = C;
257 if ( ! bspl.IsNull() ) { newc = bspl; bspl.Nullify(); }
258 try {
259 OCC_CATCH_SIGNALS
260 Approx_Curve2d Conv ( new Geom2dAdaptor_HCurve(newc,first,last),
261 first, last,
262 prec, prec, GeomAbs_C1, 9, 1000 );
263 if ( Conv.IsDone() || Conv.HasResult() )
264 bspl = Conv.Curve();
265 }
266 catch ( Standard_Failure ) {
0797d9d3 267#ifdef OCCT_DEBUG
7fd59977 268 cout << "Warning: ShapeConstruct_Curve::ConvertToBSpline(): Exception in Approx_Curve3d: ";
269 Standard_Failure::Caught()->Print(cout); cout << endl;
270#endif
271 }
272 return bspl;
273}
274
275//=======================================================================
276//function : FixKnots
277//purpose : Fix coincided knots
278//=======================================================================
279Standard_Boolean ShapeConstruct_Curve::FixKnots (Handle(TColStd_HArray1OfReal) &knots)
280{
281 Standard_Boolean Fixed = Standard_False;
282 Standard_Integer nbKnots = knots->Length();
283 Standard_Real knotVal = knots->Value(1);
284 for ( Standard_Integer i=2; i <= nbKnots; i++ ) {
285 Standard_Real knotNext = knots->Value(i);
286 if ( knotNext - knotVal <= Epsilon(knotVal) ) {
287 knotNext = knotVal + 2. * Epsilon(knotVal);
288 knots->SetValue ( i, knotNext );
289 Fixed = Standard_True;
290 }
291 knotVal = knotNext;
292 }
293 return Fixed;
294}
295
296//=======================================================================
297//function : FixKnots
298//purpose : Fix coincided knots
299//=======================================================================
300Standard_Boolean ShapeConstruct_Curve::FixKnots (TColStd_Array1OfReal& knots)
301{
302 Standard_Boolean Fixed = Standard_False;
303 Standard_Integer nbKnots = knots.Length();
304 Standard_Real knotVal = knots.Value(1);
305 for ( Standard_Integer i=2; i <= nbKnots; i++ ) {
306 Standard_Real knotNext = knots.Value(i);
307 if ( knotNext - knotVal <= Epsilon(knotVal) ) {
308 knotNext = knotVal + 2. * Epsilon(knotVal);
309 knots.SetValue ( i, knotNext );
310 Fixed = Standard_True;
311 }
312 knotVal = knotNext;
313 }
314 return Fixed;
315}
316