0025192: Unification of LineConstructor algorithms used by GeomInt_IntSS and BOP
[occt.git] / src / IntTools / IntTools_FClass2d.cxx
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
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
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.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <IntTools_FClass2d.ixx>
18
19 #include <stdio.h>
20
21 #include <Precision.hxx>
22 #include <gp_Pnt.hxx>
23 #include <ElCLib.hxx>
24
25 #include <Geom2dInt_Geom2dCurveTool.hxx>
26 #include <GeomAbs_SurfaceType.hxx>
27
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>
35
36 #include <TopoDS.hxx>
37 #include <TopoDS_Edge.hxx>
38 #include <TopExp.hxx>
39 #include <TopAbs_Orientation.hxx>
40 #include <TopExp_Explorer.hxx>
41 #include <TColgp_SequenceOfPnt2d.hxx>
42
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>
49
50 //=======================================================================
51 //function : IntTools_FClass2d:IntTools:_FClass2d
52 //purpose  : 
53 //=======================================================================
54 IntTools_FClass2d::IntTools_FClass2d()
55 {
56 }
57 //=======================================================================
58 //function : IntTools_FClass2d::IntTools_FClass2d
59 //purpose  : 
60 //=======================================================================
61   IntTools_FClass2d::IntTools_FClass2d(const TopoDS_Face& aFace,
62                                        const Standard_Real TolUV) 
63 : Toluv(TolUV), Face(aFace)  
64 {
65   Init(Face, Toluv);
66 }
67 //=======================================================================
68 //function : IsHole
69 //purpose  : 
70 //=======================================================================
71   Standard_Boolean IntTools_FClass2d::IsHole() const
72 {
73   return myIsHole;
74
75 //=======================================================================
76 //function : Init
77 //purpose  : 
78 //=======================================================================
79   void IntTools_FClass2d::Init(const TopoDS_Face& aFace,
80                                const Standard_Real TolUV) 
81 {
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;
89   //
90   TopoDS_Edge  edge;
91   TopoDS_Vertex Va,Vb;
92   TopAbs_Orientation Or;
93   BRepTools_WireExplorer aWExp;
94   TopExp_Explorer aExpF, aExp;
95   Handle(Geom2d_Curve) aC2D;
96   gp_Pnt Ancienpnt3d;
97   TColgp_SequenceOfPnt2d SeqPnt2d;
98   TColStd_DataMapOfIntegerInteger anIndexMap;
99   TColgp_SequenceOfVec2d          aD1Prev;
100   TColgp_SequenceOfVec2d          aD1Next;
101   //
102   aPrCf=Precision::Confusion();
103   aPrCf2=aPrCf*aPrCf;
104   myIsHole=Standard_True;
105   //
106   Toluv=TolUV;
107   Face=aFace;
108   Face.Orientation(TopAbs_FORWARD);
109   Handle(BRepAdaptor_HSurface) surf = new BRepAdaptor_HSurface();
110   surf->ChangeSurface().Initialize(aFace, Standard_False);
111   //
112   Tole = 0.;
113   Tol=0.;
114   Umin = Vmin = RealLast();
115   Umax = Vmax = -Umin;
116   BadWire=0;
117   //
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 
121   //
122   aExpF.Init(Face,TopAbs_WIRE); 
123   for(; aExpF.More();  aExpF.Next()) {
124     const TopoDS_Wire& aW=*((TopoDS_Wire*)&aExpF.Current());
125     //
126     nbpnts = 0;
127     firstpoint =1;
128     FlecheU = 0.;
129     FlecheV = 0.;
130     TolVertex1=0.;
131     TolVertex=0.;
132     WireIsNotEmpty = Standard_False;
133     Ancienpnt3dinitialise=Standard_False;
134     Ancienpnt3d.SetCoord(0.,0.,0.);
135     //
136     SeqPnt2d.Clear();
137     anIndexMap.Clear();
138     aD1Prev.Clear();
139     aD1Next.Clear();
140     //
141     // NbEdges
142     NbEdges=0;
143     aExp.Init(aW, TopAbs_EDGE);
144     for(; aExp.More(); aExp.Next()) { 
145       NbEdges++;
146     }
147     //
148     aWExp.Init(aW, Face);
149     for(;aWExp.More(); aWExp.Next()) {
150       NbEdges--;
151       edge = aWExp.Current();
152       Or = edge.Orientation();
153       if(!(Or==TopAbs_FORWARD || Or==TopAbs_REVERSED)) {
154         continue;
155       }
156       //
157       aC2D=BRep_Tool::CurveOnSurface(edge, Face, pfbid, plbid);
158       if (aC2D.IsNull()) {
159         return;
160       }
161       //
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;
169       }
170       //
171       TopExp::Vertices(edge,Va,Vb);
172       //
173       TolVertex1=0.;
174       TolVertex=0.;
175       if (Va.IsNull()) {
176         degenerated=Standard_True;
177       }        
178       else {
179         TolVertex1=BRep_Tool::Tolerance(Va);
180       }
181       if (Vb.IsNull()){
182         degenerated=Standard_True;
183       }        
184       else {
185         TolVertex=BRep_Tool::Tolerance(Vb);
186       }
187         // 
188       if(TolVertex<TolVertex1) {
189         TolVertex=TolVertex1;
190       }        
191       //
192       //-- Verification of cases when forgotten to code degenereted
193       if(!degenerated) {
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));
198         du = plbid - pfbid;
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++)
203         {
204           Standard_Real u = pfbid + i * du / NBSTEPS;
205           gp_Pnt P3db = C3d.Value (u);
206           Standard_Real aR2 = P3da.SquareDistance (P3db);
207           if (aR2 > aPrec2) {
208             degenerated = Standard_False;
209             break;
210           }
211         }
212       }//if(!degenerated)
213       //-- ----------------------------------------
214       Tole = BRep_Tool::Tolerance(edge);
215       if(Tole>Tol) {
216         Tol=Tole;
217       }
218       //
219       // NbSamples +> nbs
220       nbs = Geom2dInt_Geom2dCurveTool::NbSamples(C);
221       if (nbs > 2) {
222         nbs*=4;
223       }
224       du = (plbid-pfbid)/(Standard_Real)(nbs-1);
225       //
226       if(Or==TopAbs_FORWARD) { 
227         u = pfbid;
228         uFirst=pfbid;
229         uLast=plbid;
230       }
231       else { 
232         u = plbid;
233         uFirst=plbid;
234         uLast=pfbid;
235         du=-du;
236       }
237       //
238       // aPrms
239       aNbs1=nbs+1;
240       TColStd_Array1OfReal aPrms(1, aNbs1);
241       //
242       if (nbs==2) {
243         Standard_Real aCoef=0.0025;
244         aPrms(1)=uFirst;
245         aPrms(2)=uFirst+aCoef*(uLast-uFirst);
246         aPrms(3)=uLast;
247       }
248       else if (nbs>2) {
249         aNbs1=nbs;
250         aPrms(1)=uFirst;
251         for (iX=2; iX<aNbs1; ++iX) {
252           aPrms(iX)=u+(iX-1)*du;
253         }
254         aPrms(aNbs1)=uLast;
255       }
256       //
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
262       Avant = nbpnts;
263       for(iX=firstpoint; iX<=aNbs1; iX++) {
264         Standard_Boolean IsRealCurve3d;
265         Standard_Integer ii;
266         Standard_Real aDstX;
267         gp_Pnt2d P2d;
268         gp_Pnt P3d;
269         //
270         u=aPrms(iX);
271         P2d = C.Value(u);
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();
276         //
277         aDstX=RealLast();        
278         if(degenerated==Standard_False) { 
279           P3d=C3d.Value(u);
280           if(nbpnts>1) {
281             if(Ancienpnt3dinitialise) { 
282               aDstX=P3d.SquareDistance(Ancienpnt3d);
283             }
284           }
285         }
286         //
287         IsRealCurve3d = Standard_True; 
288         if (aDstX < aPrCf2)  {
289           if(iX>1) {
290             Standard_Real aDstX1;
291             gp_Pnt MidP3d;
292             //
293             MidP3d = C3d.Value(0.5*(u+aPrms(iX-1)));
294             aDstX1=P3d.SquareDistance( MidP3d );
295             if (aDstX1 < aPrCf2){
296               IsRealCurve3d = Standard_False;
297             }
298           }
299         }
300         //
301         if (IsRealCurve3d) {
302           if(degenerated==Standard_False) { 
303             Ancienpnt3d=P3d;
304             Ancienpnt3dinitialise=Standard_True;
305           }
306           nbpnts++;
307           SeqPnt2d.Append(P2d);
308         }
309         //
310         ii=nbpnts;
311         if(ii>(Avant+4)) { 
312           Standard_Real ul, dU, dV;
313           gp_Pnt2d Pp;
314           //
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());
320           if(dU>FlecheU) {
321             FlecheU = dU;
322           }
323           if(dV>FlecheV) {
324             FlecheV = dV;
325           }
326         }
327       }// for(iX=firstpoint; iX<=aNbs1; iX++) {
328       //
329       if(BadWire) {
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 
333       }
334       //
335       if(firstpoint==1) firstpoint=2;
336       WireIsNotEmpty = Standard_True;
337       // Append the derivative of the first parameter.
338       Standard_Real aU = aPrms(1);
339       gp_Pnt2d      aP;
340       gp_Vec2d      aV;
341
342       C.D1(aU, aP, aV);
343
344       if(Or == TopAbs_REVERSED)
345         aV.Reverse();
346
347       aD1Next.Append(aV);
348
349       // Append the derivative of the last parameter.
350       aU = aPrms(aNbs1);
351       C.D1(aU, aP, aV);
352
353       if(Or == TopAbs_REVERSED)
354         aV.Reverse();
355
356       if (NbEdges > 0)
357         aD1Prev.Append(aV);
358       else
359         aD1Prev.Prepend(aV);
360
361       // Fill the map anIndexMap.
362       if (Avant > 0)
363         anIndexMap.Bind(Avant, aD1Next.Length());
364       else
365         anIndexMap.Bind(1, aD1Next.Length());
366     } //for(;aWExp.More(); aWExp.Next()) {
367     // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
368     //
369     if(NbEdges) { 
370       //-- count ++ with normal explorer and -- with Wire Explorer
371       TColgp_Array1OfPnt2d PClass(1,2);
372       gp_Pnt2d anInitPnt(0., 0.);
373       //
374       PClass.Init(anInitPnt);
375       TabClass.Append((void *)new CSLib_Class2d(PClass,FlecheU,FlecheV,Umin,Vmin,Umax,Vmax));
376       BadWire=1;
377       TabOrien.Append(-1);
378     }
379     //
380     else if(WireIsNotEmpty) { 
381       TColgp_Array1OfPnt2d PClass(1,nbpnts);
382       gp_Pnt2d anInitPnt(0., 0.);
383       //
384       PClass.Init(anInitPnt);
385       if(nbpnts>3) { 
386         Standard_Integer im2=nbpnts-2;
387         Standard_Integer im1=nbpnts-1;
388         Standard_Integer im0=1;
389         Standard_Integer ii;
390         Standard_Real    angle = 0.0;
391         Standard_Real aX0, aY0, aX1, aY1, aS;
392         //
393         aS=0.;
394         //
395
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);
404           //
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); 
411
412           gp_Vec2d A(PClass(im2),PClass(im1));
413           gp_Vec2d B(PClass(im1),PClass(im0));
414
415           Standard_Real N = A.Magnitude() * B.Magnitude();
416           if(N>1e-16) { 
417             Standard_Real a=A.Angle(B);
418             //  
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);
423
424               Standard_Real aN = aVPrev.Magnitude() * aVNext.Magnitude();
425               if(aN > 1e-16) { 
426                 Standard_Real aDerivAngle = aVPrev.Angle(aVNext);
427                 //ifv 23.08.06
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.) {
433                   iFlag=0;
434                   // Bad case.
435                   angle = 0.;
436                 }
437               }
438             }
439             angle+=a;
440           }
441         }//for(ii=1; ii<nbpnts; ii++,im0++,im1++,im2++) { 
442         if (!iFlag) {
443           angle = 0.; 
444         }
445         if(aS>0.){
446           myIsHole=Standard_False;
447         }
448         //
449         if(FlecheU<Toluv)
450           FlecheU = Toluv;
451
452         if(FlecheV<Toluv)
453           FlecheV = Toluv;
454
455         TabClass.Append((void *)new CSLib_Class2d(PClass,FlecheU,FlecheV,Umin,Vmin,Umax,Vmax));
456         //
457         if((angle<2 && angle>-2)||(angle>10)||(angle<-10)) { 
458           BadWire=1;
459           TabOrien.Append(-1);
460         } 
461         else {         
462           TabOrien.Append((angle>0.0)? 1 : 0);
463         }
464       } 
465       else { 
466         BadWire=1;
467         TabOrien.Append(-1);
468         TColgp_Array1OfPnt2d PPClass(1,2);
469         PPClass.Init(anInitPnt);
470         TabClass.Append((void *)new CSLib_Class2d(PPClass,FlecheU,FlecheV,Umin,Vmin,Umax,Vmax));
471       }
472     }// else if(WireIsNotEmpty)
473   } // for(; aExpF.More();  aExpF.Next()) {
474   //
475   Standard_Integer nbtabclass = TabClass.Length();
476   //
477   if(nbtabclass>0) { 
478     //-- if an error on a wire was detected : all TabOrien set to -1
479     if(BadWire) {
480       TabOrien(1)=-1;
481     }
482     
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);
489       if(uuu<0) uuu=0;
490       U1 = Umin-uuu*0.5;
491       U2 = U1+M_PI+M_PI;
492     }
493     else { 
494       U1=U2=0.0; 
495     } 
496     
497     if(surf->GetType()==GeomAbs_Torus) { 
498       Standard_Real uuu=M_PI+M_PI-(Vmax-Vmin);
499       if(uuu<0) uuu=0;
500       
501       V1 = Vmin-uuu*0.5;
502       V2 = V1+M_PI+M_PI;
503     }
504     else { 
505       V1=V2=0.0; 
506     }   
507   }
508 }
509 //=======================================================================
510 //function : PerformInfinitePoint
511 //purpose  : 
512 //=======================================================================
513   TopAbs_State IntTools_FClass2d::PerformInfinitePoint() const 
514
515   if(Umax==-RealLast() || Vmax==-RealLast() || Umin==RealLast() || Vmin==RealLast()) { 
516     return(TopAbs_IN);
517   }
518   gp_Pnt2d P(Umin-(Umax-Umin),Vmin-(Vmax-Vmin));
519   return(Perform(P,Standard_False));
520 }
521 //=======================================================================
522 //function : Perform
523 //purpose  : 
524 //=======================================================================
525   TopAbs_State IntTools_FClass2d::Perform(const gp_Pnt2d& _Puv,
526                                           const Standard_Boolean RecadreOnPeriodic) const
527
528   Standard_Integer nbtabclass = TabClass.Length();
529   if (nbtabclass == 0)
530   {
531     return TopAbs_IN;
532   }
533
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;
540
541   Handle(BRepAdaptor_HSurface) surf = new BRepAdaptor_HSurface();
542   surf->ChangeSurface().Initialize( Face, Standard_False );
543   
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;
548
549   Standard_Boolean urecadre, vrecadre, bUseClassifier;
550   Standard_Integer dedans = 1;
551   //
552   urecadre = Standard_False;
553   vrecadre = Standard_False;
554   //
555   if (RecadreOnPeriodic) {
556     Standard_Real du, dv;
557     if (IsUPer) {
558       GeomInt::AdjustPeriodic(uu, Umin, Umax, uperiod, uu, du);
559     }// if (IsUPer) {
560     //
561     if (IsVPer) {
562       GeomInt::AdjustPeriodic(vv, Vmin, Vmax, vperiod, vv, dv);
563     }//if (IsVPer) {
564   }
565   //
566   for(;;) {
567     dedans = 1;
568     gp_Pnt2d Puv(u,v);
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);
575         
576         if(cur==1) { 
577           if(TabOrien_n==0) { 
578             dedans = -1; 
579             break;
580           }
581         }
582         else if(cur==-1) { 
583           if(TabOrien_n==1) {  
584             dedans = -1; 
585             break;
586           }
587         }
588         else { 
589           dedans = 0;
590           break;
591         }
592       } // for(n=1; n<=nbtabclass; n++)
593       
594       if(dedans==0) { 
595         bUseClassifier = Standard_True;
596       } 
597       else {
598         Status = (dedans == 1) ? TopAbs_IN : TopAbs_OUT;
599       }
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;
606       //
607       aURes = surf->UResolution(Toluv);
608       aVRes = surf->VResolution(Toluv);
609       //
610       bUIn = (u >= Umin) && (u <= Umax);
611       bVIn = (v >= Vmin) && (v <= Vmax);
612       //
613       aFCTol = (bUIn==bVIn) ? Max(aURes, aVRes) : 
614         (!bUIn ? aURes : aVRes);
615       //
616       BRepClass_FaceClassifier aClassifier;
617       aClassifier.Perform(Face,Puv,aFCTol);
618       Status = aClassifier.State();
619     }
620     
621     if (!RecadreOnPeriodic || (!IsUPer && !IsVPer))
622       return Status;
623     
624     if (Status == TopAbs_IN || Status == TopAbs_ON)
625       return Status;
626     
627     if (!urecadre){
628       u = uu;
629       urecadre = Standard_True;
630     }
631     else {
632       if (IsUPer){
633         u += uperiod;
634       }
635     }
636
637     if (u > Umax || !IsUPer) {
638       if (!vrecadre){
639         v = vv;
640         vrecadre = Standard_True;
641       }
642       else {
643         if (IsVPer){
644           v += vperiod;
645         }
646       }
647
648       u = uu;
649       
650       if (v > Vmax || !IsVPer) {
651         return Status;
652       }
653     }
654   } //while (1)
655 }
656
657 //=======================================================================
658 //function : TestOnRestriction
659 //purpose  : 
660 //=======================================================================
661   TopAbs_State IntTools_FClass2d::TestOnRestriction(const gp_Pnt2d& _Puv,
662                                                     const Standard_Real Tol,
663                                                     const Standard_Boolean RecadreOnPeriodic) const
664
665   Standard_Integer nbtabclass = TabClass.Length();
666   if (nbtabclass == 0)
667   {
668     return TopAbs_IN;
669   }
670
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;
675
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;
685
686   if (RecadreOnPeriodic) {
687     Standard_Real du, dv;
688     if (IsUPer) {
689       GeomInt::AdjustPeriodic(uu, Umin, Umax, uperiod, uu, du);
690     }// if (IsUPer) {
691     //
692     if (IsVPer) {
693       GeomInt::AdjustPeriodic(vv, Vmin, Vmax, vperiod, vv, dv);
694     }//if (IsVPer) {
695   }
696   //
697   for (;;) {
698     dedans = 1;
699     gp_Pnt2d Puv(u,v);
700     
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);
704         if(cur==1) { 
705           if(TabOrien(n)==0) { 
706             dedans = -1; 
707             break;
708           }
709         }
710         else if(cur==-1) { 
711           if(TabOrien(n)==1) {  
712             dedans = -1; 
713             break;
714           }
715         }
716         else { 
717           dedans = 0;
718           break;
719         }
720       }
721       if(dedans==0) {
722         Status = TopAbs_ON;
723       }
724       if(dedans == 1) {
725         Status = TopAbs_IN;
726       }
727       if(dedans == -1) {
728         Status = TopAbs_OUT;
729       }
730     }
731     else {  //-- TabOrien(1)=-1  Wrong  Wire 
732       BRepClass_FaceClassifier aClassifier;
733       aClassifier.Perform(Face,Puv,Tol);
734       Status = aClassifier.State();
735     }
736     
737     if (!RecadreOnPeriodic || (!IsUPer && !IsVPer))
738       return Status;
739     if (Status == TopAbs_IN || Status == TopAbs_ON)
740       return Status;
741     
742     if (!urecadre)
743       {
744         u = uu;
745         urecadre = Standard_True;
746       }
747     else
748       if (IsUPer)
749         u += uperiod;
750     if (u > Umax || !IsUPer)
751       {
752         if (!vrecadre)
753           {
754             v = vv;
755             vrecadre = Standard_True;
756           }
757         else
758           if (IsVPer)
759             v += vperiod;
760         
761         u = uu;
762         
763         if (v > Vmax || !IsVPer)
764           return Status;
765       }
766   } //for (;;)
767 }
768
769 //=======================================================================
770 //function : Destroy
771 //purpose  : 
772 //=======================================================================
773   void IntTools_FClass2d::Destroy() 
774
775   Standard_Integer nbtabclass = TabClass.Length(); 
776   for(Standard_Integer d=1; d<=nbtabclass;d++) {
777     if(TabClass(d)) { 
778       delete ((CSLib_Class2d *)TabClass(d));
779       TabClass(d)=NULL;
780     }
781   }
782 }
783
784