0026603: Problem with maximization and normalization document windows in Qt samples...
[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     Standard_TypeMismatch::Raise("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       gp_VectorWithNullMagnitude::Raise("Adaptor2d_OffsetCurve::Value");
313       return gp_Pnt2d();
314     }
315   }
316   else {
317     return myCurve->Value(U);
318   }
319 }
320
321 //=======================================================================
322 //function : D0
323 //purpose  : 
324 //=======================================================================
325
326 void Adaptor2d_OffsetCurve::D0(const Standard_Real U, gp_Pnt2d& P) const
327 {
328   P = Value( U);
329 }
330
331 //=======================================================================
332 //function : D1
333 //purpose  : 
334 //=======================================================================
335
336 void Adaptor2d_OffsetCurve::D1
337   (const Standard_Real U, gp_Pnt2d& P, gp_Vec2d& V) const
338 {
339   gp_Vec2d V1,V2,V3;
340   gp_Pnt2d PP;
341   Standard_Real Norme;
342   if ( myOffset != 0. ) {
343     myCurve->D2(U,PP,V1,V2);
344     Norme = V1.Magnitude();
345     V3.SetCoord( -V1.Y(),V1.X());
346     V2.SetCoord( -V2.Y(),V2.X());
347     if ( Norme >= gp::Resolution()) {
348       P = gp_Pnt2d( PP.XY()+myOffset*V3.XY()/Norme);
349       V = gp_Vec2d( V1.XY()+
350                    (myOffset/Norme)*(V2.XY()-V3.XY()*
351                                     (V2.XY()*V3.XY())/(Norme*Norme)));
352     }
353     else {
354       gp_VectorWithNullMagnitude::Raise("Adaptor2d_OffsetCurve::D1");
355     }
356   }
357   else {
358     myCurve->D1(U,P,V);
359   }
360 }
361
362 //=======================================================================
363 //function : D2
364 //purpose  : 
365 //=======================================================================
366
367 void Adaptor2d_OffsetCurve::D2
368   (const Standard_Real U, gp_Pnt2d& P, gp_Vec2d& V1, gp_Vec2d& V2) const
369 {
370   if ( myOffset != 0.) {
371     gp_Vec2d T1,T2,T3;
372     gp_Pnt2d PP;
373     Standard_Real Norme;
374     myCurve->D3(U,PP,T1,T2,T3);
375
376     Norme = T1.Magnitude();
377     if ( Norme >= gp::Resolution()) {
378       gp_Vec2d N1,N2,N3;             // Ni = Z ^ Ti
379       N1.SetCoord( -T1.Y(), T1.X());
380       N2.SetCoord( -T2.Y(), T2.X());
381       N3.SetCoord( -T3.Y(), T3.X());
382       Standard_Real d12,d13,d22,Nor3,Nor11;
383       d12   = T1*T2;
384       d22   = T2*T2;
385       d13   = T1*T3;
386       Nor3  = Norme*Norme*Norme;
387       Nor11 = Nor3*Nor3*Nor3*Norme*Norme;
388       V2    = gp_Vec2d( -1 * ( (d22+d13)/Nor3 + 3*d12*d12/Nor11) * N1.XY());
389       V2    = gp_Vec2d( V2.XY() - (2*d12/Nor3)*N2.XY() + N3.XY()/Norme);
390       V2    = gp_Vec2d( myOffset*V2.XY() + T2.XY());
391
392       D1( U,P,V1);
393     }
394     else {
395       gp_VectorWithNullMagnitude::Raise("Adaptor2d_OffsetCurve::D2");
396     }
397   }
398   else {
399     myCurve->D2(U,P,V1,V2);
400   }
401 }
402
403 //=======================================================================
404 //function : D3
405 //purpose  : 
406 //=======================================================================
407
408 //void Adaptor2d_OffsetCurve::D3
409 //  (const Standard_Real T, 
410 //   gp_Pnt2d& P, gp_Vec2d& V1, gp_Vec2d& V2, gp_Vec2d& V3) const
411 void Adaptor2d_OffsetCurve::D3
412   (const Standard_Real , 
413    gp_Pnt2d& , gp_Vec2d& , gp_Vec2d& , gp_Vec2d& ) const
414 {
415   Standard_NotImplemented::Raise("Adaptor2d_OffsetCurve::D3");
416 }
417
418 //=======================================================================
419 //function : DN
420 //purpose  : 
421 //=======================================================================
422
423 gp_Vec2d Adaptor2d_OffsetCurve::DN
424 //  (const Standard_Real T, const Standard_Integer N) const
425   (const Standard_Real , const Standard_Integer ) const
426 {
427   Standard_NotImplemented::Raise("Adaptor2d_OffsetCurve::DN");
428   return gp_Vec2d();
429 }
430
431
432 //=======================================================================
433 //function : Resolution
434 //purpose  : 
435 //=======================================================================
436
437 Standard_Real Adaptor2d_OffsetCurve::Resolution(const Standard_Real R3d) const
438 {
439   return Precision::PConfusion(R3d);
440 }
441
442
443 //=======================================================================
444 //function : GetType
445 //purpose  : 
446 //=======================================================================
447
448 GeomAbs_CurveType Adaptor2d_OffsetCurve::GetType() const {
449
450   if ( myOffset == 0.) {
451     return myCurve->GetType();
452   }
453   else {
454     switch (myCurve->GetType()) {
455       
456     case GeomAbs_Line:
457       return GeomAbs_Line;
458       
459     case GeomAbs_Circle:
460       return GeomAbs_Circle;
461       
462     default:
463       return GeomAbs_OtherCurve;
464       
465     }
466   }
467 }
468
469 //=======================================================================
470 //function : Line
471 //purpose  : 
472 //=======================================================================
473
474 gp_Lin2d Adaptor2d_OffsetCurve::Line() const
475 {
476   if ( GetType() == GeomAbs_Line) {
477     gp_Pnt2d P;
478     gp_Vec2d V;
479     D1(0,P,V);
480     return gp_Lin2d(P,V);
481   }
482   else {
483     Standard_NoSuchObject::Raise("Adaptor2d_OffsetCurve::Line");
484     return gp_Lin2d();
485   }
486 }
487
488
489 //=======================================================================
490 //function : Circle
491 //purpose  : 
492 //=======================================================================
493
494 gp_Circ2d Adaptor2d_OffsetCurve::Circle() const
495 {
496   if ( GetType() == GeomAbs_Circle) {
497     if (myOffset == 0.) {
498       return myCurve->Circle();
499     }
500     else {
501       gp_Circ2d C1( myCurve->Circle());
502       Standard_Real radius = C1.Radius();
503       gp_Ax22d axes( C1.Axis());
504       gp_Dir2d Xd = axes.XDirection();
505       gp_Dir2d Yd = axes.YDirection();
506       Standard_Real Crossed = Xd.X()*Yd.Y()-Xd.Y()*Yd.X();
507       Standard_Real Signe = ( Crossed > 0.) ? 1. : -1.;
508
509       radius += Signe*myOffset;
510       if ( radius > 0.) {
511         return gp_Circ2d( axes,radius);
512       }
513       else if ( radius < 0.) {
514         radius = - radius;
515         axes.SetXDirection( (axes.XDirection()).Reversed());
516         return gp_Circ2d( axes,radius); 
517       }
518       else {     // Cercle de rayon Nul
519         Standard_NoSuchObject::Raise("Adaptor2d_OffsetCurve::Circle");
520       }
521     }
522   }
523   else {
524     Standard_NoSuchObject::Raise("Adaptor2d_OffsetCurve::Circle");
525   }
526   // portage WNT
527   return gp_Circ2d();
528 }
529
530 //=======================================================================
531 //function : Ellipse
532 //purpose  : 
533 //=======================================================================
534
535 gp_Elips2d Adaptor2d_OffsetCurve::Ellipse() const
536 {
537   if (myCurve->GetType() == GeomAbs_Ellipse && myOffset == 0.) {
538     return myCurve->Ellipse();;
539   }
540   else {
541     Standard_NoSuchObject::Raise("Adaptor2d_OffsetCurve:Ellipse");
542   }
543   // portage WNT
544   return gp_Elips2d();
545 }
546
547 //=======================================================================
548 //function : Hyperbola
549 //purpose  : 
550 //=======================================================================
551
552 gp_Hypr2d Adaptor2d_OffsetCurve::Hyperbola() const
553 {
554   if (myCurve->GetType()==GeomAbs_Hyperbola && myOffset==0.) {
555     return myCurve->Hyperbola();
556   }
557   else {
558     Standard_NoSuchObject::Raise("Adaptor2d_OffsetCurve:Hyperbola");
559   }
560   // portage WNT
561   return gp_Hypr2d();
562 }
563
564 //=======================================================================
565 //function : Parabola
566 //purpose  : 
567 //=======================================================================
568
569 gp_Parab2d Adaptor2d_OffsetCurve::Parabola() const
570 {
571   if (myCurve->GetType() == GeomAbs_Parabola && myOffset == 0.) {
572     return myCurve->Parabola();
573   }
574   else {
575     Standard_NoSuchObject::Raise("Adaptor2d_OffsetCurve:Parabola");
576   }
577   // portage WNT
578   return gp_Parab2d();
579 }
580 //=======================================================================
581 //function : Degree
582 //purpose  : 
583 //=======================================================================
584
585 Standard_Integer  Adaptor2d_OffsetCurve::Degree() const
586 {
587   GeomAbs_CurveType type = myCurve->GetType();
588   if (   (type==GeomAbs_BezierCurve || type==GeomAbs_BSplineCurve) 
589       && myOffset == 0.) {
590     return myCurve->Degree();
591   }
592   else {
593     Standard_NoSuchObject::Raise("Adaptor2d_OffsetCurve::Degree");
594     return 0;
595   }
596 }
597 //=======================================================================
598 //function : IsRational
599 //purpose  : 
600 //=======================================================================
601
602 Standard_Boolean  Adaptor2d_OffsetCurve::IsRational() const
603 {
604   if ( myOffset == 0.) {
605     return myCurve->IsRational();
606   }
607   return Standard_False;
608 }
609 //=======================================================================
610 //function : NbPoles
611 //purpose  : 
612 //=======================================================================
613
614 Standard_Integer  Adaptor2d_OffsetCurve::NbPoles() const
615 {
616   GeomAbs_CurveType type = myCurve->GetType();
617   if (   (type==GeomAbs_BezierCurve || type==GeomAbs_BSplineCurve) 
618       && myOffset == 0.) {
619     return myCurve->NbPoles();
620   }
621   else {
622     Standard_NoSuchObject::Raise("Adaptor2d_OffsetCurve::NbPoles");
623     return 0;
624   }
625 }
626
627 //=======================================================================
628 //function : NbKnots
629 //purpose  : 
630 //=======================================================================
631
632 Standard_Integer  Adaptor2d_OffsetCurve::NbKnots() const
633 {
634   if( myOffset == 0.) {
635     return myCurve->NbKnots();
636   }
637   else {
638     Standard_NoSuchObject::Raise("Adaptor2d_OffsetCurve::NbKnots");
639     return 0;
640   }
641 }
642
643 //=======================================================================
644 //function : Bezier
645 //purpose  : 
646 //=======================================================================
647
648 Handle(Geom2d_BezierCurve) Adaptor2d_OffsetCurve::Bezier() const 
649 {
650   Standard_NoSuchObject_Raise_if
651     ( myOffset != 0.0e0 || GetType() != GeomAbs_BezierCurve, "");
652    return myCurve->Bezier();
653 }
654
655
656 //=======================================================================
657 //function : BSpline
658 //purpose  : 
659 //=======================================================================
660
661 Handle(Geom2d_BSplineCurve) Adaptor2d_OffsetCurve::BSpline() const 
662 {
663   Standard_NoSuchObject_Raise_if
664     ( myOffset != 0.0e0 || GetType() != GeomAbs_BSplineCurve, "");
665
666   return myCurve->BSpline();
667 }
668
669