Add Part.makeLongHelix to work around Mantis #0954
This commit is contained in:
@@ -857,6 +857,29 @@ static PyObject * makeHelix(PyObject *self, PyObject *args)
|
||||
}
|
||||
}
|
||||
|
||||
static PyObject * makeLongHelix(PyObject *self, PyObject *args)
|
||||
{
|
||||
double pitch, height, radius, angle=-1.0;
|
||||
PyObject *pleft=Py_False;
|
||||
if (!PyArg_ParseTuple(args, "ddd|dO!", &pitch, &height, &radius, &angle,
|
||||
&(PyBool_Type), &pleft)) {
|
||||
Base::Console().Message("Part.makeLongHelix fails on parms\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
try {
|
||||
TopoShape helix;
|
||||
Standard_Boolean anIsLeft = PyObject_IsTrue(pleft) ? Standard_True : Standard_False;
|
||||
TopoDS_Shape wire = helix.makeLongHelix(pitch, height, radius, angle, anIsLeft);
|
||||
return new TopoShapeWirePy(new TopoShape(wire));
|
||||
}
|
||||
catch (Standard_Failure) {
|
||||
Handle_Standard_Failure e = Standard_Failure::Caught();
|
||||
PyErr_SetString(PyExc_Exception, e->GetMessageString());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static PyObject * makeThread(PyObject *self, PyObject *args)
|
||||
{
|
||||
double pitch, depth, height, radius;
|
||||
@@ -1650,6 +1673,11 @@ struct PyMethodDef Part_methods[] = {
|
||||
"By default a cylindrical surface is used to create the helix. If the fourth parameter is set\n"
|
||||
"(the apex given in degree) a conical surface is used instead"},
|
||||
|
||||
{"makeLongHelix" ,makeLongHelix,METH_VARARGS,
|
||||
"makeLongHelix(pitch,height,radius,[angle],[hand]) -- Make a (multi-edge) helix with a given pitch, height and radius\n"
|
||||
"By default a cylindrical surface is used to create the helix. If the fourth parameter is set\n"
|
||||
"(the apex given in degree) a conical surface is used instead."},
|
||||
|
||||
{"makeThread" ,makeThread,METH_VARARGS,
|
||||
"makeThread(pitch,depth,height,radius) -- Make a thread with a given pitch, depth, height and radius"},
|
||||
|
||||
|
||||
@@ -1582,14 +1582,14 @@ TopoDS_Shape TopoShape::makeHelix(Standard_Real pitch, Standard_Real height,
|
||||
|
||||
if (newStyle) {
|
||||
// See discussion at 0001247: Part Conical Helix Height/Pitch Incorrect
|
||||
if (angle >= Precision::Confusion()) {
|
||||
// calculate end point for conical helix
|
||||
Standard_Real v = height / cos(angle);
|
||||
Standard_Real u = (height/pitch) * 2.0 * M_PI;
|
||||
gp_Pnt2d cend(u, v);
|
||||
end = cend;
|
||||
}
|
||||
}
|
||||
if (angle >= Precision::Confusion()) {
|
||||
// calculate end point for conical helix
|
||||
Standard_Real v = height / cos(angle);
|
||||
Standard_Real u = (height/pitch) * 2.0 * M_PI;
|
||||
gp_Pnt2d cend(u, v);
|
||||
end = cend;
|
||||
}
|
||||
}
|
||||
|
||||
Handle(Geom2d_TrimmedCurve) segm = GCE2d_MakeSegment(beg , end);
|
||||
|
||||
@@ -1599,6 +1599,91 @@ TopoDS_Shape TopoShape::makeHelix(Standard_Real pitch, Standard_Real height,
|
||||
return wire;
|
||||
}
|
||||
|
||||
//***********
|
||||
// makeLongHelix is a workaround for an OCC problem found in helices with more than
|
||||
// some magic number of turns. See Mantis #0954.
|
||||
//***********
|
||||
TopoDS_Shape TopoShape::makeLongHelix(Standard_Real pitch, Standard_Real height,
|
||||
Standard_Real radius, Standard_Real angle,
|
||||
Standard_Boolean leftHanded) const
|
||||
{
|
||||
if (pitch < Precision::Confusion())
|
||||
Standard_Failure::Raise("Pitch of helix too small");
|
||||
|
||||
if (height < Precision::Confusion())
|
||||
Standard_Failure::Raise("Height of helix too small");
|
||||
|
||||
gp_Ax2 cylAx2(gp_Pnt(0.0,0.0,0.0) , gp::DZ());
|
||||
Handle_Geom_Surface surf;
|
||||
Standard_Boolean isCylinder;
|
||||
|
||||
if (angle < Precision::Confusion()) { // Cylindrical helix
|
||||
if (radius < Precision::Confusion())
|
||||
Standard_Failure::Raise("Radius of helix too small");
|
||||
surf= new Geom_CylindricalSurface(cylAx2, radius);
|
||||
isCylinder = true;
|
||||
}
|
||||
else { // Conical helix
|
||||
angle = Base::toRadians(angle);
|
||||
if (angle < Precision::Confusion())
|
||||
Standard_Failure::Raise("Angle of helix too small");
|
||||
surf = new Geom_ConicalSurface(gp_Ax3(cylAx2), angle, radius);
|
||||
isCylinder = false;
|
||||
}
|
||||
|
||||
Standard_Real turns = height/pitch;
|
||||
unsigned long wholeTurns = trunc(turns);
|
||||
Standard_Real partTurn = turns - wholeTurns;
|
||||
|
||||
gp_Pnt2d aPnt(0, 0);
|
||||
gp_Dir2d aDir(2. * M_PI, pitch);
|
||||
Standard_Real coneDir = 1.0;
|
||||
if (leftHanded) {
|
||||
aPnt.SetCoord(2. * M_PI, 0.0);
|
||||
aDir.SetCoord(-2. * M_PI, pitch);
|
||||
coneDir = -1.0;
|
||||
}
|
||||
gp_Ax2d aAx2d(aPnt, aDir);
|
||||
Handle(Geom2d_Line) line = new Geom2d_Line(aAx2d);
|
||||
gp_Pnt2d beg = line->Value(0);
|
||||
gp_Pnt2d end;
|
||||
Standard_Real u,v;
|
||||
BRepBuilderAPI_MakeWire mkWire;
|
||||
Handle(Geom2d_TrimmedCurve) segm;
|
||||
TopoDS_Edge edgeOnSurf;
|
||||
|
||||
for (unsigned long i = 0; i < wholeTurns; i++) {
|
||||
if (isCylinder)
|
||||
end = line->Value(sqrt(4.0*M_PI*M_PI+pitch*pitch)*(i+1));
|
||||
else {
|
||||
u = coneDir * (i+1) * 2.0 * M_PI;
|
||||
v = ((i+1) * pitch) / cos(angle);
|
||||
end = gp_Pnt2d(u, v);
|
||||
}
|
||||
segm = GCE2d_MakeSegment(beg , end);
|
||||
edgeOnSurf = BRepBuilderAPI_MakeEdge(segm , surf);
|
||||
mkWire.Add(edgeOnSurf);
|
||||
beg = end;
|
||||
}
|
||||
|
||||
if (partTurn > Precision::Confusion()) {
|
||||
if (isCylinder)
|
||||
end = line->Value(sqrt(4.0*M_PI*M_PI+pitch*pitch)*turns);
|
||||
else {
|
||||
u = coneDir * turns * 2.0 * M_PI;
|
||||
v = height / cos(angle);
|
||||
end = gp_Pnt2d(u, v);
|
||||
}
|
||||
segm = GCE2d_MakeSegment(beg , end);
|
||||
edgeOnSurf = BRepBuilderAPI_MakeEdge(segm , surf);
|
||||
mkWire.Add(edgeOnSurf);
|
||||
}
|
||||
|
||||
TopoDS_Wire wire = mkWire.Wire();
|
||||
BRepLib::BuildCurves3d(wire);
|
||||
return wire;
|
||||
}
|
||||
|
||||
TopoDS_Shape TopoShape::makeThread(Standard_Real pitch,
|
||||
Standard_Real depth,
|
||||
Standard_Real height,
|
||||
|
||||
@@ -163,6 +163,9 @@ public:
|
||||
TopoDS_Shape makeHelix(Standard_Real pitch, Standard_Real height,
|
||||
Standard_Real radius, Standard_Real angle=0,
|
||||
Standard_Boolean left=Standard_False, Standard_Boolean style=Standard_False) const;
|
||||
TopoDS_Shape makeLongHelix(Standard_Real pitch, Standard_Real height,
|
||||
Standard_Real radius, Standard_Real angle=0,
|
||||
Standard_Boolean left=Standard_False) const;
|
||||
TopoDS_Shape makeThread(Standard_Real pitch, Standard_Real depth,
|
||||
Standard_Real height, Standard_Real radius) const;
|
||||
TopoDS_Shape makeLoft(const TopTools_ListOfShape& profiles, Standard_Boolean isSolid,
|
||||
|
||||
Reference in New Issue
Block a user