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