BRepAlgoAPI_Defeaturing never finishes

Hello everyone, When I use BRepAlgoAPI_Defeaturing to remove a small face (created by BRepFilletAPI_MakeFillet), the BRepAlgoAPI_Defeaturing never finishes even with timeout setting, it loops in IntTools_BeanFaceIntersector::ComputeLocalized with huge amount of surface ranges (20355, 40000+...) Tesed with occ 7.6.1, 7.7, and latest github main branch.

Below is the sample code:

BRep_Builder bb;
TopoDS_Shape targetEntityShape;
const char* brepFile = R"(D:\tmp\anc101_def.brep)";

TopoDS_Shape nullShape;
if (!BRepTools::Read(targetEntityShape, brepFile, bb)) {
    return nullShape;
}

ShapeFix_ShapeTolerance aFixToler;
if (!aFixToler.LimitTolerance(targetEntityShape, Precision::Confusion(), Precision::Confusion() * 10)) {
    return nullShape;
}

TopoDS_Face face;
int i = 0;
for (TopExp_Explorer faceExplorer(targetEntityShape, TopAbs_FACE); faceExplorer.More(); faceExplorer.Next()) {
    if (i == 1) {
        face = TopoDS::Face(faceExplorer.Current());
        break;
    }
    i++;
}

TopTools_ListOfShape faceShapes;
faceShapes.Append(face);

BRepAlgoAPI_Defeaturing aDefeaturing;

aDefeaturing.SetShape(targetEntityShape);
aDefeaturing.AddFacesToRemove(faceShapes);
aDefeaturing.SetRunParallel(false);
aDefeaturing.SetToFillHistory(true);
// Perform.
Handle(OcctProgressIndicator) pi = new OcctProgressIndicator(10); // 10 seconds
aDefeaturing.Build(pi->Start());

if (pi->TimedOut() || !aDefeaturing.IsDone() || aDefeaturing.HasWarnings()) {
    return targetEntityShape;
}
return aDefeaturing.Shape();

The brep file is attached, also a screen capture to show the solid and face to be removed.

Alt text

If anyone could help, appreciate it very much!

Regards.

Dmitrii Pasukhin's picture

Hello.

We will try to reproduce. Probably it is problem with internal code. If problem will be reproduced - ticket will be created.

Additionally, progress indicator don't use seconds, it is semantic iteration count and input number is not working as a timeout.

Best regards Dmitrii.

eric gao's picture

Thanks a lot for reply, I created the customized indicator like this (by UserBreak returns true after timeout seconds):

DEFINE_STANDARD_HANDLE(OcctProgressIndicator, Message_ProgressIndicator)
class OcctProgressIndicator : public Message_ProgressIndicator
{
private:
    OSD_Timer aTimer;
    Standard_Real maxRunDuration;
    bool timedOut;
public:
    OcctProgressIndicator(Standard_Real maxDurationSeconds, bool startTimer = true);
    virtual Standard_Boolean Show(const Standard_Boolean) { return true; }
    virtual Standard_Boolean UserBreak() override;
    void StartTimer() { timedOut = false;  aTimer.Start(); }
    void StopTimer() { aTimer.Stop(); }
    Standard_Real ElapsedTime() { return aTimer.ElapsedTime(); }
    bool TimedOut() { return timedOut; }
    void Show(const Message_ProgressScope& theScope, const Standard_Boolean force = Standard_True) override;

    DEFINE_STANDARD_RTTIEXT(OcctProgressIndicator, Message_ProgressIndicator)
};


IMPLEMENT_STANDARD_HANDLE(OcctProgressIndicator, Message_ProgressIndicator)
IMPLEMENT_STANDARD_RTTIEXT(OcctProgressIndicator, Message_ProgressIndicator)

OcctProgressIndicator::OcctProgressIndicator(Standard_Real maxDurationSeconds, bool startTimer) :
    Message_ProgressIndicator()
{
    timedOut = false;
    maxRunDuration = maxDurationSeconds;
    if (startTimer)
        StartTimer();
}

Standard_Boolean OcctProgressIndicator::UserBreak()
{
    if (ElapsedTime() > maxRunDuration)
    {
        StopTimer();
        timedOut = true;
        return true;
    }
    else
        return false;
}

void OcctProgressIndicator::Show(const Message_ProgressScope&, const Standard_Boolean)
{
}

Best Regards, Eric