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:
Max Wilfinger
2026-01-08 17:35:26 +01:00
committed by GitHub
parent 8010b04656
commit c6ede8614f
5 changed files with 61 additions and 0 deletions

View File

@@ -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) {

View File

@@ -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.
*/