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