mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-05-01 10:26:12 +03:00
When splitting the shell/face with internal faces/edges use the 'internal' criteria of the face to choose the way to create loops. Side effect changes: - When performing Boolean operation - move the objects located far from Origin to the Origin to increase the accuracy of intersections.
602 lines
18 KiB
C++
602 lines
18 KiB
C++
// Created by: Peter KURNEV
|
|
// Copyright (c) 1999-2014 OPEN CASCADE SAS
|
|
//
|
|
// This file is part of Open CASCADE Technology software library.
|
|
//
|
|
// This library is free software; you can redistribute it and/or modify it under
|
|
// the terms of the GNU Lesser General Public License version 2.1 as published
|
|
// by the Free Software Foundation, with special exception defined in the file
|
|
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
|
// distribution for complete text of the license and disclaimer of any warranty.
|
|
//
|
|
// Alternatively, this file may be used under the terms of Open CASCADE
|
|
// commercial license or contractual agreement.
|
|
|
|
// File: BOPAlgo_ShellSplitter.cxx
|
|
// Created: Thu Jan 16 08:33:50 2014
|
|
|
|
#include <BOPAlgo_ShellSplitter.hxx>
|
|
#include <BOPTools_AlgoTools.hxx>
|
|
#include <BOPTools_CoupleOfShape.hxx>
|
|
#include <BOPTools_Parallel.hxx>
|
|
#include <BRep_Builder.hxx>
|
|
#include <IntTools_Context.hxx>
|
|
#include <NCollection_Vector.hxx>
|
|
#include <TopExp.hxx>
|
|
#include <TopExp_Explorer.hxx>
|
|
#include <TopoDS.hxx>
|
|
#include <TopoDS_Edge.hxx>
|
|
#include <TopoDS_Shape.hxx>
|
|
#include <TopoDS_Shell.hxx>
|
|
#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
|
|
#include <TopTools_IndexedMapOfShape.hxx>
|
|
#include <TopTools_MapOfOrientedShape.hxx>
|
|
#include <TopTools_MapOfShape.hxx>
|
|
|
|
//
|
|
static
|
|
void MakeShell(const TopTools_ListOfShape& ,
|
|
TopoDS_Shell& );
|
|
//
|
|
static
|
|
void RefineShell(TopoDS_Shell& theShell,
|
|
const TopTools_IndexedDataMapOfShapeListOfShape& theMEF,
|
|
TopTools_ListOfShape& aLShX);
|
|
|
|
//=======================================================================
|
|
//class : BOPAlgo_CBK
|
|
//purpose :
|
|
//=======================================================================
|
|
class BOPAlgo_CBK {
|
|
public:
|
|
BOPAlgo_CBK() :
|
|
myPCB (NULL) {
|
|
}
|
|
//
|
|
~BOPAlgo_CBK() {
|
|
}
|
|
//
|
|
void SetConnexityBlock (const BOPTools_ConnexityBlock& aCB) {
|
|
myPCB=(BOPTools_ConnexityBlock*)&aCB;
|
|
}
|
|
//
|
|
BOPTools_ConnexityBlock& ConnexityBlock () {
|
|
return *myPCB;
|
|
}
|
|
//
|
|
void Perform() {
|
|
BOPAlgo_ShellSplitter::SplitBlock(*myPCB);
|
|
}
|
|
protected:
|
|
BOPTools_ConnexityBlock *myPCB;
|
|
};
|
|
//=======================================================================
|
|
typedef NCollection_Vector<BOPAlgo_CBK> BOPAlgo_VectorOfCBK;
|
|
|
|
//=======================================================================
|
|
//function :
|
|
//purpose :
|
|
//=======================================================================
|
|
BOPAlgo_ShellSplitter::BOPAlgo_ShellSplitter()
|
|
:
|
|
BOPAlgo_Algo(),
|
|
myStartShapes(myAllocator),
|
|
myShells(myAllocator),
|
|
myLCB(myAllocator)
|
|
{
|
|
}
|
|
//=======================================================================
|
|
//function :
|
|
//purpose :
|
|
//=======================================================================
|
|
BOPAlgo_ShellSplitter::BOPAlgo_ShellSplitter
|
|
(const Handle(NCollection_BaseAllocator)& theAllocator)
|
|
:
|
|
BOPAlgo_Algo(theAllocator),
|
|
myStartShapes(theAllocator),
|
|
myShells(theAllocator),
|
|
myLCB(myAllocator)
|
|
{
|
|
}
|
|
//=======================================================================
|
|
//function : ~
|
|
//purpose :
|
|
//=======================================================================
|
|
BOPAlgo_ShellSplitter::~BOPAlgo_ShellSplitter()
|
|
{
|
|
}
|
|
//=======================================================================
|
|
//function : AddStartElement
|
|
//purpose :
|
|
//=======================================================================
|
|
void BOPAlgo_ShellSplitter::AddStartElement(const TopoDS_Shape& aE)
|
|
{
|
|
myStartShapes.Append(aE);
|
|
}
|
|
//=======================================================================
|
|
//function : StartElements
|
|
//purpose :
|
|
//=======================================================================
|
|
const TopTools_ListOfShape& BOPAlgo_ShellSplitter::StartElements()const
|
|
{
|
|
return myStartShapes;
|
|
}
|
|
//=======================================================================
|
|
//function : Loops
|
|
//purpose :
|
|
//=======================================================================
|
|
const TopTools_ListOfShape& BOPAlgo_ShellSplitter::Shells()const
|
|
{
|
|
return myShells;
|
|
}
|
|
//=======================================================================
|
|
//function : Perform
|
|
//purpose :
|
|
//=======================================================================
|
|
void BOPAlgo_ShellSplitter::Perform()
|
|
{
|
|
GetReport()->Clear();
|
|
//
|
|
BOPTools_AlgoTools::MakeConnexityBlocks
|
|
(myStartShapes, TopAbs_EDGE, TopAbs_FACE, myLCB);
|
|
//
|
|
MakeShells();
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : SplitBlock
|
|
//purpose :
|
|
//=======================================================================
|
|
void BOPAlgo_ShellSplitter::SplitBlock(BOPTools_ConnexityBlock& aCB)
|
|
{
|
|
Standard_Integer aNbLF, aNbOff, aNbFP;
|
|
Standard_Integer i;
|
|
TopAbs_Orientation anOr;
|
|
TopoDS_Edge aEL;
|
|
BRep_Builder aBB;
|
|
TopoDS_Iterator aItS;
|
|
TopExp_Explorer aExp;
|
|
TopTools_ListIteratorOfListOfShape aItF;
|
|
BOPTools_CoupleOfShape aCSOff;
|
|
TopTools_MapOfOrientedShape AddedFacesMap;
|
|
TopTools_IndexedDataMapOfShapeListOfShape aEFMap, aMEFP;
|
|
Handle (IntTools_Context) aContext;
|
|
//
|
|
aContext=new IntTools_Context;
|
|
//
|
|
const TopTools_ListOfShape& myShapes=aCB.Shapes();
|
|
//
|
|
TopTools_ListOfShape& myLoops=aCB.ChangeLoops();
|
|
myLoops.Clear();
|
|
//
|
|
// Copy faces into the map, for recursive search of free bounds
|
|
TopTools_MapOfOrientedShape aMFaces;
|
|
aItF.Initialize (myShapes);
|
|
for (; aItF.More(); aItF.Next()) {
|
|
aMFaces.Add(aItF.Value());
|
|
}
|
|
//
|
|
// remove the faces with free edges from processing
|
|
for (;;) {
|
|
// map the shapes
|
|
aEFMap.Clear();
|
|
aItF.Initialize(myShapes);
|
|
for (; aItF.More(); aItF.Next()) {
|
|
const TopoDS_Shape& aF = aItF.Value();
|
|
if (aMFaces.Contains(aF)) {
|
|
TopExp::MapShapesAndAncestors (aF, TopAbs_EDGE, TopAbs_FACE, aEFMap);
|
|
}
|
|
}
|
|
//
|
|
Standard_Integer aNbBegin = aMFaces.Extent();
|
|
// check the free edges
|
|
Standard_Integer aNbE = aEFMap.Extent();
|
|
for (i = 1; i <= aNbE; ++i) {
|
|
const TopoDS_Edge& aE = TopoDS::Edge(aEFMap.FindKey(i));
|
|
if (!(BRep_Tool::Degenerated(aE) || aE.Orientation() == TopAbs_INTERNAL)) {
|
|
const TopTools_ListOfShape& aLF = aEFMap(i);
|
|
if (aLF.Extent() == 1) {
|
|
// remove the face
|
|
aMFaces.Remove(aLF.First());
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// check if any faces have been removed
|
|
Standard_Integer aNbEnd = aMFaces.Extent();
|
|
if ((aNbEnd == aNbBegin) || (aNbEnd == 0)) {
|
|
break;
|
|
}
|
|
}
|
|
//
|
|
if (aMFaces.IsEmpty()) {
|
|
return;
|
|
}
|
|
//
|
|
// use only connected faces
|
|
TopTools_ListOfShape aLFConnected;
|
|
// Boundary faces
|
|
TopTools_MapOfShape aBoundaryFaces;
|
|
aItF.Initialize (myShapes);
|
|
for (; aItF.More(); aItF.Next()) {
|
|
const TopoDS_Shape& aF = aItF.Value();
|
|
if (aMFaces.Contains(aF)) {
|
|
aLFConnected.Append(aF);
|
|
if (!aBoundaryFaces.Add (aF))
|
|
aBoundaryFaces.Remove (aF);
|
|
}
|
|
}
|
|
//
|
|
const Standard_Integer aNbShapes = aLFConnected.Extent();
|
|
Standard_Boolean bAllFacesTaken = Standard_False;
|
|
//
|
|
// Build the shells
|
|
aItF.Initialize (aLFConnected);
|
|
for (i = 1; aItF.More() && !bAllFacesTaken; aItF.Next(), ++i) {
|
|
const TopoDS_Shape& aFF = aItF.Value();
|
|
if (!AddedFacesMap.Add(aFF)) {
|
|
continue;
|
|
}
|
|
//
|
|
// make a new shell
|
|
TopoDS_Shell aShellStart;
|
|
aBB.MakeShell(aShellStart);
|
|
aBB.Add(aShellStart, aFF);
|
|
//
|
|
TopTools_ListOfShape aLShells;
|
|
aLShells.Append(aShellStart);
|
|
//
|
|
TopTools_ListIteratorOfListOfShape aItLShells(aLShells);
|
|
for (; aItLShells.More(); aItLShells.Next()) {
|
|
TopoDS_Shell& aShell = TopoDS::Shell(aItLShells.ChangeValue());
|
|
//
|
|
aMEFP.Clear();
|
|
TopExp::MapShapesAndAncestors(aShell, TopAbs_EDGE, TopAbs_FACE, aMEFP);
|
|
//
|
|
// loop on faces added to Shell;
|
|
// add their neighbor faces to Shell and so on
|
|
aItS.Initialize(aShell);
|
|
for (; aItS.More(); aItS.Next()) {
|
|
const TopoDS_Face& aF = (*(TopoDS_Face*)(&aItS.Value()));
|
|
Standard_Boolean isBoundary = aBoundaryFaces.Contains (aF);
|
|
//
|
|
// loop on edges of aF; find a good neighbor face of aF by aE
|
|
aExp.Init(aF, TopAbs_EDGE);
|
|
for (; aExp.More(); aExp.Next()) {
|
|
const TopoDS_Edge& aE = (*(TopoDS_Edge*)(&aExp.Current()));
|
|
//
|
|
// proceed only free edges in this shell
|
|
if (aMEFP.Contains(aE)) {
|
|
const TopTools_ListOfShape& aLFP = aMEFP.FindFromKey(aE);
|
|
aNbFP = aLFP.Extent();
|
|
if (aNbFP > 1) {
|
|
continue;
|
|
}
|
|
}
|
|
// avoid processing of internal edges
|
|
anOr = aE.Orientation();
|
|
if (anOr == TopAbs_INTERNAL) {
|
|
continue;
|
|
}
|
|
// avoid processing of degenerated edges
|
|
if (BRep_Tool::Degenerated(aE)) {
|
|
continue;
|
|
}
|
|
//
|
|
// candidate faces list
|
|
const TopTools_ListOfShape& aLF = aEFMap.FindFromKey(aE);
|
|
aNbLF = aLF.Extent();
|
|
if (!aNbLF) {
|
|
continue;
|
|
}
|
|
//
|
|
// prepare for selecting the next face
|
|
// take only not-processed faces as a candidates
|
|
BOPTools_ListOfCoupleOfShape aLCSOff;
|
|
//
|
|
Standard_Integer aNbWaysInside = 0;
|
|
TopoDS_Face aSelF;
|
|
TopTools_ListIteratorOfListOfShape aItLF(aLF);
|
|
for (; aItLF.More(); aItLF.Next()) {
|
|
const TopoDS_Face& aFL = (*(TopoDS_Face*)(&aItLF.Value()));
|
|
if (aF.IsSame(aFL) || AddedFacesMap.Contains(aFL)) {
|
|
continue;
|
|
}
|
|
//
|
|
// find current edge in the face
|
|
if (!BOPTools_AlgoTools::GetEdgeOff(aE, aFL, aEL)) {
|
|
continue;
|
|
}
|
|
//
|
|
if (isBoundary && !aBoundaryFaces.Contains (aFL))
|
|
{
|
|
++aNbWaysInside;
|
|
aSelF = aFL;
|
|
}
|
|
aCSOff.SetShape1(aEL);
|
|
aCSOff.SetShape2(aFL);
|
|
aLCSOff.Append(aCSOff);
|
|
}//for (; aItLF.More(); aItLF.Next()) {
|
|
//
|
|
aNbOff = aLCSOff.Extent();
|
|
if (!aNbOff){
|
|
continue;
|
|
}
|
|
//
|
|
// among all the adjacent faces chose one with the minimal
|
|
// angle to the current one
|
|
if (!isBoundary || aNbWaysInside != 1)
|
|
{
|
|
if (aNbOff == 1) {
|
|
aSelF = (*(TopoDS_Face*)(&aLCSOff.First().Shape2()));
|
|
}
|
|
else if (aNbOff > 1) {
|
|
BOPTools_AlgoTools::GetFaceOff(aE, aF, aLCSOff, aSelF, aContext);
|
|
}
|
|
}
|
|
//
|
|
if (!aSelF.IsNull() && AddedFacesMap.Add(aSelF)) {
|
|
aBB.Add(aShell, aSelF);
|
|
TopExp::MapShapesAndAncestors(aSelF, TopAbs_EDGE, TopAbs_FACE, aMEFP);
|
|
}
|
|
} // for (; aExp.More(); aExp.Next()) {
|
|
} // for (; aItS.More(); aItS.Next()) {
|
|
//
|
|
// split the shell on multi-connected edges
|
|
TopTools_ListOfShape aLShSp;
|
|
RefineShell(aShell, aMEFP, aLShSp);
|
|
//
|
|
// collect the not closed shells for further processing
|
|
TopTools_ListOfShape aLShNC;
|
|
//
|
|
TopTools_ListIteratorOfListOfShape aItLShSp(aLShSp);
|
|
for (; aItLShSp.More(); aItLShSp.Next()) {
|
|
TopoDS_Shell& aShSp = *((TopoDS_Shell*)&aItLShSp.Value());
|
|
//
|
|
if (BRep_Tool::IsClosed(aShSp)) {
|
|
aShSp.Closed(Standard_True);
|
|
myLoops.Append(aShSp);
|
|
}
|
|
else {
|
|
aLShNC.Append(aShSp);
|
|
}
|
|
}
|
|
//
|
|
bAllFacesTaken = (AddedFacesMap.Extent() == aNbShapes);
|
|
if (bAllFacesTaken) {
|
|
break;
|
|
}
|
|
//
|
|
if (aLShSp.Extent() == 1) {
|
|
// not further processing of not closed shells is needed,
|
|
// as it will not bring any new results
|
|
continue;
|
|
}
|
|
//
|
|
Standard_Integer aNbShNC = aLShNC.Extent();
|
|
if (aNbShNC == 1) {
|
|
// try to complete the shell with other faces
|
|
aLShells.Append(aLShNC);
|
|
}
|
|
else if (aNbShNC > 1) {
|
|
// remove th faces of not closed shells from the map of processed faces
|
|
// and try to rebuild the shells using all not processed faces,
|
|
// because faces of one shell might be needed for building the other
|
|
TopTools_ListIteratorOfListOfShape aItLShNC(aLShNC);
|
|
for (; aItLShNC.More(); aItLShNC.Next()) {
|
|
TopoDS_Iterator aItNC(aItLShNC.Value());
|
|
for (; aItNC.More(); aItNC.Next()) {
|
|
AddedFacesMap.Remove(aItNC.Value());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} // for (; aItF.More(); aItF.Next()) {
|
|
}
|
|
//=======================================================================
|
|
//function : RefineShell
|
|
//purpose :
|
|
//=======================================================================
|
|
void RefineShell(TopoDS_Shell& theShell,
|
|
const TopTools_IndexedDataMapOfShapeListOfShape& theMEF,
|
|
TopTools_ListOfShape& theLShSp)
|
|
{
|
|
TopoDS_Iterator aIt(theShell);
|
|
if(!aIt.More()) {
|
|
return;
|
|
}
|
|
//
|
|
// Find edges with more than 2 adjacent faces - branch edges -
|
|
// edges on which the input shell should be split
|
|
TopTools_MapOfShape aMEStop;
|
|
//
|
|
Standard_Integer i, aNbMEF = theMEF.Extent();
|
|
for (i = 1; i <= aNbMEF; ++i) {
|
|
const TopoDS_Edge& aE = TopoDS::Edge(theMEF.FindKey(i));
|
|
const TopTools_ListOfShape& aLF = theMEF(i);
|
|
if (aLF.Extent() > 2) {
|
|
aMEStop.Add(aE);
|
|
continue;
|
|
}
|
|
//
|
|
// check for internal edges - count faces, in which the edge
|
|
// is internal, twice
|
|
Standard_Integer aNbF = 0;
|
|
TopTools_ListIteratorOfListOfShape aItLF(aLF);
|
|
for (; aItLF.More() && aNbF <= 2; aItLF.Next()) {
|
|
const TopoDS_Face& aF = TopoDS::Face(aItLF.Value());
|
|
++aNbF;
|
|
TopExp_Explorer aExp(aF, TopAbs_EDGE);
|
|
for (; aExp.More(); aExp.Next()) {
|
|
const TopoDS_Shape& aEF = aExp.Current();
|
|
if (aEF.IsSame(aE)) {
|
|
if (aEF.Orientation() == TopAbs_INTERNAL) {
|
|
++aNbF;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
if (aNbF > 2) {
|
|
aMEStop.Add(aE);
|
|
}
|
|
}
|
|
//
|
|
if (aMEStop.IsEmpty()) {
|
|
theLShSp.Append(theShell);
|
|
return;
|
|
}
|
|
//
|
|
TopoDS_Builder aBB;
|
|
TopExp_Explorer aExp;
|
|
TopTools_IndexedMapOfShape aMFB;
|
|
TopTools_MapOfOrientedShape aMFProcessed;
|
|
TopTools_ListOfShape aLFP, aLFP1;
|
|
TopTools_ListIteratorOfListOfShape aItLF, aItLFP;
|
|
//
|
|
// The first Face
|
|
for (; aIt.More(); aIt.Next()) {
|
|
const TopoDS_Shape& aF1 = aIt.Value();
|
|
if (!aMFProcessed.Add(aF1)) {
|
|
continue;
|
|
}
|
|
//
|
|
aMFB.Clear();
|
|
aLFP.Clear();
|
|
//
|
|
aMFB.Add(aF1);
|
|
aLFP.Append(aF1);
|
|
//
|
|
// Trying to reach the branch point
|
|
for (;;) {
|
|
aItLFP.Initialize(aLFP);
|
|
for (; aItLFP.More(); aItLFP.Next()) {
|
|
const TopoDS_Shape& aFP = aItLFP.Value();
|
|
//
|
|
aExp.Init(aFP, TopAbs_EDGE);
|
|
for (; aExp.More(); aExp.Next()) {
|
|
const TopoDS_Edge& aE = (*(TopoDS_Edge*)(&aExp.Current()));
|
|
if (aMEStop.Contains(aE)) {
|
|
continue;
|
|
}
|
|
//
|
|
if (aE.Orientation() == TopAbs_INTERNAL) {
|
|
continue;
|
|
}
|
|
//
|
|
if (BRep_Tool::Degenerated(aE)) {
|
|
continue;
|
|
}
|
|
//
|
|
const TopTools_ListOfShape& aLF = theMEF.FindFromKey(aE);
|
|
//
|
|
aItLF.Initialize(aLF);
|
|
for (; aItLF.More(); aItLF.Next()) {
|
|
const TopoDS_Shape& aFP1 = aItLF.Value();
|
|
if (aFP1.IsSame(aFP)) {
|
|
continue;
|
|
}
|
|
if (aMFB.Contains(aFP1)) {
|
|
continue;
|
|
}
|
|
//
|
|
if (aMFProcessed.Add(aFP1)) {
|
|
aMFB.Add(aFP1);
|
|
aLFP1.Append(aFP1);
|
|
}
|
|
}// for (; aItLF.More(); aItLF.Next()) {
|
|
}// for (; aExp.More(); aExp.Next()) {
|
|
} // for (; aItLFP.More(); aItLFP.Next()) {
|
|
//
|
|
//
|
|
if (aLFP1.IsEmpty()) {
|
|
break;
|
|
}
|
|
//
|
|
aLFP.Clear();
|
|
aLFP.Append(aLFP1);
|
|
}// for (;;) {
|
|
//
|
|
Standard_Integer aNbMFB = aMFB.Extent();
|
|
if (aNbMFB) {
|
|
TopoDS_Shell aShSp;
|
|
aBB.MakeShell(aShSp);
|
|
//
|
|
for (i = 1; i <= aNbMFB; ++i) {
|
|
const TopoDS_Shape& aFB = aMFB(i);
|
|
aBB.Add(aShSp, aFB);
|
|
}
|
|
theLShSp.Append(aShSp);
|
|
}
|
|
}//for (; aIt.More(); aIt.Next()) {
|
|
}
|
|
//=======================================================================
|
|
//function : MakeShells
|
|
//purpose :
|
|
//=======================================================================
|
|
void BOPAlgo_ShellSplitter::MakeShells()
|
|
{
|
|
Standard_Boolean bIsRegular;
|
|
Standard_Integer aNbVCBK, k;
|
|
BOPTools_ListIteratorOfListOfConnexityBlock aItCB;
|
|
TopTools_ListIteratorOfListOfShape aIt;
|
|
BOPAlgo_VectorOfCBK aVCBK;
|
|
//
|
|
myShells.Clear();
|
|
//
|
|
aItCB.Initialize(myLCB);
|
|
for (; aItCB.More(); aItCB.Next()) {
|
|
BOPTools_ConnexityBlock& aCB=aItCB.ChangeValue();
|
|
bIsRegular=aCB.IsRegular();
|
|
if (bIsRegular) {
|
|
TopoDS_Shell aShell;
|
|
//
|
|
const TopTools_ListOfShape& aLF=aCB.Shapes();
|
|
MakeShell(aLF, aShell);
|
|
aShell.Closed(Standard_True);
|
|
myShells.Append(aShell);
|
|
}
|
|
else {
|
|
BOPAlgo_CBK& aCBK=aVCBK.Appended();
|
|
aCBK.SetConnexityBlock(aCB);
|
|
}
|
|
}
|
|
//
|
|
aNbVCBK=aVCBK.Length();
|
|
//===================================================
|
|
BOPTools_Parallel::Perform (myRunParallel, aVCBK);
|
|
//===================================================
|
|
for (k=0; k<aNbVCBK; ++k) {
|
|
BOPAlgo_CBK& aCBK=aVCBK(k);
|
|
const BOPTools_ConnexityBlock& aCB=aCBK.ConnexityBlock();
|
|
const TopTools_ListOfShape& aLS=aCB.Loops();
|
|
aIt.Initialize(aLS);
|
|
for (; aIt.More(); aIt.Next()) {
|
|
TopoDS_Shape& aShell=aIt.ChangeValue();
|
|
aShell.Closed(Standard_True);
|
|
myShells.Append(aShell);
|
|
}
|
|
}
|
|
}
|
|
//=======================================================================
|
|
//function : MakeShell
|
|
//purpose :
|
|
//=======================================================================
|
|
void MakeShell(const TopTools_ListOfShape& aLS,
|
|
TopoDS_Shell& aShell)
|
|
{
|
|
BRep_Builder aBB;
|
|
TopTools_ListIteratorOfListOfShape aIt;
|
|
//
|
|
aBB.MakeShell(aShell);
|
|
//
|
|
aIt.Initialize(aLS);
|
|
for (; aIt.More(); aIt.Next()) {
|
|
const TopoDS_Shape& aF=aIt.Value();
|
|
aBB.Add(aShell, aF);
|
|
}
|
|
//
|
|
BOPTools_AlgoTools::OrientFacesOnShell(aShell);
|
|
}
|