1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-04 13:13:25 +03:00

0029481: Implementation of the Feature Removal algorithm

Implementation of the 3D model De-featuring algorithm intended for the removal of the unwanted parts (or features) from the model consisting of solids. The features can be the holes, protrusions, gaps, chamfers, fillets etc.
The algorithm removes all possible requested features from the shape and builds the new shape as a result. The input model is not modified.

On the API level the algorithm is implemented in the class *BRepAlgoAPI_Defeaturing*. The actual features removal is performed by the low-level algorithm *BOPAlgo_RemoveFeatures*.

Documentation of the new classes.
Implementation of the DRAW commands for working with new algorithm.
Test cases for the new functionality.

Changes in other algorithms used by De-featuring algorithm:
- Provide history support for the solids in *ShapeUpgrade_UnifySameDomain* algorithm;
- Implementation of the mechanism to merge History of any Algorithm with standard history methods such as IsDeleted(), Modified() and Generated() into *BRepTools_History*.
This commit is contained in:
emv
2018-02-06 08:48:27 +03:00
committed by bugmaster
parent 9e04ccdcf8
commit d9ca2e0cb1
112 changed files with 4212 additions and 39 deletions

View File

@@ -25,12 +25,14 @@
#include <NCollection_Map.hxx>
#include <MeshTest.hxx>
#include <Message.hxx>
#include <Message_Alert.hxx>
#include <Message_Msg.hxx>
#include <Message_Messenger.hxx>
#include <Message_Report.hxx>
#include <SWDRAW.hxx>
#include <TopoDS_AlertWithShape.hxx>
#include <BOPAlgo_Algo.hxx>
#include <BOPAlgo_Alerts.hxx>
#include <BOPTest_Objects.hxx>
//=======================================================================
@@ -55,6 +57,7 @@ void BOPTest::AllCommands(Draw_Interpretor& theCommands)
BOPTest::DebugCommands (theCommands);
BOPTest::CellsCommands (theCommands);
BOPTest::UtilityCommands (theCommands);
BOPTest::RemoveFeaturesCommands(theCommands);
}
//=======================================================================
//function : Factory
@@ -84,7 +87,7 @@ DPLUGIN(BOPTest)
//purpose :
//=======================================================================
void BOPTest::ReportAlerts (const BOPAlgo_Algo& theAlgorithm)
void BOPTest::ReportAlerts(const Handle(Message_Report)& theReport)
{
// first report warnings, then errors
Message_Gravity anAlertTypes[2] = { Message_Warning, Message_Fail };
@@ -92,11 +95,12 @@ void BOPTest::ReportAlerts (const BOPAlgo_Algo& theAlgorithm)
{
// report shapes for the same type of alert together
NCollection_Map<Handle(Standard_Transient)> aPassedTypes;
const Message_ListOfAlert& aList = theAlgorithm.GetReport()->GetAlerts (anAlertTypes[iGravity]);
const Message_ListOfAlert& aList = theReport->GetAlerts (anAlertTypes[iGravity]);
for (Message_ListOfAlert::Iterator aIt (aList); aIt.More(); aIt.Next())
{
// check that this type of warnings has not yet been processed
if (! aPassedTypes.Add (aIt.Value()->DynamicType()))
const Handle(Standard_Type)& aType = aIt.Value()->DynamicType();
if (!aPassedTypes.Add(aType))
continue;
// get alert message
@@ -112,7 +116,9 @@ void BOPTest::ReportAlerts (const BOPAlgo_Algo& theAlgorithm)
{
Handle(TopoDS_AlertWithShape) aShapeAlert = Handle(TopoDS_AlertWithShape)::DownCast (aIt2.Value());
if (! aShapeAlert.IsNull() && ! aShapeAlert->GetShape().IsNull())
if (!aShapeAlert.IsNull() &&
(aType == aShapeAlert->DynamicType()) &&
!aShapeAlert->GetShape().IsNull())
{
//
char aName[80];

View File

@@ -23,7 +23,7 @@
#include <Draw_Interpretor.hxx>
class BOPTest_Objects;
class BOPTest_DrawableShape;
class BOPAlgo_Algo;
class Message_Report;
class BOPTest
{
@@ -60,9 +60,11 @@ public:
Standard_EXPORT static void UtilityCommands (Draw_Interpretor& aDI);
Standard_EXPORT static void RemoveFeaturesCommands (Draw_Interpretor& aDI);
//! Prints errors and warnings if any and draws attached shapes
//! if flag BOPTest_Objects::DrawWarnShapes() is set
Standard_EXPORT static void ReportAlerts (const BOPAlgo_Algo& theAlgorithm);
Standard_EXPORT static void ReportAlerts (const Handle(Message_Report)& theReport);
protected:

View File

@@ -164,7 +164,7 @@ Standard_Integer bop(Draw_Interpretor& di,
pPF->SetUseOBB(BOPTest_Objects::UseOBB());
//
pPF->Perform();
BOPTest::ReportAlerts(*pPF);
BOPTest::ReportAlerts(pPF->GetReport());
//
return 0;
}
@@ -257,7 +257,7 @@ Standard_Integer bopsmt(Draw_Interpretor& di,
aBOP.SetCheckInverted(BOPTest_Objects::CheckInverted());
//
aBOP.PerformWithFiller(*pPF);
BOPTest::ReportAlerts(aBOP);
BOPTest::ReportAlerts(aBOP.GetReport());
if (aBOP.HasErrors()) {
return 0;
}
@@ -318,7 +318,7 @@ Standard_Integer bopsection(Draw_Interpretor& di,
aBOP.SetCheckInverted(BOPTest_Objects::CheckInverted());
//
aBOP.PerformWithFiller(*pPF);
BOPTest::ReportAlerts(aBOP);
BOPTest::ReportAlerts(aBOP.GetReport());
if (aBOP.HasErrors()) {
return 0;
}
@@ -504,7 +504,7 @@ Standard_Integer bsmt (Draw_Interpretor& di,
aPF.SetUseOBB(BOPTest_Objects::UseOBB());
//
aPF.Perform();
BOPTest::ReportAlerts(aPF);
BOPTest::ReportAlerts(aPF.GetReport());
if (aPF.HasErrors()) {
return 0;
}
@@ -519,7 +519,7 @@ Standard_Integer bsmt (Draw_Interpretor& di,
aBOP.SetCheckInverted(BOPTest_Objects::CheckInverted());
//
aBOP.PerformWithFiller(aPF);
BOPTest::ReportAlerts(aBOP);
BOPTest::ReportAlerts(aBOP.GetReport());
if (aBOP.HasErrors()) {
return 0;
}
@@ -827,7 +827,7 @@ Standard_Integer mkvolume(Draw_Interpretor& di, Standard_Integer n, const char**
aMV.SetUseOBB(BOPTest_Objects::UseOBB());
//
aMV.Perform();
BOPTest::ReportAlerts(aMV);
BOPTest::ReportAlerts(aMV.GetReport());
if (aMV.HasErrors()) {
return 0;
}

View File

@@ -115,7 +115,7 @@ Standard_Integer bcbuild(Draw_Interpretor& di,
aCBuilder.SetUseOBB(BOPTest_Objects::UseOBB());
//
aCBuilder.PerformWithFiller(aPF);
BOPTest::ReportAlerts(aCBuilder);
BOPTest::ReportAlerts(aCBuilder.GetReport());
if (aCBuilder.HasErrors()) {
return 0;
}
@@ -162,7 +162,7 @@ Standard_Integer bcaddall(Draw_Interpretor& di,
//
aCBuilder.ClearWarnings();
aCBuilder.AddAllToResult(iMaterial, bUpdate);
BOPTest::ReportAlerts(aCBuilder);
BOPTest::ReportAlerts(aCBuilder.GetReport());
//
const TopoDS_Shape& aR = aCBuilder.Shape();
//
@@ -246,7 +246,7 @@ Standard_Integer bcadd(Draw_Interpretor& di,
//
aCBuilder.ClearWarnings();
aCBuilder.AddToResult(aLSToTake, aLSToAvoid, iMaterial, bUpdate);
BOPTest::ReportAlerts(aCBuilder);
BOPTest::ReportAlerts(aCBuilder.GetReport());
//
const TopoDS_Shape& aR = aCBuilder.Shape();
//
@@ -317,7 +317,7 @@ Standard_Integer bcremoveint(Draw_Interpretor& di,
//
aCBuilder.ClearWarnings();
aCBuilder.RemoveInternalBoundaries();
BOPTest::ReportAlerts(aCBuilder);
BOPTest::ReportAlerts(aCBuilder.GetReport());
//
const TopoDS_Shape& aR = aCBuilder.Shape();
//

View File

@@ -247,7 +247,7 @@ Standard_Integer bopcheck (Draw_Interpretor& di,
//
aTimer.Stop();
//
BOPTest::ReportAlerts(aChecker);
BOPTest::ReportAlerts(aChecker.GetReport());
//
iErr=aChecker.HasErrors();
//

View File

@@ -1350,7 +1350,7 @@ Standard_Integer bopbface (Draw_Interpretor& di,
aBF.SetFace(aF);
aBF.SetShapes(aLE);
aBF.Perform();
BOPTest::ReportAlerts(aBF);
BOPTest::ReportAlerts(aBF.GetReport());
if (aBF.HasErrors()) {
return 0;
}
@@ -1410,7 +1410,7 @@ Standard_Integer bopbsolid (Draw_Interpretor& di,
BOPAlgo_BuilderSolid aBS;
aBS.SetShapes(aLF);
aBS.Perform();
BOPTest::ReportAlerts(aBS);
BOPTest::ReportAlerts(aBS.GetReport());
if (aBS.HasErrors()) {
return 0;
}

View File

@@ -121,7 +121,7 @@ Standard_Integer bfillds(Draw_Interpretor& di,
aTimer.Start();
//
aPF.Perform();
BOPTest::ReportAlerts(aPF);
BOPTest::ReportAlerts(aPF.GetReport());
if (aPF.HasErrors()) {
return 0;
}
@@ -196,7 +196,7 @@ Standard_Integer bbuild(Draw_Interpretor& di,
aTimer.Start();
//
aBuilder.PerformWithFiller(aPF);
BOPTest::ReportAlerts(aBuilder);
BOPTest::ReportAlerts(aBuilder.GetReport());
if (aBuilder.HasErrors()) {
return 0;
}
@@ -306,7 +306,7 @@ Standard_Integer bbop(Draw_Interpretor& di,
aTimer.Start();
//
pBuilder->PerformWithFiller(aPF);
BOPTest::ReportAlerts(*pBuilder);
BOPTest::ReportAlerts(pBuilder->GetReport());
if (pBuilder->HasErrors()) {
return 0;
}
@@ -376,7 +376,7 @@ Standard_Integer bsplit(Draw_Interpretor& di,
pSplitter->PerformWithFiller(aPF);
//
aTimer.Stop();
BOPTest::ReportAlerts(*pSplitter);
BOPTest::ReportAlerts(pSplitter->GetReport());
if (pSplitter->HasErrors()) {
return 0;
}

View File

@@ -0,0 +1,269 @@
// Created by: Eugeny MALTCHIKOV
// Copyright (c) 2018 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.
#include <BOPTest.hxx>
#include <BOPTest_DrawableShape.hxx>
#include <BOPTest_Objects.hxx>
#include <BRep_Builder.hxx>
#include <BRepAlgoAPI_Defeaturing.hxx>
#include <DBRep.hxx>
#include <Draw.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Compound.hxx>
static Standard_Integer RemoveFeatures (Draw_Interpretor&, Standard_Integer, const char**);
// History commands
static Standard_Integer rfModified (Draw_Interpretor&, Standard_Integer, const char**);
static Standard_Integer rfGenerated (Draw_Interpretor&, Standard_Integer, const char**);
static Standard_Integer rfIsDeleted (Draw_Interpretor&, Standard_Integer, const char**);
namespace
{
static BRepAlgoAPI_Defeaturing TheDefeaturingTool;
}
//=======================================================================
//function : RemoveFeaturesCommands
//purpose :
//=======================================================================
void BOPTest::RemoveFeaturesCommands(Draw_Interpretor& theCommands)
{
static Standard_Boolean done = Standard_False;
if (done) return;
done = Standard_True;
// Chapter's name
const char* group = "BOPTest commands";
// Commands
theCommands.Add("removefeatures", "removefeatures result shape f1 f2 ... [-nohist] [-parallel]\n"
"\t\tRemoves user-defined features (faces) from the shape.\n"
"\t\tresult - result of the operation;\n"
"\t\tshape - the shape to remove the features from;\n"
"\t\tf1, f2 - features to remove from the shape;\n"
"\t\tnohist - disables the history collection;\n"
"\t\tparallel - enables the parallel processing mode.",
__FILE__, RemoveFeatures, group);
theCommands.Add("rfmodified", "rfmodified c_modified shape\n"
"\t\tShows the shapes <c_modified> modified from the shape <shape> during Defeaturing.",
__FILE__, rfModified, group);
theCommands.Add("rfgenerated", "rfgenerated c_generated shape\n"
"\t\tShows the shapes <c_generated> generated from the shape <shape> during Defeaturing.",
__FILE__, rfGenerated, group);
theCommands.Add("rfisdeleted", "rfisdeleted shape\n"
"\t\tChecks if the shape has been deleted during Defeaturing.",
__FILE__, rfIsDeleted, group);
}
//=======================================================================
//function : RemoveFeatures
//purpose :
//=======================================================================
Standard_Integer RemoveFeatures(Draw_Interpretor& theDI,
Standard_Integer theArgc,
const char ** theArgv)
{
if (theArgc < 4)
{
theDI.PrintHelp(theArgv[0]);
return 1;
}
// Get the shape to remove the features from
TopoDS_Shape aShape = DBRep::Get(theArgv[2]);
if (aShape.IsNull())
{
theDI << "Error: " << theArgv[2] << " is a null shape.\n";
return 1;
}
BRepAlgoAPI_Defeaturing aRF;
aRF.SetShape(aShape);
// Add faces to remove
for (Standard_Integer i = 3; i < theArgc; ++i)
{
TopoDS_Shape aF = DBRep::Get(theArgv[i]);
if (aF.IsNull())
{
// Check for the options
if (!strcmp(theArgv[i], "-nohist"))
{
// disable the history collection
aRF.TrackHistory(Standard_False);
}
else if (!strcmp(theArgv[i], "-parallel"))
{
// enable the parallel processing mode
aRF.SetRunParallel(Standard_True);
}
else
theDI << "Warning: " << theArgv[i] << " is a null shape. Skip it.\n";
continue;
}
aRF.AddFaceToRemove(aF);
}
// Perform the removal
aRF.Build();
// Check for the errors/warnings
BOPTest::ReportAlerts(aRF.GetReport());
if (aRF.HasErrors())
return 0;
const TopoDS_Shape& aResult = aRF.Shape();
DBRep::Set(theArgv[1], aResult);
TheDefeaturingTool = aRF;
return 0;
}
//=======================================================================
//function : CheckHistory
//purpose : Checks if the history available for the shape
//=======================================================================
Standard_Boolean IsHistoryAvailable(const TopoDS_Shape& theS,
Draw_Interpretor& theDI)
{
if (theS.IsNull())
{
theDI << "Null shape.\n";
return Standard_False;
}
if (!BRepTools_History::IsSupportedType(theS))
{
theDI << "The history is not supported for this kind of shape.\n";
return Standard_False;
}
if (!TheDefeaturingTool.HasHistory())
{
theDI << "The history has not been prepared.\n";
return Standard_False;
}
return Standard_True;
}
//=======================================================================
//function : rfModified
//purpose :
//=======================================================================
Standard_Integer rfModified(Draw_Interpretor& theDI,
Standard_Integer theArgc,
const char ** theArgv)
{
if (theArgc != 3)
{
theDI.PrintHelp(theArgv[0]);
return 1;
}
const TopoDS_Shape& aS = DBRep::Get(theArgv[2]);
if (!IsHistoryAvailable(aS, theDI))
return 0;
const TopTools_ListOfShape& aLSIm = TheDefeaturingTool.Modified(aS);
if (aLSIm.IsEmpty())
{
theDI << "The shape has not been modified.\n";
return 0;
}
TopoDS_Shape aCModified;
if (aLSIm.Extent() == 1)
aCModified = aLSIm.First();
else
{
BRep_Builder().MakeCompound(TopoDS::Compound(aCModified));
TopTools_ListIteratorOfListOfShape itLS(aLSIm);
for (; itLS.More(); itLS.Next())
BRep_Builder().Add(aCModified, itLS.Value());
}
DBRep::Set(theArgv[1], aCModified);
return 0;
}
//=======================================================================
//function : rfGenerated
//purpose :
//=======================================================================
Standard_Integer rfGenerated(Draw_Interpretor& theDI,
Standard_Integer theArgc,
const char ** theArgv)
{
if (theArgc != 3)
{
theDI.PrintHelp(theArgv[0]);
return 1;
}
const TopoDS_Shape& aS = DBRep::Get(theArgv[2]);
if (!IsHistoryAvailable(aS, theDI))
return 0;
const TopTools_ListOfShape& aLSGen = TheDefeaturingTool.Generated(aS);
if (aLSGen.IsEmpty())
{
theDI << "No shapes were generated from the shape.\n";
return 0;
}
TopoDS_Shape aCGenerated;
if (aLSGen.Extent() == 1)
aCGenerated = aLSGen.First();
else
{
BRep_Builder().MakeCompound(TopoDS::Compound(aCGenerated));
TopTools_ListIteratorOfListOfShape itLS(aLSGen);
for (; itLS.More(); itLS.Next())
BRep_Builder().Add(aCGenerated, itLS.Value());
}
DBRep::Set(theArgv[1], aCGenerated);
return 0;
}
//=======================================================================
//function : rfIsDeleted
//purpose :
//=======================================================================
Standard_Integer rfIsDeleted(Draw_Interpretor& theDI,
Standard_Integer theArgc,
const char ** theArgv)
{
if (theArgc != 2)
{
theDI.PrintHelp(theArgv[0]);
return 1;
}
const TopoDS_Shape& aS = DBRep::Get(theArgv[1]);
if (!IsHistoryAvailable(aS, theDI))
return 0;
theDI << (TheDefeaturingTool.IsDeleted(aS) ? "Deleted" : "Not deleted") << "\n";
return 0;
}

View File

@@ -15,4 +15,5 @@ BOPTest_TolerCommands.cxx
BOPTest_HistoryCommands.cxx
BOPTest_DebugCommands.cxx
BOPTest_CellsCommands.cxx
BOPTest_RemoveFeaturesCommands.cxx
BOPTest_UtilityCommands.cxx