PD Extrude up to multiple faces or shape

This commit is contained in:
Florian Foinant-Willig
2024-05-26 21:41:22 +02:00
committed by Chris Hennes
parent 526cc024ad
commit 7ffddb6f7d
6 changed files with 93 additions and 14 deletions

View File

@@ -4279,7 +4279,7 @@ TopoShape& TopoShape::makeElementPrismUntil(const TopoShape& _base,
// Check whether the face has limits or not. Unlimited faces have no wire
// Note: Datum planes are always unlimited
if (checkLimits && uptoface.hasSubShape(TopAbs_WIRE)) {
if (checkLimits && _uptoface.shapeType(true) == TopAbs_FACE && uptoface.hasSubShape(TopAbs_WIRE)) {
TopoDS_Face face = TopoDS::Face(uptoface.getShape());
bool remove_limits = false;
// Remove the limits of the upToFace so that the extrusion works even if profile is larger

View File

@@ -375,6 +375,7 @@ void FeatureExtrude::updateProperties(const std::string &method)
bool isMidplaneEnabled = false;
bool isReversedEnabled = false;
bool isUpToFaceEnabled = false;
bool isUpToShapeEnabled = false;
bool isTaperVisible = false;
bool isTaper2Visible = false;
if (method == "Length") {
@@ -409,6 +410,7 @@ void FeatureExtrude::updateProperties(const std::string &method)
}
else if (method == "UpToShape") {
isReversedEnabled = true;
isUpToShapeEnabled = true;
}
Length.setReadOnly(!isLengthEnabled);
@@ -420,6 +422,7 @@ void FeatureExtrude::updateProperties(const std::string &method)
Midplane.setReadOnly(!isMidplaneEnabled);
Reversed.setReadOnly(!isReversedEnabled);
UpToFace.setReadOnly(!isUpToFaceEnabled);
UpToShape.setReadOnly(!isUpToShapeEnabled);
}
void FeatureExtrude::setupObject()
@@ -558,7 +561,7 @@ App::DocumentObjectExecReturn* FeatureExtrude::buildExtrusion(ExtrudeOptions opt
TopoShape prism(0, getDocument()->getStringHasher());
if (method == "UpToFirst" || method == "UpToLast" || method == "UpToFace") {
if (method == "UpToFirst" || method == "UpToLast" || method == "UpToFace" || method == "UpToShape") {
// Note: This will return an unlimited planar face if support is a datum plane
TopoShape supportface = getTopoShapeSupportFace();
supportface.move(invObjLoc);
@@ -567,18 +570,33 @@ App::DocumentObjectExecReturn* FeatureExtrude::buildExtrusion(ExtrudeOptions opt
dir.Reverse();
}
// Find a valid face or datum plane to extrude up to
TopoShape upToFace;
if (method != "UpToShape") {
if (method == "UpToFace") {
getUpToFaceFromLinkSub(upToFace, UpToFace);
upToFace.move(invObjLoc);
TopoShape upToShape;
int faceCount = 1;
// Find a valid shape, face or datum plane to extrude up to
if (method == "UpToFace") {
getUpToFaceFromLinkSub(upToShape, UpToFace);
upToShape.move(invObjLoc);
faceCount = 1;
}
else if (method == "UpToShape") {
try {
faceCount = getUpToShapeFromLinkSubList(upToShape, UpToShape);
upToShape.move(invObjLoc);
}
catch (Base::ValueError&){
//no shape selected use the base
upToShape = base;
faceCount = 0;
}
getUpToFace(upToFace, base, supportface, sketchshape, method, dir);
addOffsetToFace(upToFace, dir, Offset.getValue());
}
if (faceCount == 1) {
getUpToFace(upToShape, base, supportface, sketchshape, method, dir);
addOffsetToFace(upToShape, dir, Offset.getValue());
}
else if (fabs(Offset.getValue()) > Precision::Confusion()){
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Extrude: Can only offset one face"));
}
if (!supportface.hasSubShape(TopAbs_WIRE)) {
supportface = TopoShape();
@@ -588,7 +606,7 @@ App::DocumentObjectExecReturn* FeatureExtrude::buildExtrusion(ExtrudeOptions opt
base.isNull() ? TopoShape::PrismMode::None : TopoShape::PrismMode::CutFromBase;
prism = base.makeElementPrismUntil(sketchshape,
supportface,
upToFace,
upToShape,
dir,
mode,
false /*CheckUpToFaceLimits.getValue()*/);
@@ -630,7 +648,7 @@ App::DocumentObjectExecReturn* FeatureExtrude::buildExtrusion(ExtrudeOptions opt
prism.makeElementPrismUntil(base,
sketchshape,
supportface,
upToFace,
upToShape,
dir,
TopoShape::PrismMode::None,
true /*CheckUpToFaceLimits.getValue()*/);

View File

@@ -55,6 +55,7 @@ Pad::Pad()
ADD_PROPERTY_TYPE(ReferenceAxis, (nullptr), "Pad", App::Prop_None, "Reference axis of direction");
ADD_PROPERTY_TYPE(AlongSketchNormal, (true), "Pad", App::Prop_None, "Measure pad length along the sketch normal direction");
ADD_PROPERTY_TYPE(UpToFace, (nullptr), "Pad", App::Prop_None, "Face where pad will end");
ADD_PROPERTY_TYPE(UpToShape, (nullptr), "Pad", App::Prop_None, "Faces or shape(s) where pad will end");
ADD_PROPERTY_TYPE(Offset, (0.0), "Pad", App::Prop_None, "Offset from face in which pad will end");
Offset.setConstraints(&signedLengthConstraint);
ADD_PROPERTY_TYPE(TaperAngle, (0.0), "Pad", App::Prop_None, "Taper angle");

View File

@@ -39,7 +39,7 @@ using namespace PartDesign;
/* TRANSLATOR PartDesign::Pocket */
const char* Pocket::TypeEnums[]= {"Length", "ThroughAll", "UpToFirst", "UpToFace", "TwoLengths", nullptr};
const char* Pocket::TypeEnums[]= {"Length", "ThroughAll", "UpToFirst", "UpToFace", "TwoLengths", "UpToShape", nullptr};
PROPERTY_SOURCE(PartDesign::Pocket, PartDesign::FeatureExtrude)
@@ -56,6 +56,7 @@ Pocket::Pocket()
ADD_PROPERTY_TYPE(ReferenceAxis, (nullptr), "Pocket", App::Prop_None, "Reference axis of direction");
ADD_PROPERTY_TYPE(AlongSketchNormal, (true), "Pocket", App::Prop_None, "Measure pocket length along the sketch normal direction");
ADD_PROPERTY_TYPE(UpToFace, (nullptr), "Pocket", App::Prop_None, "Face where pocket will end");
ADD_PROPERTY_TYPE(UpToShape, (nullptr), "Pocket", App::Prop_None, "Face(s) or shape(s) where pocket will end");
ADD_PROPERTY_TYPE(Offset, (0.0), "Pocket", App::Prop_None, "Offset from face in which pocket will end");
Offset.setConstraints(&signedLengthConstraint);
ADD_PROPERTY_TYPE(TaperAngle, (0.0), "Pocket", App::Prop_None, "Taper angle");

View File

@@ -75,6 +75,7 @@ ProfileBased::ProfileBased()
ADD_PROPERTY_TYPE(Midplane, (0), "SketchBased", App::Prop_None, "Extrude symmetric to sketch face");
ADD_PROPERTY_TYPE(Reversed, (0), "SketchBased", App::Prop_None, "Reverse extrusion direction");
ADD_PROPERTY_TYPE(UpToFace, (nullptr), "SketchBased", (App::PropertyType)(App::Prop_None), "Face where feature will end");
ADD_PROPERTY_TYPE(UpToShape, (nullptr), "SketchBased", (App::PropertyType)(App::Prop_None), "Shape where feature will end");
ADD_PROPERTY_TYPE(AllowMultiFace, (false), "SketchBased", App::Prop_None, "Allow multiple faces in profile");
}
@@ -682,6 +683,58 @@ void ProfileBased::getUpToFaceFromLinkSub(TopoShape& upToFace, const App::Proper
}
}
int ProfileBased::getUpToShapeFromLinkSubList(TopoShape& upToShape, const App::PropertyLinkSubList& refShape)
{
int ret = 0;
auto subSets = refShape.getSubListValues();
std::vector<TopoShape> faceList;
for (auto &subSet : subSets){
auto ref = subSet.first;
if (ref->isDerivedFrom<App::Plane>()) {
faceList.push_back(makeTopoShapeFromPlane(ref));
ret ++;
} else {
if (!ref->isDerivedFrom<Part::Feature>())
throw Base::TypeError("SketchBased: Must be face of a feature");
auto subStrings = subSet.second;
if (subStrings.empty() || subStrings[0].empty()) {
TopoShape baseShape = Part::Feature::getTopoShape(ref, nullptr, true);
for (auto face : baseShape.getSubTopoShapes(TopAbs_FACE)){
faceList.push_back(face);
ret ++;
}
}
else {
for (auto &subString : subStrings){
auto shape = Part::Feature::getTopoShape(ref, subString.c_str(), true);
TopoShape face = shape;
face = face.makeElementFace();
if (face.isNull()) {
throw Base::ValueError("SketchBased: Failed to extract face");
}
faceList.push_back(face);
ret ++;
}
}
}
}
if (ret == 0){
throw Base::ValueError("SketchBased: No face selected");
}
upToShape = faceList[0];
if (ret == 1){
return 1;
}
// create a unique shell with all selected faces
upToShape = upToShape.makeElementCompound(faceList);
return ret;
}
void ProfileBased::getFaceFromLinkSub(TopoDS_Face& upToFace, const App::PropertyLinkSub& refFace)
{

View File

@@ -57,6 +57,8 @@ public:
App::PropertyBool Midplane;
/// Face to extrude up to
App::PropertyLinkSub UpToFace;
/// Shape to extrude up to
App::PropertyLinkSubList UpToShape;
App::PropertyBool AllowMultiFace;
@@ -164,6 +166,10 @@ protected:
/// Extract a face from a given LinkSub
static void getUpToFaceFromLinkSub(TopoShape& upToFace, const App::PropertyLinkSub& refFace);
/// Create a shape with shapes and faces from a given LinkSubList
/// return 0 if almost one full shape is selected else the face count
int getUpToShapeFromLinkSubList(TopoShape& upToShape, const App::PropertyLinkSubList& refShape); // TODO static
/// Find a valid face to extrude up to
static void getUpToFace(TopoShape& upToFace,
const TopoShape& support,