[PD] Helix: Offer profile's normal as axis

Previously, only the vertical and horizontal axis of the profile was
selectable in the task panel of the additive/subtractive helix. Now the
profile's normal axis can be selected, too. This now allows to create
helical extrusions or "twisted pockets".

The order of the GUI entries was chosen to be in line with the order of
axis selection of the multi-transform parameters.
The actual feature's implementation needed adaption for this special case
as in some places a unit vector (`gp_Dir`) was derived from the cross-
product of axis and profile normal -- a null-vector when the axis *is*
the normal. This caused the gp_Dir's ctor to throw.
This commit is contained in:
Jonas Bähr
2021-11-24 22:29:36 +01:00
committed by Uwe
parent bc90f4480b
commit 169c38622c
3 changed files with 26 additions and 3 deletions

View File

@@ -371,6 +371,20 @@ TopoDS_Shape Helix::generateHelixPath(void)
Base::Vector3d normal = getProfileNormal();
Base::Vector3d start = v.Cross(normal); // pointing towards the desired helix start point.
// if our axis is (nearly) aligned with the profile's normal, we're only interested in the "twist"
// of the helix. The actual starting point, and thus the radius, isn't important as long as it's
// somewhere in the profile's plane: an arbitrary vector perpendicular to the normal.
if (start.IsNull()) {
auto hopefullyNotParallel = Base::Vector3d(1.0, 2.0, 3.0);
start = normal.Cross(hopefullyNotParallel);
if (start.IsNull()) {
// bad luck
hopefullyNotParallel = Base::Vector3d(3.0, 2.0, 1.0);
start = normal.Cross(hopefullyNotParallel);
}
}
gp_Dir dir_start(start.x, start.y, start.z);
// Find out in what quadrant relative to the axis the profile is located, and the exact position.
@@ -447,6 +461,12 @@ TopoDS_Shape Helix::generateHelixPath(void)
// this function calculates self intersection safe pitch based on the profile bounding box.
double Helix::safePitch()
{
Base::Vector3d v = Axis.getValue();
Base::Vector3d n = getProfileNormal();
Base::Vector3d s = v.Cross(n); // pointing towards the desired helix start point.
if (s.IsNull())
return Precision::Confusion(); // if the axis orthogonal to the profile, any pitch >0 is safe
// Below is an approximation. It is possible to do the general way by solving for the pitch
// where the helix is self intersecting.
@@ -461,14 +481,11 @@ double Helix::safePitch()
double X = Xmax - Xmin, Y = Ymax - Ymin, Z = Zmax - Zmin;
Base::Vector3d v = Axis.getValue();
gp_Dir dir(v.x,v.y,v.z);
gp_Vec bbvec(X, Y, Z);
double p0 = bbvec*dir; // safe pitch if angle=0
Base::Vector3d n = getProfileNormal();
Base::Vector3d s = v.Cross(n); // pointing towards the desired helix start point.
gp_Dir dir_s(s.x, s.y, s.z);
if (tan(abs(angle))*p0 > abs(bbvec*dir_s))

View File

@@ -202,6 +202,7 @@ void TaskHelixParameters::fillAxisCombo(bool forceRefill)
PartDesign::ProfileBased* pcFeat = static_cast<PartDesign::ProfileBased*>(vp->getObject());
Part::Part2DObject* pcSketch = dynamic_cast<Part::Part2DObject*>(pcFeat->Profile.getValue());
if (pcSketch){
addAxisToCombo(pcSketch,"N_Axis",QObject::tr("Normal sketch axis"));
addAxisToCombo(pcSketch,"V_Axis",QObject::tr("Vertical sketch axis"));
addAxisToCombo(pcSketch,"H_Axis",QObject::tr("Horizontal sketch axis"));
for (int i=0; i < pcSketch->getAxisCount(); i++) {

View File

@@ -70,6 +70,11 @@
<string>Vertical sketch axis</string>
</property>
</item>
<item>
<property name="text">
<string>Normal sketch axis</string>
</property>
</item>
<item>
<property name="text">
<string>Select reference...</string>