0031687: Draw Harness, ViewerTest - extend command vrenderparams with option updating...
[occt.git] / src / ShapeConstruct / ShapeConstruct_Curve.cxx
1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
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.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14
15 #include <Approx_Curve2d.hxx>
16 #include <Approx_Curve3d.hxx>
17 #include <ElCLib.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>
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>
41
42 //sln 29.12.2001 OCC90 : Method FixKnots was added
43 //=======================================================================
44 //function : AdjustCurve
45 //purpose  : 
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
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
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
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
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
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
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
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 const& anException) {
157 #ifdef OCCT_DEBUG
158       std::cout << "Warning: ShapeConstruct_Curve::ConvertToBSpline(): Exception in GeomConvert: ";
159       anException.Print(std::cout); std::cout << std::endl;
160 #endif
161       (void)anException;
162     }
163   }
164
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;
172     try {
173       OCC_CATCH_SIGNALS
174       bspl = Handle(Geom_BSplineCurve)::DownCast ( bspl->Copy() );
175       bspl->Segment ( fbsp, lbsp );
176       return bspl;
177     }
178     catch ( Standard_Failure const& anException) {
179 #ifdef OCCT_DEBUG
180       std::cout << "Warning: ShapeConstruct_Curve::ConvertToBSpline(): Exception in Segment: ";
181       anException.Print(std::cout); std::cout << std::endl;
182 #endif
183       (void)anException;
184     }
185   }
186
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(); }
190   try {
191     OCC_CATCH_SIGNALS
192     Approx_Curve3d Conv ( new GeomAdaptor_HCurve(newc,first,last),
193                           prec, GeomAbs_C1, 9, 1000 );
194     if ( Conv.IsDone() || Conv.HasResult() ) 
195       bspl = Conv.Curve();
196   }
197   catch (Standard_Failure const& anException) {
198 #ifdef OCCT_DEBUG
199     std::cout << "Warning: ShapeConstruct_Curve::ConvertToBSpline(): Exception in Approx_Curve3d: ";
200     anException.Print(std::cout); std::cout << std::endl;
201 #endif
202     (void)anException;
203   }
204   return bspl;
205 }
206
207 //=======================================================================
208 //function : ConvertToBSpline
209 //purpose  : 
210 //=======================================================================
211
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
216 {
217   Handle(Geom2d_BSplineCurve) bspl;
218   
219   if ( C->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve)) ) {
220     bspl = Handle(Geom2d_BSplineCurve)::DownCast ( C );
221   }
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 );
225     try {
226       OCC_CATCH_SIGNALS
227       bspl = Geom2dConvert::CurveToBSplineCurve(tc);
228     }
229     catch ( Standard_Failure const& anException) {
230 #ifdef OCCT_DEBUG
231       std::cout << "Warning: ShapeConstruct_Curve::ConvertToBSpline(): Exception in Geom2dConvert: ";
232       anException.Print(std::cout); std::cout << std::endl;
233 #endif
234       (void)anException;
235     }
236   }
237
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;
245     try {
246       OCC_CATCH_SIGNALS
247       bspl = Handle(Geom2d_BSplineCurve)::DownCast ( bspl->Copy() );
248       bspl->Segment ( fbsp, lbsp );
249       return bspl;
250     }
251     catch ( Standard_Failure const& anException) {
252 #ifdef OCCT_DEBUG
253       std::cout << "Warning: ShapeConstruct_Curve::ConvertToBSpline(): Exception in Segment: ";
254       anException.Print(std::cout); std::cout << std::endl;
255 #endif
256       (void)anException;
257     }
258   }
259
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(); }
263   try {
264     OCC_CATCH_SIGNALS
265     Approx_Curve2d Conv ( new Geom2dAdaptor_HCurve(newc,first,last),
266                           first, last,
267                           prec, prec, GeomAbs_C1, 9, 1000 );
268     if ( Conv.IsDone() || Conv.HasResult() ) 
269       bspl = Conv.Curve();
270   }
271   catch ( Standard_Failure const& anException) {
272 #ifdef OCCT_DEBUG
273     std::cout << "Warning: ShapeConstruct_Curve::ConvertToBSpline(): Exception in Approx_Curve3d: ";
274     anException.Print(std::cout); std::cout << std::endl;
275 #endif
276     (void)anException;
277   }
278   return bspl;
279 }
280
281 //=======================================================================
282 //function : FixKnots
283 //purpose  : Fix coincided knots
284 //=======================================================================
285 Standard_Boolean ShapeConstruct_Curve::FixKnots (Handle(TColStd_HArray1OfReal) &knots) 
286 {
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;
296     }
297     knotVal = knotNext;
298   }
299   return Fixed;
300 }
301
302 //=======================================================================
303 //function : FixKnots
304 //purpose  : Fix coincided knots
305 //=======================================================================
306 Standard_Boolean ShapeConstruct_Curve::FixKnots (TColStd_Array1OfReal& knots) 
307 {
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;
317     }
318     knotVal = knotNext;
319   }
320   return Fixed;
321 }
322