1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 // This file is part of Open CASCADE Technology software library.
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
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.
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
15 #include <Approx_Curve2d.hxx>
16 #include <Approx_Curve3d.hxx>
18 #include <Geom2d_BezierCurve.hxx>
19 #include <Geom2d_BSplineCurve.hxx>
20 #include <Geom2d_Curve.hxx>
21 #include <Geom2d_Line.hxx>
22 #include <Geom2d_TrimmedCurve.hxx>
23 #include <Geom2dAdaptor_HCurve.hxx>
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>
35 #include <gp_Pnt2d.hxx>
37 #include <Precision.hxx>
38 #include <ShapeConstruct_Curve.hxx>
39 #include <Standard_ErrorHandler.hxx>
40 #include <Standard_Failure.hxx>
42 //sln 29.12.2001 OCC90 : Method FixKnots was added
43 //=======================================================================
44 //function : AdjustCurve
46 //=======================================================================
47 Standard_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
49 if (!take1 && !take2) return Standard_True;
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);
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));
68 return Standard_False;
71 //=======================================================================
72 //function : AdjustCurveSegment
74 //=======================================================================
76 Standard_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
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);
87 BSPL->SetPole (BSPL->NbPoles(),P2);
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));
102 return Standard_False;
105 //=======================================================================
106 //function : AdjustCurve2d
108 //=======================================================================
110 Standard_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
112 if (!take1 && !take2) return Standard_True;
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;
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;
131 return Standard_False;
134 //=======================================================================
135 //function : ConvertToBSpline
137 //=======================================================================
139 Handle(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
144 Handle(Geom_BSplineCurve) bspl;
146 if ( C->IsKind(STANDARD_TYPE(Geom_BSplineCurve)) ) {
147 bspl = Handle(Geom_BSplineCurve)::DownCast ( C );
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 );
154 bspl = GeomConvert::CurveToBSplineCurve(tc);
156 catch ( Standard_Failure const& anException) {
158 std::cout << "Warning: ShapeConstruct_Curve::ConvertToBSpline(): Exception in GeomConvert: ";
159 anException.Print(std::cout); std::cout << std::endl;
165 if ( ! bspl.IsNull() ) {
166 // take segment if trim and range differ
167 Standard_Real fbsp = bspl->FirstParameter(), lbsp = bspl->LastParameter();
168 Standard_Boolean segment = Standard_False;
169 if ( first > fbsp + Precision::PConfusion() ) { fbsp = first; segment = Standard_True; }
170 if ( last < lbsp - Precision::PConfusion() ) { lbsp = last; segment = Standard_True; }
171 if ( ! segment ) return bspl;
174 bspl = Handle(Geom_BSplineCurve)::DownCast ( bspl->Copy() );
175 bspl->Segment ( fbsp, lbsp );
178 catch ( Standard_Failure const& anException) {
180 std::cout << "Warning: ShapeConstruct_Curve::ConvertToBSpline(): Exception in Segment: ";
181 anException.Print(std::cout); std::cout << std::endl;
187 // Approx is used for conics and when ordinary methods fail
188 Handle(Geom_Curve) newc = C;
189 if ( ! bspl.IsNull() ) { newc = bspl; bspl.Nullify(); }
192 Approx_Curve3d Conv ( new GeomAdaptor_HCurve(newc,first,last),
193 prec, GeomAbs_C1, 9, 1000 );
194 if ( Conv.IsDone() || Conv.HasResult() )
197 catch (Standard_Failure const& anException) {
199 std::cout << "Warning: ShapeConstruct_Curve::ConvertToBSpline(): Exception in Approx_Curve3d: ";
200 anException.Print(std::cout); std::cout << std::endl;
207 //=======================================================================
208 //function : ConvertToBSpline
210 //=======================================================================
212 Handle(Geom2d_BSplineCurve) ShapeConstruct_Curve::ConvertToBSpline (const Handle(Geom2d_Curve) &C,
213 const Standard_Real first,
214 const Standard_Real last,
215 const Standard_Real prec) const
217 Handle(Geom2d_BSplineCurve) bspl;
219 if ( C->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve)) ) {
220 bspl = Handle(Geom2d_BSplineCurve)::DownCast ( C );
222 else if ( C->IsKind(STANDARD_TYPE(Geom2d_BezierCurve)) ||
223 C->IsKind(STANDARD_TYPE(Geom2d_Line)) ) {
224 Handle(Geom2d_Curve) tc = new Geom2d_TrimmedCurve ( C, first, last );
227 bspl = Geom2dConvert::CurveToBSplineCurve(tc);
229 catch ( Standard_Failure const& anException) {
231 std::cout << "Warning: ShapeConstruct_Curve::ConvertToBSpline(): Exception in Geom2dConvert: ";
232 anException.Print(std::cout); std::cout << std::endl;
238 if ( ! bspl.IsNull() ) {
239 // take segment if trim and range differ
240 Standard_Real fbsp = bspl->FirstParameter(), lbsp = bspl->LastParameter();
241 Standard_Boolean segment = Standard_False;
242 if ( first > fbsp + Precision::PConfusion() ) { fbsp = first; segment = Standard_True; }
243 if ( last < lbsp - Precision::PConfusion() ) { lbsp = last; segment = Standard_True; }
244 if ( ! segment ) return bspl;
247 bspl = Handle(Geom2d_BSplineCurve)::DownCast ( bspl->Copy() );
248 bspl->Segment ( fbsp, lbsp );
251 catch ( Standard_Failure const& anException) {
253 std::cout << "Warning: ShapeConstruct_Curve::ConvertToBSpline(): Exception in Segment: ";
254 anException.Print(std::cout); std::cout << std::endl;
260 // Approx is used for conics and when ordinary methods fail
261 Handle(Geom2d_Curve) newc = C;
262 if ( ! bspl.IsNull() ) { newc = bspl; bspl.Nullify(); }
265 Approx_Curve2d Conv ( new Geom2dAdaptor_HCurve(newc,first,last),
267 prec, prec, GeomAbs_C1, 9, 1000 );
268 if ( Conv.IsDone() || Conv.HasResult() )
271 catch ( Standard_Failure const& anException) {
273 std::cout << "Warning: ShapeConstruct_Curve::ConvertToBSpline(): Exception in Approx_Curve3d: ";
274 anException.Print(std::cout); std::cout << std::endl;
281 //=======================================================================
282 //function : FixKnots
283 //purpose : Fix coincided knots
284 //=======================================================================
285 Standard_Boolean ShapeConstruct_Curve::FixKnots (Handle(TColStd_HArray1OfReal) &knots)
287 Standard_Boolean Fixed = Standard_False;
288 Standard_Integer nbKnots = knots->Length();
289 Standard_Real knotVal = knots->Value(1);
290 for ( Standard_Integer i=2; i <= nbKnots; i++ ) {
291 Standard_Real knotNext = knots->Value(i);
292 if ( knotNext - knotVal <= Epsilon(knotVal) ) {
293 knotNext = knotVal + 2. * Epsilon(knotVal);
294 knots->SetValue ( i, knotNext );
295 Fixed = Standard_True;
302 //=======================================================================
303 //function : FixKnots
304 //purpose : Fix coincided knots
305 //=======================================================================
306 Standard_Boolean ShapeConstruct_Curve::FixKnots (TColStd_Array1OfReal& knots)
308 Standard_Boolean Fixed = Standard_False;
309 Standard_Integer nbKnots = knots.Length();
310 Standard_Real knotVal = knots.Value(1);
311 for ( Standard_Integer i=2; i <= nbKnots; i++ ) {
312 Standard_Real knotNext = knots.Value(i);
313 if ( knotNext - knotVal <= Epsilon(knotVal) ) {
314 knotNext = knotVal + 2. * Epsilon(knotVal);
315 knots.SetValue ( i, knotNext );
316 Fixed = Standard_True;