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