* fix #17468 recursively unpack compounds for boolean fuse * fix and into &&, add ctest case for multifuse with compounds and recursive compounds * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * remove unneeded duplicated code - allow Part::Common to be created with a single object (compound or shape) - will result in Unity and possibly a warning message * prevent endless loop in case of endless recursive compounds as suggested in chat * Update src/Mod/Part/App/FeaturePartFuse.cpp Co-authored-by: Benjamin Nauck <benjamin@nauck.se> * implemented suggestion by wwmayer --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Benjamin Nauck <benjamin@nauck.se>
This commit is contained in:
@@ -102,12 +102,15 @@ App::DocumentObjectExecReturn *MultiFuse::execute()
|
||||
TopoShape compoundOfArguments;
|
||||
|
||||
// if only one source shape, and it is a compound - fuse children of the compound
|
||||
if (shapes.size() == 1) {
|
||||
const int maxIterations = 1'000'000; // will trigger "not enough shape objects linked" error below if ever reached
|
||||
for (int i = 0; shapes.size() == 1 && i < maxIterations; ++i) {
|
||||
compoundOfArguments = shapes[0];
|
||||
if (compoundOfArguments.getShape().ShapeType() == TopAbs_COMPOUND) {
|
||||
shapes.clear();
|
||||
shapes = compoundOfArguments.getSubTopoShapes();
|
||||
argumentsAreInCompound = true;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -368,23 +368,7 @@ void CmdPartCommon::activated(int iMsg)
|
||||
std::vector<Gui::SelectionObject> Sel =
|
||||
getSelection().getSelectionEx(nullptr, App::DocumentObject::getClassTypeId(), Gui::ResolveMode::FollowLink);
|
||||
|
||||
//test if selected object is a compound, and if it is, look how many children it has...
|
||||
std::size_t numShapes = 0;
|
||||
if (Sel.size() == 1){
|
||||
numShapes = 1; //to be updated later in code, if
|
||||
Gui::SelectionObject selobj = Sel[0];
|
||||
TopoDS_Shape sh = Part::Feature::getShape(selobj.getObject());
|
||||
if (sh.ShapeType() == TopAbs_COMPOUND) {
|
||||
numShapes = 0;
|
||||
TopoDS_Iterator it(sh);
|
||||
for (; it.More(); it.Next()) {
|
||||
++numShapes;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
numShapes = Sel.size();
|
||||
}
|
||||
if (numShapes < 2) {
|
||||
if (Sel.empty()) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("Please select two shapes or more. Or, select one compound containing two or more shapes to compute the intersection between."));
|
||||
return;
|
||||
@@ -450,12 +434,15 @@ void CmdPartFuse::activated(int iMsg)
|
||||
numShapes = 1; //to be updated later in code
|
||||
Gui::SelectionObject selobj = Sel[0];
|
||||
TopoDS_Shape sh = Part::Feature::getShape(selobj.getObject());
|
||||
if (sh.ShapeType() == TopAbs_COMPOUND) {
|
||||
while (numShapes==1 && sh.ShapeType() == TopAbs_COMPOUND) {
|
||||
numShapes = 0;
|
||||
TopoDS_Iterator it(sh);
|
||||
TopoDS_Shape last;
|
||||
for (; it.More(); it.Next()) {
|
||||
++numShapes;
|
||||
last = it.Value();
|
||||
}
|
||||
sh = last;
|
||||
}
|
||||
} else {
|
||||
numShapes = Sel.size();
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "Mod/Part/App/FeaturePartFuse.h"
|
||||
#include <src/App/InitApplication.h>
|
||||
#include "Mod/Part/App/FeatureCompound.h"
|
||||
|
||||
#include "PartTestHelpers.h"
|
||||
|
||||
@@ -20,12 +21,14 @@ protected:
|
||||
{
|
||||
createTestDoc();
|
||||
_fuse = dynamic_cast<Part::Fuse*>(_doc->addObject("Part::Fuse"));
|
||||
_multiFuse = dynamic_cast<Part::MultiFuse*>(_doc->addObject("Part::MultiFuse"));
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{}
|
||||
|
||||
Part::Fuse* _fuse = nullptr; // NOLINT Can't be private in a test framework
|
||||
Part::Fuse* _fuse = nullptr; // NOLINT Can't be private in a test framework
|
||||
Part::MultiFuse* _multiFuse = nullptr; // NOLINT Can't be private in a test framework
|
||||
};
|
||||
|
||||
TEST_F(FeaturePartFuseTest, testIntersecting)
|
||||
@@ -51,6 +54,64 @@ TEST_F(FeaturePartFuseTest, testIntersecting)
|
||||
EXPECT_DOUBLE_EQ(bb.MaxZ, 3.0);
|
||||
}
|
||||
|
||||
TEST_F(FeaturePartFuseTest, testCompound)
|
||||
{
|
||||
// Arrange
|
||||
Part::Compound* _compound = nullptr;
|
||||
_compound = dynamic_cast<Part::Compound*>(_doc->addObject("Part::Compound"));
|
||||
_compound->Links.setValues({_boxes[0], _boxes[1]});
|
||||
_multiFuse->Shapes.setValues({_compound});
|
||||
|
||||
// Act
|
||||
_compound->execute();
|
||||
_multiFuse->execute();
|
||||
Part::TopoShape ts = _multiFuse->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, testRecursiveCompound)
|
||||
{
|
||||
// Arrange
|
||||
Part::Compound* _compound[3] = {nullptr};
|
||||
int t;
|
||||
for (t = 0; t < 3; t++) {
|
||||
_compound[t] = dynamic_cast<Part::Compound*>(_doc->addObject("Part::Compound"));
|
||||
}
|
||||
_compound[0]->Links.setValues({_boxes[0], _boxes[1]});
|
||||
_compound[1]->Links.setValues({_compound[0]});
|
||||
_compound[2]->Links.setValues({_compound[1]});
|
||||
_multiFuse->Shapes.setValues({_compound[2]});
|
||||
|
||||
// Act
|
||||
for (t = 0; t < 3; t++) {
|
||||
_compound[t]->execute();
|
||||
}
|
||||
_multiFuse->execute();
|
||||
Part::TopoShape ts = _multiFuse->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
|
||||
|
||||
Reference in New Issue
Block a user