1 // Copyright (c) 1996-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
4 // This file is part of Open CASCADE Technology software library.
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.
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
15 #include <BndLib_Add2dCurve.ixx>
18 #include <Precision.hxx>
22 #include <Geom2d_Curve.hxx>
23 #include <Geom2d_TrimmedCurve.hxx>
24 #include <Geom2d_OffsetCurve.hxx>
25 #include <Geom2d_Conic.hxx>
26 #include <Geom2d_Circle.hxx>
27 #include <Geom2d_Ellipse.hxx>
28 #include <Geom2d_Hyperbola.hxx>
29 #include <Geom2d_Parabola.hxx>
30 #include <Standard_Type.hxx>
31 #include <Geom2d_Line.hxx>
32 #include <Geom2d_BezierCurve.hxx>
33 #include <Geom2d_BSplineCurve.hxx>
34 #include <Geom2d_Geometry.hxx>
36 #include <Geom2dAdaptor_Curve.hxx>
40 //=======================================================================
41 //function : BndLib_Box2dCurve
43 //=======================================================================
44 class BndLib_Box2dCurve {
48 virtual ~BndLib_Box2dCurve();
50 void SetCurve(const Handle(Geom2d_Curve)& aC);
52 const Handle_Geom2d_Curve& Curve() const;
54 void SetRange(const Standard_Real aT1,
55 const Standard_Real aT2);
57 void Range(Standard_Real& aT1,
58 Standard_Real& aT2) const;
60 const Bnd_Box2d& Box() const;
66 Standard_Integer ErrorStatus() const;
68 //-----------------------------
72 void PerformLineConic();
74 void PerformBSpline();
76 void D0(const Standard_Real, gp_Pnt2d&);
78 void Compute(const Handle(Geom2d_Conic)&,
79 const GeomAbs_CurveType,
85 Standard_Integer Compute(const Handle(Geom2d_Conic)&,
86 const GeomAbs_CurveType,
89 Standard_Boolean IsTypeBase(const Handle(Geom2d_Curve)& ,
92 Standard_Real AdjustToPeriod(const Standard_Real ,
93 const Standard_Real );
95 void PerformOnePoint();
96 //-----------------------------
98 Handle_Geom2d_Curve myCurve;
100 Standard_Integer myErrorStatus;
101 Handle_Geom2d_Curve myCurveBase;
102 Standard_Real myOffsetBase;
103 Standard_Boolean myOffsetFlag;
106 GeomAbs_CurveType myTypeBase;
110 //=======================================================================
113 //=======================================================================
114 BndLib_Box2dCurve::BndLib_Box2dCurve()
118 //=======================================================================
121 //=======================================================================
122 BndLib_Box2dCurve::~BndLib_Box2dCurve()
125 //=======================================================================
128 //=======================================================================
129 void BndLib_Box2dCurve::Clear()
134 myTypeBase=GeomAbs_OtherCurve;
136 myOffsetFlag=Standard_False;
138 //=======================================================================
139 //function : SetCurve
141 //=======================================================================
142 void BndLib_Box2dCurve::SetCurve(const Handle(Geom2d_Curve)& aC2D)
146 //=======================================================================
149 //=======================================================================
150 const Handle(Geom2d_Curve)& BndLib_Box2dCurve::Curve()const
154 //=======================================================================
155 //function : SetRange
157 //=======================================================================
158 void BndLib_Box2dCurve::SetRange(const Standard_Real aT1,
159 const Standard_Real aT2)
164 //=======================================================================
167 //=======================================================================
168 void BndLib_Box2dCurve::Range(Standard_Real& aT1,
169 Standard_Real& aT2) const
174 //=======================================================================
175 //function : ErrorStatus
177 //=======================================================================
178 Standard_Integer BndLib_Box2dCurve::ErrorStatus()const
180 return myErrorStatus;
182 //=======================================================================
185 //=======================================================================
186 const Bnd_Box2d& BndLib_Box2dCurve::Box()const
190 //=======================================================================
191 //function : CheckData
193 //=======================================================================
194 void BndLib_Box2dCurve::CheckData()
198 if(myCurve.IsNull()) {
204 myErrorStatus=12; // invalid range
208 //=======================================================================
211 //=======================================================================
212 void BndLib_Box2dCurve::Perform()
233 if (myTypeBase==GeomAbs_Line ||
234 myTypeBase==GeomAbs_Circle ||
235 myTypeBase==GeomAbs_Ellipse ||
236 myTypeBase==GeomAbs_Parabola ||
237 myTypeBase==GeomAbs_Hyperbola) { // LineConic
240 else if (myTypeBase==GeomAbs_BezierCurve) { // Bezier
243 else if (myTypeBase==GeomAbs_BSplineCurve) { //B-Spline
247 myErrorStatus=11; // unknown type base
250 //=======================================================================
251 //function : PerformOnePoint
253 //=======================================================================
254 void BndLib_Box2dCurve::PerformOnePoint()
258 myCurve->D0(myT1, aP2D);
261 //=======================================================================
262 //function : PerformBezier
264 //=======================================================================
265 void BndLib_Box2dCurve::PerformBezier()
272 Standard_Integer i, aNbPoles;
273 Standard_Real aT1, aT2, aTb[2];
275 Handle(Geom2d_Geometry) aG;
276 Handle(Geom2d_BezierCurve) aCBz, aCBzSeg;
279 Bnd_Box2d& aBox2D=myBox;
281 aCBz=Handle(Geom2d_BezierCurve)::DownCast(myCurveBase);
282 aT1=aCBz->FirstParameter();
283 aT2=aCBz->LastParameter();
295 if (!(aT1==aTb[0] && aT2==aTb[1])) {
298 aCBzSeg=Handle(Geom2d_BezierCurve)::DownCast(aG);
299 aCBzSeg->Segment(aTb[0], aTb[1]);
303 aNbPoles=aCBz->NbPoles();
304 for (i=1; i<=aNbPoles; ++i) {
309 //=======================================================================
310 //function : PerformBSpline
312 //=======================================================================
313 void BndLib_Box2dCurve::PerformBSpline()
320 Standard_Integer i, aNbPoles;
321 Standard_Real aT1, aT2, aTb[2];
323 Handle(Geom2d_Geometry) aG;
324 Handle(Geom2d_BSplineCurve) aCBS, aCBSs;
327 Bnd_Box2d& aBox2D=myBox;
329 aCBS=Handle(Geom2d_BSplineCurve)::DownCast(myCurveBase);
330 aT1=aCBS->FirstParameter();
331 aT2=aCBS->LastParameter();
349 if (!(aT1==aTb[0] && aT2==aTb[1])) {
352 aCBSs=Handle(Geom2d_BSplineCurve)::DownCast(aG);
353 aCBSs->Segment(aTb[0], aTb[1]);
357 aNbPoles=aCBS->NbPoles();
358 for (i=1; i<=aNbPoles; ++i) {
363 //=======================================================================
364 //function : PerformOther
366 //=======================================================================
367 void BndLib_Box2dCurve::PerformOther()
369 Standard_Integer j, aNb;
370 Standard_Real aT, dT;
374 dT=(myT2-myT1)/(aNb-1);
377 for (j=0; j<aNb; ++j) {
379 myCurve->D0(aT, aP2D);
382 myCurve->D0(myT2, aP2D);
385 //=======================================================================
388 //=======================================================================
389 void BndLib_Box2dCurve::D0(const Standard_Real aU,
394 myCurveBase->D1(aU, aP2D, aV1);
397 Standard_Integer aIndex, aMaxDegree;
398 Standard_Real aA, aB, aR, aRes;
402 aRes=gp::Resolution();
404 while (aV1.Magnitude() <= aRes && aIndex <= aMaxDegree) {
405 aV1=myCurveBase->DN(aU, aIndex);
411 aR=sqrt(aA*aA+aB*aB);
420 aP2D.SetCoord(aP2D.X()+aA, aP2D.Y()+aB);
424 //=======================================================================
425 //function : GetInfoBase
427 //=======================================================================
428 void BndLib_Box2dCurve::GetInfoBase()
430 Standard_Boolean bIsTypeBase;
431 Standard_Integer iTrimmed, iOffset;
432 GeomAbs_CurveType aTypeB;
433 Handle(Geom2d_Curve) aC2DB;
434 Handle(Geom2d_TrimmedCurve) aCT2D;
435 Handle(Geom2d_OffsetCurve) aCF2D;
438 myTypeBase=GeomAbs_OtherCurve;
442 bIsTypeBase=IsTypeBase(aC2DB, aTypeB);
450 while(!bIsTypeBase) {
453 aCT2D=Handle(Geom2d_TrimmedCurve)::DownCast(aC2DB);
454 if (!aCT2D.IsNull()) {
455 aC2DB=aCT2D->BasisCurve();
459 aCF2D=Handle(Geom2d_OffsetCurve)::DownCast(aC2DB);
460 if (!aCF2D.IsNull()) {
461 Standard_Real aOffset;
463 aOffset=aCF2D->Offset();
464 myOffsetBase=myOffsetBase+aOffset;
465 myOffsetFlag=Standard_True;
467 aC2DB=aCF2D->BasisCurve();
471 if (!(iTrimmed || iOffset)) {
475 bIsTypeBase=IsTypeBase(aC2DB, aTypeB);
483 myErrorStatus=11; // unknown type base
485 //=======================================================================
486 //function : IsTypeBase
488 //=======================================================================
489 Standard_Boolean BndLib_Box2dCurve::IsTypeBase
490 (const Handle(Geom2d_Curve)& aC2D,
491 GeomAbs_CurveType& aTypeB)
493 Standard_Boolean bRet;
494 Handle(Standard_Type) aType;
498 aType=aC2D->DynamicType();
499 if (aType==STANDARD_TYPE(Geom2d_Line)) {
502 else if (aType==STANDARD_TYPE(Geom2d_Circle)) {
503 aTypeB=GeomAbs_Circle;
505 else if (aType==STANDARD_TYPE(Geom2d_Ellipse)) {
506 aTypeB=GeomAbs_Ellipse;
508 else if (aType==STANDARD_TYPE(Geom2d_Parabola)) {
509 aTypeB=GeomAbs_Parabola;
511 else if (aType==STANDARD_TYPE(Geom2d_Hyperbola)) {
512 aTypeB=GeomAbs_Hyperbola;
514 else if (aType==STANDARD_TYPE(Geom2d_BezierCurve)) {
515 aTypeB=GeomAbs_BezierCurve;
517 else if (aType==STANDARD_TYPE(Geom2d_BSplineCurve)) {
518 aTypeB=GeomAbs_BSplineCurve;
521 aTypeB=GeomAbs_OtherCurve;
526 //=======================================================================
527 //function : PerformLineConic
529 //=======================================================================
530 void BndLib_Box2dCurve::PerformLineConic()
532 Standard_Integer i, iInf[2];
533 Standard_Real aTb[2], aTinf;
538 Bnd_Box2d& aBox2D=myBox;
540 aTinf=Precision::Infinite();
546 for (i=0; i<2; ++i) {
547 if (Precision::IsNegativeInfinite(aTb[i])) {
552 else if (Precision::IsPositiveInfinite(aTb[i])) {
563 if (myTypeBase==GeomAbs_Line) {
567 if (iInf[0] && iInf[1]) {
571 Handle(Geom2d_Conic) aConic2D;
573 aConic2D=Handle(Geom2d_Conic)::DownCast(myCurveBase);
574 Compute(aConic2D, myTypeBase, aTb[0], aTb[1], aBox2D);
577 //=======================================================================
580 //=======================================================================
581 void BndLib_Box2dCurve::Compute(const Handle(Geom2d_Conic)& aConic2D,
582 const GeomAbs_CurveType aType,
583 const Standard_Real aT1,
584 const Standard_Real aT2,
587 Standard_Integer i, aNbT;
588 Standard_Real pT[10], aT, aTwoPI, aT1x, aT2x, dT, aT1z, aT2z, aEps;
591 aNbT=Compute(aConic2D, aType, pT);
593 if (aType==GeomAbs_Parabola || aType==GeomAbs_Hyperbola) {
594 for (i=0; i<aNbT; ++i) {
596 if (aT>aT1 && aT<aT2) {
604 //aType==GeomAbs_Circle || aType==GeomAbs_Ellipse
612 aT1z=AdjustToPeriod(aT1z, aTwoPI);
615 if (fabs(aT1z)<aEps) {
619 if (fabs(aT2z-aTwoPI)<aEps) {
623 for (i=0; i<aNbT; ++i) {
625 if (aT>=aT1z && aT<=aT2z) {
631 aT1x=AdjustToPeriod(aT1, aTwoPI);
634 if (aT1x < aTwoPI && aT2x > aTwoPI) {
637 for (i=0; i<aNbT; ++i) {
639 if (aT>=aT1z && aT<=aT2z) {
647 for (i=0; i<aNbT; ++i) {
649 if (aT>=aT1z && aT<=aT2z) {
656 //=======================================================================
659 //=======================================================================
660 Standard_Integer BndLib_Box2dCurve::Compute
661 (const Handle(Geom2d_Conic)& aConic2D,
662 const GeomAbs_CurveType aType,
665 Standard_Integer iRet, i, j;
666 Standard_Real aCosBt, aSinBt, aCosGm, aSinGm;
667 Standard_Real aLx, aLy;
671 const gp_Ax22d& aPos=aConic2D->Position();
672 const gp_XY& aXDir=aPos.XDirection().XY();
673 const gp_XY& aYDir=aPos.YDirection().XY();
680 if (aType==GeomAbs_Circle || aType==GeomAbs_Ellipse) {
681 Standard_Real aR1 = 0.0, aR2 = 0.0, aTwoPI = M_PI+M_PI;
682 Standard_Real aA11 = 0.0, aA12 = 0.0, aA21 = 0.0, aA22 = 0.0;
683 Standard_Real aBx = 0.0, aBy = 0.0, aB = 0.0, aCosFi = 0.0, aSinFi = 0.0, aFi = 0.0;
685 if(aType==GeomAbs_Ellipse) {
686 Handle(Geom2d_Ellipse) aEL2D;
688 aEL2D=Handle(Geom2d_Ellipse)::DownCast(aConic2D);
689 aR1=aEL2D->MajorRadius();
690 aR2=aEL2D->MinorRadius();
692 else if(aType==GeomAbs_Circle) {
693 Handle(Geom2d_Circle) aCR2D;
695 aCR2D=Handle(Geom2d_Circle)::DownCast(aConic2D);
705 for (i=0; i<2; ++i) {
708 aBx=aLx*aA21-aLy*aA11;
709 aBy=aLx*aA22-aLy*aA12;
710 aB=sqrt(aBx*aBx+aBy*aBy);
722 pT[j]=AdjustToPeriod(pT[j], aTwoPI);
725 pT[j+1]=AdjustToPeriod(pT[j+1], aTwoPI);
728 }//if (aType==GeomAbs_Ellipse) {
730 else if (aType==GeomAbs_Parabola) {
731 Standard_Real aFc, aEps;
732 Standard_Real aA1, aA2;
733 Handle(Geom2d_Parabola) aPR2D;
737 aPR2D=Handle(Geom2d_Parabola)::DownCast(aConic2D);
741 for (i=0; i<2; i++) {
745 aA2=aLx*aSinBt-aLy*aCosBt;
746 if (fabs(aA2)<aEps) {
750 aA1=aLy*aCosGm-aLx*aSinGm;
752 pT[j]=2.*aFc*aA1/aA2;
756 }// else if (aType==GeomAbs_Parabola) {
758 else if (aType==GeomAbs_Hyperbola) {
760 Standard_Real aR1, aR2;
761 Standard_Real aEps, aB1, aB2, aB12, aB22, aZ, aD;
762 Handle(Geom2d_Hyperbola) aHP2D;
766 aHP2D=Handle(Geom2d_Hyperbola)::DownCast(aConic2D);
767 aR1=aHP2D->MajorRadius();
768 aR2=aHP2D->MinorRadius();
771 for (i=0; i<2; i++) {
775 aB1=aR1*(aLx*aSinBt-aLy*aCosBt);
776 aB2=aR2*(aLx*aSinGm-aLy*aCosGm);
778 if (fabs(aB1)<aEps) {
782 if (fabs(aB2)<aEps) {
795 for (k=-1; k<2; k+=2) {
798 pT[j]=-log((1.+aZ)/(1.-aZ));
805 }// else if (aType==GeomAbs_Hyperbola) {
809 //=======================================================================
810 //function : AdjustToPeriod
812 //=======================================================================
813 Standard_Real BndLib_Box2dCurve::AdjustToPeriod(const Standard_Real aT,
814 const Standard_Real aPeriod)
821 k=1+(Standard_Integer)(-aT/aPeriod);
824 else if (aT>aPeriod) {
825 k=(Standard_Integer)(aT/aPeriod);
828 if (aTRet==aPeriod) {
836 // -1 - object is just initialized
837 // 10 - myCurve is Null
838 // 12 - invalid range myT1 > myT2l
839 // 11 - unknown type of base curve
840 // 13 - offset curve can not be computed
843 //=======================================================================
846 //=======================================================================
847 void BndLib_Add2dCurve::Add(const Adaptor2d_Curve2d& aC,
848 const Standard_Real aTol,
851 BndLib_Add2dCurve::Add(aC,
857 //=======================================================================
860 //=======================================================================
861 void BndLib_Add2dCurve::Add(const Adaptor2d_Curve2d& aC,
862 const Standard_Real aU1,
863 const Standard_Real aU2,
864 const Standard_Real aTol,
867 Adaptor2d_Curve2d *pC=(Adaptor2d_Curve2d *)&aC;
868 Geom2dAdaptor_Curve *pA=dynamic_cast<Geom2dAdaptor_Curve*>(pC);
871 Standard_Integer N, j;
875 DU = (aU2-aU1)/(N-1);
876 for (j=1; j<N; j++) {
883 aBox2D.Enlarge(aTol);
887 const Handle(Geom2d_Curve)& aC2D=pA->Curve();
889 BndLib_Add2dCurve::Add(aC2D, aU1, aU2, aTol, aBox2D);
891 //=======================================================================
894 //=======================================================================
895 void BndLib_Add2dCurve::Add(const Handle(Geom2d_Curve)& aC2D,
896 const Standard_Real aTol,
899 Standard_Real aT1, aT2;
901 aT1=aC2D->FirstParameter();
902 aT2=aC2D->LastParameter();
904 BndLib_Add2dCurve::Add(aC2D, aT1, aT2, aTol, aBox2D);
907 //=======================================================================
910 //=======================================================================
911 void BndLib_Add2dCurve::Add(const Handle(Geom2d_Curve)& aC2D,
912 const Standard_Real aT1,
913 const Standard_Real aT2,
914 const Standard_Real aTol,
917 BndLib_Box2dCurve aBC;
920 aBC.SetRange(aT1, aT2);
924 const Bnd_Box2d& aBoxC=aBC.Box();
926 aBox2D.Enlarge(aTol);