Files
create/tests/src/Mod/Part/App/WireJoiner.cpp
CalligaroV 374ed64c1f Part/Toponaming: Transfer WireJoiner
* Added test for WireJoiner::setTightBound()
 * Minor modifications and typo

Signed-off-by: CalligaroV <vincenzo.calligaro@gmail.com>
2024-03-26 09:57:46 +01:00

311 lines
12 KiB
C++

// SPDX-License-Identifier: LGPL-2.1-or-later
#include "gtest/gtest.h"
#include "src/App/InitApplication.h"
#include "Mod/Part/App/WireJoiner.h"
#include "PartTestHelpers.h"
#include <BRepBuilderAPI_MakeShape.hxx>
// NOLINTBEGIN(readability-magic-numbers,cppcoreguidelines-avoid-magic-numbers)
using namespace Part;
using namespace PartTestHelpers;
class WireJoinerTest: public ::testing::Test
{
protected:
static void SetUpTestSuite()
{
tests::initApplication();
}
void SetUp() override
{
_docName = App::GetApplication().getUniqueDocumentName("test");
App::GetApplication().newDocument(_docName.c_str(), "testUser");
_hasher = Base::Reference<App::StringHasher>(new App::StringHasher);
ASSERT_EQ(_hasher.getRefCount(), 1);
}
void TearDown() override
{
App::GetApplication().closeDocument(_docName.c_str());
}
private:
std::string _docName;
Data::ElementIDRefs _sid;
App::StringHasherRef _hasher;
};
TEST_F(WireJoinerTest, addShape)
{
// Arrange
// Create various edges that will be used to define the arguments of the various
// WireJoiner::addShape() calls
auto edge1 {BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(1.0, 0.0, 0.0)).Edge()};
auto edge2 {BRepBuilderAPI_MakeEdge(gp_Pnt(1.0, 0.0, 0.0), gp_Pnt(1.0, 1.0, 0.0)).Edge()};
auto edge3 {BRepBuilderAPI_MakeEdge(gp_Pnt(1.0, 1.0, 0.0), gp_Pnt(0.0, 1.0, 0.0)).Edge()};
auto edge4 {BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, 1.0, 0.0), gp_Pnt(0.0, 0.0, 0.0)).Edge()};
// A vector of TopoDS_Shape used as argument for wjvTDS.addShape()
std::vector<TopoDS_Shape> edges {edge1, edge2, edge3, edge4};
// Create various TopoShapes used as arguments for wjvTS.addShape()
auto edge1TS {TopoShape(edge1, 1)};
auto edge2TS {TopoShape(edge2, 2)};
// A wire TopoShape used as argument for wjTS.addShape()
auto wireTS {TopoShape(BRepBuilderAPI_MakeWire(edge1, edge2, edge3).Wire(), 3)};
// An empty TopoShape that will contain the shapes added by wjvTS.addShape()
auto wirevTS {TopoShape(4)};
// An empty TopoShape that will contain the shapes added by wjvTDS.addShape()
auto wirevTDS {TopoShape(5)};
// Create 3 WireJoiner objects, one for every definition of WireJoiner::addShape()
// A WireJoiner object where it will be added a TopoShape without calling WireJoiner::Build()
// afterwards
auto wjTSNotDone {WireJoiner()};
// A WireJoiner object where it will be added a TopoShape
auto wjTS {WireJoiner()};
// A WireJoiner object where it will be added a vector of TopoShapes
auto wjvTS {WireJoiner()};
// A WireJoiner object where it will be added a vector of TopoDS_Shapes
auto wjvTDS {WireJoiner()};
// Act
// Calling only WireJoiner::addShape(). Expected result is that wjTSNotDone.Done() is false
wjTSNotDone.addShape(wireTS);
// Calling WireJoiner::addShape() and then WireJoiner::Build().
// If we don't call WireJoiner::Build() we can't see the effect of WireJoiner::addShape() as it
// adds the shapes in the private member WireJoinerP::sourceEdgeArray
wjTS.addShape(wireTS);
wjTS.Build();
// The wire in wjTS is open, therefor to see the effect of wjTS.addShape() we must call
// wjTS.getOpenWires() and put the result in wireTS
wjTS.getOpenWires(wireTS, nullptr, false);
wjvTS.addShape({edge1TS, edge2TS});
wjvTS.Build();
// The wire in wjvTS is open, therefor to see the effect of wjvTS.addShape() we must call
// wjvTS.getOpenWires() and put the result in wirevTS
wjvTS.getOpenWires(wirevTS, nullptr, false);
wjvTDS.addShape(edges);
wjvTDS.Build();
// The wire in wjvTDS is closed, therefor to see the effect of wjvTDS.addShape() we can smply
// call wjvTDS.Shape() to replace the shape in wirevTDS
wirevTDS.setShape(wjvTDS.Shape());
// Assert
// Check the output of WireJoiner::IsDone().
// It should be true for all the objects that executed also WireJoiner::Build()
// (All except wjTSNotDone)
EXPECT_FALSE(wjTSNotDone.IsDone());
EXPECT_TRUE(wjTS.IsDone());
EXPECT_TRUE(wjvTS.IsDone());
EXPECT_TRUE(wjvTDS.IsDone());
// wireTS is build with 3 edges. The same quantity should be in the shape built
EXPECT_EQ(wireTS.getSubTopoShapes(TopAbs_EDGE).size(), 3);
// wirevTS is build with 2 edges. The same quantity should be in the shape built
EXPECT_EQ(wirevTS.getSubTopoShapes(TopAbs_EDGE).size(), 2);
// wirevTDS is build with 4 edges. The same quantity should be in the shape built
EXPECT_EQ(wirevTDS.getSubTopoShapes(TopAbs_EDGE).size(), 4);
}
TEST_F(WireJoinerTest, setOutline)
{
// Arrange
// Create various edges that will be used for the WireJoiner objects tests
auto edge1 {BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(1.0, 0.0, 0.0)).Edge()};
auto edge2 {BRepBuilderAPI_MakeEdge(gp_Pnt(1.0, 0.0, 0.0), gp_Pnt(1.0, 1.0, 0.0)).Edge()};
auto edge3 {BRepBuilderAPI_MakeEdge(gp_Pnt(1.0, 1.0, 0.0), gp_Pnt(0.0, 0.0, 0.0)).Edge()};
auto edge4 {BRepBuilderAPI_MakeEdge(gp_Pnt(-0.1, -0.1, 0.0), gp_Pnt(-0.1, 1.1, 0.0)).Edge()};
auto edge5 {BRepBuilderAPI_MakeEdge(gp_Pnt(-0.1, 1.1, 0.0), gp_Pnt(1.1, 1.1, 0.0)).Edge()};
auto edge6 {BRepBuilderAPI_MakeEdge(gp_Pnt(1.1, 1.1, 0.0), gp_Pnt(-0.1, -0.1, 0.0)).Edge()};
// A vector of edges used as argument for wjNoOutline.addShape()
std::vector<TopoDS_Shape> edgesNoOutline {edge1, edge2, edge3, edge4, edge5, edge6};
// A vector of edges used as argument for wjOutline.addShape()
std::vector<TopoDS_Shape> edgesOutline {edge1, edge2, edge3, edge4, edge5, edge6};
// To see the effect of setOutline() it is necessary to set the user parameter "Iteration"
// to a value, in this case, less than zero before the WireObjects are initialized.
// To see the correct value for this parameter refer to method WireJoinerP::canShowShape()
auto hParam {App::GetApplication().GetParameterGroupByPath(
"User parameter:BaseApp/Preferences/WireJoiner")};
auto catchIteration {hParam->GetInt("Iteration", 0)};
hParam->SetInt("Iteration", -1);
// A document where there will WireJoiner.Build() will be called having setOutline() set to
// false
auto docNoOutline {App::GetApplication().getActiveDocument()};
auto _docNameOutline {App::GetApplication().getUniqueDocumentName("docOutline")};
App::GetApplication().newDocument(_docNameOutline.c_str(), "docOutlineUser");
// A document where there will WireJoiner.Build() will be called having setOutline() set to true
auto docOutline {App::GetApplication().getActiveDocument()};
// A WireJoiner object where the value of setOutline() will be changed but no shapes will be
// built
auto wjNoBuild {WireJoiner()};
// A WireJoiner object where setOutline() will be set to false
auto wjNoOutline {WireJoiner()};
// A WireJoiner object where setOutline() will be set to true
auto wjOutline {WireJoiner()};
// Reset the parameter to its previous value.
hParam->SetInt("Iteration", catchIteration);
// Act
// Changing only the value of setOutline(). This should set wjNoBuild.IsDone() to false
wjNoBuild.setOutline(true);
// We can see the effect of setOutline by searching, among all the DocumentObjects created by
// the logic, if there are any with a label containing "removed"
// Testing first the Document where WireJoiner::Build() will be executed with setOutline set to
// false
App::GetApplication().setActiveDocument(docNoOutline);
wjNoOutline.addShape(edgesNoOutline);
wjNoOutline.setOutline(false);
wjNoOutline.Build();
auto objsInDoc {docNoOutline->getObjects()};
auto foundRemovedNoOutline {false};
for (const auto& obj : objsInDoc) {
foundRemovedNoOutline =
(std::string(obj->Label.getValue()).find("removed") != std::string::npos);
if (foundRemovedNoOutline) {
break;
}
}
// Then testing the Document where WireJoiner::Build() will be executed with setOutline set to
// true
App::GetApplication().setActiveDocument(docOutline);
wjOutline.addShape(edgesOutline);
// same as wjOutline.setOutline(true);
wjOutline.setOutline();
wjOutline.Build();
objsInDoc = docOutline->getObjects();
auto foundRemovedOutline {false};
for (const auto& obj : objsInDoc) {
foundRemovedOutline =
(std::string(obj->Label.getValue()).find("removed") != std::string::npos);
if (foundRemovedOutline) {
break;
}
}
// Assert
// Without calling wjNoBuild.Build() the value of wjNoBuild.IsDone() should be false even if we
// only changed the value of setOutline()
EXPECT_FALSE(wjNoBuild.IsDone());
// In a document where WireJoiner::Build() is executed with setOutline() set to false there
// shouldn't be DocumentObjects with "removed" in their label
EXPECT_FALSE(foundRemovedNoOutline);
// In a document where WireJoiner::Build() is executed with setOutline() set to true there
// should be at least a DocumentObject with "removed" in its label
EXPECT_TRUE(foundRemovedOutline);
}
TEST_F(WireJoinerTest, setTightBound)
{
// Arrange
// Create various edges that will be used for the WireJoiner objects tests
auto edge1 {BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(1.0, 0.0, 0.0)).Edge()};
auto edge2 {BRepBuilderAPI_MakeEdge(gp_Pnt(1.0, 0.0, 0.0), gp_Pnt(1.0, 1.0, 0.0)).Edge()};
auto edge3 {BRepBuilderAPI_MakeEdge(gp_Pnt(1.0, 1.0, 0.0), gp_Pnt(0.0, 0.0, 0.0)).Edge()};
auto edge4 {BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, 1.0, 0.0), gp_Pnt(1.0, 0.0, 0.0)).Edge()};
// A vector of edges used as argument for wjNoTightBound.addShape()
std::vector<TopoDS_Shape> edgesNoTightBound {edge1, edge2, edge3, edge4};
// A vector of edges used as argument for wjTightBound.addShape()
std::vector<TopoDS_Shape> edgesTightBound {edge1, edge2, edge3, edge4};
// A WireJoiner object where the value of setTightBound() will be changed but no shapes will be
// built
auto wjNoBuild {WireJoiner()};
// A WireJoiner object where setTightBound() will be set to false
auto wjNoTightBound {WireJoiner()};
// A WireJoiner object where setTightBound() will be set to true
auto wjTightBound {WireJoiner()};
// An empty TopoShape that will contain the shapes returned by wjNoTightBound.getOpenWires()
auto wireNoTightBound {TopoShape(1)};
// An empty TopoShape that will contain the shapes returned by wjTightBound.getOpenWires()
auto wireTightBound {TopoShape(2)};
// Act
// Changing only the value of setTightBound(). This should set wjNoBuild.IsDone() to false
wjNoBuild.setTightBound(false);
// To see the effect of setTightBound() we call WireJoiner::Build() and then
// WireJoiner::getOpenWires()
wjNoTightBound.addShape(edgesNoTightBound);
wjNoTightBound.setTightBound(false);
wjNoTightBound.Build();
wjNoTightBound.getOpenWires(wireNoTightBound, nullptr, false);
wjTightBound.addShape(edgesTightBound);
// same as wjTightBound.setTightBound(true);
wjTightBound.setTightBound();
wjTightBound.Build();
wjTightBound.getOpenWires(wireTightBound, nullptr, false);
// Assert
// Without calling wjNoBuild.Build() the value of wjNoBuild.IsDone() should be false even if we
// only changed the value of setTightBound()
EXPECT_FALSE(wjNoBuild.IsDone());
// Calling wjNoTightBound.Build() will put all the edges inside the private object
// WireJoiner::WireJoinerP::openWireCompound.
// In this case the number of edges is equal to 6 because:
// edge1 and edge2 aren't modified => 2 edges
// edge3 and edge4 are both split in 2 edges => 4 edges
// The split is made at the intersection point (0.5, 0.5, 0.0)
EXPECT_EQ(wireNoTightBound.getSubTopoShapes(TopAbs_EDGE).size(), 6);
// Calling wjTightBound.Build() will put inside the private object
// WireJoiner::WireJoinerP::openWireCompound only the edges that don't contribute to the
// creation of any closed wire.
// In this case the number of those edges is equal to 1 and that edge is the one with vertexes
// at the coordinates (0.5, 0.5, 0.0) - (0.0, 1.0, 0.0)
EXPECT_EQ(wireTightBound.getSubTopoShapes(TopAbs_EDGE).size(), 1);
}
// NOLINTEND(readability-magic-numbers,cppcoreguidelines-avoid-magic-numbers)