0028499: Checkshape incorrectly reports BRepCheck_NotClosed when gap is covered by...
[occt.git] / src / BRepCheck / BRepCheck_Wire.cxx
1 // Created on: 1995-12-12
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 // Modified by dpf, Fri Dec 19 15:31:03 1997 
18 //  Processing of closing in 2d.
19 //  modified by eap Tue Dec 18 14:14:25 2001 (bug OCC23)
20 //   Check self-intersection in case of closed edge
21 //  modified by eap Fri Dec 21 17:36:55 2001 (bug OCC35)
22 //   Closed2d() added
23 //  Modified by skv - Wed Jul 23 12:22:20 2003 OCC1764 
24
25 #include <Bnd_Array1OfBox2d.hxx>
26 #include <BndLib_Add2dCurve.hxx>
27 #include <BRep_Tool.hxx>
28 #include <BRepAdaptor_Curve.hxx>
29 #include <BRepAdaptor_HSurface.hxx>
30 #include <BRepAdaptor_Surface.hxx>
31 #include <BRepCheck.hxx>
32 #include <BRepCheck_ListIteratorOfListOfStatus.hxx>
33 #include <BRepCheck_ListOfStatus.hxx>
34 #include <BRepCheck_Wire.hxx>
35 #include <BRepTools_WireExplorer.hxx>
36 #include <ElCLib.hxx>
37 #include <Geom2d_Curve.hxx>
38 #include <Geom2dAdaptor_Curve.hxx>
39 #include <Geom2dAdaptor_HCurve.hxx>
40 #include <Geom2dInt_GInter.hxx>
41 #include <Geom_Curve.hxx>
42 #include <gp_Lin.hxx>
43 #include <gp_Pnt.hxx>
44 #include <gp_Pnt2d.hxx>
45 #include <IntRes2d_Domain.hxx>
46 #include <IntRes2d_Intersection.hxx>
47 #include <IntRes2d_IntersectionPoint.hxx>
48 #include <IntRes2d_IntersectionSegment.hxx>
49 #include <IntRes2d_Transition.hxx>
50 #include <Precision.hxx>
51 #include <Standard_Type.hxx>
52 #include <TColGeom2d_Array1OfCurve.hxx>
53 #include <TopExp.hxx>
54 #include <TopExp_Explorer.hxx>
55 #include <TopLoc_Location.hxx>
56 #include <TopoDS.hxx>
57 #include <TopoDS_Edge.hxx>
58 #include <TopoDS_Face.hxx>
59 #include <TopoDS_Iterator.hxx>
60 #include <TopoDS_Shape.hxx>
61 #include <TopoDS_Vertex.hxx>
62 #include <TopoDS_Wire.hxx>
63 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
64 #include <TopTools_DataMapOfShapeListOfShape.hxx>
65 #include <TopTools_HArray1OfShape.hxx>
66 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
67 #include <TopTools_IndexedMapOfOrientedShape.hxx>
68 #include <TopTools_IndexedMapOfShape.hxx>
69 #include <TopTools_ListIteratorOfListOfShape.hxx>
70 #include <TopTools_ListOfShape.hxx>
71 #include <TopTools_MapIteratorOfMapOfOrientedShape.hxx>
72 #include <TopTools_MapIteratorOfMapOfShape.hxx>
73 #include <TopTools_MapOfOrientedShape.hxx>
74 #include <TopTools_MapOfShape.hxx>
75
76 #include <stdio.h>
77 IMPLEMENT_STANDARD_RTTIEXT(BRepCheck_Wire,BRepCheck_Result)
78
79 static void Propagate(const TopTools_IndexedDataMapOfShapeListOfShape&,
80                       const TopoDS_Shape&,   // edge
81                       TopTools_MapOfShape&); // mapofedge
82
83
84 static TopAbs_Orientation GetOrientation(const TopTools_MapOfShape&,
85                                          const TopoDS_Edge&);
86
87
88 static 
89   void ChoixUV(const TopoDS_Vertex&,
90                const TopoDS_Edge&,
91                const TopoDS_Face&,
92                TopTools_ListOfShape&);
93
94 //      20/03/02 akm vvv (OCC234)
95 // static 
96 //   Standard_Boolean CheckLoopOrientation( const TopoDS_Vertex&,
97 //                                      const TopoDS_Edge&,
98 //                                      const TopoDS_Edge&,
99 //                                      const TopoDS_Face&,
100 //                                      TopTools_ListOfShape&);
101 //      20/03/02 akm ^^^
102
103 inline Standard_Boolean IsOriented(const TopoDS_Shape& S)
104 {
105   return (S.Orientation() == TopAbs_FORWARD ||
106           S.Orientation() == TopAbs_REVERSED);
107 }
108
109 static
110   void CurveDirForParameter(const Geom2dAdaptor_Curve& aC2d,
111                             const Standard_Real aPrm,
112                             gp_Pnt2d& Pnt,
113                             gp_Vec2d& aVec2d);
114
115 //  Modified by Sergey KHROMOV - Thu Jun 20 11:21:51 2002 OCC325 Begin
116 static Standard_Boolean IsClosed2dForPeriodicFace
117                         (const TopoDS_Face   &theFace,
118                          const gp_Pnt2d      &theP1,
119                          const gp_Pnt2d      &theP2,
120                          const TopoDS_Vertex &theVertex);
121
122 static Standard_Boolean GetPnt2d(const TopoDS_Vertex    &theVertex,
123                                  const TopoDS_Edge      &theEdge,
124                                  const TopoDS_Face      &theFace,
125                                        gp_Pnt2d         &aPnt);
126 //  Modified by Sergey KHROMOV - Wed May 22 10:44:08 2002 End
127
128 //=======================================================================
129 //function : BRepCheck_Wire
130 //purpose  : 
131 //=======================================================================
132 BRepCheck_Wire::BRepCheck_Wire(const TopoDS_Wire& W)
133 {
134   Init(W);
135 }
136 //=======================================================================
137 //function : Minimum
138 //purpose  : 
139 //=======================================================================
140 void BRepCheck_Wire::Minimum()
141 {
142   myCdone = Standard_False;
143   myGctrl = Standard_True;
144   if (!myMin) {
145     BRepCheck_ListOfStatus thelist;
146     myMap.Bind(myShape, thelist);
147     BRepCheck_ListOfStatus& lst = myMap(myShape);
148
149     // check that the wire is "connex"
150     TopExp_Explorer exp(myShape,TopAbs_EDGE);
151     Standard_Integer nbedge = 0;
152     myMapVE.Clear();
153     // fill myMapVE
154     for (; exp.More(); exp.Next()) {
155       nbedge++;
156       TopExp_Explorer expv;
157       for (expv.Init(exp.Current(),TopAbs_VERTEX);
158            expv.More(); expv.Next()) {
159         const TopoDS_Shape& vtx = expv.Current();
160         Standard_Integer index = myMapVE.FindIndex(vtx);
161         if (index == 0) {
162           TopTools_ListOfShape theListOfShape;
163           index = myMapVE.Add(vtx, theListOfShape);
164         }
165         myMapVE(index).Append(exp.Current());
166       }
167     }
168     // wire must have at least one edge
169     if (nbedge == 0) {
170       BRepCheck::Add(lst,BRepCheck_EmptyWire);
171     }
172     // check if all edges are connected through vertices
173     else if (nbedge >= 2) {
174       TopTools_MapOfShape mapE;
175       exp.ReInit();
176       Propagate(myMapVE,exp.Current(),mapE);
177       for (exp.ReInit(); exp.More(); exp.Next()) {
178         if (!mapE.Contains(exp.Current())) {
179           BRepCheck::Add(lst,BRepCheck_NotConnected);
180           break;
181         }
182       }
183     }
184     if (lst.IsEmpty()) {
185       lst.Append(BRepCheck_NoError);
186     }
187     myMapVE.Clear();
188     myMin = Standard_True;
189   }
190 }
191 //=======================================================================
192 //function : InContext
193 //purpose  : 
194 //=======================================================================
195 void BRepCheck_Wire::InContext(const TopoDS_Shape& S)
196 {
197
198   if (myMap.IsBound(S)) {
199     return;
200   }
201   BRepCheck_ListOfStatus thelist;
202   myMap.Bind(S, thelist);
203
204   BRepCheck_ListOfStatus& lst = myMap(S);
205
206   // check if my wire is in <S>
207   TopExp_Explorer exp(S,TopAbs_WIRE); 
208   for ( ; exp.More(); exp.Next()) {
209     if (exp.Current().IsSame(myShape)) {
210       break;
211     }
212   }
213   if (!exp.More()) {
214     BRepCheck::Add(lst,BRepCheck_SubshapeNotInShape);
215     return;
216   }
217
218   BRepCheck_Status st = BRepCheck_NoError;
219   TopAbs_ShapeEnum styp = S.ShapeType();
220   switch (styp) {
221
222   case TopAbs_FACE:
223     {
224       TopoDS_Edge ed1,ed2; 
225       if (myGctrl) 
226         st = SelfIntersect(TopoDS::Face(S),ed1,ed2,Standard_True);
227       if (st != BRepCheck_NoError) break;
228       st = Closed();
229       if (st != BRepCheck_NoError) break;
230       st = Orientation(TopoDS::Face(S));
231       if (st != BRepCheck_NoError) break;
232       st = Closed2d(TopoDS::Face(S));
233     }
234     break;
235   default:
236     break;
237   }
238   
239   if (st != BRepCheck_NoError) 
240     BRepCheck::Add(lst,st);
241       
242   if (lst.IsEmpty()) 
243     lst.Append(BRepCheck_NoError);
244 }
245 //=======================================================================
246 //function : Blind
247 //purpose  : 
248 //=======================================================================
249 void BRepCheck_Wire::Blind()
250 {
251   if (!myBlind) {
252     // nothing more that the minimum
253     myBlind = Standard_True;
254   }
255 }
256 //=======================================================================
257 //function : Closed
258 //purpose  : 
259 //=======================================================================
260 BRepCheck_Status BRepCheck_Wire::Closed(const Standard_Boolean Update)
261 {
262
263   if (myCdone) {
264     if (Update) {
265       BRepCheck::Add(myMap(myShape),myCstat);
266     }
267     return myCstat;
268   }
269
270   myCdone = Standard_True;
271
272   BRepCheck_ListIteratorOfListOfStatus itl(myMap(myShape));
273   if (itl.Value() != BRepCheck_NoError) {
274     myCstat = itl.Value();
275     return myCstat; // already saved 
276   }
277
278   myCstat = BRepCheck_NoError;
279
280   TopExp_Explorer exp,expv;
281   TopTools_MapOfShape mapS;
282   TopTools_DataMapOfShapeListOfShape Cradoc;
283   myMapVE.Clear();
284   // Checks if the oriented edges of the wire give a "closed" wire,
285   // i-e if each oriented vertex on oriented edges is found 2 times...
286   // myNbori = 0;
287   for (exp.Init(myShape,TopAbs_EDGE);exp.More(); exp.Next()) {
288     if (IsOriented(exp.Current())) {
289       // myNbori++;
290       if (!Cradoc.IsBound(exp.Current())) {
291         TopTools_ListOfShape theListOfShape;
292         Cradoc.Bind(exp.Current(), theListOfShape);
293       }
294       Cradoc(exp.Current()).Append(exp.Current());
295
296       mapS.Add(exp.Current());
297       for (expv.Init(exp.Current(),TopAbs_VERTEX); expv.More(); expv.Next()) {
298         if (IsOriented(expv.Current())) {
299           Standard_Integer index = myMapVE.FindIndex(expv.Current());
300           if (index == 0) {
301             TopTools_ListOfShape theListOfShape1;
302             index = myMapVE.Add(expv.Current(), theListOfShape1);
303           }
304           myMapVE(index).Append(exp.Current());
305         }
306       }
307     }
308   }
309
310   Standard_Integer theNbori = mapS.Extent();
311   if (theNbori >= 2) {
312     mapS.Clear();
313     for (exp.ReInit(); exp.More(); exp.Next()) {
314       if (IsOriented(exp.Current())) {
315         break;
316       }
317     }
318     Propagate(myMapVE,exp.Current(),mapS);
319   }
320   if (theNbori != mapS.Extent()) {
321     myCstat = BRepCheck_NotConnected;
322     if (Update) {
323       BRepCheck::Add(myMap(myShape),myCstat);
324     }
325     return myCstat;
326   }
327
328   // Checks the number of occurence of an edge : maximum 2, and in this 
329   // case, one time FORWARD and one time REVERSED
330
331   Standard_Boolean yabug = Standard_False;
332   for (TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itdm(Cradoc);
333        itdm.More(); itdm.Next()) {
334     if (itdm.Value().Extent() >= 3) {
335       yabug = Standard_True;
336     }
337     else if (itdm.Value().Extent() == 2) {
338       if (itdm.Value().First().Orientation() == 
339           itdm.Value().Last().Orientation()) {
340         yabug = Standard_True;
341       }
342     }
343     if (yabug) {
344       myCstat = BRepCheck_RedundantEdge;
345       if (Update) {
346         BRepCheck::Add(myMap(myShape),myCstat);
347       }
348       return myCstat;
349     }
350   }
351
352   for (Standard_Integer i = 1; i<= myMapVE.Extent(); i++) {
353     if (myMapVE(i).Extent()%2 != 0) {
354       myCstat=BRepCheck_NotClosed;
355       if (Update) {
356         BRepCheck::Add(myMap(myShape),myCstat);
357       }
358       return myCstat;
359     }
360   }
361
362   if (Update) {
363     BRepCheck::Add(myMap(myShape),myCstat);
364   }
365   return myCstat;
366 }
367
368 //=======================================================================
369 //function : IsDistanceIn3DTolerance
370 //purpose  : Return Standard_True if distance between thePnt_f and
371 //           thePnt_l is not more, than aTol3d
372 //=======================================================================
373 Standard_Boolean IsDistanceIn3DTolerance (const gp_Pnt& thePnt_f,
374                                           const gp_Pnt& thePnt_l,
375                                           const Standard_Real aTol3d)
376   {
377   Standard_Real Dist            = thePnt_f.Distance(thePnt_l);
378   
379   if (Dist < aTol3d)
380     return Standard_True;
381
382 #ifdef OCCT_DEBUG
383   cout << endl;
384   cout << "--------Function IsDistanceIn3DTolerance(...)----------"                                                                                             << endl;
385   cout << "--- BRepCheck Wire: Closed3d -> Error"                                                                                                                                                                       << endl;
386   cout << "--- Dist (" << Dist << ") > Tol3d (" << aTol3d << ")"                                                                                                        << endl;
387   cout << "Pnt1(" << thePnt_f.X() << "; " << thePnt_f.Y() << "; " << thePnt_f.Z() << ")"        << endl;
388   cout << "Pnt2(" << thePnt_l.X() << "; " << thePnt_l.Y() << "; " << thePnt_l.Z() << ")"        << endl;
389   cout << "------------------------------------------------------"                                                                                              << endl;
390 #endif
391
392   return Standard_False;
393   }
394
395 //=======================================================================
396 //function : IsDistanceIn2DTolerance
397 //purpose  : 
398 //=======================================================================
399 static 
400 Standard_Boolean IsDistanceIn2DTolerance (const BRepAdaptor_Surface& aFaceSurface,
401                                           const gp_Pnt2d& thePnt,
402                                           const gp_Pnt2d& thePntRef,
403                                           const Standard_Real aTol3d,
404 #ifdef OCCT_DEBUG
405                                           const Standard_Boolean PrintWarnings = Standard_True)
406 #else
407                                           const Standard_Boolean = Standard_True)
408 #endif
409 {
410   Standard_Real dumax = 0.01 * (aFaceSurface.LastUParameter() - aFaceSurface.FirstUParameter());
411   Standard_Real dvmax = 0.01 * (aFaceSurface.LastVParameter() - aFaceSurface.FirstVParameter());
412   Standard_Real dumin = Abs(thePnt.X() - thePntRef.X());
413   Standard_Real dvmin = Abs(thePnt.Y() - thePntRef.Y());
414   
415   if((dumin < dumax) && (dvmin < dvmax))
416     return Standard_True;
417
418 #ifdef OCCT_DEBUG
419   if(PrintWarnings)
420     {
421     cout << endl;
422     cout << "--------Function IsDistanceIn2DTolerance(...)----------"                                                           << endl;
423     cout << "--- BRepCheck Wire: Not closed in 2D"                                                                                                                                << endl;
424     cout << "*****************************************************"                                                                     << endl;
425     cout << "*dumin = " << dumin << "; dumax = " << dumax                                                                                                               << endl;
426     cout << "* dvmin = " << dvmin << "; dvmax = " << dvmax                                                                                                      << endl;
427     cout << "* (dumin > dumax) or (dvmin > dvmax)."                                                                                                                                     << endl;
428     cout << "*****************************************************"                                                                     << endl;
429     cout << endl;
430     cout << "UFirst = "  << aFaceSurface.FirstUParameter();
431     cout << "; ULast = " << aFaceSurface.LastUParameter()                                                                                                               << endl;
432     cout << "VFirst = " << aFaceSurface.FirstVParameter();
433     cout << "; VLast = " << aFaceSurface.LastVParameter()                                                                                                               << endl;
434     }
435 #endif
436   dumax = aFaceSurface.UResolution(aTol3d);
437   dvmax = aFaceSurface.VResolution(aTol3d);
438   gp_Pnt aP;
439   gp_Vec aDU, aDV;
440   Standard_Real um = (thePnt.X() + thePntRef.X()) / 2.;
441   Standard_Real vm = (thePnt.Y() + thePntRef.Y()) / 2.;
442   aFaceSurface.D1(um, vm, aP, aDU, aDV);
443   Standard_Real aMDU = aDU.Magnitude();
444   if (aMDU > Precision::Confusion())
445   {
446     dumax = Max((aTol3d / aMDU), dumax);
447   }
448   Standard_Real aMDV = aDV.Magnitude();
449   if (aMDV > Precision::Confusion())
450   {
451     dvmax = Max((aTol3d / aMDV), dvmax);
452   }
453
454 #ifdef OCCT_DEBUG
455   if(PrintWarnings)
456     {
457     cout << "aTol3d = " << aTol3d <<"; URes = " << dumax << "; VRes = " << dvmax                << endl;
458     cout << "thePnt(" << thePnt.X() << "; " << thePnt.Y() << ")"                                                                                << endl;
459     cout << "thePntRef(" << thePntRef.X() << "; " << thePntRef.Y() << ")"                                               << endl;
460     }
461 #endif
462
463   Standard_Real aTol2d = 2*Max( dumax, dvmax);
464   
465 #ifdef OCCT_DEBUG
466   if((aTol2d <= 0.0) && (PrintWarnings))
467     {
468     cout<<"BRepCheck_Wire : UResolution and VResolution = 0.0 (Face too small ?)"<<endl;
469     cout.flush();
470     }
471 #endif
472
473   Standard_Real Dist = Max(dumin, dvmin);
474   
475   if (Dist < aTol2d)
476     return Standard_True;
477
478 #ifdef OCCT_DEBUG
479   if(PrintWarnings)
480     {
481     cout << endl;
482     cout << "--------Function IsDistanceIn2DTolerance(...)----------"                                                   << endl;
483     cout << "--- BRepCheck Wire: Not closed in 2d"                                                                                                                      << endl;
484     cout << "*****************************************************"                                                             << endl;
485     cout << "* Dist = " << Dist << " > Tol2d = " <<     aTol2d                                                                                          << endl;
486     cout << "*****************************************************"                                                             << endl;
487     cout << "aTol3d = " << aTol3d <<"; URes = " << dumax << "; VRes = " << dvmax        << endl;
488     cout << "thePnt(" << thePnt.X() << "; " << thePnt.Y() << ")"                                                                        << endl;
489     cout << "thePntRef(" << thePntRef.X() << "; " << thePntRef.Y() << ")"                                       << endl;
490     }
491 #endif
492
493   return Standard_False;
494   }
495
496 //=======================================================================
497 //function : Closed2d
498 //purpose  : for periodic faces
499 //=======================================================================
500 BRepCheck_Status BRepCheck_Wire::Closed2d(const TopoDS_Face& theFace,
501                                           const Standard_Boolean Update)
502   {
503   // 3d closure checked too
504   BRepCheck_Status aClosedStat = Closed();
505   if (aClosedStat != BRepCheck_NoError)
506     {
507     if (Update)
508       BRepCheck::Add(myMap(myShape),aClosedStat);
509
510     return aClosedStat;
511     }
512
513 // 20/03/02 akm vvv : (OCC234) Hence this method will be used to check
514 //                    both periodic and non-periodic faces
515 //   // this check is for periodic faces 
516   BRepAdaptor_Surface aFaceSurface (theFace, Standard_False);
517 // if (!aFaceSurface.IsUPeriodic() && !aFaceSurface.IsVPeriodic())
518 // {
519 //   if (Update) 
520 //     BRepCheck::Add(myMap(myShape),aClosedStat);
521 //   return aClosedStat;
522 // }
523 // 20/03/02 akm ^^^
524
525 // count edges having FORWARD or REVERSED orientation
526   Standard_Integer aNbOrirntedEdges = 0;
527   TopExp_Explorer anEdgeExp(myShape,TopAbs_EDGE);
528   for (;anEdgeExp.More(); anEdgeExp.Next())
529     {
530     if (IsOriented(anEdgeExp.Current())) 
531       aNbOrirntedEdges++;
532     }
533
534   if (aNbOrirntedEdges==0)
535     {
536     if (Update)
537       BRepCheck::Add(myMap(myShape),aClosedStat);
538
539     return aClosedStat;
540     }
541
542 // all those edges must form a closed 2d contour and be found by WireExplorer
543
544   Standard_Integer aNbFoundEdges = 0;
545   BRepTools_WireExplorer aWireExp(TopoDS::Wire(myShape), theFace);
546   TopoDS_Edge aFirstEdge = aWireExp.Current();
547   TopoDS_Vertex aFirstVertex = aWireExp.CurrentVertex();
548   TopoDS_Edge aLastEdge;
549
550   for (;aWireExp.More(); aWireExp.Next())
551     {
552     aNbFoundEdges++;
553     aLastEdge = aWireExp.Current();
554     }
555
556   if (aNbFoundEdges != aNbOrirntedEdges)
557     {
558     aClosedStat = BRepCheck_NotClosed;
559     if (Update) 
560       BRepCheck::Add(myMap(myShape),aClosedStat);
561     
562     return aClosedStat;
563     }
564
565 // Check distance between 2d ends of first and last edges
566 //  Modified by Sergey KHROMOV - Mon May 13 12:42:10 2002 Begin
567 //   First check if first and last edges are infinite:
568   Standard_Real      aF;
569   Standard_Real      aL;
570   Standard_Boolean   isFirstInfinite = Standard_False;
571   Standard_Boolean   isLastInfinite  = Standard_False;
572   TopAbs_Orientation anOri;
573
574   anOri = aFirstEdge.Orientation();
575   BRep_Tool::Range(aFirstEdge, aF, aL);
576   if ((anOri == TopAbs_FORWARD  && Precision::IsNegativeInfinite( aF )) ||
577          (anOri == TopAbs_REVERSED && Precision::IsPositiveInfinite( aL )))
578     isFirstInfinite = Standard_True;
579
580   anOri = aLastEdge.Orientation();
581   BRep_Tool::Range(aLastEdge, aF, aL);
582   
583   if ((anOri == TopAbs_FORWARD  && Precision::IsPositiveInfinite( aL )) ||
584          (anOri == TopAbs_REVERSED && Precision::IsNegativeInfinite( aF )))
585     isLastInfinite = Standard_True;
586
587   if (isFirstInfinite && isLastInfinite)
588     {
589     if (Update)
590       BRepCheck::Add(myMap(myShape),aClosedStat);
591
592     return aClosedStat;
593     }
594   else if (aFirstVertex.IsNull())
595     {
596     aClosedStat = BRepCheck_NotClosed;
597     
598     if (Update) 
599       BRepCheck::Add(myMap(myShape),aClosedStat);
600     
601     return aClosedStat;
602     }
603 //  Modified by Sergey KHROMOV - Mon May 13 12:42:10 2002 End
604
605   gp_Pnt2d aP_first, aP_last, aP_temp; // ends of prev edge, next edge, bidon
606   
607 // get last point
608   BRep_Tool::UVPoints(aLastEdge, theFace, aP_temp, aP_last);
609   if (aLastEdge.Orientation() == TopAbs_REVERSED)
610     aP_last = aP_temp;
611
612 //  Modified by Sergey KHROMOV - Mon Apr 22 10:36:33 2002 Begin
613 //   Standard_Real aTol, aUResol, aVResol;
614 //   // find 2d tolerance
615 //   aTol  = BRep_Tool::Tolerance(aFirstVertex);
616 //   aUResol = 2*aFaceSurface.UResolution(aTol);
617 //   aVResol = 2*aFaceSurface.VResolution(aTol);
618
619 // get first point
620   if (aFirstEdge.Orientation() == TopAbs_REVERSED)
621     BRep_Tool::UVPoints(aFirstEdge, theFace, aP_temp, aP_first);
622   else 
623     BRep_Tool::UVPoints(aFirstEdge, theFace, aP_first, aP_temp);
624
625 //  Modified by Sergey KHROMOV - Thu Jun 20 10:55:42 2002 OCC325 Begin
626 // Check 2d distance for periodic faces with seam edge
627   if (!IsClosed2dForPeriodicFace(theFace, aP_first, aP_last, aFirstVertex))
628     {
629     aClosedStat = BRepCheck_NotClosed;
630     if (Update)
631       BRepCheck::Add(myMap(myShape),aClosedStat);
632     
633     return aClosedStat;
634     }
635 //  Modified by Sergey KHROMOV - Thu Jun 20 10:58:05 2002 End
636
637 // check distance
638 //   Standard_Real dfUDist=Abs(p.X()-p1.X());
639 //   Standard_Real dfVDist=Abs(p.Y()-p1.Y());
640 //   if (dfUDist > aUResol || dfVDist > aVResol)
641 //   {
642
643   Standard_Real aTol3d  = Max(BRep_Tool::Tolerance(aFirstVertex),BRep_Tool::Tolerance(aWireExp.CurrentVertex()));
644
645   gp_Pnt aPntRef = BRep_Tool::Pnt(aFirstVertex);
646   gp_Pnt aPnt            = BRep_Tool::Pnt(aWireExp.CurrentVertex());
647
648   if (!(IsDistanceIn2DTolerance(aFaceSurface, aP_first, aP_last, aTol3d)))
649     aClosedStat = BRepCheck_NotClosed;
650
651   if(!IsDistanceIn3DTolerance(aPntRef, aPnt, aTol3d))
652     aClosedStat = BRepCheck_NotClosed;
653
654   if (Update) 
655     BRepCheck::Add(myMap(myShape),aClosedStat);
656
657   return aClosedStat;
658   }
659 //=======================================================================
660 //function : Orientation
661 //purpose  : 
662 //=======================================================================
663 BRepCheck_Status BRepCheck_Wire::Orientation(const TopoDS_Face& F,
664                                              const Standard_Boolean Update)
665 {
666   BRepCheck_Status theOstat = Closed();
667   if (theOstat != BRepCheck_NotClosed && theOstat != BRepCheck_NoError) {
668     if (Update) {
669       BRepCheck::Add(myMap(myShape),theOstat);
670     }
671     return theOstat;
672   }
673
674   theOstat = BRepCheck_NoError;
675
676   TopoDS_Vertex VF,VL;
677   TopAbs_Orientation orient, ortmp = TopAbs_FORWARD;
678   TopTools_ListOfShape ledge, ListOfPassedEdge;
679   TopExp_Explorer exp,vte;
680   TopTools_MapOfShape mapS;
681   TopoDS_Edge theEdge,theRef;
682
683   // Checks the orientation of the edges
684   for (exp.Init(myShape,TopAbs_EDGE); exp.More(); exp.Next()) {
685     const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
686     orient = edg.Orientation();
687     if (IsOriented(edg)) {
688       mapS.Add(edg);
689       theEdge = edg;
690       theRef = edg;
691       for (vte.Init(edg,TopAbs_VERTEX);vte.More(); vte.Next()) {
692         TopAbs_Orientation vto = vte.Current().Orientation();
693         if (vto == TopAbs_FORWARD) {
694           VF = TopoDS::Vertex(vte.Current());
695         }
696         else if (vto == TopAbs_REVERSED) {
697           VL = TopoDS::Vertex(vte.Current());
698         }
699         if (!VF.IsNull() && !VL.IsNull()) {
700           break;
701         }
702       }
703       if (VF.IsNull() && VL.IsNull())
704         theOstat = BRepCheck_InvalidDegeneratedFlag;
705       break;
706     }
707   }
708  
709   if (theOstat == BRepCheck_NoError) {
710     Standard_Integer Index = 1;
711     Standard_Integer nbOriNoDegen=myMapVE.Extent();
712 //  Modified by Sergey KHROMOV - Tue May 21 17:12:45 2002 Begin
713     Standard_Boolean isGoFwd     = Standard_True;
714
715     if (VL.IsNull())
716       isGoFwd = Standard_False;
717 //  Modified by Sergey KHROMOV - Tue May 21 17:12:45 2002 End
718
719     while (Index < nbOriNoDegen) {
720       ledge.Clear();
721       ListOfPassedEdge.Clear();
722       // find edges that make a chain on VL if !VL.IsNull 
723       // otherwise on VF.
724       
725       Standard_Integer ind;
726       if (!VL.IsNull()) {
727         ind = myMapVE.FindIndex(VL);
728       }
729       else if (!VF.IsNull()) {
730         ind = myMapVE.FindIndex(VF);
731       }
732       else {
733         theOstat = BRepCheck_InvalidDegeneratedFlag;
734         break;
735       }
736
737       for (TopTools_ListIteratorOfListOfShape itls(myMapVE(ind));
738            itls.More(); itls.Next()) {
739         const TopoDS_Edge & edg = TopoDS::Edge(itls.Value());
740
741         orient = edg.Orientation();
742         if (mapS.Contains(edg)) ortmp = GetOrientation(mapS,edg);
743
744         //Add to list already passed outcoming edges
745         if (mapS.Contains(edg) && ortmp == orient && !edg.IsSame(theEdge))
746           for (vte.Init(edg,TopAbs_VERTEX); vte.More(); vte.Next())
747             {
748               TopAbs_Orientation vto = vte.Current().Orientation();
749               if (!VL.IsNull())
750                 {
751                   if (vto == TopAbs_FORWARD && VL.IsSame(vte.Current()))
752                     {
753                       ListOfPassedEdge.Append(edg);
754                       break;
755                     }
756                 }
757               else // VF is not null
758                 {
759                   if (vto == TopAbs_REVERSED && VF.IsSame(vte.Current()))
760                     {
761                       ListOfPassedEdge.Append(edg);
762                       break;
763                     }
764                 }
765             }
766
767         if (!mapS.Contains(edg) || ortmp != orient) {
768           for (vte.Init(edg,TopAbs_VERTEX);vte.More(); vte.Next()) {
769             TopAbs_Orientation vto = vte.Current().Orientation();
770             if (!VL.IsNull()) {
771               if (vto == TopAbs_FORWARD && VL.IsSame(vte.Current())) {
772                 // If the processing is in 2d (face not null) or 
773                 // if the edge is not degenerated it is added
774                 if (!F.IsNull() || !BRep_Tool::Degenerated(edg))
775                   ledge.Append(edg);
776                 break;
777               }
778             }
779             else { // VF is not null
780               if (vto == TopAbs_REVERSED && VF.IsSame(vte.Current())) {
781                 //    // If the processing is in 2d (face not null) or 
782                 // if the edge is not degenerated it is added
783                 if (!F.IsNull() || !BRep_Tool::Degenerated(edg))
784                   ledge.Append(edg);
785                 break;
786               }
787             }
788           }
789         }
790       }
791       Standard_Integer nbconnex = ledge.Extent();
792       Standard_Boolean Changedesens = Standard_False;
793       if (nbconnex == 0) {
794         if (myCstat == BRepCheck_NotClosed) {
795           if (VL.IsNull()) {
796             if (Update) {
797               BRepCheck::Add(myMap(myShape),theOstat);
798             }
799             return theOstat; // leave
800           }
801           else {
802             Index--; // because after Index++ and if there is no chain,
803             VL.Nullify(); // chain on VF is forced
804             theEdge = theRef;
805             Changedesens = Standard_True;
806           }
807         }
808         else {
809           theOstat = BRepCheck_BadOrientationOfSubshape;
810           if (Update) {
811             BRepCheck::Add(myMap(myShape),theOstat);
812             }
813           return theOstat;
814         }
815       }
816
817       // JAG 03/07   else if (nbconnex >= 2 && !F.IsNull())  // Try to see in 2d
818       else if (!F.IsNull()) { // Try to see in 2d
819         TopoDS_Vertex pivot;
820         if (!VL.IsNull()) {
821           pivot = VL;
822         }
823         else {
824           pivot = VF;
825         }
826
827         ChoixUV(pivot,theEdge,F,ledge);
828         nbconnex = ledge.Extent();
829 //      20/03/02 akm vvv : (OCC234) - The 2d exploration of wire with necessary
830 //                         checks is performed in Closed2d, here it's useless
831 //         if (nbconnex == 1 && !CheckLoopOrientation( pivot, theEdge, TopoDS::Edge(ledge.First()), F, ListOfPassedEdge ))
832 //         {
833 //           theOstat = BRepCheck_BadOrientationOfSubshape;
834 //           if (Update)
835 //             BRepCheck::Add(myMap(myShape),theOstat);
836 //           return theOstat;
837 //         }
838 //      20/03/02 akm ^^^
839       }
840
841       if (nbconnex >= 2) {
842         theOstat = BRepCheck_BadOrientationOfSubshape;
843         if (Update) {
844           BRepCheck::Add(myMap(myShape),theOstat);
845           }
846         return theOstat;
847       }
848       else if (nbconnex == 1) {
849         // offset the vertex
850         for (vte.Init(ledge.First(),TopAbs_VERTEX);vte.More(); vte.Next()) {
851           TopAbs_Orientation vto = vte.Current().Orientation();
852           if (!VL.IsNull()) {
853             if (vto == TopAbs_REVERSED) {
854               VL = TopoDS::Vertex(vte.Current());
855               break;
856             }
857           }
858           else { // VF is not null
859             if (vto == TopAbs_FORWARD) {
860               VF = TopoDS::Vertex(vte.Current());
861               break;
862             }
863           }
864         }
865         mapS.Add(ledge.First());
866         theEdge = TopoDS::Edge(ledge.First());
867         if (!vte.More()) {
868           if (!VL.IsNull()) {
869             VL.Nullify();
870           }
871           else {
872             VF.Nullify();
873           }
874         }
875       }
876       else if (!Changedesens) { //nbconnex == 0
877         theOstat = BRepCheck_NotClosed;
878         if (Update) {
879           BRepCheck::Add(myMap(myShape),theOstat);
880           }
881         return theOstat;
882       }
883
884       // Check the closure of the wire in 2d (not done in Closed())
885       
886       TopoDS_Vertex    aVRef;
887       Standard_Boolean isCheckClose = Standard_False;
888
889       if (isGoFwd && !VF.IsNull()) {
890         aVRef        = VF;
891         isCheckClose = Standard_True;
892       } else if (!isGoFwd && !VL.IsNull()) {
893         aVRef        = VL;
894         isCheckClose = Standard_True;
895       }
896
897 //       if (Index==1 && myCstat!=BRepCheck_NotClosed && 
898 //        !VF.IsNull() && !F.IsNull()) {
899       if (Index==1 && myCstat!=BRepCheck_NotClosed && 
900           isCheckClose && !F.IsNull()) {
901         ledge.Clear();
902 //      ind = myMapVE.FindIndex(VF);
903         ind = myMapVE.FindIndex(aVRef);
904         for (TopTools_ListIteratorOfListOfShape itlsh(myMapVE(ind));
905              itlsh.More(); itlsh.Next()) {
906           const TopoDS_Edge & edg = TopoDS::Edge(itlsh.Value());
907           orient = edg.Orientation();
908           if (!theRef.IsSame(edg)) {
909             for (vte.Init(edg,TopAbs_VERTEX);vte.More(); vte.Next()) {
910               TopAbs_Orientation vto = vte.Current().Orientation();
911 //            if (vto == TopAbs_REVERSED && VF.IsSame(vte.Current())) {
912               if (vto == TopAbs_REVERSED && aVRef.IsSame(vte.Current())) {
913                 ledge.Append(edg);
914                 break;
915               }
916             }
917           }
918         }
919 //      ChoixUV(VF, theRef, F, ledge);
920         ChoixUV(aVRef, theRef, F, ledge);
921         if (ledge.Extent()==0) {
922           theOstat = BRepCheck_NotClosed;
923           if (Update) {
924             BRepCheck::Add(myMap(myShape),theOstat);
925           }
926           return theOstat;
927         }
928       }
929       // End control closure 2d
930
931       Index ++;
932     }
933   }
934   if (Update) {
935     BRepCheck::Add(myMap(myShape),theOstat);
936   }
937   return theOstat;
938 }
939 //=======================================================================
940 //function : SelfIntersect
941 //purpose  : 
942 //=======================================================================
943 BRepCheck_Status BRepCheck_Wire::SelfIntersect(const TopoDS_Face& F,
944                                                TopoDS_Edge& retE1,
945                                                TopoDS_Edge& retE2,
946                                                const Standard_Boolean Update)
947 {
948
949
950   Standard_Integer i,j,Nbedges;
951   Standard_Real first1,last1,first2,last2, tolint;
952   gp_Pnt2d pfirst1,plast1,pfirst2,plast2;
953   gp_Pnt P3d, P3d2;
954   Handle(BRepAdaptor_HSurface) HS;
955   Geom2dAdaptor_Curve C1, C2;
956   Geom2dInt_GInter      Inter;
957   IntRes2d_Domain myDomain1;
958   TopTools_IndexedMapOfOrientedShape EMap;
959   TopTools_MapOfOrientedShape auxmape;
960   //
961   //-- check with proper tolerances if there is no 
962   //-- point in the tolerance of a vertex.
963   tolint = 1.e-10; 
964   HS = new BRepAdaptor_HSurface();
965   HS->ChangeSurface().Initialize(F,Standard_False);
966   //
967   for (TopoDS_Iterator Iter1(myShape);Iter1.More();Iter1.Next()) {
968     if (Iter1.Value().ShapeType() == TopAbs_EDGE) {
969       EMap.Add(Iter1.Value());
970     }
971   }
972   //
973   Nbedges=EMap.Extent();
974   if (!Nbedges) {
975     if (Update) {
976       BRepCheck::Add(myMap(myShape),BRepCheck_EmptyWire);
977     }
978     return(BRepCheck_EmptyWire);
979   }
980   //
981   IntRes2d_Domain *tabDom = new IntRes2d_Domain[Nbedges];
982   TColGeom2d_Array1OfCurve tabCur(1,Nbedges);
983   Bnd_Array1OfBox2d boxes(1,Nbedges);
984   //
985   for(i = 1; i <= Nbedges; i++) { 
986     const TopoDS_Edge& E1 = TopoDS::Edge(EMap.FindKey(i));
987     if (i == 1) {
988       Handle(Geom2d_Curve) pcu = BRep_Tool::CurveOnSurface(E1, F, first1, last1);
989       if (pcu.IsNull()) {
990         retE1=E1;
991         if (Update) {
992           BRepCheck::Add(myMap(myShape),BRepCheck_SelfIntersectingWire);
993         }
994         delete [] tabDom;
995         return(BRepCheck_SelfIntersectingWire);
996       }
997       //
998       C1.Load(pcu);
999       // To avoid exeption in Segment if C1 is BSpline - IFV
1000       if(!C1.IsPeriodic()) {
1001         if(C1.FirstParameter() > first1) {
1002           first1 = C1.FirstParameter();
1003         }
1004         if(C1.LastParameter()  < last1 ){
1005           last1  = C1.LastParameter();
1006         }
1007       }
1008       //
1009       BRep_Tool::UVPoints(E1, F, pfirst1, plast1);
1010       myDomain1.SetValues(pfirst1,first1,tolint, plast1,last1,tolint);
1011       //
1012       BndLib_Add2dCurve::Add(C1, first1, last1, Precision::PConfusion(), boxes(i));
1013     }//if (i == 1) {
1014     else {
1015       C1.Load(tabCur(i));
1016       myDomain1 = tabDom[i-1];
1017     }
1018     //
1019     // Self intersect of C1
1020     Inter.Perform(C1, myDomain1, tolint, tolint);
1021     //
1022     if(Inter.IsDone()) { 
1023       Standard_Integer nbp = Inter.NbPoints();
1024       //Standard_Integer nbs = Inter.NbSegments();
1025       //
1026       for(Standard_Integer p=1;p<=nbp;p++) {
1027         const IntRes2d_IntersectionPoint& IP=Inter.Point(p);
1028         const IntRes2d_Transition& Tr1 = IP.TransitionOfFirst();
1029         const IntRes2d_Transition& Tr2 = IP.TransitionOfSecond();
1030         if(   Tr1.PositionOnCurve() == IntRes2d_Middle
1031            || Tr2.PositionOnCurve() == IntRes2d_Middle) { 
1032           //-- Checking of points with true tolerances (ie Tol in 3d)
1033           //-- If the point of intersection is within the tolearnce of a vertex
1034           //-- this intersection is considered correct (no error)
1035           Standard_Boolean localok = Standard_False;
1036           Standard_Real f,l;
1037           TopLoc_Location L;
1038           const Handle(Geom_Curve) ConS = BRep_Tool::Curve(E1,L,f,l);
1039           if(!ConS.IsNull()) { 
1040             //-- try to test in 3d. (ParamOnSecond gives the same result)
1041             P3d = ConS->Value(IP.ParamOnFirst()); 
1042             P3d.Transform(L.Transformation());
1043             //  Modified by Sergey KHROMOV - Mon Apr 15 12:34:22 2002 Begin
1044           } 
1045           else {
1046             gp_Pnt2d aP2d  = C1.Value(IP.ParamOnFirst());
1047             P3d = HS->Value(aP2d.X(), aP2d.Y());
1048           }
1049           //  Modified by Sergey KHROMOV - Mon Apr 15 12:34:22 2002 End
1050           TopExp_Explorer ExplVtx;
1051           for(ExplVtx.Init(E1,TopAbs_VERTEX); 
1052               localok==Standard_False && ExplVtx.More();
1053               ExplVtx.Next()) { 
1054             gp_Pnt p3dvtt;
1055             Standard_Real tolvtt, p3dvttDistanceP3d;
1056             //
1057             const TopoDS_Vertex& vtt = TopoDS::Vertex(ExplVtx.Current());
1058             p3dvtt = BRep_Tool::Pnt(vtt);
1059             tolvtt =  BRep_Tool::Tolerance(vtt);
1060             tolvtt=tolvtt*tolvtt;
1061             p3dvttDistanceP3d=p3dvtt.SquareDistance(P3d);
1062             if(p3dvttDistanceP3d <=  tolvtt) { 
1063               localok=Standard_True;
1064             }
1065           }
1066           if(localok==Standard_False) { 
1067             retE1=E1;
1068             if (Update) {
1069               BRepCheck::Add(myMap(myShape),BRepCheck_SelfIntersectingWire);
1070               }
1071             delete [] tabDom;
1072 #ifdef OCCT_DEBUG
1073             static Standard_Integer numpoint=0;
1074             cout<<"point p"<<++numpoint<<" "<<P3d.X()<<" "<<P3d.Y()<<" "<<P3d.Z()<<endl;cout.flush();
1075 #endif
1076             return(BRepCheck_SelfIntersectingWire);
1077           }
1078         }
1079       }
1080     }// if(Inter.IsDone()) { 
1081     //
1082     for(j=i+1; j<=Nbedges; j++) {
1083       const TopoDS_Edge& E2 = TopoDS::Edge(EMap.FindKey(j));
1084       if (i == 1) {
1085         tabCur(j) = BRep_Tool::CurveOnSurface(E2,F,first2,last2);
1086         if (!tabCur(j).IsNull() && last2 > first2) {
1087           C2.Load(tabCur(j));
1088           // To avoid exeption in Segment if C2 is BSpline - IFV
1089           if(!C2.IsPeriodic()) {
1090             if(C2.FirstParameter() > first2) {
1091               first2 = C2.FirstParameter();
1092             }
1093             if(C2.LastParameter()  < last2 ) {
1094               last2  = C2.LastParameter();
1095             }
1096           }
1097           //
1098           BRep_Tool::UVPoints(E2,F,pfirst2,plast2);
1099           tabDom[j-1].SetValues(pfirst2,first2,tolint,plast2,last2,tolint);
1100           
1101           BndLib_Add2dCurve::Add( C2, first2, last2, Precision::PConfusion(), boxes(j) );
1102         }
1103         else {
1104           delete [] tabDom;
1105 #ifdef OCCT_DEBUG
1106           cout<<"BRepCheck_NoCurveOnSurface or BRepCheck_InvalidRange"<<endl;cout.flush();
1107 #endif
1108           if(tabCur(j).IsNull()) {
1109             return(BRepCheck_NoCurveOnSurface);
1110           }
1111           return (BRepCheck_InvalidRange);
1112         }
1113       }// if (i == 1) {
1114       else {
1115         C2.Load(tabCur(j));
1116       }
1117       //
1118       if (boxes(i).IsOut( boxes(j))) {
1119         continue;
1120       }
1121       //modified by NIZNHY-PKV Fri Oct 29 10:09:01 2010f
1122       if (E1.IsSame(E2)) {
1123         continue;
1124       }
1125       //modified by NIZNHY-PKV Fri Oct 29 10:09:02 2010t
1126       //
1127       //-- ************************************************************
1128       //-- ******* I n t e r s e c t i o n   C 1   and   C 2   ********
1129       //-- ************************************************************
1130       Inter.Perform(C1,myDomain1,C2,tabDom[j-1],tolint,tolint);
1131       //
1132       if(Inter.IsDone()) { 
1133         Standard_Integer nbp, nbs;
1134         Standard_Real IP_ParamOnFirst, IP_ParamOnSecond;
1135         IntRes2d_Transition Tr1,Tr2;
1136         TopTools_ListOfShape CommonVertices;
1137         TopTools_ListIteratorOfListOfShape itl;
1138         TopTools_MapOfShape Vmap;
1139         //
1140         TopoDS_Iterator it( E1 );
1141         for (; it.More(); it.Next()) {
1142           Vmap.Add( it.Value() );
1143         }
1144         //
1145         it.Initialize( E2 );
1146         for (; it.More(); it.Next()) {
1147           const TopoDS_Shape& V = it.Value();
1148           if (Vmap.Contains( V )) {
1149             CommonVertices.Append( V );
1150           }
1151         }
1152         //
1153         nbp = Inter.NbPoints();
1154         nbs = Inter.NbSegments();
1155         IP_ParamOnFirst  = 0.;
1156         IP_ParamOnSecond = 0.;
1157         //
1158         //// **** Points of intersection **** ////
1159         for (Standard_Integer p = 1; p <= nbp; p++)  {
1160           const IntRes2d_IntersectionPoint& IP = Inter.Point(p);
1161           IP_ParamOnFirst  = IP.ParamOnFirst();
1162           IP_ParamOnSecond = IP.ParamOnSecond();
1163           Tr1 = IP.TransitionOfFirst();
1164           Tr2 = IP.TransitionOfSecond();
1165           if(   Tr1.PositionOnCurve() == IntRes2d_Middle
1166              || Tr2.PositionOnCurve() == IntRes2d_Middle)   {
1167             //-- Checking of points with true tolerances (ie Tol in 3d)
1168             //-- If the point of intersection is within the tolerance of a vertex
1169             //-- this intersection is considered correct (no error)
1170             Standard_Boolean localok = Standard_False;  
1171             Standard_Real f1,l1, f2, l2;
1172             TopLoc_Location L, L2;
1173             //
1174             const Handle(Geom_Curve) ConS = BRep_Tool::Curve(E1,L,f1,l1);    
1175             const Handle(Geom_Curve) ConS2 = BRep_Tool::Curve(E2,L2,f2,l2);  
1176             //gka protect against working out of edge range
1177             if ( f1-IP_ParamOnFirst > ::Precision::PConfusion() || 
1178                 IP_ParamOnFirst-l1 > ::Precision::PConfusion() || 
1179                 f2-IP_ParamOnSecond > ::Precision::PConfusion() || 
1180                 IP_ParamOnSecond-l2 > ::Precision::PConfusion() ) 
1181               continue;
1182             Standard_Real tolvtt = 0.;
1183             //  Modified by Sergey KHROMOV - Mon Apr 15 12:34:22 2002 Begin
1184             if (!ConS.IsNull()) { 
1185               P3d = ConS->Value(IP_ParamOnFirst); 
1186               P3d.Transform(L.Transformation());
1187             } 
1188             else {
1189               gp_Pnt2d aP2d  = C1.Value(IP_ParamOnFirst);
1190               P3d = HS->Value(aP2d.X(), aP2d.Y());
1191             }
1192             //
1193             if (!ConS2.IsNull()) {
1194               P3d2 = ConS2->Value(IP_ParamOnSecond); 
1195               P3d2.Transform(L2.Transformation());
1196             } 
1197             else {
1198               gp_Pnt2d aP2d  = C2.Value(IP_ParamOnSecond);
1199               P3d2 = HS->Value(aP2d.X(), aP2d.Y());
1200             }
1201             //  Modified by Sergey KHROMOV - Mon Apr 15 12:34:22 2002 End
1202             itl.Initialize( CommonVertices );
1203             for (; itl.More(); itl.Next()) {
1204               Standard_Real p3dvttDistanceP3d, p3dvttDistanceP3d2;
1205               gp_Pnt p3dvtt;
1206               //
1207               const TopoDS_Vertex& vtt = TopoDS::Vertex(itl.Value());
1208               p3dvtt = BRep_Tool::Pnt(vtt);
1209               tolvtt =  BRep_Tool::Tolerance(vtt);
1210               tolvtt=1.1*tolvtt;
1211               tolvtt=tolvtt*tolvtt;
1212               p3dvttDistanceP3d  = p3dvtt.SquareDistance(P3d);
1213               p3dvttDistanceP3d2 = p3dvtt.SquareDistance(P3d2);
1214               //
1215               if (p3dvttDistanceP3d<=tolvtt && p3dvttDistanceP3d2<=tolvtt)  { 
1216                 localok = Standard_True;
1217                 break;
1218               }
1219             }
1220             
1221             //-- --------------------------------------------------------
1222             //-- Check maximum yawn between 2 edges
1223             //--
1224             //-- Check distance from edges to the curve joining 
1225             //-- the point of intersection with vertex (if exists)
1226             if (localok == Standard_False && !CommonVertices.IsEmpty()) {
1227 #ifdef OCCT_DEBUG
1228               cout << "\n------------------------------------------------------\n" <<endl;
1229               cout << "\n--- BRepCheck Wire: AutoIntersection Phase1 -> Erreur \n" <<endl;
1230               
1231 #endif
1232               Standard_Real distauvtxleplusproche,VParaOnEdge1,VParaOnEdge2;
1233               gp_Pnt VertexLePlusProche;
1234               //
1235               VParaOnEdge1 =0.;
1236               VParaOnEdge2 =0.;
1237               distauvtxleplusproche=RealLast();
1238               //Find the nearest common vertex
1239               itl.Initialize( CommonVertices );
1240               for (; itl.More(); itl.Next())   {
1241                 Standard_Real disptvtx;
1242                 gp_Pnt p3dvtt;
1243                 //
1244                 const TopoDS_Vertex& vtt = TopoDS::Vertex(itl.Value());
1245                 p3dvtt = BRep_Tool::Pnt(vtt);
1246                 disptvtx = P3d.Distance(p3dvtt);
1247                 if (disptvtx < distauvtxleplusproche)   {
1248                   VertexLePlusProche = p3dvtt; 
1249                   distauvtxleplusproche = disptvtx;
1250                   VParaOnEdge1 = BRep_Tool::Parameter(vtt,E1);
1251                   VParaOnEdge2 = BRep_Tool::Parameter(vtt,E2);
1252                 }
1253                 // eap: case of closed edge
1254                 else if (IsEqual(distauvtxleplusproche, disptvtx)) {
1255                   Standard_Real newVParaOnEdge1 = BRep_Tool::Parameter(vtt,E1);
1256                   Standard_Real newVParaOnEdge2 = BRep_Tool::Parameter(vtt,E2);
1257                   if (Abs(IP_ParamOnFirst - VParaOnEdge1) + Abs(IP_ParamOnSecond - VParaOnEdge2)
1258                       >
1259                       Abs(IP_ParamOnFirst - newVParaOnEdge1) + Abs(IP_ParamOnSecond - newVParaOnEdge2)) {
1260                     VertexLePlusProche = p3dvtt;
1261                     VParaOnEdge1 = newVParaOnEdge1;
1262                     VParaOnEdge2 = newVParaOnEdge2;
1263                   }
1264                 }
1265               }
1266               //Patch: extraordinar situation (e.g. tolerance(v) == 0.)
1267               //  Modified by skv - Wed Jul 23 12:28:11 2003 OCC1764 Begin
1268               // if (VertexLePlusProche.Distance( P3d ) <= gp::Resolution())
1269               if (VertexLePlusProche.Distance(P3d)  <= gp::Resolution() ||
1270                   VertexLePlusProche.Distance(P3d2) <= gp::Resolution()) {
1271                     //  Modified by skv - Wed Jul 23 12:28:12 2003 OCC1764 End
1272                 localok = Standard_True;
1273               }
1274               else {
1275                 gp_Lin Lig( VertexLePlusProche, gp_Vec(VertexLePlusProche,P3d) );
1276                 Standard_Real du1 = 0.1*(IP_ParamOnFirst -VParaOnEdge1);
1277                 Standard_Real du2 = 0.1*(IP_ParamOnSecond-VParaOnEdge2);
1278                 Standard_Real maxd1 = 0., maxd2 = 0.;
1279                 Standard_Integer k;
1280                 
1281                 localok = Standard_True;
1282                 Standard_Real tole1 = BRep_Tool::Tolerance(E1);
1283                 for (k = 2; localok && k < 9; k++)      { 
1284                   Standard_Real u = VParaOnEdge1 + k*du1;  // check if it works
1285                   gp_Pnt P1;
1286                   //  Modified by Sergey KHROMOV - Mon Apr 15 12:34:22 2002 Begin
1287                   if (!ConS.IsNull()) {
1288                     P1 = ConS->Value(u);
1289                     P1.Transform(L.Transformation());
1290                   } 
1291                   else {
1292                     gp_Pnt2d aP2d  = C1.Value(u);
1293                     P1 = HS->Value(aP2d.X(), aP2d.Y());
1294                   }
1295                   //  Modified by Sergey KHROMOV - Mon Apr 15 12:34:22 2002 End
1296                   Standard_Real d1 = Lig.Distance(P1);
1297                   if (d1 > maxd1) {
1298                     maxd1 = d1;
1299                   }
1300                   if (d1 > tole1*2.0){
1301                     localok = Standard_False;
1302                   }
1303                 }
1304                 //-- same for edge2
1305                 //  Modified by skv - Wed Jul 23 12:22:20 2003 OCC1764 Begin
1306                 gp_Dir aTmpDir(P3d2.XYZ().Subtracted(VertexLePlusProche.XYZ()));
1307                 
1308                 Lig.SetDirection(aTmpDir);
1309                 //  Modified by skv - Wed Jul 23 12:22:23 2003 OCC1764 End
1310                 Standard_Real tole2 = BRep_Tool::Tolerance(E2);
1311                 for (k = 2; localok && k < 9; k++) {
1312                   Standard_Real u = VParaOnEdge2 + k*du2;  // check if it works
1313                   gp_Pnt        P2;
1314                   //  Modified by Sergey KHROMOV - Mon Apr 15 12:34:22 2002 Begin
1315                   if (!ConS2.IsNull()) {
1316                     P2 = ConS2->Value(u);
1317                     P2.Transform(L2.Transformation());
1318                   }
1319                   else {
1320                     gp_Pnt2d aP2d  = C2.Value(u);
1321                     P2 = HS->Value(aP2d.X(), aP2d.Y());
1322                   }
1323                   //  Modified by Sergey KHROMOV - Mon Apr 15 12:34:22 2002 End
1324                   Standard_Real d2 = Lig.Distance(P2);
1325                   if (d2 > maxd2) {
1326                     maxd2 = d2;
1327                   }
1328                   if (d2 > tole2*2.0){
1329                     localok = Standard_False;
1330                   }
1331                 }
1332 #ifdef OCCT_DEBUG
1333                 if(localok) { 
1334                   printf("--- BRepCheck Wire: AutoIntersection Phase2 -> Bon \n");
1335                   printf("--- distance Point Vertex : %10.7g (tol %10.7g)\n",distauvtxleplusproche,tolvtt);
1336                   printf("--- Erreur Max sur E1 : %10.7g  Tol_Edge:%10.7g\n",maxd1,tole1);
1337                   printf("--- Erreur Max sur E2 : %10.7g  Tol_Edge:%10.7g\n",maxd2,tole2);
1338                   fflush(stdout);
1339                 }
1340                 else { 
1341                   printf("--- BRepCheck Wire: AutoIntersection Phase2 -> Erreur \n");
1342                   printf("--- distance Point Vertex : %10.7g (tol %10.7g)\n",distauvtxleplusproche,tolvtt);
1343                   printf("--- Erreur Max sur E1 : %10.7g  Tol_Edge:%10.7g\n",maxd1,tole1);
1344                   printf("--- Erreur Max sur E2 : %10.7g  Tol_Edge:%10.7g\n",maxd2,tole2);
1345                   fflush(stdout);
1346                 }
1347 #endif
1348               } //end of else (construction of the line Lig)
1349             } //end of if (localok == Standard_False && !CommonVertices.IsEmpty())
1350             //
1351             if(localok==Standard_False)   { 
1352               retE1=E1;
1353               retE2=E2;
1354               if (Update) {
1355                 BRepCheck::Add(myMap(myShape),BRepCheck_SelfIntersectingWire);
1356                 }
1357 #ifdef OCCT_DEBUG
1358               static Standard_Integer numpoint1=0;
1359               cout<<"point p"<<++numpoint1<<" "<<P3d.X()<<" "<<P3d.Y()<<" "<<P3d.Z()<<endl;
1360               cout.flush();
1361 #endif
1362               delete [] tabDom;
1363               return(BRepCheck_SelfIntersectingWire);
1364             } //-- localok == False
1365           } //end of if(Tr1.PositionOnCurve() == IntRes2d_Middle || Tr2.PositionOnCurve() == IntRes2d_Middle)
1366         } //end of for (Standard_Integer p=1; p <= nbp; p++)    
1367         ////
1368         //// **** Segments of intersection **** ////
1369         for (Standard_Integer s = 1; s <= nbs; ++s) {
1370           const IntRes2d_IntersectionSegment& Seg = Inter.Segment(s);
1371           if (Seg.HasFirstPoint() && Seg.HasLastPoint())   { 
1372             Standard_Boolean localok;
1373             Standard_Integer k;
1374             IntRes2d_IntersectionPoint PSeg [2];
1375             IntRes2d_Position aPCR1, aPCR2;
1376             //
1377             localok = Standard_False;
1378             PSeg[0] = Seg.FirstPoint();
1379             PSeg[1] = Seg.LastPoint();
1380             // At least one of extremities of the segment must be inside
1381             // the tolerance of a common vertex
1382             for (k = 0; k < 2; ++k) {
1383               IP_ParamOnFirst  = PSeg[k].ParamOnFirst();
1384               IP_ParamOnSecond = PSeg[k].ParamOnSecond();
1385               Tr1 = PSeg[k].TransitionOfFirst();
1386               Tr2 = PSeg[k].TransitionOfSecond();
1387               aPCR1=Tr1.PositionOnCurve();
1388               aPCR2=Tr2.PositionOnCurve();
1389               //
1390               if(aPCR1!=IntRes2d_Middle && aPCR2!=IntRes2d_Middle)  {
1391                 GeomAbs_CurveType aCT1, aCT2;
1392                 //ZZ
1393                 aCT1=C1.GetType();
1394                 aCT2=C2.GetType();
1395                 if (aCT1==GeomAbs_Line && aCT2==GeomAbs_Line) {
1396                   // check for the two lines coincidence
1397                   Standard_Real aPAR_T, aT11, aT12, aT21, aT22, aT1m, aT2m;
1398                   Standard_Real aD2, aTolE1, aTolE2,  aTol2, aDot;
1399                   gp_Lin2d aL1, aL2;
1400                   gp_Pnt2d aP1m;
1401                   //
1402                   aPAR_T=0.43213918;
1403                   //
1404                   aTolE1=BRep_Tool::Tolerance(E1);
1405                   aTolE2=BRep_Tool::Tolerance(E2);
1406                   aTol2=aTolE1+aTolE2;
1407                   aTol2=aTol2*aTol2;
1408                   //
1409                   aL1=C1.Line();
1410                   aL2=C2.Line();
1411                   //
1412                   aT11=PSeg[0].ParamOnFirst();
1413                   aT12=PSeg[1].ParamOnFirst();
1414                   aT21=PSeg[0].ParamOnSecond();
1415                   aT22=PSeg[1].ParamOnSecond();
1416                   //
1417                   aT1m=(1.-aPAR_T)*aT11 + aPAR_T*aT12;
1418                   aP1m=C1.Value(aT1m);
1419                   //
1420                   aD2=aL2.SquareDistance(aP1m);
1421                   if (aD2<aTol2) {
1422                     aT2m=ElCLib::Parameter(aL2, aP1m);
1423                     if (aT2m>aT21 && aT2m<aT22) {
1424                       const gp_Dir2d& aDir1=aL1.Direction();
1425                       const gp_Dir2d& aDir2=aL2.Direction();
1426                       aDot=aDir1*aDir2;
1427                       if (aDot<0.) {
1428                         aDot=-aDot;
1429                       }
1430                       //
1431                       if ((1.-aDot)<5.e-11){//0.00001 rad
1432                         localok = Standard_False;
1433                         break;// from for (k = 0; k < 2; ++k){...
1434                       }
1435                     }//if (aT2m>aT21 && aT2m<aT22) {
1436                   }//if (aD2<aTol2) {
1437                 }//if (aCT1==GeomAbs_Line && aCT2==GeomAbs_Line) {
1438                 //ZZ
1439                 localok = Standard_True;
1440                 break;
1441               }
1442               //
1443               Standard_Real f,l, tolvtt;
1444               TopLoc_Location L, L2;
1445               const Handle(Geom_Curve)& ConS = BRep_Tool::Curve(E1,L,f,l);    
1446               const Handle(Geom_Curve)& ConS2 = BRep_Tool::Curve(E2,L2,f,l);    
1447               //  Modified by Sergey KHROMOV - Mon Apr 15 12:34:22 2002 Begin
1448               if (!ConS.IsNull()) { 
1449                 P3d = ConS->Value(IP_ParamOnFirst); 
1450                 P3d.Transform(L.Transformation());
1451               } else {
1452                 gp_Pnt2d aP2d  = C1.Value(IP_ParamOnFirst);
1453                 P3d = HS->Value(aP2d.X(), aP2d.Y());
1454               }
1455               if (!ConS2.IsNull()) {
1456                 P3d2 = ConS2->Value(IP_ParamOnSecond); 
1457                 P3d2.Transform(L2.Transformation());
1458               } else {
1459                 gp_Pnt2d aP2d  = C2.Value(IP_ParamOnSecond);
1460                 P3d2 = HS->Value(aP2d.X(), aP2d.Y());
1461               }
1462               //  Modified by Sergey KHROMOV - Mon Apr 15 12:34:22 2002 End
1463               itl.Initialize( CommonVertices );
1464               for (; itl.More(); itl.Next()) {
1465                 Standard_Real p3dvttDistanceP3d, p3dvttDistanceP3d2;
1466                 gp_Pnt p3dvtt;
1467                 //
1468                 const TopoDS_Vertex& vtt = TopoDS::Vertex(itl.Value());
1469                 p3dvtt = BRep_Tool::Pnt(vtt);
1470                 tolvtt =  BRep_Tool::Tolerance(vtt);
1471                 tolvtt=1.1*tolvtt;
1472                 tolvtt=tolvtt*tolvtt;
1473                 p3dvttDistanceP3d  = p3dvtt.SquareDistance(P3d);
1474                 p3dvttDistanceP3d2 = p3dvtt.SquareDistance(P3d2);
1475                 if (p3dvttDistanceP3d <= tolvtt && p3dvttDistanceP3d2 <= tolvtt) { 
1476                   localok = Standard_True;
1477                   break;
1478                 }
1479               }
1480               if (localok == Standard_True) {
1481                 break;
1482               }
1483             } //end of for (k = 0; k < 2; k++)
1484             //
1485             if(localok==Standard_False)   { 
1486               retE1=E1;
1487               retE2=E2;
1488               if (Update) {
1489                 BRepCheck::Add(myMap(myShape),BRepCheck_SelfIntersectingWire);
1490               }
1491 #ifdef OCCT_DEBUG
1492               static Standard_Integer numpoint1=0;
1493               cout<<"point p"<<++numpoint1<<" "<<P3d.X()<<" "<<P3d.Y()<<" "<<P3d.Z()<<endl;
1494               cout.flush();
1495 #endif
1496               delete [] tabDom;
1497               return(BRepCheck_SelfIntersectingWire);
1498             } //-- localok == False
1499           } //end of if(Seg.HasFirstPoint() && Seg.HasLastPoint())
1500         } //end of for (Standard_Integer s = 1; s <= nbs; p++)
1501       } //-- Inter.IsDone()
1502     } //end of for( j = i+1; j<=Nbedges; j++)
1503   } //end of for(i = 1; i <= Nbedges; i++)
1504   //
1505   delete [] tabDom;
1506   if (Update) {
1507     BRepCheck::Add(myMap(myShape),BRepCheck_NoError);
1508   }
1509   //
1510   return (BRepCheck_NoError);
1511 }
1512
1513 //=======================================================================
1514 //function :   SetStatus
1515 //purpose  : 
1516 //=======================================================================
1517
1518 void BRepCheck_Wire::SetStatus(const BRepCheck_Status theStatus)
1519 {
1520     BRepCheck::Add(myMap(myShape),theStatus);
1521 }
1522
1523 //=======================================================================
1524 //function : GeometricControls
1525 //purpose  : 
1526 //=======================================================================
1527 void BRepCheck_Wire::GeometricControls(const Standard_Boolean B)
1528 {
1529   if (myGctrl != B) {
1530     if (B) {
1531       myCdone = Standard_False;
1532     }
1533     myGctrl = B;
1534   }
1535 }
1536 //=======================================================================
1537 //function : GeometricControls
1538 //purpose  : 
1539 //=======================================================================
1540 Standard_Boolean BRepCheck_Wire::GeometricControls() const
1541 {
1542   return myGctrl;
1543 }
1544
1545 //=======================================================================
1546 //function : Propagate
1547 //purpose  : fill <mapE> with edges connected to <edg> through vertices
1548 //           contained in <mapVE>
1549 //=======================================================================
1550 static void Propagate(const TopTools_IndexedDataMapOfShapeListOfShape& mapVE,
1551                       const TopoDS_Shape& edg,
1552                       TopTools_MapOfShape& mapE)
1553 {
1554   TopTools_ListOfShape currentEdges;
1555   currentEdges.Append(edg);
1556
1557   do
1558   {
1559     TopTools_ListOfShape nextEdges;
1560     TopTools_ListIteratorOfListOfShape itrc(currentEdges);
1561     for (; itrc.More(); itrc.Next())
1562     {
1563       const TopoDS_Shape& Edge = itrc.Value();
1564       if (!mapE.Contains(Edge)) 
1565         mapE.Add(Edge);
1566
1567       TopExp_Explorer ex(Edge, TopAbs_VERTEX);
1568       for (; ex.More(); ex.Next())
1569       {
1570         const TopoDS_Vertex& vtx = TopoDS::Vertex(ex.Current());
1571         Standard_Integer indv = mapVE.FindIndex(vtx);
1572         if (indv != 0)
1573         {
1574           const TopTools_ListOfShape& edges = mapVE(indv);
1575
1576           TopTools_ListIteratorOfListOfShape itl(edges);
1577           for (; itl.More(); itl.Next())
1578           {
1579             const TopoDS_Shape& E = itl.Value();
1580             if (!Edge.IsSame(E) && !mapE.Contains(E))
1581             {
1582               mapE.Add(E);
1583               nextEdges.Append(E);
1584             }
1585           }
1586         }
1587       }
1588     }
1589     currentEdges = nextEdges;
1590   }
1591   while (!currentEdges.IsEmpty());
1592 }
1593
1594 //=======================================================================
1595 //function : GetOrientation
1596 //purpose  : 
1597 //=======================================================================
1598
1599 static TopAbs_Orientation GetOrientation(const TopTools_MapOfShape& mapE,
1600                                          const TopoDS_Edge& edg)
1601 {
1602   TopTools_MapIteratorOfMapOfShape itm(mapE);
1603   for ( ; itm.More(); itm.Next()) {
1604     if (itm.Key().IsSame(edg)) {
1605       break;
1606     }
1607   }
1608   return itm.Key().Orientation();
1609 }
1610 //=======================================================================
1611 //function : ChoixUV
1612 //purpose  : For vertex theVertex given function find an edge along 
1613 //           that we should go further.
1614 //=======================================================================
1615 void ChoixUV(const TopoDS_Vertex& theVertex,
1616              const TopoDS_Edge& theEdge,
1617              const TopoDS_Face& theFace,
1618              TopTools_ListOfShape& theLOfShape)
1619   {
1620   TopTools_ListIteratorOfListOfShape It( theLOfShape );
1621   while (It.More())
1622     {
1623     if (theEdge.IsSame( It.Value() ))
1624       theLOfShape.Remove( It );
1625     else
1626       It.Next();
1627     }
1628
1629   Standard_Real aTol3d  = BRep_Tool::Tolerance(theVertex);
1630
1631   Standard_Integer anIndex = 0, anIndMin = 0;
1632   TopoDS_Edge anEFound;
1633   gp_Pnt2d aPntRef, aPnt;
1634   gp_Vec2d aDerRef, aDer;
1635   Standard_Real aMinAngle, aMaxAngle, anAngle;
1636   Standard_Real a_gpResolution=gp::Resolution();
1637   TopAbs_Orientation aVOrientation, anEdgOrientation;
1638   Standard_Real aParam = 0.0, aFirstParam = 0.0, aLastParam = 0.0, aParPiv = 0.0;
1639   BRepAdaptor_Surface aFaceSurface(theFace,Standard_False); // no restriction
1640   
1641   Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(theEdge, theFace, aFirstParam, aLastParam);
1642   if (C2d.IsNull())// JAG 10.12.96
1643     return;
1644
1645   aVOrientation = theVertex.Orientation();
1646   anEdgOrientation = theEdge.Orientation();
1647   
1648   aParPiv =(aVOrientation==anEdgOrientation) ? aFirstParam : aLastParam;
1649   aMinAngle = RealLast();
1650   aMaxAngle = RealFirst();
1651
1652   CurveDirForParameter(C2d, aParPiv, aPntRef, aDerRef);
1653   
1654   if (aVOrientation != anEdgOrientation)
1655     aDerRef.Reverse();
1656
1657   It.Initialize(theLOfShape);
1658
1659   for (; It.More(); It.Next())
1660     {
1661     anIndex++;
1662     const TopoDS_Edge& anE=TopoDS::Edge(It.Value());
1663     C2d = BRep_Tool::CurveOnSurface(anE, theFace, aFirstParam, aLastParam);
1664     if(C2d.IsNull())
1665       continue;
1666     Geom2dAdaptor_Curve aCA(C2d);
1667
1668     aParam =(aVOrientation != anE.Orientation()) ? aFirstParam : aLastParam;
1669     aPnt = aCA.Value(aParam);
1670
1671     if(!IsDistanceIn2DTolerance(aFaceSurface, aPnt, aPntRef, aTol3d, Standard_False))
1672       continue;
1673
1674     CurveDirForParameter(aCA, aParam, aPnt, aDer);
1675
1676     if (aVOrientation == anE.Orientation())
1677       aDer.Reverse();
1678
1679     if ((aDerRef.Magnitude() <= a_gpResolution) || 
1680                  (aDer.Magnitude() <= a_gpResolution))
1681 //Vector length is too small
1682       continue;
1683
1684     anAngle = -aDerRef.Angle( aDer );
1685
1686     if ( anAngle < 0. )
1687       anAngle += 2.*M_PI;
1688
1689     if ( theFace.Orientation() == TopAbs_FORWARD )
1690       {
1691       if ( anAngle < aMinAngle )
1692         {
1693         anIndMin = anIndex;
1694         aMinAngle = anAngle;
1695         }
1696       }
1697     else //theFace.Orientation() != TopAbs_FORWARD
1698       {
1699       if ( anAngle > aMaxAngle )
1700         {
1701         anIndMin = anIndex;
1702         aMaxAngle = anAngle;
1703         }
1704       }
1705     }//end of for
1706
1707 // Update edge
1708   if (anIndMin == 0)
1709     if (theLOfShape.Extent() == 1)
1710       {
1711       Standard_Boolean IsFound = Standard_True; //all right
1712       anEFound = TopoDS::Edge(theLOfShape.First());
1713
1714       if(anEFound.IsNull() || BRep_Tool::Degenerated(theEdge) ||
1715                                   BRep_Tool::Degenerated(anEFound))
1716         IsFound = Standard_False; //bad
1717       else if (!IsDistanceIn2DTolerance(aFaceSurface, aPnt, aPntRef, aTol3d))
1718         IsFound = Standard_False; //bad
1719       else 
1720         // clousureness in 3D
1721         {
1722 //IsDistanceIn3DTolerance
1723         BRepAdaptor_Curve bcEdg(theEdge, theFace);
1724         BRepAdaptor_Curve bcEvois(anEFound, theFace);
1725         gp_Pnt pEdg = bcEdg.Value(aParPiv);
1726         gp_Pnt pEFound = bcEvois.Value(aParam);
1727
1728         if(!IsDistanceIn3DTolerance(pEdg, pEFound, aTol3d))
1729           IsFound = Standard_False;
1730         else
1731 //angle was not defined but points are close
1732           IsFound = Standard_True; //all right
1733         }
1734
1735       if(!IsFound)
1736         {
1737         theLOfShape.Clear();
1738         }
1739       }//if (theLOfShape.Extent() == 1)
1740     else //if (anIndMin == 0)
1741       {
1742       theLOfShape.Clear();
1743       }
1744   else
1745     {
1746     anIndex = 1;
1747
1748     while (anIndex < anIndMin)
1749       {
1750       theLOfShape.RemoveFirst();
1751       anIndex++;
1752       }
1753
1754     It.Initialize(theLOfShape);
1755     It.Next();
1756
1757     while (It.More())
1758       theLOfShape.Remove(It);
1759     }
1760   }//End of function
1761
1762
1763 //=======================================================================
1764 //function : CurveDirForParameter
1765 //purpose  : 
1766 //=======================================================================
1767 void CurveDirForParameter(const Geom2dAdaptor_Curve& aC2d,
1768                           const Standard_Real aPrm,
1769                           gp_Pnt2d& Pnt,
1770                           gp_Vec2d& aVec2d)
1771 {
1772   Standard_Real aTol=gp::Resolution();
1773   Standard_Integer i;
1774
1775   aC2d.D1(aPrm, Pnt, aVec2d);
1776   //
1777   if (aVec2d.Magnitude() <= aTol) {
1778     for (i = 2; i <= 100; i++){
1779       aVec2d = aC2d.DN(aPrm, i);
1780       if (aVec2d.Magnitude() > aTol) {
1781         break;
1782       }
1783     }
1784   }
1785 }
1786
1787 //  Modified by Sergey KHROMOV - Wed May 22 10:44:06 2002 OCC325 Begin
1788 //=======================================================================
1789 //function : GetPnts2d
1790 //purpose  : this function returns the parametric points of theVertex on theFace.
1791 //           If theVertex is a start and end vertex of theEdge hasSecondPnt
1792 //           becomes Standard_True and aPnt2 returns the second parametric point.
1793 //           Returns Standard_True if paraametric points are successfully found.
1794 //=======================================================================
1795
1796 static Standard_Boolean GetPnt2d(const TopoDS_Vertex    &theVertex,
1797                                  const TopoDS_Edge      &theEdge,
1798                                  const TopoDS_Face      &theFace,
1799                                        gp_Pnt2d         &aPnt)
1800 {
1801   Handle(Geom2d_Curve) aPCurve;
1802   Standard_Real        aFPar;
1803   Standard_Real        aLPar;
1804   Standard_Real        aParOnEdge;
1805   TopoDS_Vertex        aFirstVtx;
1806   TopoDS_Vertex        aLastVtx;
1807
1808   TopExp::Vertices(theEdge, aFirstVtx, aLastVtx);
1809
1810   if (!theVertex.IsSame(aFirstVtx) && !theVertex.IsSame(aLastVtx))
1811     return Standard_False;
1812
1813   aPCurve = BRep_Tool::CurveOnSurface(theEdge, theFace, aFPar, aLPar);
1814
1815   if (aPCurve.IsNull())
1816     return Standard_False;
1817
1818   aParOnEdge = BRep_Tool::Parameter(theVertex, theEdge);
1819   aPnt       = aPCurve->Value(aParOnEdge);
1820
1821   return Standard_True;
1822 }
1823
1824 //=======================================================================
1825 //function : Closed2dForPeriodicFace
1826 //purpose  : Checks the distance between first point of the first edge
1827 //           and last point of the last edge in 2d for periodic face.
1828 //=======================================================================
1829 static Standard_Boolean IsClosed2dForPeriodicFace
1830                         (const TopoDS_Face   &theFace,
1831                          const gp_Pnt2d      &theP1,
1832                          const gp_Pnt2d      &theP2,
1833                          const TopoDS_Vertex &theVertex)
1834 {
1835 // Check 2d distance for periodic faces with seam edge.
1836 // Searching for seam edges
1837   TopTools_ListOfShape aSeamEdges;
1838   TopTools_MapOfShape  NotSeams;
1839   TopTools_MapOfShape  ClosedEdges;
1840   TopExp_Explorer      anExp(theFace, TopAbs_EDGE);
1841
1842   for (;anExp.More(); anExp.Next()) {
1843     TopoDS_Edge anEdge = TopoDS::Edge(anExp.Current());
1844
1845     if (NotSeams.Contains(anEdge))
1846       continue;
1847
1848     if (!IsOriented(anEdge) ||
1849         !BRep_Tool::IsClosed(anEdge, theFace)) {
1850       NotSeams.Add(anEdge);
1851       continue;
1852     }
1853
1854     if (!ClosedEdges.Add(anEdge))
1855       aSeamEdges.Append(anEdge);
1856   }
1857
1858   if (aSeamEdges.Extent() == 0)
1859     return Standard_True;
1860
1861 // check if theVertex lies on one of the seam edges
1862   BRepAdaptor_Surface aFaceSurface (theFace, Standard_False);
1863   Standard_Real       aTol      = BRep_Tool::Tolerance(theVertex);
1864   Standard_Real       aUResol   = aFaceSurface.UResolution(aTol);
1865   Standard_Real       aVResol   = aFaceSurface.VResolution(aTol);
1866   Standard_Real       aVicinity = Sqrt(aUResol*aUResol + aVResol*aVResol);
1867   Standard_Real       aDistP1P2 = theP1.Distance(theP2);
1868
1869
1870   TopTools_ListIteratorOfListOfShape anIter(aSeamEdges);
1871
1872   for (; anIter.More(); anIter.Next()) {
1873     TopoDS_Edge aSeamEdge = TopoDS::Edge(anIter.Value());
1874
1875     anExp.Init(aSeamEdge, TopAbs_VERTEX);
1876     for (; anExp.More(); anExp.Next()) {
1877       const TopoDS_Shape &aVtx = anExp.Current();
1878
1879 // We found an edge. Check the distance between two given points
1880 //  to be lower than the computed tolerance.
1881       if (IsOriented(aVtx) && aVtx.IsSame(theVertex)) {
1882         gp_Pnt2d         aPnt1;
1883         gp_Pnt2d         aPnt2;
1884         Standard_Real    a2dTol;
1885
1886         if (!GetPnt2d(theVertex, aSeamEdge, theFace, aPnt1))
1887           continue;
1888
1889         aSeamEdge = TopoDS::Edge(aSeamEdge.Reversed());
1890
1891         if (!GetPnt2d(theVertex, aSeamEdge, theFace, aPnt2))
1892           continue;
1893
1894         a2dTol = aPnt1.Distance(aPnt2)*1.e-2;
1895         a2dTol = Max(a2dTol, aVicinity);
1896
1897         if (aDistP1P2 > a2dTol)
1898           return Standard_False;
1899       }
1900     }
1901   }
1902
1903   return Standard_True;
1904 }
1905 //  Modified by Sergey KHROMOV - Thu Jun 20 10:58:05 2002 End