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