0024596: Slow import of IGES data
[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-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 <BRepCheck_Face.ixx>
18
19 #include <BRepCheck_ListOfStatus.hxx>
20 #include <BRepCheck_ListIteratorOfListOfStatus.hxx>
21
22 #include <BRep_TFace.hxx>
23 #include <BRep_Builder.hxx>
24 #include <BRep_Tool.hxx>
25
26 #include <TopExp.hxx>
27 #include <TopExp_Explorer.hxx>
28
29 #include <TopTools_ListOfShape.hxx>
30 #include <TopTools_ListIteratorOfListOfShape.hxx>
31 #include <TopTools_DataMapOfShapeListOfShape.hxx>
32 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
33
34 //#include <BRepAdaptor_Curve2d.hxx>
35 #include <BRepClass_FaceClassifier.hxx>
36 //#include <Geom2dInt_GInter.hxx>
37 #include <Geom2d_Curve.hxx>
38 #include <Geom_Curve.hxx>
39 #include <GProp_GProps.hxx>
40
41 #include <IntRes2d_Domain.hxx>
42 #include <Geom2dInt_GInter.hxx>
43 #include <Geom2dAdaptor_Curve.hxx>
44 #include <gp_Pnt2d.hxx>
45
46
47
48 #include <BRepCheck.hxx>
49 #include <Precision.hxx>
50 #include <TopoDS.hxx>
51 #include <TopoDS_Wire.hxx>
52
53 #include <BRepTopAdaptor_FClass2d.hxx>
54 #include <TopAbs_State.hxx>
55
56 #include <Bnd_Box2d.hxx>
57 #include <BndLib_Add2dCurve.hxx>
58 #include <TopTools_MapOfShape.hxx>
59 #include <TopTools_SequenceOfShape.hxx>
60 #include <TColgp_SequenceOfPnt.hxx>
61 #include <TopoDS_Vertex.hxx>
62 #include <IntRes2d_IntersectionPoint.hxx>
63 #include <IntRes2d_IntersectionSegment.hxx>
64 #include <BRepAdaptor_HSurface.hxx>
65
66 #include <TopTools_OrientedShapeMapHasher.hxx>
67 #include <NCollection_DataMap.hxx>
68
69 typedef NCollection_DataMap<TopoDS_Shape, Bnd_Box2d, TopTools_OrientedShapeMapHasher> DataMapOfShapeBox2d;
70
71 static Standard_Boolean Intersect(const TopoDS_Wire&,
72                                   const TopoDS_Wire&,
73                                   const TopoDS_Face&,
74                                   const DataMapOfShapeBox2d&);
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   Geom2dAdaptor_Curve aC;
211   Standard_Real aFirst, aLast;
212   DataMapOfShapeBox2d aMapShapeBox2d;
213   for (exp1.Init (myShape, TopAbs_WIRE); exp1.More(); exp1.Next()) 
214   {
215     const TopoDS_Wire& aWire = TopoDS::Wire (exp1.Current());
216     // create 2d boxes for all edges from wire
217     Bnd_Box2d aBoxW;
218     for (exp2.Init (aWire, TopAbs_EDGE); exp2.More(); exp2.Next())
219     {
220       const TopoDS_Edge& anEdge = TopoDS::Edge (exp2.Current());
221       aC.Load (BRep_Tool::CurveOnSurface (anEdge, TopoDS::Face (myShape), aFirst, aLast));
222       // To avoid exeption in Segment if C1 is BSpline
223       if (aC.FirstParameter() > aFirst)
224       {
225         aFirst = aC.FirstParameter();
226       }
227       if (aC.LastParameter() < aLast)
228       {
229         aLast = aC.LastParameter();
230       }
231       Bnd_Box2d aBoxE;
232       BndLib_Add2dCurve::Add (aC, aFirst, aLast, 0., aBoxE);
233       aMapShapeBox2d.Bind (anEdge, aBoxE);
234       aBoxW.Add (aBoxE);
235     }
236     aMapShapeBox2d.Bind (aWire, aBoxW);
237   }
238
239   Standard_Integer Nbwire, Index,Indexbis;
240   Nbwire = myMapImb.Extent();
241
242   Index = 1;
243   while (Index < Nbwire) {
244     for (exp1.Init(myShape,TopAbs_WIRE),Indexbis = 0;
245          exp1.More();exp1.Next()) {
246       Indexbis++;
247       if (Indexbis == Index) {
248         break;
249       }
250     }
251     TopoDS_Wire wir1 = TopoDS::Wire(exp1.Current());
252     // to reduce the number of calls Intersect(wir1,wir2)
253     Bnd_Box2d aBox1, aBox2;
254     if (aMapShapeBox2d.IsBound (wir1))
255     {
256       aBox1 = aMapShapeBox2d (wir1);
257     }
258     exp1.Next();
259     for (; exp1.More(); exp1.Next()) {
260       const TopoDS_Wire& wir2 = TopoDS::Wire(exp1.Current());
261       if (aMapShapeBox2d.IsBound (wir2))
262       {
263         aBox2 = aMapShapeBox2d (wir2);
264       }
265       if (!aBox1.IsVoid() && !aBox2.IsVoid() && aBox1.IsOut (aBox2))
266       {
267         continue;
268       }
269       if (Intersect(wir1,wir2,TopoDS::Face(myShape), aMapShapeBox2d)) {
270         myIntres = BRepCheck_IntersectingWires;
271         if (Update) {
272           BRepCheck::Add(myMap(myShape),myIntres);
273         }
274         return myIntres;
275       }
276     }
277     Index++;
278   }
279   if (Update) {
280     BRepCheck::Add(myMap(myShape),myIntres);
281   }
282   return myIntres;
283 }
284
285
286 //=======================================================================
287 //function : ClassifyWires
288 //purpose  : 
289 //=======================================================================
290
291 BRepCheck_Status BRepCheck_Face::ClassifyWires(const Standard_Boolean Update)
292 {
293   // It is assumed that each wire does not intersect any other one.
294   if (myImbdone) {
295     if (Update) {
296       BRepCheck::Add(myMap(myShape),myImbres);
297     }
298     return myImbres;
299   }
300
301   myImbdone = Standard_True;
302   myImbres = IntersectWires();
303   if (myImbres != BRepCheck_NoError) {
304     if (Update) {
305       BRepCheck::Add(myMap(myShape),myImbres);
306     }
307     return myImbres;
308   }
309
310   Standard_Integer Nbwire = myMapImb.Extent();
311   if (Nbwire < 1) {
312     if (Update) {
313       BRepCheck::Add(myMap(myShape),myImbres);
314     }
315     return myImbres;
316   }
317
318   BRep_Builder B;
319   TopExp_Explorer exp1,exp2;
320   TopTools_ListOfShape theListOfShape;
321   for (exp1.Init(myShape.Oriented(TopAbs_FORWARD),TopAbs_WIRE);
322        exp1.More();exp1.Next()) {
323
324     const TopoDS_Wire& wir1 = TopoDS::Wire(exp1.Current());
325     TopoDS_Shape aLocalShape = myShape.EmptyCopied();
326     TopoDS_Face newFace = TopoDS::Face(aLocalShape);
327 //    TopoDS_Face newFace = TopoDS::Face(myShape.EmptyCopied());
328
329     newFace.Orientation(TopAbs_FORWARD);
330     B.Add(newFace,wir1);
331
332     BRepTopAdaptor_FClass2d FClass2d(newFace,Precision::PConfusion());
333     Standard_Boolean WireBienOriente = Standard_False;
334     if(FClass2d.PerformInfinitePoint() != TopAbs_OUT) { 
335       WireBienOriente=Standard_True;
336       // the given wire defines a hole
337       myMapImb.UnBind(wir1);
338       myMapImb.Bind(wir1.Reversed(), theListOfShape);
339     }
340
341     for (exp2.Init(myShape.Oriented(TopAbs_FORWARD),TopAbs_WIRE);
342          exp2.More();exp2.Next()) {
343       const TopoDS_Wire& wir2 = TopoDS::Wire(exp2.Current());
344       if (!wir2.IsSame(wir1)) {
345         
346         if (IsInside(wir2,WireBienOriente,FClass2d,newFace)) { 
347           myMapImb(wir1).Append(wir2);
348         }
349       }
350     }
351   }
352   // It is required to have 1 wire that contains all others, and the others should not  
353   // contain anything (case solid ended) or
354   // the wires do not contain anything : in this case the wires should be
355   // holes in an infinite face.
356   TopoDS_Wire Wext;
357   for (TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itm(myMapImb);
358        itm.More();
359        itm.Next()) {
360     if (!itm.Value().IsEmpty()) {
361       if (Wext.IsNull()) {
362         Wext = TopoDS::Wire(itm.Key());
363       }
364       else {
365         myImbres = BRepCheck_InvalidImbricationOfWires;
366         if (Update) {
367           BRepCheck::Add(myMap(myShape),myImbres);
368         }
369         return myImbres;
370       }
371     }
372   }
373
374   if (!Wext.IsNull()) {
375     // verifies that the list contains nbwire-1 elements
376     if (myMapImb(Wext).Extent() != Nbwire-1) {
377       myImbres = BRepCheck_InvalidImbricationOfWires;
378       if (Update) {
379         BRepCheck::Add(myMap(myShape),myImbres);
380       }
381       return myImbres;
382     }
383   }
384   // quit without errors
385   if (Update) {
386     BRepCheck::Add(myMap(myShape),myImbres);
387   }
388   return myImbres;
389   
390 }
391
392
393 //=======================================================================
394 //function : OrientationOfWires
395 //purpose  : 
396 //=======================================================================
397
398 BRepCheck_Status BRepCheck_Face::OrientationOfWires
399    (const Standard_Boolean Update)
400 {
401   // WARNING : it is assumed that the edges of a wire are correctly oriented
402
403
404   Standard_Boolean Infinite = myShape.Infinite();
405
406   if (myOridone) {
407     if (Update) {
408       BRepCheck::Add(myMap(myShape),myOrires);
409     }
410     return myOrires;
411   }
412
413   myOridone = Standard_True;
414   myOrires = ClassifyWires();
415   if (myOrires != BRepCheck_NoError) {
416     if (Update) {
417       BRepCheck::Add(myMap(myShape),myOrires);
418     }
419     return myOrires;
420   }
421
422   Standard_Integer Nbwire = myMapImb.Extent();
423   TopoDS_Wire Wext;
424   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itm(myMapImb);
425   if (Nbwire == 1) {
426     if (!Infinite) {
427       Wext = TopoDS::Wire(itm.Key());
428     }
429   }
430   else {
431     for (;itm.More();itm.Next()) {
432       if (!itm.Value().IsEmpty()) {
433         Wext = TopoDS::Wire(itm.Key());
434       }
435     }
436   }
437
438   if (Wext.IsNull() && !Infinite) {
439     if (Nbwire>0) myOrires = BRepCheck_InvalidImbricationOfWires;
440     if (Update) {
441       BRepCheck::Add(myMap(myShape),myOrires);
442     }
443     return myOrires;
444   }
445
446   // BRep_Builder B;
447   TopExp_Explorer exp(myShape.Oriented(TopAbs_FORWARD),TopAbs_WIRE);
448   for (; exp.More(); exp.Next()) {
449     const TopoDS_Wire& wir = TopoDS::Wire(exp.Current());
450     if (!Wext.IsNull() && wir.IsSame(Wext)) {
451       if (wir.Orientation() != Wext.Orientation()) {
452         //the exterior wire defines a hole 
453         if( CheckThin(wir,myShape.Oriented(TopAbs_FORWARD)) )
454           return myOrires;
455         myOrires = BRepCheck_BadOrientationOfSubshape;
456         if (Update) {
457           BRepCheck::Add(myMap(myShape),myOrires);
458         }
459         return myOrires;
460       }
461     }
462     else {
463       for (itm.Reset(); itm.More(); itm.Next()) {
464         if (itm.Key().IsSame(wir)) {
465           break;
466         }
467       }
468       // No control on More()
469       if (itm.Key().Orientation() == wir.Orientation()) {
470         // the given wire does not define a hole
471         myOrires = BRepCheck_BadOrientationOfSubshape;
472         if (Update) {
473           BRepCheck::Add(myMap(myShape),myOrires);
474         }
475         return myOrires;
476       }
477     }
478   }
479   // quit withour error
480   if (Update) {
481     BRepCheck::Add(myMap(myShape),myOrires);
482   }
483   return myOrires;
484 }
485
486
487 //=======================================================================
488 //function : SetUnorientable
489 //purpose  : 
490 //=======================================================================
491
492 void BRepCheck_Face::SetUnorientable()
493 {
494   BRepCheck::Add(myMap(myShape),BRepCheck_UnorientableShape);
495 }
496
497
498 //=======================================================================
499 //function : IsUnorientable
500 //purpose  : 
501 //=======================================================================
502
503 Standard_Boolean BRepCheck_Face::IsUnorientable() const
504 {
505   if (myOridone) {
506     return (myOrires != BRepCheck_NoError);
507   }
508   for (BRepCheck_ListIteratorOfListOfStatus itl(myMap(myShape));
509        itl.More();
510        itl.Next()) {
511     if (itl.Value() == BRepCheck_UnorientableShape) {
512       return Standard_True;
513     }
514   }
515   return Standard_False;
516 }
517
518 //=======================================================================
519 //function : GeometricControls
520 //purpose  : 
521 //=======================================================================
522
523 void BRepCheck_Face::GeometricControls(const Standard_Boolean B)
524 {
525   if (myGctrl != B) {
526     if (B) {
527       myIntdone = Standard_False; 
528       myImbdone = Standard_False; 
529       myOridone = Standard_False; 
530     }
531     myGctrl = B;
532   }
533 }
534
535
536 //=======================================================================
537 //function : GeometricControls
538 //purpose  : 
539 //=======================================================================
540
541 Standard_Boolean BRepCheck_Face::GeometricControls() const
542 {
543   return myGctrl;
544 }
545
546
547 //=======================================================================
548 //function : Intersect
549 //purpose  : 
550 //=======================================================================
551
552 static Standard_Boolean Intersect(const TopoDS_Wire& wir1,
553                                   const TopoDS_Wire& wir2,
554                                   const TopoDS_Face& F,
555                                   const DataMapOfShapeBox2d& theMapEdgeBox)
556 {
557   Standard_Real Inter2dTol = 1.e-10;
558   TopExp_Explorer exp1,exp2;
559 //  BRepAdaptor_Curve2d cur1,cur2;
560
561   //Find common vertices of two wires - non-manifold case
562   TopTools_MapOfShape MapW1;
563   TopTools_SequenceOfShape CommonVertices;
564   for (exp1.Init( wir1, TopAbs_VERTEX ); exp1.More(); exp1.Next())
565     MapW1.Add( exp1.Current() );
566   for (exp2.Init( wir2, TopAbs_VERTEX ); exp2.More(); exp2.Next())
567     {
568       TopoDS_Shape V = exp2.Current();
569       if (MapW1.Contains( V ))
570         CommonVertices.Append( V );
571     }
572
573   // MSV 03.04.2002: create pure surface adaptor to avoid UVBounds computation
574   //                 due to performance problem
575   BRepAdaptor_Surface Surf(F,Standard_False);
576
577   TColgp_SequenceOfPnt PntSeq;
578   Standard_Integer i;
579   for (i = 1; i <= CommonVertices.Length(); i++)
580     {
581       TopoDS_Vertex V = TopoDS::Vertex( CommonVertices(i) );
582       gp_Pnt2d P2d = BRep_Tool::Parameters( V, F );
583       gp_Pnt P = Surf.Value( P2d.X(), P2d.Y() );
584       PntSeq.Append( P );
585     }
586
587   Geom2dAdaptor_Curve   C1,C2;
588   gp_Pnt2d              pfirst1,plast1,pfirst2,plast2;
589   Standard_Real         first1,last1,first2,last2;
590   Geom2dInt_GInter      Inter;
591   IntRes2d_Domain myDomain1,myDomain2;
592   Bnd_Box2d Box1, Box2;
593
594   for (exp1.Init(wir1,TopAbs_EDGE); exp1.More(); exp1.Next())
595     {
596       const TopoDS_Edge& edg1 = TopoDS::Edge(exp1.Current());
597       //    cur1.Initialize(edg1,F);
598       C1.Load( BRep_Tool::CurveOnSurface(edg1,F,first1,last1) );
599       // To avoid exeption in Segment if C1 is BSpline - IFV
600       if(C1.FirstParameter() > first1) first1 = C1.FirstParameter();
601       if(C1.LastParameter()  < last1 ) last1  = C1.LastParameter();
602
603       Box1.SetVoid();
604       if (theMapEdgeBox.IsBound (edg1))
605       {
606         Box1 = theMapEdgeBox (edg1);
607       }
608       if (Box1.IsVoid())
609       {
610         BndLib_Add2dCurve::Add( C1, first1, last1, 0., Box1 );
611       }
612       for (exp2.Init(wir2,TopAbs_EDGE); exp2.More(); exp2.Next())
613         {
614           const TopoDS_Edge& edg2 = TopoDS::Edge(exp2.Current());
615           if (!edg1.IsSame(edg2))
616             {
617               //cur2.Initialize(edg2,F);
618               C2.Load( BRep_Tool::CurveOnSurface(edg2,F,first2,last2) );
619               // To avoid exeption in Segment if C2 is BSpline - IFV
620               if(C2.FirstParameter() > first2) first2 = C2.FirstParameter();
621               if(C2.LastParameter()  < last2 ) last2  = C2.LastParameter();
622
623               Box2.SetVoid();
624               if (theMapEdgeBox.IsBound (edg2))
625               {
626           Box2 = theMapEdgeBox (edg2);
627               }
628               if (Box2.IsVoid())
629               {
630           BndLib_Add2dCurve::Add( C2, first2, last2, 0., Box2 );
631               }
632               if (! Box1.IsOut( Box2 ))
633                 {
634                   BRep_Tool::UVPoints(edg1,F,pfirst1,plast1);
635                   myDomain1.SetValues( pfirst1, first1, Inter2dTol, plast1, last1, Inter2dTol );
636                   BRep_Tool::UVPoints(edg2,F,pfirst2,plast2);
637                   myDomain2.SetValues( pfirst2, first2, Inter2dTol, plast2, last2, Inter2dTol );
638                   Inter.Perform( C1, myDomain1, C2, myDomain2, Inter2dTol, Inter2dTol );
639                   if (!Inter.IsDone())
640                     return Standard_True;
641                   if (Inter.NbSegments() > 0)
642                     {
643                       if (PntSeq.IsEmpty())
644                         return Standard_True;
645                       else
646                         {
647                           Standard_Integer NbCoinc = 0;
648                           for (i = 1; i <= Inter.NbSegments(); i++)
649                             {
650                               if (!Inter.Segment(i).HasFirstPoint() || !Inter.Segment(i).HasLastPoint())
651                                 return Standard_True;
652                               gp_Pnt2d FirstP2d = Inter.Segment(i).FirstPoint().Value();
653                               gp_Pnt2d LastP2d = Inter.Segment(i).LastPoint().Value();
654                               gp_Pnt FirstP = Surf.Value( FirstP2d.X(), FirstP2d.Y() );
655                               gp_Pnt LastP = Surf.Value( LastP2d.X(), LastP2d.Y() );
656                               for (Standard_Integer j = 1; j <= PntSeq.Length(); j++)
657                                 {
658                                   Standard_Real tolv = BRep_Tool::Tolerance( TopoDS::Vertex(CommonVertices(j)) );
659                                   if (FirstP.IsEqual( PntSeq(j), tolv ) || LastP.IsEqual( PntSeq(j), tolv ))
660                                     {
661                                       NbCoinc++;
662                                       break;
663                                     }
664                                 }
665                             }
666                           if (NbCoinc == Inter.NbSegments())
667                             return Standard_False;
668                           return Standard_True;
669                         }
670                     }
671                   if (Inter.NbPoints() > 0)
672                     {
673                       if (PntSeq.IsEmpty())
674                         return Standard_True;
675                       else
676                         {
677                           Standard_Integer NbCoinc = 0;
678                           for (i = 1; i <= Inter.NbPoints(); i++)
679                             {
680                               gp_Pnt2d P2d = Inter.Point(i).Value();
681                               gp_Pnt P = Surf.Value( P2d.X(), P2d.Y() );
682                               for (Standard_Integer j = 1; j <= PntSeq.Length(); j++)
683                                 {
684                                   Standard_Real tolv = BRep_Tool::Tolerance( TopoDS::Vertex(CommonVertices(j)) );
685                                   if (P.IsEqual( PntSeq(j), tolv ))
686                                     {
687                                       NbCoinc++;
688                                       break;
689                                     }
690                                 }
691                             }
692                           if (NbCoinc == Inter.NbPoints())
693                             return Standard_False;
694                           return Standard_True;
695                         }
696                     }
697                 }
698             }
699         }
700     }
701   return Standard_False;
702 }
703
704
705 //=======================================================================
706 //function : IsInside
707 //purpose  : 
708 //=======================================================================
709
710 static Standard_Boolean IsInside(const TopoDS_Wire& theWire,
711                                  const Standard_Boolean WireBienOriente,
712                                  const BRepTopAdaptor_FClass2d& FClass2d,
713                                  const TopoDS_Face& theFace)
714 {
715   Standard_Real aParameter, aFirst, aLast;
716
717   TopExp_Explorer anExplorer(theWire, TopAbs_EDGE);
718   for( ; anExplorer.More(); anExplorer.Next() )
719   {
720     const TopoDS_Edge& anEdge = TopoDS::Edge( anExplorer.Current() );
721     Handle(Geom2d_Curve) aCurve2D =
722       BRep_Tool::CurveOnSurface( anEdge, theFace, aFirst, aLast );
723
724     // Selects the parameter of point on the curve
725     if( !Precision::IsNegativeInfinite(aFirst) &&
726         !Precision::IsPositiveInfinite(aLast) )
727     {
728       aParameter = (aFirst + aLast) * 0.5;
729
730       // Edge is skipped if its parametric range is too small
731       if( Abs(aParameter - aFirst) < Precision::PConfusion() )
732       {
733         continue;
734       }
735
736           //Edge is skipped if its length is too small
737           Standard_Real aFirst3D, aLast3D;
738           Handle(Geom_Curve) aCurve = BRep_Tool::Curve( anEdge, aFirst3D, aLast3D );      
739       if ( aCurve.IsNull() )
740       {
741         continue;
742       }
743
744       gp_Pnt aPoints[2];
745       // Compute start point of edge
746       aCurve->D0( aFirst, aPoints[0] );
747       // Compute middle point of edge 
748       aCurve->D0( (aFirst3D+aLast3D)/2., aPoints[1] );
749       if( aPoints[0].Distance(aPoints[1]) < Precision::Confusion() )
750       {
751         continue;
752       }
753     }
754     else
755     {
756       if( Precision::IsNegativeInfinite(aFirst) &&
757           Precision::IsPositiveInfinite(aLast) )
758       {
759         aParameter = 0.;
760       }
761       else if( Precision::IsNegativeInfinite(aFirst) )
762       {
763         aParameter = aLast - 1.;
764       }
765       else
766       {
767         aParameter = aFirst + 1.;
768       }
769     }
770
771     // Find point on curve (edge)
772     gp_Pnt2d aPoint2D(aCurve2D->Value(aParameter));
773     // Compute the topological position of a point relative to face
774     TopAbs_State aState = FClass2d.Perform(aPoint2D, Standard_False);
775
776     if( WireBienOriente )
777     {
778       return aState == TopAbs_OUT;
779     }
780     else
781     {
782       return aState == TopAbs_IN;
783     }
784   }
785   return Standard_False;
786 }
787 Standard_Boolean CheckThin(const TopoDS_Shape& w, const TopoDS_Shape& f)
788 {
789   TopoDS_Face aF = TopoDS::Face(f);
790   TopoDS_Wire aW = TopoDS::Wire(w);
791
792   Standard_Integer nbE = 0;
793   TopTools_ListOfShape lE;
794   TopExp_Explorer exp(aW,TopAbs_EDGE);
795   for(; exp.More(); exp.Next()) {
796     const TopoDS_Shape& s = exp.Current();
797     lE.Append(s);
798     nbE++;
799   }
800
801   if( nbE != 2 ) return Standard_False;
802   TopoDS_Edge e1 = TopoDS::Edge(lE.First());
803   TopoDS_Edge e2 = TopoDS::Edge(lE.Last());
804
805   TopoDS_Vertex v1, v2, v3, v4;
806   TopExp::Vertices(e1,v1,v2);
807   TopExp::Vertices(e2,v3,v4);
808
809   if( v1.IsNull() || v2.IsNull() || 
810       v3.IsNull() || v4.IsNull() ) return Standard_False;
811
812   if( v1.IsSame(v2) || v3.IsSame(v4) )
813     return Standard_False;
814
815   Standard_Boolean sF = Standard_False, sL = Standard_False;
816   if( v1.IsSame(v3) || v1.IsSame(v4) ) sF = Standard_True;
817   if( v2.IsSame(v3) || v2.IsSame(v4) ) sL = Standard_True;
818
819   if( !sF || !sL ) return Standard_False;
820
821   TopAbs_Orientation e1or = e1.Orientation();
822   TopAbs_Orientation e2or = e2.Orientation();
823  
824   Standard_Real f1 = 0., l1 = 0., f2 = 0., l2 = 0.;
825   Handle(Geom2d_Curve) pc1 = BRep_Tool::CurveOnSurface(e1,aF,f1,l1);
826   Handle(Geom2d_Curve) pc2 = BRep_Tool::CurveOnSurface(e2,aF,f2,l2);
827   
828   if( pc1.IsNull() || pc2.IsNull() ) return Standard_False;
829
830   Standard_Real d1 = Abs(l1-f1)/100.;
831   Standard_Real d2 = Abs(l2-f2)/100.;
832   Standard_Real m1 = (l1+f1)*0.5;
833   Standard_Real m2 = (l2+f2)*0.5;
834
835   gp_Pnt2d p1f(pc1->Value(m1-d1));
836   gp_Pnt2d p1l(pc1->Value(m1+d1));
837   gp_Pnt2d p2f(pc2->Value(m2-d2));
838   gp_Pnt2d p2l(pc2->Value(m2+d2));
839
840   gp_Vec2d vc1(p1f,p1l);
841   gp_Vec2d vc2(p2f,p2l);
842   
843   if( (vc1*vc2) >= 0. && e1or == e2or ) return Standard_False;
844
845   return Standard_True;
846 }