1 // Created by: Peter KURNEV
2 // Copyright (c) 2010-2014 OPEN CASCADE SAS
3 // Copyright (c) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE
4 // Copyright (c) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, CEDRAT,
5 // EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
7 // This file is part of Open CASCADE Technology software library.
9 // This library is free software; you can redistribute it and / or modify it
10 // under the terms of the GNU Lesser General Public version 2.1 as published
11 // by the Free Software Foundation, with special exception defined in the file
12 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
13 // distribution for complete text of the license and disclaimer of any warranty.
15 // Alternatively, this file may be used under the terms of Open CASCADE
16 // commercial license or contractual agreement.
18 #include <BOPAlgo_BuilderSolid.ixx>
20 #include <gp_Pnt2d.hxx>
26 #include <Geom_Curve.hxx>
27 #include <Geom_Surface.hxx>
28 #include <Geom2d_Curve.hxx>
32 #include <TopoDS_Iterator.hxx>
33 #include <TopoDS_Face.hxx>
34 #include <TopoDS_Shape.hxx>
35 #include <TopoDS_Shell.hxx>
36 #include <TopoDS_Edge.hxx>
37 #include <TopoDS_Solid.hxx>
38 #include <TopoDS_Vertex.hxx>
39 #include <TopoDS_Compound.hxx>
41 #include <BRep_Builder.hxx>
42 #include <BRep_Tool.hxx>
43 #include <BRepTools.hxx>
44 #include <BRepClass3d_SolidClassifier.hxx>
47 #include <TopExp_Explorer.hxx>
49 #include <BOPTools_AlgoTools.hxx>
50 #include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx>
51 #include <BOPTools.hxx>
52 #include <BOPCol_ListOfShape.hxx>
53 #include <BOPCol_MapOfOrientedShape.hxx>
55 #include <NCollection_List.hxx>
57 #include <BOPCol_DataMapOfShapeShape.hxx>
58 #include <BOPCol_DataMapOfShapeListOfShape.hxx>
59 #include <BOPInt_Context.hxx>
60 #include <BOPTools_CoupleOfShape.hxx>
61 #include <BOPCol_MapOfShape.hxx>
64 Standard_Boolean IsGrowthShell(const TopoDS_Shape& ,
65 const BOPCol_IndexedMapOfShape& );
67 Standard_Boolean IsHole(const TopoDS_Shape& ,
68 Handle(BOPInt_Context)& );
70 Standard_Boolean IsInside(const TopoDS_Shape& ,
72 Handle(BOPInt_Context)& );
74 void MakeInternalShells(const BOPCol_MapOfShape& ,
75 BOPCol_ListOfShape& );
78 Standard_Boolean IsClosedShell(const TopoDS_Shell& theShell);
80 //=======================================================================
83 //=======================================================================
84 BOPAlgo_BuilderSolid::BOPAlgo_BuilderSolid()
89 //=======================================================================
92 //=======================================================================
93 BOPAlgo_BuilderSolid::BOPAlgo_BuilderSolid(const Handle(NCollection_BaseAllocator)& theAllocator)
95 BOPAlgo_BuilderArea(theAllocator)
98 //=======================================================================
101 //=======================================================================
102 BOPAlgo_BuilderSolid::~BOPAlgo_BuilderSolid()
105 //=======================================================================
108 //=======================================================================
109 void BOPAlgo_BuilderSolid::Perform()
113 if (myContext.IsNull()) {
114 //myErrorStatus=11;// Null Context
116 myContext=new BOPInt_Context;
121 BOPCol_ListIteratorOfListOfShape aIt;
123 aBB.MakeCompound(aC);
124 aIt.Initialize(myShapes);
125 for(; aIt.More(); aIt.Next()) {
126 const TopoDS_Shape& aF=aIt.Value();
131 PerformShapesToAvoid();
144 PerformInternalShapes();
149 //=======================================================================
150 //function :PerformShapesToAvoid
152 //=======================================================================
153 void BOPAlgo_BuilderSolid::PerformShapesToAvoid()
155 Standard_Boolean bFound;
156 Standard_Integer i, iCnt, aNbE, aNbF;
157 TopAbs_Orientation aOrE;
158 BOPCol_IndexedDataMapOfShapeListOfShape aMEF;
159 BOPCol_ListIteratorOfListOfShape aIt;
161 myShapesToAvoid.Clear();
166 bFound=Standard_False;
170 aIt.Initialize (myShapes);
171 for (; aIt.More(); aIt.Next()) {
172 const TopoDS_Shape& aF=aIt.Value();
173 if (!myShapesToAvoid.Contains(aF)) {
174 BOPTools::MapShapesAndAncestors(aF, TopAbs_EDGE, TopAbs_FACE, aMEF);
180 for (i=1; i<=aNbE; ++i) {
181 const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aMEF.FindKey(i)));
182 if (BRep_Tool::Degenerated(aE)) {
186 BOPCol_ListOfShape& aLF=aMEF.ChangeFromKey(aE);
192 aOrE=aE.Orientation();
194 const TopoDS_Face& aF1=(*(TopoDS_Face*)(&aLF.First()));
196 if (aOrE==TopAbs_INTERNAL) {
199 bFound=Standard_True;
200 myShapesToAvoid.Add(aF1);
203 const TopoDS_Face& aF2=(*(TopoDS_Face*)(&aLF.Last()));
204 if (aF2.IsSame(aF1)) {
205 if (BRep_Tool::IsClosed(aE, aF1)) {
209 if (aOrE==TopAbs_INTERNAL) {
213 bFound=Standard_True;
214 myShapesToAvoid.Add(aF1);
215 myShapesToAvoid.Add(aF2);
218 }// for (i=1; i<=aNbE; ++i) {
226 //=======================================================================
227 //function : PerformLoops
229 //=======================================================================
230 void BOPAlgo_BuilderSolid::PerformLoops()
236 Standard_Integer aNbLF, aNbOff, aNbFP, aNbFA;
238 TopAbs_Orientation anOr;
241 TopoDS_Iterator aItS;
243 BOPCol_ListIteratorOfListOfShape aItF, aIt;
244 BOPCol_MapIteratorOfMapOfOrientedShape aItM;
245 BOPTools_CoupleOfShape aCSOff;
247 BOPCol_MapOfOrientedShape AddedFacesMap;
248 BOPCol_IndexedDataMapOfShapeListOfShape aEFMap, aMEFP;
250 //=================================================
254 aItF.Initialize (myShapes);
255 for (; aItF.More(); aItF.Next()) {
256 const TopoDS_Shape& aFF = aItF.Value();
257 BOPTools::MapShapesAndAncestors(aFF, TopAbs_EDGE, TopAbs_FACE, aEFMap);
260 aItF.Initialize (myShapes);
261 for (i=1; aItF.More(); aItF.Next(), ++i) {
262 const TopoDS_Shape& aFF = aItF.Value();
263 if (myShapesToAvoid.Contains(aFF)) {
266 if (!AddedFacesMap.Add(aFF)) {
272 aBB.MakeShell(aShell);
273 aBB.Add(aShell, aFF);
276 BOPTools::MapShapesAndAncestors(aFF, TopAbs_EDGE, TopAbs_FACE, aMEFP);
278 // loop on faces added to Shell; add their neighbor faces to Shell and so on
279 TopoDS_Iterator aItAddedF (aShell);
280 for (; aItAddedF.More(); aItAddedF.Next()) {
281 const TopoDS_Face& aF = (*(TopoDS_Face*)(&aItAddedF.Value()));
283 // loop on edges of aF; find a good neighbor face of aF by aE
284 TopExp_Explorer aEdgeExp(aF, TopAbs_EDGE);
285 for (; aEdgeExp.More(); aEdgeExp.Next()) {
286 const TopoDS_Edge& aE = (*(TopoDS_Edge*)(&aEdgeExp.Current()));
289 if (aMEFP.Contains(aE)) {
290 const BOPCol_ListOfShape& aLFP=aMEFP.FindFromKey(aE);
297 anOr=aE.Orientation();
298 if (anOr==TopAbs_INTERNAL) {
302 if (BRep_Tool::Degenerated(aE)) {
306 // candidate faces list
307 const BOPCol_ListOfShape& aLF=aEFMap.FindFromKey(aE);
313 // try to select one of neighbors
314 // check if a face already added to Shell shares E
315 Standard_Boolean bFound;
316 BOPCol_ListIteratorOfListOfShape aItLF;
317 BOPTools_ListOfCoupleOfShape aLCSOff;
319 aItLF.Initialize(aLF);
320 for (; aItLF.More(); aItLF.Next()) {
321 const TopoDS_Face& aFL=(*(TopoDS_Face*)(&aItLF.Value()));
322 if (myShapesToAvoid.Contains(aFL)) {
325 if (aF.IsSame(aFL)) {
328 if (AddedFacesMap.Contains(aFL)){
332 bFound=BOPTools_AlgoTools::GetEdgeOff(aE, aFL, aEL);
337 aCSOff.SetShape1(aEL);
338 aCSOff.SetShape2(aFL);
339 aLCSOff.Append(aCSOff);
340 }//for (; aItLF.More(); aItLF.Next()) {
342 aNbOff=aLCSOff.Extent();
349 aSelF=(*(TopoDS_Face*)(&aLCSOff.First().Shape2()));
352 BOPTools_AlgoTools::GetFaceOff(aE, aF, aLCSOff, aSelF, myContext);
355 if (!aSelF.IsNull() && AddedFacesMap.Add(aSelF)) {
356 aBB.Add(aShell, aSelF);
357 BOPTools::MapShapesAndAncestors(aSelF, TopAbs_EDGE, TopAbs_FACE, aMEFP);
359 } // for (; aEdgeExp.More(); aEdgeExp.Next()) {
360 } //for (; aItAddedF.More(); aItAddedF.Next()) {
362 if (IsClosedShell(aShell)) {
363 myLoops.Append(aShell);
365 } // for (; aItF.More(); aItF.Next()) {
369 BOPCol_MapOfOrientedShape aMP;
371 // a. collect all edges that are in loops
372 aIt.Initialize (myLoops);
373 for (; aIt.More(); aIt.Next()) {
374 const TopoDS_Shape& aS=aIt.Value();
376 for (; aItS.More(); aItS.Next()) {
377 const TopoDS_Shape& aF=aItS.Value();
382 // b. collect all edges that are to avoid
383 aItM.Initialize(myShapesToAvoid);
384 for (; aItM.More(); aItM.Next()) {
385 const TopoDS_Shape& aF=aItM.Key();
389 // c. add all edges that are not processed to myShapesToAvoid
390 aIt.Initialize (myShapes);
391 for (; aIt.More(); aIt.Next()) {
392 const TopoDS_Shape& aF=aIt.Value();
393 if (!aMP.Contains(aF)) {
394 myShapesToAvoid.Add(aF);
397 //=================================================
401 myLoopsInternal.Clear();
404 AddedFacesMap.Clear();
406 aNbFA=myShapesToAvoid.Extent();
408 aItM.Initialize(myShapesToAvoid);
409 for (; aItM.More(); aItM.Next()) {
410 const TopoDS_Shape& aFF=aItM.Key();
411 BOPTools::MapShapesAndAncestors(aFF, TopAbs_EDGE, TopAbs_FACE, aEFMap);
414 aItM.Initialize(myShapesToAvoid);
415 for (; aItM.More(); aItM.Next()) {
416 const TopoDS_Shape& aFF=aItM.Key();
417 if (!AddedFacesMap.Add(aFF)) {
423 aBB.MakeShell(aShell);
424 aBB.Add(aShell, aFF);
426 TopoDS_Iterator aItAddedF (aShell);
427 for (; aItAddedF.More(); aItAddedF.Next()) {
428 const TopoDS_Face& aF = (*(TopoDS_Face*)(&aItAddedF.Value()));
430 TopExp_Explorer aEdgeExp(aF, TopAbs_EDGE);
431 for (; aEdgeExp.More(); aEdgeExp.Next()) {
432 const TopoDS_Edge& aE = (*(TopoDS_Edge*)(&aEdgeExp.Current()));
433 const BOPCol_ListOfShape& aLF=aEFMap.FindFromKey(aE);
434 aItF.Initialize(aLF);
435 for (; aItF.More(); aItF.Next()) {
436 const TopoDS_Face& aFL=(*(TopoDS_Face*)(&aItF.Value()));
437 if (AddedFacesMap.Add(aFL)){
438 aBB.Add(aShell, aFL);
443 myLoopsInternal.Append(aShell);
446 //=======================================================================
447 //function : PerformAreas
449 //=======================================================================
450 void BOPAlgo_BuilderSolid::PerformAreas()
454 Standard_Boolean bIsGrowthShell, bIsHole;
456 TopoDS_Shape anInfinitePointShape;
457 BOPCol_DataMapIteratorOfDataMapOfShapeListOfShape aItMSH;
458 BOPCol_ListIteratorOfListOfShape aShellIt, aSolidIt;
460 BOPCol_ListOfShape aNewSolids, aHoleShells;
461 BOPCol_DataMapOfShapeShape aInOutMap;
462 BOPCol_DataMapOfShapeListOfShape aMSH;
463 BOPCol_IndexedMapOfShape aMHF;
467 // Draft solids [aNewSolids]
468 aShellIt.Initialize(myLoops);
469 for ( ; aShellIt.More(); aShellIt.Next()) {
470 const TopoDS_Shape& aShell = aShellIt.Value();
472 bIsGrowthShell=IsGrowthShell(aShell, aMHF);
473 if (bIsGrowthShell) {
474 // make a growth solid from a shell
476 aBB.MakeSolid(Solid);
477 aBB.Add (Solid, aShell);
479 aNewSolids.Append (Solid);
482 // check if a shell is a hole
484 bIsHole=IsHole(aShell, myContext);
487 aHoleShells.Append(aShell);
488 BOPTools::MapShapes(aShell, TopAbs_FACE, aMHF);
491 // make a growth solid from a shell
493 aBB.MakeSolid(Solid);
494 aBB.Add (Solid, aShell);
496 aNewSolids.Append (Solid);
501 // 2. Find outer growth shell that is most close to each hole shell
502 aShellIt.Initialize(aHoleShells);
503 for (; aShellIt.More(); aShellIt.Next()) {
504 const TopoDS_Shape& aHole = aShellIt.Value();
506 aSolidIt.Initialize(aNewSolids);
507 for ( ; aSolidIt.More(); aSolidIt.Next()) {
508 const TopoDS_Shape& aSolid = aSolidIt.Value();
510 if (!IsInside(aHole, aSolid, myContext)){
514 if ( aInOutMap.IsBound (aHole)){
515 const TopoDS_Shape& aSolid2 = aInOutMap(aHole);
516 if (IsInside(aSolid, aSolid2, myContext)) {
517 aInOutMap.UnBind(aHole);
518 aInOutMap.Bind (aHole, aSolid);
522 aInOutMap.Bind (aHole, aSolid);
526 // Add aHole to a map Solid/ListOfHoles [aMSH]
527 if (aInOutMap.IsBound(aHole)){
528 const TopoDS_Shape& aSolid=aInOutMap(aHole);
529 if (aMSH.IsBound(aSolid)) {
530 BOPCol_ListOfShape& aLH=aMSH.ChangeFind(aSolid);
534 BOPCol_ListOfShape aLH;
536 aMSH.Bind(aSolid, aLH);
538 //aBB.Add (aSolid, aHole);
540 }// for (; aShellIt.More(); aShellIt.Next()) {
542 // 3. Add aHoles to Solids
543 aItMSH.Initialize(aMSH);
544 for (; aItMSH.More(); aItMSH.Next()) {
545 TopoDS_Solid aSolid=(*(TopoDS_Solid*)(&aItMSH.Key()));
547 const BOPCol_ListOfShape& aLH=aItMSH.Value();
548 aShellIt.Initialize(aLH);
549 for (; aShellIt.More(); aShellIt.Next()) {
550 const TopoDS_Shape& aHole = aShellIt.Value();
551 aBB.Add (aSolid, aHole);
555 BRepClass3d_SolidClassifier& aSC=myContext->SolidClassifier(aSolid);
560 // These aNewSolids are draft solids that
561 // do not contain any internal shapes
563 aShellIt.Initialize(aNewSolids);
564 for ( ; aShellIt.More(); aShellIt.Next()) {
565 const TopoDS_Shape& aSx = aShellIt.Value();
569 // Add holes that outside the solids to myAreas
570 aShellIt.Initialize(aHoleShells);
571 for (; aShellIt.More(); aShellIt.Next()) {
572 const TopoDS_Shape& aHole = aShellIt.Value();
573 if (!aInOutMap.IsBound(aHole)){
575 aBB.MakeSolid(aSolid);
576 aBB.Add (aSolid, aHole);
578 myAreas.Append(aSolid);
582 //=======================================================================
583 //function : PerformInternalShapes
585 //=======================================================================
586 void BOPAlgo_BuilderSolid::PerformInternalShapes()
590 Standard_Integer aNbFI=myLoopsInternal.Extent();
591 if (!aNbFI) {// nothing to do
597 BOPCol_ListIteratorOfListOfShape aShellIt, aSolidIt;
598 BOPCol_MapIteratorOfMapOfShape aItMF;
600 BOPCol_MapOfShape aMF, aMFP, aMFx;
601 BOPCol_IndexedDataMapOfShapeListOfShape aMEF;
602 BOPCol_ListOfShape aLSI;
604 // 1. All internal faces
605 aShellIt.Initialize(myLoopsInternal);
606 for (; aShellIt.More(); aShellIt.Next()) {
607 const TopoDS_Shape& aShell=aShellIt.Value();
608 aIt.Initialize(aShell);
609 for (; aIt.More(); aIt.Next()) {
610 const TopoDS_Shape& aF=aIt.Value();
617 aSolidIt.Initialize(myAreas);
618 for ( ; aSolidIt.More(); aSolidIt.Next()) {
619 TopoDS_Solid& aSolid=(*(TopoDS_Solid*)(&aSolidIt.Value()));
621 TopExp_Explorer anExpSol(aSolid, TopAbs_FACE);;
622 for (; anExpSol.More(); anExpSol.Next()) {
623 const TopoDS_Shape& aF = anExpSol.Current();
626 aFF.Orientation(TopAbs_FORWARD);
628 aFF.Orientation(TopAbs_REVERSED);
632 BOPTools::MapShapesAndAncestors(aSolid, TopAbs_EDGE, TopAbs_FACE, aMEF);
634 // 2.1 Separate faces to process aMFP
636 aItMF.Initialize(aMF);
637 for (; aItMF.More(); aItMF.Next()) {
638 const TopoDS_Face& aF=(*(TopoDS_Face*)(&aItMF.Key()));
639 if (!aMFx.Contains(aF)) {
640 if (BOPTools_AlgoTools::IsInternalFace(aF, aSolid, aMEF, 1.e-14, myContext)) {
647 // 2.2 Make Internal Shells
649 MakeInternalShells(aMFP, aLSI);
651 // 2.3 Add them to aSolid
652 aShellIt.Initialize(aLSI);
653 for (; aShellIt.More(); aShellIt.Next()) {
654 const TopoDS_Shape& aSI=aShellIt.Value();
655 aBB.Add (aSolid, aSI);
658 // 2.4 Remove faces aMFP from aMF
659 aItMF.Initialize(aMFP);
660 for (; aItMF.More(); aItMF.Next()) {
661 const TopoDS_Shape& aF=aItMF.Key();
669 } //for ( ; aSolidIt.More(); aSolidIt.Next()) {
672 aBB.MakeSolid(aSolid);
674 MakeInternalShells(aMF, aLSI);
675 aShellIt.Initialize(aLSI);
676 for (; aShellIt.More(); aShellIt.Next()) {
677 const TopoDS_Shape& aSI=aShellIt.Value();
678 aBB.Add (aSolid, aSI);
680 myAreas.Append(aSolid);
684 //=======================================================================
685 //function : MakeInternalShells
687 //=======================================================================
688 void MakeInternalShells(const BOPCol_MapOfShape& theMF,
689 BOPCol_ListOfShape& theShells)
691 BOPCol_ListIteratorOfListOfShape aItF;
694 BOPCol_IndexedDataMapOfShapeListOfShape aMEF;
695 BOPCol_MapIteratorOfMapOfShape aItM;
696 BOPCol_MapOfShape aAddedFacesMap;
698 aItM.Initialize(theMF);
699 for (; aItM.More(); aItM.Next()) {
700 const TopoDS_Shape& aF=aItM.Key();
701 BOPTools::MapShapesAndAncestors(aF, TopAbs_EDGE, TopAbs_FACE, aMEF);
704 aItM.Initialize(theMF);
705 for (; aItM.More(); aItM.Next()) {
706 TopoDS_Shape aFF=aItM.Key();
707 if (!aAddedFacesMap.Add(aFF)) {
713 aBB.MakeShell(aShell);
714 aFF.Orientation(TopAbs_INTERNAL);
715 aBB.Add(aShell, aFF);
717 TopoDS_Iterator aItAddedF (aShell);
718 for (; aItAddedF.More(); aItAddedF.Next()) {
719 const TopoDS_Shape& aF =aItAddedF.Value();
721 TopExp_Explorer aEdgeExp(aF, TopAbs_EDGE);
722 for (; aEdgeExp.More(); aEdgeExp.Next()) {
723 const TopoDS_Shape& aE =aEdgeExp.Current();
724 const BOPCol_ListOfShape& aLF=aMEF.FindFromKey(aE);
725 aItF.Initialize(aLF);
726 for (; aItF.More(); aItF.Next()) {
727 TopoDS_Shape aFL=aItF.Value();
728 if (aAddedFacesMap.Add(aFL)){
729 aFL.Orientation(TopAbs_INTERNAL);
730 aBB.Add(aShell, aFL);
735 theShells.Append(aShell);
738 //=======================================================================
741 //=======================================================================
742 Standard_Boolean IsHole(const TopoDS_Shape& theS2,
743 Handle(BOPInt_Context)& theContext)
745 TopoDS_Solid *pS2=(TopoDS_Solid *)&theS2;
746 BRepClass3d_SolidClassifier& aClsf=theContext->SolidClassifier(*pS2);
748 aClsf.PerformInfinitePoint(::RealSmall());
750 return (aClsf.State()==TopAbs_IN);
752 //=======================================================================
753 //function : IsInside
755 //=======================================================================
756 Standard_Boolean IsInside(const TopoDS_Shape& theS1,
757 const TopoDS_Shape& theS2,
758 Handle(BOPInt_Context)& theContext)
760 TopExp_Explorer aExp;
763 TopoDS_Solid *pS2=(TopoDS_Solid *)&theS2;
765 aExp.Init(theS1, TopAbs_FACE);
767 BRepClass3d_SolidClassifier& aClsf=theContext->SolidClassifier(*pS2);
768 aClsf.PerformInfinitePoint(::RealSmall());
769 aState=aClsf.State();
772 BOPCol_IndexedMapOfShape aBounds;
773 BOPTools::MapShapes(*pS2, TopAbs_EDGE, aBounds);
774 const TopoDS_Face& aF = (*(TopoDS_Face*)(&aExp.Current()));
775 aState=BOPTools_AlgoTools::ComputeState(aF, *pS2, 1.e-14, aBounds, theContext);
777 return (aState==TopAbs_IN);
779 //=======================================================================
780 //function : IsGrowthShell
782 //=======================================================================
783 Standard_Boolean IsGrowthShell(const TopoDS_Shape& theShell,
784 const BOPCol_IndexedMapOfShape& theMHF)
786 Standard_Boolean bRet;
790 if (theMHF.Extent()) {
791 aIt.Initialize(theShell);
792 for(; aIt.More(); aIt.Next()) {
793 const TopoDS_Shape& aF=aIt.Value();
794 if (theMHF.Contains(aF)) {
801 //=======================================================================
802 //function : IsClosedShell
804 //=======================================================================
805 Standard_Boolean IsClosedShell(const TopoDS_Shell& theShell)
807 Standard_Integer aNbE;
808 Standard_Boolean bRet;
810 TopExp_Explorer aExp;
812 BOPCol_MapOfShape aM;
815 aIt.Initialize(theShell);
816 for(; aIt.More(); aIt.Next()) {
817 const TopoDS_Face& aF=(*(TopoDS_Face*)(&aIt.Value()));
818 aExp.Init(aF, TopAbs_EDGE);
819 for (; aExp.More(); aExp.Next()) {
820 const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aExp.Current()));
821 if (BRep_Tool::Degenerated(aE)) {
825 if (aE.Orientation()==TopAbs_INTERNAL) {