0023604: Uninitialized variables in debug mode
[occt.git] / src / BRepCheck / BRepCheck_Face.cxx
1 // Created on: 1995-12-15
2 // Created by: Jacques GOUSSARD
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
5 //
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
10 //
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 //
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
20
21
22
23 #include <BRepCheck_Face.ixx>
24
25 #include <BRepCheck_ListOfStatus.hxx>
26 #include <BRepCheck_ListIteratorOfListOfStatus.hxx>
27
28 #include <BRep_TFace.hxx>
29 #include <BRep_Builder.hxx>
30 #include <BRep_Tool.hxx>
31
32 #include <TopExp.hxx>
33 #include <TopExp_Explorer.hxx>
34
35 #include <TopTools_ListOfShape.hxx>
36 #include <TopTools_ListIteratorOfListOfShape.hxx>
37 #include <TopTools_DataMapOfShapeListOfShape.hxx>
38 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
39
40 //#include <BRepAdaptor_Curve2d.hxx>
41 #include <BRepClass_FaceClassifier.hxx>
42 //#include <Geom2dInt_GInter.hxx>
43 #include <Geom2d_Curve.hxx>
44 #include <GProp_GProps.hxx>
45
46 #include <IntRes2d_Domain.hxx>
47 #include <Geom2dInt_GInter.hxx>
48 #include <Geom2dAdaptor_Curve.hxx>
49 #include <gp_Pnt2d.hxx>
50
51
52
53 #include <BRepCheck.hxx>
54 #include <Precision.hxx>
55 #include <TopoDS.hxx>
56 #include <TopoDS_Wire.hxx>
57
58 #include <BRepTopAdaptor_FClass2d.hxx>
59 #include <TopAbs_State.hxx>
60
61 #include <Bnd_Box2d.hxx>
62 #include <BndLib_Add2dCurve.hxx>
63 #include <TopTools_MapOfShape.hxx>
64 #include <TopTools_SequenceOfShape.hxx>
65 #include <TColgp_SequenceOfPnt.hxx>
66 #include <TopoDS_Vertex.hxx>
67 #include <IntRes2d_IntersectionPoint.hxx>
68 #include <IntRes2d_IntersectionSegment.hxx>
69 #include <BRepAdaptor_HSurface.hxx>
70
71
72 static Standard_Boolean Intersect(const TopoDS_Wire&,
73                                   const TopoDS_Wire&,
74                                   const TopoDS_Face&);
75                                   
76
77 static Standard_Boolean IsInside(const TopoDS_Wire& wir,
78                                  const Standard_Boolean Inside,
79                                  const BRepTopAdaptor_FClass2d& FClass2d,
80                                  const TopoDS_Face& F);
81
82 static Standard_Boolean CheckThin(const TopoDS_Shape& w,
83                                   const TopoDS_Shape& f);
84
85 //=======================================================================
86 //function : BRepCheck_Face
87 //purpose  : 
88 //=======================================================================
89
90 BRepCheck_Face::BRepCheck_Face (const TopoDS_Face& F)
91 {
92   Init(F);
93   myIntdone = Standard_False;
94   myImbdone = Standard_False;
95   myOridone = Standard_False;
96   myGctrl   = Standard_True;
97 }
98
99 //=======================================================================
100 //function : Minimum
101 //purpose  : 
102 //=======================================================================
103
104 void BRepCheck_Face::Minimum()
105 {
106   if (!myMin) {
107     BRepCheck_ListOfStatus thelist;
108     myMap.Bind(myShape, thelist);
109     BRepCheck_ListOfStatus& lst = myMap(myShape);
110
111     Handle(BRep_TFace)& TF = *((Handle(BRep_TFace)*) &myShape.TShape());
112     if (TF->Surface().IsNull()) {
113       BRepCheck::Add(lst,BRepCheck_NoSurface);
114     }
115     else {
116       // Flag natural restriction???
117     }
118     if (lst.IsEmpty()) {
119       lst.Append(BRepCheck_NoError);
120     }
121     myMin = Standard_True;
122   }
123 }
124
125
126 //=======================================================================
127 //function : InContext
128 //purpose  : 
129 //=======================================================================
130
131 void BRepCheck_Face::InContext(const TopoDS_Shape& S)
132 {
133   if (myMap.IsBound(S)) {
134     return;
135   }
136   BRepCheck_ListOfStatus thelist;
137   myMap.Bind(S, thelist);
138
139   BRepCheck_ListOfStatus& lst = myMap(S);
140   
141   TopExp_Explorer exp(S,TopAbs_FACE);
142   for (; exp.More(); exp.Next()) {
143     if (exp.Current().IsSame(myShape)) {
144       break;
145     }
146   }
147   if (!exp.More()) {
148     BRepCheck::Add(lst,BRepCheck_SubshapeNotInShape);
149     return;
150   }
151
152   if (lst.IsEmpty()) {
153     lst.Append(BRepCheck_NoError);
154   }
155 }
156
157
158 //=======================================================================
159 //function : Blind
160 //purpose  : 
161 //=======================================================================
162
163 void BRepCheck_Face::Blind()
164 {
165   if (!myBlind) {
166     // nothing more than in the minimum
167     myBlind = Standard_True;
168   }
169 }
170
171
172 //=======================================================================
173 //function : IntersectWires
174 //purpose  : 
175 //=======================================================================
176
177 BRepCheck_Status BRepCheck_Face::IntersectWires(const Standard_Boolean Update)
178 {
179   if (myIntdone) {
180     if (Update) {
181       BRepCheck::Add(myMap(myShape),myIntres);
182     }
183     return myIntres;
184   }
185
186   myIntdone = Standard_True;
187   myIntres = BRepCheck_NoError;
188   // This method has to be called by an analyzer. It is assumed that
189   // each edge has a correct 2d representation on the face.
190
191   TopExp_Explorer exp1,exp2;
192
193   // the wires are mapped
194   exp1.Init(myShape.Oriented(TopAbs_FORWARD),TopAbs_WIRE);
195   TopTools_ListOfShape theListOfShape;
196   while (exp1.More()) {
197     if (!myMapImb.IsBound(exp1.Current())) {
198       myMapImb.Bind(exp1.Current(), theListOfShape);
199     }
200     else { // the same wire is met twice...
201       myIntres = BRepCheck_RedundantWire;
202       if (Update) {
203         BRepCheck::Add(myMap(myShape),myIntres);
204       }
205       return myIntres;
206     }
207     exp1.Next();
208   }
209   
210   Standard_Integer Nbwire, Index,Indexbis;
211   Nbwire = myMapImb.Extent();
212
213   Index = 1;
214   while (Index < Nbwire) {
215     for (exp1.Init(myShape,TopAbs_WIRE),Indexbis = 0;
216          exp1.More();exp1.Next()) {
217       Indexbis++;
218       if (Indexbis == Index) {
219         break;
220       }
221     }
222     TopoDS_Wire wir1 = TopoDS::Wire(exp1.Current());
223     exp1.Next();
224     for (; exp1.More(); exp1.Next()) {
225       const TopoDS_Wire& wir2 = TopoDS::Wire(exp1.Current());
226       if (Intersect(wir1,wir2,TopoDS::Face(myShape))) {
227         myIntres = BRepCheck_IntersectingWires;
228         if (Update) {
229           BRepCheck::Add(myMap(myShape),myIntres);
230         }
231         return myIntres;
232       }
233     }
234     Index++;
235   }
236   if (Update) {
237     BRepCheck::Add(myMap(myShape),myIntres);
238   }
239   return myIntres;
240 }
241
242
243 //=======================================================================
244 //function : ClassifyWires
245 //purpose  : 
246 //=======================================================================
247
248 BRepCheck_Status BRepCheck_Face::ClassifyWires(const Standard_Boolean Update)
249 {
250   // It is assumed that each wire does not intersect any other one.
251   if (myImbdone) {
252     if (Update) {
253       BRepCheck::Add(myMap(myShape),myImbres);
254     }
255     return myImbres;
256   }
257
258   myImbdone = Standard_True;
259   myImbres = IntersectWires();
260   if (myImbres != BRepCheck_NoError) {
261     if (Update) {
262       BRepCheck::Add(myMap(myShape),myImbres);
263     }
264     return myImbres;
265   }
266
267   Standard_Integer Nbwire = myMapImb.Extent();
268   if (Nbwire < 1) {
269     if (Update) {
270       BRepCheck::Add(myMap(myShape),myImbres);
271     }
272     return myImbres;
273   }
274
275   BRep_Builder B;
276   TopExp_Explorer exp1,exp2;
277   TopTools_ListOfShape theListOfShape;
278   for (exp1.Init(myShape.Oriented(TopAbs_FORWARD),TopAbs_WIRE);
279        exp1.More();exp1.Next()) {
280
281     const TopoDS_Wire& wir1 = TopoDS::Wire(exp1.Current());
282     TopoDS_Shape aLocalShape = myShape.EmptyCopied();
283     TopoDS_Face newFace = TopoDS::Face(aLocalShape);
284 //    TopoDS_Face newFace = TopoDS::Face(myShape.EmptyCopied());
285
286     newFace.Orientation(TopAbs_FORWARD);
287     B.Add(newFace,wir1);
288
289     BRepTopAdaptor_FClass2d FClass2d(newFace,Precision::PConfusion());
290     Standard_Boolean WireBienOriente = Standard_False;
291     if(FClass2d.PerformInfinitePoint() != TopAbs_OUT) { 
292       WireBienOriente=Standard_True;
293       // the given wire defines a hole
294       myMapImb.UnBind(wir1);
295       myMapImb.Bind(wir1.Reversed(), theListOfShape);
296     }
297
298     for (exp2.Init(myShape.Oriented(TopAbs_FORWARD),TopAbs_WIRE);
299          exp2.More();exp2.Next()) {
300       const TopoDS_Wire& wir2 = TopoDS::Wire(exp2.Current());
301       if (!wir2.IsSame(wir1)) {
302         
303         if (IsInside(wir2,WireBienOriente,FClass2d,newFace)) { 
304           myMapImb(wir1).Append(wir2);
305         }
306       }
307     }
308   }
309   // It is required to have 1 wire that contains all others, and the others should not  
310   // contain anything (case solid ended) or
311   // the wires do not contain anything : in this case the wires should be
312   // holes in an infinite face.
313   TopoDS_Wire Wext;
314   for (TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itm(myMapImb);
315        itm.More();
316        itm.Next()) {
317     if (!itm.Value().IsEmpty()) {
318       if (Wext.IsNull()) {
319         Wext = TopoDS::Wire(itm.Key());
320       }
321       else {
322         myImbres = BRepCheck_InvalidImbricationOfWires;
323         if (Update) {
324           BRepCheck::Add(myMap(myShape),myImbres);
325         }
326         return myImbres;
327       }
328     }
329   }
330
331   if (!Wext.IsNull()) {
332     // verifies that the list contains nbwire-1 elements
333     if (myMapImb(Wext).Extent() != Nbwire-1) {
334       myImbres = BRepCheck_InvalidImbricationOfWires;
335       if (Update) {
336         BRepCheck::Add(myMap(myShape),myImbres);
337       }
338       return myImbres;
339     }
340   }
341   // quit without errors
342   if (Update) {
343     BRepCheck::Add(myMap(myShape),myImbres);
344   }
345   return myImbres;
346   
347 }
348
349
350 //=======================================================================
351 //function : OrientationOfWires
352 //purpose  : 
353 //=======================================================================
354
355 BRepCheck_Status BRepCheck_Face::OrientationOfWires
356    (const Standard_Boolean Update)
357 {
358   // WARNING : it is assumed that the edges of a wire are correctly oriented
359
360
361   Standard_Boolean Infinite = myShape.Infinite();
362
363   if (myOridone) {
364     if (Update) {
365       BRepCheck::Add(myMap(myShape),myOrires);
366     }
367     return myOrires;
368   }
369
370   myOridone = Standard_True;
371   myOrires = ClassifyWires();
372   if (myOrires != BRepCheck_NoError) {
373     if (Update) {
374       BRepCheck::Add(myMap(myShape),myOrires);
375     }
376     return myOrires;
377   }
378
379   Standard_Integer Nbwire = myMapImb.Extent();
380   TopoDS_Wire Wext;
381   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itm(myMapImb);
382   if (Nbwire == 1) {
383     if (!Infinite) {
384       Wext = TopoDS::Wire(itm.Key());
385     }
386   }
387   else {
388     for (;itm.More();itm.Next()) {
389       if (!itm.Value().IsEmpty()) {
390         Wext = TopoDS::Wire(itm.Key());
391       }
392     }
393   }
394
395   if (Wext.IsNull() && !Infinite) {
396     if (Nbwire>0) myOrires = BRepCheck_InvalidImbricationOfWires;
397     if (Update) {
398       BRepCheck::Add(myMap(myShape),myOrires);
399     }
400     return myOrires;
401   }
402
403   // BRep_Builder B;
404   TopExp_Explorer exp(myShape.Oriented(TopAbs_FORWARD),TopAbs_WIRE);
405   for (; exp.More(); exp.Next()) {
406     const TopoDS_Wire& wir = TopoDS::Wire(exp.Current());
407     if (!Wext.IsNull() && wir.IsSame(Wext)) {
408       if (wir.Orientation() != Wext.Orientation()) {
409         //the exterior wire defines a hole 
410         if( CheckThin(wir,myShape.Oriented(TopAbs_FORWARD)) )
411           return myOrires;
412         myOrires = BRepCheck_BadOrientationOfSubshape;
413         if (Update) {
414           BRepCheck::Add(myMap(myShape),myOrires);
415         }
416         return myOrires;
417       }
418     }
419     else {
420       for (itm.Reset(); itm.More(); itm.Next()) {
421         if (itm.Key().IsSame(wir)) {
422           break;
423         }
424       }
425       // No control on More()
426       if (itm.Key().Orientation() == wir.Orientation()) {
427         // the given wire does not define a hole
428         myOrires = BRepCheck_BadOrientationOfSubshape;
429         if (Update) {
430           BRepCheck::Add(myMap(myShape),myOrires);
431         }
432         return myOrires;
433       }
434     }
435   }
436   // quit withour error
437   if (Update) {
438     BRepCheck::Add(myMap(myShape),myOrires);
439   }
440   return myOrires;
441 }
442
443
444 //=======================================================================
445 //function : SetUnorientable
446 //purpose  : 
447 //=======================================================================
448
449 void BRepCheck_Face::SetUnorientable()
450 {
451   BRepCheck::Add(myMap(myShape),BRepCheck_UnorientableShape);
452 }
453
454
455 //=======================================================================
456 //function : IsUnorientable
457 //purpose  : 
458 //=======================================================================
459
460 Standard_Boolean BRepCheck_Face::IsUnorientable() const
461 {
462   if (myOridone) {
463     return (myOrires != BRepCheck_NoError);
464   }
465   for (BRepCheck_ListIteratorOfListOfStatus itl(myMap(myShape));
466        itl.More();
467        itl.Next()) {
468     if (itl.Value() == BRepCheck_UnorientableShape) {
469       return Standard_True;
470     }
471   }
472   return Standard_False;
473 }
474
475 //=======================================================================
476 //function : GeometricControls
477 //purpose  : 
478 //=======================================================================
479
480 void BRepCheck_Face::GeometricControls(const Standard_Boolean B)
481 {
482   if (myGctrl != B) {
483     if (B) {
484       myIntdone = Standard_False; 
485       myImbdone = Standard_False; 
486       myOridone = Standard_False; 
487     }
488     myGctrl = B;
489   }
490 }
491
492
493 //=======================================================================
494 //function : GeometricControls
495 //purpose  : 
496 //=======================================================================
497
498 Standard_Boolean BRepCheck_Face::GeometricControls() const
499 {
500   return myGctrl;
501 }
502
503
504 //=======================================================================
505 //function : Intersect
506 //purpose  : 
507 //=======================================================================
508
509 static Standard_Boolean Intersect(const TopoDS_Wire& wir1,
510                                   const TopoDS_Wire& wir2,
511                                   const TopoDS_Face& F)
512 {
513   Standard_Real Inter2dTol = 1.e-10;
514   TopExp_Explorer exp1,exp2;
515 //  BRepAdaptor_Curve2d cur1,cur2;
516
517   //Find common vertices of two wires - non-manifold case
518   TopTools_MapOfShape MapW1;
519   TopTools_SequenceOfShape CommonVertices;
520   for (exp1.Init( wir1, TopAbs_VERTEX ); exp1.More(); exp1.Next())
521     MapW1.Add( exp1.Current() );
522   for (exp2.Init( wir2, TopAbs_VERTEX ); exp2.More(); exp2.Next())
523     {
524       TopoDS_Shape V = exp2.Current();
525       if (MapW1.Contains( V ))
526         CommonVertices.Append( V );
527     }
528
529   // MSV 03.04.2002: create pure surface adaptor to avoid UVBounds computation
530   //                 due to performance problem
531   BRepAdaptor_Surface Surf(F,Standard_False);
532
533   TColgp_SequenceOfPnt PntSeq;
534   Standard_Integer i;
535   for (i = 1; i <= CommonVertices.Length(); i++)
536     {
537       TopoDS_Vertex V = TopoDS::Vertex( CommonVertices(i) );
538       gp_Pnt2d P2d = BRep_Tool::Parameters( V, F );
539       gp_Pnt P = Surf.Value( P2d.X(), P2d.Y() );
540       PntSeq.Append( P );
541     }
542
543   Geom2dAdaptor_Curve   C1,C2;
544   gp_Pnt2d              pfirst1,plast1,pfirst2,plast2;
545   Standard_Real         first1,last1,first2,last2;
546   Geom2dInt_GInter      Inter;
547   IntRes2d_Domain myDomain1,myDomain2;
548   Bnd_Box2d Box1, Box2;
549
550   for (exp1.Init(wir1,TopAbs_EDGE); exp1.More(); exp1.Next())
551     {
552       const TopoDS_Edge& edg1 = TopoDS::Edge(exp1.Current());
553       //    cur1.Initialize(edg1,F);
554       C1.Load( BRep_Tool::CurveOnSurface(edg1,F,first1,last1) );
555       // To avoid exeption in Segment if C1 is BSpline - IFV
556       if(C1.FirstParameter() > first1) first1 = C1.FirstParameter();
557       if(C1.LastParameter()  < last1 ) last1  = C1.LastParameter();
558
559       BRep_Tool::UVPoints(edg1,F,pfirst1,plast1);
560       myDomain1.SetValues( pfirst1, first1, Inter2dTol, plast1, last1, Inter2dTol );
561       Box1.SetVoid();
562       BndLib_Add2dCurve::Add( C1, first1, last1, 0., Box1 );
563       
564       for (exp2.Init(wir2,TopAbs_EDGE); exp2.More(); exp2.Next())
565         {
566           const TopoDS_Edge& edg2 = TopoDS::Edge(exp2.Current());
567           if (!edg1.IsSame(edg2))
568             {
569               //cur2.Initialize(edg2,F);
570               C2.Load( BRep_Tool::CurveOnSurface(edg2,F,first2,last2) );
571               // To avoid exeption in Segment if C2 is BSpline - IFV
572               if(C2.FirstParameter() > first2) first2 = C2.FirstParameter();
573               if(C2.LastParameter()  < last2 ) last2  = C2.LastParameter();
574
575               Box2.SetVoid();
576               BndLib_Add2dCurve::Add( C2, first2, last2, 0., Box2 );
577               if (! Box1.IsOut( Box2 ))
578                 {
579                   BRep_Tool::UVPoints(edg2,F,pfirst2,plast2);
580                   myDomain2.SetValues( pfirst2, first2, Inter2dTol, plast2, last2, Inter2dTol );
581                   Inter.Perform( C1, myDomain1, C2, myDomain2, Inter2dTol, Inter2dTol );
582                   if (!Inter.IsDone())
583                     return Standard_True;
584                   if (Inter.NbSegments() > 0)
585                     {
586                       if (PntSeq.IsEmpty())
587                         return Standard_True;
588                       else
589                         {
590                           Standard_Integer NbCoinc = 0;
591                           for (i = 1; i <= Inter.NbSegments(); i++)
592                             {
593                               if (!Inter.Segment(i).HasFirstPoint() || !Inter.Segment(i).HasLastPoint())
594                                 return Standard_True;
595                               gp_Pnt2d FirstP2d = Inter.Segment(i).FirstPoint().Value();
596                               gp_Pnt2d LastP2d = Inter.Segment(i).LastPoint().Value();
597                               gp_Pnt FirstP = Surf.Value( FirstP2d.X(), FirstP2d.Y() );
598                               gp_Pnt LastP = Surf.Value( LastP2d.X(), LastP2d.Y() );
599                               for (Standard_Integer j = 1; j <= PntSeq.Length(); j++)
600                                 {
601                                   Standard_Real tolv = BRep_Tool::Tolerance( TopoDS::Vertex(CommonVertices(j)) );
602                                   if (FirstP.IsEqual( PntSeq(j), tolv ) || LastP.IsEqual( PntSeq(j), tolv ))
603                                     {
604                                       NbCoinc++;
605                                       break;
606                                     }
607                                 }
608                             }
609                           if (NbCoinc == Inter.NbSegments())
610                             return Standard_False;
611                           return Standard_True;
612                         }
613                     }
614                   if (Inter.NbPoints() > 0)
615                     {
616                       if (PntSeq.IsEmpty())
617                         return Standard_True;
618                       else
619                         {
620                           Standard_Integer NbCoinc = 0;
621                           for (i = 1; i <= Inter.NbPoints(); i++)
622                             {
623                               gp_Pnt2d P2d = Inter.Point(i).Value();
624                               gp_Pnt P = Surf.Value( P2d.X(), P2d.Y() );
625                               for (Standard_Integer j = 1; j <= PntSeq.Length(); j++)
626                                 {
627                                   Standard_Real tolv = BRep_Tool::Tolerance( TopoDS::Vertex(CommonVertices(j)) );
628                                   if (P.IsEqual( PntSeq(j), tolv ))
629                                     {
630                                       NbCoinc++;
631                                       break;
632                                     }
633                                 }
634                             }
635                           if (NbCoinc == Inter.NbPoints())
636                             return Standard_False;
637                           return Standard_True;
638                         }
639                     }
640                 }
641             }
642         }
643     }
644   return Standard_False;
645 }
646
647
648 //=======================================================================
649 //function : IsInside
650 //purpose  : 
651 //=======================================================================
652
653 static Standard_Boolean IsInside(const TopoDS_Wire& wir,
654                                  const Standard_Boolean WireBienOriente,
655                                  const BRepTopAdaptor_FClass2d& FClass2d,
656                                  const TopoDS_Face& F)
657 {
658   // Standard_Real U,V;
659   TopExp_Explorer exp;
660   for (exp.Init(wir,TopAbs_EDGE);
661        exp.More();
662        exp.Next()) {
663
664     const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
665     Standard_Real f,l;
666     Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(edg,F,f,l);
667     Standard_Real prm;
668
669     if (!Precision::IsNegativeInfinite(f) && 
670         !Precision::IsPositiveInfinite(l)) {
671       prm = (f+l)/2.;
672     }
673     else {
674       if (Precision::IsNegativeInfinite(f) && 
675           Precision::IsPositiveInfinite(l)){
676         prm = 0.;
677       }
678       else if (Precision::IsNegativeInfinite(f)) {
679         prm = l-1.;
680       }
681       else {
682         prm = f+1.;
683       }
684     }
685
686     gp_Pnt2d pt2d(C2d->Value(prm));
687     
688     if(WireBienOriente) { 
689       return(FClass2d.Perform(pt2d,Standard_False) == TopAbs_OUT);     
690     }
691     else { 
692       return(FClass2d.Perform(pt2d,Standard_False) == TopAbs_IN);
693     }
694   }
695   return Standard_False;
696 }
697
698 Standard_Boolean CheckThin(const TopoDS_Shape& w, const TopoDS_Shape& f)
699 {
700   TopoDS_Face aF = TopoDS::Face(f);
701   TopoDS_Wire aW = TopoDS::Wire(w);
702
703   Standard_Integer nbE = 0;
704   TopTools_ListOfShape lE;
705   TopExp_Explorer exp(aW,TopAbs_EDGE);
706   for(; exp.More(); exp.Next()) {
707     const TopoDS_Shape& s = exp.Current();
708     lE.Append(s);
709     nbE++;
710   }
711
712   if( nbE != 2 ) return Standard_False;
713   TopoDS_Edge e1 = TopoDS::Edge(lE.First());
714   TopoDS_Edge e2 = TopoDS::Edge(lE.Last());
715
716   TopoDS_Vertex v1, v2, v3, v4;
717   TopExp::Vertices(e1,v1,v2);
718   TopExp::Vertices(e2,v3,v4);
719
720   if( v1.IsNull() || v2.IsNull() || 
721       v3.IsNull() || v4.IsNull() ) return Standard_False;
722
723   if( v1.IsSame(v2) || v3.IsSame(v4) )
724     return Standard_False;
725
726   Standard_Boolean sF = Standard_False, sL = Standard_False;
727   if( v1.IsSame(v3) || v1.IsSame(v4) ) sF = Standard_True;
728   if( v2.IsSame(v3) || v2.IsSame(v4) ) sL = Standard_True;
729
730   if( !sF || !sL ) return Standard_False;
731
732   TopAbs_Orientation e1or = e1.Orientation();
733   TopAbs_Orientation e2or = e2.Orientation();
734  
735   Standard_Real f1 = 0., l1 = 0., f2 = 0., l2 = 0.;
736   Handle(Geom2d_Curve) pc1 = BRep_Tool::CurveOnSurface(e1,aF,f1,l1);
737   Handle(Geom2d_Curve) pc2 = BRep_Tool::CurveOnSurface(e2,aF,f2,l2);
738   
739   if( pc1.IsNull() || pc2.IsNull() ) return Standard_False;
740
741   Standard_Real d1 = Abs(l1-f1)/100.;
742   Standard_Real d2 = Abs(l2-f2)/100.;
743   Standard_Real m1 = (l1+f1)*0.5;
744   Standard_Real m2 = (l2+f2)*0.5;
745
746   gp_Pnt2d p1f(pc1->Value(m1-d1));
747   gp_Pnt2d p1l(pc1->Value(m1+d1));
748   gp_Pnt2d p2f(pc2->Value(m2-d2));
749   gp_Pnt2d p2l(pc2->Value(m2+d2));
750
751   gp_Vec2d vc1(p1f,p1l);
752   gp_Vec2d vc2(p2f,p2l);
753   
754   if( (vc1*vc2) >= 0. && e1or == e2or ) return Standard_False;
755
756   return Standard_True;
757 }