diff --git a/src/Mod/Part/App/CMakeLists.txt b/src/Mod/Part/App/CMakeLists.txt index d24476215..39d4b18ab 100644 --- a/src/Mod/Part/App/CMakeLists.txt +++ b/src/Mod/Part/App/CMakeLists.txt @@ -119,6 +119,7 @@ SOURCE_GROUP("Features" FILES ${Features_SRCS}) IF(MSVC) SET_SOURCE_FILES_PROPERTIES(FeatureFillet.cpp PROPERTIES COMPILE_FLAGS "/EHa") SET_SOURCE_FILES_PROPERTIES(FeaturePartBoolean.cpp PROPERTIES COMPILE_FLAGS "/EHa") +SET_SOURCE_FILES_PROPERTIES(FeatureExtrusion.cpp PROPERTIES COMPILE_FLAGS "/EHa") ENDIF(MSVC) SET(Properties_SRCS diff --git a/src/Mod/Part/App/FeatureExtrusion.cpp b/src/Mod/Part/App/FeatureExtrusion.cpp index 6633d2e39..e110eb9c6 100644 --- a/src/Mod/Part/App/FeatureExtrusion.cpp +++ b/src/Mod/Part/App/FeatureExtrusion.cpp @@ -23,10 +23,23 @@ #include "PreCompiled.h" #ifndef _PreComp_ +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include #endif #include "FeatureExtrusion.h" +#include +#include using namespace Part; @@ -38,12 +51,16 @@ Extrusion::Extrusion() { ADD_PROPERTY(Base,(0)); ADD_PROPERTY(Dir,(Base::Vector3f(0.0f,0.0f,1.0f))); + ADD_PROPERTY(Solid,(false)); + ADD_PROPERTY(TaperAngle,(0.0f)); } short Extrusion::mustExecute() const { if (Base.isTouched() || - Dir.isTouched() ) + Dir.isTouched() || + Solid.isTouched() || + TaperAngle.isTouched()) return 1; return 0; } @@ -59,13 +76,69 @@ App::DocumentObjectExecReturn *Extrusion::execute(void) Base::Vector3f v = Dir.getValue(); gp_Vec vec(v.x,v.y,v.z); + float taperAngle = TaperAngle.getValue(); + bool makeSolid = Solid.getValue(); try { - // Now, let's get the TopoDS_Shape - TopoDS_Shape swept = base->Shape.getShape().makePrism(vec); - if (swept.IsNull()) - return new App::DocumentObjectExecReturn("Resulting shape is null"); - this->Shape.setValue(swept); + if (std::fabs(taperAngle) >= Precision::Confusion()) { +#if defined(__GNUC__) && defined (FC_OS_LINUX) + Base::SignalException se; +#endif + double distance = std::tan(Base::toRadians(taperAngle)) * vec.Magnitude(); + const TopoDS_Shape& shape = base->Shape.getValue(); + bool isWire = (shape.ShapeType() == TopAbs_WIRE); + if (!isWire) + return new App::DocumentObjectExecReturn("Only wires supported"); + + std::list wire_list; + BRepOffsetAPI_MakeOffset mkOffset; +#if 1 //OCC_HEX_VERSION < 0x060502 + // The input wire may have erorrs in its topology + // and thus may cause a crash in the Perfrom() method + // See also: + // http://www.opencascade.org/org/forum/thread_17640/ + // http://www.opencascade.org/org/forum/thread_12012/ + ShapeFix_Wire aFix; + aFix.Load(TopoDS::Wire(shape)); + aFix.FixReorder(); + aFix.FixConnected(); + aFix.FixClosed(); + mkOffset.AddWire(aFix.Wire()); + wire_list.push_back(aFix.Wire()); +#else + mkOffset.AddWire(TopoDS::Wire(shape)); +#endif + mkOffset.Perform(distance); + + gp_Trsf mat; + mat.SetTranslation(vec); + BRepBuilderAPI_Transform mkTransform(mkOffset.Shape(),mat); + wire_list.push_back(TopoDS::Wire(mkTransform.Shape())); + + BRepOffsetAPI_ThruSections mkGenerator(makeSolid ? Standard_True : Standard_False, Standard_False); + for (std::list::const_iterator it = wire_list.begin(); it != wire_list.end(); ++it) { + const TopoDS_Wire &wire = *it; + mkGenerator.AddWire(wire); + } + + mkGenerator.Build(); + this->Shape.setValue(mkGenerator.Shape()); + } + else { + // Now, let's get the TopoDS_Shape + TopoDS_Shape myShape = base->Shape.getValue(); + if (myShape.IsNull()) + Standard_Failure::Raise("Cannot extrude empty shape"); + if (makeSolid && myShape.ShapeType() == TopAbs_WIRE) { + BRepBuilderAPI_MakeFace mkFace(TopoDS::Wire(myShape)); + myShape = mkFace.Face(); + } + BRepPrimAPI_MakePrism mkPrism(myShape, vec); + TopoDS_Shape swept = mkPrism.Shape(); + if (swept.IsNull()) + return new App::DocumentObjectExecReturn("Resulting shape is null"); + this->Shape.setValue(swept); + } return App::DocumentObject::StdReturn; } catch (Standard_Failure) { diff --git a/src/Mod/Part/App/FeatureExtrusion.h b/src/Mod/Part/App/FeatureExtrusion.h index c5db68103..6576d0b17 100644 --- a/src/Mod/Part/App/FeatureExtrusion.h +++ b/src/Mod/Part/App/FeatureExtrusion.h @@ -25,6 +25,7 @@ #define PART_FEATUREEXTRUSION_H #include +#include #include "PartFeature.h" namespace Part @@ -39,6 +40,8 @@ public: App::PropertyLink Base; App::PropertyVector Dir; + App::PropertyBool Solid; + App::PropertyAngle TaperAngle; /** @name methods override feature */ //@{ diff --git a/src/Mod/Part/Gui/DlgExtrusion.cpp b/src/Mod/Part/Gui/DlgExtrusion.cpp index 5450f83a9..38e167657 100644 --- a/src/Mod/Part/Gui/DlgExtrusion.cpp +++ b/src/Mod/Part/Gui/DlgExtrusion.cpp @@ -162,6 +162,8 @@ void DlgExtrusion::apply() double dirX = ui->dirX->value(); double dirY = ui->dirY->value(); double dirZ = ui->dirZ->value(); + double angle = ui->taperAngle->value(); + bool makeSolid = ui->makeSolid->isChecked(); // inspect geometry App::DocumentObject* obj = activeDoc->getObject((const char*)shape.toAscii()); @@ -192,12 +194,16 @@ void DlgExtrusion::apply() "FreeCAD.getDocument(\"%1\").addObject(\"%2\",\"%3\")\n" "FreeCAD.getDocument(\"%1\").%3.Base = FreeCAD.getDocument(\"%1\").%4\n" "FreeCAD.getDocument(\"%1\").%3.Dir = (%5,%6,%7)\n" + "FreeCAD.getDocument(\"%1\").%3.Solid = (%8)\n" + "FreeCAD.getDocument(\"%1\").%3.TaperAngle = (%9)\n" "FreeCADGui.getDocument(\"%1\").%4.Visibility = False\n") .arg(QString::fromAscii(this->document.c_str())) .arg(type).arg(name).arg(shape) .arg(dirX*len) .arg(dirY*len) - .arg(dirZ*len); + .arg(dirZ*len) + .arg(makeSolid ? QLatin1String("True") : QLatin1String("False")) + .arg(angle); Gui::Application::Instance->runPythonCode((const char*)code.toAscii()); QByteArray to = name.toAscii(); QByteArray from = shape.toAscii(); diff --git a/src/Mod/Part/Gui/DlgExtrusion.h b/src/Mod/Part/Gui/DlgExtrusion.h index 60d5254bc..deeabe375 100644 --- a/src/Mod/Part/Gui/DlgExtrusion.h +++ b/src/Mod/Part/Gui/DlgExtrusion.h @@ -68,7 +68,7 @@ public: void clicked(int); virtual QDialogButtonBox::StandardButtons getStandardButtons() const - { return QDialogButtonBox::Apply | QDialogButtonBox::Cancel; } + { return QDialogButtonBox::Apply | QDialogButtonBox::Close; } private: DlgExtrusion* widget; diff --git a/src/Mod/Part/Gui/DlgExtrusion.ui b/src/Mod/Part/Gui/DlgExtrusion.ui index 0244152f2..3fad61682 100644 --- a/src/Mod/Part/Gui/DlgExtrusion.ui +++ b/src/Mod/Part/Gui/DlgExtrusion.ui @@ -181,6 +181,37 @@ + + + Create solid + + + + + + + + + Taper outward angle + + + + + + + -180.000000000000000 + + + 180.000000000000000 + + + 5.000000000000000 + + + + + +