diff --git a/src/Mod/PartDesign/App/FeatureChamfer.cpp b/src/Mod/PartDesign/App/FeatureChamfer.cpp index 77d3bb10e..2c0685abf 100644 --- a/src/Mod/PartDesign/App/FeatureChamfer.cpp +++ b/src/Mod/PartDesign/App/FeatureChamfer.cpp @@ -35,6 +35,7 @@ #endif #include +#include #include #include @@ -66,17 +67,12 @@ App::DocumentObjectExecReturn *Chamfer::execute(void) { // NOTE: Normally the Base property and the BaseFeature property should point to the same object. // The only difference is that the Base property also stores the edges that are to be chamfered - App::DocumentObject* link = BaseFeature.getValue(); - if (!link) - link = Base.getValue(); // For legacy features - if (!link) - return new App::DocumentObjectExecReturn("No object linked"); - if (!link->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) - return new App::DocumentObjectExecReturn("Linked object is not a Part object"); - Part::Feature *base = static_cast(link); - const Part::TopoShape& TopShape = base->Shape.getShape(); - if (TopShape._Shape.IsNull()) - return new App::DocumentObjectExecReturn("Cannot chamfer invalid shape"); + Part::TopoShape TopShape; + try { + TopShape = getBaseShape(); + } catch (Base::Exception& e) { + return new App::DocumentObjectExecReturn(e.what()); + } const std::vector& SubVals = Base.getSubValuesStartsWith("Edge"); if (SubVals.size() == 0) diff --git a/src/Mod/PartDesign/App/FeatureChamfer.cpp.orig b/src/Mod/PartDesign/App/FeatureChamfer.cpp.orig new file mode 100644 index 000000000..063bcc439 --- /dev/null +++ b/src/Mod/PartDesign/App/FeatureChamfer.cpp.orig @@ -0,0 +1,153 @@ +/*************************************************************************** + * Copyright (c) 2010 Juergen Riegel * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" +#ifndef _PreComp_ +# include +# include +# include +# include +# include +# include +# include +#endif + +<<<<<<< 50287516b47694e57429cc98f6d5596a06a635d6 +#include +#include +======= +#include +>>>>>>> Some code unification for DressUp features +#include + +#include "FeatureChamfer.h" + + +using namespace PartDesign; + + +PROPERTY_SOURCE(PartDesign::Chamfer, PartDesign::DressUp) + +const App::PropertyQuantityConstraint::Constraints floatSize = {0.0,FLT_MAX,0.1}; + +Chamfer::Chamfer() +{ + ADD_PROPERTY(Size,(1.0)); + Size.setUnit(Base::Unit::Length); + Size.setConstraints(&floatSize); +} + +short Chamfer::mustExecute() const +{ + if (Placement.isTouched() || Size.isTouched()) + return 1; + return DressUp::mustExecute(); +} + +App::DocumentObjectExecReturn *Chamfer::execute(void) +{ + // NOTE: Normally the Base property and the BaseFeature property should point to the same object. + // The only difference is that the Base property also stores the edges that are to be chamfered + Part::TopoShape TopShape; + try { + TopShape = getBaseShape(); + } catch (Base::Exception& e) { + return new App::DocumentObjectExecReturn(e.what()); + } + + const std::vector& SubVals = Base.getSubValuesStartsWith("Edge"); + if (SubVals.size() == 0) + return new App::DocumentObjectExecReturn("No edges specified"); + + double size = Size.getValue(); + + this->positionByBaseFeature(); + // create an untransformed copy of the basefeature shape + Part::TopoShape baseShape(TopShape); + baseShape.setTransform(Base::Matrix4D()); + try { + BRepFilletAPI_MakeChamfer mkChamfer(baseShape._Shape); + + TopTools_IndexedMapOfShape mapOfEdges; + TopTools_IndexedDataMapOfShapeListOfShape mapEdgeFace; + TopExp::MapShapesAndAncestors(baseShape._Shape, TopAbs_EDGE, TopAbs_FACE, mapEdgeFace); + TopExp::MapShapes(baseShape._Shape, TopAbs_EDGE, mapOfEdges); + + for (std::vector::const_iterator it=SubVals.begin(); it != SubVals.end(); ++it) { + TopoDS_Edge edge = TopoDS::Edge(baseShape.getSubShape(it->c_str())); + const TopoDS_Face& face = TopoDS::Face(mapEdgeFace.FindFromKey(edge).First()); + mkChamfer.Add(size, edge, face); + } + + mkChamfer.Build(); + if (!mkChamfer.IsDone()) + return new App::DocumentObjectExecReturn("Failed to create chamfer"); + + TopoDS_Shape shape = mkChamfer.Shape(); + if (shape.IsNull()) + return new App::DocumentObjectExecReturn("Resulting shape is null"); + + this->Shape.setValue(shape); + return App::DocumentObject::StdReturn; + } + catch (Standard_Failure) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + return new App::DocumentObjectExecReturn(e->GetMessageString()); + } +} + +void Chamfer::Restore(Base::XMLReader &reader) +{ + reader.readElement("Properties"); + int Cnt = reader.getAttributeAsInteger("Count"); + + for (int i=0 ;igetTypeId().getName(), TypeName) == 0) { + prop->Restore(reader); + } + else if (prop && strcmp(TypeName,"App::PropertyFloatConstraint") == 0 && + strcmp(prop->getTypeId().getName(), "App::PropertyQuantityConstraint") == 0) { + App::PropertyFloatConstraint p; + p.Restore(reader); + static_cast(prop)->setValue(p.getValue()); + } + } + catch (const Base::XMLParseException&) { + throw; // re-throw + } + catch (const Base::Exception &e) { + Base::Console().Error("%s\n", e.what()); + } + catch (const std::exception &e) { + Base::Console().Error("%s\n", e.what()); + } + reader.readEndElement("Property"); + } + reader.readEndElement("Properties"); +} diff --git a/src/Mod/PartDesign/App/FeatureDraft.cpp b/src/Mod/PartDesign/App/FeatureDraft.cpp index f3e8a686f..ca46e02ab 100644 --- a/src/Mod/PartDesign/App/FeatureDraft.cpp +++ b/src/Mod/PartDesign/App/FeatureDraft.cpp @@ -49,6 +49,7 @@ #include #include +#include #include #include "FeatureDraft.h" @@ -90,17 +91,12 @@ App::DocumentObjectExecReturn *Draft::execute(void) { // Get parameters // Base shape - App::DocumentObject* link = BaseFeature.getValue(); - if (!link) - link = Base.getValue(); // For legacy features - if (!link) - return new App::DocumentObjectExecReturn("No object linked"); - if (!link->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) - return new App::DocumentObjectExecReturn("Linked object is not a Part object"); - Part::Feature *base = static_cast(link); - const Part::TopoShape& TopShape = base->Shape.getShape(); - if (TopShape._Shape.IsNull()) - return new App::DocumentObjectExecReturn("Cannot draft invalid shape"); + Part::TopoShape TopShape; + try { + TopShape = getBaseShape(); + } catch (Base::Exception& e) { + return new App::DocumentObjectExecReturn(e.what()); + } // Faces where draft should be applied // Note: Cannot be const reference currently because of BRepOffsetAPI_DraftAngle::Remove() bug, see below diff --git a/src/Mod/PartDesign/App/FeatureDressUp.cpp b/src/Mod/PartDesign/App/FeatureDressUp.cpp index 8d8a42a64..95fc0467f 100644 --- a/src/Mod/PartDesign/App/FeatureDressUp.cpp +++ b/src/Mod/PartDesign/App/FeatureDressUp.cpp @@ -27,6 +27,7 @@ #include "FeatureDressUp.h" +#include using namespace PartDesign; @@ -57,6 +58,22 @@ void DressUp::positionByBaseFeature(void) this->Placement.setValue(base->Placement.getValue()); } +Part::TopoShape DressUp::getBaseShape() +{ + App::DocumentObject* link = BaseFeature.getValue(); + if (!link) + link = this->Base.getValue(); // For legacy features + if (!link) + throw Base::Exception("No object linked"); + if (!link->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) + throw Base::Exception("Linked object is not a Part object"); + Part::Feature* base = static_cast(link); + const Part::TopoShape& shape = base->Shape.getShape(); + if (shape._Shape.IsNull()) + throw Base::Exception("Cannot draft invalid shape"); + return shape; +} + void DressUp::onChanged(const App::Property* prop) { if (prop == &BaseFeature) { diff --git a/src/Mod/PartDesign/App/FeatureDressUp.h b/src/Mod/PartDesign/App/FeatureDressUp.h index 81e8a556d..af143e8fc 100644 --- a/src/Mod/PartDesign/App/FeatureDressUp.h +++ b/src/Mod/PartDesign/App/FeatureDressUp.h @@ -42,6 +42,7 @@ public: short mustExecute() const; /// updates the Placement property from the Placement of the BaseFeature void positionByBaseFeature(void); + Part::TopoShape getBaseShape(); protected: void onChanged(const App::Property* prop); diff --git a/src/Mod/PartDesign/App/FeatureFillet.cpp b/src/Mod/PartDesign/App/FeatureFillet.cpp index d0ba06222..0c82686df 100644 --- a/src/Mod/PartDesign/App/FeatureFillet.cpp +++ b/src/Mod/PartDesign/App/FeatureFillet.cpp @@ -32,6 +32,7 @@ #endif #include +#include #include #include @@ -61,17 +62,12 @@ short Fillet::mustExecute() const App::DocumentObjectExecReturn *Fillet::execute(void) { - App::DocumentObject* link = BaseFeature.getValue(); - if (!link) - link = Base.getValue(); // For legacy features - if (!link) - return new App::DocumentObjectExecReturn("No object linked"); - if (!link->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) - return new App::DocumentObjectExecReturn("Linked object is not a Part object"); - Part::Feature *base = static_cast(link); - const Part::TopoShape& TopShape = base->Shape.getShape(); - if (TopShape._Shape.IsNull()) - return new App::DocumentObjectExecReturn("Cannot fillet invalid shape"); + Part::TopoShape TopShape; + try { + TopShape = getBaseShape(); + } catch (Base::Exception& e) { + return new App::DocumentObjectExecReturn(e.what()); + } const std::vector& SubVals = Base.getSubValuesStartsWith("Edge"); if (SubVals.size() == 0) diff --git a/src/Mod/PartDesign/App/FeatureFillet.cpp.orig b/src/Mod/PartDesign/App/FeatureFillet.cpp.orig new file mode 100644 index 000000000..7e4324a6f --- /dev/null +++ b/src/Mod/PartDesign/App/FeatureFillet.cpp.orig @@ -0,0 +1,143 @@ +/*************************************************************************** + * Copyright (c) 2008 Werner Mayer * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" +#ifndef _PreComp_ +# include +# include +# include +# include +#endif + +<<<<<<< 50287516b47694e57429cc98f6d5596a06a635d6 +#include +#include +======= +#include +>>>>>>> Some code unification for DressUp features +#include + +#include "FeatureFillet.h" + + +using namespace PartDesign; + + +PROPERTY_SOURCE(PartDesign::Fillet, PartDesign::DressUp) + +const App::PropertyQuantityConstraint::Constraints floatRadius = {0.0,FLT_MAX,0.1}; + +Fillet::Fillet() +{ + ADD_PROPERTY(Radius,(1.0)); + Radius.setUnit(Base::Unit::Length); + Radius.setConstraints(&floatRadius); +} + +short Fillet::mustExecute() const +{ + if (Placement.isTouched() || Radius.isTouched()) + return 1; + return DressUp::mustExecute(); +} + +App::DocumentObjectExecReturn *Fillet::execute(void) +{ + Part::TopoShape TopShape; + try { + TopShape = getBaseShape(); + } catch (Base::Exception& e) { + return new App::DocumentObjectExecReturn(e.what()); + } + + const std::vector& SubVals = Base.getSubValuesStartsWith("Edge"); + if (SubVals.size() == 0) + return new App::DocumentObjectExecReturn("No edges specified"); + + double radius = Radius.getValue(); + + this->positionByBaseFeature(); + + // create an untransformed copy of the base shape + Part::TopoShape baseShape(TopShape); + baseShape.setTransform(Base::Matrix4D()); + try { + BRepFilletAPI_MakeFillet mkFillet(baseShape._Shape); + + for (std::vector::const_iterator it=SubVals.begin(); it != SubVals.end(); ++it) { + TopoDS_Edge edge = TopoDS::Edge(baseShape.getSubShape(it->c_str())); + mkFillet.Add(radius, edge); + } + + mkFillet.Build(); + if (!mkFillet.IsDone()) + return new App::DocumentObjectExecReturn("Failed to create fillet"); + + TopoDS_Shape shape = mkFillet.Shape(); + if (shape.IsNull()) + return new App::DocumentObjectExecReturn("Resulting shape is null"); + + this->Shape.setValue(shape); + return App::DocumentObject::StdReturn; + } + catch (Standard_Failure) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + return new App::DocumentObjectExecReturn(e->GetMessageString()); + } +} + +void Fillet::Restore(Base::XMLReader &reader) +{ + reader.readElement("Properties"); + int Cnt = reader.getAttributeAsInteger("Count"); + + for (int i=0 ;igetTypeId().getName(), TypeName) == 0) { + prop->Restore(reader); + } + else if (prop && strcmp(TypeName,"App::PropertyFloatConstraint") == 0 && + strcmp(prop->getTypeId().getName(), "App::PropertyQuantityConstraint") == 0) { + App::PropertyFloatConstraint p; + p.Restore(reader); + static_cast(prop)->setValue(p.getValue()); + } + } + catch (const Base::XMLParseException&) { + throw; // re-throw + } + catch (const Base::Exception &e) { + Base::Console().Error("%s\n", e.what()); + } + catch (const std::exception &e) { + Base::Console().Error("%s\n", e.what()); + } + reader.readEndElement("Property"); + } + reader.readEndElement("Properties"); +}