Part: Fix orientation of internal shells of a solid (#26717)
* Part: Fix orientation of internal shells of a solid If a solid consists of multiple shells then it can happen that the internal shells have incorrect orientation that leads to a broken solid. This fixes issue https://github.com/FreeCAD/FreeCAD/issues/24994 * Part: Add method Feature::fixSolids This method explicitly checks for solids with the error 'BRepCheck_EnclosedRegion' that means that internal shells of a solid are wrong. Using ShapeFix_Solid fixes the solid. --------- Co-authored-by: wwmayer <wmayer@freecad.org>
This commit is contained in:
@@ -150,6 +150,7 @@
|
||||
#include <BRepCheck_Analyzer.hxx>
|
||||
#include <BRepCheck_ListIteratorOfListOfStatus.hxx>
|
||||
#include <BRepCheck_Result.hxx>
|
||||
#include <BRepCheck_Solid.hxx>
|
||||
#include <BRepClass_FaceClassifier.hxx>
|
||||
#include <BRepClass3d.hxx>
|
||||
#include <BRepClass3d_SolidClassifier.hxx>
|
||||
|
||||
@@ -1292,6 +1292,13 @@ bool FaceUniter::process()
|
||||
return true;
|
||||
}
|
||||
|
||||
void FaceUniter::fixOrientation(const TopoDS_Shell& shell)
|
||||
{
|
||||
if (shell.Orientation() != workShell.Orientation()) {
|
||||
workShell.Reverse();
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// BRepBuilderAPI_RefineModel implement a way to log all modifications on the faces
|
||||
@@ -1358,11 +1365,16 @@ void Part::BRepBuilderAPI_RefineModel::Build()
|
||||
const TopoDS_Solid& solid = TopoDS::Solid(xp.Current());
|
||||
BRepTools_ReShape reshape;
|
||||
TopExp_Explorer it;
|
||||
int countShells = 0;
|
||||
for (it.Init(solid, TopAbs_SHELL); it.More(); it.Next()) {
|
||||
countShells++;
|
||||
const TopoDS_Shell& currentShell = TopoDS::Shell(it.Current());
|
||||
ModelRefine::FaceUniter uniter(currentShell);
|
||||
if (uniter.process()) {
|
||||
if (uniter.isModified()) {
|
||||
if (countShells > 1) {
|
||||
uniter.fixOrientation(currentShell);
|
||||
}
|
||||
const TopoDS_Shell& newShell = uniter.getShell();
|
||||
reshape.Replace(currentShell, newShell);
|
||||
LogModifications(uniter);
|
||||
|
||||
@@ -198,6 +198,7 @@ public:
|
||||
{
|
||||
return workShell;
|
||||
}
|
||||
void fixOrientation(const TopoDS_Shell& shell);
|
||||
bool isModified()
|
||||
{
|
||||
return modifiedSignal;
|
||||
|
||||
@@ -23,11 +23,15 @@
|
||||
|
||||
#include <BRep_Tool.hxx>
|
||||
#include <BRepBuilderAPI_MakeFace.hxx>
|
||||
#include <BRepCheck_Solid.hxx>
|
||||
#include <BRepCheck_Status.hxx>
|
||||
#include <gp_Pln.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <ShapeFix_Solid.hxx>
|
||||
#include <Standard_Failure.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <TopoDS_Builder.hxx>
|
||||
|
||||
|
||||
#include "App/Datums.h"
|
||||
@@ -241,6 +245,44 @@ int Feature::countSolids(const TopoDS_Shape& shape, TopAbs_ShapeEnum type)
|
||||
return result;
|
||||
}
|
||||
|
||||
TopoShape Feature::fixSolids(const TopoShape& solids)
|
||||
{
|
||||
if (solids.isNull()) {
|
||||
return solids;
|
||||
}
|
||||
|
||||
std::vector<TopoDS_Solid> fixSolids;
|
||||
|
||||
TopExp_Explorer xp;
|
||||
xp.Init(solids.getShape(), TopAbs_SOLID);
|
||||
for (; xp.More(); xp.Next()) {
|
||||
TopoDS_Solid solid = TopoDS::Solid(xp.Current());
|
||||
BRepCheck_Solid bs(solid);
|
||||
if (bs.IsStatusOnShape(solid)) {
|
||||
const auto& listOfStatus = bs.StatusOnShape(solid);
|
||||
if (listOfStatus.Contains(BRepCheck_EnclosedRegion)) {
|
||||
fixSolids.emplace_back(solid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fixSolids.empty()) {
|
||||
return solids;
|
||||
}
|
||||
|
||||
TopoDS_Compound comp;
|
||||
TopoDS_Builder bb;
|
||||
bb.MakeCompound(comp);
|
||||
for (const TopoDS_Solid& it : fixSolids) {
|
||||
ShapeFix_Solid fix(it);
|
||||
fix.Perform();
|
||||
bb.Add(comp, fix.Solid());
|
||||
}
|
||||
|
||||
TopoShape fixShape(comp);
|
||||
return fixShape;
|
||||
}
|
||||
|
||||
bool Feature::isSingleSolidRuleSatisfied(const TopoDS_Shape& shape, TopAbs_ShapeEnum type)
|
||||
{
|
||||
if (singleSolidRuleMode() == Feature::SingleSolidRuleMode::Disabled) {
|
||||
|
||||
@@ -127,6 +127,11 @@ protected:
|
||||
TopoShape getSolid(const TopoShape&) const;
|
||||
static int countSolids(const TopoDS_Shape&, TopAbs_ShapeEnum type = TopAbs_SOLID);
|
||||
|
||||
/**
|
||||
* Fix solids
|
||||
*/
|
||||
TopoShape fixSolids(const TopoShape&);
|
||||
|
||||
/**
|
||||
* Checks if the single-solid body rule is fulfilled.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user