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