Fix boolean operations (#17119)

* add BRepAlgoAPI wrapper files to CMakeList

* introduce wrapper for BRepAlgoAPI_BooleanOperation and derivatives, set sensible default Fuzzyness for boolean operations

* allow default fuzzyness to be set in settings - including off

* backwards compatibility with OCCT 7.3.3 - removed newer paramateres from wrapper

* added missing header

* reverted src/Mod/Part/App/OpenCascadeAll.h to original state

* implement some changes suggested by @wwmayer

* removed unneeded destructor definitions

* moved getDefaultFuzzyValue into its own helper class

* removed unneeded references to base class default constructor

* default to SetRunParallel(Standard_True) as suggested by @FlachyJoe

* fixed license header as requested

* Added new method to autocalculate fuzzyness to BooleanOperation base class and use it for those parts that do not call the obsolete constructor but also do not set precision

* implemented static variable solution as suggested by @wwmayer

* added helix for test case

* Refactoring FCRepAlgoAPI to FCBRepAlgoAPI

* Added Test Case (fuse cylinder with helix with different working and non-working Fuzzy values)

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* increased default value of FuzzyBoolean and made tests more robust for compatibility with OCCT 7.3

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* fixes for FREECAD_USE_PCH - allow testing of FREECAD_USE_PCH on linux with cmake switch (default OFF)

* removed surplus line - wasn't needed after all

* included precompiled as instructed

* set anti-corruption flag in boolean operations, ensures source shape is not damaged in OCCT 7.1 and higher

* fix #17085

* disable subtests that were too specific for now

* fixed all CLI tests - see comments in Pull Request https://github.com/FreeCAD/FreeCAD/pull/17119#issuecomment-2420772452

* Update src/Mod/PartDesign/PartDesignTests/TestTopologicalNamingProblem.py

suggested updated test by CalligaroV

Co-authored-by: Vincenzo Calligaro <vincenzo.calligaro@gmail.com>

* Update tests/src/Mod/Part/App/TopoShapeExpansion.cpp

suggested updated test by CalligaroV

Co-authored-by: Vincenzo Calligaro <vincenzo.calligaro@gmail.com>

* Update tests/src/Mod/Part/App/TopoShapeExpansion.cpp

suggested updated test by CalligaroV

Co-authored-by: Vincenzo Calligaro <vincenzo.calligaro@gmail.com>

* Update tests/src/Mod/Part/App/TopoShapeExpansion.cpp

suggested updated test by CalligaroV

Co-authored-by: Vincenzo Calligaro <vincenzo.calligaro@gmail.com>

* Update tests/src/Mod/Part/App/TopoShapeExpansion.cpp

suggested updated test by CalligaroV

Co-authored-by: Vincenzo Calligaro <vincenzo.calligaro@gmail.com>

* Update tests/src/Mod/Part/App/TopoShapeExpansion.cpp

suggested updated test by CalligaroV

Co-authored-by: Vincenzo Calligaro <vincenzo.calligaro@gmail.com>

* Update tests/src/Mod/Part/App/TopoShapeExpansion.cpp

suggested updated test by CalligaroV

Co-authored-by: Vincenzo Calligaro <vincenzo.calligaro@gmail.com>

* Update tests/src/Mod/Part/App/TopoShapeExpansion.cpp

suggested updated test by CalligaroV

Co-authored-by: Vincenzo Calligaro <vincenzo.calligaro@gmail.com>

* Update tests/src/Mod/Part/App/TopoShapeExpansion.cpp

suggested updated test by CalligaroV

Co-authored-by: Vincenzo Calligaro <vincenzo.calligaro@gmail.com>

* Update tests/src/Mod/Part/App/TopoShapeExpansion.cpp

suggested updated test by CalligaroV

Co-authored-by: Vincenzo Calligaro <vincenzo.calligaro@gmail.com>

* Update tests/src/Mod/Part/App/TopoShapeExpansion.cpp

suggested updated test by CalligaroV

Co-authored-by: Vincenzo Calligaro <vincenzo.calligaro@gmail.com>

* Update tests/src/Mod/Part/App/TopoShapeExpansion.cpp

suggested updated test by CalligaroV

Co-authored-by: Vincenzo Calligaro <vincenzo.calligaro@gmail.com>

* Update tests/src/Mod/Part/App/TopoShapeExpansion.cpp

suggested updated test by CalligaroV

Co-authored-by: Vincenzo Calligaro <vincenzo.calligaro@gmail.com>

* Update tests/src/Mod/Part/App/TopoShapeExpansion.cpp

suggested updated test by CalligaroV

Co-authored-by: Vincenzo Calligaro <vincenzo.calligaro@gmail.com>

* Update tests/src/Mod/Part/App/TopoShapeExpansion.cpp

Co-authored-by: Vincenzo Calligaro <vincenzo.calligaro@gmail.com>

* remove surplus tests from github suggestion interface bug

* hide the BooleanFuzzy variable - can now be only set by manually editing the config file
i
in FCParamGroup "Boolean"
<FCFloat Name="BooleanFuzzy" Value="10.000000000000"/>

* Suggestion by @FlachyJoe - add validity checks to the base and tool shape in any direct boolean op

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Vincenzo Calligaro <vincenzo.calligaro@gmail.com>
This commit is contained in:
Eric Price
2024-10-21 18:38:51 +02:00
committed by GitHub
parent 5979ebd6f8
commit cf8ad66373
58 changed files with 2098 additions and 189 deletions

View File

@@ -16,6 +16,7 @@ target_sources(
${CMAKE_CURRENT_SOURCE_DIR}/FeaturePartCut.cpp
${CMAKE_CURRENT_SOURCE_DIR}/FeaturePartFuse.cpp
${CMAKE_CURRENT_SOURCE_DIR}/FeatureRevolution.cpp
${CMAKE_CURRENT_SOURCE_DIR}/FuzzyBoolean.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Geometry.cpp
${CMAKE_CURRENT_SOURCE_DIR}/PartFeature.cpp
${CMAKE_CURRENT_SOURCE_DIR}/PartFeatures.cpp
@@ -31,3 +32,17 @@ target_sources(
${CMAKE_CURRENT_SOURCE_DIR}/TopoShapeMakeShape.cpp
${CMAKE_CURRENT_SOURCE_DIR}/WireJoiner.cpp
)
set(PartTestData_Files
brepfiles/cylinder1.brep
brepfiles/helix1.brep
)
ADD_CUSTOM_TARGET(PartTestData ALL
SOURCES ${PartTestData_Files}
)
fc_target_copy_resource(PartTestData
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_BINARY_DIR}/tests
${PartTestData_Files})

View File

@@ -0,0 +1,170 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
#include <gtest/gtest.h>
#include "Mod/Part/App/FuzzyHelper.h"
#include "Mod/Part/App/FeaturePartImportBrep.h"
#include <src/App/InitApplication.h>
#include <BRepBuilderAPI_Copy.hxx>
#include <BOPAlgo_ArgumentAnalyzer.hxx>
#include "PartTestHelpers.h"
class FuzzyBooleanTest: public ::testing::Test, public PartTestHelpers::PartTestHelperClass
{
protected:
static void SetUpTestSuite()
{
tests::initApplication();
}
void SetUp() override
{
createTestDoc();
std::string testPath = App::Application::getHomePath() + "/tests/brepfiles/";
_fuse = dynamic_cast<Part::Fuse*>(_doc->addObject("Part::Fuse"));
_cylinder1 = dynamic_cast<Part::ImportBrep*>(_doc->addObject("Part::ImportBrep"));
_cylinder1->FileName.setValue(testPath + "cylinder1.brep");
_helix1 = dynamic_cast<Part::ImportBrep*>(_doc->addObject("Part::ImportBrep"));
_helix1->FileName.setValue(testPath + "helix1.brep");
// Load
_cylinder1->execute();
_helix1->execute();
// Arrange
_fuse->Base.setValue(_cylinder1);
_fuse->Tool.setValue(_helix1);
}
void TearDown() override
{}
Part::Fuse* _fuse = nullptr; // NOLINT Can't be private in a test framework
Part::ImportBrep* _cylinder1 = nullptr; // NOLINT Can't be private in a test framework
Part::ImportBrep* _helix1 = nullptr; // NOLINT Can't be private in a test framework
};
TEST_F(FuzzyBooleanTest, testLoadedCorrectly)
{
EXPECT_NEAR(PartTestHelpers::getVolume(_cylinder1->Shape.getValue()), 125.6, 1.0);
EXPECT_NEAR(PartTestHelpers::getVolume(_helix1->Shape.getValue()), 33.32, 1.0);
}
TEST_F(FuzzyBooleanTest, testDefaultFuzzy)
{
// Act
_fuse->execute();
// Verify
EXPECT_NEAR(PartTestHelpers::getVolume(_fuse->Shape.getValue()),
PartTestHelpers::getVolume(_helix1->Shape.getValue())
+ PartTestHelpers::getVolume(_cylinder1->Shape.getValue()),
0.1);
// Analyse
Part::TopoShape ts = _fuse->Shape.getValue();
ASSERT_FALSE(ts.isNull());
TopoDS_Shape BOPCopy = BRepBuilderAPI_Copy(ts.getShape()).Shape();
BOPAlgo_ArgumentAnalyzer BOPCheck;
BOPCheck.SetShape1(BOPCopy);
BOPCheck.SelfInterMode() = Standard_True;
BOPCheck.Perform();
// Assert
EXPECT_FALSE(BOPCheck.HasFaulty());
}
TEST_F(FuzzyBooleanTest, testGoodFuzzy)
{
// Act
double oldFuzzy = Part::FuzzyHelper::getBooleanFuzzy();
Part::FuzzyHelper::setBooleanFuzzy(10.0);
_fuse->execute();
EXPECT_FLOAT_EQ(Part::FuzzyHelper::getBooleanFuzzy(), 10.0);
Part::FuzzyHelper::setBooleanFuzzy(oldFuzzy);
// Verify
EXPECT_NEAR(PartTestHelpers::getVolume(_fuse->Shape.getValue()),
PartTestHelpers::getVolume(_helix1->Shape.getValue())
+ PartTestHelpers::getVolume(_cylinder1->Shape.getValue()),
0.1);
// Analyse
Part::TopoShape ts = _fuse->Shape.getValue();
ASSERT_FALSE(ts.isNull());
TopoDS_Shape BOPCopy = BRepBuilderAPI_Copy(ts.getShape()).Shape();
BOPAlgo_ArgumentAnalyzer BOPCheck;
BOPCheck.SetShape1(BOPCopy);
BOPCheck.SelfInterMode() = Standard_True;
BOPCheck.Perform();
// Assert
int result = BOPCheck.HasFaulty();
EXPECT_FALSE(result);
}
TEST_F(FuzzyBooleanTest, testFailsTooSmallFuzzy)
{
// Act
double oldFuzzy = Part::FuzzyHelper::getBooleanFuzzy();
Part::FuzzyHelper::setBooleanFuzzy(0.01);
_fuse->execute();
EXPECT_FLOAT_EQ(Part::FuzzyHelper::getBooleanFuzzy(), 0.01);
Part::FuzzyHelper::setBooleanFuzzy(oldFuzzy);
// Verify
// EXPECT_NEAR(PartTestHelpers::getVolume(_fuse->Shape.getValue()),PartTestHelpers::getVolume(_helix1->Shape.getValue())+PartTestHelpers::getVolume(_cylinder1->Shape.getValue()),0.1);
// // fails on OCCT 7.3 - ignore
// Analyse
Part::TopoShape ts = _fuse->Shape.getValue();
ASSERT_FALSE(ts.isNull());
TopoDS_Shape BOPCopy = BRepBuilderAPI_Copy(ts.getShape()).Shape();
BOPAlgo_ArgumentAnalyzer BOPCheck;
BOPCheck.SetShape1(BOPCopy);
BOPCheck.SelfInterMode() = Standard_True;
BOPCheck.Perform();
// Assert
int result = BOPCheck.HasFaulty();
EXPECT_TRUE(result);
}
TEST_F(FuzzyBooleanTest, testCompletelyFailsTooBigFuzzy)
{
// Act
double oldFuzzy = Part::FuzzyHelper::getBooleanFuzzy();
Part::FuzzyHelper::setBooleanFuzzy(1e10);
int failed = 0;
Part::TopoShape ts;
try {
_fuse->execute();
ts = _fuse->Shape.getValue();
if (ts.isNull()) {
failed = 1;
}
else {
TopoDS_Shape BOPCopy = BRepBuilderAPI_Copy(ts.getShape()).Shape();
BOPAlgo_ArgumentAnalyzer BOPCheck;
BOPCheck.SetShape1(BOPCopy);
BOPCheck.SelfInterMode() = Standard_True;
BOPCheck.Perform();
// Assert
if (BOPCheck.HasFaulty()) {
failed = 1;
}
}
}
catch (...) {
failed = 1;
}
Part::FuzzyHelper::setBooleanFuzzy(oldFuzzy);
EXPECT_EQ(failed, 1);
}

View File

@@ -1444,7 +1444,7 @@ TEST_F(TopoShapeExpansionTest, makeElementBooleanCut)
"Edge2",
"Edge2;:M;CUT;:H2:7,E",
"Edge3",
"Edge3;:H2,E",
"Edge3;:M;CUT;:H2:7,E",
"Edge4",
"Edge4;:M;CUT;:H2:7,E",
"Edge6;:G(Edge12;K-1;:H2:4,E);CUT;:H1:1b,V",
@@ -1467,9 +1467,9 @@ TEST_F(TopoShapeExpansionTest, makeElementBooleanCut)
"Vertex1",
"Vertex2",
"Vertex3",
"Vertex3;:H2,V",
"Vertex3;:M;CUT;:H2:7,V",
"Vertex4",
"Vertex4;:H2,V",
"Vertex4;:M;CUT;:H2:7,V",
"Vertex7",
"Vertex8",
}));
@@ -1550,13 +1550,13 @@ TEST_F(TopoShapeExpansionTest, makeElementBooleanFuse)
"Vertex2",
"Vertex2;:H2,V",
"Vertex3",
"Vertex3;:H2,V",
"Vertex3;:M;FUS;:H2:7,V",
"Vertex4",
"Vertex4;:H2,V",
"Vertex5",
"Vertex4;:M;FUS;:H2:7,V",
"Vertex5;:H2,V",
"Vertex6",
"Vertex5;:M;FUS;:H1:7,V",
"Vertex6;:H2,V",
"Vertex6;:M;FUS;:H1:7,V",
"Vertex7",
"Vertex7;:H2,V",
"Vertex8",
@@ -2021,13 +2021,13 @@ TEST_F(TopoShapeExpansionTest, makeElementFuse)
"Vertex2",
"Vertex2;:H2,V",
"Vertex3",
"Vertex3;:H2,V",
"Vertex3;:M;FUS;:H2:7,V",
"Vertex4",
"Vertex4;:H2,V",
"Vertex5",
"Vertex4;:M;FUS;:H2:7,V",
"Vertex5;:H2,V",
"Vertex6",
"Vertex5;:M;FUS;:H1:7,V",
"Vertex6;:H2,V",
"Vertex6;:M;FUS;:H1:7,V",
"Vertex7",
"Vertex7;:H2,V",
"Vertex8",
@@ -2065,7 +2065,7 @@ TEST_F(TopoShapeExpansionTest, makeElementCut)
"Edge2",
"Edge2;:M;CUT;:H2:7,E",
"Edge3",
"Edge3;:H2,E",
"Edge3;:M;CUT;:H2:7,E",
"Edge4",
"Edge4;:M;CUT;:H2:7,E",
"Edge6;:G(Edge12;K-1;:H2:4,E);CUT;:H1:1b,V",
@@ -2088,9 +2088,9 @@ TEST_F(TopoShapeExpansionTest, makeElementCut)
"Vertex1",
"Vertex2",
"Vertex3",
"Vertex3;:H2,V",
"Vertex3;:M;CUT;:H2:7,V",
"Vertex4",
"Vertex4;:H2,V",
"Vertex4;:M;CUT;:H2:7,V",
"Vertex7",
"Vertex8",
}));
@@ -2546,13 +2546,13 @@ TEST_F(TopoShapeExpansionTest, makeElementTransformWithMap)
"Vertex2",
"Vertex2;:H2,V",
"Vertex3",
"Vertex3;:H2,V",
"Vertex3;:M;FUS;:H2:7,V",
"Vertex4",
"Vertex4;:H2,V",
"Vertex5",
"Vertex4;:M;FUS;:H2:7,V",
"Vertex5;:H2,V",
"Vertex6",
"Vertex5;:M;FUS;:H1:7,V",
"Vertex6;:H2,V",
"Vertex6;:M;FUS;:H1:7,V",
"Vertex7",
"Vertex7;:H2,V",
"Vertex8",
@@ -2655,13 +2655,13 @@ TEST_F(TopoShapeExpansionTest, makeElementGTransformWithMap)
"Vertex2",
"Vertex2;:H2,V",
"Vertex3",
"Vertex3;:H2,V",
"Vertex3;:M;FUS;:H2:7,V",
"Vertex4",
"Vertex4;:H2,V",
"Vertex5",
"Vertex4;:M;FUS;:H2:7,V",
"Vertex5;:H2,V",
"Vertex6",
"Vertex5;:M;FUS;:H1:7,V",
"Vertex6;:H2,V",
"Vertex6;:M;FUS;:H1:7,V",
"Vertex7",
"Vertex7;:H2,V",
"Vertex8",
@@ -3051,7 +3051,7 @@ TEST_F(TopoShapeExpansionTest, traceElement)
"Edge2",
"Edge2;:M;CUT;:H2:7,E",
"Edge3",
"Edge3;:H2,E",
"Edge3;:M;CUT;:H2:7,E",
"Edge4",
"Edge4;:M;CUT;:H2:7,E",
"Edge6;:G(Edge12;K-1;:H2:4,E);CUT;:H1:1b,V",
@@ -3074,9 +3074,9 @@ TEST_F(TopoShapeExpansionTest, traceElement)
"Vertex1",
"Vertex2",
"Vertex3",
"Vertex3;:H2,V",
"Vertex3;:M;CUT;:H2:7,V",
"Vertex4",
"Vertex4;:H2,V",
"Vertex4;:M;CUT;:H2:7,V",
"Vertex7",
"Vertex8",
}));

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long