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