0031642: Visualization - crash in Graphic3d_Structure::SetVisual() on redisplaying...
[occt.git] / src / BndLib / BndLib_Add2dCurve.cxx
1 // Copyright (c) 1996-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15
16 #include <Adaptor2d_Curve2d.hxx>
17 #include <Bnd_Box2d.hxx>
18 #include <BndLib_Add2dCurve.hxx>
19 #include <Geom2d_BezierCurve.hxx>
20 #include <Geom2d_BSplineCurve.hxx>
21 #include <Geom2d_Circle.hxx>
22 #include <Geom2d_Conic.hxx>
23 #include <Geom2d_Curve.hxx>
24 #include <Geom2d_Ellipse.hxx>
25 #include <Geom2d_Geometry.hxx>
26 #include <Geom2d_Hyperbola.hxx>
27 #include <Geom2d_Line.hxx>
28 #include <Geom2d_OffsetCurve.hxx>
29 #include <Geom2d_Parabola.hxx>
30 #include <Geom2d_TrimmedCurve.hxx>
31 #include <Geom2dAdaptor_Curve.hxx>
32 #include <gp.hxx>
33 #include <Precision.hxx>
34 #include <Standard_Type.hxx>
35 #include <math_MultipleVarFunction.hxx>
36 #include <math_Function.hxx>
37 #include <math_BrentMinimum.hxx>
38 #include <math_PSO.hxx>
39
40 //=======================================================================
41 //function : BndLib_Box2dCurve
42 //purpose  : 
43 //=======================================================================
44 class BndLib_Box2dCurve  {
45  public:
46   BndLib_Box2dCurve();
47
48   virtual ~BndLib_Box2dCurve();
49
50   void SetCurve(const Handle(Geom2d_Curve)& aC);
51
52   const Handle(Geom2d_Curve)& Curve() const;
53
54   void SetRange(const Standard_Real aT1,
55                 const Standard_Real aT2);
56
57   void Range(Standard_Real& aT1,
58              Standard_Real& aT2) const;
59
60   const Bnd_Box2d& Box() const;
61
62   void Perform();
63
64   void PerformOptimal(const Standard_Real Tol);
65
66   void Clear();
67
68   Standard_Integer ErrorStatus() const;
69   //
70   //-----------------------------
71  protected:
72   void CheckData();
73   void GetInfoBase();
74   void PerformLineConic();
75   void PerformBezier();
76   void PerformBSpline();
77   void PerformOther();
78   void D0(const Standard_Real, gp_Pnt2d&);
79   //
80   void Compute(const Handle(Geom2d_Conic)&,
81                const GeomAbs_CurveType,
82                const Standard_Real,
83                const Standard_Real,
84                Bnd_Box2d& aBox2D);
85   //
86   static
87     Standard_Integer Compute(const Handle(Geom2d_Conic)&,
88                              const GeomAbs_CurveType,
89                              Standard_Real *);
90   static
91     Standard_Boolean IsTypeBase(const Handle(Geom2d_Curve)& ,
92                               GeomAbs_CurveType& );
93   static
94     Standard_Real AdjustToPeriod(const Standard_Real ,
95                                  const Standard_Real );
96   //
97   void PerformOnePoint();
98   //
99   void PerformGenCurv(const Standard_Real Tol = Precision::PConfusion());
100   //
101   Standard_Integer NbSamples();
102   //
103   Standard_Real AdjustExtr(const Standard_Real UMin,
104                            const Standard_Real UMax,
105                            const Standard_Real Extr0,
106                            const Standard_Integer CoordIndx,
107                            const Standard_Real Tol, 
108                            const Standard_Boolean IsMin);
109   //-----------------------------
110  protected:
111   Handle(Geom2d_Curve) myCurve;
112   Bnd_Box2d myBox;
113   Standard_Integer myErrorStatus;
114   Handle(Geom2d_Curve) myCurveBase;
115   Standard_Real myOffsetBase;
116   Standard_Boolean myOffsetFlag;
117   Standard_Real myT1;
118   Standard_Real myT2;
119   GeomAbs_CurveType myTypeBase;
120 };
121 //
122 class Curv2dMaxMinCoordMVar : public math_MultipleVarFunction
123 {
124 public:
125   Curv2dMaxMinCoordMVar(const Handle(Geom2d_Curve)& theCurve, 
126                         const Standard_Real UMin,
127                         const Standard_Real UMax,
128                         const Standard_Integer CoordIndx,
129                         const Standard_Real Sign)
130 : myCurve(theCurve),
131   myUMin(UMin),
132   myUMax(UMax),
133   myCoordIndx(CoordIndx),
134   mySign(Sign)
135   {
136   }
137
138   Standard_Boolean Value (const math_Vector& X,
139                                 Standard_Real& F)
140   {
141     if (!CheckInputData(X(1)))
142     {
143       return Standard_False;
144     }
145     gp_Pnt2d aP = myCurve->Value(X(1));
146
147     F = mySign * aP.Coord(myCoordIndx);
148
149     return Standard_True;
150   }
151
152   
153
154   Standard_Integer NbVariables() const
155   {
156     return 1;
157   }
158
159 private:
160   Curv2dMaxMinCoordMVar & operator = (const Curv2dMaxMinCoordMVar & theOther);
161
162   Standard_Boolean CheckInputData(Standard_Real theParam)
163   {
164     if (theParam < myUMin || 
165         theParam > myUMax)
166       return Standard_False;
167     return Standard_True;
168   }
169
170   const Handle(Geom2d_Curve)& myCurve;
171   Standard_Real myUMin;
172   Standard_Real myUMax;
173   Standard_Integer myCoordIndx;
174   Standard_Real mySign;
175 };
176 //
177 class Curv2dMaxMinCoord : public math_Function
178 {
179 public:
180   Curv2dMaxMinCoord(const Handle(Geom2d_Curve)& theCurve, 
181                      const Standard_Real UMin,
182                      const Standard_Real UMax,
183                      const Standard_Integer CoordIndx,
184                      const Standard_Real Sign)
185 : myCurve(theCurve),
186   myUMin(UMin),
187   myUMax(UMax),
188   myCoordIndx(CoordIndx),
189   mySign(Sign)
190   {
191   }
192
193   Standard_Boolean Value (const Standard_Real X,
194                                 Standard_Real& F)
195   {
196     if (!CheckInputData(X))
197     {
198       return Standard_False;
199     }
200     gp_Pnt2d aP = myCurve->Value(X);
201
202     F = mySign * aP.Coord(myCoordIndx);
203
204     return Standard_True;
205   }
206
207 private:
208   Curv2dMaxMinCoord & operator = (const Curv2dMaxMinCoord & theOther);
209
210   Standard_Boolean CheckInputData(Standard_Real theParam)
211   {
212     if (theParam < myUMin || 
213         theParam > myUMax)
214       return Standard_False;
215     return Standard_True;
216   }
217
218   const Handle(Geom2d_Curve)& myCurve;
219   Standard_Real myUMin;
220   Standard_Real myUMax;
221   Standard_Integer myCoordIndx;
222   Standard_Real mySign;
223 };
224
225 //=======================================================================
226 //function : 
227 //purpose  : 
228 //=======================================================================
229 BndLib_Box2dCurve::BndLib_Box2dCurve()
230 {
231   Clear();
232 }
233 //=======================================================================
234 //function : ~
235 //purpose  : 
236 //=======================================================================
237 BndLib_Box2dCurve::~BndLib_Box2dCurve()
238 {
239 }
240 //=======================================================================
241 //function : Clear
242 //purpose  : 
243 //=======================================================================
244 void BndLib_Box2dCurve::Clear()
245 {
246   myBox.SetVoid();
247   //
248   myErrorStatus=-1;
249   myTypeBase=GeomAbs_OtherCurve;
250   myOffsetBase=0.;
251   myOffsetFlag=Standard_False;
252 }
253 //=======================================================================
254 //function : SetCurve
255 //purpose  : 
256 //=======================================================================
257 void BndLib_Box2dCurve::SetCurve(const Handle(Geom2d_Curve)& aC2D)
258 {
259   myCurve=aC2D;
260 }
261 //=======================================================================
262 //function : Curve
263 //purpose  : 
264 //=======================================================================
265 const Handle(Geom2d_Curve)& BndLib_Box2dCurve::Curve()const
266 {
267   return myCurve;
268 }
269 //=======================================================================
270 //function : SetRange
271 //purpose  : 
272 //=======================================================================
273 void BndLib_Box2dCurve::SetRange(const Standard_Real aT1,
274                                  const Standard_Real aT2)
275 {
276   myT1=aT1;
277   myT2=aT2;
278 }
279 //=======================================================================
280 //function : tRange
281 //purpose  : 
282 //=======================================================================
283 void BndLib_Box2dCurve::Range(Standard_Real& aT1,
284                               Standard_Real& aT2) const
285 {
286   aT1=myT1;
287   aT2=myT2;
288 }
289 //=======================================================================
290 //function : ErrorStatus
291 //purpose  : 
292 //=======================================================================
293 Standard_Integer BndLib_Box2dCurve::ErrorStatus()const
294 {
295   return myErrorStatus;
296 }
297 //=======================================================================
298 //function : Box
299 //purpose  : 
300 //=======================================================================
301 const Bnd_Box2d& BndLib_Box2dCurve::Box()const
302 {
303   return myBox;
304 }
305 //=======================================================================
306 //function : CheckData
307 //purpose  : 
308 //=======================================================================
309 void BndLib_Box2dCurve::CheckData()
310 {
311   myErrorStatus=0;
312   //
313   if(myCurve.IsNull()) {
314     myErrorStatus=10;
315     return;
316   }
317   //
318   if(myT1>myT2) {
319     myErrorStatus=12; // invalid range
320     return;
321   }
322 }
323 //=======================================================================
324 //function : Perform
325 //purpose  : 
326 //=======================================================================
327 void BndLib_Box2dCurve::Perform()
328 {
329   Clear();
330   // 
331   myErrorStatus=0;
332   //
333   CheckData();
334   if(myErrorStatus) {
335     return;
336   }
337   //
338   if (myT1==myT2) {
339     PerformOnePoint();
340     return;
341   }
342   //
343   GetInfoBase();
344   if(myErrorStatus) {
345     return;
346   }
347   // 
348   if (myTypeBase==GeomAbs_Line ||
349       myTypeBase==GeomAbs_Circle ||
350       myTypeBase==GeomAbs_Ellipse ||
351       myTypeBase==GeomAbs_Parabola ||
352       myTypeBase==GeomAbs_Hyperbola) { // LineConic
353     PerformLineConic();
354   }
355   else if (myTypeBase==GeomAbs_BezierCurve) { // Bezier
356     PerformBezier();
357   }
358   else if (myTypeBase==GeomAbs_BSplineCurve) { //B-Spline
359     PerformBSpline();
360   }
361   else {
362     myErrorStatus=11; // unknown type base
363   }
364 }
365 //=======================================================================
366 //function : PerformOptimal
367 //purpose  : 
368 //=======================================================================
369 void BndLib_Box2dCurve::PerformOptimal(const Standard_Real Tol)
370 {
371   Clear();
372   myErrorStatus=0;
373   CheckData();
374
375   if(myErrorStatus) {
376     return;
377   }
378   
379   if (myT1==myT2) {
380     PerformOnePoint();
381     return;
382   }
383   
384   GetInfoBase();
385   if(myErrorStatus) {
386     return;
387   }
388   
389   if (myTypeBase==GeomAbs_Line ||
390       myTypeBase==GeomAbs_Circle ||
391       myTypeBase==GeomAbs_Ellipse ||
392       myTypeBase==GeomAbs_Parabola ||
393       myTypeBase==GeomAbs_Hyperbola) { // LineConic
394     PerformLineConic();
395   }
396   else {
397     PerformGenCurv(Tol);
398   }
399 }
400 //=======================================================================
401 //function : PerformOnePoint
402 //purpose  : 
403 //=======================================================================
404 void BndLib_Box2dCurve::PerformOnePoint()
405 {
406   gp_Pnt2d aP2D;
407   //
408   myCurve->D0(myT1, aP2D);
409   myBox.Add(aP2D);
410 }
411 //=======================================================================
412 //function : PerformBezier
413 //purpose  : 
414 //=======================================================================
415 void BndLib_Box2dCurve::PerformBezier()
416 {
417   if (myOffsetFlag) {
418     PerformOther();
419     return;
420   }
421   //
422   Standard_Integer i, aNbPoles;
423   Standard_Real aT1, aT2, aTb[2];
424   gp_Pnt2d aP2D;
425   Handle(Geom2d_Geometry) aG;
426   Handle(Geom2d_BezierCurve) aCBz, aCBzSeg;
427   //
428   myErrorStatus=0;
429   Bnd_Box2d& aBox2D=myBox;
430   //
431   aCBz=Handle(Geom2d_BezierCurve)::DownCast(myCurveBase);
432   aT1=aCBz->FirstParameter();
433   aT2=aCBz->LastParameter();
434   //
435   aTb[0]=myT1;
436   if (aTb[0]<aT1) {
437     aTb[0]=aT1;
438   }
439   //
440   aTb[1]=myT2;
441   if (aTb[1]>aT2) {
442     aTb[1]=aT2;
443   }
444   //
445   if (!(aT1==aTb[0] && aT2==aTb[1])) {  
446     aG=aCBz->Copy();
447     //
448     aCBzSeg=Handle(Geom2d_BezierCurve)::DownCast(aG);
449     aCBzSeg->Segment(aTb[0], aTb[1]);
450     aCBz=aCBzSeg;
451   }
452   //
453   aNbPoles=aCBz->NbPoles();
454   for (i=1; i<=aNbPoles; ++i) {
455     aP2D=aCBz->Pole(i);
456     aBox2D.Add(aP2D);
457   }
458 }
459 //=======================================================================
460 //function : PerformBSpline
461 //purpose  : 
462 //=======================================================================
463 void BndLib_Box2dCurve::PerformBSpline()
464 {
465   if (myOffsetFlag) {
466     PerformOther();
467     return;
468   }
469   //
470   Standard_Integer i, aNbPoles;
471   Standard_Real  aT1, aT2, aTb[2];
472   gp_Pnt2d aP2D;
473   Handle(Geom2d_Geometry) aG;
474   Handle(Geom2d_BSplineCurve) aCBS, aCBSs;
475   //
476   myErrorStatus=0;
477   Bnd_Box2d& aBox2D=myBox;
478   //
479   aCBS=Handle(Geom2d_BSplineCurve)::DownCast(myCurveBase);
480   aT1=aCBS->FirstParameter();
481   aT2=aCBS->LastParameter();
482   //
483   aTb[0]=myT1;
484   if (aTb[0]<aT1) {
485     aTb[0]=aT1;
486   } 
487   aTb[1]=myT2;
488   if (aTb[1]>aT2) {
489     aTb[1]=aT2;
490   }
491
492   if(aTb[1] < aTb[0])
493   {
494     aTb[0]=aT1;
495     aTb[1]=aT2;
496   }
497
498   //
499   const Standard_Real eps = Precision::PConfusion();
500   if (fabs(aT1-aTb[0]) > eps || fabs(aT2-aTb[1]) > eps) {
501     aG=aCBS->Copy();
502     //
503     aCBSs=Handle(Geom2d_BSplineCurve)::DownCast(aG);
504     aCBSs->Segment(aTb[0], aTb[1]);
505     aCBS=aCBSs;
506   }
507   //
508   aNbPoles=aCBS->NbPoles();
509   for (i=1; i<=aNbPoles; ++i) {
510     aP2D=aCBS->Pole(i);
511     aBox2D.Add(aP2D);
512   }
513 }
514 //=======================================================================
515 //function : PerformOther
516 //purpose  : 
517 //=======================================================================
518 void BndLib_Box2dCurve::PerformOther()
519 {
520   Standard_Integer j, aNb;
521   Standard_Real aT, dT;
522   gp_Pnt2d aP2D;
523   //
524   aNb=33;
525   dT=(myT2-myT1)/(aNb-1);
526   //
527   for (j=0; j<aNb; ++j) {
528     aT=myT1+j*dT;
529     myCurve->D0(aT, aP2D);
530     myBox.Add(aP2D);
531   }
532   myCurve->D0(myT2, aP2D);
533   myBox.Add(aP2D);
534 }
535 //=======================================================================
536 //function : NbSamples
537 //purpose  : 
538 //=======================================================================
539 Standard_Integer BndLib_Box2dCurve::NbSamples()
540 {
541   Standard_Integer N;
542   switch (myTypeBase) {
543   case GeomAbs_BezierCurve: 
544     {
545       Handle(Geom2d_BezierCurve) aCBz=Handle(Geom2d_BezierCurve)::DownCast(myCurveBase);
546       N = aCBz->NbPoles();
547       //By default parametric range of Bezier curv is [0, 1]
548       Standard_Real du = myT2 - myT1;
549       if(du < .9)
550       {
551         N = RealToInt(du*N) + 1;
552         N = Max(N, 5);
553       }
554       break;
555     }
556   case GeomAbs_BSplineCurve: 
557     {
558       Handle(Geom2d_BSplineCurve) aCBS=Handle(Geom2d_BSplineCurve)::DownCast(myCurveBase);
559       N = (aCBS->Degree() + 1)*(aCBS->NbKnots() -1);
560       Standard_Real umin = aCBS->FirstParameter(), 
561                     umax = aCBS->LastParameter();
562       Standard_Real du = (myT2 - myT1) / (umax - umin);
563       if(du < .9)
564       {
565         N = RealToInt(du*N) + 1;
566         N = Max(N, 5);
567       }
568       break;
569     }
570   default:
571     N = 17;
572   }
573   return Min (23,N);
574 }
575 //=======================================================================
576 //function : AdjustExtr
577 //purpose  : 
578 //=======================================================================
579 Standard_Real BndLib_Box2dCurve::AdjustExtr(const Standard_Real UMin,
580                                             const Standard_Real UMax,
581                                             const Standard_Real Extr0,
582                                             const Standard_Integer CoordIndx,                                 
583                                             const Standard_Real Tol, 
584                                             const Standard_Boolean IsMin)
585 {
586   Standard_Real aSign = IsMin ? 1.:-1.;
587   Standard_Real extr = aSign * Extr0;
588   //
589   Standard_Real Du = (myCurve->LastParameter() - myCurve->FirstParameter());
590   //
591   Geom2dAdaptor_Curve aGAC(myCurve);
592   Standard_Real UTol = Max(aGAC.Resolution(Tol), Precision::PConfusion());
593   Standard_Real reltol = UTol / Max(Abs(UMin), Abs(UMax));
594   if(UMax - UMin < 0.01 * Du)
595   {
596     //It is suggested that function has one extremum on small interval
597     math_BrentMinimum anOptLoc(reltol, 100, UTol);
598     Curv2dMaxMinCoord aFunc(myCurve, UMin, UMax, CoordIndx, aSign);
599     anOptLoc.Perform(aFunc, UMin, (UMin+UMax)/2., UMax);
600     if(anOptLoc.IsDone())
601     {
602       extr = anOptLoc.Minimum();
603       return aSign * extr;
604     }
605   }
606   //
607   Standard_Integer aNbParticles = Max(8, RealToInt(32 * (UMax - UMin) / Du));
608   Standard_Real maxstep = (UMax - UMin) / (aNbParticles + 1);
609   math_Vector aT(1,1);
610   math_Vector aLowBorder(1,1);
611   math_Vector aUppBorder(1,1);
612   math_Vector aSteps(1,1);
613   aLowBorder(1) = UMin;
614   aUppBorder(1) = UMax;
615   aSteps(1) = Min(0.1 * Du, maxstep);
616
617   Curv2dMaxMinCoordMVar aFunc(myCurve, UMin, UMax, CoordIndx, aSign);
618   math_PSO aFinder(&aFunc, aLowBorder, aUppBorder, aSteps, aNbParticles); 
619   aFinder.Perform(aSteps, extr, aT);
620   //
621   math_BrentMinimum anOptLoc(reltol, 100, UTol);
622   Curv2dMaxMinCoord aFunc1(myCurve, UMin, UMax, CoordIndx, aSign);
623   anOptLoc.Perform(aFunc1, Max(aT(1) - aSteps(1), UMin), aT(1), Min(aT(1) + aSteps(1), UMax));
624
625   if(anOptLoc.IsDone())
626   {
627     extr = anOptLoc.Minimum();
628     return aSign * extr;
629   }
630
631   return aSign * extr;
632 }
633
634 //=======================================================================
635 //function : PerformGenCurv
636 //purpose  : 
637 //=======================================================================
638 void BndLib_Box2dCurve::PerformGenCurv(const Standard_Real Tol)
639 {
640   //
641   Standard_Integer Nu = NbSamples();
642   //
643   Standard_Real CoordMin[2] = {RealLast(), RealLast()}; 
644   Standard_Real CoordMax[2] = {-RealLast(), -RealLast()};
645   Standard_Real DeflMax[2] = {-RealLast(), -RealLast()};
646   //
647   gp_Pnt2d P;
648   Standard_Integer i, k;
649   Standard_Real du = (myT2 - myT1)/(Nu-1), du2 = du / 2.;
650   NCollection_Array1<gp_XY> aPnts(1, Nu);
651   Standard_Real u;
652   for (i = 1, u = myT1; i <= Nu; i++, u += du)
653   {
654     D0(u,P);
655     aPnts(i) = P.XY();
656     //
657     for(k = 0; k < 2; ++k)
658     {
659       if(CoordMin[k] > P.Coord(k+1))
660       {
661         CoordMin[k] = P.Coord(k+1);
662       }
663       if(CoordMax[k] < P.Coord(k+1))
664       {
665         CoordMax[k] = P.Coord(k+1);
666       }
667     }
668     //
669     if(i > 1)
670     {
671       gp_XY aPm = 0.5 * (aPnts(i-1) + aPnts(i));
672       D0(u - du2, P);
673       gp_XY aD = (P.XY() - aPm);
674       for(k = 0; k < 2; ++k)
675       {
676         if(CoordMin[k] > P.Coord(k+1))
677         {
678           CoordMin[k] = P.Coord(k+1);
679         }
680         if(CoordMax[k] < P.Coord(k+1))
681         {
682           CoordMax[k] = P.Coord(k+1);
683         }
684         Standard_Real d = Abs(aD.Coord(k+1));
685         if(DeflMax[k] < d)
686         {
687           DeflMax[k] = d;
688         }
689       }
690     }
691   }
692   //
693   //Adjusting minmax 
694   for(k = 0; k < 2; ++k)
695   {
696     Standard_Real d = DeflMax[k];
697     if(d <= Tol)
698     {
699       continue;
700     }
701     Standard_Real CMin = CoordMin[k];
702     Standard_Real CMax = CoordMax[k];
703     for(i = 1; i <= Nu; ++i)
704     {
705       if(aPnts(i).Coord(k+1) - CMin < d)
706       {
707         Standard_Real tmin, tmax;
708         tmin = myT1 + Max(0, i-2) * du;
709         tmax = myT1 + Min(Nu-1, i) * du;
710         Standard_Real cmin = AdjustExtr(tmin, tmax,
711                                         CMin, k + 1, Tol, Standard_True);
712         if(cmin < CMin)
713         {
714           CMin = cmin;
715         }
716       }
717       else if(CMax - aPnts(i).Coord(k+1) < d)
718       {
719         Standard_Real tmin, tmax;
720         tmin = myT1 + Max(0, i-2) * du;
721         tmax = myT1 + Min(Nu-1, i) * du;
722         Standard_Real cmax = AdjustExtr(tmin, tmax,
723                                         CMax, k + 1, Tol, Standard_False);
724         if(cmax > CMax)
725         {
726           CMax = cmax;
727         }
728       }
729     }
730     CoordMin[k] = CMin;
731     CoordMax[k] = CMax;
732   }
733
734   myBox.Add(gp_Pnt2d(CoordMin[0], CoordMin[1]));
735   myBox.Add(gp_Pnt2d(CoordMax[0], CoordMax[1]));
736   myBox.Enlarge(Tol);
737 }
738 //=======================================================================
739 //function : D0
740 //purpose  : 
741 //=======================================================================
742 void BndLib_Box2dCurve::D0(const Standard_Real aU,
743                             gp_Pnt2d& aP2D)  
744 {
745   gp_Vec2d aV1;
746   //
747   myCurveBase->D1(aU, aP2D, aV1);
748   //
749   if (myOffsetFlag) {
750     Standard_Integer aIndex, aMaxDegree;
751     Standard_Real aA, aB, aR, aRes;
752     //
753     aMaxDegree=9;
754     aIndex = 2;
755     aRes=gp::Resolution();
756     //
757     while (aV1.Magnitude() <= aRes && aIndex <= aMaxDegree) {
758       aV1=myCurveBase->DN(aU, aIndex);
759       ++aIndex;
760     }
761     //
762     aA=aV1.Y();
763     aB=-aV1.X();
764     aR=sqrt(aA*aA+aB*aB);
765     if(aR<=aRes) {
766       myErrorStatus=13;
767       return;
768     } 
769     //
770     aR=myOffsetBase/aR;
771     aA=aA*aR;
772     aB=aB*aR;
773     aP2D.SetCoord(aP2D.X()+aA, aP2D.Y()+aB);
774   }
775   //
776 }
777 //=======================================================================
778 //function : GetInfoBase
779 //purpose  : 
780 //=======================================================================
781 void BndLib_Box2dCurve::GetInfoBase()
782 {
783   Standard_Boolean bIsTypeBase;
784   Standard_Integer  iTrimmed, iOffset;
785   GeomAbs_CurveType aTypeB;
786   Handle(Geom2d_Curve) aC2DB;
787   Handle(Geom2d_TrimmedCurve) aCT2D;
788   Handle(Geom2d_OffsetCurve) aCF2D;
789   //
790   myErrorStatus=0;
791   myTypeBase=GeomAbs_OtherCurve;
792   myOffsetBase=0;
793   //
794   aC2DB=myCurve;
795   bIsTypeBase=IsTypeBase(aC2DB, aTypeB);
796   if (bIsTypeBase) {
797     myTypeBase=aTypeB;
798     myCurveBase=myCurve;
799     return;
800   }
801   //
802   while(!bIsTypeBase) {
803     iTrimmed=0;
804     iOffset=0;
805     aCT2D=Handle(Geom2d_TrimmedCurve)::DownCast(aC2DB);
806     if (!aCT2D.IsNull()) {
807       aC2DB=aCT2D->BasisCurve();
808       ++iTrimmed;
809     }
810     //
811     aCF2D=Handle(Geom2d_OffsetCurve)::DownCast(aC2DB);
812     if (!aCF2D.IsNull()) {
813       Standard_Real aOffset;
814       //
815       aOffset=aCF2D->Offset();
816       myOffsetBase=myOffsetBase+aOffset;
817       myOffsetFlag=Standard_True;
818       //
819       aC2DB=aCF2D->BasisCurve();
820       ++iOffset;
821     }
822     //
823     if (!(iTrimmed || iOffset)) {
824       break;
825     }
826     //
827     bIsTypeBase=IsTypeBase(aC2DB, aTypeB);
828     if (bIsTypeBase) {
829       myTypeBase=aTypeB;
830       myCurveBase=aC2DB;
831       return;
832     }
833   }
834   //
835   myErrorStatus=11; // unknown type base
836 }
837 //=======================================================================
838 //function : IsTypeBase
839 //purpose  : 
840 //=======================================================================
841 Standard_Boolean BndLib_Box2dCurve::IsTypeBase
842   (const Handle(Geom2d_Curve)& aC2D,
843    GeomAbs_CurveType& aTypeB)
844 {
845   Standard_Boolean bRet; 
846   Handle(Standard_Type) aType;
847   //
848   bRet=Standard_True;
849   //
850   aType=aC2D->DynamicType();
851   if (aType==STANDARD_TYPE(Geom2d_Line)) {
852     aTypeB=GeomAbs_Line;
853   }
854   else if (aType==STANDARD_TYPE(Geom2d_Circle)) {
855     aTypeB=GeomAbs_Circle;
856   }
857   else if (aType==STANDARD_TYPE(Geom2d_Ellipse)) {
858     aTypeB=GeomAbs_Ellipse;
859   }
860   else if (aType==STANDARD_TYPE(Geom2d_Parabola)) {
861     aTypeB=GeomAbs_Parabola;
862   }
863   else if (aType==STANDARD_TYPE(Geom2d_Hyperbola)) {
864     aTypeB=GeomAbs_Hyperbola;
865   }
866   else if (aType==STANDARD_TYPE(Geom2d_BezierCurve)) {
867     aTypeB=GeomAbs_BezierCurve;
868   }
869   else if (aType==STANDARD_TYPE(Geom2d_BSplineCurve)) {
870     aTypeB=GeomAbs_BSplineCurve;
871   }
872   else {
873     aTypeB=GeomAbs_OtherCurve;
874     bRet=!bRet;
875   }
876   return bRet;
877 }
878 //=======================================================================
879 //function : PerformLineConic
880 //purpose  : 
881 //=======================================================================
882 void BndLib_Box2dCurve::PerformLineConic()
883 {
884   Standard_Integer i, iInf[2];
885   Standard_Real  aTb[2];
886   gp_Pnt2d aP2D;
887   //
888   myErrorStatus=0;
889   //
890   Bnd_Box2d& aBox2D=myBox;
891   //
892   iInf[0]=0;
893   iInf[1]=0;
894   aTb[0]=myT1;
895   aTb[1]=myT2;
896   //
897   for (i=0; i<2; ++i) {
898     if (Precision::IsNegativeInfinite(aTb[i])) {
899       D0(aTb[i], aP2D);
900       aBox2D.Add(aP2D);
901       ++iInf[0];
902     }
903     else if (Precision::IsPositiveInfinite(aTb[i])) {
904       D0(aTb[i], aP2D);
905       aBox2D.Add(aP2D);
906       ++iInf[1];
907     }
908     else {
909       D0(aTb[i], aP2D);
910       aBox2D.Add(aP2D);
911     }
912   } 
913   //
914   if (myTypeBase==GeomAbs_Line) {
915     return;
916   }
917   //
918   if (iInf[0] && iInf[1]) {
919     return;
920   }
921   //-------------
922   Handle(Geom2d_Conic) aConic2D;
923   //
924   aConic2D=Handle(Geom2d_Conic)::DownCast(myCurveBase);
925   Compute(aConic2D, myTypeBase, aTb[0], aTb[1], aBox2D);
926   
927 }
928 //=======================================================================
929 //function : Compute
930 //purpose  : 
931 //=======================================================================
932 void BndLib_Box2dCurve::Compute(const Handle(Geom2d_Conic)& aConic2D,
933                                 const GeomAbs_CurveType aType,
934                                 const Standard_Real aT1,
935                                 const Standard_Real aT2,
936                                 Bnd_Box2d& aBox2D)
937 {
938   Standard_Integer i, aNbT;
939   Standard_Real pT[10], aT, aTwoPI, dT, aEps;
940   gp_Pnt2d aP2D;
941   //
942   aNbT=Compute(aConic2D, aType, pT);
943   //
944   if (aType==GeomAbs_Parabola ||  aType==GeomAbs_Hyperbola) {
945     for (i=0; i<aNbT; ++i) {
946       aT=pT[i];
947       if (aT>aT1 && aT<aT2) {
948         D0(aT, aP2D);
949         aBox2D.Add(aP2D);
950       }
951     }
952     return;
953   }
954   //
955   //aType==GeomAbs_Circle ||  aType==GeomAbs_Ellipse
956   aEps=1.e-14;
957   aTwoPI=2.*M_PI;
958   dT=aT2-aT1;
959   //
960   Standard_Real aT1z = AdjustToPeriod (aT1, aTwoPI);
961   if (fabs(aT1z)<aEps) {
962     aT1z=0.;
963   }
964   //
965   Standard_Real aT2z = aT1z + dT;
966   if (fabs(aT2z-aTwoPI)<aEps) {
967     aT2z=aTwoPI;
968   }
969   //
970   for (i=0; i<aNbT; ++i) {
971     aT = pT[i];
972     // adjust aT to range [aT1z, aT1z + 2*PI]; note that pT[i] and aT1z
973     // are adjusted to range [0, 2*PI], but aT2z can be greater than 2*PI
974     aT = (aT < aT1z ? aT + aTwoPI : aT);
975     if (aT <= aT2z) {
976       D0(aT, aP2D);
977       aBox2D.Add(aP2D);
978     }
979   }
980 }
981
982 //=======================================================================
983 //function : Compute
984 //purpose  : 
985 //=======================================================================
986 Standard_Integer BndLib_Box2dCurve::Compute
987   (const Handle(Geom2d_Conic)& aConic2D,
988    const GeomAbs_CurveType aType,
989    Standard_Real *pT)
990 {
991   Standard_Integer iRet, i, j;
992   Standard_Real aCosBt, aSinBt, aCosGm, aSinGm;
993   Standard_Real aLx, aLy;
994   //
995   iRet=0;
996   //
997   const gp_Ax22d& aPos=aConic2D->Position();
998   const gp_XY& aXDir=aPos.XDirection().XY();
999   const gp_XY& aYDir=aPos.YDirection().XY();
1000   //
1001   aCosBt=aXDir.X();
1002   aSinBt=aXDir.Y();
1003   aCosGm=aYDir.X();
1004   aSinGm=aYDir.Y();
1005   //
1006   if (aType==GeomAbs_Circle ||  aType==GeomAbs_Ellipse) {
1007     Standard_Real aR1 = 0.0, aR2 = 0.0, aTwoPI = M_PI+M_PI;
1008     Standard_Real aA11 = 0.0, aA12 = 0.0, aA21 = 0.0, aA22 = 0.0;
1009     Standard_Real aBx = 0.0, aBy = 0.0, aB = 0.0, aCosFi = 0.0, aSinFi = 0.0, aFi = 0.0;
1010     //
1011     if(aType==GeomAbs_Ellipse) {
1012       Handle(Geom2d_Ellipse) aEL2D;
1013       //
1014       aEL2D=Handle(Geom2d_Ellipse)::DownCast(aConic2D);
1015       aR1=aEL2D->MajorRadius();
1016       aR2=aEL2D->MinorRadius();
1017     }
1018     else if(aType==GeomAbs_Circle) {
1019       Handle(Geom2d_Circle) aCR2D;
1020       //
1021       aCR2D=Handle(Geom2d_Circle)::DownCast(aConic2D);
1022       aR1=aCR2D->Radius();
1023       aR2=aR1;
1024     }
1025     //
1026     aA11=-aR1*aCosBt;
1027     aA12= aR2*aCosGm;
1028     aA21=-aR1*aSinBt;
1029     aA22= aR2*aSinGm;
1030     //
1031     for (i=0; i<2; ++i) {
1032       aLx=(!i) ? 0. : 1.;
1033       aLy=(!i) ? 1. : 0.;
1034       aBx=aLx*aA21-aLy*aA11;
1035       aBy=aLx*aA22-aLy*aA12;
1036       aB=sqrt(aBx*aBx+aBy*aBy);
1037       //
1038       aCosFi=aBx/aB;
1039       aSinFi=aBy/aB;
1040       //
1041       aFi=acos(aCosFi);
1042       if (aSinFi<0.) {
1043         aFi=aTwoPI-aFi;
1044       }
1045       //
1046       j=2*i;
1047       pT[j]=aTwoPI-aFi;
1048       pT[j]=AdjustToPeriod(pT[j], aTwoPI);
1049       //
1050       pT[j+1]=M_PI-aFi;
1051       pT[j+1]=AdjustToPeriod(pT[j+1], aTwoPI);
1052     }
1053     iRet=4;
1054   }//if (aType==GeomAbs_Ellipse) {
1055   //
1056   else if (aType==GeomAbs_Parabola) {
1057     Standard_Real aFc, aEps;
1058     Standard_Real aA1, aA2;
1059     Handle(Geom2d_Parabola) aPR2D;
1060     //
1061     aEps=1.e-12;
1062     //
1063     aPR2D=Handle(Geom2d_Parabola)::DownCast(aConic2D);
1064     aFc=aPR2D->Focal();
1065     //
1066     j=0;
1067     for (i=0; i<2; i++) {
1068       aLx=(!i) ? 0. : 1.;
1069       aLy=(!i) ? 1. : 0.;
1070       //
1071       aA2=aLx*aSinBt-aLy*aCosBt;
1072       if (fabs(aA2)<aEps) {
1073         continue;
1074       } 
1075       //
1076       aA1=aLy*aCosGm-aLx*aSinGm;
1077       //
1078       pT[j]=2.*aFc*aA1/aA2;
1079       ++j;
1080     }
1081     iRet=j;
1082   }// else if (aType==GeomAbs_Parabola) {
1083   //
1084   else if (aType==GeomAbs_Hyperbola) {
1085     Standard_Integer k;
1086     Standard_Real aR1, aR2; 
1087     Standard_Real aEps, aB1, aB2, aB12, aB22, aZ, aD;
1088     Handle(Geom2d_Hyperbola) aHP2D;
1089     //
1090     aEps=1.e-12;
1091     //
1092     aHP2D=Handle(Geom2d_Hyperbola)::DownCast(aConic2D);
1093     aR1=aHP2D->MajorRadius();
1094     aR2=aHP2D->MinorRadius();
1095     //
1096     j=0;
1097     for (i=0; i<2; i++) {
1098       aLx=(!i) ? 0. : 1.;
1099       aLy=(!i) ? 1. : 0.;
1100       //
1101       aB1=aR1*(aLx*aSinBt-aLy*aCosBt);
1102       aB2=aR2*(aLx*aSinGm-aLy*aCosGm);
1103       // 
1104       if (fabs(aB1)<aEps) {
1105         continue;
1106       } 
1107       //
1108       if (fabs(aB2)<aEps) {
1109         pT[j]=0.;
1110         ++j;
1111       } 
1112       else {
1113         aB12=aB1*aB1;
1114         aB22=aB2*aB2;
1115         if (!(aB12>aB22)) {
1116           continue;
1117         }
1118         //
1119         aD=sqrt(aB12-aB22);
1120         //-------------
1121         for (k=-1; k<2; k+=2) {
1122           aZ=(aB1+k*aD)/aB2;
1123           if (fabs(aZ)<1.) {
1124             pT[j]=-log((1.+aZ)/(1.-aZ));
1125             ++j;
1126           }
1127         }
1128       }
1129     }
1130     iRet=j;
1131   }// else if (aType==GeomAbs_Hyperbola) {
1132   //
1133   return iRet;
1134 }
1135 //=======================================================================
1136 //function : AdjustToPeriod
1137 //purpose  : 
1138 //=======================================================================
1139 Standard_Real BndLib_Box2dCurve::AdjustToPeriod(const Standard_Real aT,
1140                                                 const Standard_Real aPeriod)
1141 {
1142   Standard_Integer k;
1143   Standard_Real aTRet;
1144   //
1145   aTRet=aT;
1146   if (aT<0.) {
1147     k=1+(Standard_Integer)(-aT/aPeriod);
1148     aTRet=aT+k*aPeriod;
1149   }
1150   else if (aT>aPeriod) {
1151     k=(Standard_Integer)(aT/aPeriod);
1152     aTRet=aT-k*aPeriod;
1153   }
1154   if (aTRet==aPeriod) {
1155     aTRet=0.;
1156   }
1157   return aTRet;
1158 }
1159 //
1160 // myErrorStatus:
1161 //
1162 // -1 - object is just initialized
1163 // 10 - myCurve is Null
1164 // 12 - invalid range myT1 >  myT2l
1165 // 11 - unknown type of base curve
1166 // 13 - offset curve can not be computed
1167 //NMTTest
1168
1169 //=======================================================================
1170 //function : Add
1171 //purpose  : 
1172 //=======================================================================
1173 void BndLib_Add2dCurve::Add(const Adaptor2d_Curve2d& aC,
1174                              const Standard_Real aTol,
1175                              Bnd_Box2d& aBox2D) 
1176 {
1177   BndLib_Add2dCurve::Add(aC,
1178                           aC.FirstParameter(),
1179                           aC.LastParameter (),
1180                           aTol,
1181                           aBox2D);
1182 }
1183 //=======================================================================
1184 //function : Add
1185 //purpose  : 
1186 //=======================================================================
1187 void BndLib_Add2dCurve::Add(const Adaptor2d_Curve2d& aC,
1188                              const Standard_Real aU1,
1189                              const Standard_Real aU2,
1190                              const Standard_Real aTol,
1191                              Bnd_Box2d& aBox2D)
1192 {
1193   Adaptor2d_Curve2d *pC=(Adaptor2d_Curve2d *)&aC;
1194   Geom2dAdaptor_Curve *pA=dynamic_cast<Geom2dAdaptor_Curve*>(pC);
1195   if (!pA) {
1196     Standard_Real U, DU;
1197     Standard_Integer N, j;
1198     gp_Pnt2d P;
1199     N = 33;
1200     U  = aU1;
1201     DU = (aU2-aU1)/(N-1);
1202     for (j=1; j<N; j++) {
1203       aC.D0(U,P);
1204       U+=DU;
1205       aBox2D.Add(P);
1206     }
1207     aC.D0(aU2,P);
1208     aBox2D.Add(P);
1209     aBox2D.Enlarge(aTol);
1210     return;
1211   }
1212   //
1213   const Handle(Geom2d_Curve)& aC2D=pA->Curve();
1214   //
1215   BndLib_Add2dCurve::Add(aC2D, aU1, aU2, aTol, aBox2D);
1216 }
1217 //=======================================================================
1218 //function : Add
1219 //purpose  : 
1220 //=======================================================================
1221 void BndLib_Add2dCurve::Add(const Handle(Geom2d_Curve)& aC2D,
1222                              const Standard_Real aTol,
1223                              Bnd_Box2d& aBox2D)
1224 {
1225   Standard_Real aT1, aT2;
1226   //
1227   aT1=aC2D->FirstParameter();
1228   aT2=aC2D->LastParameter();
1229   //
1230   BndLib_Add2dCurve::Add(aC2D, aT1, aT2, aTol, aBox2D);
1231 }
1232
1233 //=======================================================================
1234 //function : Add
1235 //purpose  : 
1236 //=======================================================================
1237 void BndLib_Add2dCurve::Add(const Handle(Geom2d_Curve)& aC2D,
1238                              const Standard_Real aT1,
1239                              const Standard_Real aT2,
1240                              const Standard_Real aTol,
1241                              Bnd_Box2d& aBox2D)
1242 {
1243   BndLib_Box2dCurve aBC;
1244   //
1245   aBC.SetCurve(aC2D);
1246   aBC.SetRange(aT1, aT2);
1247   //
1248   aBC.Perform();
1249   //
1250   const Bnd_Box2d& aBoxC=aBC.Box();
1251   aBox2D.Add(aBoxC);
1252   aBox2D.Enlarge(aTol);
1253 }
1254 //=======================================================================
1255 //function : AddOptimal
1256 //purpose  : 
1257 //=======================================================================
1258 void BndLib_Add2dCurve::AddOptimal(const Handle(Geom2d_Curve)& aC2D,
1259                                    const Standard_Real aT1,
1260                                    const Standard_Real aT2,
1261                                    const Standard_Real aTol,
1262                                    Bnd_Box2d& aBox2D)
1263 {
1264   BndLib_Box2dCurve aBC;
1265   //
1266   aBC.SetCurve(aC2D);
1267   aBC.SetRange(aT1, aT2);
1268   //
1269   aBC.PerformOptimal(aTol);
1270   //
1271   const Bnd_Box2d& aBoxC=aBC.Box();
1272   aBox2D.Add(aBoxC);
1273   aBox2D.Enlarge(aTol);
1274 }