Create Base property for SketchBased features and changed Pad to use it
This commit is contained in:
parent
417576d5eb
commit
6235385c5a
|
@ -86,6 +86,22 @@ const Part::TopoShape Body::getPreviousSolid(const PartDesign::Feature* f)
|
||||||
return static_cast<const PartDesign::Feature*>(*it)->Shape.getShape();
|
return static_cast<const PartDesign::Feature*>(*it)->Shape.getShape();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
App::DocumentObject* Body::getTipSolidFeature()
|
||||||
|
{
|
||||||
|
std::vector<App::DocumentObject*> features = Model.getValues();
|
||||||
|
if (features.empty()) return NULL;
|
||||||
|
std::vector<App::DocumentObject*>::const_iterator it = std::find(features.begin(), features.end(), Tip.getValue());
|
||||||
|
|
||||||
|
// Skip sketches
|
||||||
|
while (!(*it)->getTypeId().isDerivedFrom(PartDesign::Feature::getClassTypeId())) {
|
||||||
|
if (it == features.begin())
|
||||||
|
return NULL;
|
||||||
|
it--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *it;
|
||||||
|
}
|
||||||
|
|
||||||
const bool Body::hasFeature(const App::DocumentObject* f)
|
const bool Body::hasFeature(const App::DocumentObject* f)
|
||||||
{
|
{
|
||||||
std::vector<App::DocumentObject*> features = Model.getValues();
|
std::vector<App::DocumentObject*> features = Model.getValues();
|
||||||
|
|
|
@ -58,6 +58,14 @@ public:
|
||||||
/// Get the tip shape
|
/// Get the tip shape
|
||||||
const Part::TopoShape getTipShape();
|
const Part::TopoShape getTipShape();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return Tip feature if it is a solid. Otherwise, go backwards in the Model and
|
||||||
|
* find the first feature that is a solid (i.e. Sketches are skipped)
|
||||||
|
* This is used by SketchBased features to determine the shape they should fuse with or cut out off
|
||||||
|
* NOTE: Currently only PartDesign features are accepted as TipSolidFeatures
|
||||||
|
*/
|
||||||
|
App::DocumentObject *getTipSolidFeature();
|
||||||
|
|
||||||
/// Return the shape of the feature preceding this feature
|
/// Return the shape of the feature preceding this feature
|
||||||
const Part::TopoShape getPreviousSolid(const PartDesign::Feature* f);
|
const Part::TopoShape getPreviousSolid(const PartDesign::Feature* f);
|
||||||
|
|
||||||
|
|
|
@ -96,7 +96,20 @@ App::DocumentObjectExecReturn *Pad::execute(void)
|
||||||
return new App::DocumentObjectExecReturn(e.what());
|
return new App::DocumentObjectExecReturn(e.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TopoDS_Shape support;
|
||||||
|
try {
|
||||||
|
support = getSupportShape();
|
||||||
|
} catch (const Base::Exception&) {
|
||||||
|
// ignore, because support isn't mandatory
|
||||||
|
support = TopoDS_Shape();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
// Find Body feature which owns this Pad and get the shape of the feature preceding this one for fusing
|
// Find Body feature which owns this Pad and get the shape of the feature preceding this one for fusing
|
||||||
|
// This method was rejected in favour of the Base property because it makes the feature atomic (independent of the
|
||||||
|
// Body object). See
|
||||||
|
// https://sourceforge.net/apps/phpbb/free-cad/viewtopic.php?f=19&t=3831
|
||||||
|
// https://sourceforge.net/apps/phpbb/free-cad/viewtopic.php?f=19&t=3855
|
||||||
PartDesign::Body* body = getBody();
|
PartDesign::Body* body = getBody();
|
||||||
if (body == NULL) {
|
if (body == NULL) {
|
||||||
return new App::DocumentObjectExecReturn(
|
return new App::DocumentObjectExecReturn(
|
||||||
|
@ -113,6 +126,7 @@ App::DocumentObjectExecReturn *Pad::execute(void)
|
||||||
support = TopoDS_Shape();
|
support = TopoDS_Shape();
|
||||||
else
|
else
|
||||||
support = prevShape._Shape;
|
support = prevShape._Shape;
|
||||||
|
*/
|
||||||
|
|
||||||
// get the Sketch plane
|
// get the Sketch plane
|
||||||
Base::Placement SketchPos = sketch->Placement.getValue();
|
Base::Placement SketchPos = sketch->Placement.getValue();
|
||||||
|
@ -184,13 +198,22 @@ App::DocumentObjectExecReturn *Pad::execute(void)
|
||||||
prism = refineShapeIfActive(prism);
|
prism = refineShapeIfActive(prism);
|
||||||
this->AddShape.setValue(prism);
|
this->AddShape.setValue(prism);
|
||||||
|
|
||||||
// if the sketch has a support fuse them to get one result object
|
// if the Base property has a valid shape, fuse the prism into it
|
||||||
if (!support.IsNull()) {
|
TopoDS_Shape base;
|
||||||
|
try {
|
||||||
|
base = getBaseShape();
|
||||||
|
base.Move(invObjLoc);
|
||||||
|
} catch (const Base::Exception&) {
|
||||||
|
// fall back to support (for legacy features)
|
||||||
|
base = support;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!base.IsNull()) {
|
||||||
// Let's call algorithm computing a fuse operation:
|
// Let's call algorithm computing a fuse operation:
|
||||||
BRepAlgoAPI_Fuse mkFuse(support, prism);
|
BRepAlgoAPI_Fuse mkFuse(base, prism);
|
||||||
// Let's check if the fusion has been successful
|
// Let's check if the fusion has been successful
|
||||||
if (!mkFuse.IsDone())
|
if (!mkFuse.IsDone())
|
||||||
return new App::DocumentObjectExecReturn("Pad: Fusion with support failed");
|
return new App::DocumentObjectExecReturn("Pad: Fusion with base feature failed");
|
||||||
TopoDS_Shape result = mkFuse.Shape();
|
TopoDS_Shape result = mkFuse.Shape();
|
||||||
// we have to get the solids (fuse sometimes creates compounds)
|
// we have to get the solids (fuse sometimes creates compounds)
|
||||||
TopoDS_Shape solRes = this->getSolid(result);
|
TopoDS_Shape solRes = this->getSolid(result);
|
||||||
|
|
|
@ -98,6 +98,7 @@ PROPERTY_SOURCE(PartDesign::SketchBased, PartDesign::Feature)
|
||||||
|
|
||||||
SketchBased::SketchBased()
|
SketchBased::SketchBased()
|
||||||
{
|
{
|
||||||
|
ADD_PROPERTY(Base,(0));
|
||||||
ADD_PROPERTY_TYPE(Sketch,(0),"SketchBased", App::Prop_None, "Reference to sketch");
|
ADD_PROPERTY_TYPE(Sketch,(0),"SketchBased", App::Prop_None, "Reference to sketch");
|
||||||
ADD_PROPERTY_TYPE(Midplane,(0),"SketchBased", App::Prop_None, "Extrude symmetric to sketch face");
|
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(Reversed, (0),"SketchBased", App::Prop_None, "Reverse extrusion direction");
|
||||||
|
@ -231,6 +232,26 @@ const TopoDS_Shape& SketchBased::getSupportShape() const {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const TopoDS_Shape& SketchBased::getBaseShape() const {
|
||||||
|
App::DocumentObject* BaseLink = Base.getValue();
|
||||||
|
if (BaseLink == NULL) throw Base::Exception("Base property not set");
|
||||||
|
Part::Feature* BaseObject = NULL;
|
||||||
|
if (BaseLink->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId()))
|
||||||
|
BaseObject = static_cast<Part::Feature*>(BaseLink);
|
||||||
|
|
||||||
|
if (BaseObject == NULL)
|
||||||
|
throw Base::Exception("No base feature linked");
|
||||||
|
|
||||||
|
const TopoDS_Shape& result = BaseObject->Shape.getValue();
|
||||||
|
if (result.IsNull())
|
||||||
|
throw Base::Exception("Base feature's shape is invalid");
|
||||||
|
TopExp_Explorer xp (result, TopAbs_SOLID);
|
||||||
|
if (!xp.More())
|
||||||
|
throw Base::Exception("Base feature's shape is not a solid");
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
int SketchBased::getSketchAxisCount(void) const
|
int SketchBased::getSketchAxisCount(void) const
|
||||||
{
|
{
|
||||||
Part::Part2DObject *sketch = static_cast<Part::Part2DObject*>(Sketch.getValue());
|
Part::Part2DObject *sketch = static_cast<Part::Part2DObject*>(Sketch.getValue());
|
||||||
|
|
|
@ -44,7 +44,10 @@ class PartDesignExport SketchBased : public PartDesign::Feature
|
||||||
public:
|
public:
|
||||||
SketchBased();
|
SketchBased();
|
||||||
|
|
||||||
/// Common properties for all sketch based features
|
// Common properties for all sketch based features
|
||||||
|
/// Base feature which this feature will be fused into or cut out of
|
||||||
|
App::PropertyLink Base;
|
||||||
|
/// Sketch used to create this feature
|
||||||
App::PropertyLink Sketch;
|
App::PropertyLink Sketch;
|
||||||
/// Reverse extrusion direction
|
/// Reverse extrusion direction
|
||||||
App::PropertyBool Reversed;
|
App::PropertyBool Reversed;
|
||||||
|
@ -72,6 +75,8 @@ public:
|
||||||
Part::Feature* getSupport() const;
|
Part::Feature* getSupport() const;
|
||||||
/// Returns the sketch support shape (if any)
|
/// Returns the sketch support shape (if any)
|
||||||
const TopoDS_Shape& getSupportShape() const;
|
const TopoDS_Shape& getSupportShape() const;
|
||||||
|
/// Returns the base property's shape (if any)
|
||||||
|
const TopoDS_Shape& getBaseShape() const;
|
||||||
|
|
||||||
/// retrieves the number of axes in the linked sketch (defined as construction lines)
|
/// retrieves the number of axes in the linked sketch (defined as construction lines)
|
||||||
int getSketchAxisCount(void) const;
|
int getSketchAxisCount(void) const;
|
||||||
|
|
|
@ -300,7 +300,7 @@ void CmdPartDesignNewSketch::activated(int iMsg)
|
||||||
doCommand(Gui,"App.activeDocument().%s.Support = %s",FeatName.c_str(),supportString.c_str());
|
doCommand(Gui,"App.activeDocument().%s.Support = %s",FeatName.c_str(),supportString.c_str());
|
||||||
doCommand(Doc,"App.activeDocument().%s.Placement = App.Placement(App.Vector(%f,%f,%f),App.Rotation(%f,%f,%f,%f))",FeatName.c_str(),p.x,p.y,p.z,r[0],r[1],r[2],r[3]);
|
doCommand(Doc,"App.activeDocument().%s.Placement = App.Placement(App.Vector(%f,%f,%f),App.Rotation(%f,%f,%f,%f))",FeatName.c_str(),p.x,p.y,p.z,r[0],r[1],r[2],r[3]);
|
||||||
doCommand(Doc,"App.activeDocument().%s.Model = App.activeDocument().%s.Model + [App.activeDocument().%s]",pcActiveBody->getNameInDocument(),pcActiveBody->getNameInDocument(),FeatName.c_str());
|
doCommand(Doc,"App.activeDocument().%s.Model = App.activeDocument().%s.Model + [App.activeDocument().%s]",pcActiveBody->getNameInDocument(),pcActiveBody->getNameInDocument(),FeatName.c_str());
|
||||||
doCommand(Doc,"App.activeDocument().%s.Tip = App.activeDocument().%s",pcActiveBody->getNameInDocument(),FeatName.c_str());
|
doCommand(Doc,"App.activeDocument().%s.Tip = App.activeDocument().%s",pcActiveBody->getNameInDocument(),FeatName.c_str());
|
||||||
doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str());
|
doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -382,11 +382,10 @@ bool CmdPartDesignNewSketch::isActive(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
void prepareSketchBased(Gui::Command* cmd, const std::string& which,
|
void prepareSketchBased(Gui::Command* cmd, const std::string& which,
|
||||||
Part::Part2DObject*& sketch, std::string& FeatName, App::DocumentObject*& prevTip)
|
Part::Part2DObject*& sketch, std::string& FeatName, App::DocumentObject*& prevSolidFeature)
|
||||||
{
|
{
|
||||||
PartDesign::Body *pcActiveBody = getBody();
|
PartDesign::Body *pcActiveBody = getBody();
|
||||||
if (!pcActiveBody) return;
|
if (!pcActiveBody) return;
|
||||||
prevTip = pcActiveBody->Tip.getValue();
|
|
||||||
|
|
||||||
// Get a valid sketch from the user
|
// Get a valid sketch from the user
|
||||||
// First check selections
|
// First check selections
|
||||||
|
@ -415,17 +414,22 @@ void prepareSketchBased(Gui::Command* cmd, const std::string& which,
|
||||||
}
|
}
|
||||||
|
|
||||||
sketch = static_cast<Part::Part2DObject*>(*firstValidSketch);
|
sketch = static_cast<Part::Part2DObject*>(*firstValidSketch);
|
||||||
|
|
||||||
|
// Find valid Body feature to set as the base feature
|
||||||
|
prevSolidFeature = pcActiveBody->getTipSolidFeature();
|
||||||
FeatName = cmd->getUniqueObjectName(which.c_str());
|
FeatName = cmd->getUniqueObjectName(which.c_str());
|
||||||
|
|
||||||
cmd->openCommand((std::string("Make ") + which).c_str());
|
cmd->openCommand((std::string("Make ") + which).c_str());
|
||||||
cmd->doCommand(cmd->Doc,"App.activeDocument().addObject(\"PartDesign::%s\",\"%s\")",which.c_str(), FeatName.c_str());
|
cmd->doCommand(cmd->Doc,"App.activeDocument().addObject(\"PartDesign::%s\",\"%s\")",which.c_str(), FeatName.c_str());
|
||||||
|
if (prevSolidFeature != NULL)
|
||||||
|
cmd->doCommand(cmd->Doc,"App.activeDocument().%s.Base = App.activeDocument().%s",FeatName.c_str(),prevSolidFeature->getNameInDocument());
|
||||||
cmd->doCommand(cmd->Doc,"App.activeDocument().%s.Model = App.activeDocument().%s.Model + [App.activeDocument().%s]",pcActiveBody->getNameInDocument(),pcActiveBody->getNameInDocument(),FeatName.c_str());
|
cmd->doCommand(cmd->Doc,"App.activeDocument().%s.Model = App.activeDocument().%s.Model + [App.activeDocument().%s]",pcActiveBody->getNameInDocument(),pcActiveBody->getNameInDocument(),FeatName.c_str());
|
||||||
cmd->doCommand(cmd->Doc,"App.activeDocument().%s.Tip = App.activeDocument().%s",pcActiveBody->getNameInDocument(),FeatName.c_str());
|
cmd->doCommand(cmd->Doc,"App.activeDocument().%s.Tip = App.activeDocument().%s",pcActiveBody->getNameInDocument(),FeatName.c_str());
|
||||||
cmd->doCommand(cmd->Doc,"App.activeDocument().%s.Sketch = App.activeDocument().%s",FeatName.c_str(),sketch->getNameInDocument());
|
cmd->doCommand(cmd->Doc,"App.activeDocument().%s.Sketch = App.activeDocument().%s",FeatName.c_str(),sketch->getNameInDocument());
|
||||||
}
|
}
|
||||||
|
|
||||||
void finishSketchBased(const Gui::Command* cmd,
|
void finishSketchBased(const Gui::Command* cmd,
|
||||||
const Part::Part2DObject* sketch, const std::string& FeatName, const App::DocumentObject* prevTip)
|
const Part::Part2DObject* sketch, const std::string& FeatName, const App::DocumentObject* prevSolidFeature)
|
||||||
{
|
{
|
||||||
App::DocumentObjectGroup* grp = sketch->getGroup();
|
App::DocumentObjectGroup* grp = sketch->getGroup();
|
||||||
if (grp) {
|
if (grp) {
|
||||||
|
@ -438,8 +442,8 @@ void finishSketchBased(const Gui::Command* cmd,
|
||||||
cmd->updateActive();
|
cmd->updateActive();
|
||||||
if (cmd->isActiveObjectValid()) {
|
if (cmd->isActiveObjectValid()) {
|
||||||
cmd->doCommand(cmd->Gui,"Gui.activeDocument().hide(\"%s\")", sketch->getNameInDocument());
|
cmd->doCommand(cmd->Gui,"Gui.activeDocument().hide(\"%s\")", sketch->getNameInDocument());
|
||||||
if (prevTip != NULL)
|
if (prevSolidFeature != NULL)
|
||||||
cmd->doCommand(cmd->Gui,"Gui.activeDocument().hide(\"%s\")", prevTip->getNameInDocument());
|
cmd->doCommand(cmd->Gui,"Gui.activeDocument().hide(\"%s\")", prevSolidFeature->getNameInDocument());
|
||||||
}
|
}
|
||||||
// #0001721: use '0' as edit value to avoid switching off selection in
|
// #0001721: use '0' as edit value to avoid switching off selection in
|
||||||
// ViewProviderGeometryObject::setEditViewer
|
// ViewProviderGeometryObject::setEditViewer
|
||||||
|
@ -474,14 +478,14 @@ void CmdPartDesignPad::activated(int iMsg)
|
||||||
{
|
{
|
||||||
Part::Part2DObject* sketch;
|
Part::Part2DObject* sketch;
|
||||||
std::string FeatName;
|
std::string FeatName;
|
||||||
App::DocumentObject* prevTip;
|
App::DocumentObject* prevSolidFeature;
|
||||||
prepareSketchBased(this, "Pad", sketch, FeatName, prevTip);
|
prepareSketchBased(this, "Pad", sketch, FeatName, prevSolidFeature);
|
||||||
if (FeatName.empty()) return;
|
if (FeatName.empty()) return;
|
||||||
|
|
||||||
// specific parameters for Pad
|
// specific parameters for Pad
|
||||||
doCommand(Doc,"App.activeDocument().%s.Length = 10.0",FeatName.c_str());
|
doCommand(Doc,"App.activeDocument().%s.Length = 10.0",FeatName.c_str());
|
||||||
|
|
||||||
finishSketchBased(this, sketch, FeatName, prevTip);
|
finishSketchBased(this, sketch, FeatName, prevSolidFeature);
|
||||||
adjustCameraPosition();
|
adjustCameraPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -511,13 +515,13 @@ void CmdPartDesignPocket::activated(int iMsg)
|
||||||
{
|
{
|
||||||
Part::Part2DObject* sketch;
|
Part::Part2DObject* sketch;
|
||||||
std::string FeatName;
|
std::string FeatName;
|
||||||
App::DocumentObject* prevTip;
|
App::DocumentObject* prevSolidFeature;
|
||||||
prepareSketchBased(this, "Pocket", sketch, FeatName, prevTip);
|
prepareSketchBased(this, "Pocket", sketch, FeatName, prevSolidFeature);
|
||||||
if (FeatName.empty()) return;
|
if (FeatName.empty()) return;
|
||||||
|
|
||||||
doCommand(Doc,"App.activeDocument().%s.Length = 5.0",FeatName.c_str());
|
doCommand(Doc,"App.activeDocument().%s.Length = 5.0",FeatName.c_str());
|
||||||
|
|
||||||
finishSketchBased(this, sketch, FeatName, prevTip);
|
finishSketchBased(this, sketch, FeatName, prevSolidFeature);
|
||||||
adjustCameraPosition();
|
adjustCameraPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -547,8 +551,8 @@ void CmdPartDesignRevolution::activated(int iMsg)
|
||||||
{
|
{
|
||||||
Part::Part2DObject* sketch;
|
Part::Part2DObject* sketch;
|
||||||
std::string FeatName;
|
std::string FeatName;
|
||||||
App::DocumentObject* prevTip;
|
App::DocumentObject* prevSolidFeature;
|
||||||
prepareSketchBased(this, "Revolution", sketch, FeatName, prevTip);
|
prepareSketchBased(this, "Revolution", sketch, FeatName, prevSolidFeature);
|
||||||
if (FeatName.empty()) return;
|
if (FeatName.empty()) return;
|
||||||
|
|
||||||
doCommand(Doc,"App.activeDocument().%s.ReferenceAxis = (App.activeDocument().%s,['V_Axis'])",
|
doCommand(Doc,"App.activeDocument().%s.ReferenceAxis = (App.activeDocument().%s,['V_Axis'])",
|
||||||
|
@ -558,7 +562,7 @@ void CmdPartDesignRevolution::activated(int iMsg)
|
||||||
if (pcRevolution && pcRevolution->suggestReversed())
|
if (pcRevolution && pcRevolution->suggestReversed())
|
||||||
doCommand(Doc,"App.activeDocument().%s.Reversed = 1",FeatName.c_str());
|
doCommand(Doc,"App.activeDocument().%s.Reversed = 1",FeatName.c_str());
|
||||||
|
|
||||||
finishSketchBased(this, sketch, FeatName, prevTip);
|
finishSketchBased(this, sketch, FeatName, prevSolidFeature);
|
||||||
adjustCameraPosition();
|
adjustCameraPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -588,8 +592,8 @@ void CmdPartDesignGroove::activated(int iMsg)
|
||||||
{
|
{
|
||||||
Part::Part2DObject* sketch;
|
Part::Part2DObject* sketch;
|
||||||
std::string FeatName;
|
std::string FeatName;
|
||||||
App::DocumentObject* prevTip;
|
App::DocumentObject* prevSolidFeature;
|
||||||
prepareSketchBased(this, "Groove", sketch, FeatName, prevTip);
|
prepareSketchBased(this, "Groove", sketch, FeatName, prevSolidFeature);
|
||||||
if (FeatName.empty()) return;
|
if (FeatName.empty()) return;
|
||||||
|
|
||||||
doCommand(Doc,"App.activeDocument().%s.ReferenceAxis = (App.activeDocument().%s,['V_Axis'])",
|
doCommand(Doc,"App.activeDocument().%s.ReferenceAxis = (App.activeDocument().%s,['V_Axis'])",
|
||||||
|
@ -599,7 +603,7 @@ void CmdPartDesignGroove::activated(int iMsg)
|
||||||
if (pcGroove && pcGroove->suggestReversed())
|
if (pcGroove && pcGroove->suggestReversed())
|
||||||
doCommand(Doc,"App.activeDocument().%s.Reversed = 1",FeatName.c_str());
|
doCommand(Doc,"App.activeDocument().%s.Reversed = 1",FeatName.c_str());
|
||||||
|
|
||||||
finishSketchBased(this, sketch, FeatName, prevTip);
|
finishSketchBased(this, sketch, FeatName, prevSolidFeature);
|
||||||
adjustCameraPosition();
|
adjustCameraPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user