1 #include <ShapeConstruct_Curve.ixx>
3 #include <Standard_ErrorHandler.hxx>
4 #include <Standard_Failure.hxx>
11 #include <Precision.hxx>
13 #include <Geom_BSplineCurve.hxx>
14 #include <Geom_BezierCurve.hxx>
15 #include <Geom_TrimmedCurve.hxx>
16 #include <Geom_Line.hxx>
18 #include <Geom2d_BSplineCurve.hxx>
19 #include <Geom2d_BezierCurve.hxx>
20 #include <Geom2d_TrimmedCurve.hxx>
21 #include <Geom2d_Line.hxx>
23 #include <GeomConvert.hxx>
24 #include <GeomAdaptor_HCurve.hxx>
25 #include <Approx_Curve3d.hxx>
27 #include <Geom2dConvert.hxx>
28 #include <Geom2dAdaptor_HCurve.hxx>
29 #include <Approx_Curve2d.hxx>
31 //sln 29.12.2001 OCC90 : Method FixKnots was added
33 //=======================================================================
34 //function : AdjustCurve
36 //=======================================================================
38 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
40 if (!take1 && !take2) return Standard_True;
42 if (C3D->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) {
43 Handle(Geom_BSplineCurve) BSPL = Handle(Geom_BSplineCurve)::DownCast(C3D);
44 if (take1) BSPL->SetPole (1,P1);
45 if (take2) BSPL->SetPole (BSPL->NbPoles(),P2);
49 if (C3D->IsKind(STANDARD_TYPE(Geom_Line))) {
50 Handle(Geom_Line) L3D = Handle(Geom_Line)::DownCast(C3D);
51 // ATTENTION, P1 et P2 sont supposes tous deux pertinents ...
52 gp_Vec avec (P1,P2); gp_Dir adir (avec); gp_Lin alin (P1,adir);
53 Standard_Real theParam = ElCLib::Parameter(alin, L3D->Lin().Location());
54 alin.SetLocation (ElCLib::Value(theParam, alin));
59 return Standard_False;
62 //=======================================================================
63 //function : AdjustCurveSegment
65 //=======================================================================
67 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
69 if (C3D->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) {
70 Handle(Geom_BSplineCurve) BSPL = Handle(Geom_BSplineCurve)::DownCast(C3D);
71 // Forcer l extremite c est bien
72 // Propager sur le reste, c est pas mal non plus
73 if (U1 >= U2) return Standard_False;
74 Standard_Real UU1 = Max (U1,BSPL->FirstParameter());
75 Standard_Real UU2 = Min (U2,BSPL->LastParameter());
76 BSPL->Segment (UU1,UU2);
78 BSPL->SetPole (BSPL->NbPoles(),P2);
82 if (C3D->IsKind(STANDARD_TYPE(Geom_Line))) {
83 Handle(Geom_Line) L3D = Handle(Geom_Line)::DownCast(C3D);
84 // ATTENTION, P1 et P2 sont supposes tous deux pertinents ...
85 // NB : on ne s aide pas de U1 et U2
86 gp_Vec avec (P1,P2); gp_Dir adir (avec); gp_Lin alin (P1,adir);
87 Standard_Real theParam = ElCLib::Parameter(alin, L3D->Lin().Location());
88 alin.SetLocation (ElCLib::Value(theParam, alin));
93 return Standard_False;
96 //=======================================================================
97 //function : AdjustCurve2d
99 //=======================================================================
101 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
103 if (!take1 && !take2) return Standard_True;
105 if (C2D->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))) {
106 Handle(Geom2d_BSplineCurve) BSPL = Handle(Geom2d_BSplineCurve)::DownCast(C2D);
107 if (take1) BSPL->SetPole (1,P1);
108 if (take2) BSPL->SetPole (BSPL->NbPoles(),P2);
109 return Standard_True;
112 if (C2D->IsKind(STANDARD_TYPE(Geom2d_Line))) {
113 Handle(Geom2d_Line) L2D = Handle(Geom2d_Line)::DownCast(C2D);
114 // ATTENTION, P1 et P2 sont supposes tous deux pertinents ...
115 gp_Vec2d avec (P1,P2); gp_Dir2d adir (avec); gp_Lin2d alin (P1,adir);
116 Standard_Real theParam = ElCLib::Parameter(alin, L2D->Lin2d().Location());
117 alin.SetLocation (ElCLib::Value(theParam, alin));
118 L2D->SetLin2d (alin);
119 return Standard_True;
122 return Standard_False;
125 //=======================================================================
126 //function : ConvertToBSpline
128 //=======================================================================
130 Handle(Geom_BSplineCurve) ShapeConstruct_Curve::ConvertToBSpline (const Handle(Geom_Curve) &C,
131 const Standard_Real first,
132 const Standard_Real last,
133 const Standard_Real prec) const
135 Handle(Geom_BSplineCurve) bspl;
137 if ( C->IsKind(STANDARD_TYPE(Geom_BSplineCurve)) ) {
138 bspl = Handle(Geom_BSplineCurve)::DownCast ( C );
140 else if ( C->IsKind(STANDARD_TYPE(Geom_BezierCurve)) ||
141 C->IsKind(STANDARD_TYPE(Geom_Line)) ) {
142 Handle(Geom_Curve) tc = new Geom_TrimmedCurve ( C, first, last );
145 bspl = GeomConvert::CurveToBSplineCurve(tc);
147 catch ( Standard_Failure ) {
149 cout << "Warning: ShapeConstruct_Curve::ConvertToBSpline(): Exception in GeomConvert: ";
150 Standard_Failure::Caught()->Print(cout); cout << endl;
155 if ( ! bspl.IsNull() ) {
156 // take segment if trim and range differ
157 Standard_Real fbsp = bspl->FirstParameter(), lbsp = bspl->LastParameter();
158 Standard_Boolean segment = Standard_False;
159 if ( first > fbsp + Precision::PConfusion() ) { fbsp = first; segment = Standard_True; }
160 if ( last < lbsp - Precision::PConfusion() ) { lbsp = last; segment = Standard_True; }
161 if ( ! segment ) return bspl;
164 bspl = Handle(Geom_BSplineCurve)::DownCast ( bspl->Copy() );
165 bspl->Segment ( fbsp, lbsp );
168 catch ( Standard_Failure ) {
170 cout << "Warning: ShapeConstruct_Curve::ConvertToBSpline(): Exception in Segment: ";
171 Standard_Failure::Caught()->Print(cout); cout << endl;
176 // Approx is used for conics and when ordinary methods fail
177 Handle(Geom_Curve) newc = C;
178 if ( ! bspl.IsNull() ) { newc = bspl; bspl.Nullify(); }
181 Approx_Curve3d Conv ( new GeomAdaptor_HCurve(newc,first,last),
182 prec, GeomAbs_C1, 9, 1000 );
183 if ( Conv.IsDone() || Conv.HasResult() )
186 catch ( Standard_Failure ) {
188 cout << "Warning: ShapeConstruct_Curve::ConvertToBSpline(): Exception in Approx_Curve3d: ";
189 Standard_Failure::Caught()->Print(cout); cout << endl;
195 //=======================================================================
196 //function : ConvertToBSpline
198 //=======================================================================
200 Handle(Geom2d_BSplineCurve) ShapeConstruct_Curve::ConvertToBSpline (const Handle(Geom2d_Curve) &C,
201 const Standard_Real first,
202 const Standard_Real last,
203 const Standard_Real prec) const
205 Handle(Geom2d_BSplineCurve) bspl;
207 if ( C->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve)) ) {
208 bspl = Handle(Geom2d_BSplineCurve)::DownCast ( C );
210 else if ( C->IsKind(STANDARD_TYPE(Geom2d_BezierCurve)) ||
211 C->IsKind(STANDARD_TYPE(Geom2d_Line)) ) {
212 Handle(Geom2d_Curve) tc = new Geom2d_TrimmedCurve ( C, first, last );
215 bspl = Geom2dConvert::CurveToBSplineCurve(tc);
217 catch ( Standard_Failure ) {
219 cout << "Warning: ShapeConstruct_Curve::ConvertToBSpline(): Exception in Geom2dConvert: ";
220 Standard_Failure::Caught()->Print(cout); cout << endl;
225 if ( ! bspl.IsNull() ) {
226 // take segment if trim and range differ
227 Standard_Real fbsp = bspl->FirstParameter(), lbsp = bspl->LastParameter();
228 Standard_Boolean segment = Standard_False;
229 if ( first > fbsp + Precision::PConfusion() ) { fbsp = first; segment = Standard_True; }
230 if ( last < lbsp - Precision::PConfusion() ) { lbsp = last; segment = Standard_True; }
231 if ( ! segment ) return bspl;
234 bspl = Handle(Geom2d_BSplineCurve)::DownCast ( bspl->Copy() );
235 bspl->Segment ( fbsp, lbsp );
238 catch ( Standard_Failure ) {
240 cout << "Warning: ShapeConstruct_Curve::ConvertToBSpline(): Exception in Segment: ";
241 Standard_Failure::Caught()->Print(cout); cout << endl;
246 // Approx is used for conics and when ordinary methods fail
247 Handle(Geom2d_Curve) newc = C;
248 if ( ! bspl.IsNull() ) { newc = bspl; bspl.Nullify(); }
251 Approx_Curve2d Conv ( new Geom2dAdaptor_HCurve(newc,first,last),
253 prec, prec, GeomAbs_C1, 9, 1000 );
254 if ( Conv.IsDone() || Conv.HasResult() )
257 catch ( Standard_Failure ) {
259 cout << "Warning: ShapeConstruct_Curve::ConvertToBSpline(): Exception in Approx_Curve3d: ";
260 Standard_Failure::Caught()->Print(cout); cout << endl;
266 //=======================================================================
267 //function : FixKnots
268 //purpose : Fix coincided knots
269 //=======================================================================
270 Standard_Boolean ShapeConstruct_Curve::FixKnots (Handle(TColStd_HArray1OfReal) &knots)
272 Standard_Boolean Fixed = Standard_False;
273 Standard_Integer nbKnots = knots->Length();
274 Standard_Real knotVal = knots->Value(1);
275 for ( Standard_Integer i=2; i <= nbKnots; i++ ) {
276 Standard_Real knotNext = knots->Value(i);
277 if ( knotNext - knotVal <= Epsilon(knotVal) ) {
278 knotNext = knotVal + 2. * Epsilon(knotVal);
279 knots->SetValue ( i, knotNext );
280 Fixed = Standard_True;
287 //=======================================================================
288 //function : FixKnots
289 //purpose : Fix coincided knots
290 //=======================================================================
291 Standard_Boolean ShapeConstruct_Curve::FixKnots (TColStd_Array1OfReal& knots)
293 Standard_Boolean Fixed = Standard_False;
294 Standard_Integer nbKnots = knots.Length();
295 Standard_Real knotVal = knots.Value(1);
296 for ( Standard_Integer i=2; i <= nbKnots; i++ ) {
297 Standard_Real knotNext = knots.Value(i);
298 if ( knotNext - knotVal <= Epsilon(knotVal) ) {
299 knotNext = knotVal + 2. * Epsilon(knotVal);
300 knots.SetValue ( i, knotNext );
301 Fixed = Standard_True;