PD: fix ProfileBased::getAxis

Introduce an enum to verify the axis depending on the used context.
* For helix no restriction is needed
* For Pad/Pocket the axis must not be parallel with the sketch plane
* For Revolve/Groove the axis must not be perpendicular with the sketch plane
This commit is contained in:
wmayer
2021-12-02 17:24:18 +01:00
parent 5824a64b61
commit d4f0eb5bfb
6 changed files with 56 additions and 37 deletions

View File

@@ -95,7 +95,7 @@ Base::Vector3d FeatureExtrude::computeDirection(const Base::Vector3d& sketchVect
const std::vector<std::string>& 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;

View File

@@ -208,7 +208,7 @@ void Groove::updateAxis(void)
const std::vector<std::string> &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);

View File

@@ -355,7 +355,7 @@ void Helix::updateAxis(void)
const std::vector<std::string>& 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);

View File

@@ -204,7 +204,7 @@ void Revolution::updateAxis(void)
const std::vector<std::string> &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);

View File

@@ -1040,10 +1040,49 @@ double ProfileBased::getReversedAngle(const Base::Vector3d &b, const Base::Vecto
}
void ProfileBased::getAxis(const App::DocumentObject *pcReferenceAxis, const std::vector<std::string> &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 {

View File

@@ -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<std::string>& 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: