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