PartDesign: Introduce ability to disable single-solid rule
This adds "SingleSolidRuleMode" enum that controls if PartDesign will enforce singular solid. By default the single-solid is enforced so nothing changes for the user, it must be explicitly disabled by setting new Allow Compound boolean property on a given body. Default for this value is controled using user parameter under Mod/PartDesign/AllowCompoundDefault
This commit is contained in:
committed by
Adrián Insaurralde Avalos
parent
d0a35c8c03
commit
e4ed0d883f
@@ -47,9 +47,8 @@ public:
|
||||
/**
|
||||
* The final feature of the body it is associated with.
|
||||
* Note: tip may either point to the BaseFeature or to some feature inside the Group list.
|
||||
* in case it points to the model the PartDesign::Body guaranties that it is a solid.
|
||||
*/
|
||||
App::PropertyLink Tip;
|
||||
App::PropertyLink Tip;
|
||||
|
||||
/**
|
||||
* A base object of the body, serves as a base object for the first feature of the body.
|
||||
|
||||
@@ -40,7 +40,17 @@ using namespace PartDesign;
|
||||
PROPERTY_SOURCE(PartDesign::Body, Part::BodyBase)
|
||||
|
||||
Body::Body() {
|
||||
_GroupTouched.setStatus(App::Property::Output,true);
|
||||
ADD_PROPERTY_TYPE(AllowCompound, (false), "Experimental", App::Prop_None, "Allow multiple solids in Body (experimental)");
|
||||
|
||||
_GroupTouched.setStatus(App::Property::Output, true);
|
||||
|
||||
static Base::Reference<ParameterGrp> hGrp = App::GetApplication()
|
||||
.GetUserParameter()
|
||||
.GetGroup("BaseApp/Preferences/Mod/PartDesign");
|
||||
|
||||
auto allowCompoundDefaultValue = hGrp->GetBool("AllowCompoundDefault", false);
|
||||
|
||||
ADD_PROPERTY(AllowCompound, (allowCompoundDefaultValue));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -428,7 +438,7 @@ void Body::onSettingDocument() {
|
||||
Part::BodyBase::onSettingDocument();
|
||||
}
|
||||
|
||||
void Body::onChanged (const App::Property* prop) {
|
||||
void Body::onChanged(const App::Property* prop) {
|
||||
// we neither load a project nor perform undo/redo
|
||||
if (!this->isRestoring()
|
||||
&& this->getDocument()
|
||||
@@ -438,7 +448,6 @@ void Body::onChanged (const App::Property* prop) {
|
||||
auto first = Group.getValues().empty() ? nullptr : Group.getValues().front();
|
||||
|
||||
if (BaseFeature.getValue()) {
|
||||
|
||||
//setup the FeatureBase if needed
|
||||
if (!first || !first->isDerivedFrom(FeatureBase::getClassTypeId())) {
|
||||
bf = static_cast<FeatureBase*>(getDocument()->addObject("PartDesign::FeatureBase", "BaseFeature"));
|
||||
@@ -452,17 +461,26 @@ void Body::onChanged (const App::Property* prop) {
|
||||
}
|
||||
}
|
||||
|
||||
if (bf && (bf->BaseFeature.getValue() != BaseFeature.getValue()))
|
||||
if (bf && (bf->BaseFeature.getValue() != BaseFeature.getValue())) {
|
||||
bf->BaseFeature.setValue(BaseFeature.getValue());
|
||||
}
|
||||
}
|
||||
else if( prop == &Group ) {
|
||||
|
||||
else if (prop == &Group) {
|
||||
//if the FeatureBase was deleted we set the BaseFeature link to nullptr
|
||||
if (BaseFeature.getValue() &&
|
||||
(Group.getValues().empty() || !Group.getValues().front()->isDerivedFrom(FeatureBase::getClassTypeId()))) {
|
||||
BaseFeature.setValue(nullptr);
|
||||
}
|
||||
}
|
||||
else if (prop == &AllowCompound) {
|
||||
// As disallowing compounds can break the model we need to recompute the whole tree.
|
||||
// This will inform user about first place where there is more than one solid.
|
||||
if (!AllowCompound.getValue()) {
|
||||
for (auto feature : getFullModel()) {
|
||||
feature->enforceRecompute();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Part::BodyBase::onChanged(prop);
|
||||
|
||||
@@ -41,6 +41,7 @@ class PartDesignExport Body : public Part::BodyBase
|
||||
PROPERTY_HEADER_WITH_OVERRIDE(PartDesign::Body);
|
||||
|
||||
public:
|
||||
App::PropertyBool AllowCompound;
|
||||
|
||||
/// True if this body feature is active or was active when the document was last closed
|
||||
//App::PropertyBool IsActive;
|
||||
|
||||
@@ -91,10 +91,17 @@ short Feature::mustExecute() const
|
||||
// TODO: Toponaming April 2024 Deprecated in favor of TopoShape method. Remove when possible.
|
||||
TopoDS_Shape Feature::getSolid(const TopoDS_Shape& shape)
|
||||
{
|
||||
if (shape.IsNull())
|
||||
if (shape.IsNull()) {
|
||||
Standard_Failure::Raise("Shape is null");
|
||||
}
|
||||
|
||||
// If single solid rule is not enforced we simply return the shape as is
|
||||
if (singleSolidRuleMode() != Feature::SingleSolidRuleMode::Enforced) {
|
||||
return shape;
|
||||
}
|
||||
|
||||
TopExp_Explorer xp;
|
||||
xp.Init(shape,TopAbs_SOLID);
|
||||
xp.Init(shape, TopAbs_SOLID);
|
||||
if (xp.More()) {
|
||||
return xp.Current();
|
||||
}
|
||||
@@ -107,12 +114,19 @@ TopoShape Feature::getSolid(const TopoShape& shape)
|
||||
if (shape.isNull()) {
|
||||
throw Part::NullShapeException("Null shape");
|
||||
}
|
||||
|
||||
// If single solid rule is not enforced we simply return the shape as is
|
||||
if (singleSolidRuleMode() != Feature::SingleSolidRuleMode::Enforced) {
|
||||
return shape;
|
||||
}
|
||||
|
||||
int count = shape.countSubShapes(TopAbs_SOLID);
|
||||
if(count) {
|
||||
auto res = shape.getSubTopoShape(TopAbs_SOLID,1);
|
||||
if (count) {
|
||||
auto res = shape.getSubTopoShape(TopAbs_SOLID, 1);
|
||||
res.fixSolidOrientation();
|
||||
return res;
|
||||
}
|
||||
|
||||
return shape;
|
||||
}
|
||||
|
||||
@@ -153,12 +167,24 @@ int Feature::countSolids(const TopoDS_Shape& shape, TopAbs_ShapeEnum type)
|
||||
|
||||
bool Feature::isSingleSolidRuleSatisfied(const TopoDS_Shape& shape, TopAbs_ShapeEnum type)
|
||||
{
|
||||
if (singleSolidRuleMode() == Feature::SingleSolidRuleMode::Disabled) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int solidCount = countSolids(shape, type);
|
||||
|
||||
return solidCount <= 1;
|
||||
}
|
||||
|
||||
|
||||
Feature::SingleSolidRuleMode Feature::singleSolidRuleMode()
|
||||
{
|
||||
auto body = getFeatureBody();
|
||||
auto areCompoundSolidsAllowed = body->AllowCompound.getValue();
|
||||
|
||||
return areCompoundSolidsAllowed ? SingleSolidRuleMode::Disabled : SingleSolidRuleMode::Enforced;
|
||||
}
|
||||
|
||||
const gp_Pnt Feature::getPointFromFace(const TopoDS_Face& f)
|
||||
{
|
||||
if (!f.Infinite()) {
|
||||
|
||||
@@ -52,6 +52,8 @@ class PartDesignExport Feature : public Part::Feature, public App::SuppressibleE
|
||||
public:
|
||||
Feature();
|
||||
|
||||
enum SingleSolidRuleMode { Disabled = 0, Enforced = 1 };
|
||||
|
||||
/// Base feature which this feature will be fused into or cut out of
|
||||
App::PropertyLink BaseFeature;
|
||||
App::PropertyLinkHidden _Body;
|
||||
@@ -96,14 +98,15 @@ protected:
|
||||
* Get a solid of the given shape. If no solid is found an exception is raised.
|
||||
*/
|
||||
// TODO: Toponaming April 2024 Deprecated in favor of TopoShape method. Remove when possible.
|
||||
static TopoDS_Shape getSolid(const TopoDS_Shape&);
|
||||
TopoDS_Shape getSolid(const TopoDS_Shape&);
|
||||
TopoShape getSolid(const TopoShape&);
|
||||
static int countSolids(const TopoDS_Shape&, TopAbs_ShapeEnum type = TopAbs_SOLID);
|
||||
|
||||
/**
|
||||
* Checks if the single-solid body rule is fulfilled.
|
||||
*/
|
||||
static bool isSingleSolidRuleSatisfied(const TopoDS_Shape&, TopAbs_ShapeEnum type = TopAbs_SOLID);
|
||||
bool isSingleSolidRuleSatisfied(const TopoDS_Shape&, TopAbs_ShapeEnum type = TopAbs_SOLID);
|
||||
SingleSolidRuleMode singleSolidRuleMode();
|
||||
|
||||
/// Grab any point from the given face
|
||||
static const gp_Pnt getPointFromFace(const TopoDS_Face& f);
|
||||
|
||||
Reference in New Issue
Block a user