1 // Copyright (C) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // File: GEOMAlgo_BuilderSolid.cxx
25 // Author: Peter KURNEV
27 #include <GEOMAlgo_BuilderSolid.ixx>
29 #include <gp_Pnt2d.hxx>
35 #include <Geom_Curve.hxx>
36 #include <Geom_Surface.hxx>
37 #include <Geom2d_Curve.hxx>
41 #include <TopoDS_Iterator.hxx>
42 #include <TopoDS_Face.hxx>
44 #include <TopoDS_Shape.hxx>
45 #include <TopoDS_Shell.hxx>
46 #include <TopoDS_Edge.hxx>
47 #include <TopoDS_Solid.hxx>
48 #include <TopoDS_Vertex.hxx>
49 #include <TopoDS_Compound.hxx>
51 #include <BRep_Builder.hxx>
52 #include <BRep_Tool.hxx>
53 #include <BRepTools.hxx>
54 #include <BRepClass3d_SolidClassifier.hxx>
57 #include <TopExp_Explorer.hxx>
59 #include <TopTools_MapOfShape.hxx>
60 #include <TopTools_MapIteratorOfMapOfShape.hxx>
61 #include <TopTools_MapOfOrientedShape.hxx>
62 #include <TopTools_MapIteratorOfMapOfOrientedShape.hxx>
63 #include <TopTools_ListOfShape.hxx>
64 #include <TopTools_ListIteratorOfListOfShape.hxx>
65 #include <TopTools_DataMapOfShapeShape.hxx>
66 #include <TopTools_IndexedMapOfShape.hxx>
67 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
68 #include <TopTools_DataMapOfShapeListOfShape.hxx>
69 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
71 #include <IntTools_Context.hxx>
73 #include <BOPTools_Tools2D.hxx>
74 #include <BOPTools_Tools3D.hxx>
76 #include <NMTTools_ListOfCoupleOfShape.hxx>
77 #include <NMTTools_CoupleOfShape.hxx>
78 #include <NMTTools_ListIteratorOfListOfCoupleOfShape.hxx>
80 #include <GEOMAlgo_Tools3D.hxx>
81 #include <GEOMAlgo_BuilderTools.hxx>
85 Standard_Boolean IsGrowthShell(const TopoDS_Shape& ,
86 const TopTools_IndexedMapOfShape& );
88 Standard_Boolean IsHole(const TopoDS_Shape& ,
91 Standard_Boolean IsInside(const TopoDS_Shape& ,
95 void MakeInternalShells(const TopTools_MapOfShape& ,
96 TopTools_ListOfShape& );
98 //modified by NIZNHY-PKV Tue Aug 5 15:06:50 2008f
100 Standard_Boolean IsClosedShell(const TopoDS_Shell& theShell);
101 //modified by NIZNHY-PKV Tue Aug 5 15:06:57 2008t
103 //=======================================================================
106 //=======================================================================
107 GEOMAlgo_BuilderSolid::GEOMAlgo_BuilderSolid()
109 GEOMAlgo_BuilderArea()
112 //=======================================================================
115 //=======================================================================
116 GEOMAlgo_BuilderSolid::~GEOMAlgo_BuilderSolid()
119 //=======================================================================
122 //=======================================================================
123 void GEOMAlgo_BuilderSolid::Perform()
130 TopTools_ListIteratorOfListOfShape aIt;
132 aBB.MakeCompound(aC);
133 aIt.Initialize(myShapes);
134 for(; aIt.More(); aIt.Next()) {
135 const TopoDS_Shape& aF=aIt.Value();
140 if (myContext==NULL) {
141 myErrorStatus=11;// Null Context
145 PerformShapesToAvoid();
158 PerformInternalShapes();
163 //=======================================================================
164 //function :PerformShapesToAvoid
166 //=======================================================================
167 void GEOMAlgo_BuilderSolid::PerformShapesToAvoid()
169 Standard_Boolean bFound;
170 Standard_Integer i, iCnt, aNbE, aNbF;
171 TopAbs_Orientation aOrE;
172 TopTools_IndexedDataMapOfShapeListOfShape aMEF;
173 TopTools_ListIteratorOfListOfShape aIt;
175 myShapesToAvoid.Clear();
180 bFound=Standard_False;
184 aIt.Initialize (myShapes);
185 for (; aIt.More(); aIt.Next()) {
186 const TopoDS_Shape& aF=aIt.Value();
187 if (!myShapesToAvoid.Contains(aF)) {
188 TopExp::MapShapesAndAncestors(aF, TopAbs_EDGE, TopAbs_FACE, aMEF);
197 for (i=1; i<=aNbE; ++i) {
198 const TopoDS_Edge& aE=TopoDS::Edge(aMEF.FindKey(i));
199 if (BRep_Tool::Degenerated(aE)) {
203 TopTools_ListOfShape& aLF=aMEF.ChangeFromKey(aE);
210 aOrE=aE.Orientation();
212 const TopoDS_Face& aF1=TopoDS::Face(aLF.First());
214 if (aOrE==TopAbs_INTERNAL) {
217 bFound=Standard_True;
218 myShapesToAvoid.Add(aF1);
221 const TopoDS_Face& aF2=TopoDS::Face(aLF.Last());
222 if (aF2.IsSame(aF1)) {
223 if (BRep_Tool::IsClosed(aE, aF1)) {
227 if (aOrE==TopAbs_INTERNAL) {
231 bFound=Standard_True;
232 myShapesToAvoid.Add(aF1);
233 myShapesToAvoid.Add(aF2);
238 TopTools_ListIteratorOfListOfShape aItLF;
240 aItLF.Initialize (aLF);
241 for (; aItLF.More(); aItLF.Next()) {
242 const TopoDS_Shape& aFx=aItLF.Value();
247 }// for (i=1; i<=aNbE; ++i) {
255 //=======================================================================
256 //function : PerformLoops
258 //=======================================================================
259 void GEOMAlgo_BuilderSolid::PerformLoops()
265 Standard_Integer aNbLF, aNbOff, aNbFP, aNbFA;
266 TopAbs_Orientation anOr;
269 NMTTools_CoupleOfShape aCSOff;
270 TopTools_MapOfOrientedShape AddedFacesMap;//, aMFP;
271 TopTools_IndexedDataMapOfShapeListOfShape aEFMap, aMEFP;
272 TopTools_ListIteratorOfListOfShape aItF, aIt;
273 TopTools_MapIteratorOfMapOfOrientedShape aItM;
274 TopoDS_Iterator aItS;
276 //=================================================
280 aItF.Initialize (myShapes);
281 for (; aItF.More(); aItF.Next()) {
282 const TopoDS_Shape& aFF = aItF.Value();
283 TopExp::MapShapesAndAncestors(aFF, TopAbs_EDGE, TopAbs_FACE, aEFMap);
286 aItF.Initialize (myShapes);
287 for (; aItF.More(); aItF.Next()) {
288 const TopoDS_Shape& aFF = aItF.Value();
289 if (myShapesToAvoid.Contains(aFF)) {
292 if (!AddedFacesMap.Add(aFF)) {
298 aBB.MakeShell(aShell);
299 aBB.Add(aShell, aFF);
302 TopExp::MapShapesAndAncestors(aFF, TopAbs_EDGE, TopAbs_FACE, aMEFP);
304 // loop on faces added to Shell; add their neighbor faces to Shell and so on
305 TopoDS_Iterator aItAddedF (aShell);
306 for (; aItAddedF.More(); aItAddedF.Next()) {
307 const TopoDS_Face& aF = TopoDS::Face(aItAddedF.Value());
309 // loop on edges of aF; find a good neighbor face of aF by aE
310 TopExp_Explorer aEdgeExp(aF, TopAbs_EDGE);
311 for (; aEdgeExp.More(); aEdgeExp.Next()) {
312 const TopoDS_Edge& aE = TopoDS::Edge(aEdgeExp.Current());
315 if (aMEFP.Contains(aE)) {
316 const TopTools_ListOfShape& aLFP=aMEFP.FindFromKey(aE);
323 anOr=aE.Orientation();
324 if (anOr==TopAbs_INTERNAL) {
328 if (BRep_Tool::Degenerated(aE)) {
332 // candidate faces list
333 const TopTools_ListOfShape& aLF=aEFMap.FindFromKey(aE);
339 // try to select one of neighbors
340 // check if a face already added to Shell shares E
341 Standard_Boolean bFound;
342 TopTools_ListIteratorOfListOfShape aItLF;
343 NMTTools_ListOfCoupleOfShape aLCSOff;
345 aItLF.Initialize(aLF);
346 for (; aItLF.More(); aItLF.Next()) {
347 const TopoDS_Face& aFL=TopoDS::Face(aItLF.Value());
348 if (myShapesToAvoid.Contains(aFL)) {
351 if (aF.IsSame(aFL)) {
354 if (AddedFacesMap.Contains(aFL)){
358 bFound=GEOMAlgo_Tools3D::GetEdgeOff(aE, aFL, aEL);
363 aCSOff.SetShape1(aEL);
364 aCSOff.SetShape2(aFL);
365 aLCSOff.Append(aCSOff);
366 }//for (; aItLF.More(); aItLF.Next()) {
368 aNbOff=aLCSOff.Extent();
375 aSelF=TopoDS::Face(aLCSOff.First().Shape2());
378 GEOMAlgo_Tools3D::GetFaceOff(aE, aF, aLCSOff, aSelF);
381 if (!aSelF.IsNull() && AddedFacesMap.Add(aSelF)) {
382 aBB.Add(aShell, aSelF);
383 TopExp::MapShapesAndAncestors(aSelF, TopAbs_EDGE, TopAbs_FACE, aMEFP);
385 } // for (; aEdgeExp.More(); aEdgeExp.Next()) {
386 } //for (; aItAddedF.More(); aItAddedF.Next()) {
387 //modified by NIZNHY-PKV Tue Aug 5 15:07:08 2008f
388 //myLoops.Append(aShell);
389 if (IsClosedShell(aShell)) {
390 myLoops.Append(aShell);
394 TopoDS_Iterator aItS;
395 aItS.Initialize(aShell);
396 for (; aItS.More(); aItS.Next()) {
397 const TopoDS_Shape& aFs=aItS.Value();
402 //modified by NIZNHY-PKV Tue Aug 5 15:07:30 2008t
403 } // for (; aItF.More(); aItF.Next()) {
404 //modified by NIZNHY-PKV Tue Aug 5 15:07:35 2008f
407 TopTools_MapOfOrientedShape aMP;
409 // a. collect all edges that are in loops
410 aIt.Initialize (myLoops);
411 for (; aIt.More(); aIt.Next()) {
412 const TopoDS_Shape& aS=aIt.Value();
414 for (; aItS.More(); aItS.Next()) {
415 const TopoDS_Shape& aF=aItS.Value();
420 // b. collect all edges that are to avoid
421 aItM.Initialize(myShapesToAvoid);
422 for (; aItM.More(); aItM.Next()) {
423 const TopoDS_Shape& aF=aItM.Key();
427 // c. add all edges that are not processed to myShapesToAvoid
428 aIt.Initialize (myShapes);
429 for (; aIt.More(); aIt.Next()) {
430 const TopoDS_Shape& aF=aIt.Value();
431 if (!aMP.Contains(aF)) {
432 myShapesToAvoid.Add(aF);
435 //modified by NIZNHY-PKV Tue Aug 5 15:07:44 2008t
436 //=================================================
440 myLoopsInternal.Clear();
443 AddedFacesMap.Clear();
445 aNbFA=myShapesToAvoid.Extent();
447 aItM.Initialize(myShapesToAvoid);
448 for (; aItM.More(); aItM.Next()) {
449 const TopoDS_Shape& aFF=aItM.Key();
450 TopExp::MapShapesAndAncestors(aFF, TopAbs_EDGE, TopAbs_FACE, aEFMap);
453 aItM.Initialize(myShapesToAvoid);
454 for (; aItM.More(); aItM.Next()) {
455 const TopoDS_Shape& aFF=aItM.Key();
456 if (!AddedFacesMap.Add(aFF)) {
462 aBB.MakeShell(aShell);
463 aBB.Add(aShell, aFF);
465 TopoDS_Iterator aItAddedF (aShell);
466 for (; aItAddedF.More(); aItAddedF.Next()) {
467 const TopoDS_Face& aF = TopoDS::Face(aItAddedF.Value());
469 TopExp_Explorer aEdgeExp(aF, TopAbs_EDGE);
470 for (; aEdgeExp.More(); aEdgeExp.Next()) {
471 const TopoDS_Edge& aE = TopoDS::Edge(aEdgeExp.Current());
472 const TopTools_ListOfShape& aLF=aEFMap.FindFromKey(aE);
473 aItF.Initialize(aLF);
474 for (; aItF.More(); aItF.Next()) {
475 const TopoDS_Face& aFL=TopoDS::Face(aItF.Value());
476 if (AddedFacesMap.Add(aFL)){
477 aBB.Add(aShell, aFL);
482 myLoopsInternal.Append(aShell);
485 //=======================================================================
486 //function : PerformAreas
488 //=======================================================================
489 void GEOMAlgo_BuilderSolid::PerformAreas()
493 Standard_Boolean bIsGrowthShell, bIsHole;
494 TopTools_ListOfShape aNewSolids, aHoleShells;
495 TopoDS_Shape anInfinitePointShape;
496 TopTools_DataMapOfShapeShape aInOutMap;
497 TopTools_DataMapOfShapeListOfShape aMSH;
498 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItMSH;
499 TopTools_ListIteratorOfListOfShape aShellIt, aSolidIt;
500 TopTools_IndexedMapOfShape aMHF;
505 // Draft solids [aNewSolids]
506 aShellIt.Initialize(myLoops);
507 for ( ; aShellIt.More(); aShellIt.Next()) {
508 const TopoDS_Shape& aShell = aShellIt.Value();
510 bIsGrowthShell=IsGrowthShell(aShell, aMHF);
511 if (bIsGrowthShell) {
512 // make a growth solid from a shell
514 aBB.MakeSolid(Solid);
515 aBB.Add (Solid, aShell);
517 aNewSolids.Append (Solid);
520 // check if a shell is a hole
522 bIsHole=IsHole(aShell, myContext);
523 //bIsHole=GEOMAlgo_BuilderTools::IsHole(aShell);
526 aHoleShells.Append(aShell);
527 TopExp::MapShapes(aShell, TopAbs_FACE, aMHF);
530 // make a growth solid from a shell
532 aBB.MakeSolid(Solid);
533 aBB.Add (Solid, aShell);
535 aNewSolids.Append (Solid);
540 // 2. Find outer growth shell that is most close to each hole shell
541 aShellIt.Initialize(aHoleShells);
542 for (; aShellIt.More(); aShellIt.Next()) {
543 const TopoDS_Shape& aHole = aShellIt.Value();
545 aSolidIt.Initialize(aNewSolids);
546 for ( ; aSolidIt.More(); aSolidIt.Next()) {
547 const TopoDS_Shape& aSolid = aSolidIt.Value();
549 if (!IsInside(aHole, aSolid, myContext)){
553 if ( aInOutMap.IsBound (aHole)){
554 const TopoDS_Shape& aSolid2 = aInOutMap(aHole);
555 if (IsInside(aSolid, aSolid2, myContext)) {
556 aInOutMap.UnBind(aHole);
557 aInOutMap.Bind (aHole, aSolid);
561 aInOutMap.Bind (aHole, aSolid);
565 // Add aHole to a map Solid/ListOfHoles [aMSH]
566 if (aInOutMap.IsBound(aHole)){
567 const TopoDS_Shape& aSolid=aInOutMap(aHole);
568 if (aMSH.IsBound(aSolid)) {
569 TopTools_ListOfShape& aLH=aMSH.ChangeFind(aSolid);
573 TopTools_ListOfShape aLH;
575 aMSH.Bind(aSolid, aLH);
577 //aBB.Add (aSolid, aHole);
579 }// for (; aShellIt.More(); aShellIt.Next()) {
581 // 3. Add aHoles to Solids
582 aItMSH.Initialize(aMSH);
583 for (; aItMSH.More(); aItMSH.Next()) {
584 TopoDS_Solid aSolid=TopoDS::Solid(aItMSH.Key());
586 const TopTools_ListOfShape& aLH=aItMSH.Value();
587 aShellIt.Initialize(aLH);
588 for (; aShellIt.More(); aShellIt.Next()) {
589 const TopoDS_Shape& aHole = aShellIt.Value();
590 aBB.Add (aSolid, aHole);
594 BRepClass3d_SolidClassifier& aSC=myContext->SolidClassifier(aSolid);
599 // These aNewSolids are draft solids that
600 // do not contain any internal shapes
602 myAreas.Append(aNewSolids);
604 //=======================================================================
605 //function : PerformInternalShapes
607 //=======================================================================
608 void GEOMAlgo_BuilderSolid::PerformInternalShapes()
612 Standard_Integer aNbFI=myLoopsInternal.Extent();
613 if (!aNbFI) {// nothing to do
618 TopTools_ListIteratorOfListOfShape aShellIt, aSolidIt;
620 TopTools_MapOfShape aMF, aMFP;
621 TopTools_MapIteratorOfMapOfShape aItMF;
622 TopTools_IndexedDataMapOfShapeListOfShape aMEF;
623 TopTools_ListOfShape aLSI;
625 // 1. All internal faces
626 aShellIt.Initialize(myLoopsInternal);
627 for (; aShellIt.More(); aShellIt.Next()) {
628 const TopoDS_Shape& aShell=aShellIt.Value();
629 aIt.Initialize(aShell);
630 for (; aIt.More(); aIt.Next()) {
631 const TopoDS_Shape& aF=aIt.Value();
638 aSolidIt.Initialize(myAreas);
639 for ( ; aSolidIt.More(); aSolidIt.Next()) {
640 TopoDS_Solid& aSolid=TopoDS::Solid(aSolidIt.Value());
643 TopExp::MapShapesAndAncestors(aSolid, TopAbs_EDGE, TopAbs_FACE, aMEF);
645 // 2.1 Separate faces to process aMFP
647 aItMF.Initialize(aMF);
648 for (; aItMF.More(); aItMF.Next()) {
649 const TopoDS_Face& aF=TopoDS::Face(aItMF.Key());
650 if (GEOMAlgo_Tools3D::IsInternalFace(aF, aSolid, aMEF, 1.e-14, *myContext)) {
655 // 2.2 Make Internal Shells
657 MakeInternalShells(aMFP, aLSI);
659 // 2.3 Add them to aSolid
660 aShellIt.Initialize(aLSI);
661 for (; aShellIt.More(); aShellIt.Next()) {
662 const TopoDS_Shape& aSI=aShellIt.Value();
663 aBB.Add (aSolid, aSI);
666 // 2.4 Remove faces aMFP from aMF
667 aItMF.Initialize(aMFP);
668 for (; aItMF.More(); aItMF.Next()) {
669 const TopoDS_Shape& aF=aItMF.Key();
677 } //for ( ; aSolidIt.More(); aSolidIt.Next()) {
680 //=======================================================================
681 //function : MakeInternalShells
683 //=======================================================================
684 void MakeInternalShells(const TopTools_MapOfShape& theMF,
685 TopTools_ListOfShape& theShells)
687 TopTools_MapIteratorOfMapOfShape aItM;
688 TopTools_MapOfShape aAddedFacesMap;
689 TopTools_ListIteratorOfListOfShape aItF;
690 TopTools_IndexedDataMapOfShapeListOfShape aMEF;
693 aItM.Initialize(theMF);
694 for (; aItM.More(); aItM.Next()) {
695 const TopoDS_Shape& aF=aItM.Key();
696 TopExp::MapShapesAndAncestors(aF, TopAbs_EDGE, TopAbs_FACE, aMEF);
699 aItM.Initialize(theMF);
700 for (; aItM.More(); aItM.Next()) {
701 TopoDS_Shape aFF=aItM.Key();
702 if (!aAddedFacesMap.Add(aFF)) {
708 aBB.MakeShell(aShell);
709 aFF.Orientation(TopAbs_INTERNAL);
710 aBB.Add(aShell, aFF);
712 TopoDS_Iterator aItAddedF (aShell);
713 for (; aItAddedF.More(); aItAddedF.Next()) {
714 const TopoDS_Shape& aF =aItAddedF.Value();
716 TopExp_Explorer aEdgeExp(aF, TopAbs_EDGE);
717 for (; aEdgeExp.More(); aEdgeExp.Next()) {
718 const TopoDS_Shape& aE =aEdgeExp.Current();
719 const TopTools_ListOfShape& aLF=aMEF.FindFromKey(aE);
720 aItF.Initialize(aLF);
721 for (; aItF.More(); aItF.Next()) {
722 TopoDS_Shape aFL=aItF.Value();
723 if (aAddedFacesMap.Add(aFL)){
724 aFL.Orientation(TopAbs_INTERNAL);
725 aBB.Add(aShell, aFL);
730 theShells.Append(aShell);
733 //=======================================================================
736 //=======================================================================
737 Standard_Boolean IsHole(const TopoDS_Shape& theS2,
738 IntTools_PContext& theContext)
740 TopoDS_Solid *pS2=(TopoDS_Solid *)&theS2;
741 BRepClass3d_SolidClassifier& aClsf=theContext->SolidClassifier(*pS2);
743 aClsf.PerformInfinitePoint(::RealSmall());
745 return (aClsf.State()==TopAbs_IN);
747 //=======================================================================
748 //function : IsInside
750 //=======================================================================
751 Standard_Boolean IsInside(const TopoDS_Shape& theS1,
752 const TopoDS_Shape& theS2,
753 IntTools_PContext& theContext)
755 TopExp_Explorer aExp;
758 TopoDS_Solid *pS2=(TopoDS_Solid *)&theS2;
760 aExp.Init(theS1, TopAbs_FACE);
762 BRepClass3d_SolidClassifier& aClsf=theContext->SolidClassifier(*pS2);
763 aClsf.PerformInfinitePoint(::RealSmall());
764 aState=aClsf.State();
767 TopTools_IndexedMapOfShape aBounds;
768 const TopoDS_Face& aF = TopoDS::Face(aExp.Current());
769 aState=GEOMAlgo_Tools3D::ComputeState(aF, *pS2, 1.e-14, aBounds, *theContext);
771 return (aState==TopAbs_IN);
773 //=======================================================================
774 //function : IsGrowthShell
776 //=======================================================================
777 Standard_Boolean IsGrowthShell(const TopoDS_Shape& theShell,
778 const TopTools_IndexedMapOfShape& theMHF)
780 Standard_Boolean bRet;
784 if (theMHF.Extent()) {
785 aIt.Initialize(theShell);
786 for(; aIt.More(); aIt.Next()) {
787 const TopoDS_Shape& aF=aIt.Value();
788 if (theMHF.Contains(aF)) {
795 //modified by NIZNHY-PKV Tue Aug 5 15:07:50 2008f
796 //=======================================================================
797 //function : IsClosedShell
799 //=======================================================================
800 Standard_Boolean IsClosedShell(const TopoDS_Shell& theShell)
802 Standard_Integer aNbE;
803 Standard_Boolean bRet;
805 TopExp_Explorer aExp;
806 TopTools_MapOfShape aM;
809 aIt.Initialize(theShell);
810 for(; aIt.More(); aIt.Next()) {
811 const TopoDS_Face& aF=TopoDS::Face(aIt.Value());
812 aExp.Init(aF, TopAbs_EDGE);
813 for (; aExp.More(); aExp.Next()) {
814 const TopoDS_Edge& aE=TopoDS::Edge(aExp.Current());
815 if (BRep_Tool::Degenerated(aE)) {
819 if (BRep_Tool::IsClosed(aE, aF)) {
823 if (aE.Orientation()==TopAbs_INTERNAL) {
838 //modified by NIZNHY-PKV Tue Aug 5 15:08:07 2008t
839 //BRepTools::Write(aFF, "ff");