0028211: Modeling Algorithms - Boolean fuse operation produces incorrect result
[occt.git] / src / BRepTopAdaptor / BRepTopAdaptor_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 #define AFFICHAGE 0
18
19 #define No_Standard_OutOfRange
20
21
22 #include <BRep_Tool.hxx>
23 #include <BRepAdaptor_Curve.hxx>
24 #include <BRepAdaptor_Curve2d.hxx>
25 #include <BRepAdaptor_HSurface.hxx>
26 #include <BRepClass_FaceClassifier.hxx>
27 #include <BRepTools_WireExplorer.hxx>
28 #include <BRepTopAdaptor_FClass2d.hxx>
29 #include <CSLib_Class2d.hxx>
30 #include <ElCLib.hxx>
31 #include <Geom2dInt_Geom2dCurveTool.hxx>
32 #include <GeomAbs_SurfaceType.hxx>
33 #include <GCPnts_QuasiUniformDeflection.hxx>
34 #include <gp_Pnt.hxx>
35 #include <gp_Pnt2d.hxx>
36 #include <Precision.hxx>
37 #include <TColgp_Array1OfPnt2d.hxx>
38 #include <TColgp_SequenceOfPnt2d.hxx>
39 #include <TopAbs_Orientation.hxx>
40 #include <TopExp.hxx>
41 #include <TopExp_Explorer.hxx>
42 #include <TopoDS.hxx>
43 #include <TopoDS_Edge.hxx>
44 #include <TopoDS_Face.hxx>
45
46 #ifdef _MSC_VER
47 #include <stdio.h>
48 #endif
49
50
51 #ifdef OCCT_DEBUG
52 #define LBRCOMPT 0
53 #else
54 #define LBRCOMPT 0
55 #endif
56
57
58 #if LBRCOMPT  
59 class StatistiquesFClass2d { 
60 public:
61   long unsigned NbConstrShape;
62   long unsigned NbPerformInfinitePoint;
63   long unsigned NbPerform;
64   long unsigned NbTestOnRestriction;
65   long unsigned NbDestroy;
66 public:
67   StatistiquesFClass2d() { 
68     NbConstrShape=NbPerform=NbPerformInfinitePoint=NbDestroy=0;
69   }
70   ~StatistiquesFClass2d() { 
71     printf("\n--- Statistiques BRepTopAdaptor:\n");
72     printf("\nConstructeur(Shape) : %10lu",NbConstrShape);
73     printf("\nPerformInfinitePoint: %10lu",NbPerformInfinitePoint);
74     printf("\nTestOnRestriction   : %10lu",NbTestOnRestriction);
75     printf("\nPerform(pnt2d)      : %10lu",NbPerform);
76     printf("\nDestroy             : %10lu",NbDestroy);
77   }
78 };
79
80 static StatistiquesFClass2d STAT;
81 #endif
82
83
84
85
86 BRepTopAdaptor_FClass2d::BRepTopAdaptor_FClass2d(const TopoDS_Face& aFace,const Standard_Real TolUV) 
87 : Toluv(TolUV), Face(aFace)  { 
88   
89 #if LBRCOMPT 
90   STAT.NbConstrShape++;
91 #endif
92
93   //-- dead end on surfaces defined on more than one period
94
95   Face.Orientation(TopAbs_FORWARD);
96   Handle(BRepAdaptor_HSurface) surf = new BRepAdaptor_HSurface();
97   surf->ChangeSurface().Initialize(aFace,Standard_False);
98   
99   TopoDS_Edge  edge;
100   TopAbs_Orientation Or;
101   Standard_Real u,du,Tole = 0.0,Tol=0.0;
102   BRepTools_WireExplorer WireExplorer;
103   TopExp_Explorer FaceExplorer;
104
105   Umin = Vmin = 0.0; //RealLast();
106   Umax = Vmax = -Umin;
107
108   Standard_Integer BadWire=0;
109   for( FaceExplorer.Init(Face,TopAbs_WIRE); (FaceExplorer.More() && BadWire==0); FaceExplorer.Next() )
110     {
111       Standard_Integer nbpnts = 0;
112       TColgp_SequenceOfPnt2d SeqPnt2d;
113       Standard_Integer firstpoint = 1;
114       Standard_Real FlecheU = 0.0;
115       Standard_Real FlecheV = 0.0;
116       Standard_Boolean WireIsNotEmpty = Standard_False;
117       Standard_Integer NbEdges = 0;
118
119       TopExp_Explorer Explorer;
120       for( Explorer.Init(FaceExplorer.Current(),TopAbs_EDGE); Explorer.More(); Explorer.Next() ) NbEdges++;
121         
122       gp_Pnt Ancienpnt3d(0,0,0);
123       Standard_Boolean Ancienpnt3dinitialise = Standard_False;
124
125       for( WireExplorer.Init(TopoDS::Wire(FaceExplorer.Current()),Face); WireExplorer.More(); WireExplorer.Next() )
126         {
127           
128           NbEdges--;
129           edge = WireExplorer.Current();
130           Or = edge.Orientation();
131           if(Or == TopAbs_FORWARD || Or == TopAbs_REVERSED)
132             {
133               Standard_Real pfbid,plbid;
134               if(BRep_Tool::CurveOnSurface(edge,Face,pfbid,plbid).IsNull()) return;
135               BRepAdaptor_Curve2d C(edge,Face);
136         
137               //-- ----------------------------------------
138               Standard_Boolean degenerated=Standard_False;
139               if(BRep_Tool::Degenerated(edge))   degenerated=Standard_True;
140               if(BRep_Tool::IsClosed(edge,Face)) degenerated=Standard_True;
141               TopoDS_Vertex Va,Vb;
142               TopExp::Vertices(edge,Va,Vb);
143               Standard_Real TolVertex1=0.,TolVertex=0.;
144               if (Va.IsNull()) degenerated=Standard_True;
145               else TolVertex1=BRep_Tool::Tolerance(Va);
146               if (Vb.IsNull()) degenerated=Standard_True;
147               else TolVertex=BRep_Tool::Tolerance(Vb);
148               if(TolVertex<TolVertex1) TolVertex=TolVertex1;
149               BRepAdaptor_Curve C3d;
150         
151               if(Abs(plbid-pfbid) < 1.e-9) continue;
152
153               //if(degenerated==Standard_False)
154               //  C3d.Initialize(edge,Face);
155
156               //-- Check cases when it was forgotten to code degenerated :  PRO17410 (janv 99)
157               if(degenerated == Standard_False)
158                 {
159                   C3d.Initialize(edge,Face);
160                   du=(plbid-pfbid)*0.1;
161                   u=pfbid+du;
162                   gp_Pnt P3da=C3d.Value(u);
163                   degenerated=Standard_True;
164                   u+=du;
165                   do
166                     {
167                       
168                       gp_Pnt P3db=C3d.Value(u);
169                       //                      if(P3da.SquareDistance(P3db)) { degenerated=Standard_False; break; }
170                       if(P3da.SquareDistance(P3db) > Precision::Confusion()) { degenerated=Standard_False; break; }
171                       u+=du;
172                     }
173                   while(u<plbid);
174                 }
175               
176               //-- ----------------------------------------
177
178               Tole = BRep_Tool::Tolerance(edge);
179               if(Tole>Tol) Tol=Tole;
180               
181               //Standard_Integer nbs = 1 + Geom2dInt_Geom2dCurveTool::NbSamples(C);
182               Standard_Integer nbs = Geom2dInt_Geom2dCurveTool::NbSamples(C);
183               //-- Attention to rational bsplines of degree 3. (ends of circles among others)
184               if (nbs > 2) nbs*=4;
185               du = (plbid-pfbid)/(Standard_Real)(nbs-1);
186
187               if(Or==TopAbs_FORWARD) u = pfbid;
188               else { u = plbid; du=-du; }
189         
190               //-- ------------------------------------------------------------
191               //-- Check distance uv between the start point of the edge
192               //-- and the last point registered in SeqPnt2d
193               //-- Try to remote the first point of the current edge 
194               //-- from the last saved point
195 #ifdef OCCT_DEBUG
196               gp_Pnt2d Pnt2dDebutEdgeCourant = C.Value(u); (void)Pnt2dDebutEdgeCourant;
197 #endif
198
199               //Standard_Real Baillement2dU=0;
200               //Standard_Real Baillement2dV=0;
201 #if AFFICHAGE
202               if(nbpnts>1) printf("\nTolVertex %g ",TolVertex);
203 #endif
204
205               if(firstpoint==2) u+=du;
206               Standard_Integer Avant = nbpnts;
207               for(Standard_Integer e = firstpoint; e<=nbs; e++)
208                 {
209                   gp_Pnt2d P2d = C.Value(u);
210                   if(P2d.X()<Umin) Umin = P2d.X();
211                   if(P2d.X()>Umax) Umax = P2d.X();
212                   if(P2d.Y()<Vmin) Vmin = P2d.Y();
213                   if(P2d.Y()>Vmax) Vmax = P2d.Y();
214           
215                   Standard_Real dist3dptcourant_ancienpnt=1e+20;//RealLast();
216                   gp_Pnt P3d;
217                   if(degenerated==Standard_False)
218                     {
219                       P3d=C3d.Value(u);
220                       if(nbpnts>1 && Ancienpnt3dinitialise) dist3dptcourant_ancienpnt = P3d.Distance(Ancienpnt3d);
221                     }
222                   Standard_Boolean IsRealCurve3d = Standard_True; //patch
223                   if(dist3dptcourant_ancienpnt < Precision::Confusion())
224                     {
225                       gp_Pnt MidP3d = C3d.Value( u-du/2. );
226                       if (P3d.Distance( MidP3d ) < Precision::Confusion()) IsRealCurve3d = Standard_False;
227                     }
228                   if(IsRealCurve3d)
229                     {
230                       if(degenerated==Standard_False) { Ancienpnt3d=P3d;  Ancienpnt3dinitialise=Standard_True; }
231                       nbpnts++;
232                       SeqPnt2d.Append(P2d);
233                     }
234 #if AFFICHAGE
235                   else { static int mm=0; printf("\npoint p%d  %g %g %g",++mm,P3d.X(),P3d.Y(),P3d.Z()); }
236 #endif
237                   u+=du;
238                   Standard_Integer ii = nbpnts;
239                   //-- printf("\n nbpnts:%4d  u=%7.5g   FlecheU=%7.5g  FlecheV=%7.5g  ii=%3d  Avant=%3d ",nbpnts,u,FlecheU,FlecheV,ii,Avant);
240 //                if(ii>(Avant+4))
241 //  Modified by Sergey KHROMOV - Fri Apr 19 09:46:12 2002 Begin
242                   if(ii>(Avant+4) && SeqPnt2d(ii-2).SquareDistance(SeqPnt2d(ii)))
243 //  Modified by Sergey KHROMOV - Fri Apr 19 09:46:13 2002 End
244                     {
245                       gp_Lin2d Lin(SeqPnt2d(ii-2),gp_Dir2d(gp_Vec2d(SeqPnt2d(ii-2),SeqPnt2d(ii))));
246                       Standard_Real ul = ElCLib::Parameter(Lin,SeqPnt2d(ii-1));
247                       gp_Pnt2d Pp = ElCLib::Value(ul,Lin);
248                       Standard_Real dU = Abs(Pp.X()-SeqPnt2d(ii-1).X());
249                       Standard_Real dV = Abs(Pp.Y()-SeqPnt2d(ii-1).Y());
250                       //-- printf(" (du=%7.5g   dv=%7.5g)",dU,dV);
251                       if(dU>FlecheU) FlecheU = dU;
252                       if(dV>FlecheV) FlecheV = dV;
253                     }
254                 }//for(e=firstpoint
255               if(firstpoint==1) firstpoint=2;
256               WireIsNotEmpty = Standard_True;
257             }//if(Or==FORWARD,REVERSED
258         } //-- Edges -> for(Ware.Explorer
259
260       if(NbEdges)
261         { //-- on compte ++ with a normal explorer and with the Wire Explorer
262 /*
263 #ifdef OCCT_DEBUG
264
265           cout << endl;
266           cout << "*** BRepTopAdaptor_Fclass2d  ** Wire Probablement FAUX **" << endl;
267           cout << "*** WireExplorer does not find all edges " << endl;
268           cout << "*** Connect old classifier" << endl;
269 #endif
270 */
271           TColgp_Array1OfPnt2d PClass(1,2);
272           //// modified by jgv, 28.04.2009 ////
273           PClass.Init(gp_Pnt2d(0.,0.));
274           /////////////////////////////////////
275           TabClass.Append((void *)new CSLib_Class2d(PClass,FlecheU,FlecheV,Umin,Vmin,Umax,Vmax));
276           BadWire=1;
277           TabOrien.Append(-1);
278         }
279       else if(WireIsNotEmpty)
280         {
281           //Standard_Real anglep=0,anglem=0;
282           TColgp_Array1OfPnt2d PClass(1,nbpnts);
283           Standard_Real square = 0.0;
284
285           //-------------------------------------------------------------------
286           //-- ** The mode of calculation was somewhat changed 
287           //-- Before Oct 31 97 , the total angle of  
288           //-- rotation of the wire was evaluated on all angles except for the last 
289           //-- ** Now, exactly the angle of rotation is evaluated
290           //-- If a value remote from 2PI or -2PI is found, it means that there is 
291           //-- an uneven number of loops
292
293           if(nbpnts>3)
294             {
295 //            Standard_Integer im2=nbpnts-2;
296               Standard_Integer im1=nbpnts-1;
297               Standard_Integer im0=1;
298 //            PClass(im2)=SeqPnt2d.Value(im2);
299               PClass(im1)=SeqPnt2d.Value(im1);
300               PClass(nbpnts)=SeqPnt2d.Value(nbpnts);
301
302               Standard_Real aPer = 0.;
303 //            for(Standard_Integer ii=1; ii<nbpnts; ii++,im0++,im1++,im2++)
304               for(Standard_Integer ii=1; ii<nbpnts; ii++,im0++,im1++)
305                 { 
306 //                if(im2>=nbpnts) im2=1;
307                   if(im1>=nbpnts) im1=1;
308                   PClass(ii)=SeqPnt2d.Value(ii);
309 //                gp_Vec2d A(PClass(im2),PClass(im1));
310 //                gp_Vec2d B(PClass(im1),PClass(im0));
311 //                Standard_Real N = A.Magnitude() * B.Magnitude();
312
313                   square += (PClass(im0).X()-PClass(im1).X())*(PClass(im0).Y()+PClass(im1).Y())*.5; 
314                   aPer += (PClass(im0).XY() - PClass(im1).XY()).Modulus();
315
316 //                if(N>1e-16){ Standard_Real a=A.Angle(B); angle+=a; }
317                 }
318
319               Standard_Real anExpThick = Max(2. * Abs(square) / aPer, 1e-7);
320               Standard_Real aDefl = Max(FlecheU, FlecheV);
321               Standard_Real aDiscrDefl = Min(aDefl*0.1, anExpThick * 10.);
322               while (aDefl > anExpThick && aDiscrDefl > 1e-7)
323               {
324                 // Deflection of the polygon is too much for this ratio of area and perimeter,
325                 // and this might lead to self-intersections.
326                 // Discretize the wire more tightly to eliminate the error.
327                 firstpoint = 1;
328                 SeqPnt2d.Clear();
329                 FlecheU = 0.0;
330                 FlecheV = 0.0;
331                 for (WireExplorer.Init(TopoDS::Wire(FaceExplorer.Current()), Face);
332                   WireExplorer.More(); WireExplorer.Next())
333                 {
334                   edge = WireExplorer.Current();
335                   Or = edge.Orientation();
336                   if (Or == TopAbs_FORWARD || Or == TopAbs_REVERSED)
337                   {
338                     Standard_Real pfbid, plbid;
339                     BRep_Tool::Range(edge, Face, pfbid, plbid);
340                     if (Abs(plbid - pfbid) < 1.e-9) continue;
341                     BRepAdaptor_Curve2d C(edge, Face);
342                     GCPnts_QuasiUniformDeflection aDiscr(C, aDiscrDefl);
343                     if (!aDiscr.IsDone())
344                       break;
345                     Standard_Integer nbp = aDiscr.NbPoints();
346                     Standard_Integer iStep = 1, i = 1, iEnd = nbp + 1;
347                     if (Or == TopAbs_REVERSED)
348                     {
349                       iStep = -1;
350                       i = nbp;
351                       iEnd = 0;
352                     }
353                     if (firstpoint == 2)
354                       i += iStep;
355                     for (; i != iEnd; i += iStep)
356                     {
357                       gp_Pnt2d aP2d = C.Value(aDiscr.Parameter(i));
358                       SeqPnt2d.Append(aP2d);
359                     }
360                     if (nbp > 2)
361                     {
362                       Standard_Integer ii = SeqPnt2d.Length();
363                       gp_Lin2d Lin(SeqPnt2d(ii - 2), gp_Dir2d(gp_Vec2d(SeqPnt2d(ii - 2), SeqPnt2d(ii))));
364                       Standard_Real ul = ElCLib::Parameter(Lin, SeqPnt2d(ii - 1));
365                       gp_Pnt2d Pp = ElCLib::Value(ul, Lin);
366                       Standard_Real dU = Abs(Pp.X() - SeqPnt2d(ii - 1).X());
367                       Standard_Real dV = Abs(Pp.Y() - SeqPnt2d(ii - 1).Y());
368                       if (dU > FlecheU) FlecheU = dU;
369                       if (dV > FlecheV) FlecheV = dV;
370                     }
371                     firstpoint = 2;
372                   }
373                 }
374                 nbpnts = SeqPnt2d.Length();
375                 PClass.Resize(1, nbpnts, Standard_False);
376                 im1 = nbpnts - 1;
377                 im0 = 1;
378                 PClass(im1) = SeqPnt2d.Value(im1);
379                 PClass(nbpnts) = SeqPnt2d.Value(nbpnts);
380                 square = 0.;
381                 aPer = 0.;
382                 for (Standard_Integer ii = 1; ii<nbpnts; ii++, im0++, im1++)
383                 {
384                   if (im1 >= nbpnts) im1 = 1;
385                   PClass(ii) = SeqPnt2d.Value(ii);
386                   square += (PClass(im0).X() - PClass(im1).X())*(PClass(im0).Y() + PClass(im1).Y())*.5;
387                   aPer += (PClass(im0).XY() - PClass(im1).XY()).Modulus();
388                 }
389
390                 anExpThick = Max(2. * Abs(square) / aPer, 1e-7);
391                 aDefl = Max(FlecheU, FlecheV);
392                 aDiscrDefl = Min(aDiscrDefl * 0.1, anExpThick * 10.);
393               }
394       
395               //-- FlecheU*=10.0;
396               //-- FlecheV*=10.0;
397               if(FlecheU<Toluv) FlecheU = Toluv;
398               if(FlecheV<Toluv) FlecheV = Toluv;
399               //-- cout<<" U:"<<FlecheU<<" V:"<<FlecheV<<endl;
400               TabClass.Append((void *)new CSLib_Class2d(PClass,FlecheU,FlecheV,Umin,Vmin,Umax,Vmax));
401
402 //            if((angle<2 && angle>-2)||(angle>10)||(angle<-10))
403 //              {
404 //                BadWire=1;
405 //                TabOrien.Append(-1);
406 //#ifdef OCCT_DEBUG
407 //                cout << endl;
408 //                cout << "*** BRepTopAdaptor_Fclass2d  ** Wire Probably FALSE **" << endl;
409 //                cout << "*** Total rotation angle of the wire : " << angle << endl;
410 //                cout << "*** Connect the old classifier" << endl;
411 //#endif
412 //              } 
413 //            else TabOrien.Append(((angle>0.0)? 1 : 0));
414               TabOrien.Append(((square < 0.0)? 1 : 0));
415             }//if(nbpoints>3
416           else
417             { 
418 #ifdef OCCT_DEBUG
419               cout << endl;
420               cout << "*** BRepTopAdaptor_Fclass2d  ** Wire Probably FALSE **" << endl;
421               cout << "*** The sample wire contains less than 3 points" << endl;
422               cout << "*** Connect the old classifier" << endl;
423 #endif       
424               BadWire=1;
425               TabOrien.Append(-1);
426               TColgp_Array1OfPnt2d xPClass(1,2);
427               xPClass(1) = SeqPnt2d(1); 
428               xPClass(2) = SeqPnt2d(2);
429               TabClass.Append((void *)new CSLib_Class2d(xPClass,FlecheU,FlecheV,Umin,Vmin,Umax,Vmax));
430             }
431         }//else if(WareIsNotEmpty
432   }//for(FaceExplorer
433
434   Standard_Integer nbtabclass = TabClass.Length();
435
436   if(nbtabclass>0)
437     {
438       //-- If an error was detected on a wire: set all TabOrien to -1
439       if(BadWire) TabOrien(1)=-1;
440
441       if(   surf->GetType()==GeomAbs_Cone
442          || surf->GetType()==GeomAbs_Cylinder
443          || surf->GetType()==GeomAbs_Torus
444          || surf->GetType()==GeomAbs_Sphere
445          || surf->GetType()==GeomAbs_SurfaceOfRevolution)
446         
447         {
448           Standard_Real uuu=M_PI+M_PI-(Umax-Umin);
449           if(uuu<0) uuu=0;
450           U1 = 0.0;  // modified by NIZHNY-OFV  Thu May 31 14:24:10 2001 ---> //Umin-uuu*0.5;
451           U2 = 2*M_PI; // modified by NIZHNY-OFV  Thu May 31 14:24:35 2001 ---> //U1+M_PI+M_PI;
452         }
453       else { U1=U2=0.0; } 
454     
455       if(surf->GetType()==GeomAbs_Torus)
456         { 
457           Standard_Real uuu=M_PI+M_PI-(Vmax-Vmin);
458           if(uuu<0) uuu=0;
459           V1 = 0.0;  // modified by NIZHNY-OFV  Thu May 31 14:24:55 2001 ---> //Vmin-uuu*0.5;
460           V2 = 2*M_PI; // modified by NIZHNY-OFV  Thu May 31 14:24:59 2001 ---> //V1+M_PI+M_PI;
461         }
462       else { V1=V2=0.0; }   
463     }
464 }
465
466 TopAbs_State BRepTopAdaptor_FClass2d::PerformInfinitePoint() const { 
467 #if LBRCOMPT 
468   STAT.NbPerformInfinitePoint++;
469 #endif
470   
471   if(Umax==-RealLast() || Vmax==-RealLast() || Umin==RealLast() || Vmin==RealLast()) { 
472     return(TopAbs_IN);
473   }
474   gp_Pnt2d P(Umin-(Umax-Umin),Vmin-(Vmax-Vmin));
475   return(Perform(P,Standard_False));
476 }
477
478 TopAbs_State BRepTopAdaptor_FClass2d::Perform(const gp_Pnt2d& _Puv,
479                                               const Standard_Boolean RecadreOnPeriodic) const
480
481 #if LBRCOMPT 
482   STAT.NbPerform++;
483 #endif
484   
485   Standard_Integer dedans;
486   Standard_Integer nbtabclass = TabClass.Length();
487   
488   if(nbtabclass==0) { 
489     return(TopAbs_IN);
490   }
491   
492   //-- U1 is the First Param and U2 in this case is U1+Period
493   Standard_Real u=_Puv.X();
494   Standard_Real v=_Puv.Y();
495   Standard_Real uu = u, vv = v;
496
497   Handle(BRepAdaptor_HSurface) surf = new BRepAdaptor_HSurface();
498   surf->ChangeSurface().Initialize( Face, Standard_False );
499   const Standard_Boolean IsUPer  = surf->IsUPeriodic();
500   const Standard_Boolean IsVPer  = surf->IsVPeriodic();
501   const Standard_Real    uperiod = IsUPer ? surf->UPeriod() : 0.0;
502   const Standard_Real    vperiod = IsVPer ? surf->VPeriod() : 0.0;
503   TopAbs_State aStatus = TopAbs_UNKNOWN;
504   Standard_Boolean urecadre = Standard_False, vrecadre = Standard_False;
505
506   if (RecadreOnPeriodic)
507     {
508       if (IsUPer)
509         {
510           if (uu < Umin)
511             while (uu < Umin)
512               uu += uperiod;
513           else
514             {
515               while (uu >= Umin)
516                 uu -= uperiod;
517               uu += uperiod;
518             }
519         }
520       if (IsVPer)
521         {
522           if (vv < Vmin)
523             while (vv < Vmin)
524               vv += vperiod;
525           else
526             {
527               while (vv >= Vmin)
528                 vv -= vperiod;
529               vv += vperiod;
530             }
531         }
532     }
533
534   for (;;)
535     {
536       dedans = 1;
537       gp_Pnt2d Puv(u,v);
538       
539       if(TabOrien(1)!=-1) { 
540         for(Standard_Integer n=1; n<=nbtabclass; n++) { 
541           Standard_Integer cur = ((CSLib_Class2d *)TabClass(n))->SiDans(Puv);
542           if(cur==1) { 
543             if(TabOrien(n)==0) { 
544               dedans = -1; 
545               break;
546             }
547           }
548           else if(cur==-1) { 
549             if(TabOrien(n)==1) {  
550               dedans = -1; 
551               break;
552             }
553           }
554           else { 
555             dedans = 0;
556             break;
557           }
558         }
559         if(dedans==0) { 
560           BRepClass_FaceClassifier aClassifier;
561           Standard_Real m_Toluv = (Toluv > 4.0) ? 4.0 : Toluv;
562           //aClassifier.Perform(Face,Puv,Toluv);
563           aClassifier.Perform(Face,Puv,m_Toluv);
564           aStatus = aClassifier.State();
565         }
566         if(dedans == 1) { 
567           aStatus = TopAbs_IN;
568         }
569         if(dedans == -1) {
570           aStatus = TopAbs_OUT;
571         }
572       }
573       else {  //-- TabOrien(1)=-1    False Wire
574         BRepClass_FaceClassifier aClassifier;
575         aClassifier.Perform(Face,Puv,Toluv);
576         aStatus = aClassifier.State();
577       }
578
579       if (!RecadreOnPeriodic || (!IsUPer && !IsVPer))
580         return aStatus;
581       if (aStatus == TopAbs_IN || aStatus == TopAbs_ON)
582         return aStatus;
583
584       if (!urecadre)
585         {
586           u = uu;
587           urecadre = Standard_True;
588         }
589       else
590         if (IsUPer)
591           u += uperiod;
592       if (u > Umax || !IsUPer)
593         {
594           if (!vrecadre)
595             {
596               v = vv;
597               vrecadre = Standard_True;
598             }
599           else
600             if (IsVPer)
601               v += vperiod;
602
603           u = uu;
604
605           if (v > Vmax || !IsVPer)
606             return aStatus;
607         }
608     } //for (;;)
609 }
610
611 TopAbs_State BRepTopAdaptor_FClass2d::TestOnRestriction(const gp_Pnt2d& _Puv,
612                                                         const Standard_Real Tol,
613                                                         const Standard_Boolean RecadreOnPeriodic) const
614
615 #if LBRCOMPT 
616   STAT.NbConstrShape++;
617 #endif
618   
619   Standard_Integer dedans;
620   Standard_Integer nbtabclass = TabClass.Length();
621   
622   if(nbtabclass==0) { 
623     return(TopAbs_IN);
624   }
625   
626   //-- U1 is the First Param and U2 in this case is U1+Period
627   Standard_Real u=_Puv.X();
628   Standard_Real v=_Puv.Y();
629   Standard_Real uu = u, vv = v;
630   
631   Handle(BRepAdaptor_HSurface) surf = new BRepAdaptor_HSurface();
632   surf->ChangeSurface().Initialize( Face, Standard_False );
633   const Standard_Boolean IsUPer  = surf->IsUPeriodic();
634   const Standard_Boolean IsVPer  = surf->IsVPeriodic();
635   const Standard_Real    uperiod = IsUPer ? surf->UPeriod() : 0.0;
636   const Standard_Real    vperiod = IsVPer ? surf->VPeriod() : 0.0;
637   TopAbs_State aStatus = TopAbs_UNKNOWN;
638   Standard_Boolean urecadre = Standard_False, vrecadre = Standard_False;
639   
640   if (RecadreOnPeriodic)
641     {
642       if (IsUPer)
643         {
644           if (uu < Umin)
645             while (uu < Umin)
646               uu += uperiod;
647           else
648             {
649               while (uu >= Umin)
650                 uu -= uperiod;
651               uu += uperiod;
652             }
653         }
654       if (IsVPer)
655         {
656           if (vv < Vmin)
657             while (vv < Vmin)
658               vv += vperiod;
659           else
660             {
661               while (vv >= Vmin)
662                 vv -= vperiod;
663               vv += vperiod;
664             }
665         }
666     }
667   
668   for (;;)
669     {
670       dedans = 1;
671       gp_Pnt2d Puv(u,v);
672       
673       if(TabOrien(1)!=-1) { 
674         for(Standard_Integer n=1; n<=nbtabclass; n++) { 
675           Standard_Integer cur = ((CSLib_Class2d *)TabClass(n))->SiDans_OnMode(Puv,Tol);
676           if(cur==1) { 
677             if(TabOrien(n)==0) { 
678               dedans = -1; 
679               break;
680             }
681           }
682           else if(cur==-1) { 
683             if(TabOrien(n)==1) {  
684               dedans = -1; 
685               break;
686             }
687           }
688           else { 
689             dedans = 0;
690             break;
691           }
692         }
693         if(dedans==0) {
694           aStatus = TopAbs_ON;
695         }
696         if(dedans == 1) {
697           aStatus = TopAbs_IN;
698         }
699         if(dedans == -1) {
700           aStatus = TopAbs_OUT;
701         }
702       }
703       else {  //-- TabOrien(1)=-1    False Wire
704         BRepClass_FaceClassifier aClassifier;
705         aClassifier.Perform(Face,Puv,Tol);
706         aStatus = aClassifier.State();
707       }
708       
709       if (!RecadreOnPeriodic || (!IsUPer && !IsVPer))
710         return aStatus;
711       if (aStatus == TopAbs_IN || aStatus == TopAbs_ON)
712         return aStatus;
713       
714       if (!urecadre)
715         {
716           u = uu;
717           urecadre = Standard_True;
718         }
719       else
720         if (IsUPer)
721           u += uperiod;
722       if (u > Umax || !IsUPer)
723         {
724           if (!vrecadre)
725             {
726               v = vv;
727               vrecadre = Standard_True;
728             }
729           else
730             if (IsVPer)
731               v += vperiod;
732           
733           u = uu;
734           
735           if (v > Vmax || !IsVPer)
736             return aStatus;
737         }
738     } //for (;;)
739 }
740
741
742 void BRepTopAdaptor_FClass2d::Destroy() { 
743 #if LBRCOMPT
744   STAT.NbDestroy++;
745 #endif
746   
747   Standard_Integer nbtabclass = TabClass.Length(); 
748   for(Standard_Integer d=1; d<=nbtabclass;d++) {
749     if(TabClass(d)) { 
750       delete ((CSLib_Class2d *)TabClass(d));
751       TabClass(d)=NULL;
752     }
753   }
754 }
755
756
757
758 #include <Standard_ConstructionError.hxx>
759
760
761 //const BRepTopAdaptor_FClass2d &  BRepTopAdaptor_FClass2d::Copy(const BRepTopAdaptor_FClass2d& Other) const { 
762 const BRepTopAdaptor_FClass2d &  BRepTopAdaptor_FClass2d::Copy(const BRepTopAdaptor_FClass2d& ) const { 
763 #ifdef OCCT_DEBUG
764   cerr<<"Copy not allowed in BRepTopAdaptor_FClass2d"<<endl;
765 #endif
766   throw Standard_ConstructionError();
767 }