0031642: Visualization - crash in Graphic3d_Structure::SetVisual() on redisplaying...
[occt.git] / src / BndLib / BndLib_Add2dCurve.cxx
CommitLineData
b311480e 1// Copyright (c) 1996-1999 Matra Datavision
973c2be1 2// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 3//
973c2be1 4// This file is part of Open CASCADE Technology software library.
b311480e 5//
d5f74e42 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
973c2be1 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.
b311480e 11//
973c2be1 12// Alternatively, this file may be used under the terms of Open CASCADE
13// commercial license or contractual agreement.
7fd59977 14
7fd59977 15
42cf5bc1 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>
59495dbe 21#include <Geom2d_Circle.hxx>
42cf5bc1 22#include <Geom2d_Conic.hxx>
23#include <Geom2d_Curve.hxx>
59495dbe 24#include <Geom2d_Ellipse.hxx>
42cf5bc1 25#include <Geom2d_Geometry.hxx>
59495dbe 26#include <Geom2d_Hyperbola.hxx>
59495dbe 27#include <Geom2d_Line.hxx>
42cf5bc1 28#include <Geom2d_OffsetCurve.hxx>
29#include <Geom2d_Parabola.hxx>
30#include <Geom2d_TrimmedCurve.hxx>
59495dbe 31#include <Geom2dAdaptor_Curve.hxx>
42cf5bc1 32#include <gp.hxx>
33#include <Precision.hxx>
34#include <Standard_Type.hxx>
3ba87fdb 35#include <math_MultipleVarFunction.hxx>
36#include <math_Function.hxx>
37#include <math_BrentMinimum.hxx>
38#include <math_PSO.hxx>
7fd59977 39
40//=======================================================================
59495dbe 41//function : BndLib_Box2dCurve
7fd59977 42//purpose :
43//=======================================================================
59495dbe 44class BndLib_Box2dCurve {
45 public:
46 BndLib_Box2dCurve();
47
48 virtual ~BndLib_Box2dCurve();
49
50 void SetCurve(const Handle(Geom2d_Curve)& aC);
51
35c0599a 52 const Handle(Geom2d_Curve)& Curve() const;
59495dbe 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;
7fd59977 61
59495dbe 62 void Perform();
63
3ba87fdb 64 void PerformOptimal(const Standard_Real Tol);
65
59495dbe 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();
3ba87fdb 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);
59495dbe 109 //-----------------------------
110 protected:
35c0599a 111 Handle(Geom2d_Curve) myCurve;
59495dbe 112 Bnd_Box2d myBox;
113 Standard_Integer myErrorStatus;
35c0599a 114 Handle(Geom2d_Curve) myCurveBase;
59495dbe 115 Standard_Real myOffsetBase;
116 Standard_Boolean myOffsetFlag;
117 Standard_Real myT1;
118 Standard_Real myT2;
119 GeomAbs_CurveType myTypeBase;
120};
3ba87fdb 121//
122class Curv2dMaxMinCoordMVar : public math_MultipleVarFunction
123{
124public:
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
159private:
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//
177class Curv2dMaxMinCoord : public math_Function
178{
179public:
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 }
59495dbe 206
3ba87fdb 207private:
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};
59495dbe 224
225//=======================================================================
226//function :
227//purpose :
228//=======================================================================
229BndLib_Box2dCurve::BndLib_Box2dCurve()
7fd59977 230{
59495dbe 231 Clear();
7fd59977 232}
7fd59977 233//=======================================================================
59495dbe 234//function : ~
7fd59977 235//purpose :
236//=======================================================================
59495dbe 237BndLib_Box2dCurve::~BndLib_Box2dCurve()
238{
239}
240//=======================================================================
241//function : Clear
242//purpose :
243//=======================================================================
244void 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//=======================================================================
257void BndLib_Box2dCurve::SetCurve(const Handle(Geom2d_Curve)& aC2D)
258{
259 myCurve=aC2D;
260}
261//=======================================================================
262//function : Curve
263//purpose :
264//=======================================================================
265const Handle(Geom2d_Curve)& BndLib_Box2dCurve::Curve()const
266{
267 return myCurve;
268}
269//=======================================================================
270//function : SetRange
271//purpose :
272//=======================================================================
273void 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//=======================================================================
283void 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//=======================================================================
293Standard_Integer BndLib_Box2dCurve::ErrorStatus()const
294{
295 return myErrorStatus;
296}
297//=======================================================================
298//function : Box
299//purpose :
300//=======================================================================
301const Bnd_Box2d& BndLib_Box2dCurve::Box()const
302{
303 return myBox;
304}
305//=======================================================================
306//function : CheckData
307//purpose :
308//=======================================================================
309void 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//=======================================================================
327void BndLib_Box2dCurve::Perform()
7fd59977 328{
59495dbe 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//=======================================================================
3ba87fdb 366//function : PerformOptimal
367//purpose :
368//=======================================================================
369void 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//=======================================================================
59495dbe 401//function : PerformOnePoint
402//purpose :
403//=======================================================================
404void 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//=======================================================================
415void 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//=======================================================================
463void 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 }
7fd59977 491
59495dbe 492 if(aTb[1] < aTb[0])
493 {
494 aTb[0]=aT1;
495 aTb[1]=aT2;
496 }
497
498 //
81093856 499 const Standard_Real eps = Precision::PConfusion();
500 if (fabs(aT1-aTb[0]) > eps || fabs(aT2-aTb[1]) > eps) {
59495dbe 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//=======================================================================
518void 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 //
59495dbe 527 for (j=0; j<aNb; ++j) {
ece3f950 528 aT=myT1+j*dT;
59495dbe 529 myCurve->D0(aT, aP2D);
530 myBox.Add(aP2D);
531 }
532 myCurve->D0(myT2, aP2D);
533 myBox.Add(aP2D);
534}
535//=======================================================================
3ba87fdb 536//function : NbSamples
537//purpose :
538//=======================================================================
539Standard_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//=======================================================================
579Standard_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//=======================================================================
638void 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//=======================================================================
59495dbe 739//function : D0
740//purpose :
741//=======================================================================
742void 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;
7fd59977 760 }
59495dbe 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//=======================================================================
781void 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 //
59495dbe 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;
7fd59977 809 }
59495dbe 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;
7fd59977 821 }
59495dbe 822 //
823 if (!(iTrimmed || iOffset)) {
7fd59977 824 break;
825 }
59495dbe 826 //
827 bIsTypeBase=IsTypeBase(aC2DB, aTypeB);
828 if (bIsTypeBase) {
829 myTypeBase=aTypeB;
830 myCurveBase=aC2DB;
831 return;
7fd59977 832 }
59495dbe 833 }
834 //
835 myErrorStatus=11; // unknown type base
836}
837//=======================================================================
838//function : IsTypeBase
839//purpose :
840//=======================================================================
841Standard_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//=======================================================================
882void BndLib_Box2dCurve::PerformLineConic()
883{
884 Standard_Integer i, iInf[2];
bcf50875 885 Standard_Real aTb[2];
59495dbe 886 gp_Pnt2d aP2D;
887 //
888 myErrorStatus=0;
889 //
890 Bnd_Box2d& aBox2D=myBox;
891 //
59495dbe 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//=======================================================================
932void 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;
99661617 939 Standard_Real pT[10], aT, aTwoPI, dT, aEps;
59495dbe 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);
7fd59977 950 }
59495dbe 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 //
99661617 960 Standard_Real aT1z = AdjustToPeriod (aT1, aTwoPI);
59495dbe 961 if (fabs(aT1z)<aEps) {
962 aT1z=0.;
963 }
964 //
99661617 965 Standard_Real aT2z = aT1z + dT;
59495dbe 966 if (fabs(aT2z-aTwoPI)<aEps) {
967 aT2z=aTwoPI;
968 }
99661617 969 //
59495dbe 970 for (i=0; i<aNbT; ++i) {
99661617 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) {
59495dbe 976 D0(aT, aP2D);
977 aBox2D.Add(aP2D);
978 }
979 }
59495dbe 980}
99661617 981
59495dbe 982//=======================================================================
983//function : Compute
984//purpose :
985//=======================================================================
986Standard_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;
7fd59977 1044 }
59495dbe 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);
7fd59977 1052 }
59495dbe 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 }
7fd59977 1128 }
7fd59977 1129 }
59495dbe 1130 iRet=j;
1131 }// else if (aType==GeomAbs_Hyperbola) {
1132 //
1133 return iRet;
1134}
1135//=======================================================================
1136//function : AdjustToPeriod
1137//purpose :
1138//=======================================================================
1139Standard_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;
7fd59977 1149 }
59495dbe 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;
7fd59977 1158}
59495dbe 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
7fd59977 1168
59495dbe 1169//=======================================================================
1170//function : Add
1171//purpose :
1172//=======================================================================
1173void 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//=======================================================================
1187void 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//=======================================================================
1221void 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}
7fd59977 1232
59495dbe 1233//=======================================================================
1234//function : Add
1235//purpose :
1236//=======================================================================
1237void 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}
3ba87fdb 1254//=======================================================================
1255//function : AddOptimal
1256//purpose :
1257//=======================================================================
1258void 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}