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