66be2af51867c090c69a7399658040a9dd6e5d41
[occt.git] / src / Adaptor2d / Adaptor2d_OffsetCurve.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 <Adaptor2d_HCurve2d.hxx>
16 #include <Adaptor2d_HOffsetCurve.hxx>
17 #include <Adaptor2d_OffsetCurve.hxx>
18 #include <Geom2d_BezierCurve.hxx>
19 #include <Geom2d_BSplineCurve.hxx>
20 #include <Geom2dEvaluator.hxx>
21 #include <GeomAbs_SurfaceType.hxx>
22 #include <gp.hxx>
23 #include <gp_Ax22d.hxx>
24 #include <gp_Circ2d.hxx>
25 #include <gp_Dir2d.hxx>
26 #include <gp_Elips2d.hxx>
27 #include <gp_Hypr2d.hxx>
28 #include <gp_Lin2d.hxx>
29 #include <gp_Parab2d.hxx>
30 #include <gp_Pnt2d.hxx>
31 #include <gp_Vec2d.hxx>
32 #include <gp_VectorWithNullMagnitude.hxx>
33 #include <Precision.hxx>
34 #include <Standard_DomainError.hxx>
35 #include <Standard_NoSuchObject.hxx>
36 #include <Standard_NotImplemented.hxx>
37 #include <Standard_TypeMismatch.hxx>
38
39 //=======================================================================
40 //function : Adaptor2d_OffsetCurve
41 //purpose  : 
42 //=======================================================================
43 Adaptor2d_OffsetCurve::Adaptor2d_OffsetCurve()
44 : myOffset(0.0),
45   myFirst (0.0),
46   myLast  (0.0)
47 {
48 }
49
50 //=======================================================================
51 //function : Adaptor2d_OffsetCurve
52 //purpose  : 
53 //=======================================================================
54
55 Adaptor2d_OffsetCurve::Adaptor2d_OffsetCurve(const Handle(Adaptor2d_HCurve2d)& theCurve)
56 : myCurve (theCurve),
57   myOffset(0.0),
58   myFirst (0.0),
59   myLast  (0.0)
60 {
61 }
62
63 //=======================================================================
64 //function : Adaptor2d_OffsetCurve
65 //purpose  : 
66 //=======================================================================
67
68 Adaptor2d_OffsetCurve::Adaptor2d_OffsetCurve
69   (const Handle(Adaptor2d_HCurve2d)& theCurve, const Standard_Real theOffset)
70 : myCurve (theCurve),
71   myOffset(theOffset),
72   myFirst (theCurve->FirstParameter()),
73   myLast  (theCurve->LastParameter())
74 {
75 }
76
77 //=======================================================================
78 //function : Adaptor2d_OffsetCurve
79 //purpose  : 
80 //=======================================================================
81
82 Adaptor2d_OffsetCurve::Adaptor2d_OffsetCurve(
83                               const Handle(Adaptor2d_HCurve2d)& theCurve,
84                               const Standard_Real theOffset,
85                               const Standard_Real theWFirst,
86                               const Standard_Real theWLast )
87 : myCurve (theCurve),
88   myOffset(theOffset),
89   myFirst (theWFirst),
90   myLast  (theWLast)
91 {
92 }
93
94 //=======================================================================
95 //function : Load
96 //purpose  : 
97 //=======================================================================
98
99 void Adaptor2d_OffsetCurve::Load(const Handle(Adaptor2d_HCurve2d)& C ) 
100 {
101   myCurve = C;
102   myOffset = 0.;
103 }
104
105 //=======================================================================
106 //function : Load
107 //purpose  : 
108 //=======================================================================
109
110 void Adaptor2d_OffsetCurve::Load( const Standard_Real Offset)
111 {
112   myOffset = Offset;
113   myFirst = myCurve->FirstParameter();
114   myLast = myCurve->LastParameter();
115 }
116
117 //=======================================================================
118 //function : Load
119 //purpose  : 
120 //=======================================================================
121
122 void Adaptor2d_OffsetCurve::Load(const Standard_Real Offset,
123                                  const Standard_Real WFirst,
124                                  const Standard_Real WLast) 
125 {
126   myOffset = Offset;
127   myFirst = WFirst;
128   myLast = WLast;
129 }
130
131 //=======================================================================
132 //function : Continuity
133 //purpose  : 
134 //=======================================================================
135
136 GeomAbs_Shape Adaptor2d_OffsetCurve::Continuity() const
137 {
138   switch (myCurve->Continuity()) {
139   case GeomAbs_CN: return GeomAbs_CN;
140   case GeomAbs_C3: return GeomAbs_C2;
141   case GeomAbs_C2: return GeomAbs_G2;
142   case GeomAbs_G2: return GeomAbs_C1;
143   case GeomAbs_C1: return GeomAbs_G1;
144   case GeomAbs_G1: return GeomAbs_C0;
145   case GeomAbs_C0:
146 // No Continuity !!
147     throw Standard_TypeMismatch("Adaptor2d_OffsetCurve::IntervalContinuity");
148     break;
149   }
150
151   //portage WNT
152   return GeomAbs_C0;
153 }
154
155 //=======================================================================
156 //function : NbIntervals
157 //purpose  : 
158 //=======================================================================
159
160 Standard_Integer Adaptor2d_OffsetCurve::NbIntervals(const GeomAbs_Shape S) const
161 {
162   GeomAbs_Shape Sh;
163   if ( S >= GeomAbs_C2)  Sh = GeomAbs_CN;
164   else 
165     Sh = (GeomAbs_Shape)((Standard_Integer)S + 2);
166
167   Standard_Integer nbInter = myCurve->NbIntervals(Sh);
168
169   if(nbInter == 1) return nbInter;
170
171   TColStd_Array1OfReal T(1,nbInter+1);
172
173   myCurve->Intervals(T,Sh);
174
175   Standard_Integer first = 1;
176   while (T(first) <= myFirst) first++;
177   Standard_Integer last = nbInter+1;
178   while (T(last) >= myLast) last--;
179   return (last - first + 2);
180 }
181
182 //=======================================================================
183 //function : Intervals
184 //purpose  : 
185 //=======================================================================
186
187 void Adaptor2d_OffsetCurve::Intervals(TColStd_Array1OfReal& TI, 
188                                       const GeomAbs_Shape S) const 
189 {
190   GeomAbs_Shape Sh;
191   if ( S >= GeomAbs_C2)  Sh = GeomAbs_CN;
192   else 
193     Sh = (GeomAbs_Shape)((Standard_Integer)S + 2);
194
195   Standard_Integer nbInter = myCurve->NbIntervals(Sh);
196
197
198   if(nbInter == 1) {
199     TI(TI.Lower()) = myFirst ;
200     TI(TI.Lower() + 1) = myLast ;
201     return;
202   }
203
204   TColStd_Array1OfReal T(1,nbInter+1);
205   myCurve->Intervals(T,Sh);
206
207   Standard_Integer first = 1;
208   while (T(first) <= myFirst) first++;
209   Standard_Integer last = nbInter+1;
210   while (T(last) >= myLast) last--;
211
212   Standard_Integer i = TI.Lower(), j;
213   for (j = first-1; j <= last+1; j++) {
214     TI(i) = T(j);
215     i++;
216   }
217
218   TI(TI.Lower()) = myFirst ;
219   TI(TI.Lower() + last-first + 2) = myLast ; 
220
221 }
222
223
224 //=======================================================================
225 //function : Trim
226 //purpose  : 
227 //=======================================================================
228
229 Handle(Adaptor2d_HCurve2d) Adaptor2d_OffsetCurve::Trim
230 (const Standard_Real First, 
231  const Standard_Real Last,
232  const Standard_Real) const 
233 {
234   Handle(Adaptor2d_HOffsetCurve) HO = new Adaptor2d_HOffsetCurve(*this);
235   HO->ChangeCurve2d().Load(myOffset,First,Last);
236   return HO;
237 }
238
239
240 //=======================================================================
241 //function : IsClosed
242 //purpose  : 
243 //=======================================================================
244
245 Standard_Boolean Adaptor2d_OffsetCurve::IsClosed() const
246 {
247   if ( myOffset == 0.) {
248     return myCurve->IsClosed();
249   }
250   else {
251     if (myCurve->Continuity() == GeomAbs_C0)
252       return Standard_False;
253     else {
254       if ( myCurve->IsClosed()) {
255         gp_Vec2d Dummy[2];
256         gp_Pnt2d P;
257         myCurve->D1
258           (myCurve->FirstParameter(),P,Dummy[0]);
259         myCurve->D1
260           (myCurve->LastParameter(),P,Dummy[1]);
261         if (Dummy[0].IsParallel(Dummy[1],Precision::Angular()) && 
262             !(Dummy[0].IsOpposite(Dummy[1],Precision::Angular())))
263           return Standard_True;
264         else
265           return Standard_False;
266       }
267       else
268         return Standard_False;
269     }
270   }
271 }
272
273 //=======================================================================
274 //function : IsPeriodic
275 //purpose  : 
276 //=======================================================================
277
278 Standard_Boolean Adaptor2d_OffsetCurve::IsPeriodic() const
279 {
280   return myCurve->IsPeriodic();
281 }
282
283 //=======================================================================
284 //function : Period
285 //purpose  : 
286 //=======================================================================
287
288 Standard_Real Adaptor2d_OffsetCurve::Period() const
289 {
290   return myCurve->Period();
291 }
292
293 //=======================================================================
294 //function : Value
295 //purpose  : 
296 //=======================================================================
297
298 gp_Pnt2d Adaptor2d_OffsetCurve::Value(const Standard_Real U) const
299 {
300   if ( myOffset != 0.) {
301     gp_Pnt2d aP;
302     gp_Vec2d aV;
303     myCurve->D1(U, aP, aV);
304     Geom2dEvaluator::CalculateD0(aP, aV, myOffset);
305     return aP;
306   }
307   else {
308     return myCurve->Value(U);
309   }
310 }
311
312 //=======================================================================
313 //function : D0
314 //purpose  : 
315 //=======================================================================
316
317 void Adaptor2d_OffsetCurve::D0(const Standard_Real U, gp_Pnt2d& P) const
318 {
319   P = Value( U);
320 }
321
322 //=======================================================================
323 //function : D1
324 //purpose  : 
325 //=======================================================================
326
327 void Adaptor2d_OffsetCurve::D1
328 (const Standard_Real U, gp_Pnt2d& P, gp_Vec2d& V) const
329 {
330   if (myOffset != 0.) {
331     gp_Vec2d aV2;
332     myCurve->D2(U, P, V, aV2);
333     Geom2dEvaluator::CalculateD1( P, V, aV2, myOffset);
334   }
335   else {
336     myCurve->D1(U, P, V);
337   }
338 }
339
340 //=======================================================================
341 //function : D2
342 //purpose  : 
343 //=======================================================================
344
345 void Adaptor2d_OffsetCurve::D2
346 (const Standard_Real U, gp_Pnt2d& P, gp_Vec2d& V1, gp_Vec2d& V2) const
347 {
348   if (myOffset != 0.) {
349     gp_Vec2d aV3;
350     myCurve->D3(U, P, V1, V2, aV3);
351     Geom2dEvaluator::CalculateD2(P, V1, V2, aV3, Standard_False, myOffset);
352   }
353   else {
354     myCurve->D2(U, P, V1, V2);
355   }
356 }
357
358 //=======================================================================
359 //function : D3
360 //purpose  : 
361 //=======================================================================
362
363 void Adaptor2d_OffsetCurve::D3
364   (const Standard_Real U, 
365    gp_Pnt2d& P, gp_Vec2d& V1, gp_Vec2d& V2, gp_Vec2d& V3) const
366 {
367   if (myOffset != 0.) {
368     gp_Vec2d aV4 = myCurve->DN(U, 4);
369     myCurve->D3(U, P, V1, V2, V3);
370     Geom2dEvaluator::CalculateD3(P, V1, V2, V3, aV4, Standard_False, myOffset);
371   }
372   else {
373     myCurve->D3(U, P, V1, V2, V3);
374   }
375 }
376
377 //=======================================================================
378 //function : DN
379 //purpose  : 
380 //=======================================================================
381
382 gp_Vec2d Adaptor2d_OffsetCurve::DN
383   (const Standard_Real , const Standard_Integer ) const
384 {
385   throw Standard_NotImplemented("Adaptor2d_OffsetCurve::DN");
386 }
387
388
389 //=======================================================================
390 //function : Resolution
391 //purpose  : 
392 //=======================================================================
393
394 Standard_Real Adaptor2d_OffsetCurve::Resolution(const Standard_Real R3d) const
395 {
396   return Precision::PConfusion(R3d);
397 }
398
399
400 //=======================================================================
401 //function : GetType
402 //purpose  : 
403 //=======================================================================
404
405 GeomAbs_CurveType Adaptor2d_OffsetCurve::GetType() const {
406
407   if ( myOffset == 0.) {
408     return myCurve->GetType();
409   }
410   else {
411     switch (myCurve->GetType()) {
412       
413     case GeomAbs_Line:
414       return GeomAbs_Line;
415       
416     case GeomAbs_Circle:
417       return GeomAbs_Circle;
418       
419     default:
420       return GeomAbs_OffsetCurve;
421       
422     }
423   }
424 }
425
426 //=======================================================================
427 //function : Line
428 //purpose  : 
429 //=======================================================================
430
431 gp_Lin2d Adaptor2d_OffsetCurve::Line() const
432 {
433   if ( GetType() == GeomAbs_Line) {
434     gp_Pnt2d P;
435     gp_Vec2d V;
436     D1(0,P,V);
437     return gp_Lin2d(P,V);
438   }
439   else {
440     throw Standard_NoSuchObject("Adaptor2d_OffsetCurve::Line");
441   }
442 }
443
444
445 //=======================================================================
446 //function : Circle
447 //purpose  : 
448 //=======================================================================
449
450 gp_Circ2d Adaptor2d_OffsetCurve::Circle() const
451 {
452   if ( GetType() == GeomAbs_Circle) {
453     if (myOffset == 0.) {
454       return myCurve->Circle();
455     }
456     else {
457       gp_Circ2d C1( myCurve->Circle());
458       Standard_Real radius = C1.Radius();
459       gp_Ax22d axes( C1.Axis());
460       gp_Dir2d Xd = axes.XDirection();
461       gp_Dir2d Yd = axes.YDirection();
462       Standard_Real Crossed = Xd.X()*Yd.Y()-Xd.Y()*Yd.X();
463       Standard_Real Signe = ( Crossed > 0.) ? 1. : -1.;
464
465       radius += Signe*myOffset;
466       if ( radius > 0.) {
467         return gp_Circ2d( axes,radius);
468       }
469       else if ( radius < 0.) {
470         radius = - radius;
471         axes.SetXDirection( (axes.XDirection()).Reversed());
472         return gp_Circ2d( axes,radius); 
473       }
474       else {     // Cercle de rayon Nul
475         throw Standard_NoSuchObject("Adaptor2d_OffsetCurve::Circle");
476       }
477     }
478   }
479   else {
480     throw Standard_NoSuchObject("Adaptor2d_OffsetCurve::Circle");
481   }
482 }
483
484 //=======================================================================
485 //function : Ellipse
486 //purpose  : 
487 //=======================================================================
488
489 gp_Elips2d Adaptor2d_OffsetCurve::Ellipse() const
490 {
491   if (myCurve->GetType() == GeomAbs_Ellipse && myOffset == 0.) {
492     return myCurve->Ellipse();
493   }
494   else {
495     throw Standard_NoSuchObject("Adaptor2d_OffsetCurve:Ellipse");
496   }
497 }
498
499 //=======================================================================
500 //function : Hyperbola
501 //purpose  : 
502 //=======================================================================
503
504 gp_Hypr2d Adaptor2d_OffsetCurve::Hyperbola() const
505 {
506   if (myCurve->GetType()==GeomAbs_Hyperbola && myOffset==0.) {
507     return myCurve->Hyperbola();
508   }
509   else {
510     throw Standard_NoSuchObject("Adaptor2d_OffsetCurve:Hyperbola");
511   }
512 }
513
514 //=======================================================================
515 //function : Parabola
516 //purpose  : 
517 //=======================================================================
518
519 gp_Parab2d Adaptor2d_OffsetCurve::Parabola() const
520 {
521   if (myCurve->GetType() == GeomAbs_Parabola && myOffset == 0.) {
522     return myCurve->Parabola();
523   }
524   else {
525     throw Standard_NoSuchObject("Adaptor2d_OffsetCurve:Parabola");
526   }
527 }
528 //=======================================================================
529 //function : Degree
530 //purpose  : 
531 //=======================================================================
532
533 Standard_Integer  Adaptor2d_OffsetCurve::Degree() const
534 {
535   GeomAbs_CurveType type = myCurve->GetType();
536   if (   (type==GeomAbs_BezierCurve || type==GeomAbs_BSplineCurve) 
537       && myOffset == 0.) {
538     return myCurve->Degree();
539   }
540   else {
541     throw Standard_NoSuchObject("Adaptor2d_OffsetCurve::Degree");
542   }
543 }
544 //=======================================================================
545 //function : IsRational
546 //purpose  : 
547 //=======================================================================
548
549 Standard_Boolean  Adaptor2d_OffsetCurve::IsRational() const
550 {
551   if ( myOffset == 0.) {
552     return myCurve->IsRational();
553   }
554   return Standard_False;
555 }
556 //=======================================================================
557 //function : NbPoles
558 //purpose  : 
559 //=======================================================================
560
561 Standard_Integer  Adaptor2d_OffsetCurve::NbPoles() const
562 {
563   GeomAbs_CurveType type = myCurve->GetType();
564   if (   (type==GeomAbs_BezierCurve || type==GeomAbs_BSplineCurve) 
565       && myOffset == 0.) {
566     return myCurve->NbPoles();
567   }
568   else {
569     throw Standard_NoSuchObject("Adaptor2d_OffsetCurve::NbPoles");
570   }
571 }
572
573 //=======================================================================
574 //function : NbKnots
575 //purpose  : 
576 //=======================================================================
577
578 Standard_Integer  Adaptor2d_OffsetCurve::NbKnots() const
579 {
580   if( myOffset == 0.) {
581     return myCurve->NbKnots();
582   }
583   else {
584     throw Standard_NoSuchObject("Adaptor2d_OffsetCurve::NbKnots");
585   }
586 }
587
588 //=======================================================================
589 //function : Bezier
590 //purpose  : 
591 //=======================================================================
592
593 Handle(Geom2d_BezierCurve) Adaptor2d_OffsetCurve::Bezier() const 
594 {
595   Standard_NoSuchObject_Raise_if (myOffset != 0.0e0 || GetType() != GeomAbs_BezierCurve,
596                                   "Adaptor2d_OffsetCurve::Bezier() - wrong curve type");
597    return myCurve->Bezier();
598 }
599
600
601 //=======================================================================
602 //function : BSpline
603 //purpose  : 
604 //=======================================================================
605
606 Handle(Geom2d_BSplineCurve) Adaptor2d_OffsetCurve::BSpline() const 
607 {
608   Standard_NoSuchObject_Raise_if (myOffset != 0.0e0 || GetType() != GeomAbs_BSplineCurve,
609                                   "Adaptor2d_OffsetCurve::BSpline() - wrong curve type");
610   return myCurve->BSpline();
611 }
612
613 static Standard_Integer nbPoints(const Handle(Adaptor2d_HCurve2d)& theCurve)
614 {
615
616   Standard_Integer nbs = 20;
617
618   if (theCurve->GetType() == GeomAbs_BezierCurve)
619   {
620     nbs = Max(nbs, 3 + theCurve->NbPoles());
621   }
622   else if (theCurve->GetType() == GeomAbs_BSplineCurve) {
623     nbs = Max(nbs, theCurve->NbKnots() * theCurve->Degree());
624   }
625
626   if (nbs > 300)
627     nbs = 300;
628   return nbs;
629
630 }
631 //=======================================================================
632 //function : NbSamples
633 //purpose  : 
634 //=======================================================================
635
636 Standard_Integer Adaptor2d_OffsetCurve::NbSamples() const
637 {
638   return  nbPoints(myCurve);
639 }