mirror of
https://github.com/Open-Cascade-SAS/OCCT.git
synced 2026-05-11 10:10:56 +08:00
Update empty method guards to new style with regex (see PR). Used clang-format 18.1.8. New actions to validate code formatting is added. Update .clang-format with disabling of include sorting. It is temporary changes, then include will be sorted. Apply formatting for /src and /tools folder. The files with .hxx,.cxx,.lxx,.h,.pxx,.hpp,*.cpp extensions.
1249 lines
42 KiB
C++
1249 lines
42 KiB
C++
// Created on: 1998-08-12
|
|
// Created by: Galina KULIKOVA
|
|
// Copyright (c) 1998-1999 Matra Datavision
|
|
// 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.
|
|
|
|
// pdn 17.12.98 ie_exhaust-A.stp
|
|
|
|
#include <Bnd_Array1OfBox.hxx>
|
|
#include <Bnd_Box.hxx>
|
|
#include <BRep_Builder.hxx>
|
|
#include <BRep_Tool.hxx>
|
|
#include <BRepBndLib.hxx>
|
|
#include <Message_Msg.hxx>
|
|
#include <Message_ProgressScope.hxx>
|
|
#include <ShapeAnalysis_Shell.hxx>
|
|
#include <ShapeBuild_ReShape.hxx>
|
|
#include <ShapeFix_Face.hxx>
|
|
#include <ShapeFix_Shell.hxx>
|
|
#include <Standard_Type.hxx>
|
|
#include <TColStd_DataMapOfIntegerListOfInteger.hxx>
|
|
#include <TColStd_MapOfInteger.hxx>
|
|
#include <TopExp.hxx>
|
|
#include <TopExp_Explorer.hxx>
|
|
#include <TopoDS.hxx>
|
|
#include <TopoDS_Compound.hxx>
|
|
#include <TopoDS_Edge.hxx>
|
|
#include <TopoDS_Face.hxx>
|
|
#include <TopoDS_Iterator.hxx>
|
|
#include <TopoDS_Shape.hxx>
|
|
#include <TopoDS_Shell.hxx>
|
|
#include <TopTools_DataMapOfShapeInteger.hxx>
|
|
#include <TopTools_DataMapOfShapeShape.hxx>
|
|
#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
|
|
#include <TopTools_IndexedDataMapOfShapeShape.hxx>
|
|
#include <TopTools_IndexedMapOfShape.hxx>
|
|
#include <TopTools_ListOfShape.hxx>
|
|
#include <TopTools_MapOfShape.hxx>
|
|
#include <TopTools_SequenceOfShape.hxx>
|
|
|
|
IMPLEMENT_STANDARD_RTTIEXT(ShapeFix_Shell, ShapeFix_Root)
|
|
|
|
//=================================================================================================
|
|
|
|
ShapeFix_Shell::ShapeFix_Shell()
|
|
{
|
|
myStatus = ShapeExtend::EncodeStatus(ShapeExtend_OK);
|
|
myFixFaceMode = -1;
|
|
myFixOrientationMode = -1;
|
|
myFixFace = new ShapeFix_Face;
|
|
myNbShells = 0;
|
|
myNonManifold = Standard_False;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
ShapeFix_Shell::ShapeFix_Shell(const TopoDS_Shell& shape)
|
|
{
|
|
myStatus = ShapeExtend::EncodeStatus(ShapeExtend_OK);
|
|
myFixFaceMode = -1;
|
|
myFixOrientationMode = -1;
|
|
myFixFace = new ShapeFix_Face;
|
|
Init(shape);
|
|
myNonManifold = Standard_False;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void ShapeFix_Shell::Init(const TopoDS_Shell& shell)
|
|
{
|
|
myShape = shell;
|
|
myShell = shell;
|
|
myNbShells = 0;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Boolean ShapeFix_Shell::Perform(const Message_ProgressRange& theProgress)
|
|
{
|
|
Standard_Boolean status = Standard_False;
|
|
if (Context().IsNull())
|
|
SetContext(new ShapeBuild_ReShape);
|
|
myFixFace->SetContext(Context());
|
|
|
|
if (NeedFix(myFixFaceMode))
|
|
{
|
|
TopoDS_Shape S = Context()->Apply(myShell);
|
|
|
|
// Get the number of faces for progress indication
|
|
Standard_Integer aNbFaces = S.NbChildren();
|
|
|
|
// Start progress scope (no need to check if progress exists -- it is safe)
|
|
Message_ProgressScope aPS(theProgress, "Fixing face", aNbFaces);
|
|
|
|
for (TopoDS_Iterator iter(S); iter.More() && aPS.More(); iter.Next(), aPS.Next())
|
|
{
|
|
TopoDS_Shape sh = iter.Value();
|
|
TopoDS_Face tmpFace = TopoDS::Face(sh);
|
|
myFixFace->Init(tmpFace);
|
|
if (myFixFace->Perform())
|
|
{
|
|
status = Standard_True;
|
|
myStatus |= ShapeExtend::EncodeStatus(ShapeExtend_DONE1);
|
|
}
|
|
}
|
|
|
|
// Halt algorithm in case of user's abort
|
|
if (!aPS.More())
|
|
return Standard_False;
|
|
}
|
|
|
|
TopoDS_Shape newsh = Context()->Apply(myShell);
|
|
if (NeedFix(myFixOrientationMode))
|
|
FixFaceOrientation(TopoDS::Shell(newsh), Standard_True, myNonManifold);
|
|
|
|
TopoDS_Shape aNewsh = Context()->Apply(newsh);
|
|
ShapeAnalysis_Shell aSas;
|
|
for (TopExp_Explorer aShellExp(aNewsh, TopAbs_SHELL); aShellExp.More(); aShellExp.Next())
|
|
{
|
|
TopoDS_Shell aCurShell = TopoDS::Shell(aShellExp.Current());
|
|
if (aCurShell.Closed())
|
|
{
|
|
aSas.LoadShells(aCurShell);
|
|
aSas.CheckOrientedShells(aCurShell, Standard_True);
|
|
if (aSas.HasFreeEdges())
|
|
{
|
|
aCurShell.Closed(Standard_False);
|
|
// clang-format off
|
|
SendWarning (Message_Msg ("FixAdvShell.FixClosedFlag.MSG0"));//Shell has incorrect flag isClosed
|
|
// clang-format on
|
|
}
|
|
aSas.Clear();
|
|
}
|
|
}
|
|
|
|
if (status)
|
|
myStatus |= ShapeExtend::EncodeStatus(ShapeExtend_DONE1);
|
|
if (Status(ShapeExtend_DONE2))
|
|
status = Standard_True;
|
|
return status;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
static Standard_Boolean GetFreeEdges(const TopoDS_Shape& aShape, TopTools_MapOfShape& MapEdges)
|
|
{
|
|
for (TopExp_Explorer aExpF(aShape, TopAbs_FACE); aExpF.More(); aExpF.Next())
|
|
{
|
|
for (TopExp_Explorer aExpE(aExpF.Current(), TopAbs_EDGE); aExpE.More(); aExpE.Next())
|
|
{
|
|
TopoDS_Edge edge = TopoDS::Edge(aExpE.Current());
|
|
if (!MapEdges.Contains(edge))
|
|
MapEdges.Add(edge);
|
|
else
|
|
MapEdges.Remove(edge);
|
|
}
|
|
}
|
|
return !MapEdges.IsEmpty();
|
|
}
|
|
|
|
//=======================================================================
|
|
// function : GetShells
|
|
// purpose : If mode isMultiConnex = Standard_True gets max possible shell for
|
|
// exception of multiconnexity parts.
|
|
// Else if this mode is equal to Standard_False maximum possible
|
|
// shell will be created without taking account of multiconnexity.
|
|
// In this function map face - shell and sequence of mebius faces is formed.
|
|
//=======================================================================
|
|
static Standard_Boolean GetShells(TopTools_SequenceOfShape& Lface,
|
|
const TopTools_MapOfShape& aMapMultiConnectEdges,
|
|
TopTools_SequenceOfShape& aSeqShells,
|
|
TopTools_DataMapOfShapeShape& aMapFaceShells,
|
|
TopTools_SequenceOfShape& ErrFaces)
|
|
{
|
|
Standard_Boolean done = Standard_False;
|
|
if (!Lface.Length())
|
|
return Standard_False;
|
|
TopoDS_Shell nshell;
|
|
TopTools_MapOfShape dire, reve;
|
|
BRep_Builder B;
|
|
B.MakeShell(nshell);
|
|
Standard_Boolean isMultiConnex = !aMapMultiConnectEdges.IsEmpty();
|
|
Standard_Integer i = 1, j = 1;
|
|
TopTools_SequenceOfShape aSeqUnconnectFaces;
|
|
for (; i <= Lface.Length(); i++)
|
|
{
|
|
TopTools_MapOfShape dtemp, rtemp;
|
|
Standard_Integer nbbe = 0, nbe = 0;
|
|
TopoDS_Face F1 = TopoDS::Face(Lface.Value(i));
|
|
for (TopExp_Explorer expe(F1, TopAbs_EDGE); expe.More(); expe.Next())
|
|
{
|
|
TopoDS_Edge edge = TopoDS::Edge(expe.Current());
|
|
|
|
// if multiconnexity mode is equal to Standard_True faces contains
|
|
// the same multiconnexity edges are not added to one shell.
|
|
if (isMultiConnex && aMapMultiConnectEdges.Contains(edge))
|
|
continue;
|
|
|
|
if ((edge.Orientation() == TopAbs_FORWARD && dire.Contains(edge))
|
|
|| (edge.Orientation() == TopAbs_REVERSED && reve.Contains(edge)))
|
|
nbbe++;
|
|
else if ((edge.Orientation() == TopAbs_FORWARD && reve.Contains(edge))
|
|
|| (edge.Orientation() == TopAbs_REVERSED && dire.Contains(edge)))
|
|
nbe++;
|
|
|
|
if (dire.Contains(edge))
|
|
dire.Remove(edge);
|
|
else if (reve.Contains(edge))
|
|
reve.Remove(edge);
|
|
else
|
|
{
|
|
if (edge.Orientation() == TopAbs_FORWARD)
|
|
dtemp.Add(edge);
|
|
if (edge.Orientation() == TopAbs_REVERSED)
|
|
rtemp.Add(edge);
|
|
}
|
|
}
|
|
if (!nbbe && !nbe && dtemp.IsEmpty() && rtemp.IsEmpty())
|
|
continue;
|
|
|
|
// if face can not be added to shell it added to sequence of error faces.
|
|
|
|
if (nbe != 0 && nbbe != 0)
|
|
{
|
|
ErrFaces.Append(F1);
|
|
Lface.Remove(i);
|
|
j++;
|
|
continue;
|
|
}
|
|
|
|
// Addition of face to shell. In the dependance of orientation faces in the shell
|
|
// added face can be reversed.
|
|
|
|
if ((nbe != 0 || nbbe != 0) || j == 1)
|
|
{
|
|
if (nbbe != 0)
|
|
{
|
|
F1.Reverse();
|
|
for (TopTools_MapIteratorOfMapOfShape ite(dtemp); ite.More(); ite.Next())
|
|
reve.Add(ite.Key());
|
|
for (TopTools_MapIteratorOfMapOfShape ite1(rtemp); ite1.More(); ite1.Next())
|
|
dire.Add(ite1.Key());
|
|
done = Standard_True;
|
|
}
|
|
else
|
|
{
|
|
for (TopTools_MapIteratorOfMapOfShape ite(dtemp); ite.More(); ite.Next())
|
|
dire.Add(ite.Key());
|
|
for (TopTools_MapIteratorOfMapOfShape ite1(rtemp); ite1.More(); ite1.Next())
|
|
reve.Add(ite1.Key());
|
|
}
|
|
j++;
|
|
B.Add(nshell, F1);
|
|
aMapFaceShells.Bind(F1, nshell);
|
|
Lface.Remove(i);
|
|
|
|
// check if closed shell is obtained in multi connex mode and add to sequence of
|
|
// shells and new shell begin to construct.
|
|
// (check is n*2)
|
|
if (isMultiConnex && BRep_Tool::IsClosed(nshell))
|
|
{
|
|
nshell.Closed(Standard_True);
|
|
aSeqShells.Append(nshell);
|
|
TopoDS_Shell nshellnext;
|
|
B.MakeShell(nshellnext);
|
|
nshell = nshellnext;
|
|
j = 1;
|
|
}
|
|
|
|
i = 0;
|
|
}
|
|
// if shell contains of one face. This face is added to sequence of faces.
|
|
// This shell is removed.
|
|
if (Lface.Length() && i == Lface.Length() && j <= 2)
|
|
{
|
|
TopoDS_Iterator aItf(nshell, Standard_False);
|
|
if (aItf.More())
|
|
{
|
|
aSeqUnconnectFaces.Append(aItf.Value());
|
|
aMapFaceShells.UnBind(aItf.Value());
|
|
}
|
|
TopoDS_Shell nshellnext;
|
|
B.MakeShell(nshellnext);
|
|
nshell = nshellnext;
|
|
i = 0;
|
|
j = 1;
|
|
}
|
|
}
|
|
Standard_Boolean isContains = Standard_False;
|
|
for (Standard_Integer k = 1; k <= aSeqShells.Length() && !isContains; k++)
|
|
isContains = nshell.IsSame(aSeqShells.Value(k));
|
|
if (!isContains)
|
|
{
|
|
Standard_Integer numFace = 0;
|
|
TopoDS_Shape aFace;
|
|
for (TopoDS_Iterator aItf(nshell, Standard_False); aItf.More(); aItf.Next())
|
|
{
|
|
aFace = aItf.Value();
|
|
numFace++;
|
|
}
|
|
if (numFace > 1)
|
|
{
|
|
// close all closed shells in no multi connex mode
|
|
if (!isMultiConnex)
|
|
nshell.Closed(BRep_Tool::IsClosed(nshell));
|
|
aSeqShells.Append(nshell);
|
|
}
|
|
else if (numFace == 1)
|
|
{
|
|
if (aMapFaceShells.IsBound(aFace))
|
|
aMapFaceShells.UnBind(aFace);
|
|
Lface.Append(aFace);
|
|
}
|
|
}
|
|
|
|
// Sequence of faces Lface contains faces which can not be added to obtained shells.
|
|
for (Standard_Integer j1 = 1; j1 <= aSeqUnconnectFaces.Length(); j1++)
|
|
{
|
|
Lface.Append(aSeqUnconnectFaces);
|
|
}
|
|
|
|
return done;
|
|
}
|
|
|
|
//=======================================================================
|
|
// function : AddMultiConexityFaces
|
|
// purpose : In this function faces have only of multiconnexity boundary
|
|
// are added to shells having free boundary contains the same
|
|
// multiconnexity edges as faces.
|
|
//=======================================================================
|
|
static Standard_Boolean AddMultiConexityFaces(
|
|
TopTools_SequenceOfShape& Lface,
|
|
const TopTools_MapOfShape& aMapMultiConnectEdges,
|
|
TopTools_SequenceOfShape& SeqShells,
|
|
const TopTools_DataMapOfShapeShape& aMapFaceShells,
|
|
const TopTools_IndexedDataMapOfShapeListOfShape& aMapEdgeFaces,
|
|
TopTools_SequenceOfShape& ErrFaces,
|
|
const Standard_Boolean NonManifold)
|
|
{
|
|
Standard_Boolean done = Standard_False;
|
|
// BRep_Builder aB;
|
|
TopTools_SequenceOfShape llPosibleShells;
|
|
TopTools_SequenceOfShape AddShapes;
|
|
for (Standard_Integer i1 = 1; i1 <= Lface.Length(); i1++)
|
|
{
|
|
|
|
const TopoDS_Shape& aShape = Lface.Value(i1);
|
|
|
|
Standard_Integer aNbMultEdges = 0;
|
|
|
|
// Finds faces having only multiconnexity boundary.
|
|
for (TopoDS_Iterator aItWires(aShape, Standard_False); aItWires.More(); aItWires.Next())
|
|
{
|
|
Standard_Integer aNbEdges = 0;
|
|
for (TopoDS_Iterator aItEdges(aItWires.Value(), Standard_False); aItEdges.More();
|
|
aItEdges.Next(), aNbEdges++)
|
|
{
|
|
const TopoDS_Shape& edge = aItEdges.Value();
|
|
if (!aMapMultiConnectEdges.Contains(edge))
|
|
continue;
|
|
aNbMultEdges++;
|
|
}
|
|
if (!aNbMultEdges)
|
|
continue;
|
|
|
|
if (aNbMultEdges == aNbEdges)
|
|
AddShapes.Append(aShape);
|
|
else
|
|
llPosibleShells.Append(aShape);
|
|
}
|
|
}
|
|
|
|
// Attempt to create shell from unconnected which have not only multiconnexity boundary.
|
|
TopTools_SequenceOfShape aTmpShells;
|
|
if (!llPosibleShells.IsEmpty())
|
|
{
|
|
TopTools_MapOfShape aMap;
|
|
TopTools_SequenceOfShape aTmp;
|
|
TopTools_DataMapOfShapeShape aTmpFaceShell;
|
|
if (GetShells(llPosibleShells, aMap, aTmpShells, aTmpFaceShell, aTmp))
|
|
{
|
|
for (Standard_Integer kk = 1; kk <= aTmpShells.Length(); kk++)
|
|
{
|
|
const TopoDS_Shape& aSh = aTmpShells.Value(kk);
|
|
TopTools_MapOfShape mapEdges;
|
|
if (GetFreeEdges(aSh, mapEdges))
|
|
{
|
|
Standard_Integer nbedge = 0;
|
|
for (TopTools_MapIteratorOfMapOfShape amapIter(mapEdges); amapIter.More();
|
|
amapIter.Next())
|
|
{
|
|
if (aMapMultiConnectEdges.Contains(amapIter.Key()))
|
|
nbedge++;
|
|
}
|
|
if (nbedge && nbedge == mapEdges.Extent())
|
|
AddShapes.Append(aSh);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add chosen faces to shells.
|
|
for (Standard_Integer k1 = 1; k1 <= AddShapes.Length(); k1++)
|
|
{
|
|
TopTools_DataMapOfShapeInteger MapOtherShells;
|
|
TopTools_MapOfShape dire, reve;
|
|
const TopoDS_Shape& aSh = AddShapes.Value(k1);
|
|
TopTools_MapOfShape mapEdges;
|
|
if (!GetFreeEdges(aSh, mapEdges))
|
|
continue;
|
|
TopTools_ListOfShape lfaces;
|
|
|
|
// Fill MapOtherShells which will contain shells with orientation in which selected shape aSh
|
|
// will be add.
|
|
|
|
for (TopTools_MapIteratorOfMapOfShape amapIter(mapEdges); amapIter.More(); amapIter.Next())
|
|
{
|
|
if (!aMapMultiConnectEdges.Contains(amapIter.Key()))
|
|
continue;
|
|
TopoDS_Edge edge = TopoDS::Edge(amapIter.Key());
|
|
if (edge.Orientation() == TopAbs_FORWARD)
|
|
dire.Add(edge);
|
|
else
|
|
reve.Add(edge);
|
|
TopTools_ListOfShape lf;
|
|
lf = aMapEdgeFaces.FindFromKey(edge);
|
|
lfaces.Append(lf);
|
|
}
|
|
for (TopTools_ListIteratorOfListOfShape aItl(lfaces); aItl.More(); aItl.Next())
|
|
{
|
|
TopoDS_Shape aF = aItl.Value();
|
|
if (!aMapFaceShells.IsBound(aF))
|
|
continue;
|
|
|
|
TopoDS_Shape aOthershell;
|
|
aOthershell = aMapFaceShells.Find(aF);
|
|
if (MapOtherShells.IsBound(aOthershell))
|
|
continue;
|
|
if (!NonManifold && BRep_Tool::IsClosed(aOthershell))
|
|
continue;
|
|
|
|
TopTools_MapOfShape mapShellEdges;
|
|
GetFreeEdges(aOthershell, mapShellEdges);
|
|
Standard_Boolean isAdd = Standard_True;
|
|
for (TopTools_MapIteratorOfMapOfShape amapIter1(mapEdges); amapIter1.More() && isAdd;
|
|
amapIter1.Next())
|
|
isAdd = mapShellEdges.Contains(amapIter1.Key());
|
|
|
|
if (!isAdd)
|
|
continue;
|
|
Standard_Integer nbdir = 0, nbrev = 0;
|
|
|
|
// add only free face whome all edges contains in the shell as open boundary.
|
|
for (TopTools_MapIteratorOfMapOfShape aIte(mapShellEdges); aIte.More(); aIte.Next())
|
|
{
|
|
TopoDS_Edge edgeS = TopoDS::Edge(aIte.Key());
|
|
if (!aMapMultiConnectEdges.Contains(edgeS))
|
|
continue;
|
|
if ((edgeS.Orientation() == TopAbs_FORWARD && dire.Contains(edgeS))
|
|
|| (edgeS.Orientation() == TopAbs_REVERSED && reve.Contains(edgeS)))
|
|
nbrev++;
|
|
else if ((edgeS.Orientation() == TopAbs_FORWARD && reve.Contains(edgeS))
|
|
|| (edgeS.Orientation() == TopAbs_REVERSED && dire.Contains(edgeS)))
|
|
nbdir++;
|
|
}
|
|
if (nbdir && nbrev)
|
|
{
|
|
ErrFaces.Append(aSh);
|
|
continue;
|
|
}
|
|
if (nbdir || nbrev)
|
|
{
|
|
Standard_Integer isReverse = (nbrev ? 1 : 0);
|
|
MapOtherShells.Bind(aOthershell, isReverse);
|
|
}
|
|
}
|
|
if (MapOtherShells.IsEmpty())
|
|
{
|
|
// i1++;
|
|
continue;
|
|
}
|
|
|
|
// Adds face to open shells containing the same multishared edges.
|
|
// For nonmanifold mode creation ine shell from face and shells containing the same multishared
|
|
// edges.
|
|
// If one face can be added to a few shells (case of compsolid) face will be added to each
|
|
// shell.
|
|
done = Standard_True;
|
|
Standard_Integer FirstRev = 0, FirstInd = 0;
|
|
Standard_Integer ind = 0;
|
|
for (Standard_Integer l = 1; l <= SeqShells.Length(); l++)
|
|
{
|
|
if (!MapOtherShells.IsBound(SeqShells.Value(l)))
|
|
continue;
|
|
ind++;
|
|
Standard_Integer isRev = MapOtherShells.Find(SeqShells.Value(l));
|
|
TopoDS_Shape anewShape = (isRev ? aSh.Reversed() : aSh);
|
|
|
|
BRep_Builder aB1;
|
|
TopoDS_Shape aShell = SeqShells.Value(l);
|
|
if (ind == 1 || !NonManifold)
|
|
{
|
|
if (ind == 1)
|
|
{
|
|
FirstRev = isRev;
|
|
FirstInd = l;
|
|
}
|
|
for (TopExp_Explorer aE(anewShape, TopAbs_FACE); aE.More(); aE.Next())
|
|
aB1.Add(aShell, aE.Current());
|
|
SeqShells.ChangeValue(l) = aShell;
|
|
}
|
|
else if (NonManifold)
|
|
{
|
|
Standard_Boolean isReversed = !((!(isRev) && !FirstRev) || ((isRev) && FirstRev));
|
|
aShell = SeqShells.Value(FirstInd);
|
|
for (TopoDS_Iterator aItF(SeqShells.Value(l), Standard_False); aItF.More(); aItF.Next())
|
|
{
|
|
TopoDS_Shape nF = (isReversed ? aItF.Value().Reversed() : aItF.Value());
|
|
aB1.Add(aShell, nF);
|
|
}
|
|
SeqShells.ChangeValue(FirstInd) = aShell;
|
|
SeqShells.Remove(l--);
|
|
}
|
|
}
|
|
|
|
dire.Clear();
|
|
reve.Clear();
|
|
for (TopExp_Explorer aEt(aSh, TopAbs_FACE); aEt.More(); aEt.Next())
|
|
{
|
|
for (Standard_Integer kk = 1; kk <= Lface.Length(); kk++)
|
|
{
|
|
if (aEt.Current().IsSame(Lface.Value(kk)))
|
|
Lface.Remove(kk--);
|
|
}
|
|
}
|
|
}
|
|
return done;
|
|
}
|
|
|
|
//=======================================================================
|
|
// function : BoxIn
|
|
// purpose : Check if one face contains inside other.
|
|
//=======================================================================
|
|
static Standard_Integer BoxIn(const Bnd_Box& theBox1, const Bnd_Box& theBox2)
|
|
{
|
|
Standard_Integer aNumIn = 0;
|
|
Standard_Real aXmin1, aYmin1, aXmax1, aYmax1, aXmin2, aYmin2, aXmax2, aYmax2, aZmin1, aZmax1,
|
|
aZmin2, aZmax2;
|
|
theBox1.Get(aXmin1, aYmin1, aZmin1, aXmax1, aYmax1, aZmax1);
|
|
theBox2.Get(aXmin2, aYmin2, aZmin2, aXmax2, aYmax2, aZmax2);
|
|
if (aXmin1 == aXmin2 && aXmax1 == aXmax2 && aYmin1 == aYmin2 && aYmax1 == aYmax2
|
|
&& aZmin1 == aZmin2 && aZmax1 == aZmax2)
|
|
aNumIn = 0;
|
|
else if (aXmin1 >= aXmin2 && aXmax1 <= aXmax2 && aYmin1 >= aYmin2 && aYmax1 <= aYmax2
|
|
&& aZmin1 >= aZmin2 && aZmax1 <= aZmax2)
|
|
aNumIn = 1;
|
|
else if (aXmin1 <= aXmin2 && aXmax1 >= aXmax2 && aYmin1 <= aYmin2 && aYmax1 >= aYmax2
|
|
&& aZmin1 <= aZmin2 && aZmax1 >= aZmax2)
|
|
aNumIn = 2;
|
|
return aNumIn;
|
|
}
|
|
|
|
//=======================================================================
|
|
// function : GetClosedShells
|
|
// purpose : Check if one shell is a part from other shell.
|
|
// For case of compsolid when a few shells are created from
|
|
// the same set of faces.
|
|
//=======================================================================
|
|
static void GetClosedShells(TopTools_SequenceOfShape& Shells,
|
|
TopTools_SequenceOfShape& aRemainShells)
|
|
{
|
|
Bnd_Array1OfBox aBoxes(1, Shells.Length());
|
|
for (Standard_Integer i = 1; i <= Shells.Length(); i++)
|
|
{
|
|
Bnd_Box Box;
|
|
BRepBndLib::AddClose(Shells.Value(i), Box);
|
|
aBoxes.SetValue(i, Box);
|
|
}
|
|
TColStd_MapOfInteger aMapNum;
|
|
for (Standard_Integer j = 1; j <= aBoxes.Length(); j++)
|
|
{
|
|
for (Standard_Integer k = j + 1; k <= aBoxes.Length(); k++)
|
|
{
|
|
Standard_Integer NumIn = BoxIn(aBoxes.Value(j), aBoxes.Value(k));
|
|
switch (NumIn)
|
|
{
|
|
case 1:
|
|
aMapNum.Add(k);
|
|
break;
|
|
case 2:
|
|
aMapNum.Add(j);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
for (Standard_Integer i1 = 1; i1 <= Shells.Length(); i1++)
|
|
{
|
|
if (!aMapNum.Contains(i1))
|
|
aRemainShells.Append(Shells.Value(i1));
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
// function : GlueClosedCandidate
|
|
// purpose : First, attempt to create closed shells from sequence of open shells.
|
|
//=======================================================================
|
|
static void GlueClosedCandidate(TopTools_SequenceOfShape& OpenShells,
|
|
const TopTools_MapOfShape& aMapMultiConnectEdges,
|
|
TopTools_SequenceOfShape& aSeqNewShells)
|
|
{
|
|
// Creating new shells if some open shells contain the same free boundary.
|
|
for (Standard_Integer i = 1; i < OpenShells.Length(); i++)
|
|
{
|
|
TopoDS_Shape aShell = OpenShells.Value(i);
|
|
TopTools_MapOfShape mapEdges1;
|
|
TopTools_MapOfShape dire, reve;
|
|
if (!GetFreeEdges(aShell, mapEdges1))
|
|
continue;
|
|
|
|
for (TopTools_MapIteratorOfMapOfShape aIte(mapEdges1); aIte.More(); aIte.Next())
|
|
{
|
|
TopoDS_Edge edge1 = TopoDS::Edge(aIte.Key());
|
|
if (!aMapMultiConnectEdges.Contains(edge1))
|
|
break;
|
|
if (edge1.Orientation() == TopAbs_FORWARD)
|
|
dire.Add(edge1);
|
|
else if (edge1.Orientation() == TopAbs_REVERSED)
|
|
reve.Add(edge1);
|
|
}
|
|
if (mapEdges1.Extent() > (dire.Extent() + reve.Extent()))
|
|
continue;
|
|
|
|
// Filling map MapOtherShells which contains candidate to creation of closed shell
|
|
// with aShell.
|
|
NCollection_DataMap<TopoDS_Shape, Standard_Boolean, TopTools_ShapeMapHasher> MapOtherShells;
|
|
for (Standard_Integer j = i + 1; j <= OpenShells.Length(); j++)
|
|
{
|
|
Standard_Boolean isAddShell = Standard_True;
|
|
Standard_Boolean isReversed = Standard_False;
|
|
TopTools_MapOfShape mapEdges2;
|
|
const TopoDS_Shape& aShell2 = OpenShells.Value(j);
|
|
if (!GetFreeEdges(aShell2, mapEdges2))
|
|
continue;
|
|
for (TopTools_MapIteratorOfMapOfShape aIte2(mapEdges2); aIte2.More() && isAddShell;
|
|
aIte2.Next())
|
|
{
|
|
TopoDS_Edge edge2 = TopoDS::Edge(aIte2.Key());
|
|
if (!aMapMultiConnectEdges.Contains(edge2))
|
|
{
|
|
isAddShell = Standard_False;
|
|
break;
|
|
// continue;
|
|
}
|
|
isAddShell = (dire.Contains(edge2) || reve.Contains(edge2));
|
|
if ((edge2.Orientation() == TopAbs_FORWARD && dire.Contains(edge2))
|
|
|| (edge2.Orientation() == TopAbs_REVERSED && reve.Contains(edge2)))
|
|
isReversed = Standard_True;
|
|
}
|
|
|
|
if (!isAddShell)
|
|
continue;
|
|
MapOtherShells.Bind(OpenShells.Value(j), isReversed);
|
|
}
|
|
if (MapOtherShells.IsEmpty())
|
|
continue;
|
|
|
|
if (!MapOtherShells.IsEmpty())
|
|
{
|
|
// Case of compsolid when more than two shells have the same free boundary.
|
|
TopTools_SequenceOfShape aSeqCandidate;
|
|
aSeqCandidate.Append(OpenShells.Value(i));
|
|
|
|
for (NCollection_DataMap<TopoDS_Shape, Standard_Boolean, TopTools_ShapeMapHasher>::Iterator
|
|
aIt(MapOtherShells);
|
|
aIt.More();
|
|
aIt.Next())
|
|
{
|
|
aSeqCandidate.Append(aIt.Key());
|
|
}
|
|
|
|
// Creation of all possible shells from chosen candidate.
|
|
// And the addition of them to temporary sequence.
|
|
|
|
TopTools_SequenceOfShape aTmpSeq;
|
|
for (Standard_Integer k = 1; k <= aSeqCandidate.Length(); k++)
|
|
{
|
|
|
|
for (Standard_Integer l = k + 1; l <= aSeqCandidate.Length(); l++)
|
|
{
|
|
TopoDS_Shell aNewSh;
|
|
BRep_Builder aB;
|
|
aB.MakeShell(aNewSh);
|
|
for (TopoDS_Iterator aIt1(aSeqCandidate.Value(k), Standard_False); aIt1.More();
|
|
aIt1.Next())
|
|
aB.Add(aNewSh, aIt1.Value());
|
|
Standard_Boolean isRev = MapOtherShells.Find(aSeqCandidate.Value(l));
|
|
if (k != 1)
|
|
{
|
|
isRev = (isRev == MapOtherShells.Find(aSeqCandidate.Value(k)));
|
|
}
|
|
for (TopExp_Explorer aExp(aSeqCandidate.Value(l), TopAbs_FACE); aExp.More(); aExp.Next())
|
|
{
|
|
TopoDS_Shape aFace = (isRev ? aExp.Current().Reversed() : aExp.Current());
|
|
aB.Add(aNewSh, aFace);
|
|
}
|
|
aTmpSeq.Append(aNewSh);
|
|
}
|
|
}
|
|
|
|
// Choice from temporary sequence shells contains different set of faces (case of compsolid)
|
|
TopTools_SequenceOfShape aRemainShells;
|
|
GetClosedShells(aTmpSeq, aRemainShells);
|
|
aSeqNewShells.Append(aRemainShells);
|
|
|
|
for (Standard_Integer j1 = i + 1; j1 <= OpenShells.Length(); j1++)
|
|
{
|
|
if (!MapOtherShells.IsBound(OpenShells.Value(j1)))
|
|
continue;
|
|
OpenShells.Remove(j1--);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
BRep_Builder aB;
|
|
TopoDS_Shape aNewShell = aShell;
|
|
TopoDS_Shape addShell;
|
|
Standard_Boolean isReversed = Standard_False;
|
|
for (Standard_Integer j1 = i + 1; j1 <= OpenShells.Length(); j1++)
|
|
{
|
|
if (!MapOtherShells.Find(OpenShells.Value(j1), isReversed))
|
|
continue;
|
|
addShell = OpenShells.Value(j1);
|
|
OpenShells.Remove(j1);
|
|
break;
|
|
}
|
|
|
|
for (TopExp_Explorer aExpF(addShell, TopAbs_FACE); aExpF.More(); aExpF.Next())
|
|
{
|
|
TopoDS_Shape aFace = aExpF.Current();
|
|
if (isReversed)
|
|
aFace.Reverse();
|
|
aB.Add(aNewShell, aFace);
|
|
}
|
|
aSeqNewShells.Append(aNewShell);
|
|
}
|
|
|
|
// OpenShells.ChangeValue(i) = aShell;
|
|
OpenShells.Remove(i--);
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
// function : CreateNonManifoldShells
|
|
// purpose : Attempt to create max possible shells from open shells.
|
|
//=======================================================================
|
|
|
|
static void CreateNonManifoldShells(TopTools_SequenceOfShape& SeqShells,
|
|
const TopTools_MapOfShape& aMapMultiConnectEdges)
|
|
{
|
|
TopTools_IndexedDataMapOfShapeListOfShape aMap;
|
|
for (Standard_Integer i = 1; i <= SeqShells.Length(); i++)
|
|
{
|
|
const TopoDS_Shape& aShell = SeqShells.Value(i);
|
|
TopTools_IndexedMapOfShape medeg;
|
|
TopExp::MapShapes(aShell, TopAbs_EDGE, medeg);
|
|
for (TopTools_MapIteratorOfMapOfShape mit(aMapMultiConnectEdges); mit.More(); mit.Next())
|
|
{
|
|
// for(TopExp_Explorer aExp(aShell,TopAbs_EDGE); aExp.More(); aExp.Next(),nbe++) {
|
|
// TopoDS_Shape ae = aExp.Current();
|
|
const TopoDS_Shape& ae = mit.Key();
|
|
// if( aMapMultiConnectEdges.Contains(aExp.Current())) {
|
|
if (medeg.Contains(ae))
|
|
{
|
|
if (aMap.Contains(ae))
|
|
aMap.ChangeFromKey(ae).Append(aShell);
|
|
else
|
|
{
|
|
TopTools_ListOfShape al;
|
|
al.Append(aShell);
|
|
aMap.Add(ae, al);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
TopTools_IndexedDataMapOfShapeShape aMapShells;
|
|
for (Standard_Integer j = 1; j <= aMap.Extent(); j++)
|
|
{
|
|
const TopTools_ListOfShape& LShells = aMap.FindFromIndex(j);
|
|
TopoDS_Shell aNewShell;
|
|
BRep_Builder aB;
|
|
aB.MakeShell(aNewShell);
|
|
TopTools_MapOfShape mapmerge;
|
|
Standard_Boolean ismerged = Standard_False;
|
|
Standard_Integer num = 1;
|
|
for (TopTools_ListIteratorOfListOfShape alit(LShells); alit.More(); alit.Next(), num++)
|
|
{
|
|
if (!aMapShells.Contains(alit.Value()))
|
|
{
|
|
for (TopExp_Explorer aEf(alit.Value(), TopAbs_FACE); aEf.More(); aEf.Next())
|
|
{
|
|
aB.Add(aNewShell, aEf.Current());
|
|
}
|
|
ismerged = Standard_True;
|
|
mapmerge.Add(alit.Value());
|
|
}
|
|
else if (ismerged)
|
|
{
|
|
TopoDS_Shape arshell = aMapShells.FindFromKey(alit.Value());
|
|
while (aMapShells.Contains(arshell))
|
|
{
|
|
const TopoDS_Shape& ss = aMapShells.FindFromKey(arshell);
|
|
if (ss.IsSame(arshell))
|
|
break;
|
|
arshell = ss;
|
|
}
|
|
|
|
if (!mapmerge.Contains(arshell))
|
|
{
|
|
for (TopExp_Explorer aEf(arshell, TopAbs_FACE); aEf.More(); aEf.Next())
|
|
{
|
|
aB.Add(aNewShell, aEf.Current());
|
|
}
|
|
mapmerge.Add(arshell);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TopoDS_Shape arshell = aMapShells.FindFromKey(alit.Value());
|
|
while (aMapShells.Contains(arshell))
|
|
{
|
|
const TopoDS_Shape& ss = aMapShells.FindFromKey(arshell);
|
|
if (ss.IsSame(arshell))
|
|
break;
|
|
arshell = ss;
|
|
}
|
|
if (num == 1)
|
|
{
|
|
for (TopExp_Explorer aEf(arshell, TopAbs_FACE); aEf.More(); aEf.Next())
|
|
aB.Add(aNewShell, aEf.Current());
|
|
|
|
mapmerge.Add(arshell);
|
|
}
|
|
else if (!mapmerge.Contains(arshell))
|
|
{
|
|
for (TopExp_Explorer aEf(arshell, TopAbs_FACE); aEf.More(); aEf.Next())
|
|
{
|
|
aB.Add(aNewShell, aEf.Current());
|
|
}
|
|
mapmerge.Add(arshell);
|
|
}
|
|
}
|
|
}
|
|
if (mapmerge.Extent() > 1 || ismerged)
|
|
{
|
|
for (TopTools_MapIteratorOfMapOfShape alit1(mapmerge); alit1.More(); alit1.Next())
|
|
{
|
|
const TopoDS_Shape& oldShell = alit1.Key();
|
|
// while(aMapShells.Contains(oldShell)) {
|
|
// TopoDS_Shape ss = aMapShells.FindFromKey(oldShell);
|
|
// if(ss.IsSame(oldShell)) break;
|
|
// oldShell = ss;
|
|
// }
|
|
aMapShells.Add(oldShell, aNewShell);
|
|
}
|
|
}
|
|
}
|
|
TopTools_IndexedMapOfShape MapNewShells;
|
|
for (Standard_Integer nn = 1; nn <= SeqShells.Length(); nn++)
|
|
{
|
|
if (aMapShells.Contains(SeqShells.Value(nn)))
|
|
{
|
|
TopoDS_Shape aNewShell = aMapShells.FindFromKey(SeqShells.Value(nn));
|
|
while (aMapShells.Contains(aNewShell))
|
|
{
|
|
const TopoDS_Shape& ss = aMapShells.FindFromKey(aNewShell);
|
|
if (ss.IsSame(aNewShell))
|
|
break;
|
|
aNewShell = ss;
|
|
}
|
|
MapNewShells.Add(aNewShell);
|
|
|
|
SeqShells.Remove(nn--);
|
|
}
|
|
}
|
|
for (Standard_Integer ii = 1; ii <= MapNewShells.Extent(); ii++)
|
|
SeqShells.Append(MapNewShells.FindKey(ii));
|
|
}
|
|
|
|
//=======================================================================
|
|
// function : CreateClosedShell
|
|
// purpose : Attempt to create max possible shells from open shells.
|
|
//=======================================================================
|
|
|
|
static void CreateClosedShell(TopTools_SequenceOfShape& OpenShells,
|
|
const TopTools_MapOfShape& aMapMultiConnectEdges)
|
|
{
|
|
TopTools_SequenceOfShape aNewShells;
|
|
// First, attempt to create closed shells.
|
|
GlueClosedCandidate(OpenShells, aMapMultiConnectEdges, aNewShells);
|
|
|
|
// Creating new shells if some open shells contain the multishared same edges.
|
|
for (Standard_Integer i = 1; i < OpenShells.Length(); i++)
|
|
{
|
|
Standard_Boolean isAddShell = Standard_False;
|
|
TopoDS_Shape aShell = OpenShells.Value(i);
|
|
Standard_Boolean isReversed = Standard_False;
|
|
for (Standard_Integer j = i + 1; j <= OpenShells.Length(); j++)
|
|
{
|
|
TopTools_MapOfShape mapEdges1;
|
|
TopTools_MapOfShape dire, reve;
|
|
if (!GetFreeEdges(aShell, mapEdges1))
|
|
break;
|
|
for (TopTools_MapIteratorOfMapOfShape aIte(mapEdges1); aIte.More(); aIte.Next())
|
|
{
|
|
TopoDS_Edge edge1 = TopoDS::Edge(aIte.Key());
|
|
if (!aMapMultiConnectEdges.Contains(edge1))
|
|
continue;
|
|
if (edge1.Orientation() == TopAbs_FORWARD)
|
|
dire.Add(edge1);
|
|
else if (edge1.Orientation() == TopAbs_REVERSED)
|
|
reve.Add(edge1);
|
|
}
|
|
if (dire.IsEmpty() && reve.IsEmpty())
|
|
break;
|
|
TopTools_MapOfShape mapEdges2;
|
|
TopoDS_Shape aShell2 = OpenShells.Value(j);
|
|
if (!GetFreeEdges(aShell2, mapEdges2))
|
|
continue;
|
|
for (TopTools_MapIteratorOfMapOfShape aIte2(mapEdges2); aIte2.More(); aIte2.Next())
|
|
{
|
|
TopoDS_Edge edge2 = TopoDS::Edge(aIte2.Key());
|
|
if (!aMapMultiConnectEdges.Contains(edge2))
|
|
continue;
|
|
if (!dire.Contains(edge2) && !reve.Contains(edge2))
|
|
continue;
|
|
isAddShell = Standard_True;
|
|
if ((edge2.Orientation() == TopAbs_FORWARD && dire.Contains(edge2))
|
|
|| (edge2.Orientation() == TopAbs_REVERSED && reve.Contains(edge2)))
|
|
isReversed = Standard_True;
|
|
}
|
|
|
|
if (!isAddShell)
|
|
continue;
|
|
BRep_Builder aB;
|
|
|
|
for (TopExp_Explorer aExpF21(OpenShells.Value(j), TopAbs_FACE); aExpF21.More();
|
|
aExpF21.Next())
|
|
{
|
|
TopoDS_Shape aFace = aExpF21.Current();
|
|
if (isReversed)
|
|
aFace.Reverse();
|
|
aB.Add(aShell, aFace);
|
|
}
|
|
|
|
OpenShells.ChangeValue(i) = aShell;
|
|
OpenShells.Remove(j--);
|
|
}
|
|
}
|
|
|
|
OpenShells.Append(aNewShells);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Boolean ShapeFix_Shell::FixFaceOrientation(const TopoDS_Shell& shell,
|
|
const Standard_Boolean isAccountMultiConex,
|
|
const Standard_Boolean NonManifold)
|
|
{
|
|
// myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
|
|
Standard_Boolean done = Standard_False;
|
|
TopTools_SequenceOfShape aSeqShells;
|
|
TopTools_SequenceOfShape aErrFaces; // Compound of faces like to Mebiuce leaf.
|
|
TopTools_SequenceOfShape Lface;
|
|
TopTools_DataMapOfShapeShape aMapFaceShells;
|
|
myShell = shell;
|
|
myShape = shell;
|
|
Standard_Integer aNumMultShell = 0;
|
|
Standard_Integer nbF = 0;
|
|
TopTools_MapOfShape aMapAdded;
|
|
for (TopoDS_Iterator iter(shell); iter.More(); iter.Next(), nbF++)
|
|
{
|
|
if (aMapAdded.Add(iter.Value()))
|
|
Lface.Append(iter.Value());
|
|
}
|
|
if (Lface.Length() < nbF)
|
|
done = Standard_True;
|
|
|
|
TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces;
|
|
TopExp::MapShapesAndAncestors(myShell, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces);
|
|
TopTools_MapOfShape aMapMultiConnectEdges;
|
|
Standard_Boolean isFreeBoundaries = Standard_False;
|
|
for (Standard_Integer k = 1; k <= aMapEdgeFaces.Extent(); k++)
|
|
{
|
|
const Standard_Integer aFaceCount = aMapEdgeFaces.FindFromIndex(k).Extent();
|
|
if (!isFreeBoundaries && aFaceCount == 1)
|
|
{
|
|
TopoDS_Edge E = TopoDS::Edge(aMapEdgeFaces.FindKey(k));
|
|
if (!BRep_Tool::Degenerated(E))
|
|
isFreeBoundaries = Standard_True;
|
|
}
|
|
// Finds multishared edges
|
|
else if (isAccountMultiConex && aFaceCount > 2)
|
|
aMapMultiConnectEdges.Add(aMapEdgeFaces.FindKey(k));
|
|
}
|
|
if (BRep_Tool::IsClosed(myShell) ? isFreeBoundaries : !isFreeBoundaries)
|
|
{
|
|
myShell.Closed(!isFreeBoundaries);
|
|
// clang-format off
|
|
SendWarning (Message_Msg ("FixAdvShell.FixClosedFlag.MSG0"));//Shell has incorrect flag isClosed
|
|
// clang-format on
|
|
}
|
|
Standard_Boolean isGetShells = Standard_True;
|
|
// Gets possible shells with taking in account of multiconnexity.
|
|
while (isGetShells && Lface.Length())
|
|
{
|
|
TopTools_SequenceOfShape aTmpSeqShells;
|
|
if (GetShells(Lface, aMapMultiConnectEdges, aTmpSeqShells, aMapFaceShells, aErrFaces))
|
|
{
|
|
done = Standard_True;
|
|
}
|
|
isGetShells = !aTmpSeqShells.IsEmpty();
|
|
if (isGetShells)
|
|
aSeqShells.Append(aTmpSeqShells);
|
|
}
|
|
if (!done)
|
|
done = (aSeqShells.Length() > 1);
|
|
Standard_Boolean aIsDone = Standard_False;
|
|
if (Lface.Length() > 0 && aSeqShells.Length())
|
|
{
|
|
for (Standard_Integer jj = 1; jj <= Lface.Length(); jj++)
|
|
{
|
|
if (aMapFaceShells.IsBound(Lface.Value(jj)))
|
|
aMapFaceShells.UnBind(Lface.Value(jj));
|
|
}
|
|
|
|
// Addition of faces having only multiconnexity boundary to shells having holes
|
|
// containing only the multiconnexity edges
|
|
aIsDone = AddMultiConexityFaces(Lface,
|
|
aMapMultiConnectEdges,
|
|
aSeqShells,
|
|
aMapFaceShells,
|
|
aMapEdgeFaces,
|
|
aErrFaces,
|
|
NonManifold);
|
|
}
|
|
aNumMultShell = aSeqShells.Length();
|
|
if (!aErrFaces.IsEmpty())
|
|
{
|
|
|
|
// if Shell contains of Mebius faces one shell will be created from each those face.
|
|
BRep_Builder B;
|
|
B.MakeCompound(myErrFaces);
|
|
TopoDS_Compound aCompShells;
|
|
B.MakeCompound(aCompShells);
|
|
for (Standard_Integer n = 1; n <= aErrFaces.Length(); n++)
|
|
B.Add(myErrFaces, aErrFaces.Value(n));
|
|
if (aNumMultShell)
|
|
{
|
|
if (aNumMultShell == 1)
|
|
{
|
|
B.Add(aCompShells, aSeqShells.Value(1));
|
|
for (Standard_Integer n1 = 1; n1 <= aErrFaces.Length(); n1++)
|
|
{
|
|
TopoDS_Shell aSh;
|
|
B.MakeShell(aSh);
|
|
B.Add(aSh, aErrFaces.Value(n1));
|
|
B.Add(aCompShells, aSh);
|
|
}
|
|
myShape = aCompShells;
|
|
}
|
|
else
|
|
{
|
|
for (Standard_Integer i = 1; i <= aSeqShells.Length(); i++)
|
|
B.Add(aCompShells, aSeqShells.Value(i));
|
|
for (Standard_Integer n1 = 1; n1 <= aErrFaces.Length(); n1++)
|
|
{
|
|
TopoDS_Shell aSh;
|
|
B.MakeShell(aSh);
|
|
B.Add(aSh, aErrFaces.Value(n1));
|
|
B.Add(aCompShells, aSh);
|
|
}
|
|
myShape = aCompShells;
|
|
}
|
|
}
|
|
|
|
done = Standard_True;
|
|
myStatus = ShapeExtend::EncodeStatus(ShapeExtend_FAIL);
|
|
// clang-format off
|
|
SendWarning ( Message_Msg ( "FixAdvShell.FixOrientation.MSG20" ) );// Impossible to orient faces in shell, several shells created
|
|
// clang-format on
|
|
return Standard_True;
|
|
}
|
|
if (aNumMultShell > 1)
|
|
{
|
|
TopTools_SequenceOfShape OpenShells;
|
|
for (Standard_Integer i1 = 1; i1 <= aSeqShells.Length(); i1++)
|
|
{
|
|
TopoDS_Shape aShell = aSeqShells.Value(i1);
|
|
if (!BRep_Tool::IsClosed(aShell))
|
|
{
|
|
OpenShells.Append(aShell);
|
|
aSeqShells.Remove(i1--);
|
|
}
|
|
}
|
|
if (OpenShells.Length() > 1)
|
|
// Attempt of creation closed shell from open shells with taking into account multiconnexity.
|
|
CreateClosedShell(OpenShells, aMapMultiConnectEdges);
|
|
aSeqShells.Append(OpenShells);
|
|
}
|
|
|
|
// In the case if NonManifold is equal to Standard_True one non-manifold shell will be created.
|
|
// Else compound from shells will be created if length of sequence of shape >1.
|
|
if (Lface.Length())
|
|
{
|
|
|
|
for (Standard_Integer i = 1; i <= Lface.Length(); i++)
|
|
{
|
|
BRep_Builder aB;
|
|
TopoDS_Shell OneShell;
|
|
aB.MakeShell(OneShell);
|
|
aB.Add(OneShell, Lface.Value(i));
|
|
aSeqShells.Append(OneShell);
|
|
}
|
|
}
|
|
if (NonManifold && aSeqShells.Length() > 1)
|
|
{
|
|
CreateNonManifoldShells(aSeqShells, aMapMultiConnectEdges);
|
|
}
|
|
if (!done)
|
|
done = (aSeqShells.Length() > 1 || aIsDone);
|
|
if (aSeqShells.Length() == 1)
|
|
{
|
|
myShell = TopoDS::Shell(aSeqShells.Value(1));
|
|
myShape = myShell;
|
|
myNbShells = 1;
|
|
}
|
|
else
|
|
{
|
|
BRep_Builder B;
|
|
TopoDS_Compound aCompShells;
|
|
B.MakeCompound(aCompShells);
|
|
for (Standard_Integer i = 1; i <= aSeqShells.Length(); i++)
|
|
B.Add(aCompShells, aSeqShells.Value(i));
|
|
myShape = aCompShells;
|
|
myNbShells = aSeqShells.Length();
|
|
}
|
|
if (done)
|
|
{
|
|
myStatus = ShapeExtend::EncodeStatus(ShapeExtend_DONE2);
|
|
if (!Context().IsNull())
|
|
Context()->Replace(shell, myShape);
|
|
if (myNbShells == 1)
|
|
// clang-format off
|
|
SendWarning ( Message_Msg ( "FixAdvShell.FixOrientation.MSG0" ) );// Faces were incorrectly oriented in the shell, corrected
|
|
else
|
|
SendWarning ( Message_Msg ( "FixAdvShell.FixOrientation.MSG30" ) );// Improperly connected shell split into parts
|
|
// clang-format on
|
|
return Standard_True;
|
|
}
|
|
else
|
|
return Standard_False;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Boolean ShapeFix_Shell::Status(const ShapeExtend_Status status) const
|
|
{
|
|
return ShapeExtend::DecodeStatus(myStatus, status);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
TopoDS_Shell ShapeFix_Shell::Shell()
|
|
{
|
|
return myShell;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
TopoDS_Shape ShapeFix_Shell::Shape()
|
|
{
|
|
return myShape;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
TopoDS_Compound ShapeFix_Shell::ErrorFaces() const
|
|
{
|
|
return myErrFaces;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void ShapeFix_Shell::SetMsgRegistrator(const Handle(ShapeExtend_BasicMsgRegistrator)& msgreg)
|
|
{
|
|
ShapeFix_Root::SetMsgRegistrator(msgreg);
|
|
myFixFace->SetMsgRegistrator(msgreg);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void ShapeFix_Shell::SetPrecision(const Standard_Real preci)
|
|
{
|
|
ShapeFix_Root::SetPrecision(preci);
|
|
myFixFace->SetPrecision(preci);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void ShapeFix_Shell::SetMinTolerance(const Standard_Real mintol)
|
|
{
|
|
ShapeFix_Root::SetMinTolerance(mintol);
|
|
myFixFace->SetMinTolerance(mintol);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void ShapeFix_Shell::SetMaxTolerance(const Standard_Real maxtol)
|
|
{
|
|
ShapeFix_Root::SetMaxTolerance(maxtol);
|
|
myFixFace->SetMaxTolerance(maxtol);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Integer ShapeFix_Shell::NbShells() const
|
|
{
|
|
return myNbShells;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void ShapeFix_Shell::SetNonManifoldFlag(const Standard_Boolean isNonManifold)
|
|
{
|
|
myNonManifold = isNonManifold;
|
|
}
|