0024167: Compiler warnings 'unreacheable code' and 'conditional expression is constan...
[occt.git] / src / BRepCheck / BRepCheck_Face.cxx
CommitLineData
b311480e 1// Created on: 1995-12-15
2// Created by: Jacques GOUSSARD
3// Copyright (c) 1995-1999 Matra Datavision
4// Copyright (c) 1999-2012 OPEN CASCADE SAS
5//
6// The content of this file is subject to the Open CASCADE Technology Public
7// License Version 6.5 (the "License"). You may not use the content of this file
8// except in compliance with the License. Please obtain a copy of the License
9// at http://www.opencascade.org and read it completely before using this file.
10//
11// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13//
14// The Original Code and all software distributed under the License is
15// distributed on an "AS IS" basis, without warranty of any kind, and the
16// Initial Developer hereby disclaims all such warranties, including without
17// limitation, any warranties of merchantability, fitness for a particular
18// purpose or non-infringement. Please see the License for the specific terms
19// and conditions governing the rights and limitations under the License.
20
7fd59977 21
22
23#include <BRepCheck_Face.ixx>
24
25#include <BRepCheck_ListOfStatus.hxx>
26#include <BRepCheck_ListIteratorOfListOfStatus.hxx>
27
28#include <BRep_TFace.hxx>
29#include <BRep_Builder.hxx>
30#include <BRep_Tool.hxx>
31
32#include <TopExp.hxx>
33#include <TopExp_Explorer.hxx>
34
35#include <TopTools_ListOfShape.hxx>
36#include <TopTools_ListIteratorOfListOfShape.hxx>
37#include <TopTools_DataMapOfShapeListOfShape.hxx>
38#include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
39
40//#include <BRepAdaptor_Curve2d.hxx>
41#include <BRepClass_FaceClassifier.hxx>
42//#include <Geom2dInt_GInter.hxx>
43#include <Geom2d_Curve.hxx>
44#include <GProp_GProps.hxx>
45
46#include <IntRes2d_Domain.hxx>
47#include <Geom2dInt_GInter.hxx>
48#include <Geom2dAdaptor_Curve.hxx>
49#include <gp_Pnt2d.hxx>
50
51
52
53#include <BRepCheck.hxx>
54#include <Precision.hxx>
55#include <TopoDS.hxx>
56#include <TopoDS_Wire.hxx>
57
58#include <BRepTopAdaptor_FClass2d.hxx>
59#include <TopAbs_State.hxx>
60
61#include <Bnd_Box2d.hxx>
62#include <BndLib_Add2dCurve.hxx>
63#include <TopTools_MapOfShape.hxx>
64#include <TopTools_SequenceOfShape.hxx>
65#include <TColgp_SequenceOfPnt.hxx>
66#include <TopoDS_Vertex.hxx>
67#include <IntRes2d_IntersectionPoint.hxx>
68#include <IntRes2d_IntersectionSegment.hxx>
69#include <BRepAdaptor_HSurface.hxx>
70
71
72static Standard_Boolean Intersect(const TopoDS_Wire&,
73 const TopoDS_Wire&,
74 const TopoDS_Face&);
75
76
77static Standard_Boolean IsInside(const TopoDS_Wire& wir,
78 const Standard_Boolean Inside,
79 const BRepTopAdaptor_FClass2d& FClass2d,
80 const TopoDS_Face& F);
81
82static Standard_Boolean CheckThin(const TopoDS_Shape& w,
83 const TopoDS_Shape& f);
84
85//=======================================================================
86//function : BRepCheck_Face
87//purpose :
88//=======================================================================
89
90BRepCheck_Face::BRepCheck_Face (const TopoDS_Face& F)
91{
92 Init(F);
93 myIntdone = Standard_False;
94 myImbdone = Standard_False;
95 myOridone = Standard_False;
96 myGctrl = Standard_True;
97}
98
99//=======================================================================
100//function : Minimum
101//purpose :
102//=======================================================================
103
104void BRepCheck_Face::Minimum()
105{
106 if (!myMin) {
107 BRepCheck_ListOfStatus thelist;
108 myMap.Bind(myShape, thelist);
109 BRepCheck_ListOfStatus& lst = myMap(myShape);
110
111 Handle(BRep_TFace)& TF = *((Handle(BRep_TFace)*) &myShape.TShape());
112 if (TF->Surface().IsNull()) {
113 BRepCheck::Add(lst,BRepCheck_NoSurface);
114 }
115 else {
116 // Flag natural restriction???
117 }
118 if (lst.IsEmpty()) {
119 lst.Append(BRepCheck_NoError);
120 }
121 myMin = Standard_True;
122 }
123}
124
125
126//=======================================================================
127//function : InContext
128//purpose :
129//=======================================================================
130
131void BRepCheck_Face::InContext(const TopoDS_Shape& S)
132{
133 if (myMap.IsBound(S)) {
134 return;
135 }
136 BRepCheck_ListOfStatus thelist;
137 myMap.Bind(S, thelist);
138
139 BRepCheck_ListOfStatus& lst = myMap(S);
140
141 TopExp_Explorer exp(S,TopAbs_FACE);
142 for (; exp.More(); exp.Next()) {
143 if (exp.Current().IsSame(myShape)) {
144 break;
145 }
146 }
147 if (!exp.More()) {
148 BRepCheck::Add(lst,BRepCheck_SubshapeNotInShape);
149 return;
150 }
151
152 if (lst.IsEmpty()) {
153 lst.Append(BRepCheck_NoError);
154 }
155}
156
157
158//=======================================================================
159//function : Blind
160//purpose :
161//=======================================================================
162
163void BRepCheck_Face::Blind()
164{
165 if (!myBlind) {
0d969553 166 // nothing more than in the minimum
7fd59977 167 myBlind = Standard_True;
168 }
169}
170
171
172//=======================================================================
173//function : IntersectWires
174//purpose :
175//=======================================================================
176
177BRepCheck_Status BRepCheck_Face::IntersectWires(const Standard_Boolean Update)
178{
179 if (myIntdone) {
180 if (Update) {
181 BRepCheck::Add(myMap(myShape),myIntres);
182 }
183 return myIntres;
184 }
185
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.
190
191 TopExp_Explorer exp1,exp2;
192
0d969553 193 // the wires are mapped
7fd59977 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);
199 }
0d969553 200 else { // the same wire is met twice...
7fd59977 201 myIntres = BRepCheck_RedundantWire;
202 if (Update) {
203 BRepCheck::Add(myMap(myShape),myIntres);
204 }
205 return myIntres;
206 }
207 exp1.Next();
208 }
209
210 Standard_Integer Nbwire, Index,Indexbis;
211 Nbwire = myMapImb.Extent();
212
213 Index = 1;
214 while (Index < Nbwire) {
215 for (exp1.Init(myShape,TopAbs_WIRE),Indexbis = 0;
216 exp1.More();exp1.Next()) {
217 Indexbis++;
218 if (Indexbis == Index) {
219 break;
220 }
221 }
222 TopoDS_Wire wir1 = TopoDS::Wire(exp1.Current());
223 exp1.Next();
224 for (; exp1.More(); exp1.Next()) {
225 const TopoDS_Wire& wir2 = TopoDS::Wire(exp1.Current());
226 if (Intersect(wir1,wir2,TopoDS::Face(myShape))) {
227 myIntres = BRepCheck_IntersectingWires;
228 if (Update) {
229 BRepCheck::Add(myMap(myShape),myIntres);
230 }
231 return myIntres;
232 }
233 }
234 Index++;
235 }
236 if (Update) {
237 BRepCheck::Add(myMap(myShape),myIntres);
238 }
239 return myIntres;
240}
241
242
243//=======================================================================
244//function : ClassifyWires
245//purpose :
246//=======================================================================
247
248BRepCheck_Status BRepCheck_Face::ClassifyWires(const Standard_Boolean Update)
249{
250 // It is assumed that each wire does not intersect any other one.
251 if (myImbdone) {
252 if (Update) {
253 BRepCheck::Add(myMap(myShape),myImbres);
254 }
255 return myImbres;
256 }
257
258 myImbdone = Standard_True;
259 myImbres = IntersectWires();
260 if (myImbres != BRepCheck_NoError) {
261 if (Update) {
262 BRepCheck::Add(myMap(myShape),myImbres);
263 }
264 return myImbres;
265 }
266
267 Standard_Integer Nbwire = myMapImb.Extent();
268 if (Nbwire < 1) {
269 if (Update) {
270 BRepCheck::Add(myMap(myShape),myImbres);
271 }
272 return myImbres;
273 }
274
275 BRep_Builder B;
276 TopExp_Explorer exp1,exp2;
277 TopTools_ListOfShape theListOfShape;
278 for (exp1.Init(myShape.Oriented(TopAbs_FORWARD),TopAbs_WIRE);
279 exp1.More();exp1.Next()) {
280
281 const TopoDS_Wire& wir1 = TopoDS::Wire(exp1.Current());
282 TopoDS_Shape aLocalShape = myShape.EmptyCopied();
283 TopoDS_Face newFace = TopoDS::Face(aLocalShape);
284// TopoDS_Face newFace = TopoDS::Face(myShape.EmptyCopied());
6e6cd5d9 285
7fd59977 286 newFace.Orientation(TopAbs_FORWARD);
287 B.Add(newFace,wir1);
288
289 BRepTopAdaptor_FClass2d FClass2d(newFace,Precision::PConfusion());
290 Standard_Boolean WireBienOriente = Standard_False;
291 if(FClass2d.PerformInfinitePoint() != TopAbs_OUT) {
292 WireBienOriente=Standard_True;
0d969553 293 // the given wire defines a hole
7fd59977 294 myMapImb.UnBind(wir1);
295 myMapImb.Bind(wir1.Reversed(), theListOfShape);
296 }
297
298 for (exp2.Init(myShape.Oriented(TopAbs_FORWARD),TopAbs_WIRE);
299 exp2.More();exp2.Next()) {
300 const TopoDS_Wire& wir2 = TopoDS::Wire(exp2.Current());
301 if (!wir2.IsSame(wir1)) {
302
303 if (IsInside(wir2,WireBienOriente,FClass2d,newFace)) {
304 myMapImb(wir1).Append(wir2);
305 }
306 }
307 }
308 }
0d969553
Y
309 // It is required to have 1 wire that contains all others, and the others should not
310 // contain anything (case solid ended) or
311 // the wires do not contain anything : in this case the wires should be
312 // holes in an infinite face.
7fd59977 313 TopoDS_Wire Wext;
314 for (TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itm(myMapImb);
315 itm.More();
316 itm.Next()) {
317 if (!itm.Value().IsEmpty()) {
318 if (Wext.IsNull()) {
319 Wext = TopoDS::Wire(itm.Key());
320 }
321 else {
322 myImbres = BRepCheck_InvalidImbricationOfWires;
323 if (Update) {
324 BRepCheck::Add(myMap(myShape),myImbres);
325 }
326 return myImbres;
327 }
328 }
329 }
330
331 if (!Wext.IsNull()) {
332 // verifies that the list contains nbwire-1 elements
333 if (myMapImb(Wext).Extent() != Nbwire-1) {
334 myImbres = BRepCheck_InvalidImbricationOfWires;
335 if (Update) {
336 BRepCheck::Add(myMap(myShape),myImbres);
337 }
338 return myImbres;
339 }
340 }
0d969553 341 // quit without errors
7fd59977 342 if (Update) {
343 BRepCheck::Add(myMap(myShape),myImbres);
344 }
345 return myImbres;
346
347}
348
349
350//=======================================================================
351//function : OrientationOfWires
352//purpose :
353//=======================================================================
354
355BRepCheck_Status BRepCheck_Face::OrientationOfWires
356 (const Standard_Boolean Update)
357{
358 // WARNING : it is assumed that the edges of a wire are correctly oriented
359
360
361 Standard_Boolean Infinite = myShape.Infinite();
362
363 if (myOridone) {
364 if (Update) {
365 BRepCheck::Add(myMap(myShape),myOrires);
366 }
367 return myOrires;
368 }
369
370 myOridone = Standard_True;
371 myOrires = ClassifyWires();
372 if (myOrires != BRepCheck_NoError) {
373 if (Update) {
374 BRepCheck::Add(myMap(myShape),myOrires);
375 }
376 return myOrires;
377 }
378
379 Standard_Integer Nbwire = myMapImb.Extent();
380 TopoDS_Wire Wext;
381 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itm(myMapImb);
382 if (Nbwire == 1) {
383 if (!Infinite) {
384 Wext = TopoDS::Wire(itm.Key());
385 }
386 }
387 else {
388 for (;itm.More();itm.Next()) {
389 if (!itm.Value().IsEmpty()) {
390 Wext = TopoDS::Wire(itm.Key());
391 }
392 }
393 }
394
395 if (Wext.IsNull() && !Infinite) {
396 if (Nbwire>0) myOrires = BRepCheck_InvalidImbricationOfWires;
397 if (Update) {
398 BRepCheck::Add(myMap(myShape),myOrires);
399 }
400 return myOrires;
401 }
402
403 // BRep_Builder B;
404 TopExp_Explorer exp(myShape.Oriented(TopAbs_FORWARD),TopAbs_WIRE);
405 for (; exp.More(); exp.Next()) {
406 const TopoDS_Wire& wir = TopoDS::Wire(exp.Current());
407 if (!Wext.IsNull() && wir.IsSame(Wext)) {
408 if (wir.Orientation() != Wext.Orientation()) {
0d969553 409 //the exterior wire defines a hole
7fd59977 410 if( CheckThin(wir,myShape.Oriented(TopAbs_FORWARD)) )
411 return myOrires;
412 myOrires = BRepCheck_BadOrientationOfSubshape;
413 if (Update) {
414 BRepCheck::Add(myMap(myShape),myOrires);
415 }
416 return myOrires;
417 }
418 }
419 else {
420 for (itm.Reset(); itm.More(); itm.Next()) {
421 if (itm.Key().IsSame(wir)) {
422 break;
423 }
424 }
0d969553 425 // No control on More()
7fd59977 426 if (itm.Key().Orientation() == wir.Orientation()) {
0d969553 427 // the given wire does not define a hole
7fd59977 428 myOrires = BRepCheck_BadOrientationOfSubshape;
429 if (Update) {
430 BRepCheck::Add(myMap(myShape),myOrires);
431 }
432 return myOrires;
433 }
434 }
435 }
0d969553 436 // quit withour error
7fd59977 437 if (Update) {
438 BRepCheck::Add(myMap(myShape),myOrires);
439 }
440 return myOrires;
441}
442
443
444//=======================================================================
445//function : SetUnorientable
446//purpose :
447//=======================================================================
448
449void BRepCheck_Face::SetUnorientable()
450{
451 BRepCheck::Add(myMap(myShape),BRepCheck_UnorientableShape);
452}
453
454
455//=======================================================================
456//function : IsUnorientable
457//purpose :
458//=======================================================================
459
460Standard_Boolean BRepCheck_Face::IsUnorientable() const
461{
462 if (myOridone) {
463 return (myOrires != BRepCheck_NoError);
464 }
465 for (BRepCheck_ListIteratorOfListOfStatus itl(myMap(myShape));
466 itl.More();
467 itl.Next()) {
468 if (itl.Value() == BRepCheck_UnorientableShape) {
469 return Standard_True;
470 }
471 }
472 return Standard_False;
473}
474
475//=======================================================================
476//function : GeometricControls
477//purpose :
478//=======================================================================
479
480void BRepCheck_Face::GeometricControls(const Standard_Boolean B)
481{
482 if (myGctrl != B) {
483 if (B) {
484 myIntdone = Standard_False;
485 myImbdone = Standard_False;
486 myOridone = Standard_False;
487 }
488 myGctrl = B;
489 }
490}
491
492
493//=======================================================================
494//function : GeometricControls
495//purpose :
496//=======================================================================
497
498Standard_Boolean BRepCheck_Face::GeometricControls() const
499{
500 return myGctrl;
501}
502
503
504//=======================================================================
505//function : Intersect
506//purpose :
507//=======================================================================
508
509static Standard_Boolean Intersect(const TopoDS_Wire& wir1,
510 const TopoDS_Wire& wir2,
511 const TopoDS_Face& F)
512{
513 Standard_Real Inter2dTol = 1.e-10;
514 TopExp_Explorer exp1,exp2;
515// BRepAdaptor_Curve2d cur1,cur2;
516
517 //Find common vertices of two wires - non-manifold case
518 TopTools_MapOfShape MapW1;
519 TopTools_SequenceOfShape CommonVertices;
520 for (exp1.Init( wir1, TopAbs_VERTEX ); exp1.More(); exp1.Next())
521 MapW1.Add( exp1.Current() );
522 for (exp2.Init( wir2, TopAbs_VERTEX ); exp2.More(); exp2.Next())
523 {
524 TopoDS_Shape V = exp2.Current();
525 if (MapW1.Contains( V ))
526 CommonVertices.Append( V );
527 }
528
529 // MSV 03.04.2002: create pure surface adaptor to avoid UVBounds computation
530 // due to performance problem
531 BRepAdaptor_Surface Surf(F,Standard_False);
532
533 TColgp_SequenceOfPnt PntSeq;
534 Standard_Integer i;
535 for (i = 1; i <= CommonVertices.Length(); i++)
536 {
537 TopoDS_Vertex V = TopoDS::Vertex( CommonVertices(i) );
538 gp_Pnt2d P2d = BRep_Tool::Parameters( V, F );
539 gp_Pnt P = Surf.Value( P2d.X(), P2d.Y() );
540 PntSeq.Append( P );
541 }
542
543 Geom2dAdaptor_Curve C1,C2;
544 gp_Pnt2d pfirst1,plast1,pfirst2,plast2;
545 Standard_Real first1,last1,first2,last2;
546 Geom2dInt_GInter Inter;
547 IntRes2d_Domain myDomain1,myDomain2;
548 Bnd_Box2d Box1, Box2;
549
550 for (exp1.Init(wir1,TopAbs_EDGE); exp1.More(); exp1.Next())
551 {
552 const TopoDS_Edge& edg1 = TopoDS::Edge(exp1.Current());
553 // cur1.Initialize(edg1,F);
554 C1.Load( BRep_Tool::CurveOnSurface(edg1,F,first1,last1) );
555 // To avoid exeption in Segment if C1 is BSpline - IFV
556 if(C1.FirstParameter() > first1) first1 = C1.FirstParameter();
557 if(C1.LastParameter() < last1 ) last1 = C1.LastParameter();
558
559 BRep_Tool::UVPoints(edg1,F,pfirst1,plast1);
560 myDomain1.SetValues( pfirst1, first1, Inter2dTol, plast1, last1, Inter2dTol );
561 Box1.SetVoid();
562 BndLib_Add2dCurve::Add( C1, first1, last1, 0., Box1 );
563
564 for (exp2.Init(wir2,TopAbs_EDGE); exp2.More(); exp2.Next())
565 {
566 const TopoDS_Edge& edg2 = TopoDS::Edge(exp2.Current());
567 if (!edg1.IsSame(edg2))
568 {
569 //cur2.Initialize(edg2,F);
570 C2.Load( BRep_Tool::CurveOnSurface(edg2,F,first2,last2) );
571 // To avoid exeption in Segment if C2 is BSpline - IFV
572 if(C2.FirstParameter() > first2) first2 = C2.FirstParameter();
573 if(C2.LastParameter() < last2 ) last2 = C2.LastParameter();
574
575 Box2.SetVoid();
576 BndLib_Add2dCurve::Add( C2, first2, last2, 0., Box2 );
577 if (! Box1.IsOut( Box2 ))
578 {
579 BRep_Tool::UVPoints(edg2,F,pfirst2,plast2);
580 myDomain2.SetValues( pfirst2, first2, Inter2dTol, plast2, last2, Inter2dTol );
581 Inter.Perform( C1, myDomain1, C2, myDomain2, Inter2dTol, Inter2dTol );
582 if (!Inter.IsDone())
583 return Standard_True;
584 if (Inter.NbSegments() > 0)
585 {
586 if (PntSeq.IsEmpty())
587 return Standard_True;
588 else
589 {
590 Standard_Integer NbCoinc = 0;
591 for (i = 1; i <= Inter.NbSegments(); i++)
592 {
593 if (!Inter.Segment(i).HasFirstPoint() || !Inter.Segment(i).HasLastPoint())
594 return Standard_True;
595 gp_Pnt2d FirstP2d = Inter.Segment(i).FirstPoint().Value();
596 gp_Pnt2d LastP2d = Inter.Segment(i).LastPoint().Value();
597 gp_Pnt FirstP = Surf.Value( FirstP2d.X(), FirstP2d.Y() );
598 gp_Pnt LastP = Surf.Value( LastP2d.X(), LastP2d.Y() );
599 for (Standard_Integer j = 1; j <= PntSeq.Length(); j++)
600 {
601 Standard_Real tolv = BRep_Tool::Tolerance( TopoDS::Vertex(CommonVertices(j)) );
602 if (FirstP.IsEqual( PntSeq(j), tolv ) || LastP.IsEqual( PntSeq(j), tolv ))
603 {
604 NbCoinc++;
605 break;
606 }
607 }
608 }
609 if (NbCoinc == Inter.NbSegments())
610 return Standard_False;
611 return Standard_True;
612 }
613 }
614 if (Inter.NbPoints() > 0)
615 {
616 if (PntSeq.IsEmpty())
617 return Standard_True;
618 else
619 {
620 Standard_Integer NbCoinc = 0;
621 for (i = 1; i <= Inter.NbPoints(); i++)
622 {
623 gp_Pnt2d P2d = Inter.Point(i).Value();
624 gp_Pnt P = Surf.Value( P2d.X(), P2d.Y() );
625 for (Standard_Integer j = 1; j <= PntSeq.Length(); j++)
626 {
627 Standard_Real tolv = BRep_Tool::Tolerance( TopoDS::Vertex(CommonVertices(j)) );
628 if (P.IsEqual( PntSeq(j), tolv ))
629 {
630 NbCoinc++;
631 break;
632 }
633 }
634 }
635 if (NbCoinc == Inter.NbPoints())
636 return Standard_False;
637 return Standard_True;
638 }
639 }
640 }
641 }
642 }
643 }
644 return Standard_False;
645}
646
647
648//=======================================================================
649//function : IsInside
650//purpose :
651//=======================================================================
652
653static Standard_Boolean IsInside(const TopoDS_Wire& wir,
654 const Standard_Boolean WireBienOriente,
655 const BRepTopAdaptor_FClass2d& FClass2d,
656 const TopoDS_Face& F)
657{
658 // Standard_Real U,V;
659 TopExp_Explorer exp;
3ed30348 660 exp.Init(wir,TopAbs_EDGE);
661 if (exp.More()) {
7fd59977 662
663 const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
664 Standard_Real f,l;
665 Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(edg,F,f,l);
666 Standard_Real prm;
667
668 if (!Precision::IsNegativeInfinite(f) &&
669 !Precision::IsPositiveInfinite(l)) {
670 prm = (f+l)/2.;
671 }
672 else {
673 if (Precision::IsNegativeInfinite(f) &&
674 Precision::IsPositiveInfinite(l)){
675 prm = 0.;
676 }
677 else if (Precision::IsNegativeInfinite(f)) {
678 prm = l-1.;
679 }
680 else {
681 prm = f+1.;
682 }
683 }
684
685 gp_Pnt2d pt2d(C2d->Value(prm));
7fd59977 686
687 if(WireBienOriente) {
7fd59977 688 return(FClass2d.Perform(pt2d,Standard_False) == TopAbs_OUT);
689 }
690 else {
691 return(FClass2d.Perform(pt2d,Standard_False) == TopAbs_IN);
692 }
7fd59977 693 }
694 return Standard_False;
695}
696
697Standard_Boolean CheckThin(const TopoDS_Shape& w, const TopoDS_Shape& f)
698{
699 TopoDS_Face aF = TopoDS::Face(f);
700 TopoDS_Wire aW = TopoDS::Wire(w);
701
702 Standard_Integer nbE = 0;
703 TopTools_ListOfShape lE;
704 TopExp_Explorer exp(aW,TopAbs_EDGE);
705 for(; exp.More(); exp.Next()) {
706 const TopoDS_Shape& s = exp.Current();
707 lE.Append(s);
708 nbE++;
709 }
710
711 if( nbE != 2 ) return Standard_False;
712 TopoDS_Edge e1 = TopoDS::Edge(lE.First());
713 TopoDS_Edge e2 = TopoDS::Edge(lE.Last());
714
715 TopoDS_Vertex v1, v2, v3, v4;
716 TopExp::Vertices(e1,v1,v2);
717 TopExp::Vertices(e2,v3,v4);
718
719 if( v1.IsNull() || v2.IsNull() ||
720 v3.IsNull() || v4.IsNull() ) return Standard_False;
721
722 if( v1.IsSame(v2) || v3.IsSame(v4) )
723 return Standard_False;
724
725 Standard_Boolean sF = Standard_False, sL = Standard_False;
726 if( v1.IsSame(v3) || v1.IsSame(v4) ) sF = Standard_True;
727 if( v2.IsSame(v3) || v2.IsSame(v4) ) sL = Standard_True;
728
729 if( !sF || !sL ) return Standard_False;
730
731 TopAbs_Orientation e1or = e1.Orientation();
732 TopAbs_Orientation e2or = e2.Orientation();
733
734 Standard_Real f1 = 0., l1 = 0., f2 = 0., l2 = 0.;
735 Handle(Geom2d_Curve) pc1 = BRep_Tool::CurveOnSurface(e1,aF,f1,l1);
736 Handle(Geom2d_Curve) pc2 = BRep_Tool::CurveOnSurface(e2,aF,f2,l2);
737
738 if( pc1.IsNull() || pc2.IsNull() ) return Standard_False;
739
740 Standard_Real d1 = Abs(l1-f1)/100.;
741 Standard_Real d2 = Abs(l2-f2)/100.;
742 Standard_Real m1 = (l1+f1)*0.5;
743 Standard_Real m2 = (l2+f2)*0.5;
744
745 gp_Pnt2d p1f(pc1->Value(m1-d1));
746 gp_Pnt2d p1l(pc1->Value(m1+d1));
747 gp_Pnt2d p2f(pc2->Value(m2-d2));
748 gp_Pnt2d p2l(pc2->Value(m2+d2));
749
750 gp_Vec2d vc1(p1f,p1l);
751 gp_Vec2d vc2(p2f,p2l);
752
753 if( (vc1*vc2) >= 0. && e1or == e2or ) return Standard_False;
754
755 return Standard_True;
756}