0026254: Inject GeomAbs_OffsetCurve into GeomAbs_CurveType enumeration
[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
18 #include <BRep_Tool.hxx>
19 #include <BRepAdaptor_Curve.hxx>
20 #include <BRepAdaptor_Curve2d.hxx>
21 #include <BRepAdaptor_HSurface.hxx>
22 #include <BRepClass_FaceClassifier.hxx>
23 #include <BRepTools_WireExplorer.hxx>
24 #include <CSLib_Class2d.hxx>
25 #include <ElCLib.hxx>
26 #include <Geom2dInt_Geom2dCurveTool.hxx>
27 #include <GeomAbs_SurfaceType.hxx>
28 #include <GeomInt.hxx>
29 #include <gp_Pnt.hxx>
30 #include <gp_Pnt2d.hxx>
31 #include <IntTools_FClass2d.hxx>
32 #include <IntTools_Tools.hxx>
33 #include <Precision.hxx>
34 #include <TColgp_Array1OfPnt2d.hxx>
35 #include <TColgp_SequenceOfPnt2d.hxx>
36 #include <TColgp_SequenceOfVec2d.hxx>
37 #include <TColStd_DataMapOfIntegerInteger.hxx>
38 #include <TopAbs_Orientation.hxx>
39 #include <TopExp.hxx>
40 #include <TopExp_Explorer.hxx>
41 #include <TopoDS.hxx>
42 #include <TopoDS_Edge.hxx>
43 #include <TopoDS_Face.hxx>
44 #include <TopoDS_Wire.hxx>
45
46 #include <stdio.h>
47 //=======================================================================
48 //function : IntTools_FClass2d:IntTools:_FClass2d
49 //purpose  : 
50 //=======================================================================
51 IntTools_FClass2d::IntTools_FClass2d()
52 {
53 }
54 //=======================================================================
55 //function : IntTools_FClass2d::IntTools_FClass2d
56 //purpose  : 
57 //=======================================================================
58 IntTools_FClass2d::IntTools_FClass2d(const TopoDS_Face& aFace,
59                                      const Standard_Real TolUV) 
60 : Toluv(TolUV), Face(aFace)  
61 {
62   Init(Face, Toluv);
63 }
64 //=======================================================================
65 //function : IsHole
66 //purpose  : 
67 //=======================================================================
68 Standard_Boolean IntTools_FClass2d::IsHole() const
69 {
70   return myIsHole;
71
72 //=======================================================================
73 //function : Init
74 //purpose  : 
75 //=======================================================================
76 void IntTools_FClass2d::Init(const TopoDS_Face& aFace,
77                              const Standard_Real TolUV) 
78 {
79   Standard_Boolean WireIsNotEmpty, Ancienpnt3dinitialise, degenerated;
80   Standard_Integer nbpnts, firstpoint, NbEdges;
81   Standard_Integer iX, aNbs1, nbs, Avant, BadWire;
82   Standard_Real u, du, Tole, Tol, pfbid, plbid;
83   Standard_Real FlecheU, FlecheV, TolVertex1, TolVertex;
84   Standard_Real uFirst, uLast;
85   Standard_Real aPrCf, aPrCf2;
86   //
87   TopoDS_Edge  edge;
88   TopoDS_Vertex Va,Vb;
89   TopAbs_Orientation Or;
90   BRepTools_WireExplorer aWExp;
91   TopExp_Explorer aExpF, aExp;
92   Handle(Geom2d_Curve) aC2D;
93   gp_Pnt Ancienpnt3d;
94   TColgp_SequenceOfPnt2d SeqPnt2d;
95   TColStd_DataMapOfIntegerInteger anIndexMap;
96   TColgp_SequenceOfVec2d          aD1Prev;
97   TColgp_SequenceOfVec2d          aD1Next;
98   //
99   aPrCf=Precision::Confusion();
100   aPrCf2=aPrCf*aPrCf;
101   myIsHole=Standard_True;
102   //
103   Toluv=TolUV;
104   Face=aFace;
105   Face.Orientation(TopAbs_FORWARD);
106   Handle(BRepAdaptor_HSurface) surf = new BRepAdaptor_HSurface();
107   surf->ChangeSurface().Initialize(aFace, Standard_False);
108   //
109   Tole = 0.;
110   Tol=0.;
111   Umin = Vmin = RealLast();
112   Umax = Vmax = -Umin;
113   BadWire=0;
114   //
115   //if face has several wires and one of them is bad,
116   //it is necessary to process all of them for correct
117   //calculation of Umin, Umax, Vmin, Vmax - ifv, 23.08.06 
118   //
119   aExpF.Init(Face,TopAbs_WIRE); 
120   for(; aExpF.More();  aExpF.Next()) {
121     const TopoDS_Wire& aW=*((TopoDS_Wire*)&aExpF.Current());
122     //
123     nbpnts = 0;
124     firstpoint =1;
125     FlecheU = 0.;
126     FlecheV = 0.;
127     TolVertex1=0.;
128     TolVertex=0.;
129     WireIsNotEmpty = Standard_False;
130     Ancienpnt3dinitialise=Standard_False;
131     Ancienpnt3d.SetCoord(0.,0.,0.);
132     //
133     SeqPnt2d.Clear();
134     anIndexMap.Clear();
135     aD1Prev.Clear();
136     aD1Next.Clear();
137     //
138     // NbEdges
139     NbEdges=0;
140     aExp.Init(aW, TopAbs_EDGE);
141     for(; aExp.More(); aExp.Next()) { 
142       NbEdges++;
143     }
144     //
145     aWExp.Init(aW, Face);
146     for(;aWExp.More(); aWExp.Next()) {
147       NbEdges--;
148       edge = aWExp.Current();
149       Or = edge.Orientation();
150       if(!(Or==TopAbs_FORWARD || Or==TopAbs_REVERSED)) {
151         continue;
152       }
153       //
154       aC2D=BRep_Tool::CurveOnSurface(edge, Face, pfbid, plbid);
155       if (aC2D.IsNull()) {
156         return;
157       }
158       //
159       BRepAdaptor_Curve2d C(edge,Face);
160       BRepAdaptor_Curve C3d;
161       //------------------------------------------
162       degenerated=Standard_False;
163       if(BRep_Tool::Degenerated(edge) ||
164          BRep_Tool::IsClosed(edge, Face)) {
165         degenerated=Standard_True;
166       }
167       //
168       TopExp::Vertices(edge,Va,Vb);
169       //
170       TolVertex1=0.;
171       TolVertex=0.;
172       if (Va.IsNull()) {
173         degenerated=Standard_True;
174       }        
175       else {
176         TolVertex1=BRep_Tool::Tolerance(Va);
177       }
178       if (Vb.IsNull()){
179         degenerated=Standard_True;
180       }        
181       else {
182         TolVertex=BRep_Tool::Tolerance(Vb);
183       }
184         // 
185       if(TolVertex<TolVertex1) {
186         TolVertex=TolVertex1;
187       }        
188       //
189       //-- Verification of cases when forgotten to code degenereted
190       if(!degenerated) {
191         // check that whole curve is located in vicinity of its middle point
192         // (within sphere of Precision::Confusion() diameter)
193         C3d.Initialize (edge, Face);
194         gp_Pnt P3da = C3d.Value (0.5 * (pfbid + plbid));
195         du = plbid - pfbid;
196         const int NBSTEPS = 10;
197         Standard_Real aPrec2 = 0.25 * Precision::Confusion() * Precision::Confusion();
198         degenerated = Standard_True;
199         for (Standard_Integer i=0; i <= NBSTEPS; i++)
200         {
201           Standard_Real U = pfbid + i * du / NBSTEPS;
202           gp_Pnt P3db = C3d.Value (U);
203           Standard_Real aR2 = P3da.SquareDistance (P3db);
204           if (aR2 > aPrec2) {
205             degenerated = Standard_False;
206             break;
207           }
208         }
209       }//if(!degenerated)
210       //-- ----------------------------------------
211       Tole = BRep_Tool::Tolerance(edge);
212       if(Tole>Tol) {
213         Tol=Tole;
214       }
215       //
216       // NbSamples +> nbs
217       nbs = Geom2dInt_Geom2dCurveTool::NbSamples(C);
218       if (nbs > 2) {
219         nbs*=4;
220       }
221       du = (plbid-pfbid)/(Standard_Real)(nbs-1);
222       //
223       if(Or==TopAbs_FORWARD) { 
224         u = pfbid;
225         uFirst=pfbid;
226         uLast=plbid;
227       }
228       else { 
229         u = plbid;
230         uFirst=plbid;
231         uLast=pfbid;
232         du=-du;
233       }
234       //
235       // aPrms
236       aNbs1=nbs+1;
237       TColStd_Array1OfReal aPrms(1, aNbs1);
238       //
239       if (nbs==2) {
240         Standard_Real aCoef=0.0025;
241         aPrms(1)=uFirst;
242         aPrms(2)=uFirst+aCoef*(uLast-uFirst);
243         aPrms(3)=uLast;
244       }
245       else if (nbs>2) {
246         aNbs1=nbs;
247         aPrms(1)=uFirst;
248         for (iX=2; iX<aNbs1; ++iX) {
249           aPrms(iX)=u+(iX-1)*du;
250         }
251         aPrms(aNbs1)=uLast;
252       }
253       //
254       //-- ------------------------------------------------------------
255       //-- Check distance uv between the start point of the edge
256       //-- and the last point saved in SeqPnt2d
257       //-- To to set the first point of the current 
258       //-- afar from the last saved point
259       Avant = nbpnts;
260       for(iX=firstpoint; iX<=aNbs1; iX++) {
261         Standard_Boolean IsRealCurve3d;
262         Standard_Integer ii;
263         Standard_Real aDstX;
264         gp_Pnt2d P2d;
265         gp_Pnt P3d;
266         //
267         u=aPrms(iX);
268         P2d = C.Value(u);
269         if(P2d.X()<Umin) Umin = P2d.X();
270         if(P2d.X()>Umax) Umax = P2d.X();
271         if(P2d.Y()<Vmin) Vmin = P2d.Y();
272         if(P2d.Y()>Vmax) Vmax = P2d.Y();
273         //
274         aDstX=RealLast();        
275         if(degenerated==Standard_False) { 
276           P3d=C3d.Value(u);
277           if(nbpnts>1) {
278             if(Ancienpnt3dinitialise) { 
279               aDstX=P3d.SquareDistance(Ancienpnt3d);
280             }
281           }
282         }
283         //
284         IsRealCurve3d = Standard_True; 
285         if (aDstX < aPrCf2)  {
286           if(iX>1) {
287             Standard_Real aDstX1;
288             gp_Pnt MidP3d;
289             //
290             MidP3d = C3d.Value(0.5*(u+aPrms(iX-1)));
291             aDstX1=P3d.SquareDistance( MidP3d );
292             if (aDstX1 < aPrCf2){
293               IsRealCurve3d = Standard_False;
294             }
295           }
296         }
297         //
298         if (IsRealCurve3d) {
299           if(degenerated==Standard_False) { 
300             Ancienpnt3d=P3d;
301             Ancienpnt3dinitialise=Standard_True;
302           }
303           nbpnts++;
304           SeqPnt2d.Append(P2d);
305         }
306         //
307         ii=nbpnts;
308         if(ii>(Avant+4)) { 
309           Standard_Real ul, dU, dV;
310           gp_Pnt2d Pp;
311           //
312           gp_Lin2d Lin(SeqPnt2d(ii-2),gp_Dir2d(gp_Vec2d(SeqPnt2d(ii-2),SeqPnt2d(ii))));
313           ul = ElCLib::Parameter(Lin,SeqPnt2d(ii-1));
314           Pp = ElCLib::Value(ul,Lin);
315           dU = Abs(Pp.X()-SeqPnt2d(ii-1).X());
316           dV = Abs(Pp.Y()-SeqPnt2d(ii-1).Y());
317           if(dU>FlecheU) {
318             FlecheU = dU;
319           }
320           if(dV>FlecheV) {
321             FlecheV = dV;
322           }
323         }
324       }// for(iX=firstpoint; iX<=aNbs1; iX++) {
325       //
326       if(BadWire) {
327         continue; //if face has several wires and one of them is bad,
328                   //it is necessary to process all of them for correct
329                   //calculation of Umin, Umax, Vmin, Vmax - ifv, 23.08.06 
330       }
331       //
332       if(firstpoint==1) firstpoint=2;
333       WireIsNotEmpty = Standard_True;
334       // Append the derivative of the first parameter.
335       Standard_Real aU = aPrms(1);
336       gp_Pnt2d      aP;
337       gp_Vec2d      aV;
338
339       C.D1(aU, aP, aV);
340
341       if(Or == TopAbs_REVERSED)
342         aV.Reverse();
343
344       aD1Next.Append(aV);
345
346       // Append the derivative of the last parameter.
347       aU = aPrms(aNbs1);
348       C.D1(aU, aP, aV);
349
350       if(Or == TopAbs_REVERSED)
351         aV.Reverse();
352
353       if (NbEdges > 0)
354         aD1Prev.Append(aV);
355       else
356         aD1Prev.Prepend(aV);
357
358       // Fill the map anIndexMap.
359       if (Avant > 0)
360         anIndexMap.Bind(Avant, aD1Next.Length());
361       else
362         anIndexMap.Bind(1, aD1Next.Length());
363     } //for(;aWExp.More(); aWExp.Next()) {
364     // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
365     //
366     if(NbEdges) { 
367       //-- count ++ with normal explorer and -- with Wire Explorer
368       TColgp_Array1OfPnt2d PClass(1,2);
369       gp_Pnt2d anInitPnt(0., 0.);
370       //
371       PClass.Init(anInitPnt);
372       TabClass.Append((void *)new CSLib_Class2d(PClass,
373                                                 FlecheU,
374                                                 FlecheV,
375                                                 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         Standard_Integer iFlag=1;
396         //
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, aAbsDA, aProduct, aPA;
427                 //ifv 23.08.06
428                 aPA=Precision::Angular();
429                 aDerivAngle = aVPrev.Angle(aVNext);
430                 aAbsDA=Abs(aDerivAngle);
431                 if(aAbsDA <= aPA) {
432                   aDerivAngle = 0.; 
433                 }
434                 //
435                 aProduct=aDerivAngle * a;
436                 //
437                 if(Abs(aAbsDA - M_PI) <= aPA) {
438                   if (aProduct > 0.) {
439                     aProduct=-aProduct; 
440                   }
441                 }
442                 //ifv 23.08.06 : if edges continuity > G1, |aDerivAngle| ~0,
443                 //but can has wrong sign and causes condition aDerivAngle * a < 0.
444                 //that is wrong in such situation
445                 if (iFlag && aProduct < 0.) {
446                   iFlag=0;
447                   // Bad case.
448                   angle = 0.;
449                 }
450               }
451             }
452             angle+=a;
453           }
454         }//for(ii=1; ii<nbpnts; ii++,im0++,im1++,im2++) { 
455         if (!iFlag) {
456           angle = 0.; 
457         }
458         if(aS>0.){
459           myIsHole=Standard_False;
460         }
461         //
462         if(FlecheU<Toluv)
463           FlecheU = Toluv;
464
465         if(FlecheV<Toluv)
466           FlecheV = Toluv;
467
468         TabClass.Append((void *)new CSLib_Class2d(PClass,
469                                                   FlecheU,
470                                                   FlecheV,
471                                                   Umin,Vmin,Umax,Vmax));
472         //
473         if((angle<2 && angle>-2)||(angle>10)||(angle<-10)) { 
474           BadWire=1;
475           TabOrien.Append(-1);
476         } 
477         else {         
478           TabOrien.Append((angle>0.0)? 1 : 0);
479         }
480       } 
481       else { 
482         BadWire=1;
483         TabOrien.Append(-1);
484         TColgp_Array1OfPnt2d PPClass(1,2);
485         PPClass.Init(anInitPnt);
486         TabClass.Append((void *)new CSLib_Class2d(PPClass,
487                                                   FlecheU,
488                                                   FlecheV,
489                                                   Umin,Vmin,Umax,Vmax));
490       }
491     }// else if(WireIsNotEmpty)
492   } // for(; aExpF.More();  aExpF.Next()) {
493   //
494   Standard_Integer nbtabclass = TabClass.Length();
495   //
496   if(nbtabclass>0) { 
497     //-- if an error on a wire was detected : all TabOrien set to -1
498     if(BadWire) {
499       TabOrien(1)=-1;
500     }
501     
502     if(   surf->GetType()==GeomAbs_Cone
503        || surf->GetType()==GeomAbs_Cylinder
504        || surf->GetType()==GeomAbs_Torus
505        || surf->GetType()==GeomAbs_Sphere
506        || surf->GetType()==GeomAbs_SurfaceOfRevolution) { 
507       Standard_Real uuu=M_PI+M_PI-(Umax-Umin);
508       if(uuu<0) uuu=0;
509       U1 = Umin-uuu*0.5;
510       U2 = U1+M_PI+M_PI;
511     }
512     else { 
513       U1=U2=0.0; 
514     } 
515     
516     if(surf->GetType()==GeomAbs_Torus) { 
517       Standard_Real uuu=M_PI+M_PI-(Vmax-Vmin);
518       if(uuu<0) uuu=0;
519       
520       V1 = Vmin-uuu*0.5;
521       V2 = V1+M_PI+M_PI;
522     }
523     else { 
524       V1=V2=0.0; 
525     }   
526   }
527 }
528 //=======================================================================
529 //function : PerformInfinitePoint
530 //purpose  : 
531 //=======================================================================
532 TopAbs_State IntTools_FClass2d::PerformInfinitePoint() const 
533
534   if(Umax==-RealLast() || Vmax==-RealLast() || 
535      Umin==RealLast() || Vmin==RealLast()) { 
536     return(TopAbs_IN);
537   }
538   gp_Pnt2d P(Umin-(Umax-Umin),Vmin-(Vmax-Vmin));
539   return(Perform(P,Standard_False));
540 }
541 //=======================================================================
542 //function : Perform
543 //purpose  : 
544 //=======================================================================
545 TopAbs_State IntTools_FClass2d::Perform
546   (const gp_Pnt2d& _Puv,
547    const Standard_Boolean RecadreOnPeriodic) const
548
549   Standard_Integer nbtabclass = TabClass.Length();
550   if (nbtabclass == 0)
551   {
552     return TopAbs_IN;
553   }
554
555   //-- U1 is the First Param and U2 is in this case U1+Period
556   Standard_Real u = _Puv.X();
557   Standard_Real v = _Puv.Y();
558   Standard_Real uu = u;
559   Standard_Real vv = v;
560   TopAbs_State Status = TopAbs_UNKNOWN;
561
562   Handle(BRepAdaptor_HSurface) surf = new BRepAdaptor_HSurface();
563   surf->ChangeSurface().Initialize( Face, Standard_False );
564   
565   const Standard_Boolean IsUPer  = surf->IsUPeriodic();
566   const Standard_Boolean IsVPer  = surf->IsVPeriodic();
567   const Standard_Real    uperiod = IsUPer ? surf->UPeriod() : 0.0;
568   const Standard_Real    vperiod = IsVPer ? surf->VPeriod() : 0.0;
569
570   Standard_Boolean urecadre, vrecadre, bUseClassifier;
571   Standard_Integer dedans = 1;
572   //
573   urecadre = Standard_False;
574   vrecadre = Standard_False;
575   //
576   if (RecadreOnPeriodic) {
577     Standard_Real du, dv;
578     if (IsUPer) {
579       GeomInt::AdjustPeriodic(uu, Umin, Umax, uperiod, uu, du);
580     }// if (IsUPer) {
581     //
582     if (IsVPer) {
583       GeomInt::AdjustPeriodic(vv, Vmin, Vmax, vperiod, vv, dv);
584     }//if (IsVPer) {
585   }
586   //
587   for(;;) {
588     dedans = 1;
589     gp_Pnt2d Puv(u,v);
590     bUseClassifier = (TabOrien(1) == -1);
591     if(!bUseClassifier) {
592       Standard_Integer n, cur, TabOrien_n ;
593       for(n=1; n<=nbtabclass; n++) { 
594         cur = ((CSLib_Class2d *)TabClass(n))->SiDans(Puv);
595         TabOrien_n=TabOrien(n);
596         
597         if(cur==1) { 
598           if(TabOrien_n==0) { 
599             dedans = -1; 
600             break;
601           }
602         }
603         else if(cur==-1) { 
604           if(TabOrien_n==1) {  
605             dedans = -1; 
606             break;
607           }
608         }
609         else { 
610           dedans = 0;
611           break;
612         }
613       } // for(n=1; n<=nbtabclass; n++)
614       
615       if(dedans==0) { 
616         bUseClassifier = Standard_True;
617       } 
618       else {
619         Status = (dedans == 1) ? TopAbs_IN : TopAbs_OUT;
620       }
621     } // if(TabOrien(1)!=-1) {
622     //compute state of the point using face classifier
623     if (bUseClassifier) {
624       //compute tolerance to use in face classifier
625       Standard_Real aURes, aVRes, aFCTol;
626       Standard_Boolean bUIn, bVIn;
627       //
628       aURes = surf->UResolution(Toluv);
629       aVRes = surf->VResolution(Toluv);
630       //
631       bUIn = (u >= Umin) && (u <= Umax);
632       bVIn = (v >= Vmin) && (v <= Vmax);
633       //
634       if (bUIn==bVIn) {
635         aFCTol = Min(aURes, aVRes);
636       }
637       else {
638         aFCTol = (!bUIn) ? aURes : aVRes;
639       }
640       //
641       BRepClass_FaceClassifier aClassifier;
642       aClassifier.Perform(Face,Puv,aFCTol);
643       Status = aClassifier.State();
644     }
645     
646     if (!RecadreOnPeriodic || (!IsUPer && !IsVPer))
647       return Status;
648     
649     if (Status == TopAbs_IN || Status == TopAbs_ON)
650       return Status;
651     
652     if (!urecadre){
653       u = uu;
654       urecadre = Standard_True;
655     }
656     else {
657       if (IsUPer){
658         u += uperiod;
659       }
660     }
661
662     if (u > Umax || !IsUPer) {
663       if (!vrecadre){
664         v = vv;
665         vrecadre = Standard_True;
666       }
667       else {
668         if (IsVPer){
669           v += vperiod;
670         }
671       }
672
673       u = uu;
674       
675       if (v > Vmax || !IsVPer) {
676         return Status;
677       }
678     }
679   } //while (1)
680 }
681
682 //=======================================================================
683 //function : TestOnRestriction
684 //purpose  : 
685 //=======================================================================
686 TopAbs_State IntTools_FClass2d::TestOnRestriction
687   (const gp_Pnt2d& _Puv,
688    const Standard_Real Tol,
689    const Standard_Boolean RecadreOnPeriodic) const
690
691   Standard_Integer nbtabclass = TabClass.Length();
692   if (nbtabclass == 0)
693   {
694     return TopAbs_IN;
695   }
696
697   //-- U1 is the First Param and U2 in this case is U1+Period
698   Standard_Real u=_Puv.X();
699   Standard_Real v=_Puv.Y();
700   Standard_Real uu = u, vv = v;
701
702   Handle(BRepAdaptor_HSurface) surf = new BRepAdaptor_HSurface();
703   surf->ChangeSurface().Initialize( Face, Standard_False );
704   const Standard_Boolean IsUPer  = surf->IsUPeriodic();
705   const Standard_Boolean IsVPer  = surf->IsVPeriodic();
706   const Standard_Real    uperiod = IsUPer ? surf->UPeriod() : 0.0;
707   const Standard_Real    vperiod = IsVPer ? surf->VPeriod() : 0.0;
708   TopAbs_State Status = TopAbs_UNKNOWN;
709   Standard_Boolean urecadre = Standard_False, vrecadre = Standard_False;
710   Standard_Integer dedans = 1;
711
712   if (RecadreOnPeriodic) {
713     Standard_Real du, dv;
714     if (IsUPer) {
715       GeomInt::AdjustPeriodic(uu, Umin, Umax, uperiod, uu, du);
716     }// if (IsUPer) {
717     //
718     if (IsVPer) {
719       GeomInt::AdjustPeriodic(vv, Vmin, Vmax, vperiod, vv, dv);
720     }//if (IsVPer) {
721   }
722   //
723   for (;;) {
724     dedans = 1;
725     gp_Pnt2d Puv(u,v);
726     
727     if(TabOrien(1)!=-1) { 
728       for(Standard_Integer n=1; n<=nbtabclass; n++) { 
729         Standard_Integer cur = ((CSLib_Class2d *)TabClass(n))->SiDans_OnMode(Puv,Tol);
730         if(cur==1) { 
731           if(TabOrien(n)==0) { 
732             dedans = -1; 
733             break;
734           }
735         }
736         else if(cur==-1) { 
737           if(TabOrien(n)==1) {  
738             dedans = -1; 
739             break;
740           }
741         }
742         else { 
743           dedans = 0;
744           break;
745         }
746       }
747       if(dedans==0) {
748         Status = TopAbs_ON;
749       }
750       if(dedans == 1) {
751         Status = TopAbs_IN;
752       }
753       if(dedans == -1) {
754         Status = TopAbs_OUT;
755       }
756     }
757     else {  //-- TabOrien(1)=-1  Wrong  Wire 
758       BRepClass_FaceClassifier aClassifier;
759       aClassifier.Perform(Face,Puv,Tol);
760       Status = aClassifier.State();
761     }
762     
763     if (!RecadreOnPeriodic || (!IsUPer && !IsVPer))
764       return Status;
765     if (Status == TopAbs_IN || Status == TopAbs_ON)
766       return Status;
767     
768     if (!urecadre)
769       {
770         u = uu;
771         urecadre = Standard_True;
772       }
773     else
774       if (IsUPer)
775         u += uperiod;
776     if (u > Umax || !IsUPer)
777       {
778         if (!vrecadre)
779           {
780             v = vv;
781             vrecadre = Standard_True;
782           }
783         else
784           if (IsVPer)
785             v += vperiod;
786         
787         u = uu;
788         
789         if (v > Vmax || !IsVPer)
790           return Status;
791       }
792   } //for (;;)
793 }
794 //=======================================================================
795 //function : Destroy
796 //purpose  : 
797 //=======================================================================
798 void IntTools_FClass2d::Destroy() 
799
800   Standard_Integer nbtabclass = TabClass.Length(); 
801   for(Standard_Integer d=1; d<=nbtabclass;d++) {
802     if(TabClass(d)) { 
803       delete ((CSLib_Class2d *)TabClass(d));
804       TabClass(d)=NULL;
805     }
806   }
807 }
808
809