diff --git a/src/Mod/PartDesign/App/FeatureExtrude.cpp b/src/Mod/PartDesign/App/FeatureExtrude.cpp index 54a3599328..765ea8ae69 100644 --- a/src/Mod/PartDesign/App/FeatureExtrude.cpp +++ b/src/Mod/PartDesign/App/FeatureExtrude.cpp @@ -95,7 +95,7 @@ Base::Vector3d FeatureExtrude::computeDirection(const Base::Vector3d& sketchVect const std::vector& subReferenceAxis = ReferenceAxis.getSubValues(); Base::Vector3d base; Base::Vector3d dir; - getAxis(pcReferenceAxis, subReferenceAxis, base, dir, false); + getAxis(pcReferenceAxis, subReferenceAxis, base, dir, ForbiddenAxis::NotPerpendicularWithNormal); switch (addSubType) { case Type::Additive: extrudeDirection = dir; diff --git a/src/Mod/PartDesign/App/FeatureGroove.cpp b/src/Mod/PartDesign/App/FeatureGroove.cpp index 2b4ffc00ba..bb0822ef11 100644 --- a/src/Mod/PartDesign/App/FeatureGroove.cpp +++ b/src/Mod/PartDesign/App/FeatureGroove.cpp @@ -208,7 +208,7 @@ void Groove::updateAxis(void) const std::vector &subReferenceAxis = ReferenceAxis.getSubValues(); Base::Vector3d base; Base::Vector3d dir; - getAxis(pcReferenceAxis, subReferenceAxis, base, dir); + getAxis(pcReferenceAxis, subReferenceAxis, base, dir, ForbiddenAxis::NotParallelWithNormal); if (dir.Length() > Precision::Confusion()) { Base.setValue(base.x,base.y,base.z); diff --git a/src/Mod/PartDesign/App/FeatureHelix.cpp b/src/Mod/PartDesign/App/FeatureHelix.cpp index 1ab173895c..ce56c7fd45 100644 --- a/src/Mod/PartDesign/App/FeatureHelix.cpp +++ b/src/Mod/PartDesign/App/FeatureHelix.cpp @@ -355,7 +355,7 @@ void Helix::updateAxis(void) const std::vector& subReferenceAxis = ReferenceAxis.getSubValues(); Base::Vector3d base; Base::Vector3d dir; - getAxis(pcReferenceAxis, subReferenceAxis, base, dir, false); + getAxis(pcReferenceAxis, subReferenceAxis, base, dir, ForbiddenAxis::NoCheck); Base.setValue(base.x, base.y, base.z); Axis.setValue(dir.x, dir.y, dir.z); diff --git a/src/Mod/PartDesign/App/FeatureRevolution.cpp b/src/Mod/PartDesign/App/FeatureRevolution.cpp index 419dc5b817..f5ec892e74 100644 --- a/src/Mod/PartDesign/App/FeatureRevolution.cpp +++ b/src/Mod/PartDesign/App/FeatureRevolution.cpp @@ -204,7 +204,7 @@ void Revolution::updateAxis(void) const std::vector &subReferenceAxis = ReferenceAxis.getSubValues(); Base::Vector3d base; Base::Vector3d dir; - getAxis(pcReferenceAxis, subReferenceAxis, base, dir); + getAxis(pcReferenceAxis, subReferenceAxis, base, dir, ForbiddenAxis::NotParallelWithNormal); Base.setValue(base.x,base.y,base.z); Axis.setValue(dir.x,dir.y,dir.z); diff --git a/src/Mod/PartDesign/App/FeatureSketchBased.cpp b/src/Mod/PartDesign/App/FeatureSketchBased.cpp index 9fd240f5e8..d3a215be10 100644 --- a/src/Mod/PartDesign/App/FeatureSketchBased.cpp +++ b/src/Mod/PartDesign/App/FeatureSketchBased.cpp @@ -1040,10 +1040,49 @@ double ProfileBased::getReversedAngle(const Base::Vector3d &b, const Base::Vecto } void ProfileBased::getAxis(const App::DocumentObject *pcReferenceAxis, const std::vector &subReferenceAxis, - Base::Vector3d& base, Base::Vector3d& dir, bool checkPerpendicular) + Base::Vector3d& base, Base::Vector3d& dir, ProfileBased::ForbiddenAxis checkAxis) { + auto verifyAxisFunc = [](ProfileBased::ForbiddenAxis checkAxis, const gp_Pln& sketchplane, const gp_Dir& dir) { + switch (checkAxis) { + case ForbiddenAxis::NotPerpendicularWithNormal: + // If perpendicular to the normal then it's parallel to the plane + if (sketchplane.Axis().Direction().IsNormal(dir, Precision::Angular())) + throw Base::ValueError("Axis must not be parallel to the sketch plane"); + break; + case ForbiddenAxis::NotParallelWithNormal: + // If parallel with the normal then it's perpendicular to the plane + if (sketchplane.Axis().Direction().IsParallel(dir, Precision::Angular())) + throw Base::ValueError("Axis must not be perpendicular to the sketch plane"); + break; + default: + break; + } + }; + + auto getAxisFromEdge = [](const TopoDS_Edge& refEdge, Base::Vector3d& base, Base::Vector3d& dir) { + if (refEdge.IsNull()) + throw Base::ValueError("Failed to extract rotation edge"); + BRepAdaptor_Curve adapt(refEdge); + gp_Pnt b; + gp_Dir d; + if (adapt.GetType() == GeomAbs_Line) { + b = adapt.Line().Location(); + d = adapt.Line().Direction(); + } + else if (adapt.GetType() == GeomAbs_Circle) { + b = adapt.Circle().Location(); + d = adapt.Circle().Axis().Direction(); + } + else { + throw Base::TypeError("Edge must be a straight line, circle or arc of circle"); + } + + base = Base::Vector3d(b.X(), b.Y(), b.Z()); + dir = Base::Vector3d(d.X(), d.Y(), d.Z()); + }; + dir = Base::Vector3d(0,0,0); // If unchanged signals that no valid axis was found - if (pcReferenceAxis == NULL) + if (!pcReferenceAxis) return; App::DocumentObject* profile = Profile.getValue(); @@ -1102,9 +1141,7 @@ void ProfileBased::getAxis(const App::DocumentObject *pcReferenceAxis, const std base = line->getBasePoint(); dir = line->getDirection(); - // Check that axis is perpendicular with sketch plane! - if (checkPerpendicular && sketchplane.Axis().Direction().IsParallel(gp_Dir(dir.x, dir.y, dir.z), Precision::Angular())) - throw Base::ValueError("Rotation axis must not be perpendicular with the sketch plane"); + verifyAxisFunc(checkAxis, sketchplane, gp_Dir(dir.x, dir.y, dir.z)); return; } @@ -1113,9 +1150,7 @@ void ProfileBased::getAxis(const App::DocumentObject *pcReferenceAxis, const std base = Base::Vector3d(0,0,0); line->Placement.getValue().multVec(Base::Vector3d (1,0,0), dir); - // Check that axis is perpendicular with sketch plane! - if (checkPerpendicular && sketchplane.Axis().Direction().IsParallel(gp_Dir(dir.x, dir.y, dir.z), Precision::Angular())) - throw Base::ValueError("Rotation axis must not be perpendicular with the sketch plane"); + verifyAxisFunc(checkAxis, sketchplane, gp_Dir(dir.x, dir.y, dir.z)); return; } @@ -1134,34 +1169,13 @@ void ProfileBased::getAxis(const App::DocumentObject *pcReferenceAxis, const std } if (ref.ShapeType() == TopAbs_EDGE) { - TopoDS_Edge refEdge = TopoDS::Edge(ref); - if (refEdge.IsNull()) - throw Base::ValueError("Failed to extract rotation edge"); - BRepAdaptor_Curve adapt(refEdge); - gp_Pnt b; - gp_Dir d; - if (adapt.GetType() == GeomAbs_Line) { - b = adapt.Line().Location(); - d = adapt.Line().Direction(); - } else if (adapt.GetType() == GeomAbs_Circle) { - b = adapt.Circle().Location(); - d = adapt.Circle().Axis().Direction(); - } else { - throw Base::TypeError("Rotation edge must be a straight line, circle or arc of circle"); - } - base = Base::Vector3d(b.X(), b.Y(), b.Z()); - dir = Base::Vector3d(d.X(), d.Y(), d.Z()); - // Check that axis is co-planar with sketch plane! - // Check that axis is perpendicular with sketch plane! - if (sketchplane.Axis().Direction().IsParallel(d, Precision::Angular())) - throw Base::ValueError("Rotation axis must not be perpendicular with the sketch plane"); + getAxisFromEdge(TopoDS::Edge(ref), base, dir); + verifyAxisFunc(checkAxis, sketchplane, gp_Dir(dir.x, dir.y, dir.z)); return; - } else { - throw Base::TypeError("Rotation reference must be an edge"); } } - throw Base::TypeError("Rotation axis reference is invalid"); + throw Base::TypeError("Unsupported geometry type to get reference axis"); } Base::Vector3d ProfileBased::getProfileNormal() const { diff --git a/src/Mod/PartDesign/App/FeatureSketchBased.h b/src/Mod/PartDesign/App/FeatureSketchBased.h index 52e1b12f17..3e3522e156 100644 --- a/src/Mod/PartDesign/App/FeatureSketchBased.h +++ b/src/Mod/PartDesign/App/FeatureSketchBased.h @@ -42,6 +42,11 @@ class PartDesignExport ProfileBased : public PartDesign::FeatureAddSub PROPERTY_HEADER(PartDesign::SketchBased); public: + enum class ForbiddenAxis { + NoCheck = 0, + NotPerpendicularWithNormal = 1, + NotParallelWithNormal = 2 + }; ProfileBased(); // Common properties for all sketch based features @@ -182,7 +187,7 @@ protected: double getReversedAngle(const Base::Vector3d& b, const Base::Vector3d& v); /// get Axis from ReferenceAxis void getAxis(const App::DocumentObject* pcReferenceAxis, const std::vector& subReferenceAxis, - Base::Vector3d& base, Base::Vector3d& dir, bool checkPerpendicular=true); + Base::Vector3d& base, Base::Vector3d& dir, ForbiddenAxis checkAxis); void onChanged(const App::Property* prop); private: