[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:
@@ -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))
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user