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