diff --git a/src/Mod/PartDesign/App/FeatureHole.cpp b/src/Mod/PartDesign/App/FeatureHole.cpp index e11afcea59..058082c6f2 100644 --- a/src/Mod/PartDesign/App/FeatureHole.cpp +++ b/src/Mod/PartDesign/App/FeatureHole.cpp @@ -26,6 +26,7 @@ # include # include # include +# include # include # include # include @@ -39,6 +40,7 @@ # include # include # include +# include # include # include # include @@ -58,6 +60,7 @@ #include #include #include +#include #include "FeatureHole.h" #include "json.hpp" @@ -1410,7 +1413,7 @@ double Hole::getThreadProfileAngle() void Hole::findClosestDesignation() { int threadType = ThreadType.getValue(); - const int numTypes = static_cast(std::size(threadDescription)); + const int numTypes = static_cast(std::size(threadDescription)); if (threadType < 0 || threadType >= numTypes) { throw Base::IndexError(QT_TRANSLATE_NOOP("Exception", "Thread type is invalid")); @@ -1758,9 +1761,9 @@ void Hole::setupObject() Base::Reference hGrp = App::GetApplication().GetUserParameter() .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/PartDesign"); - + BaseProfileType.setValue(baseProfileOption_idxToBitmask(hGrp->GetInt("defaultBaseTypeHole", 1))); - + ProfileBased::setupObject(); } @@ -1887,9 +1890,9 @@ static gp_Pnt toPnt(gp_Vec dir) App::DocumentObjectExecReturn* Hole::execute() { TopoShape profileshape = - getProfileShape( Part::ShapeOption::NeedSubElement + getProfileShape( Part::ShapeOption::NeedSubElement | Part::ShapeOption::ResolveLink - | Part::ShapeOption::Transform + | Part::ShapeOption::Transform | Part::ShapeOption::DontSimplifyCompound); // Find the base shape @@ -1918,7 +1921,8 @@ App::DocumentObjectExecReturn* Hole::execute() /* Build the prototype hole */ // Get vector normal to profile - Base::Vector3d SketchVector = getProfileNormal(); + Base::Vector3d SketchVector = guessNormalDirection(profileshape); + if (Reversed.getValue()) SketchVector *= -1.0; @@ -2254,6 +2258,24 @@ gp_Vec Hole::computePerpendicular(const gp_Vec& zDir) const xDir.Normalize(); return xDir; } +Base::Vector3d Hole::guessNormalDirection(const TopoShape& profileshape) const +{ + // If trying to build a hole from a cylinder face + // we must try to find the direction ourselves as + // getProfileNormal() will try to find the normal to + // the middle of the face + if (profileshape.hasSubShape(TopAbs_FACE)) { + BRepAdaptor_Surface sf(TopoDS::Face(profileshape.getSubShape(TopAbs_FACE, 1))); + + if (sf.GetType() != GeomAbs_Cylinder) { + throw Base::Exception("Cannot create hole from non cylindrical face"); + } + + return Base::convertTo(sf.Cylinder().Axis().Direction()); + } + + return getProfileNormal(); +} TopoShape Hole::findHoles(std::vector &holes, const TopoShape& profileshape, const TopoDS_Shape& protoHole) const @@ -2279,7 +2301,7 @@ TopoShape Hole::findHoles(std::vector &holes, int baseProfileType = BaseProfileType.getValue(); // Iterate over edges and filter out non-circle/non-arc types - if (baseProfileType & BaseProfileTypeOptions::OnCircles || + if (baseProfileType & BaseProfileTypeOptions::OnCircles || baseProfileType & BaseProfileTypeOptions::OnArcs) { for (const auto &profileEdge : profileshape.getSubTopoShapes(TopAbs_EDGE)) { TopoDS_Edge edge = TopoDS::Edge(profileEdge.getShape()); @@ -2293,7 +2315,7 @@ TopoShape Hole::findHoles(std::vector &holes, if (!(baseProfileType & BaseProfileTypeOptions::OnCircles) && adaptor.IsClosed()) { continue; } - + // Filter for arcs if (!(baseProfileType & BaseProfileTypeOptions::OnArcs) && !adaptor.IsClosed()) { continue; @@ -2726,7 +2748,7 @@ int Hole::baseProfileOption_idxToBitmask(int index) } if (index == 2) { return PartDesign::Hole::BaseProfileTypeOptions::OnPoints; - } + } Base::Console().error("Unexpected hole base profile combobox index: %i", index); return 0; } @@ -2734,10 +2756,10 @@ int Hole::baseProfileOption_bitmaskToIdx(int bitmask) { if (bitmask == PartDesign::Hole::BaseProfileTypeOptions::OnCirclesArcs) { return 0; - } + } if (bitmask == PartDesign::Hole::BaseProfileTypeOptions::OnPointsCirclesArcs) { return 1; - } + } if (bitmask == PartDesign::Hole::BaseProfileTypeOptions::OnPoints) { return 2; } diff --git a/src/Mod/PartDesign/App/FeatureHole.h b/src/Mod/PartDesign/App/FeatureHole.h index d1ecf74371..5c7c018bc2 100644 --- a/src/Mod/PartDesign/App/FeatureHole.h +++ b/src/Mod/PartDesign/App/FeatureHole.h @@ -254,6 +254,7 @@ private: void findClosestDesignation(); void rotateToNormal(const gp_Dir& helixAxis, const gp_Dir& normalAxis, TopoDS_Shape& helixShape) const; gp_Vec computePerpendicular(const gp_Vec&) const; + Base::Vector3d guessNormalDirection(const TopoShape& profileshape) const; TopoDS_Shape makeThread(const gp_Vec&, const gp_Vec&, double); TopoShape findHoles(std::vector &holes, const TopoShape& profileshape, const TopoDS_Shape& protohole) const;