Integration of OCCT 6.5.0 from SVN
[occt.git] / src / ShapeConstruct / ShapeConstruct_Curve.cxx
1 #include <ShapeConstruct_Curve.ixx>
2
3 #include <Standard_ErrorHandler.hxx>
4 #include <Standard_Failure.hxx>
5
6 #include <gp_Vec.hxx>
7 #include <gp_Dir.hxx>
8 #include <gp_Lin.hxx>
9
10 #include <ElCLib.hxx>
11 #include <Precision.hxx>
12
13 #include <Geom_BSplineCurve.hxx>
14 #include <Geom_BezierCurve.hxx>
15 #include <Geom_TrimmedCurve.hxx>
16 #include <Geom_Line.hxx>
17
18 #include <Geom2d_BSplineCurve.hxx>
19 #include <Geom2d_BezierCurve.hxx>
20 #include <Geom2d_TrimmedCurve.hxx>
21 #include <Geom2d_Line.hxx>
22
23 #include <GeomConvert.hxx>
24 #include <GeomAdaptor_HCurve.hxx>
25 #include <Approx_Curve3d.hxx>
26
27 #include <Geom2dConvert.hxx>
28 #include <Geom2dAdaptor_HCurve.hxx>
29 #include <Approx_Curve2d.hxx>
30
31 //sln 29.12.2001 OCC90 : Method FixKnots was added
32
33 //=======================================================================
34 //function : AdjustCurve
35 //purpose  : 
36 //=======================================================================
37
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
39 {
40   if (!take1 && !take2) return Standard_True;
41
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);
46     return Standard_True;
47   }
48
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));
55     L3D->SetLin (alin);
56     return Standard_True;
57   }
58
59   return Standard_False;
60 }
61
62 //=======================================================================
63 //function : AdjustCurveSegment
64 //purpose  : 
65 //=======================================================================
66
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
68 {
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);
77     BSPL->SetPole (1,P1);
78     BSPL->SetPole (BSPL->NbPoles(),P2);
79     return Standard_True;
80   }
81     
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));
89     L3D->SetLin (alin);
90     return Standard_True;
91   }
92
93   return Standard_False;
94 }
95
96 //=======================================================================
97 //function : AdjustCurve2d
98 //purpose  : 
99 //=======================================================================
100
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
102 {
103   if (!take1 && !take2) return Standard_True;
104
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;
110   }
111
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;
120   }
121
122   return Standard_False;
123 }
124
125 //=======================================================================
126 //function : ConvertToBSpline
127 //purpose  : 
128 //=======================================================================
129
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
134 {
135   Handle(Geom_BSplineCurve) bspl;
136   
137   if ( C->IsKind(STANDARD_TYPE(Geom_BSplineCurve)) ) {
138     bspl = Handle(Geom_BSplineCurve)::DownCast ( C );
139   }
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 );
143     try {
144       OCC_CATCH_SIGNALS
145       bspl = GeomConvert::CurveToBSplineCurve(tc);
146     }
147     catch ( Standard_Failure ) {
148 #ifdef DEB 
149       cout << "Warning: ShapeConstruct_Curve::ConvertToBSpline(): Exception in GeomConvert: ";
150       Standard_Failure::Caught()->Print(cout); cout << endl;
151 #endif
152     }
153   }
154
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;
162     try {
163       OCC_CATCH_SIGNALS
164       bspl = Handle(Geom_BSplineCurve)::DownCast ( bspl->Copy() );
165       bspl->Segment ( fbsp, lbsp );
166       return bspl;
167     }
168     catch ( Standard_Failure ) {
169 #ifdef DEB 
170       cout << "Warning: ShapeConstruct_Curve::ConvertToBSpline(): Exception in Segment: ";
171       Standard_Failure::Caught()->Print(cout); cout << endl;
172 #endif
173     }
174   }
175
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(); }
179   try {
180     OCC_CATCH_SIGNALS
181     Approx_Curve3d Conv ( new GeomAdaptor_HCurve(newc,first,last),
182                           prec, GeomAbs_C1, 9, 1000 );
183     if ( Conv.IsDone() || Conv.HasResult() ) 
184       bspl = Conv.Curve();
185   }
186   catch ( Standard_Failure ) {
187 #ifdef DEB 
188     cout << "Warning: ShapeConstruct_Curve::ConvertToBSpline(): Exception in Approx_Curve3d: ";
189     Standard_Failure::Caught()->Print(cout); cout << endl;
190 #endif
191   }
192   return bspl;
193 }
194
195 //=======================================================================
196 //function : ConvertToBSpline
197 //purpose  : 
198 //=======================================================================
199
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
204 {
205   Handle(Geom2d_BSplineCurve) bspl;
206   
207   if ( C->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve)) ) {
208     bspl = Handle(Geom2d_BSplineCurve)::DownCast ( C );
209   }
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 );
213     try {
214       OCC_CATCH_SIGNALS
215       bspl = Geom2dConvert::CurveToBSplineCurve(tc);
216     }
217     catch ( Standard_Failure ) {
218 #ifdef DEB 
219       cout << "Warning: ShapeConstruct_Curve::ConvertToBSpline(): Exception in Geom2dConvert: ";
220       Standard_Failure::Caught()->Print(cout); cout << endl;
221 #endif
222     }
223   }
224
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;
232     try {
233       OCC_CATCH_SIGNALS
234       bspl = Handle(Geom2d_BSplineCurve)::DownCast ( bspl->Copy() );
235       bspl->Segment ( fbsp, lbsp );
236       return bspl;
237     }
238     catch ( Standard_Failure ) {
239 #ifdef DEB 
240       cout << "Warning: ShapeConstruct_Curve::ConvertToBSpline(): Exception in Segment: ";
241       Standard_Failure::Caught()->Print(cout); cout << endl;
242 #endif
243     }
244   }
245
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(); }
249   try {
250     OCC_CATCH_SIGNALS
251     Approx_Curve2d Conv ( new Geom2dAdaptor_HCurve(newc,first,last),
252                           first, last,
253                           prec, prec, GeomAbs_C1, 9, 1000 );
254     if ( Conv.IsDone() || Conv.HasResult() ) 
255       bspl = Conv.Curve();
256   }
257   catch ( Standard_Failure ) {
258 #ifdef DEB 
259     cout << "Warning: ShapeConstruct_Curve::ConvertToBSpline(): Exception in Approx_Curve3d: ";
260     Standard_Failure::Caught()->Print(cout); cout << endl;
261 #endif
262   }
263   return bspl;
264 }
265
266 //=======================================================================
267 //function : FixKnots
268 //purpose  : Fix coincided knots
269 //=======================================================================
270 Standard_Boolean ShapeConstruct_Curve::FixKnots (Handle(TColStd_HArray1OfReal) &knots) 
271 {
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;
281     }
282     knotVal = knotNext;
283   }
284   return Fixed;
285 }
286
287 //=======================================================================
288 //function : FixKnots
289 //purpose  : Fix coincided knots
290 //=======================================================================
291 Standard_Boolean ShapeConstruct_Curve::FixKnots (TColStd_Array1OfReal& knots) 
292 {
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;
302     }
303     knotVal = knotNext;
304   }
305   return Fixed;
306 }
307