Merge pull request #11803 from bgbsww/bgbsww-patch-24
Preliminary cpp tests for Part boolean operations
This commit is contained in:
@@ -4,4 +4,9 @@ target_sources(
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/TopoShape.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/TopoShapeCache.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/FeaturePartCommon.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/FeaturePartCut.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/FeaturePartFuse.cpp
|
||||
# ${CMAKE_CURRENT_SOURCE_DIR}/FeatureFillet.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/PartTestHelpers.cpp
|
||||
)
|
||||
|
||||
201
tests/src/Mod/Part/App/FeaturePartCommon.cpp
Normal file
201
tests/src/Mod/Part/App/FeaturePartCommon.cpp
Normal file
@@ -0,0 +1,201 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "Mod/Part/App/FeaturePartCommon.h"
|
||||
#include <src/App/InitApplication.h>
|
||||
|
||||
#include "PartTestHelpers.h"
|
||||
|
||||
class FeaturePartCommonTest: public ::testing::Test, public PartTestHelpers::PartTestHelperClass
|
||||
{
|
||||
protected:
|
||||
static void SetUpTestSuite()
|
||||
{
|
||||
tests::initApplication();
|
||||
}
|
||||
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
createTestDoc();
|
||||
_common = dynamic_cast<Part::Common*>(_doc->addObject("Part::Common"));
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{}
|
||||
|
||||
Part::Common* _common = nullptr; // NOLINT Can't be private in a test framework
|
||||
};
|
||||
|
||||
TEST_F(FeaturePartCommonTest, testIntersecting)
|
||||
{
|
||||
// Arrange
|
||||
_common->Base.setValue(_boxes[0]);
|
||||
_common->Tool.setValue(_boxes[1]);
|
||||
|
||||
// Act
|
||||
_common->execute();
|
||||
Part::TopoShape ts = _common->Shape.getValue();
|
||||
double volume = PartTestHelpers::getVolume(ts.getShape());
|
||||
Base::BoundBox3d bb = ts.getBoundBox();
|
||||
|
||||
// Assert
|
||||
EXPECT_DOUBLE_EQ(volume, 3.0);
|
||||
// double check using bounds:
|
||||
EXPECT_DOUBLE_EQ(bb.MinX, 0.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MinY, 1.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MinZ, 0.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MaxX, 1.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MaxY, 2.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MaxZ, 3.0);
|
||||
}
|
||||
|
||||
TEST_F(FeaturePartCommonTest, testNonIntersecting)
|
||||
{
|
||||
// Arrange
|
||||
_common->Base.setValue(_boxes[0]);
|
||||
_common->Tool.setValue(_boxes[2]);
|
||||
|
||||
// Act
|
||||
_common->execute();
|
||||
Part::TopoShape ts = _common->Shape.getValue();
|
||||
double volume = PartTestHelpers::getVolume(ts.getShape());
|
||||
Base::BoundBox3d bb = ts.getBoundBox();
|
||||
|
||||
// Assert
|
||||
EXPECT_FALSE(bb.IsValid());
|
||||
EXPECT_DOUBLE_EQ(volume, 0.0);
|
||||
}
|
||||
|
||||
TEST_F(FeaturePartCommonTest, testTouching)
|
||||
{
|
||||
// Arrange
|
||||
_common->Base.setValue(_boxes[0]);
|
||||
_common->Tool.setValue(_boxes[3]);
|
||||
|
||||
// Act
|
||||
_common->execute();
|
||||
Part::TopoShape ts = _common->Shape.getValue();
|
||||
double volume = PartTestHelpers::getVolume(ts.getShape());
|
||||
Base::BoundBox3d bb = ts.getBoundBox();
|
||||
|
||||
// Assert
|
||||
EXPECT_FALSE(bb.IsValid());
|
||||
EXPECT_DOUBLE_EQ(volume, 0.0);
|
||||
}
|
||||
|
||||
TEST_F(FeaturePartCommonTest, testAlmostTouching)
|
||||
{
|
||||
// Arrange
|
||||
_common->Base.setValue(_boxes[0]);
|
||||
_common->Tool.setValue(_boxes[4]);
|
||||
|
||||
// Act
|
||||
_common->execute();
|
||||
Part::TopoShape ts = _common->Shape.getValue();
|
||||
double volume = PartTestHelpers::getVolume(ts.getShape());
|
||||
Base::BoundBox3d bb = ts.getBoundBox();
|
||||
|
||||
// Assert
|
||||
EXPECT_FALSE(bb.IsValid());
|
||||
EXPECT_DOUBLE_EQ(volume, 0.0);
|
||||
}
|
||||
|
||||
TEST_F(FeaturePartCommonTest, testBarelyIntersecting)
|
||||
{
|
||||
// Arrange
|
||||
_common->Base.setValue(_boxes[0]);
|
||||
_common->Tool.setValue(_boxes[5]); // NOLINT magic number
|
||||
|
||||
// Act
|
||||
_common->execute();
|
||||
Part::TopoShape ts = _common->Shape.getValue();
|
||||
double volume = PartTestHelpers::getVolume(ts.getShape());
|
||||
double target = PartTestHelpers::minimalDistance * 3; // 3 dimensions in a Volume
|
||||
Base::BoundBox3d bb = ts.getBoundBox();
|
||||
|
||||
// Assert
|
||||
// Using FLOAT, not DOUBLE here so test library comparison is of reasonable precision 1e07
|
||||
// rather than 1e15 See
|
||||
// https://google.github.io/googletest/reference/assertions.html#floating-point
|
||||
EXPECT_FLOAT_EQ(volume, target); // Should be approximately 0.00029999999999996696
|
||||
// double check using bounds:
|
||||
EXPECT_DOUBLE_EQ(bb.MinX, 0.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MinY, 2.0 - PartTestHelpers::minimalDistance);
|
||||
EXPECT_DOUBLE_EQ(bb.MinZ, 0.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MaxX, 1.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MaxY, 2.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MaxZ, 3.0);
|
||||
}
|
||||
|
||||
TEST_F(FeaturePartCommonTest, testMustExecute)
|
||||
{
|
||||
// Assert initially we don't need to execute
|
||||
EXPECT_FALSE(_common->mustExecute());
|
||||
// Act to change one property
|
||||
_common->Base.setValue(_boxes[0]);
|
||||
// Assert we still can't execute
|
||||
EXPECT_FALSE(_common->mustExecute());
|
||||
// Act to complete the properties we need
|
||||
_common->Tool.setValue(_boxes[1]);
|
||||
// Assert that we now must execute
|
||||
EXPECT_TRUE(_common->mustExecute());
|
||||
// Act to execute
|
||||
_doc->recompute();
|
||||
// Assert we don't need to execute anymore
|
||||
EXPECT_FALSE(_common->mustExecute());
|
||||
}
|
||||
|
||||
TEST_F(FeaturePartCommonTest, testGetProviderName)
|
||||
{
|
||||
// Act
|
||||
_common->execute();
|
||||
const char* name = _common->getViewProviderName();
|
||||
// Assert
|
||||
EXPECT_STREQ(name, "PartGui::ViewProviderBoolean");
|
||||
}
|
||||
|
||||
TEST_F(FeaturePartCommonTest, testHistory)
|
||||
{
|
||||
// Arrange
|
||||
_common->Base.setValue(_boxes[0]);
|
||||
_common->Tool.setValue(_boxes[1]);
|
||||
// Manually create the histories classically generated by FreeCAD for comparison
|
||||
using MapList = std::map<int, std::vector<int>>;
|
||||
using List = std::vector<int>;
|
||||
MapList compare1 = {{0, List {0}},
|
||||
{1, List {5}}, // NOLINT magic number
|
||||
{2, List()},
|
||||
{3, List {2}},
|
||||
{4, List {3}},
|
||||
{5, List {1}}}; // NOLINT magic number
|
||||
MapList compare2 = {{0, List {0}},
|
||||
{1, List {5}}, // NOLINT magic number
|
||||
{2, List {4}},
|
||||
{3, List()},
|
||||
{4, List {3}},
|
||||
{5, List {1}}}; // NOLINT magic number
|
||||
|
||||
// Act and Assert no histories yet
|
||||
std::vector<Part::ShapeHistory> hist = _common->History.getValues();
|
||||
EXPECT_EQ(hist.size(), 0);
|
||||
|
||||
// Act to generate histories
|
||||
_common->execute();
|
||||
hist = _common->History.getValues();
|
||||
// Assert
|
||||
ASSERT_EQ(hist.size(), 2);
|
||||
EXPECT_EQ(hist[0].shapeMap, compare1);
|
||||
EXPECT_EQ(hist[1].shapeMap, compare2);
|
||||
|
||||
// Act to reverse the histories
|
||||
_common->Base.setValue(_boxes[1]);
|
||||
_common->Tool.setValue(_boxes[0]);
|
||||
_common->execute();
|
||||
hist = _common->History.getValues();
|
||||
// Assert
|
||||
ASSERT_EQ(hist.size(), 2);
|
||||
EXPECT_EQ(hist[0].shapeMap, compare2);
|
||||
EXPECT_EQ(hist[1].shapeMap, compare1);
|
||||
}
|
||||
176
tests/src/Mod/Part/App/FeaturePartCut.cpp
Normal file
176
tests/src/Mod/Part/App/FeaturePartCut.cpp
Normal file
@@ -0,0 +1,176 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "Mod/Part/App/FeaturePartCut.h"
|
||||
#include <src/App/InitApplication.h>
|
||||
|
||||
#include "PartTestHelpers.h"
|
||||
|
||||
class FeaturePartCutTest: public ::testing::Test, public PartTestHelpers::PartTestHelperClass
|
||||
{
|
||||
protected:
|
||||
static void SetUpTestSuite()
|
||||
{
|
||||
tests::initApplication();
|
||||
}
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
createTestDoc();
|
||||
_cut = dynamic_cast<Part::Cut*>(_doc->addObject("Part::Cut"));
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{}
|
||||
|
||||
Part::Cut* _cut = nullptr; // NOLINT Can't be private in a test framework
|
||||
};
|
||||
|
||||
TEST_F(FeaturePartCutTest, testIntersecting)
|
||||
{
|
||||
// Arrange
|
||||
_cut->Base.setValue(_boxes[0]);
|
||||
_cut->Tool.setValue(_boxes[1]);
|
||||
|
||||
// Act
|
||||
_cut->execute();
|
||||
Part::TopoShape ts = _cut->Shape.getValue();
|
||||
double volume = PartTestHelpers::getVolume(ts.getShape());
|
||||
Base::BoundBox3d bb = ts.getBoundBox();
|
||||
|
||||
// Assert
|
||||
EXPECT_DOUBLE_EQ(volume, 3.0);
|
||||
// double check using bounds:
|
||||
EXPECT_DOUBLE_EQ(bb.MinX, 0.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MinY, 0.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MinZ, 0.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MaxX, 1.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MaxY, 1.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MaxZ, 3.0);
|
||||
}
|
||||
|
||||
TEST_F(FeaturePartCutTest, testNonIntersecting)
|
||||
{
|
||||
// Arrange
|
||||
_cut->Base.setValue(_boxes[0]);
|
||||
_cut->Tool.setValue(_boxes[2]);
|
||||
|
||||
// Act
|
||||
_cut->execute();
|
||||
Part::TopoShape ts = _cut->Shape.getValue();
|
||||
double volume = PartTestHelpers::getVolume(ts.getShape());
|
||||
Base::BoundBox3d bb = ts.getBoundBox();
|
||||
|
||||
// Assert
|
||||
EXPECT_DOUBLE_EQ(volume, 6.0);
|
||||
// double check using bounds:
|
||||
EXPECT_DOUBLE_EQ(bb.MinX, 0.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MinY, 0.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MinZ, 0.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MaxX, 1.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MaxY, 2.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MaxZ, 3.0);
|
||||
}
|
||||
|
||||
TEST_F(FeaturePartCutTest, testTouching)
|
||||
{
|
||||
// Arrange
|
||||
_cut->Base.setValue(_boxes[0]);
|
||||
_cut->Tool.setValue(_boxes[3]);
|
||||
|
||||
// Act
|
||||
_cut->execute();
|
||||
Part::TopoShape ts = _cut->Shape.getValue();
|
||||
double volume = PartTestHelpers::getVolume(ts.getShape());
|
||||
Base::BoundBox3d bb = ts.getBoundBox();
|
||||
|
||||
// Assert
|
||||
EXPECT_DOUBLE_EQ(volume, 6.0);
|
||||
// double check using bounds:
|
||||
EXPECT_DOUBLE_EQ(bb.MinX, 0.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MinY, 0.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MinZ, 0.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MaxX, 1.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MaxY, 2.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MaxZ, 3.0);
|
||||
}
|
||||
|
||||
TEST_F(FeaturePartCutTest, testAlmostTouching)
|
||||
{
|
||||
// Arrange
|
||||
_cut->Base.setValue(_boxes[0]);
|
||||
_cut->Tool.setValue(_boxes[4]);
|
||||
|
||||
// Act
|
||||
_cut->execute();
|
||||
Part::TopoShape ts = _cut->Shape.getValue();
|
||||
double volume = PartTestHelpers::getVolume(ts.getShape());
|
||||
Base::BoundBox3d bb = ts.getBoundBox();
|
||||
|
||||
// Assert
|
||||
EXPECT_DOUBLE_EQ(volume, 6.0);
|
||||
// double check using bounds:
|
||||
EXPECT_DOUBLE_EQ(bb.MinX, 0.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MinY, 0.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MinZ, 0.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MaxX, 1.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MaxY, 2.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MaxZ, 3.0);
|
||||
}
|
||||
|
||||
TEST_F(FeaturePartCutTest, testBarelyIntersecting)
|
||||
{
|
||||
// Arrange
|
||||
_cut->Base.setValue(_boxes[0]);
|
||||
_cut->Tool.setValue(_boxes[5]); // NOLINT magic number
|
||||
|
||||
// Act
|
||||
_cut->execute();
|
||||
Part::TopoShape ts = _cut->Shape.getValue();
|
||||
double volume = PartTestHelpers::getVolume(ts.getShape());
|
||||
double target = 6 - PartTestHelpers::minimalDistance * 3; // NOLINT 3 dimensions in a Volume
|
||||
Base::BoundBox3d bb = ts.getBoundBox();
|
||||
|
||||
// Assert
|
||||
// Using FLOAT, not DOUBLE here so test library comparison is of reasonable precision 1e07
|
||||
// rather than 1e15 See
|
||||
// https://google.github.io/googletest/reference/assertions.html#floating-point
|
||||
EXPECT_FLOAT_EQ(volume, target);
|
||||
// double check using bounds:
|
||||
EXPECT_DOUBLE_EQ(bb.MinX, 0.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MinY, 0.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MinZ, 0.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MaxX, 1.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MaxY, 2.0 - PartTestHelpers::minimalDistance);
|
||||
EXPECT_DOUBLE_EQ(bb.MaxZ, 3.0);
|
||||
}
|
||||
|
||||
TEST_F(FeaturePartCutTest, testMustExecute)
|
||||
{
|
||||
// Assert initially we don't need to execute
|
||||
EXPECT_FALSE(_cut->mustExecute());
|
||||
// Act to change one property
|
||||
_cut->Base.setValue(_boxes[0]);
|
||||
// Assert we still can't execute
|
||||
EXPECT_FALSE(_cut->mustExecute());
|
||||
// Act to complete the properties we need
|
||||
_cut->Tool.setValue(_boxes[1]);
|
||||
// Assert that we now must execute
|
||||
EXPECT_TRUE(_cut->mustExecute());
|
||||
// Act to execute
|
||||
_doc->recompute();
|
||||
// Assert we don't need to execute anymore
|
||||
EXPECT_FALSE(_cut->mustExecute());
|
||||
}
|
||||
|
||||
TEST_F(FeaturePartCutTest, testGetProviderName)
|
||||
{
|
||||
// Act
|
||||
_cut->execute();
|
||||
const char* name = _cut->getViewProviderName();
|
||||
// Assert
|
||||
EXPECT_STREQ(name, "PartGui::ViewProviderBoolean");
|
||||
}
|
||||
|
||||
// See FeaturePartCommon.cpp for a history test. It would be exactly the same and redundant here.
|
||||
199
tests/src/Mod/Part/App/FeaturePartFuse.cpp
Normal file
199
tests/src/Mod/Part/App/FeaturePartFuse.cpp
Normal file
@@ -0,0 +1,199 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "Mod/Part/App/FeaturePartFuse.h"
|
||||
#include <src/App/InitApplication.h>
|
||||
|
||||
#include "PartTestHelpers.h"
|
||||
|
||||
|
||||
class FeaturePartFuseTest: public ::testing::Test, public PartTestHelpers::PartTestHelperClass
|
||||
{
|
||||
protected:
|
||||
static void SetUpTestSuite()
|
||||
{
|
||||
tests::initApplication();
|
||||
}
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
createTestDoc();
|
||||
_fuse = dynamic_cast<Part::Fuse*>(_doc->addObject("Part::Fuse"));
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{}
|
||||
|
||||
Part::Fuse* _fuse = nullptr; // NOLINT Can't be private in a test framework
|
||||
};
|
||||
|
||||
TEST_F(FeaturePartFuseTest, testIntersecting)
|
||||
{
|
||||
// Arrange
|
||||
_fuse->Base.setValue(_boxes[0]);
|
||||
_fuse->Tool.setValue(_boxes[1]);
|
||||
|
||||
// Act
|
||||
_fuse->execute();
|
||||
Part::TopoShape ts = _fuse->Shape.getValue();
|
||||
double volume = PartTestHelpers::getVolume(ts.getShape());
|
||||
Base::BoundBox3d bb = ts.getBoundBox();
|
||||
|
||||
// Assert
|
||||
EXPECT_DOUBLE_EQ(volume, 9.0);
|
||||
// double check using bounds:
|
||||
EXPECT_DOUBLE_EQ(bb.MinX, 0.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MinY, 0.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MinZ, 0.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MaxX, 1.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MaxY, 3.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MaxZ, 3.0);
|
||||
}
|
||||
|
||||
TEST_F(FeaturePartFuseTest, testNonIntersecting)
|
||||
{
|
||||
// Arrange
|
||||
_fuse->Base.setValue(_boxes[0]);
|
||||
_fuse->Tool.setValue(_boxes[2]);
|
||||
|
||||
// Act
|
||||
_fuse->execute();
|
||||
Part::TopoShape ts = _fuse->Shape.getValue();
|
||||
double volume = PartTestHelpers::getVolume(ts.getShape());
|
||||
Base::BoundBox3d bb = ts.getBoundBox();
|
||||
|
||||
// Assert
|
||||
EXPECT_DOUBLE_EQ(volume, 12.0);
|
||||
// double check using bounds:
|
||||
EXPECT_DOUBLE_EQ(bb.MinX, 0.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MinY, 0.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MinZ, 0.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MaxX, 1.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MaxY, 5.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MaxZ, 3.0);
|
||||
}
|
||||
|
||||
TEST_F(FeaturePartFuseTest, testTouching)
|
||||
{
|
||||
// Arrange
|
||||
_fuse->Base.setValue(_boxes[0]);
|
||||
_fuse->Tool.setValue(_boxes[3]);
|
||||
|
||||
// Act
|
||||
_fuse->execute();
|
||||
Part::TopoShape ts = _fuse->Shape.getValue();
|
||||
double volume = PartTestHelpers::getVolume(ts.getShape());
|
||||
Base::BoundBox3d bb = ts.getBoundBox();
|
||||
|
||||
// Assert
|
||||
EXPECT_DOUBLE_EQ(volume, 12.0);
|
||||
// double check using bounds:
|
||||
EXPECT_DOUBLE_EQ(bb.MinX, 0.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MinY, 0.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MinZ, 0.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MaxX, 1.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MaxY, 4.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MaxZ, 3.0);
|
||||
}
|
||||
|
||||
TEST_F(FeaturePartFuseTest, testAlmostTouching)
|
||||
{
|
||||
// Arrange
|
||||
_fuse->Base.setValue(_boxes[0]);
|
||||
_fuse->Tool.setValue(_boxes[4]);
|
||||
|
||||
// Act
|
||||
_fuse->execute();
|
||||
Part::TopoShape ts = _fuse->Shape.getValue();
|
||||
double volume = PartTestHelpers::getVolume(ts.getShape());
|
||||
Base::BoundBox3d bb = ts.getBoundBox();
|
||||
|
||||
// Assert
|
||||
EXPECT_FLOAT_EQ(volume, 12.0); // Use FLOAT to limit precision to 1E07 rather than 1E15
|
||||
// double check using bounds:
|
||||
EXPECT_DOUBLE_EQ(bb.MinX, 0.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MinY, 0.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MinZ, 0.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MaxX, 1.0);
|
||||
EXPECT_FLOAT_EQ(bb.MaxY, 4.0); // Use FLOAT to limit precision to 1E07 rather than 1E15
|
||||
EXPECT_DOUBLE_EQ(bb.MaxZ, 3.0);
|
||||
}
|
||||
|
||||
TEST_F(FeaturePartFuseTest, testBarelyIntersecting)
|
||||
{
|
||||
// Arrange
|
||||
_fuse->Base.setValue(_boxes[0]);
|
||||
_fuse->Tool.setValue(_boxes[5]); // NOLINT magic number
|
||||
|
||||
// Act
|
||||
_fuse->execute();
|
||||
Part::TopoShape ts = _fuse->Shape.getValue();
|
||||
double volume = PartTestHelpers::getVolume(ts.getShape());
|
||||
double target = 12 - PartTestHelpers::minimalDistance * 3; // NOLINT 3 dimensions in a Volume
|
||||
Base::BoundBox3d bb = ts.getBoundBox();
|
||||
|
||||
// Assert
|
||||
// Using FLOAT, not DOUBLE here so test library comparison is of reasonable precision 1e07
|
||||
// rather than 1e15 See
|
||||
// https://google.github.io/googletest/reference/assertions.html#floating-point
|
||||
EXPECT_FLOAT_EQ(volume, target);
|
||||
// double check using bounds:
|
||||
EXPECT_DOUBLE_EQ(bb.MinX, 0.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MinY, 0.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MinZ, 0.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MaxX, 1.0);
|
||||
EXPECT_DOUBLE_EQ(bb.MaxY, 4.0 - PartTestHelpers::minimalDistance);
|
||||
EXPECT_DOUBLE_EQ(bb.MaxZ, 3.0);
|
||||
}
|
||||
|
||||
TEST_F(FeaturePartFuseTest, testMustExecute)
|
||||
{
|
||||
// Assert initially we don't need to execute
|
||||
EXPECT_FALSE(_fuse->mustExecute());
|
||||
// Act to change one property
|
||||
_fuse->Base.setValue(_boxes[0]);
|
||||
// Assert we still can't execute
|
||||
EXPECT_FALSE(_fuse->mustExecute());
|
||||
// Act to complete the properties we need
|
||||
_fuse->Tool.setValue(_boxes[1]);
|
||||
// Assert that we now must execute
|
||||
EXPECT_TRUE(_fuse->mustExecute());
|
||||
// Act to execute
|
||||
_doc->recompute();
|
||||
// Assert we don't need to execute anymore
|
||||
EXPECT_FALSE(_fuse->mustExecute());
|
||||
}
|
||||
|
||||
TEST_F(FeaturePartFuseTest, testGetProviderName)
|
||||
{
|
||||
// Act
|
||||
_fuse->execute();
|
||||
const char* name = _fuse->getViewProviderName();
|
||||
// Assert
|
||||
EXPECT_STREQ(name, "PartGui::ViewProviderBoolean");
|
||||
}
|
||||
|
||||
TEST_F(FeaturePartFuseTest, testRefine)
|
||||
{
|
||||
// Arrange
|
||||
_fuse->Base.setValue(_boxes[0]);
|
||||
_fuse->Tool.setValue(_boxes[1]);
|
||||
|
||||
// Act
|
||||
_fuse->execute();
|
||||
Part::TopoShape ts = _fuse->Shape.getValue();
|
||||
std::vector<Part::TopoShape> subs =
|
||||
ts.getSubTopoShapes(TopAbs_FACE); // TopAbs_WIRE alternate approach
|
||||
// Assert two boxes, plus redundant faces at the joint.
|
||||
EXPECT_EQ(subs.size(), 14);
|
||||
// Act
|
||||
_fuse->Refine.setValue(true);
|
||||
_fuse->execute();
|
||||
ts = _fuse->Shape.getValue();
|
||||
subs = ts.getSubTopoShapes(TopAbs_FACE);
|
||||
// Assert we now just have one big box
|
||||
EXPECT_EQ(subs.size(), 6);
|
||||
}
|
||||
|
||||
// See FeaturePartCommon.cpp for a history test. It would be exactly the same and redundant here.
|
||||
38
tests/src/Mod/Part/App/PartTestHelpers.cpp
Normal file
38
tests/src/Mod/Part/App/PartTestHelpers.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
|
||||
#include "PartTestHelpers.h"
|
||||
|
||||
namespace PartTestHelpers
|
||||
{
|
||||
|
||||
double getVolume(const TopoDS_Shape shape)
|
||||
{
|
||||
GProp_GProps prop;
|
||||
BRepGProp::VolumeProperties(shape, prop);
|
||||
return prop.Mass();
|
||||
}
|
||||
|
||||
void PartTestHelperClass::createTestDoc()
|
||||
{
|
||||
_docName = App::GetApplication().getUniqueDocumentName("test");
|
||||
_doc = App::GetApplication().newDocument(_docName.c_str(), "testUser");
|
||||
std::array<Base::Vector3d, 6> box_origins = {
|
||||
// NOLINT magic number
|
||||
Base::Vector3d(), // First box at 0,0,0
|
||||
Base::Vector3d(0, 1, 0), // Overlap with first box
|
||||
Base::Vector3d(0, 3, 0), // Don't Overlap with first box
|
||||
Base::Vector3d(0, 2, 0), // Touch the first box
|
||||
Base::Vector3d(0, 2 + Base::Precision::Confusion(), 0), // Just Outside of touching
|
||||
// For the Just Inside Of Touching case, go enough that we exceed precision rounding
|
||||
Base::Vector3d(0, 2 - minimalDistance, 0)};
|
||||
|
||||
for (int i = 0; i < _boxes.size(); i++) {
|
||||
auto box = _boxes[i] = static_cast<Part::Box*>(_doc->addObject("Part::Box"));
|
||||
box->Length.setValue(1);
|
||||
box->Width.setValue(2);
|
||||
box->Height.setValue(3);
|
||||
box->Placement.setValue(
|
||||
Base::Placement(box_origins[i], Base::Rotation(), Base::Vector3d()));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace PartTestHelpers
|
||||
25
tests/src/Mod/Part/App/PartTestHelpers.h
Normal file
25
tests/src/Mod/Part/App/PartTestHelpers.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#include <App/Application.h>
|
||||
#include <App/Document.h>
|
||||
#include <Base/Precision.h>
|
||||
#include "Mod/Part/App/FeaturePartBox.h"
|
||||
#include "Mod/Part/App/FeaturePartFuse.h"
|
||||
#include "Mod/Part/App/FeatureFillet.h"
|
||||
#include <BRepGProp.hxx>
|
||||
|
||||
namespace PartTestHelpers
|
||||
{
|
||||
|
||||
double getVolume(TopoDS_Shape shape);
|
||||
|
||||
class PartTestHelperClass
|
||||
{
|
||||
public:
|
||||
App::Document* _doc;
|
||||
std::string _docName;
|
||||
std::array<Part::Box*, 6> _boxes;
|
||||
void createTestDoc();
|
||||
};
|
||||
|
||||
const double minimalDistance = Base::Precision::Confusion() * 1000;
|
||||
|
||||
} // namespace PartTestHelpers
|
||||
Reference in New Issue
Block a user