discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

Bug in my code or OpenSCAD?

JB
Jordan Brown
Fri, Nov 1, 2024 3:42 AM

Unfortunately, you cannot raise the cone by _conic  + _chamferHeight. The chamfer must (should?) radiate from the “origin” just like the ridge and grooves. I believe your code as written takes a constant chamfer off the teeth, but at the inner radius, that’s too much.

Indeed, I missed that subtlety. Sorry.  Your fix looks right.

> Unfortunately, you cannot raise the cone by _conic + _chamferHeight. The chamfer must (should?) radiate from the “origin” just like the ridge and grooves. I believe your code as written takes a constant chamfer off the teeth, but at the inner radius, that’s too much. Indeed, I missed that subtlety. Sorry. Your fix looks right.
SP
Sanjeev Prabhakar
Fri, Nov 1, 2024 4:20 AM

There was a little issue in the previous code i sent:
here is the corrected one:

from openscad2 import *

hirth coupling

n=20 # number of teeths
ta=60 # teeth angle
ca=10 # for straight 360/42.232 # cone angle
i_r=30 # inner radius
o_r=100 # outer radius
ch=.5 # chamfer height
l1=[[i_r,0],[o_r,0]]
l2=[ q_rot([f'z{i}'],l1)  for i in linspace(0,360,n+1)[:-1]]

l3=axis_rot_1(l1,ax1=[0,1,0],loc1=[o_r,0],theta=ca)
l3= line2length(flip(line2length(l3,(o_r-i_r)+5)),(o_r-i_r)+10)
cone1=[ q_rot([f'z{i}'],l3) for i in linspace(0,360,n)]
l2=psos(cone1,l2,[0,0,1])
l1=[l2[0][0],l2[1][0]]
d1=l_len(l1)/2/cos(d2r(ta))
l1=axis_rot_1(l1,line_as_axis(l2[0]),l2[0][0],ta)
l1=line2length(l1,d1)
l3=[l2[0][1],l2[1][1]]
d2=l_len(l3)/2/cos(d2r(ta))
l3=axis_rot_1(l3,line_as_axis(l2[0]),l2[0][1],ta)
l3=line2length(l3,d2)
l4=[l1[1],l3[1]]

a,b=l4

l4=line2length(flip(line2length(l4,(o_r-i_r)+5)),(o_r-i_r)+10)
cone2=[ q_rot([f'z{i}'],l4) for i in linspace(0,360,n)]
l3=psos(cone2,l2,[0,0,1])
l3=q_rot([f'z{360/n/2}'],l3)
s1=l_(a_([l2,l3]).transpose(1,0,2,3).reshape(n*2,2,3))
s1=s1+[s1[0]]
s1=l_(a_(s1).transpose(1,0,2))
sol1=flip(surf_base(s1,s1[0][1][2]+10))
s2=l_(a_(cone1).transpose(1,0,2))
s2=surface_offset(s2,-ch)
sol2=surf_base(s2,s1[1][0][2]-10)
sol2=sol2+[sol2[0]]
sol3=surf_base(flip(s1),s1[1][0][2]-10)
s3=q_rot(['z5'],l_(a_(cone2[:-1]).transpose(1,0,2)))
s3=surface_offset(s3,ch)
sol4=surf_base(s3,s1[0][1][2]+10)
sol4=sol4+[sol4[0]]
with open('trial.scad','w+') as f:
f.write(f'''

translate([0,0,25])

// color([.13,.81,.37])
difference(){{
{swp_c(sol1)}
{swp_c(sol2)}
}}
difference(){{
{swp_c(sol3)}
{swp_c(sol4)}
}}

''')

On Fri, 1 Nov 2024 at 09:12, Jordan Brown via Discuss <
discuss@lists.openscad.org> wrote:

Unfortunately, you cannot raise the cone by _conic  + _chamferHeight.

The chamfer must (should?) radiate from the “origin” just like the ridge
and grooves. I believe your code as written takes a constant chamfer off
the teeth, but at the inner radius, that’s too much.

Indeed, I missed that subtlety. Sorry.  Your fix looks right.


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

There was a little issue in the previous code i sent: here is the corrected one: from openscad2 import * # hirth coupling n=20 # number of teeths ta=60 # teeth angle ca=10 # for straight 360/42.232 # cone angle i_r=30 # inner radius o_r=100 # outer radius ch=.5 # chamfer height l1=[[i_r,0],[o_r,0]] l2=[ q_rot([f'z{i}'],l1) for i in linspace(0,360,n+1)[:-1]] l3=axis_rot_1(l1,ax1=[0,1,0],loc1=[o_r,0],theta=ca) l3= line2length(flip(line2length(l3,(o_r-i_r)+5)),(o_r-i_r)+10) cone1=[ q_rot([f'z{i}'],l3) for i in linspace(0,360,n)] l2=psos(cone1,l2,[0,0,1]) l1=[l2[0][0],l2[1][0]] d1=l_len(l1)/2/cos(d2r(ta)) l1=axis_rot_1(l1,line_as_axis(l2[0]),l2[0][0],ta) l1=line2length(l1,d1) l3=[l2[0][1],l2[1][1]] d2=l_len(l3)/2/cos(d2r(ta)) l3=axis_rot_1(l3,line_as_axis(l2[0]),l2[0][1],ta) l3=line2length(l3,d2) l4=[l1[1],l3[1]] # a,b=l4 l4=line2length(flip(line2length(l4,(o_r-i_r)+5)),(o_r-i_r)+10) cone2=[ q_rot([f'z{i}'],l4) for i in linspace(0,360,n)] l3=psos(cone2,l2,[0,0,1]) l3=q_rot([f'z{360/n/2}'],l3) s1=l_(a_([l2,l3]).transpose(1,0,2,3).reshape(n*2,2,3)) s1=s1+[s1[0]] s1=l_(a_(s1).transpose(1,0,2)) sol1=flip(surf_base(s1,s1[0][1][2]+10)) s2=l_(a_(cone1).transpose(1,0,2)) s2=surface_offset(s2,-ch) sol2=surf_base(s2,s1[1][0][2]-10) sol2=sol2+[sol2[0]] sol3=surf_base(flip(s1),s1[1][0][2]-10) s3=q_rot(['z5'],l_(a_(cone2[:-1]).transpose(1,0,2))) s3=surface_offset(s3,ch) sol4=surf_base(s3,s1[0][1][2]+10) sol4=sol4+[sol4[0]] with open('trial.scad','w+') as f: f.write(f''' translate([0,0,25]) // color([.13,.81,.37]) difference(){{ {swp_c(sol1)} {swp_c(sol2)} }} difference(){{ {swp_c(sol3)} {swp_c(sol4)} }} ''') On Fri, 1 Nov 2024 at 09:12, Jordan Brown via Discuss < discuss@lists.openscad.org> wrote: > > > > Unfortunately, you cannot raise the cone by _conic + _chamferHeight. > The chamfer must (should?) radiate from the “origin” just like the ridge > and grooves. I believe your code as written takes a constant chamfer off > the teeth, but at the inner radius, that’s too much. > > Indeed, I missed that subtlety. Sorry. Your fix looks right. > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org >
JD
John David
Fri, Nov 1, 2024 6:59 PM

Ummmm... Hirth Joint https://en.wikipedia.org/wiki/Hirth_joint  That
said, maybe because you used "joints" threw it as they are singular.  Hope
this helps.

On Fri, Nov 1, 2024 at 12:20 AM Sanjeev Prabhakar via Discuss <
discuss@lists.openscad.org> wrote:

There was a little issue in the previous code i sent:
here is the corrected one:

from openscad2 import *

hirth coupling

n=20 # number of teeths
ta=60 # teeth angle
ca=10 # for straight 360/42.232 # cone angle
i_r=30 # inner radius
o_r=100 # outer radius
ch=.5 # chamfer height
l1=[[i_r,0],[o_r,0]]
l2=[ q_rot([f'z{i}'],l1)  for i in linspace(0,360,n+1)[:-1]]

l3=axis_rot_1(l1,ax1=[0,1,0],loc1=[o_r,0],theta=ca)
l3= line2length(flip(line2length(l3,(o_r-i_r)+5)),(o_r-i_r)+10)
cone1=[ q_rot([f'z{i}'],l3) for i in linspace(0,360,n)]
l2=psos(cone1,l2,[0,0,1])
l1=[l2[0][0],l2[1][0]]
d1=l_len(l1)/2/cos(d2r(ta))
l1=axis_rot_1(l1,line_as_axis(l2[0]),l2[0][0],ta)
l1=line2length(l1,d1)
l3=[l2[0][1],l2[1][1]]
d2=l_len(l3)/2/cos(d2r(ta))
l3=axis_rot_1(l3,line_as_axis(l2[0]),l2[0][1],ta)
l3=line2length(l3,d2)
l4=[l1[1],l3[1]]

a,b=l4

l4=line2length(flip(line2length(l4,(o_r-i_r)+5)),(o_r-i_r)+10)
cone2=[ q_rot([f'z{i}'],l4) for i in linspace(0,360,n)]
l3=psos(cone2,l2,[0,0,1])
l3=q_rot([f'z{360/n/2}'],l3)
s1=l_(a_([l2,l3]).transpose(1,0,2,3).reshape(n*2,2,3))
s1=s1+[s1[0]]
s1=l_(a_(s1).transpose(1,0,2))
sol1=flip(surf_base(s1,s1[0][1][2]+10))
s2=l_(a_(cone1).transpose(1,0,2))
s2=surface_offset(s2,-ch)
sol2=surf_base(s2,s1[1][0][2]-10)
sol2=sol2+[sol2[0]]
sol3=surf_base(flip(s1),s1[1][0][2]-10)
s3=q_rot(['z5'],l_(a_(cone2[:-1]).transpose(1,0,2)))
s3=surface_offset(s3,ch)
sol4=surf_base(s3,s1[0][1][2]+10)
sol4=sol4+[sol4[0]]
with open('trial.scad','w+') as f:
f.write(f'''

 translate([0,0,25])
// color([.13,.81,.37])
 difference(){{
 {swp_c(sol1)}
 {swp_c(sol2)}
 }}

difference(){{
{swp_c(sol3)}
{swp_c(sol4)}
}}

 ''')

On Fri, 1 Nov 2024 at 09:12, Jordan Brown via Discuss <
discuss@lists.openscad.org> wrote:

Unfortunately, you cannot raise the cone by _conic  + _chamferHeight.

The chamfer must (should?) radiate from the “origin” just like the ridge
and grooves. I believe your code as written takes a constant chamfer off
the teeth, but at the inner radius, that’s too much.

Indeed, I missed that subtlety. Sorry.  Your fix looks right.


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

Ummmm... Hirth Joint <https://en.wikipedia.org/wiki/Hirth_joint> That said, maybe because you used "joints" threw it as they are singular. Hope this helps. On Fri, Nov 1, 2024 at 12:20 AM Sanjeev Prabhakar via Discuss < discuss@lists.openscad.org> wrote: > There was a little issue in the previous code i sent: > here is the corrected one: > > from openscad2 import * > > # hirth coupling > n=20 # number of teeths > ta=60 # teeth angle > ca=10 # for straight 360/42.232 # cone angle > i_r=30 # inner radius > o_r=100 # outer radius > ch=.5 # chamfer height > l1=[[i_r,0],[o_r,0]] > l2=[ q_rot([f'z{i}'],l1) for i in linspace(0,360,n+1)[:-1]] > > l3=axis_rot_1(l1,ax1=[0,1,0],loc1=[o_r,0],theta=ca) > l3= line2length(flip(line2length(l3,(o_r-i_r)+5)),(o_r-i_r)+10) > cone1=[ q_rot([f'z{i}'],l3) for i in linspace(0,360,n)] > l2=psos(cone1,l2,[0,0,1]) > l1=[l2[0][0],l2[1][0]] > d1=l_len(l1)/2/cos(d2r(ta)) > l1=axis_rot_1(l1,line_as_axis(l2[0]),l2[0][0],ta) > l1=line2length(l1,d1) > l3=[l2[0][1],l2[1][1]] > d2=l_len(l3)/2/cos(d2r(ta)) > l3=axis_rot_1(l3,line_as_axis(l2[0]),l2[0][1],ta) > l3=line2length(l3,d2) > l4=[l1[1],l3[1]] > # a,b=l4 > l4=line2length(flip(line2length(l4,(o_r-i_r)+5)),(o_r-i_r)+10) > cone2=[ q_rot([f'z{i}'],l4) for i in linspace(0,360,n)] > l3=psos(cone2,l2,[0,0,1]) > l3=q_rot([f'z{360/n/2}'],l3) > s1=l_(a_([l2,l3]).transpose(1,0,2,3).reshape(n*2,2,3)) > s1=s1+[s1[0]] > s1=l_(a_(s1).transpose(1,0,2)) > sol1=flip(surf_base(s1,s1[0][1][2]+10)) > s2=l_(a_(cone1).transpose(1,0,2)) > s2=surface_offset(s2,-ch) > sol2=surf_base(s2,s1[1][0][2]-10) > sol2=sol2+[sol2[0]] > sol3=surf_base(flip(s1),s1[1][0][2]-10) > s3=q_rot(['z5'],l_(a_(cone2[:-1]).transpose(1,0,2))) > s3=surface_offset(s3,ch) > sol4=surf_base(s3,s1[0][1][2]+10) > sol4=sol4+[sol4[0]] > with open('trial.scad','w+') as f: > f.write(f''' > > translate([0,0,25]) > // color([.13,.81,.37]) > difference(){{ > {swp_c(sol1)} > {swp_c(sol2)} > }} > difference(){{ > {swp_c(sol3)} > {swp_c(sol4)} > }} > > ''') > > On Fri, 1 Nov 2024 at 09:12, Jordan Brown via Discuss < > discuss@lists.openscad.org> wrote: > >> >> >> > Unfortunately, you cannot raise the cone by _conic + _chamferHeight. >> The chamfer must (should?) radiate from the “origin” just like the ridge >> and grooves. I believe your code as written takes a constant chamfer off >> the teeth, but at the inner radius, that’s too much. >> >> Indeed, I missed that subtlety. Sorry. Your fix looks right. >> _______________________________________________ >> OpenSCAD mailing list >> To unsubscribe send an email to discuss-leave@lists.openscad.org >> > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org >
RW
Raymond West
Fri, Nov 1, 2024 7:44 PM

I modified my previous code, to reproduce the recess and centre hole.
These items were simple to make before the advent of cnc. If grinding, a
simple link between the traverse and spindle height and a rotary table,
with correctly profiled wheel. The crest of the ridges could be skimmed
off, so they didn't bottom out. As they are meant to be a solid joint, 
although separation available, they can have simpler design requirements
compared to gear wheels.

I may print a couple, see what torque they can take, compared to say,
flat solvent welded joints.

On 01/11/2024 18:59, John David via Discuss wrote:

Ummmm... Hirth Joint https://en.wikipedia.org/wiki/Hirth_joint That
said, maybe because you used "joints" threw it as they are singular. 
Hope this helps.

On Fri, Nov 1, 2024 at 12:20 AM Sanjeev Prabhakar via Discuss
discuss@lists.openscad.org wrote:

 There was a little issue in the previous code i sent:
 here is the corrected one:

 from openscad2 import *

 # hirth coupling
 n=20 # number of teeths
 ta=60 # teeth angle
 ca=10 # for straight 360/42.232 # cone angle
 i_r=30 # inner radius
 o_r=100 # outer radius
 ch=.5 # chamfer height
 l1=[[i_r,0],[o_r,0]]
 l2=[ q_rot([f'z{i}'],l1)  for i in linspace(0,360,n+1)[:-1]]

 l3=axis_rot_1(l1,ax1=[0,1,0],loc1=[o_r,0],theta=ca)
 l3= line2length(flip(line2length(l3,(o_r-i_r)+5)),(o_r-i_r)+10)
 cone1=[ q_rot([f'z{i}'],l3) for i in linspace(0,360,n)]
 l2=psos(cone1,l2,[0,0,1])
 l1=[l2[0][0],l2[1][0]]
 d1=l_len(l1)/2/cos(d2r(ta))
 l1=axis_rot_1(l1,line_as_axis(l2[0]),l2[0][0],ta)
 l1=line2length(l1,d1)
 l3=[l2[0][1],l2[1][1]]
 d2=l_len(l3)/2/cos(d2r(ta))
 l3=axis_rot_1(l3,line_as_axis(l2[0]),l2[0][1],ta)
 l3=line2length(l3,d2)
 l4=[l1[1],l3[1]]
 # a,b=l4
 l4=line2length(flip(line2length(l4,(o_r-i_r)+5)),(o_r-i_r)+10)
 cone2=[ q_rot([f'z{i}'],l4) for i in linspace(0,360,n)]
 l3=psos(cone2,l2,[0,0,1])
 l3=q_rot([f'z{360/n/2}'],l3)
 s1=l_(a_([l2,l3]).transpose(1,0,2,3).reshape(n*2,2,3))
 s1=s1+[s1[0]]
 s1=l_(a_(s1).transpose(1,0,2))
 sol1=flip(surf_base(s1,s1[0][1][2]+10))
 s2=l_(a_(cone1).transpose(1,0,2))
 s2=surface_offset(s2,-ch)
 sol2=surf_base(s2,s1[1][0][2]-10)
 sol2=sol2+[sol2[0]]
 sol3=surf_base(flip(s1),s1[1][0][2]-10)
 s3=q_rot(['z5'],l_(a_(cone2[:-1]).transpose(1,0,2)))
 s3=surface_offset(s3,ch)
 sol4=surf_base(s3,s1[0][1][2]+10)
 sol4=sol4+[sol4[0]]
 with open('trial.scad','w+') as f:
     f.write(f'''

     translate([0,0,25])
    // color([.13,.81,.37])
     difference(){{
     {swp_c(sol1)}
     {swp_c(sol2)}
     }}
 difference(){{
    {swp_c(sol3)}
    {swp_c(sol4)}
    }}

     ''')

 On Fri, 1 Nov 2024 at 09:12, Jordan Brown via Discuss
 <discuss@lists.openscad.org> wrote:

Unfortunately, you cannot raise the cone by _conic +

     _chamferHeight. The chamfer must (should?) radiate from the
     “origin” just like the ridge and grooves. I believe your code
     as written takes a constant chamfer off the teeth, but at the
     inner radius, that’s too much.

     Indeed, I missed that subtlety. Sorry.  Your fix looks right.
     _______________________________________________
     OpenSCAD mailing list
     To unsubscribe send an email to discuss-leave@lists.openscad.org

 _______________________________________________
 OpenSCAD mailing list
 To unsubscribe send an email to discuss-leave@lists.openscad.org

OpenSCAD mailing list
To unsubscribe send an email todiscuss-leave@lists.openscad.org

I modified my previous code, to reproduce the recess and centre hole. These items were simple to make before the advent of cnc. If grinding, a simple link between the traverse and spindle height and a rotary table, with correctly profiled wheel. The crest of the ridges could be skimmed off, so they didn't bottom out. As they are meant to be a solid joint,  although separation available, they can have simpler design requirements compared to gear wheels. I may print a couple, see what torque they can take, compared to say, flat solvent welded joints. On 01/11/2024 18:59, John David via Discuss wrote: > Ummmm... Hirth Joint <https://en.wikipedia.org/wiki/Hirth_joint> That > said, maybe because you used "joints" threw it as they are singular.  > Hope this helps. > > On Fri, Nov 1, 2024 at 12:20 AM Sanjeev Prabhakar via Discuss > <discuss@lists.openscad.org> wrote: > > There was a little issue in the previous code i sent: > here is the corrected one: > > from openscad2 import * > > # hirth coupling > n=20 # number of teeths > ta=60 # teeth angle > ca=10 # for straight 360/42.232 # cone angle > i_r=30 # inner radius > o_r=100 # outer radius > ch=.5 # chamfer height > l1=[[i_r,0],[o_r,0]] > l2=[ q_rot([f'z{i}'],l1)  for i in linspace(0,360,n+1)[:-1]] > > l3=axis_rot_1(l1,ax1=[0,1,0],loc1=[o_r,0],theta=ca) > l3= line2length(flip(line2length(l3,(o_r-i_r)+5)),(o_r-i_r)+10) > cone1=[ q_rot([f'z{i}'],l3) for i in linspace(0,360,n)] > l2=psos(cone1,l2,[0,0,1]) > l1=[l2[0][0],l2[1][0]] > d1=l_len(l1)/2/cos(d2r(ta)) > l1=axis_rot_1(l1,line_as_axis(l2[0]),l2[0][0],ta) > l1=line2length(l1,d1) > l3=[l2[0][1],l2[1][1]] > d2=l_len(l3)/2/cos(d2r(ta)) > l3=axis_rot_1(l3,line_as_axis(l2[0]),l2[0][1],ta) > l3=line2length(l3,d2) > l4=[l1[1],l3[1]] > # a,b=l4 > l4=line2length(flip(line2length(l4,(o_r-i_r)+5)),(o_r-i_r)+10) > cone2=[ q_rot([f'z{i}'],l4) for i in linspace(0,360,n)] > l3=psos(cone2,l2,[0,0,1]) > l3=q_rot([f'z{360/n/2}'],l3) > s1=l_(a_([l2,l3]).transpose(1,0,2,3).reshape(n*2,2,3)) > s1=s1+[s1[0]] > s1=l_(a_(s1).transpose(1,0,2)) > sol1=flip(surf_base(s1,s1[0][1][2]+10)) > s2=l_(a_(cone1).transpose(1,0,2)) > s2=surface_offset(s2,-ch) > sol2=surf_base(s2,s1[1][0][2]-10) > sol2=sol2+[sol2[0]] > sol3=surf_base(flip(s1),s1[1][0][2]-10) > s3=q_rot(['z5'],l_(a_(cone2[:-1]).transpose(1,0,2))) > s3=surface_offset(s3,ch) > sol4=surf_base(s3,s1[0][1][2]+10) > sol4=sol4+[sol4[0]] > with open('trial.scad','w+') as f: >     f.write(f''' > >     translate([0,0,25]) >    // color([.13,.81,.37]) >     difference(){{ >     {swp_c(sol1)} >     {swp_c(sol2)} >     }} > difference(){{ >    {swp_c(sol3)} >    {swp_c(sol4)} >    }} > >     ''') > > On Fri, 1 Nov 2024 at 09:12, Jordan Brown via Discuss > <discuss@lists.openscad.org> wrote: > > > > > Unfortunately, you cannot raise the cone by _conic + > _chamferHeight. The chamfer must (should?) radiate from the > “origin” just like the ridge and grooves. I believe your code > as written takes a constant chamfer off the teeth, but at the > inner radius, that’s too much. > > Indeed, I missed that subtlety. Sorry.  Your fix looks right. > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org > > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org > > > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email todiscuss-leave@lists.openscad.org
AM
Adrian Mariano
Fri, Nov 1, 2024 8:19 PM

I'm not sure what you are suggesting with the "ummm" and the reference to a
remarkably short and unhelpful wikipedia entry, that gives absolutely no
information on how you might design one, doesn't mention the conical
version, doesn't talk about the basic parameters of the joint.  Basically
useless.

In ongoing fiddling with my code I've found that this is remarkably tricky
to get right.  My version looked OK with lots of teeth but at low teeth
count, the errors became apparent.  Bob's version works even at low teeth
count, at least in terms of producing a proper mesh between the parts.

On Fri, Nov 1, 2024 at 2:59 PM John David via Discuss <
discuss@lists.openscad.org> wrote:

Ummmm... Hirth Joint https://en.wikipedia.org/wiki/Hirth_joint  That
said, maybe because you used "joints" threw it as they are singular.  Hope
this helps.

On Fri, Nov 1, 2024 at 12:20 AM Sanjeev Prabhakar via Discuss <
discuss@lists.openscad.org> wrote:

There was a little issue in the previous code i sent:
here is the corrected one:

from openscad2 import *

hirth coupling

n=20 # number of teeths
ta=60 # teeth angle
ca=10 # for straight 360/42.232 # cone angle
i_r=30 # inner radius
o_r=100 # outer radius
ch=.5 # chamfer height
l1=[[i_r,0],[o_r,0]]
l2=[ q_rot([f'z{i}'],l1)  for i in linspace(0,360,n+1)[:-1]]

l3=axis_rot_1(l1,ax1=[0,1,0],loc1=[o_r,0],theta=ca)
l3= line2length(flip(line2length(l3,(o_r-i_r)+5)),(o_r-i_r)+10)
cone1=[ q_rot([f'z{i}'],l3) for i in linspace(0,360,n)]
l2=psos(cone1,l2,[0,0,1])
l1=[l2[0][0],l2[1][0]]
d1=l_len(l1)/2/cos(d2r(ta))
l1=axis_rot_1(l1,line_as_axis(l2[0]),l2[0][0],ta)
l1=line2length(l1,d1)
l3=[l2[0][1],l2[1][1]]
d2=l_len(l3)/2/cos(d2r(ta))
l3=axis_rot_1(l3,line_as_axis(l2[0]),l2[0][1],ta)
l3=line2length(l3,d2)
l4=[l1[1],l3[1]]

a,b=l4

l4=line2length(flip(line2length(l4,(o_r-i_r)+5)),(o_r-i_r)+10)
cone2=[ q_rot([f'z{i}'],l4) for i in linspace(0,360,n)]
l3=psos(cone2,l2,[0,0,1])
l3=q_rot([f'z{360/n/2}'],l3)
s1=l_(a_([l2,l3]).transpose(1,0,2,3).reshape(n*2,2,3))
s1=s1+[s1[0]]
s1=l_(a_(s1).transpose(1,0,2))
sol1=flip(surf_base(s1,s1[0][1][2]+10))
s2=l_(a_(cone1).transpose(1,0,2))
s2=surface_offset(s2,-ch)
sol2=surf_base(s2,s1[1][0][2]-10)
sol2=sol2+[sol2[0]]
sol3=surf_base(flip(s1),s1[1][0][2]-10)
s3=q_rot(['z5'],l_(a_(cone2[:-1]).transpose(1,0,2)))
s3=surface_offset(s3,ch)
sol4=surf_base(s3,s1[0][1][2]+10)
sol4=sol4+[sol4[0]]
with open('trial.scad','w+') as f:
f.write(f'''

 translate([0,0,25])
// color([.13,.81,.37])
 difference(){{
 {swp_c(sol1)}
 {swp_c(sol2)}
 }}

difference(){{
{swp_c(sol3)}
{swp_c(sol4)}
}}

 ''')

On Fri, 1 Nov 2024 at 09:12, Jordan Brown via Discuss <
discuss@lists.openscad.org> wrote:

Unfortunately, you cannot raise the cone by _conic  + _chamferHeight.

The chamfer must (should?) radiate from the “origin” just like the ridge
and grooves. I believe your code as written takes a constant chamfer off
the teeth, but at the inner radius, that’s too much.

Indeed, I missed that subtlety. Sorry.  Your fix looks right.


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

I'm not sure what you are suggesting with the "ummm" and the reference to a remarkably short and unhelpful wikipedia entry, that gives absolutely no information on how you might design one, doesn't mention the conical version, doesn't talk about the basic parameters of the joint. Basically useless. In ongoing fiddling with my code I've found that this is remarkably tricky to get right. My version looked OK with lots of teeth but at low teeth count, the errors became apparent. Bob's version works even at low teeth count, at least in terms of producing a proper mesh between the parts. On Fri, Nov 1, 2024 at 2:59 PM John David via Discuss < discuss@lists.openscad.org> wrote: > Ummmm... Hirth Joint <https://en.wikipedia.org/wiki/Hirth_joint> That > said, maybe because you used "joints" threw it as they are singular. Hope > this helps. > > On Fri, Nov 1, 2024 at 12:20 AM Sanjeev Prabhakar via Discuss < > discuss@lists.openscad.org> wrote: > >> There was a little issue in the previous code i sent: >> here is the corrected one: >> >> from openscad2 import * >> >> # hirth coupling >> n=20 # number of teeths >> ta=60 # teeth angle >> ca=10 # for straight 360/42.232 # cone angle >> i_r=30 # inner radius >> o_r=100 # outer radius >> ch=.5 # chamfer height >> l1=[[i_r,0],[o_r,0]] >> l2=[ q_rot([f'z{i}'],l1) for i in linspace(0,360,n+1)[:-1]] >> >> l3=axis_rot_1(l1,ax1=[0,1,0],loc1=[o_r,0],theta=ca) >> l3= line2length(flip(line2length(l3,(o_r-i_r)+5)),(o_r-i_r)+10) >> cone1=[ q_rot([f'z{i}'],l3) for i in linspace(0,360,n)] >> l2=psos(cone1,l2,[0,0,1]) >> l1=[l2[0][0],l2[1][0]] >> d1=l_len(l1)/2/cos(d2r(ta)) >> l1=axis_rot_1(l1,line_as_axis(l2[0]),l2[0][0],ta) >> l1=line2length(l1,d1) >> l3=[l2[0][1],l2[1][1]] >> d2=l_len(l3)/2/cos(d2r(ta)) >> l3=axis_rot_1(l3,line_as_axis(l2[0]),l2[0][1],ta) >> l3=line2length(l3,d2) >> l4=[l1[1],l3[1]] >> # a,b=l4 >> l4=line2length(flip(line2length(l4,(o_r-i_r)+5)),(o_r-i_r)+10) >> cone2=[ q_rot([f'z{i}'],l4) for i in linspace(0,360,n)] >> l3=psos(cone2,l2,[0,0,1]) >> l3=q_rot([f'z{360/n/2}'],l3) >> s1=l_(a_([l2,l3]).transpose(1,0,2,3).reshape(n*2,2,3)) >> s1=s1+[s1[0]] >> s1=l_(a_(s1).transpose(1,0,2)) >> sol1=flip(surf_base(s1,s1[0][1][2]+10)) >> s2=l_(a_(cone1).transpose(1,0,2)) >> s2=surface_offset(s2,-ch) >> sol2=surf_base(s2,s1[1][0][2]-10) >> sol2=sol2+[sol2[0]] >> sol3=surf_base(flip(s1),s1[1][0][2]-10) >> s3=q_rot(['z5'],l_(a_(cone2[:-1]).transpose(1,0,2))) >> s3=surface_offset(s3,ch) >> sol4=surf_base(s3,s1[0][1][2]+10) >> sol4=sol4+[sol4[0]] >> with open('trial.scad','w+') as f: >> f.write(f''' >> >> translate([0,0,25]) >> // color([.13,.81,.37]) >> difference(){{ >> {swp_c(sol1)} >> {swp_c(sol2)} >> }} >> difference(){{ >> {swp_c(sol3)} >> {swp_c(sol4)} >> }} >> >> ''') >> >> On Fri, 1 Nov 2024 at 09:12, Jordan Brown via Discuss < >> discuss@lists.openscad.org> wrote: >> >>> >>> >>> > Unfortunately, you cannot raise the cone by _conic + _chamferHeight. >>> The chamfer must (should?) radiate from the “origin” just like the ridge >>> and grooves. I believe your code as written takes a constant chamfer off >>> the teeth, but at the inner radius, that’s too much. >>> >>> Indeed, I missed that subtlety. Sorry. Your fix looks right. >>> _______________________________________________ >>> OpenSCAD mailing list >>> To unsubscribe send an email to discuss-leave@lists.openscad.org >>> >> _______________________________________________ >> OpenSCAD mailing list >> To unsubscribe send an email to discuss-leave@lists.openscad.org >> > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org >
M
mikeonenine@web.de
Fri, Nov 1, 2024 9:33 PM

Adrian Mariano wrote:

I'm not sure what you are suggesting with the "ummm" and the reference to a
remarkably short and unhelpful wikipedia entry, that gives absolutely no
information on how you might design one, doesn't mention the conical
version, doesn't talk about the basic parameters of the joint.  Basically
useless.

Another remarkably short and unhelpful wikipedia entry:

https://en.wikipedia.org/wiki/Spline_(mechanical)

Doesn’t even mention face splines let alone conical ones!!!

Adrian Mariano wrote: > I'm not sure what you are suggesting with the "ummm" and the reference to a > remarkably short and unhelpful wikipedia entry, that gives absolutely no > information on how you might design one, doesn't mention the conical > version, doesn't talk about the basic parameters of the joint. Basically > useless. Another remarkably short and unhelpful wikipedia entry: https://en.wikipedia.org/wiki/Spline_(mechanical) Doesn’t even mention face splines let alone conical ones!!!
JD
John David
Fri, Nov 1, 2024 9:53 PM

Sorry Adrian.  Your post basically said there was no such thing, and was
also terse on details on what you wanted.  So, they are on the net with a
slight change of spelling.  That was the entire reason for my post.

If you want me to explain how to make them in a tool-and-die shop, or how
modeling a machine-tool path as a diff operator will give you the same
thing, I can go over that.  I'll be backing up to travel tonight, so if you
want me to code that up it will be next week sometime at the earliest.

EBo --

On Fri, Nov 1, 2024 at 4:20 PM Adrian Mariano avm4@cornell.edu wrote:

I'm not sure what you are suggesting with the "ummm" and the reference to
a remarkably short and unhelpful wikipedia entry, that gives absolutely no
information on how you might design one, doesn't mention the conical
version, doesn't talk about the basic parameters of the joint.  Basically
useless.

In ongoing fiddling with my code I've found that this is remarkably tricky
to get right.  My version looked OK with lots of teeth but at low teeth
count, the errors became apparent.  Bob's version works even at low teeth
count, at least in terms of producing a proper mesh between the parts.

On Fri, Nov 1, 2024 at 2:59 PM John David via Discuss <
discuss@lists.openscad.org> wrote:

Ummmm... Hirth Joint https://en.wikipedia.org/wiki/Hirth_joint  That
said, maybe because you used "joints" threw it as they are singular.  Hope
this helps.

On Fri, Nov 1, 2024 at 12:20 AM Sanjeev Prabhakar via Discuss <
discuss@lists.openscad.org> wrote:

There was a little issue in the previous code i sent:
here is the corrected one:

from openscad2 import *

hirth coupling

n=20 # number of teeths
ta=60 # teeth angle
ca=10 # for straight 360/42.232 # cone angle
i_r=30 # inner radius
o_r=100 # outer radius
ch=.5 # chamfer height
l1=[[i_r,0],[o_r,0]]
l2=[ q_rot([f'z{i}'],l1)  for i in linspace(0,360,n+1)[:-1]]

l3=axis_rot_1(l1,ax1=[0,1,0],loc1=[o_r,0],theta=ca)
l3= line2length(flip(line2length(l3,(o_r-i_r)+5)),(o_r-i_r)+10)
cone1=[ q_rot([f'z{i}'],l3) for i in linspace(0,360,n)]
l2=psos(cone1,l2,[0,0,1])
l1=[l2[0][0],l2[1][0]]
d1=l_len(l1)/2/cos(d2r(ta))
l1=axis_rot_1(l1,line_as_axis(l2[0]),l2[0][0],ta)
l1=line2length(l1,d1)
l3=[l2[0][1],l2[1][1]]
d2=l_len(l3)/2/cos(d2r(ta))
l3=axis_rot_1(l3,line_as_axis(l2[0]),l2[0][1],ta)
l3=line2length(l3,d2)
l4=[l1[1],l3[1]]

a,b=l4

l4=line2length(flip(line2length(l4,(o_r-i_r)+5)),(o_r-i_r)+10)
cone2=[ q_rot([f'z{i}'],l4) for i in linspace(0,360,n)]
l3=psos(cone2,l2,[0,0,1])
l3=q_rot([f'z{360/n/2}'],l3)
s1=l_(a_([l2,l3]).transpose(1,0,2,3).reshape(n*2,2,3))
s1=s1+[s1[0]]
s1=l_(a_(s1).transpose(1,0,2))
sol1=flip(surf_base(s1,s1[0][1][2]+10))
s2=l_(a_(cone1).transpose(1,0,2))
s2=surface_offset(s2,-ch)
sol2=surf_base(s2,s1[1][0][2]-10)
sol2=sol2+[sol2[0]]
sol3=surf_base(flip(s1),s1[1][0][2]-10)
s3=q_rot(['z5'],l_(a_(cone2[:-1]).transpose(1,0,2)))
s3=surface_offset(s3,ch)
sol4=surf_base(s3,s1[0][1][2]+10)
sol4=sol4+[sol4[0]]
with open('trial.scad','w+') as f:
f.write(f'''

 translate([0,0,25])
// color([.13,.81,.37])
 difference(){{
 {swp_c(sol1)}
 {swp_c(sol2)}
 }}

difference(){{
{swp_c(sol3)}
{swp_c(sol4)}
}}

 ''')

On Fri, 1 Nov 2024 at 09:12, Jordan Brown via Discuss <
discuss@lists.openscad.org> wrote:

Unfortunately, you cannot raise the cone by _conic  +

_chamferHeight. The chamfer must (should?) radiate from the “origin” just
like the ridge and grooves. I believe your code as written takes a constant
chamfer off the teeth, but at the inner radius, that’s too much.

Indeed, I missed that subtlety. Sorry.  Your fix looks right.


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

Sorry Adrian. Your post basically said there was no such thing, and was also terse on details on what you wanted. So, they are on the net with a slight change of spelling. That was the entire reason for my post. If you want me to explain how to make them in a tool-and-die shop, or how modeling a machine-tool path as a diff operator will give you the same thing, I can go over that. I'll be backing up to travel tonight, so if you want me to code that up it will be next week sometime at the earliest. EBo -- On Fri, Nov 1, 2024 at 4:20 PM Adrian Mariano <avm4@cornell.edu> wrote: > I'm not sure what you are suggesting with the "ummm" and the reference to > a remarkably short and unhelpful wikipedia entry, that gives absolutely no > information on how you might design one, doesn't mention the conical > version, doesn't talk about the basic parameters of the joint. Basically > useless. > > In ongoing fiddling with my code I've found that this is remarkably tricky > to get right. My version looked OK with lots of teeth but at low teeth > count, the errors became apparent. Bob's version works even at low teeth > count, at least in terms of producing a proper mesh between the parts. > > On Fri, Nov 1, 2024 at 2:59 PM John David via Discuss < > discuss@lists.openscad.org> wrote: > >> Ummmm... Hirth Joint <https://en.wikipedia.org/wiki/Hirth_joint> That >> said, maybe because you used "joints" threw it as they are singular. Hope >> this helps. >> >> On Fri, Nov 1, 2024 at 12:20 AM Sanjeev Prabhakar via Discuss < >> discuss@lists.openscad.org> wrote: >> >>> There was a little issue in the previous code i sent: >>> here is the corrected one: >>> >>> from openscad2 import * >>> >>> # hirth coupling >>> n=20 # number of teeths >>> ta=60 # teeth angle >>> ca=10 # for straight 360/42.232 # cone angle >>> i_r=30 # inner radius >>> o_r=100 # outer radius >>> ch=.5 # chamfer height >>> l1=[[i_r,0],[o_r,0]] >>> l2=[ q_rot([f'z{i}'],l1) for i in linspace(0,360,n+1)[:-1]] >>> >>> l3=axis_rot_1(l1,ax1=[0,1,0],loc1=[o_r,0],theta=ca) >>> l3= line2length(flip(line2length(l3,(o_r-i_r)+5)),(o_r-i_r)+10) >>> cone1=[ q_rot([f'z{i}'],l3) for i in linspace(0,360,n)] >>> l2=psos(cone1,l2,[0,0,1]) >>> l1=[l2[0][0],l2[1][0]] >>> d1=l_len(l1)/2/cos(d2r(ta)) >>> l1=axis_rot_1(l1,line_as_axis(l2[0]),l2[0][0],ta) >>> l1=line2length(l1,d1) >>> l3=[l2[0][1],l2[1][1]] >>> d2=l_len(l3)/2/cos(d2r(ta)) >>> l3=axis_rot_1(l3,line_as_axis(l2[0]),l2[0][1],ta) >>> l3=line2length(l3,d2) >>> l4=[l1[1],l3[1]] >>> # a,b=l4 >>> l4=line2length(flip(line2length(l4,(o_r-i_r)+5)),(o_r-i_r)+10) >>> cone2=[ q_rot([f'z{i}'],l4) for i in linspace(0,360,n)] >>> l3=psos(cone2,l2,[0,0,1]) >>> l3=q_rot([f'z{360/n/2}'],l3) >>> s1=l_(a_([l2,l3]).transpose(1,0,2,3).reshape(n*2,2,3)) >>> s1=s1+[s1[0]] >>> s1=l_(a_(s1).transpose(1,0,2)) >>> sol1=flip(surf_base(s1,s1[0][1][2]+10)) >>> s2=l_(a_(cone1).transpose(1,0,2)) >>> s2=surface_offset(s2,-ch) >>> sol2=surf_base(s2,s1[1][0][2]-10) >>> sol2=sol2+[sol2[0]] >>> sol3=surf_base(flip(s1),s1[1][0][2]-10) >>> s3=q_rot(['z5'],l_(a_(cone2[:-1]).transpose(1,0,2))) >>> s3=surface_offset(s3,ch) >>> sol4=surf_base(s3,s1[0][1][2]+10) >>> sol4=sol4+[sol4[0]] >>> with open('trial.scad','w+') as f: >>> f.write(f''' >>> >>> translate([0,0,25]) >>> // color([.13,.81,.37]) >>> difference(){{ >>> {swp_c(sol1)} >>> {swp_c(sol2)} >>> }} >>> difference(){{ >>> {swp_c(sol3)} >>> {swp_c(sol4)} >>> }} >>> >>> ''') >>> >>> On Fri, 1 Nov 2024 at 09:12, Jordan Brown via Discuss < >>> discuss@lists.openscad.org> wrote: >>> >>>> >>>> >>>> > Unfortunately, you cannot raise the cone by _conic + >>>> _chamferHeight. The chamfer must (should?) radiate from the “origin” just >>>> like the ridge and grooves. I believe your code as written takes a constant >>>> chamfer off the teeth, but at the inner radius, that’s too much. >>>> >>>> Indeed, I missed that subtlety. Sorry. Your fix looks right. >>>> _______________________________________________ >>>> OpenSCAD mailing list >>>> To unsubscribe send an email to discuss-leave@lists.openscad.org >>>> >>> _______________________________________________ >>> OpenSCAD mailing list >>> To unsubscribe send an email to discuss-leave@lists.openscad.org >>> >> _______________________________________________ >> OpenSCAD mailing list >> To unsubscribe send an email to discuss-leave@lists.openscad.org >> >
BC
Bob Carlson
Fri, Nov 1, 2024 10:25 PM

IIRC, the best source I found was a paper by a grad student about machining hirth joints. I think it is where I got much of the math for the groove angle and so on. And I think it is what made me more aware of the importantance of the groove and ridge angles. In fact, originally I found it hard to understand why the teeth fit perfectly and what the trick was. Understanding that everything radiates from the origin is critical.

When adding the base to the upper (concave) part, I was really confused for a long time. The problem is that the upper base has to be positioned at the groove of the inner teeth OR the groove of the outer teeth. At low conic, it's the outer teeth. At high conic it’s the inner teeth. I have separate code for the convex and concave parts. I suspect that now that my concave code works, a little more work would allow one set of code to generate either part, by sending in positive and negative conic. So far that is conjecture on my part.

Note, the code I posted a while ago is now way out of date. I’ve changed quite a bit.

  • Bob

On Nov 1, 2024, at 14:33, Caddiy via Discuss discuss@lists.openscad.org wrote:

Adrian Mariano wrote:

I'm not sure what you are suggesting with the "ummm" and the reference to a remarkably short and unhelpful wikipedia entry, that gives absolutely no information on how you might design one, doesn't mention the conical version, doesn't talk about the basic parameters of the joint. Basically useless.

Another remarkably short and unhelpful wikipedia entry:

https://en.wikipedia.org/wiki/Spline_(mechanical)

Doesn’t even mention face splines let alone conical ones!!!


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

IIRC, the best source I found was a paper by a grad student about machining hirth joints. I think it is where I got much of the math for the groove angle and so on. And I think it is what made me more aware of the importantance of the groove and ridge angles. In fact, originally I found it hard to understand why the teeth fit perfectly and what the trick was. Understanding that everything radiates from the origin is critical. When adding the base to the upper (concave) part, I was really confused for a long time. The problem is that the upper base has to be positioned at the groove of the inner teeth OR the groove of the outer teeth. At low conic, it's the outer teeth. At high conic it’s the inner teeth. I have separate code for the convex and concave parts. I suspect that now that my concave code works, a little more work would allow one set of code to generate either part, by sending in positive and negative conic. So far that is conjecture on my part. Note, the code I posted a while ago is now way out of date. I’ve changed quite a bit. - Bob > On Nov 1, 2024, at 14:33, Caddiy via Discuss <discuss@lists.openscad.org> wrote: > > Adrian Mariano wrote: > > I'm not sure what you are suggesting with the "ummm" and the reference to a remarkably short and unhelpful wikipedia entry, that gives absolutely no information on how you might design one, doesn't mention the conical version, doesn't talk about the basic parameters of the joint. Basically useless. > > Another remarkably short and unhelpful wikipedia entry: > > https://en.wikipedia.org/wiki/Spline_(mechanical) > > Doesn’t even mention face splines let alone conical ones!!! > > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org
BC
Bob Carlson
Fri, Nov 1, 2024 10:35 PM

Of course it's almost axiomatic that a rounded groove chamfer would be stronger. I was starting to write that I had no idea how to do it with reasonable understandable code. However, I did think of something. Not exactly cheap in “computes”, but maybe OK. Maybe I’ll look into it, but I am also feeling the need to move onlo other projects. So, …

There are lots of other face splines, a hirth is just one kind.

-Bob

On Oct 31, 2024, at 16:39, Adrian Mariano avm4@cornell.edu wrote:

There is a question that I've noted before about what is meant by "tooth angle".  The wikipedia page suggests that it is measured relative to the cylinder axis.  In gears tooth angle is measured relative to the ridge of the tooth.  These two ideas produce a different result, and the steeper the cone angle gets the bigger the difference.  Arguably it doesn't matter if you're just trying to make parts that mate with each other as opposed to mating with some manufactured standard part.  (You can change your tooth angle if you don't like what happened when you specified a steep cone.)  Your method of using spherical coordinates is just a way of projecting (scaling) a triangle.  The results should be the same.  (I did want to confirm that.)  There is another question about what you consider the "zero" conical angle.  I initially did it so that the base of the teeth was at zero angle, but later thought this wasn't right: it should be the angle that produces a part that mates with itself, which should occur if the line through the center of the teeth is at angle zero.  At least, I think that's right.

Note: it may not matter  in practice, but a rounded valley is STRONGER than a chamfer.  Corners concentrate forces and are the places where parts fail.  If the part is small printing will limit this, but what if someone prints an 8" diameter part with 6 teeth?  There is nothing weird about this joint that should limit the number of teeth to be more than 12.  It should work with 3 teeth.  One might in fact want an 8 tooth version to provide part alignment at 45 degree detents, so a 12 limit is...welll...limiting.

If you're machining a tooth you're surely going to have a constant roundover at the bottom, not one that varies with tooth size.  At the top I suppose other things are possible, but it does seem like the natural way to machine it would also be with a constant with chamfer, not one that varies with tooth size.  I didn't do it that way in my code for two reasons:  (1) I was trying to match Bob's code and (2) the varying width chamfer was much simpler to implement.  Of course, we aren't machining and we don't have to limit ourselves to things that are easy to machine.

It can be a nuisance as a library author to have to write code that works on the old version.  That's definitely the case.  Seeking efficiency in general for library code is also a good goal, though.  When someone makes a model with 45 hirth joints what happens?  I wonder if it's better to call this "hirth" or "face_spline".

I see you just posted your code while I was typing so I'll take a look and see if I can compare to mine.

On Thu, Oct 31, 2024 at 7:13 PM Bob Carlson <bob@rjcarlson.com mailto:bob@rjcarlson.com> wrote:

I had the same experience. I found no mention of conical joints. But since my one and only real world example is conical, I know they exist and are used. Someone said early on that hirths are not standardized so maybe it’s not surprising that online sources are incomplete. An interesting problem is that if you have a conical hirth part and need to measure it to determine what the “conic” argument should be I have not figured out any way to do that precisely! The ridge angle is easily measured but a “hirth calculator” would be needed to go from ridge angle to conic.

As I worked with the code over the last month or so, I grew to mistrust the idea of a flat profile being projected away from the origin. I used that idea originally. But he more I thought about the situation at the outer radius, the more I suspected that my powers of visualization were not adequate. The tooth at the outer radius is the intersection of the tooth with a cylinder. In a flat joint that doesn’t seem too terrible, but then move the origin make a conical joint and it really gets hard to keep in my mind. Maybe that all doesn’t matter, but I wasn’t confident it didn't.

Much of the material I found about hirth joints was about how to machine them. It was clear that the groove angle was the critical number, because the groove is the path the cutter follows. I realized that I could trust the groove and ridge angles. Using spherical coordinates it was easy to create a tooth and easy to see why it worked correctly. Someone used to working with trig could probably come up with the angles for chamfer shoulders, but not me.

I may spend some more time understanding your method, but right now I’m concentrating on some other things.

  • Bob

On Oct 31, 2024, at 13:39, Adrian Mariano <avm4@cornell.edu mailto:avm4@cornell.edu> wrote:

I looked up Hirth joints online and found no indication at all that a conical hirth joint exists.  No pictures.  Nobody selling them.  Nobody describing them.  So that did make me wonder what the advantage is.  Is it in fact easier to connect conical joints?  The joint is said to self-center normally and it could be made so the parts are identical, which is a simplification compared to a conical design where you need two different parts.

Personally I think the simplest way to chamfer the teeth of this joint is as in the code I posted: in 2d on the profile.  No cone required.

On Thu, Oct 31, 2024 at 4:27 PM Bob Carlson via Discuss <discuss@lists.openscad.org mailto:discuss@lists.openscad.org> wrote:

I have encountered exactly one hirth spline IRL and it was conical. I made some attachments for my golf cart (carries just my bag). The spot where options are attached has a hirth spline to prevent rotation of the things attached. It is conical, 60 teeth and 35 mm in D. I made a matching part without understanding anything about the hirth spline or knowing the name.

It seems obvious that the cone shape makes it easier to center the parts by hand as you put new attachments on.

  • Bob

On Oct 31, 2024, at 12:36, Caddiy via Discuss <discuss@lists.openscad.org mailto:discuss@lists.openscad.org> wrote:

Jordan Brown wrote:

To cut a long story short, a polygon can give you the filler-cone plus a bit more in one piece, which a primitive cone can’t.

Sort of.  It depends on what your requirements are for the "plus a bit more".

If your cone is anchored at the top, scaling it up will expand it at the base without changing the shape of the top.

This is easy to demonstrate with BOSL2, because you can natively anchor at the top:

include <BOSL2/std.scad>

s = 1;
scale(s) zcyl(r1=10, r2=0, h=10, anchor=TOP);
as you change s, observe that the top portion of the cone stays the same.

It's a tiny bit more complex in base OpenSCAD because base OpenSCAD cylinders are anchored at their bottoms or centers.

s = 1;
h = 10;
scale(s) translate([0,0,-h]) cylinder(r1=10, r2=0, h=h);
(Though you can demonstrate it with an upside-down cone without needing a translate().)

It even retains the same number of sides as it grows, because cylinder() decides on the number of sides when it creates the object, and scale() doesn't affect that choice.

In the particular case that this came from, the user was already using BOSL2, and it happened that the top of the cone was easy to know, and that since it was cutting away past the bottom of the object the shape of the "extra" didn't matter.  Net, that negative object could be a straightforward cone anchored at its top.

A conical face spline joint will need two different cones as fillers to get a flat face at the back of each piece. One piece, with luck or by design, may already have a flat face, or it may even be conical, requiring a negative/hollow cone, that I’m calling an anticone, to get a flat face. But neither a primitive cone nor a BOSL2 cone can handle a negative “h”.

A polygon can. (The polygon is then rotate-extruded to form the desired anticone.)

I wonder, though, how many Hirth joints are conical and why. A conical joint seems like an unnecessary complication, as a plain joint already self-centres very precisely.


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org mailto:discuss-leave@lists.openscad.org


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org mailto:discuss-leave@lists.openscad.org

Of course it's almost axiomatic that a rounded groove chamfer would be stronger. I was starting to write that I had no idea how to do it with reasonable understandable code. However, I did think of something. Not exactly cheap in “computes”, but maybe OK. Maybe I’ll look into it, but I am also feeling the need to move onlo other projects. So, … There are lots of other face splines, a hirth is just one kind. -Bob > On Oct 31, 2024, at 16:39, Adrian Mariano <avm4@cornell.edu> wrote: > > There is a question that I've noted before about what is meant by "tooth angle". The wikipedia page suggests that it is measured relative to the cylinder axis. In gears tooth angle is measured relative to the ridge of the tooth. These two ideas produce a different result, and the steeper the cone angle gets the bigger the difference. Arguably it doesn't matter if you're just trying to make parts that mate with each other as opposed to mating with some manufactured standard part. (You can change your tooth angle if you don't like what happened when you specified a steep cone.) Your method of using spherical coordinates is just a way of projecting (scaling) a triangle. The results should be the same. (I did want to confirm that.) There is another question about what you consider the "zero" conical angle. I initially did it so that the base of the teeth was at zero angle, but later thought this wasn't right: it should be the angle that produces a part that mates with itself, which should occur if the line through the center of the teeth is at angle zero. At least, I think that's right. > > Note: it may not matter in practice, but a rounded valley is STRONGER than a chamfer. Corners concentrate forces and are the places where parts fail. If the part is small printing will limit this, but what if someone prints an 8" diameter part with 6 teeth? There is nothing weird about this joint that should limit the number of teeth to be more than 12. It should work with 3 teeth. One might in fact want an 8 tooth version to provide part alignment at 45 degree detents, so a 12 limit is...welll...limiting. > > If you're machining a tooth you're surely going to have a constant roundover at the bottom, not one that varies with tooth size. At the top I suppose other things are possible, but it does seem like the natural way to machine it would also be with a constant with chamfer, not one that varies with tooth size. I didn't do it that way in my code for two reasons: (1) I was trying to match Bob's code and (2) the varying width chamfer was much simpler to implement. Of course, we aren't machining and we don't have to limit ourselves to things that are easy to machine. > > It can be a nuisance as a library author to have to write code that works on the old version. That's definitely the case. Seeking efficiency in general for library code is also a good goal, though. When someone makes a model with 45 hirth joints what happens? I wonder if it's better to call this "hirth" or "face_spline". > > I see you just posted your code while I was typing so I'll take a look and see if I can compare to mine. > > On Thu, Oct 31, 2024 at 7:13 PM Bob Carlson <bob@rjcarlson.com <mailto:bob@rjcarlson.com>> wrote: >> I had the same experience. I found no mention of conical joints. But since my one and only real world example is conical, I know they exist and are used. Someone said early on that hirths are not standardized so maybe it’s not surprising that online sources are incomplete. An interesting problem is that if you have a conical hirth part and need to measure it to determine what the “conic” argument should be I have not figured out any way to do that precisely! The ridge angle is easily measured but a “hirth calculator” would be needed to go from ridge angle to conic. >> >> As I worked with the code over the last month or so, I grew to mistrust the idea of a flat profile being projected away from the origin. I used that idea originally. But he more I thought about the situation at the outer radius, the more I suspected that my powers of visualization were not adequate. The tooth at the outer radius is the intersection of the tooth with a cylinder. In a flat joint that doesn’t seem too terrible, but then move the origin make a conical joint and it really gets hard to keep in my mind. Maybe that all doesn’t matter, but I wasn’t confident it didn't. >> >> Much of the material I found about hirth joints was about how to machine them. It was clear that the groove angle was the critical number, because the groove is the path the cutter follows. I realized that I could trust the groove and ridge angles. Using spherical coordinates it was easy to create a tooth and easy to see why it worked correctly. Someone used to working with trig could probably come up with the angles for chamfer shoulders, but not me. >> >> I may spend some more time understanding your method, but right now I’m concentrating on some other things. >> >> - Bob >> >>> On Oct 31, 2024, at 13:39, Adrian Mariano <avm4@cornell.edu <mailto:avm4@cornell.edu>> wrote: >>> >>> I looked up Hirth joints online and found no indication at all that a conical hirth joint exists. No pictures. Nobody selling them. Nobody describing them. So that did make me wonder what the advantage is. Is it in fact easier to connect conical joints? The joint is said to self-center normally and it could be made so the parts are identical, which is a simplification compared to a conical design where you need two different parts. >>> >>> Personally I think the simplest way to chamfer the teeth of this joint is as in the code I posted: in 2d on the profile. No cone required. >>> >>> >>> On Thu, Oct 31, 2024 at 4:27 PM Bob Carlson via Discuss <discuss@lists.openscad.org <mailto:discuss@lists.openscad.org>> wrote: >>>> I have encountered exactly one hirth spline IRL and it was conical. I made some attachments for my golf cart (carries just my bag). The spot where options are attached has a hirth spline to prevent rotation of the things attached. It is conical, 60 teeth and 35 mm in D. I made a matching part without understanding anything about the hirth spline or knowing the name. >>>> >>>> It seems obvious that the cone shape makes it easier to center the parts by hand as you put new attachments on. >>>> >>>> - Bob >>>> >>>>> On Oct 31, 2024, at 12:36, Caddiy via Discuss <discuss@lists.openscad.org <mailto:discuss@lists.openscad.org>> wrote: >>>>> >>>>> Jordan Brown wrote: >>>>> >>>>> To cut a long story short, a polygon can give you the filler-cone plus a bit more in one piece, which a primitive cone can’t. >>>>> >>>>> Sort of. It depends on what your requirements are for the "plus a bit more". >>>>> >>>>> If your cone is anchored at the top, scaling it up will expand it at the base without changing the shape of the top. >>>>> >>>>> This is easy to demonstrate with BOSL2, because you can natively anchor at the top: >>>>> >>>>> include <BOSL2/std.scad> >>>>> >>>>> s = 1; >>>>> scale(s) zcyl(r1=10, r2=0, h=10, anchor=TOP); >>>>> as you change s, observe that the top portion of the cone stays the same. >>>>> >>>>> It's a tiny bit more complex in base OpenSCAD because base OpenSCAD cylinders are anchored at their bottoms or centers. >>>>> >>>>> s = 1; >>>>> h = 10; >>>>> scale(s) translate([0,0,-h]) cylinder(r1=10, r2=0, h=h); >>>>> (Though you can demonstrate it with an upside-down cone without needing a translate().) >>>>> >>>>> It even retains the same number of sides as it grows, because cylinder() decides on the number of sides when it creates the object, and scale() doesn't affect that choice. >>>>> >>>>> In the particular case that this came from, the user was already using BOSL2, and it happened that the top of the cone was easy to know, and that since it was cutting away past the bottom of the object the shape of the "extra" didn't matter. Net, that negative object could be a straightforward cone anchored at its top. >>>>> >>>>> A conical face spline joint will need two different cones as fillers to get a flat face at the back of each piece. One piece, with luck or by design, may already have a flat face, or it may even be conical, requiring a negative/hollow cone, that I’m calling an anticone, to get a flat face. But neither a primitive cone nor a BOSL2 cone can handle a negative “h”. >>>>> >>>>> A polygon can. (The polygon is then rotate-extruded to form the desired anticone.) >>>>> >>>>> I wonder, though, how many Hirth joints are conical and why. A conical joint seems like an unnecessary complication, as a plain joint already self-centres very precisely. >>>>> >>>>> _______________________________________________ >>>>> OpenSCAD mailing list >>>>> To unsubscribe send an email to discuss-leave@lists.openscad.org <mailto:discuss-leave@lists.openscad.org> >>>> _______________________________________________ >>>> OpenSCAD mailing list >>>> To unsubscribe send an email to discuss-leave@lists.openscad.org <mailto:discuss-leave@lists.openscad.org> >>
AM
Adrian Mariano
Fri, Nov 1, 2024 10:44 PM

No, I did not say Hirth joints don't exist.  Specifically I said:  "I
looked up Hirth joints online and found no indication at all that a
conical hirth joint exists" [emphasis added].  And the wikipedia page
sure doesn't mention such a beast.  In terms of what would be nice to
have?  That would be a document with clear pictures (not those
incomprehensible patent diagrams) that lays out what the parameters of the
thing is (like how is the tooth angle defined?) and geometrically how it is
formed.  After struggling with my implementation's failures I think I know
a way to form the thing that is more direct than Bob's approach, but not
sure if I can generalize it neatly to the conical case without introducing
lots of complexity...and the point of my approach was supposed to be
simplicity.

Bob, what other kinds of face splines exist?  That is, how are they
different?

On Fri, Nov 1, 2024 at 5:54 PM John David ebo.2112@gmail.com wrote:

Sorry Adrian.  Your post basically said there was no such thing, and was
also terse on details on what you wanted.  So, they are on the net with a
slight change of spelling.  That was the entire reason for my post.

If you want me to explain how to make them in a tool-and-die shop, or how
modeling a machine-tool path as a diff operator will give you the same
thing, I can go over that.  I'll be backing up to travel tonight, so if you
want me to code that up it will be next week sometime at the earliest.

EBo --

On Fri, Nov 1, 2024 at 4:20 PM Adrian Mariano avm4@cornell.edu wrote:

I'm not sure what you are suggesting with the "ummm" and the reference to
a remarkably short and unhelpful wikipedia entry, that gives absolutely no
information on how you might design one, doesn't mention the conical
version, doesn't talk about the basic parameters of the joint.  Basically
useless.

In ongoing fiddling with my code I've found that this is remarkably
tricky to get right.  My version looked OK with lots of teeth but at low
teeth count, the errors became apparent.  Bob's version works even at low
teeth count, at least in terms of producing a proper mesh between the
parts.

On Fri, Nov 1, 2024 at 2:59 PM John David via Discuss <
discuss@lists.openscad.org> wrote:

Ummmm... Hirth Joint https://en.wikipedia.org/wiki/Hirth_joint  That
said, maybe because you used "joints" threw it as they are singular.  Hope
this helps.

On Fri, Nov 1, 2024 at 12:20 AM Sanjeev Prabhakar via Discuss <
discuss@lists.openscad.org> wrote:

There was a little issue in the previous code i sent:
here is the corrected one:

from openscad2 import *

hirth coupling

n=20 # number of teeths
ta=60 # teeth angle
ca=10 # for straight 360/42.232 # cone angle
i_r=30 # inner radius
o_r=100 # outer radius
ch=.5 # chamfer height
l1=[[i_r,0],[o_r,0]]
l2=[ q_rot([f'z{i}'],l1)  for i in linspace(0,360,n+1)[:-1]]

l3=axis_rot_1(l1,ax1=[0,1,0],loc1=[o_r,0],theta=ca)
l3= line2length(flip(line2length(l3,(o_r-i_r)+5)),(o_r-i_r)+10)
cone1=[ q_rot([f'z{i}'],l3) for i in linspace(0,360,n)]
l2=psos(cone1,l2,[0,0,1])
l1=[l2[0][0],l2[1][0]]
d1=l_len(l1)/2/cos(d2r(ta))
l1=axis_rot_1(l1,line_as_axis(l2[0]),l2[0][0],ta)
l1=line2length(l1,d1)
l3=[l2[0][1],l2[1][1]]
d2=l_len(l3)/2/cos(d2r(ta))
l3=axis_rot_1(l3,line_as_axis(l2[0]),l2[0][1],ta)
l3=line2length(l3,d2)
l4=[l1[1],l3[1]]

a,b=l4

l4=line2length(flip(line2length(l4,(o_r-i_r)+5)),(o_r-i_r)+10)
cone2=[ q_rot([f'z{i}'],l4) for i in linspace(0,360,n)]
l3=psos(cone2,l2,[0,0,1])
l3=q_rot([f'z{360/n/2}'],l3)
s1=l_(a_([l2,l3]).transpose(1,0,2,3).reshape(n*2,2,3))
s1=s1+[s1[0]]
s1=l_(a_(s1).transpose(1,0,2))
sol1=flip(surf_base(s1,s1[0][1][2]+10))
s2=l_(a_(cone1).transpose(1,0,2))
s2=surface_offset(s2,-ch)
sol2=surf_base(s2,s1[1][0][2]-10)
sol2=sol2+[sol2[0]]
sol3=surf_base(flip(s1),s1[1][0][2]-10)
s3=q_rot(['z5'],l_(a_(cone2[:-1]).transpose(1,0,2)))
s3=surface_offset(s3,ch)
sol4=surf_base(s3,s1[0][1][2]+10)
sol4=sol4+[sol4[0]]
with open('trial.scad','w+') as f:
f.write(f'''

 translate([0,0,25])
// color([.13,.81,.37])
 difference(){{
 {swp_c(sol1)}
 {swp_c(sol2)}
 }}

difference(){{
{swp_c(sol3)}
{swp_c(sol4)}
}}

 ''')

On Fri, 1 Nov 2024 at 09:12, Jordan Brown via Discuss <
discuss@lists.openscad.org> wrote:

Unfortunately, you cannot raise the cone by _conic  +

_chamferHeight. The chamfer must (should?) radiate from the “origin” just
like the ridge and grooves. I believe your code as written takes a constant
chamfer off the teeth, but at the inner radius, that’s too much.

Indeed, I missed that subtlety. Sorry.  Your fix looks right.


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

No, I did not say Hirth joints don't exist. Specifically I said: "I looked up Hirth joints online and found no indication at all that a *conical* hirth joint exists" [emphasis added]. And the wikipedia page sure doesn't mention such a beast. In terms of what would be nice to have? That would be a document with clear pictures (not those incomprehensible patent diagrams) that lays out what the parameters of the thing is (like how is the tooth angle defined?) and geometrically how it is formed. After struggling with my implementation's failures I think I know a way to form the thing that is more direct than Bob's approach, but not sure if I can generalize it neatly to the conical case without introducing lots of complexity...and the point of my approach was supposed to be simplicity. Bob, what other kinds of face splines exist? That is, how are they different? On Fri, Nov 1, 2024 at 5:54 PM John David <ebo.2112@gmail.com> wrote: > Sorry Adrian. Your post basically said there was no such thing, and was > also terse on details on what you wanted. So, they are on the net with a > slight change of spelling. That was the entire reason for my post. > > If you want me to explain how to make them in a tool-and-die shop, or how > modeling a machine-tool path as a diff operator will give you the same > thing, I can go over that. I'll be backing up to travel tonight, so if you > want me to code that up it will be next week sometime at the earliest. > > EBo -- > > On Fri, Nov 1, 2024 at 4:20 PM Adrian Mariano <avm4@cornell.edu> wrote: > >> I'm not sure what you are suggesting with the "ummm" and the reference to >> a remarkably short and unhelpful wikipedia entry, that gives absolutely no >> information on how you might design one, doesn't mention the conical >> version, doesn't talk about the basic parameters of the joint. Basically >> useless. >> >> In ongoing fiddling with my code I've found that this is remarkably >> tricky to get right. My version looked OK with lots of teeth but at low >> teeth count, the errors became apparent. Bob's version works even at low >> teeth count, at least in terms of producing a proper mesh between the >> parts. >> >> On Fri, Nov 1, 2024 at 2:59 PM John David via Discuss < >> discuss@lists.openscad.org> wrote: >> >>> Ummmm... Hirth Joint <https://en.wikipedia.org/wiki/Hirth_joint> That >>> said, maybe because you used "joints" threw it as they are singular. Hope >>> this helps. >>> >>> On Fri, Nov 1, 2024 at 12:20 AM Sanjeev Prabhakar via Discuss < >>> discuss@lists.openscad.org> wrote: >>> >>>> There was a little issue in the previous code i sent: >>>> here is the corrected one: >>>> >>>> from openscad2 import * >>>> >>>> # hirth coupling >>>> n=20 # number of teeths >>>> ta=60 # teeth angle >>>> ca=10 # for straight 360/42.232 # cone angle >>>> i_r=30 # inner radius >>>> o_r=100 # outer radius >>>> ch=.5 # chamfer height >>>> l1=[[i_r,0],[o_r,0]] >>>> l2=[ q_rot([f'z{i}'],l1) for i in linspace(0,360,n+1)[:-1]] >>>> >>>> l3=axis_rot_1(l1,ax1=[0,1,0],loc1=[o_r,0],theta=ca) >>>> l3= line2length(flip(line2length(l3,(o_r-i_r)+5)),(o_r-i_r)+10) >>>> cone1=[ q_rot([f'z{i}'],l3) for i in linspace(0,360,n)] >>>> l2=psos(cone1,l2,[0,0,1]) >>>> l1=[l2[0][0],l2[1][0]] >>>> d1=l_len(l1)/2/cos(d2r(ta)) >>>> l1=axis_rot_1(l1,line_as_axis(l2[0]),l2[0][0],ta) >>>> l1=line2length(l1,d1) >>>> l3=[l2[0][1],l2[1][1]] >>>> d2=l_len(l3)/2/cos(d2r(ta)) >>>> l3=axis_rot_1(l3,line_as_axis(l2[0]),l2[0][1],ta) >>>> l3=line2length(l3,d2) >>>> l4=[l1[1],l3[1]] >>>> # a,b=l4 >>>> l4=line2length(flip(line2length(l4,(o_r-i_r)+5)),(o_r-i_r)+10) >>>> cone2=[ q_rot([f'z{i}'],l4) for i in linspace(0,360,n)] >>>> l3=psos(cone2,l2,[0,0,1]) >>>> l3=q_rot([f'z{360/n/2}'],l3) >>>> s1=l_(a_([l2,l3]).transpose(1,0,2,3).reshape(n*2,2,3)) >>>> s1=s1+[s1[0]] >>>> s1=l_(a_(s1).transpose(1,0,2)) >>>> sol1=flip(surf_base(s1,s1[0][1][2]+10)) >>>> s2=l_(a_(cone1).transpose(1,0,2)) >>>> s2=surface_offset(s2,-ch) >>>> sol2=surf_base(s2,s1[1][0][2]-10) >>>> sol2=sol2+[sol2[0]] >>>> sol3=surf_base(flip(s1),s1[1][0][2]-10) >>>> s3=q_rot(['z5'],l_(a_(cone2[:-1]).transpose(1,0,2))) >>>> s3=surface_offset(s3,ch) >>>> sol4=surf_base(s3,s1[0][1][2]+10) >>>> sol4=sol4+[sol4[0]] >>>> with open('trial.scad','w+') as f: >>>> f.write(f''' >>>> >>>> translate([0,0,25]) >>>> // color([.13,.81,.37]) >>>> difference(){{ >>>> {swp_c(sol1)} >>>> {swp_c(sol2)} >>>> }} >>>> difference(){{ >>>> {swp_c(sol3)} >>>> {swp_c(sol4)} >>>> }} >>>> >>>> ''') >>>> >>>> On Fri, 1 Nov 2024 at 09:12, Jordan Brown via Discuss < >>>> discuss@lists.openscad.org> wrote: >>>> >>>>> >>>>> >>>>> > Unfortunately, you cannot raise the cone by _conic + >>>>> _chamferHeight. The chamfer must (should?) radiate from the “origin” just >>>>> like the ridge and grooves. I believe your code as written takes a constant >>>>> chamfer off the teeth, but at the inner radius, that’s too much. >>>>> >>>>> Indeed, I missed that subtlety. Sorry. Your fix looks right. >>>>> _______________________________________________ >>>>> OpenSCAD mailing list >>>>> To unsubscribe send an email to discuss-leave@lists.openscad.org >>>>> >>>> _______________________________________________ >>>> OpenSCAD mailing list >>>> To unsubscribe send an email to discuss-leave@lists.openscad.org >>>> >>> _______________________________________________ >>> OpenSCAD mailing list >>> To unsubscribe send an email to discuss-leave@lists.openscad.org >>> >>