0026838: Using GeomEvaluators for calculation of values of curves
[occt.git] / src / Geom / Geom_OffsetCurve.cxx
1 // Created on: 1991-06-25
2 // Created by: JCV
3 // Copyright (c) 1991-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 // 24-Aug-95 : xab removed C1 and C2 test : appeller  D1 et D2 
18 //             avec discernement !
19 // 19-09-97  : JPI correction derivee seconde
20
21 #include <Geom_BezierCurve.hxx>
22 #include <Geom_BSplineCurve.hxx>
23 #include <Geom_Circle.hxx>
24 #include <Geom_Curve.hxx>
25 #include <Geom_Ellipse.hxx>
26 #include <Geom_Geometry.hxx>
27 #include <Geom_Hyperbola.hxx>
28 #include <Geom_Line.hxx>
29 #include <Geom_OffsetCurve.hxx>
30 #include <Geom_Parabola.hxx>
31 #include <Geom_TrimmedCurve.hxx>
32 #include <Geom_UndefinedDerivative.hxx>
33 #include <Geom_UndefinedValue.hxx>
34 #include <gp.hxx>
35 #include <gp_Dir.hxx>
36 #include <gp_Pnt.hxx>
37 #include <gp_Trsf.hxx>
38 #include <gp_Vec.hxx>
39 #include <gp_XYZ.hxx>
40 #include <Standard_ConstructionError.hxx>
41 #include <Standard_NoSuchObject.hxx>
42 #include <Standard_NotImplemented.hxx>
43 #include <Standard_RangeError.hxx>
44 #include <Standard_Type.hxx>
45
46
47 static const Standard_Real MyAngularToleranceForG1 = Precision::Angular();
48
49
50 //=======================================================================
51 //function : Copy
52 //purpose  : 
53 //=======================================================================
54
55 Handle(Geom_Geometry) Geom_OffsetCurve::Copy () const {
56
57  Handle(Geom_OffsetCurve) C;
58  C = new Geom_OffsetCurve (basisCurve, offsetValue, direction);
59  return C;
60 }
61
62
63
64 //=======================================================================
65 //function : Geom_OffsetCurve
66 //purpose  : Basis curve cannot be an Offset curve or trimmed from
67 //            offset curve.
68 //=======================================================================
69
70 Geom_OffsetCurve::Geom_OffsetCurve (const Handle(Geom_Curve)& theCurve,
71                                     const Standard_Real       theOffset,
72                                     const gp_Dir&             theDir,
73                                     const Standard_Boolean    isTheNotCheckC0)
74  : direction(theDir), offsetValue(theOffset)
75 {
76   SetBasisCurve (theCurve, isTheNotCheckC0);
77 }
78
79
80 //=======================================================================
81 //function : Reverse
82 //purpose  : 
83 //=======================================================================
84
85 void Geom_OffsetCurve::Reverse ()
86
87   basisCurve->Reverse();
88   offsetValue = -offsetValue;
89   myEvaluator->SetOffsetValue(offsetValue);
90 }
91
92
93 //=======================================================================
94 //function : ReversedParameter
95 //purpose  : 
96 //=======================================================================
97
98 Standard_Real Geom_OffsetCurve::ReversedParameter( const Standard_Real U) const 
99 {
100   return basisCurve->ReversedParameter( U);
101 }
102
103 //=======================================================================
104 //function : Direction
105 //purpose  : 
106 //=======================================================================
107
108 const gp_Dir& Geom_OffsetCurve::Direction () const               
109   { return direction; }
110
111 //=======================================================================
112 //function : SetDirection
113 //purpose  : 
114 //=======================================================================
115
116 void Geom_OffsetCurve::SetDirection (const gp_Dir& V)     
117 {
118   direction = V;
119   myEvaluator->SetOffsetDirection(direction);
120 }
121
122 //=======================================================================
123 //function : SetOffsetValue
124 //purpose  : 
125 //=======================================================================
126
127 void Geom_OffsetCurve::SetOffsetValue (const Standard_Real D)   
128 {
129   offsetValue = D;
130   myEvaluator->SetOffsetValue(offsetValue);
131 }
132
133
134 //=======================================================================
135 //function : IsPeriodic
136 //purpose  : 
137 //=======================================================================
138
139 Standard_Boolean Geom_OffsetCurve::IsPeriodic () const
140 {
141   return basisCurve->IsPeriodic();
142 }
143
144 //=======================================================================
145 //function : Period
146 //purpose  : 
147 //=======================================================================
148
149 Standard_Real Geom_OffsetCurve::Period () const
150 {
151   return basisCurve->Period();
152 }
153
154 //=======================================================================
155 //function : SetBasisCurve
156 //purpose  : 
157 //=======================================================================
158
159 void Geom_OffsetCurve::SetBasisCurve (const Handle(Geom_Curve)& C,
160                                       const Standard_Boolean isNotCheckC0)
161 {
162   const Standard_Real aUf = C->FirstParameter(),
163                       aUl = C->LastParameter();
164   Handle(Geom_Curve) aCheckingCurve =  Handle(Geom_Curve)::DownCast(C->Copy());
165   Standard_Boolean isTrimmed = Standard_False;
166
167   while(aCheckingCurve->IsKind(STANDARD_TYPE(Geom_TrimmedCurve)) ||
168         aCheckingCurve->IsKind(STANDARD_TYPE(Geom_OffsetCurve)))
169   {
170     if (aCheckingCurve->IsKind(STANDARD_TYPE(Geom_TrimmedCurve)))
171     {
172       Handle(Geom_TrimmedCurve) aTrimC = 
173                 Handle(Geom_TrimmedCurve)::DownCast(aCheckingCurve);
174       aCheckingCurve = aTrimC->BasisCurve();
175       isTrimmed = Standard_True;
176     }
177
178     if (aCheckingCurve->IsKind(STANDARD_TYPE(Geom_OffsetCurve)))
179     {
180       Handle(Geom_OffsetCurve) aOC = 
181             Handle(Geom_OffsetCurve)::DownCast(aCheckingCurve);
182       aCheckingCurve = aOC->BasisCurve();
183       Standard_Real PrevOff = aOC->Offset();
184       gp_Vec V1(aOC->Direction());
185       gp_Vec V2(direction);
186       gp_Vec Vdir(PrevOff*V1 + offsetValue*V2);
187
188       if (offsetValue >= 0.)
189       {
190         offsetValue = Vdir.Magnitude();
191         direction.SetXYZ(Vdir.XYZ());
192       }
193       else
194       {
195         offsetValue = -Vdir.Magnitude();
196         direction.SetXYZ((-Vdir).XYZ());
197       }
198     }
199   }
200   
201   myBasisCurveContinuity = aCheckingCurve->Continuity();
202
203   Standard_Boolean isC0 = !isNotCheckC0 &&
204                           (myBasisCurveContinuity == GeomAbs_C0);
205
206   // Basis curve must be at least C1
207   if (isC0 && aCheckingCurve->IsKind(STANDARD_TYPE(Geom_BSplineCurve)))
208   {
209     Handle(Geom_BSplineCurve) aBC = Handle(Geom_BSplineCurve)::DownCast(aCheckingCurve);
210     if(aBC->IsG1(aUf, aUl, MyAngularToleranceForG1))
211     {
212       //Checking if basis curve has more smooth (C1, G2 and above) is not done.
213       //It can be done in case of need.
214       myBasisCurveContinuity = GeomAbs_G1;
215       isC0 = Standard_False;
216     }
217
218     // Raise exception if still C0
219     if (isC0)
220       Standard_ConstructionError::Raise("Offset on C0 curve");
221   }
222   //
223   if(isTrimmed)
224   {
225     basisCurve = new Geom_TrimmedCurve(aCheckingCurve, aUf, aUl);
226   } 
227   else
228   {
229     basisCurve = aCheckingCurve;
230   }
231
232   myEvaluator = new GeomEvaluator_OffsetCurve(basisCurve, offsetValue, direction);
233 }
234
235
236
237 //=======================================================================
238 //function : BasisCurve
239 //purpose  : 
240 //=======================================================================
241
242 Handle(Geom_Curve) Geom_OffsetCurve::BasisCurve () const 
243
244   return basisCurve;
245 }
246
247
248 //=======================================================================
249 //function : Continuity
250 //purpose  : 
251 //=======================================================================
252
253 GeomAbs_Shape Geom_OffsetCurve::Continuity () const {
254
255   GeomAbs_Shape OffsetShape=GeomAbs_C0;
256   switch (myBasisCurveContinuity) {
257     case GeomAbs_C0 : OffsetShape = GeomAbs_C0;       break;
258     case GeomAbs_C1 : OffsetShape = GeomAbs_C0;       break;
259     case GeomAbs_C2 : OffsetShape = GeomAbs_C1;       break;
260     case GeomAbs_C3 : OffsetShape = GeomAbs_C2;       break;
261     case GeomAbs_CN : OffsetShape = GeomAbs_CN;       break;
262     case GeomAbs_G1 : OffsetShape = GeomAbs_G1;       break;
263     case GeomAbs_G2 : OffsetShape = GeomAbs_G2;       break;
264   }
265   return OffsetShape;
266 }
267
268
269 //=======================================================================
270 //function : D0
271 //purpose  : 
272 //=======================================================================
273
274 void Geom_OffsetCurve::D0 (const Standard_Real U, gp_Pnt& P) const 
275 {
276   myEvaluator->D0(U, P);
277 }
278
279 //=======================================================================
280 //function : D1
281 //purpose  : 
282 //=======================================================================
283
284 void Geom_OffsetCurve::D1 (const Standard_Real U, gp_Pnt& P, gp_Vec& V1) const 
285 {
286   myEvaluator->D1(U, P, V1);
287 }
288
289 //=======================================================================
290 //function : D2
291 //purpose  : 
292 //=======================================================================
293
294 void Geom_OffsetCurve::D2 (const Standard_Real U, gp_Pnt& P, gp_Vec& V1, gp_Vec& V2) const 
295 {
296   myEvaluator->D2(U, P, V1, V2);
297 }
298
299 //=======================================================================
300 //function : D3
301 //purpose  : 
302 //=======================================================================
303
304 void Geom_OffsetCurve::D3 (const Standard_Real theU, gp_Pnt& theP,
305                            gp_Vec& theV1, gp_Vec& theV2, gp_Vec& theV3) const
306 {
307   myEvaluator->D3(theU, theP, theV1, theV2, theV3);
308 }
309
310
311 //=======================================================================
312 //function : DN
313 //purpose  : 
314 //=======================================================================
315
316 gp_Vec Geom_OffsetCurve::DN (const Standard_Real U, const Standard_Integer N) const 
317 {
318   Standard_RangeError_Raise_if (N < 1, "Exception: "
319                               "Geom_OffsetCurve::DN(...). N<1.");
320
321   gp_Vec VN, Vtemp;
322   gp_Pnt Ptemp;
323   switch (N)
324     {
325     case 1:
326       D1( U, Ptemp, VN);
327       break;
328     case 2:
329       D2( U, Ptemp, Vtemp, VN);
330       break;
331     case 3:
332       D3( U, Ptemp, Vtemp, Vtemp, VN);
333       break;
334     default:
335       Standard_NotImplemented::Raise("Exception: "
336         "Derivative order is greater than 3. Cannot compute of derivative.");
337   }
338   
339   return VN;
340 }
341
342
343 //=======================================================================
344 //function : FirstParameter
345 //purpose  : 
346 //=======================================================================
347
348 Standard_Real Geom_OffsetCurve::FirstParameter () const
349 {
350    return basisCurve->FirstParameter();
351 }
352
353
354 //=======================================================================
355 //function : LastParameter
356 //purpose  : 
357 //=======================================================================
358
359 Standard_Real Geom_OffsetCurve::LastParameter () const
360 {
361    return basisCurve->LastParameter();
362 }
363
364
365 //=======================================================================
366 //function : Offset
367 //purpose  : 
368 //=======================================================================
369
370 Standard_Real Geom_OffsetCurve::Offset () const
371 { return offsetValue; }
372
373
374 //=======================================================================
375 //function : IsClosed
376 //purpose  : 
377 //=======================================================================
378
379 Standard_Boolean Geom_OffsetCurve::IsClosed () const 
380
381   gp_Pnt PF,PL;
382   D0(FirstParameter(),PF);
383   D0(LastParameter(),PL);
384   return ( PF.Distance(PL) <= gp::Resolution());
385 }
386
387
388
389 //=======================================================================
390 //function : IsCN
391 //purpose  : 
392 //=======================================================================
393
394 Standard_Boolean Geom_OffsetCurve::IsCN (const Standard_Integer N) const {
395
396    Standard_RangeError_Raise_if (N < 0, " ");
397    return basisCurve->IsCN (N + 1);
398 }
399
400
401 //=======================================================================
402 //function : Transform
403 //purpose  : 
404 //=======================================================================
405
406 void Geom_OffsetCurve::Transform (const gp_Trsf& T)
407 {
408   basisCurve->Transform (T);
409   direction.Transform(T);
410   offsetValue *= T.ScaleFactor();
411
412   myEvaluator->SetOffsetValue(offsetValue);
413   myEvaluator->SetOffsetDirection(direction);
414 }
415
416 //=======================================================================
417 //function : TransformedParameter
418 //purpose  : 
419 //=======================================================================
420
421 Standard_Real Geom_OffsetCurve::TransformedParameter(const Standard_Real U,
422                                                      const gp_Trsf& T) const
423 {
424   return basisCurve->TransformedParameter(U,T);
425 }
426
427 //=======================================================================
428 //function : ParametricTransformation
429 //purpose  : 
430 //=======================================================================
431
432 Standard_Real Geom_OffsetCurve::ParametricTransformation(const gp_Trsf& T)
433 const
434 {
435   return basisCurve->ParametricTransformation(T);
436 }
437
438 //=======================================================================
439 //function : GetBasisCurveContinuity
440 //purpose  : 
441 //=======================================================================
442 GeomAbs_Shape Geom_OffsetCurve::GetBasisCurveContinuity() const
443 {
444   return myBasisCurveContinuity;
445 }