1 // Created on: 1995-03-22
2 // Created by: Laurent BUCHARD
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 #include <IntTools_FClass2d.ixx>
21 #include <Precision.hxx>
25 #include <Geom2dInt_Geom2dCurveTool.hxx>
26 #include <GeomAbs_SurfaceType.hxx>
28 #include <BRep_Tool.hxx>
29 #include <BRepTools_WireExplorer.hxx>
30 #include <BRepClass_FaceClassifier.hxx>
31 #include <CSLib_Class2d.hxx>
32 #include <BRepAdaptor_HSurface.hxx>
33 #include <BRepAdaptor_Curve.hxx>
34 #include <BRepAdaptor_Curve2d.hxx>
37 #include <TopoDS_Edge.hxx>
39 #include <TopAbs_Orientation.hxx>
40 #include <TopExp_Explorer.hxx>
41 #include <TColgp_SequenceOfPnt2d.hxx>
43 #include <TColgp_Array1OfPnt2d.hxx>
44 #include <TopoDS_Wire.hxx>
45 #include <TColStd_DataMapOfIntegerInteger.hxx>
46 #include <TColgp_SequenceOfVec2d.hxx>
47 #include <IntTools_Tools.hxx>
48 #include <GeomInt.hxx>
50 //=======================================================================
51 //function : IntTools_FClass2d:IntTools:_FClass2d
53 //=======================================================================
54 IntTools_FClass2d::IntTools_FClass2d()
57 //=======================================================================
58 //function : IntTools_FClass2d::IntTools_FClass2d
60 //=======================================================================
61 IntTools_FClass2d::IntTools_FClass2d(const TopoDS_Face& aFace,
62 const Standard_Real TolUV)
63 : Toluv(TolUV), Face(aFace)
67 //=======================================================================
70 //=======================================================================
71 Standard_Boolean IntTools_FClass2d::IsHole() const
75 //=======================================================================
78 //=======================================================================
79 void IntTools_FClass2d::Init(const TopoDS_Face& aFace,
80 const Standard_Real TolUV)
82 Standard_Boolean WireIsNotEmpty, Ancienpnt3dinitialise, degenerated;
83 Standard_Integer nbpnts, firstpoint, NbEdges;
84 Standard_Integer iX, aNbs1, nbs, Avant, BadWire;
85 Standard_Real u, du, Tole, Tol, pfbid, plbid;
86 Standard_Real FlecheU, FlecheV, TolVertex1, TolVertex;
87 Standard_Real uFirst, uLast;
88 Standard_Real aPrCf, aPrCf2;
92 TopAbs_Orientation Or;
93 BRepTools_WireExplorer aWExp;
94 TopExp_Explorer aExpF, aExp;
95 Handle(Geom2d_Curve) aC2D;
97 TColgp_SequenceOfPnt2d SeqPnt2d;
98 TColStd_DataMapOfIntegerInteger anIndexMap;
99 TColgp_SequenceOfVec2d aD1Prev;
100 TColgp_SequenceOfVec2d aD1Next;
102 aPrCf=Precision::Confusion();
104 myIsHole=Standard_True;
108 Face.Orientation(TopAbs_FORWARD);
109 Handle(BRepAdaptor_HSurface) surf = new BRepAdaptor_HSurface();
110 surf->ChangeSurface().Initialize(aFace, Standard_False);
114 Umin = Vmin = RealLast();
118 //if face has several wires and one of them is bad,
119 //it is necessary to process all of them for correct
120 //calculation of Umin, Umax, Vmin, Vmax - ifv, 23.08.06
122 aExpF.Init(Face,TopAbs_WIRE);
123 for(; aExpF.More(); aExpF.Next()) {
124 const TopoDS_Wire& aW=*((TopoDS_Wire*)&aExpF.Current());
132 WireIsNotEmpty = Standard_False;
133 Ancienpnt3dinitialise=Standard_False;
134 Ancienpnt3d.SetCoord(0.,0.,0.);
143 aExp.Init(aW, TopAbs_EDGE);
144 for(; aExp.More(); aExp.Next()) {
148 aWExp.Init(aW, Face);
149 for(;aWExp.More(); aWExp.Next()) {
151 edge = aWExp.Current();
152 Or = edge.Orientation();
153 if(!(Or==TopAbs_FORWARD || Or==TopAbs_REVERSED)) {
157 aC2D=BRep_Tool::CurveOnSurface(edge, Face, pfbid, plbid);
162 BRepAdaptor_Curve2d C(edge,Face);
163 BRepAdaptor_Curve C3d;
164 //------------------------------------------
165 degenerated=Standard_False;
166 if(BRep_Tool::Degenerated(edge) ||
167 BRep_Tool::IsClosed(edge, Face)) {
168 degenerated=Standard_True;
171 TopExp::Vertices(edge,Va,Vb);
176 degenerated=Standard_True;
179 TolVertex1=BRep_Tool::Tolerance(Va);
182 degenerated=Standard_True;
185 TolVertex=BRep_Tool::Tolerance(Vb);
188 if(TolVertex<TolVertex1) {
189 TolVertex=TolVertex1;
192 //-- Verification of cases when forgotten to code degenereted
194 // check that whole curve is located in vicinity of its middle point
195 // (within sphere of Precision::Confusion() diameter)
196 C3d.Initialize (edge, Face);
197 gp_Pnt P3da = C3d.Value (0.5 * (pfbid + plbid));
199 const int NBSTEPS = 10;
200 Standard_Real aPrec2 = 0.25 * Precision::Confusion() * Precision::Confusion();
201 degenerated = Standard_True;
202 for (Standard_Integer i=0; i <= NBSTEPS; i++)
204 Standard_Real u = pfbid + i * du / NBSTEPS;
205 gp_Pnt P3db = C3d.Value (u);
206 Standard_Real aR2 = P3da.SquareDistance (P3db);
208 degenerated = Standard_False;
213 //-- ----------------------------------------
214 Tole = BRep_Tool::Tolerance(edge);
220 nbs = Geom2dInt_Geom2dCurveTool::NbSamples(C);
224 du = (plbid-pfbid)/(Standard_Real)(nbs-1);
226 if(Or==TopAbs_FORWARD) {
240 TColStd_Array1OfReal aPrms(1, aNbs1);
243 Standard_Real aCoef=0.0025;
245 aPrms(2)=uFirst+aCoef*(uLast-uFirst);
251 for (iX=2; iX<aNbs1; ++iX) {
252 aPrms(iX)=u+(iX-1)*du;
257 //-- ------------------------------------------------------------
258 //-- Check distance uv between the start point of the edge
259 //-- and the last point saved in SeqPnt2d
260 //-- To to set the first point of the current
261 //-- afar from the last saved point
263 for(iX=firstpoint; iX<=aNbs1; iX++) {
264 Standard_Boolean IsRealCurve3d;
272 if(P2d.X()<Umin) Umin = P2d.X();
273 if(P2d.X()>Umax) Umax = P2d.X();
274 if(P2d.Y()<Vmin) Vmin = P2d.Y();
275 if(P2d.Y()>Vmax) Vmax = P2d.Y();
278 if(degenerated==Standard_False) {
281 if(Ancienpnt3dinitialise) {
282 aDstX=P3d.SquareDistance(Ancienpnt3d);
287 IsRealCurve3d = Standard_True;
288 if (aDstX < aPrCf2) {
290 Standard_Real aDstX1;
293 MidP3d = C3d.Value(0.5*(u+aPrms(iX-1)));
294 aDstX1=P3d.SquareDistance( MidP3d );
295 if (aDstX1 < aPrCf2){
296 IsRealCurve3d = Standard_False;
302 if(degenerated==Standard_False) {
304 Ancienpnt3dinitialise=Standard_True;
307 SeqPnt2d.Append(P2d);
312 Standard_Real ul, dU, dV;
315 gp_Lin2d Lin(SeqPnt2d(ii-2),gp_Dir2d(gp_Vec2d(SeqPnt2d(ii-2),SeqPnt2d(ii))));
316 ul = ElCLib::Parameter(Lin,SeqPnt2d(ii-1));
317 Pp = ElCLib::Value(ul,Lin);
318 dU = Abs(Pp.X()-SeqPnt2d(ii-1).X());
319 dV = Abs(Pp.Y()-SeqPnt2d(ii-1).Y());
327 }// for(iX=firstpoint; iX<=aNbs1; iX++) {
330 continue; //if face has several wires and one of them is bad,
331 //it is necessary to process all of them for correct
332 //calculation of Umin, Umax, Vmin, Vmax - ifv, 23.08.06
335 if(firstpoint==1) firstpoint=2;
336 WireIsNotEmpty = Standard_True;
337 // Append the derivative of the first parameter.
338 Standard_Real aU = aPrms(1);
344 if(Or == TopAbs_REVERSED)
349 // Append the derivative of the last parameter.
353 if(Or == TopAbs_REVERSED)
361 // Fill the map anIndexMap.
363 anIndexMap.Bind(Avant, aD1Next.Length());
365 anIndexMap.Bind(1, aD1Next.Length());
366 } //for(;aWExp.More(); aWExp.Next()) {
367 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
370 //-- count ++ with normal explorer and -- with Wire Explorer
371 TColgp_Array1OfPnt2d PClass(1,2);
372 gp_Pnt2d anInitPnt(0., 0.);
374 PClass.Init(anInitPnt);
375 TabClass.Append((void *)new CSLib_Class2d(PClass,FlecheU,FlecheV,Umin,Vmin,Umax,Vmax));
380 else if(WireIsNotEmpty) {
381 TColgp_Array1OfPnt2d PClass(1,nbpnts);
382 gp_Pnt2d anInitPnt(0., 0.);
384 PClass.Init(anInitPnt);
386 Standard_Integer im2=nbpnts-2;
387 Standard_Integer im1=nbpnts-1;
388 Standard_Integer im0=1;
390 Standard_Real angle = 0.0;
391 Standard_Real aX0, aY0, aX1, aY1, aS;
396 Standard_Integer iFlag=1;
397 PClass(im2)=SeqPnt2d.Value(im2);
398 PClass(im1)=SeqPnt2d.Value(im1);
399 PClass(nbpnts)=SeqPnt2d.Value(nbpnts);
400 for(ii=1; ii<nbpnts; ii++,im0++,im1++,im2++) {
401 if(im2>=nbpnts) im2=1;
402 if(im1>=nbpnts) im1=1;
403 PClass(ii)=SeqPnt2d.Value(ii);
405 const gp_Pnt2d& aP2D1=PClass(im1);
406 const gp_Pnt2d& aP2D0=PClass(im0);
407 //aP2D0 is next to aP2D1
408 aP2D0.Coord(aX0, aY0);
409 aP2D1.Coord(aX1, aY1);
410 aS=aS+(aY0+aY1)*(aX1-aX0);
412 gp_Vec2d A(PClass(im2),PClass(im1));
413 gp_Vec2d B(PClass(im1),PClass(im0));
415 Standard_Real N = A.Magnitude() * B.Magnitude();
417 Standard_Real a=A.Angle(B);
419 if (anIndexMap.IsBound(im1)) {
420 Standard_Integer anInd = anIndexMap.Find(im1);
421 const gp_Vec2d &aVPrev = aD1Prev.Value(anInd);
422 const gp_Vec2d &aVNext = aD1Next.Value(anInd);
424 Standard_Real aN = aVPrev.Magnitude() * aVNext.Magnitude();
426 Standard_Real aDerivAngle = aVPrev.Angle(aVNext);
428 if(Abs(aDerivAngle) <= Precision::Angular()) aDerivAngle = 0.;
429 //ifv 23.08.06 : if edges continuity > G1, |aDerivAngle| ~0,
430 //but can has wrong sign and causes condition aDerivAngle * a < 0.
431 //that is wrong in such situation
432 if (iFlag && aDerivAngle * a < 0.) {
441 }//for(ii=1; ii<nbpnts; ii++,im0++,im1++,im2++) {
446 myIsHole=Standard_False;
455 TabClass.Append((void *)new CSLib_Class2d(PClass,FlecheU,FlecheV,Umin,Vmin,Umax,Vmax));
457 if((angle<2 && angle>-2)||(angle>10)||(angle<-10)) {
462 TabOrien.Append((angle>0.0)? 1 : 0);
468 TColgp_Array1OfPnt2d PPClass(1,2);
469 PPClass.Init(anInitPnt);
470 TabClass.Append((void *)new CSLib_Class2d(PPClass,FlecheU,FlecheV,Umin,Vmin,Umax,Vmax));
472 }// else if(WireIsNotEmpty)
473 } // for(; aExpF.More(); aExpF.Next()) {
475 Standard_Integer nbtabclass = TabClass.Length();
478 //-- if an error on a wire was detected : all TabOrien set to -1
483 if( surf->GetType()==GeomAbs_Cone
484 || surf->GetType()==GeomAbs_Cylinder
485 || surf->GetType()==GeomAbs_Torus
486 || surf->GetType()==GeomAbs_Sphere
487 || surf->GetType()==GeomAbs_SurfaceOfRevolution) {
488 Standard_Real uuu=M_PI+M_PI-(Umax-Umin);
497 if(surf->GetType()==GeomAbs_Torus) {
498 Standard_Real uuu=M_PI+M_PI-(Vmax-Vmin);
509 //=======================================================================
510 //function : PerformInfinitePoint
512 //=======================================================================
513 TopAbs_State IntTools_FClass2d::PerformInfinitePoint() const
515 if(Umax==-RealLast() || Vmax==-RealLast() || Umin==RealLast() || Vmin==RealLast()) {
518 gp_Pnt2d P(Umin-(Umax-Umin),Vmin-(Vmax-Vmin));
519 return(Perform(P,Standard_False));
521 //=======================================================================
524 //=======================================================================
525 TopAbs_State IntTools_FClass2d::Perform(const gp_Pnt2d& _Puv,
526 const Standard_Boolean RecadreOnPeriodic) const
528 Standard_Integer nbtabclass = TabClass.Length();
534 //-- U1 is the First Param and U2 is in this case U1+Period
535 Standard_Real u = _Puv.X();
536 Standard_Real v = _Puv.Y();
537 Standard_Real uu = u;
538 Standard_Real vv = v;
539 TopAbs_State Status = TopAbs_UNKNOWN;
541 Handle(BRepAdaptor_HSurface) surf = new BRepAdaptor_HSurface();
542 surf->ChangeSurface().Initialize( Face, Standard_False );
544 const Standard_Boolean IsUPer = surf->IsUPeriodic();
545 const Standard_Boolean IsVPer = surf->IsVPeriodic();
546 const Standard_Real uperiod = IsUPer ? surf->UPeriod() : 0.0;
547 const Standard_Real vperiod = IsVPer ? surf->VPeriod() : 0.0;
549 Standard_Boolean urecadre, vrecadre, bUseClassifier;
550 Standard_Integer dedans = 1;
552 urecadre = Standard_False;
553 vrecadre = Standard_False;
555 if (RecadreOnPeriodic) {
556 Standard_Real du, dv;
558 GeomInt::AdjustPeriodic(uu, Umin, Umax, uperiod, uu, du);
562 GeomInt::AdjustPeriodic(vv, Vmin, Vmax, vperiod, vv, dv);
569 bUseClassifier = (TabOrien(1) == -1);
570 if(!bUseClassifier) {
571 Standard_Integer n, cur, TabOrien_n ;
572 for(n=1; n<=nbtabclass; n++) {
573 cur = ((CSLib_Class2d *)TabClass(n))->SiDans(Puv);
574 TabOrien_n=TabOrien(n);
592 } // for(n=1; n<=nbtabclass; n++)
595 bUseClassifier = Standard_True;
598 Status = (dedans == 1) ? TopAbs_IN : TopAbs_OUT;
600 } // if(TabOrien(1)!=-1) {
601 //compute state of the point using face classifier
602 if (bUseClassifier) {
603 //compute tolerance to use in face classifier
604 Standard_Real aURes, aVRes, aFCTol;
605 Standard_Boolean bUIn, bVIn;
607 aURes = surf->UResolution(Toluv);
608 aVRes = surf->VResolution(Toluv);
610 bUIn = (u >= Umin) && (u <= Umax);
611 bVIn = (v >= Vmin) && (v <= Vmax);
613 aFCTol = (bUIn==bVIn) ? Max(aURes, aVRes) :
614 (!bUIn ? aURes : aVRes);
616 BRepClass_FaceClassifier aClassifier;
617 aClassifier.Perform(Face,Puv,aFCTol);
618 Status = aClassifier.State();
621 if (!RecadreOnPeriodic || (!IsUPer && !IsVPer))
624 if (Status == TopAbs_IN || Status == TopAbs_ON)
629 urecadre = Standard_True;
637 if (u > Umax || !IsUPer) {
640 vrecadre = Standard_True;
650 if (v > Vmax || !IsVPer) {
657 //=======================================================================
658 //function : TestOnRestriction
660 //=======================================================================
661 TopAbs_State IntTools_FClass2d::TestOnRestriction(const gp_Pnt2d& _Puv,
662 const Standard_Real Tol,
663 const Standard_Boolean RecadreOnPeriodic) const
665 Standard_Integer nbtabclass = TabClass.Length();
671 //-- U1 is the First Param and U2 in this case is U1+Period
672 Standard_Real u=_Puv.X();
673 Standard_Real v=_Puv.Y();
674 Standard_Real uu = u, vv = v;
676 Handle(BRepAdaptor_HSurface) surf = new BRepAdaptor_HSurface();
677 surf->ChangeSurface().Initialize( Face, Standard_False );
678 const Standard_Boolean IsUPer = surf->IsUPeriodic();
679 const Standard_Boolean IsVPer = surf->IsVPeriodic();
680 const Standard_Real uperiod = IsUPer ? surf->UPeriod() : 0.0;
681 const Standard_Real vperiod = IsVPer ? surf->VPeriod() : 0.0;
682 TopAbs_State Status = TopAbs_UNKNOWN;
683 Standard_Boolean urecadre = Standard_False, vrecadre = Standard_False;
684 Standard_Integer dedans = 1;
686 if (RecadreOnPeriodic) {
687 Standard_Real du, dv;
689 GeomInt::AdjustPeriodic(uu, Umin, Umax, uperiod, uu, du);
693 GeomInt::AdjustPeriodic(vv, Vmin, Vmax, vperiod, vv, dv);
701 if(TabOrien(1)!=-1) {
702 for(Standard_Integer n=1; n<=nbtabclass; n++) {
703 Standard_Integer cur = ((CSLib_Class2d *)TabClass(n))->SiDans_OnMode(Puv,Tol);
731 else { //-- TabOrien(1)=-1 Wrong Wire
732 BRepClass_FaceClassifier aClassifier;
733 aClassifier.Perform(Face,Puv,Tol);
734 Status = aClassifier.State();
737 if (!RecadreOnPeriodic || (!IsUPer && !IsVPer))
739 if (Status == TopAbs_IN || Status == TopAbs_ON)
745 urecadre = Standard_True;
750 if (u > Umax || !IsUPer)
755 vrecadre = Standard_True;
763 if (v > Vmax || !IsVPer)
769 //=======================================================================
772 //=======================================================================
773 void IntTools_FClass2d::Destroy()
775 Standard_Integer nbtabclass = TabClass.Length();
776 for(Standard_Integer d=1; d<=nbtabclass;d++) {
778 delete ((CSLib_Class2d *)TabClass(d));