1 // Created on: 1995-12-15
2 // Created by: Jacques GOUSSARD
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 #include <BRepCheck_Face.ixx>
19 #include <BRepCheck_ListOfStatus.hxx>
20 #include <BRepCheck_ListIteratorOfListOfStatus.hxx>
22 #include <BRep_TFace.hxx>
23 #include <BRep_Builder.hxx>
24 #include <BRep_Tool.hxx>
27 #include <TopExp_Explorer.hxx>
29 #include <TopTools_ListOfShape.hxx>
30 #include <TopTools_ListIteratorOfListOfShape.hxx>
31 #include <TopTools_DataMapOfShapeListOfShape.hxx>
32 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
34 //#include <BRepAdaptor_Curve2d.hxx>
35 #include <BRepClass_FaceClassifier.hxx>
36 //#include <Geom2dInt_GInter.hxx>
37 #include <Geom2d_Curve.hxx>
38 #include <Geom_Curve.hxx>
39 #include <GProp_GProps.hxx>
41 #include <IntRes2d_Domain.hxx>
42 #include <Geom2dInt_GInter.hxx>
43 #include <Geom2dAdaptor_Curve.hxx>
44 #include <gp_Pnt2d.hxx>
48 #include <BRepCheck.hxx>
49 #include <Precision.hxx>
51 #include <TopoDS_Wire.hxx>
53 #include <BRepTopAdaptor_FClass2d.hxx>
54 #include <TopAbs_State.hxx>
56 #include <Bnd_Box2d.hxx>
57 #include <BndLib_Add2dCurve.hxx>
58 #include <TopTools_MapOfShape.hxx>
59 #include <TopTools_SequenceOfShape.hxx>
60 #include <TColgp_SequenceOfPnt.hxx>
61 #include <TopoDS_Vertex.hxx>
62 #include <IntRes2d_IntersectionPoint.hxx>
63 #include <IntRes2d_IntersectionSegment.hxx>
64 #include <BRepAdaptor_HSurface.hxx>
66 #include <TopTools_OrientedShapeMapHasher.hxx>
67 #include <NCollection_DataMap.hxx>
69 typedef NCollection_DataMap<TopoDS_Shape, Bnd_Box2d, TopTools_OrientedShapeMapHasher> DataMapOfShapeBox2d;
71 static Standard_Boolean Intersect(const TopoDS_Wire&,
74 const DataMapOfShapeBox2d&);
77 static Standard_Boolean IsInside(const TopoDS_Wire& wir,
78 const Standard_Boolean Inside,
79 const BRepTopAdaptor_FClass2d& FClass2d,
80 const TopoDS_Face& F);
82 static Standard_Boolean CheckThin(const TopoDS_Shape& w,
83 const TopoDS_Shape& f);
85 //=======================================================================
86 //function : BRepCheck_Face
88 //=======================================================================
90 BRepCheck_Face::BRepCheck_Face (const TopoDS_Face& F)
93 myIntdone = Standard_False;
94 myImbdone = Standard_False;
95 myOridone = Standard_False;
96 myGctrl = Standard_True;
99 //=======================================================================
102 //=======================================================================
104 void BRepCheck_Face::Minimum()
107 BRepCheck_ListOfStatus thelist;
108 myMap.Bind(myShape, thelist);
109 BRepCheck_ListOfStatus& lst = myMap(myShape);
111 Handle(BRep_TFace)& TF = *((Handle(BRep_TFace)*) &myShape.TShape());
112 if (TF->Surface().IsNull()) {
113 BRepCheck::Add(lst,BRepCheck_NoSurface);
116 // Flag natural restriction???
119 lst.Append(BRepCheck_NoError);
121 myMin = Standard_True;
126 //=======================================================================
127 //function : InContext
129 //=======================================================================
131 void BRepCheck_Face::InContext(const TopoDS_Shape& S)
133 if (myMap.IsBound(S)) {
136 BRepCheck_ListOfStatus thelist;
137 myMap.Bind(S, thelist);
139 BRepCheck_ListOfStatus& lst = myMap(S);
141 TopExp_Explorer exp(S,TopAbs_FACE);
142 for (; exp.More(); exp.Next()) {
143 if (exp.Current().IsSame(myShape)) {
148 BRepCheck::Add(lst,BRepCheck_SubshapeNotInShape);
153 lst.Append(BRepCheck_NoError);
158 //=======================================================================
161 //=======================================================================
163 void BRepCheck_Face::Blind()
166 // nothing more than in the minimum
167 myBlind = Standard_True;
172 //=======================================================================
173 //function : IntersectWires
175 //=======================================================================
177 BRepCheck_Status BRepCheck_Face::IntersectWires(const Standard_Boolean Update)
181 BRepCheck::Add(myMap(myShape),myIntres);
186 myIntdone = Standard_True;
187 myIntres = BRepCheck_NoError;
188 // This method has to be called by an analyzer. It is assumed that
189 // each edge has a correct 2d representation on the face.
191 TopExp_Explorer exp1,exp2;
193 // the wires are mapped
194 exp1.Init(myShape.Oriented(TopAbs_FORWARD),TopAbs_WIRE);
195 TopTools_ListOfShape theListOfShape;
196 while (exp1.More()) {
197 if (!myMapImb.IsBound(exp1.Current())) {
198 myMapImb.Bind(exp1.Current(), theListOfShape);
200 else { // the same wire is met twice...
201 myIntres = BRepCheck_RedundantWire;
203 BRepCheck::Add(myMap(myShape),myIntres);
210 Geom2dAdaptor_Curve aC;
211 Standard_Real aFirst, aLast;
212 DataMapOfShapeBox2d aMapShapeBox2d;
213 for (exp1.Init (myShape, TopAbs_WIRE); exp1.More(); exp1.Next())
215 const TopoDS_Wire& aWire = TopoDS::Wire (exp1.Current());
216 // create 2d boxes for all edges from wire
218 for (exp2.Init (aWire, TopAbs_EDGE); exp2.More(); exp2.Next())
220 const TopoDS_Edge& anEdge = TopoDS::Edge (exp2.Current());
221 aC.Load (BRep_Tool::CurveOnSurface (anEdge, TopoDS::Face (myShape), aFirst, aLast));
222 // To avoid exeption in Segment if C1 is BSpline
223 if (aC.FirstParameter() > aFirst)
225 aFirst = aC.FirstParameter();
227 if (aC.LastParameter() < aLast)
229 aLast = aC.LastParameter();
232 BndLib_Add2dCurve::Add (aC, aFirst, aLast, 0., aBoxE);
233 aMapShapeBox2d.Bind (anEdge, aBoxE);
236 aMapShapeBox2d.Bind (aWire, aBoxW);
239 Standard_Integer Nbwire, Index,Indexbis;
240 Nbwire = myMapImb.Extent();
243 while (Index < Nbwire) {
244 for (exp1.Init(myShape,TopAbs_WIRE),Indexbis = 0;
245 exp1.More();exp1.Next()) {
247 if (Indexbis == Index) {
251 TopoDS_Wire wir1 = TopoDS::Wire(exp1.Current());
252 // to reduce the number of calls Intersect(wir1,wir2)
253 Bnd_Box2d aBox1, aBox2;
254 if (aMapShapeBox2d.IsBound (wir1))
256 aBox1 = aMapShapeBox2d (wir1);
259 for (; exp1.More(); exp1.Next()) {
260 const TopoDS_Wire& wir2 = TopoDS::Wire(exp1.Current());
261 if (aMapShapeBox2d.IsBound (wir2))
263 aBox2 = aMapShapeBox2d (wir2);
265 if (!aBox1.IsVoid() && !aBox2.IsVoid() && aBox1.IsOut (aBox2))
269 if (Intersect(wir1,wir2,TopoDS::Face(myShape), aMapShapeBox2d)) {
270 myIntres = BRepCheck_IntersectingWires;
272 BRepCheck::Add(myMap(myShape),myIntres);
280 BRepCheck::Add(myMap(myShape),myIntres);
286 //=======================================================================
287 //function : ClassifyWires
289 //=======================================================================
291 BRepCheck_Status BRepCheck_Face::ClassifyWires(const Standard_Boolean Update)
293 // It is assumed that each wire does not intersect any other one.
296 BRepCheck::Add(myMap(myShape),myImbres);
301 myImbdone = Standard_True;
302 myImbres = IntersectWires();
303 if (myImbres != BRepCheck_NoError) {
305 BRepCheck::Add(myMap(myShape),myImbres);
310 Standard_Integer Nbwire = myMapImb.Extent();
313 BRepCheck::Add(myMap(myShape),myImbres);
319 TopExp_Explorer exp1,exp2;
320 TopTools_ListOfShape theListOfShape;
321 for (exp1.Init(myShape.Oriented(TopAbs_FORWARD),TopAbs_WIRE);
322 exp1.More();exp1.Next()) {
324 const TopoDS_Wire& wir1 = TopoDS::Wire(exp1.Current());
325 TopoDS_Shape aLocalShape = myShape.EmptyCopied();
326 TopoDS_Face newFace = TopoDS::Face(aLocalShape);
327 // TopoDS_Face newFace = TopoDS::Face(myShape.EmptyCopied());
329 newFace.Orientation(TopAbs_FORWARD);
332 BRepTopAdaptor_FClass2d FClass2d(newFace,Precision::PConfusion());
333 Standard_Boolean WireBienOriente = Standard_False;
334 if(FClass2d.PerformInfinitePoint() != TopAbs_OUT) {
335 WireBienOriente=Standard_True;
336 // the given wire defines a hole
337 myMapImb.UnBind(wir1);
338 myMapImb.Bind(wir1.Reversed(), theListOfShape);
341 for (exp2.Init(myShape.Oriented(TopAbs_FORWARD),TopAbs_WIRE);
342 exp2.More();exp2.Next()) {
343 const TopoDS_Wire& wir2 = TopoDS::Wire(exp2.Current());
344 if (!wir2.IsSame(wir1)) {
346 if (IsInside(wir2,WireBienOriente,FClass2d,newFace)) {
347 myMapImb(wir1).Append(wir2);
352 // It is required to have 1 wire that contains all others, and the others should not
353 // contain anything (case solid ended) or
354 // the wires do not contain anything : in this case the wires should be
355 // holes in an infinite face.
357 for (TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itm(myMapImb);
360 if (!itm.Value().IsEmpty()) {
362 Wext = TopoDS::Wire(itm.Key());
365 myImbres = BRepCheck_InvalidImbricationOfWires;
367 BRepCheck::Add(myMap(myShape),myImbres);
374 if (!Wext.IsNull()) {
375 // verifies that the list contains nbwire-1 elements
376 if (myMapImb(Wext).Extent() != Nbwire-1) {
377 myImbres = BRepCheck_InvalidImbricationOfWires;
379 BRepCheck::Add(myMap(myShape),myImbres);
384 // quit without errors
386 BRepCheck::Add(myMap(myShape),myImbres);
393 //=======================================================================
394 //function : OrientationOfWires
396 //=======================================================================
398 BRepCheck_Status BRepCheck_Face::OrientationOfWires
399 (const Standard_Boolean Update)
401 // WARNING : it is assumed that the edges of a wire are correctly oriented
404 Standard_Boolean Infinite = myShape.Infinite();
408 BRepCheck::Add(myMap(myShape),myOrires);
413 myOridone = Standard_True;
414 myOrires = ClassifyWires();
415 if (myOrires != BRepCheck_NoError) {
417 BRepCheck::Add(myMap(myShape),myOrires);
422 Standard_Integer Nbwire = myMapImb.Extent();
424 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itm(myMapImb);
427 Wext = TopoDS::Wire(itm.Key());
431 for (;itm.More();itm.Next()) {
432 if (!itm.Value().IsEmpty()) {
433 Wext = TopoDS::Wire(itm.Key());
438 if (Wext.IsNull() && !Infinite) {
439 if (Nbwire>0) myOrires = BRepCheck_InvalidImbricationOfWires;
441 BRepCheck::Add(myMap(myShape),myOrires);
447 TopExp_Explorer exp(myShape.Oriented(TopAbs_FORWARD),TopAbs_WIRE);
448 for (; exp.More(); exp.Next()) {
449 const TopoDS_Wire& wir = TopoDS::Wire(exp.Current());
450 if (!Wext.IsNull() && wir.IsSame(Wext)) {
451 if (wir.Orientation() != Wext.Orientation()) {
452 //the exterior wire defines a hole
453 if( CheckThin(wir,myShape.Oriented(TopAbs_FORWARD)) )
455 myOrires = BRepCheck_BadOrientationOfSubshape;
457 BRepCheck::Add(myMap(myShape),myOrires);
463 for (itm.Reset(); itm.More(); itm.Next()) {
464 if (itm.Key().IsSame(wir)) {
468 // No control on More()
469 if (itm.Key().Orientation() == wir.Orientation()) {
470 // the given wire does not define a hole
471 myOrires = BRepCheck_BadOrientationOfSubshape;
473 BRepCheck::Add(myMap(myShape),myOrires);
479 // quit withour error
481 BRepCheck::Add(myMap(myShape),myOrires);
487 //=======================================================================
488 //function : SetUnorientable
490 //=======================================================================
492 void BRepCheck_Face::SetUnorientable()
494 BRepCheck::Add(myMap(myShape),BRepCheck_UnorientableShape);
498 //=======================================================================
499 //function : IsUnorientable
501 //=======================================================================
503 Standard_Boolean BRepCheck_Face::IsUnorientable() const
506 return (myOrires != BRepCheck_NoError);
508 for (BRepCheck_ListIteratorOfListOfStatus itl(myMap(myShape));
511 if (itl.Value() == BRepCheck_UnorientableShape) {
512 return Standard_True;
515 return Standard_False;
518 //=======================================================================
519 //function : GeometricControls
521 //=======================================================================
523 void BRepCheck_Face::GeometricControls(const Standard_Boolean B)
527 myIntdone = Standard_False;
528 myImbdone = Standard_False;
529 myOridone = Standard_False;
536 //=======================================================================
537 //function : GeometricControls
539 //=======================================================================
541 Standard_Boolean BRepCheck_Face::GeometricControls() const
547 //=======================================================================
548 //function : Intersect
550 //=======================================================================
552 static Standard_Boolean Intersect(const TopoDS_Wire& wir1,
553 const TopoDS_Wire& wir2,
554 const TopoDS_Face& F,
555 const DataMapOfShapeBox2d& theMapEdgeBox)
557 Standard_Real Inter2dTol = 1.e-10;
558 TopExp_Explorer exp1,exp2;
559 // BRepAdaptor_Curve2d cur1,cur2;
561 //Find common vertices of two wires - non-manifold case
562 TopTools_MapOfShape MapW1;
563 TopTools_SequenceOfShape CommonVertices;
564 for (exp1.Init( wir1, TopAbs_VERTEX ); exp1.More(); exp1.Next())
565 MapW1.Add( exp1.Current() );
566 for (exp2.Init( wir2, TopAbs_VERTEX ); exp2.More(); exp2.Next())
568 TopoDS_Shape V = exp2.Current();
569 if (MapW1.Contains( V ))
570 CommonVertices.Append( V );
573 // MSV 03.04.2002: create pure surface adaptor to avoid UVBounds computation
574 // due to performance problem
575 BRepAdaptor_Surface Surf(F,Standard_False);
577 TColgp_SequenceOfPnt PntSeq;
579 for (i = 1; i <= CommonVertices.Length(); i++)
581 TopoDS_Vertex V = TopoDS::Vertex( CommonVertices(i) );
582 gp_Pnt2d P2d = BRep_Tool::Parameters( V, F );
583 gp_Pnt P = Surf.Value( P2d.X(), P2d.Y() );
587 Geom2dAdaptor_Curve C1,C2;
588 gp_Pnt2d pfirst1,plast1,pfirst2,plast2;
589 Standard_Real first1,last1,first2,last2;
590 Geom2dInt_GInter Inter;
591 IntRes2d_Domain myDomain1,myDomain2;
592 Bnd_Box2d Box1, Box2;
594 for (exp1.Init(wir1,TopAbs_EDGE); exp1.More(); exp1.Next())
596 const TopoDS_Edge& edg1 = TopoDS::Edge(exp1.Current());
597 // cur1.Initialize(edg1,F);
598 C1.Load( BRep_Tool::CurveOnSurface(edg1,F,first1,last1) );
599 // To avoid exeption in Segment if C1 is BSpline - IFV
600 if(C1.FirstParameter() > first1) first1 = C1.FirstParameter();
601 if(C1.LastParameter() < last1 ) last1 = C1.LastParameter();
604 if (theMapEdgeBox.IsBound (edg1))
606 Box1 = theMapEdgeBox (edg1);
610 BndLib_Add2dCurve::Add( C1, first1, last1, 0., Box1 );
612 for (exp2.Init(wir2,TopAbs_EDGE); exp2.More(); exp2.Next())
614 const TopoDS_Edge& edg2 = TopoDS::Edge(exp2.Current());
615 if (!edg1.IsSame(edg2))
617 //cur2.Initialize(edg2,F);
618 C2.Load( BRep_Tool::CurveOnSurface(edg2,F,first2,last2) );
619 // To avoid exeption in Segment if C2 is BSpline - IFV
620 if(C2.FirstParameter() > first2) first2 = C2.FirstParameter();
621 if(C2.LastParameter() < last2 ) last2 = C2.LastParameter();
624 if (theMapEdgeBox.IsBound (edg2))
626 Box2 = theMapEdgeBox (edg2);
630 BndLib_Add2dCurve::Add( C2, first2, last2, 0., Box2 );
632 if (! Box1.IsOut( Box2 ))
634 BRep_Tool::UVPoints(edg1,F,pfirst1,plast1);
635 myDomain1.SetValues( pfirst1, first1, Inter2dTol, plast1, last1, Inter2dTol );
636 BRep_Tool::UVPoints(edg2,F,pfirst2,plast2);
637 myDomain2.SetValues( pfirst2, first2, Inter2dTol, plast2, last2, Inter2dTol );
638 Inter.Perform( C1, myDomain1, C2, myDomain2, Inter2dTol, Inter2dTol );
640 return Standard_True;
641 if (Inter.NbSegments() > 0)
643 if (PntSeq.IsEmpty())
644 return Standard_True;
647 Standard_Integer NbCoinc = 0;
648 for (i = 1; i <= Inter.NbSegments(); i++)
650 if (!Inter.Segment(i).HasFirstPoint() || !Inter.Segment(i).HasLastPoint())
651 return Standard_True;
652 gp_Pnt2d FirstP2d = Inter.Segment(i).FirstPoint().Value();
653 gp_Pnt2d LastP2d = Inter.Segment(i).LastPoint().Value();
654 gp_Pnt FirstP = Surf.Value( FirstP2d.X(), FirstP2d.Y() );
655 gp_Pnt LastP = Surf.Value( LastP2d.X(), LastP2d.Y() );
656 for (Standard_Integer j = 1; j <= PntSeq.Length(); j++)
658 Standard_Real tolv = BRep_Tool::Tolerance( TopoDS::Vertex(CommonVertices(j)) );
659 if (FirstP.IsEqual( PntSeq(j), tolv ) || LastP.IsEqual( PntSeq(j), tolv ))
666 if (NbCoinc == Inter.NbSegments())
667 return Standard_False;
668 return Standard_True;
671 if (Inter.NbPoints() > 0)
673 if (PntSeq.IsEmpty())
674 return Standard_True;
677 Standard_Integer NbCoinc = 0;
678 for (i = 1; i <= Inter.NbPoints(); i++)
680 gp_Pnt2d P2d = Inter.Point(i).Value();
681 gp_Pnt P = Surf.Value( P2d.X(), P2d.Y() );
682 for (Standard_Integer j = 1; j <= PntSeq.Length(); j++)
684 Standard_Real tolv = BRep_Tool::Tolerance( TopoDS::Vertex(CommonVertices(j)) );
685 if (P.IsEqual( PntSeq(j), tolv ))
692 if (NbCoinc == Inter.NbPoints())
693 return Standard_False;
694 return Standard_True;
701 return Standard_False;
705 //=======================================================================
706 //function : IsInside
708 //=======================================================================
710 static Standard_Boolean IsInside(const TopoDS_Wire& theWire,
711 const Standard_Boolean WireBienOriente,
712 const BRepTopAdaptor_FClass2d& FClass2d,
713 const TopoDS_Face& theFace)
715 Standard_Real aParameter, aFirst, aLast;
717 TopExp_Explorer anExplorer(theWire, TopAbs_EDGE);
718 for( ; anExplorer.More(); anExplorer.Next() )
720 const TopoDS_Edge& anEdge = TopoDS::Edge( anExplorer.Current() );
721 Handle(Geom2d_Curve) aCurve2D =
722 BRep_Tool::CurveOnSurface( anEdge, theFace, aFirst, aLast );
724 // Selects the parameter of point on the curve
725 if( !Precision::IsNegativeInfinite(aFirst) &&
726 !Precision::IsPositiveInfinite(aLast) )
728 aParameter = (aFirst + aLast) * 0.5;
730 // Edge is skipped if its parametric range is too small
731 if( Abs(aParameter - aFirst) < Precision::PConfusion() )
736 //Edge is skipped if its length is too small
737 Standard_Real aFirst3D, aLast3D;
738 Handle(Geom_Curve) aCurve = BRep_Tool::Curve( anEdge, aFirst3D, aLast3D );
739 if ( aCurve.IsNull() )
745 // Compute start point of edge
746 aCurve->D0( aFirst, aPoints[0] );
747 // Compute middle point of edge
748 aCurve->D0( (aFirst3D+aLast3D)/2., aPoints[1] );
749 if( aPoints[0].Distance(aPoints[1]) < Precision::Confusion() )
756 if( Precision::IsNegativeInfinite(aFirst) &&
757 Precision::IsPositiveInfinite(aLast) )
761 else if( Precision::IsNegativeInfinite(aFirst) )
763 aParameter = aLast - 1.;
767 aParameter = aFirst + 1.;
771 // Find point on curve (edge)
772 gp_Pnt2d aPoint2D(aCurve2D->Value(aParameter));
773 // Compute the topological position of a point relative to face
774 TopAbs_State aState = FClass2d.Perform(aPoint2D, Standard_False);
776 if( WireBienOriente )
778 return aState == TopAbs_OUT;
782 return aState == TopAbs_IN;
785 return Standard_False;
787 Standard_Boolean CheckThin(const TopoDS_Shape& w, const TopoDS_Shape& f)
789 TopoDS_Face aF = TopoDS::Face(f);
790 TopoDS_Wire aW = TopoDS::Wire(w);
792 Standard_Integer nbE = 0;
793 TopTools_ListOfShape lE;
794 TopExp_Explorer exp(aW,TopAbs_EDGE);
795 for(; exp.More(); exp.Next()) {
796 const TopoDS_Shape& s = exp.Current();
801 if( nbE != 2 ) return Standard_False;
802 TopoDS_Edge e1 = TopoDS::Edge(lE.First());
803 TopoDS_Edge e2 = TopoDS::Edge(lE.Last());
805 TopoDS_Vertex v1, v2, v3, v4;
806 TopExp::Vertices(e1,v1,v2);
807 TopExp::Vertices(e2,v3,v4);
809 if( v1.IsNull() || v2.IsNull() ||
810 v3.IsNull() || v4.IsNull() ) return Standard_False;
812 if( v1.IsSame(v2) || v3.IsSame(v4) )
813 return Standard_False;
815 Standard_Boolean sF = Standard_False, sL = Standard_False;
816 if( v1.IsSame(v3) || v1.IsSame(v4) ) sF = Standard_True;
817 if( v2.IsSame(v3) || v2.IsSame(v4) ) sL = Standard_True;
819 if( !sF || !sL ) return Standard_False;
821 TopAbs_Orientation e1or = e1.Orientation();
822 TopAbs_Orientation e2or = e2.Orientation();
824 Standard_Real f1 = 0., l1 = 0., f2 = 0., l2 = 0.;
825 Handle(Geom2d_Curve) pc1 = BRep_Tool::CurveOnSurface(e1,aF,f1,l1);
826 Handle(Geom2d_Curve) pc2 = BRep_Tool::CurveOnSurface(e2,aF,f2,l2);
828 if( pc1.IsNull() || pc2.IsNull() ) return Standard_False;
830 Standard_Real d1 = Abs(l1-f1)/100.;
831 Standard_Real d2 = Abs(l2-f2)/100.;
832 Standard_Real m1 = (l1+f1)*0.5;
833 Standard_Real m2 = (l2+f2)*0.5;
835 gp_Pnt2d p1f(pc1->Value(m1-d1));
836 gp_Pnt2d p1l(pc1->Value(m1+d1));
837 gp_Pnt2d p2f(pc2->Value(m2-d2));
838 gp_Pnt2d p2l(pc2->Value(m2+d2));
840 gp_Vec2d vc1(p1f,p1l);
841 gp_Vec2d vc2(p2f,p2l);
843 if( (vc1*vc2) >= 0. && e1or == e2or ) return Standard_False;
845 return Standard_True;