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