Description
Description
In some cases, a boolean cut operation results in incorrect result.
More specifically, it seems to happen when there's some sharp intersection and a part that should be discarded is not.
See this example.
This is Part A:
and this is Part B (it's the same part with the holes offset in the x axis)
If a boolean operation is done A - B, and also B - A, you would get the following results:
But doing this with OpenCascade we get:
The B - A operation (on the right) is correct, but A - B operation (on the left) includes an extra outer part that should've been removed.
Expected Behavior
Only the parts that are left over from the cut should remain.
Actual Behavior
Additionally the part that should be discarded also remains.
Sample Code or DRAW Tcl Script
void LoadStepIntoDoc(std::string path, Handle(TDocStd_Document)& doc)
{
STEPCAFControl_Reader reader;
IFSelect_ReturnStatus status = reader.ReadFile(path.c_str());
if (status != IFSelect_RetDone)
{
throw std::runtime_error("Error reading step file.");
}
reader.Transfer(doc);
}
TopoDS_Shape GetFreeShapesCompound(const Handle(TDocStd_Document)& doc)
{
Handle(XCAFDoc_ShapeTool) shapeTool = XCAFDoc_DocumentTool::ShapeTool(doc->Main());
TDF_LabelSequence rootLabels;
shapeTool->GetFreeShapes(rootLabels);
TopoDS_Compound compound;
BRep_Builder builder;
builder.MakeCompound(compound);
for (TDF_LabelSequence::Iterator it(rootLabels); it.More(); it.Next())
{
const TDF_Label& label = it.Value();
TopoDS_Shape shape;
if (XCAFDoc_ShapeTool::GetShape(label, shape) && !shape.IsNull())
{
builder.Add(compound, shape);
}
}
return compound;
}
TopoDS_Shape Cut(const TopoDS_Shape& shapeA, const TopoDS_Shape& shapeB)
{
BRepAlgoAPI_Cut aBuilder;
TopTools_ListOfShape arguments, tools;
arguments.Append(shapeA);
tools.Append(shapeB);
aBuilder.SetArguments(arguments);
aBuilder.SetTools(tools);
aBuilder.Build();
if (aBuilder.HasErrors() || !aBuilder.IsDone())
{
aBuilder.DumpErrors(std::cout);
aBuilder.DumpWarnings(std::cout);
throw std::runtime_error("BRepAlgoAPI_Cut encountered errors.");
}
// Retrieve the resulting shape
const TopoDS_Shape& result = aBuilder.Shape();
return result;
}
std::string pathA = "Rev_1_simple cut.STEP";
std::string pathB = "Rev_2_simple cut.STEP";
Handle(TDocStd_Application) app = new TDocStd_Application();
BinXCAFDrivers::DefineFormat(app);
Handle(TDocStd_Document) docA = app->NewDocument("BinXCAF", doc);
Handle(TDocStd_Document) docB = app->NewDocument("BinXCAF", doc);
LoadStepIntoDoc(pathA, docA);
LoadStepIntoDoc(pathB, docB);
TopoDS_Shape shapeA = GetFreeShapesCompound(docA);
TopoDS_Shape shapeB = GetFreeShapesCompound(docB);
TopoDS_Shape resAminusB = Cut(shapeA, shapeB);
Note: this is extracted to show the basic idea, not tested, but it should work.
Operating System
Windows
Compiler
MSVC
Bitness
64-bit
OCCT Version
latest
Additional Files
Sample files:
simplecuts.zip
I think this type of intersection might be the problematic one. You can see that the outer part (aquamarine, highlighted) also includes again the light green part (which is a correct one and should remain)
Metadata
Metadata
Assignees
Labels
Type
Projects
Status
Todo