discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

Bug in my code or OpenSCAD?

BC
Bob Carlson
Fri, Oct 25, 2024 11:44 PM

I got really intrigued by the Hirth joint and have been working a library entry that would generate them. I have it fully working, apparently, because it renders perfectly as far as I can see. However when I load one of the parts (a concave part) into PrusaSlicer, it reports thousands of errors that it supposedly fixed. The visual rendering is fine, but when you look at the slice it is completely screwed up.

First some explanation. When I looked up hirth joints I only saw flat ones mentioned. The one I have actually encountered though is a conical one. There is a concave part and a convex part. They fit together perfectly. I had to invent some terminology since I did not find terms for some things I found to be important. The outer center line is the plane that passes through the midpoint of the teeth at the outer radius. In a flat hirth joint all the teeth radiate from the center of this circle, call it the origin. If the origin of the teeth is above the outer center line, then joint has a conical shape and the two parts are concave and convex.

Each tooth at every point has the same profile, the top of the tooth profile is either 60 or 90 degrees. The groove angle is the angle that the groove forms from the origin to the outer radius. It will pass below (for a convex part) the outer radius. It’s critical for making hirth joints because it forms the tool path. The ridge angle is the angle formed by the corresponding ridge.

If the joint is conical, then there is an inner center line that passes through the center of the teeth at the inner radius. The tooth height is the critical number to calculate. It is dependent on the number of teeth, the profile angle and the inner and out radii. Something that really complicates the mental gymnastics is that the tooth height is smaller at the inner radius. My code adds a “base” of extra material at the bottom of the convex part and the top of the concave part. What’s tricky is positioning the base of the concave part relative to the inner center line. The concave parts base is relatively easy to place because it depends on the outer radius and center line.

I generate the raw teeth using the groove and ridge angles and spherical coordinates to make two 2d tooth profiles. Then I complete a tooth using skin(). A for loop generates the full set of N teeth. Then intersection or difference is used the trim the teeth at the inner and outer radii. I discovered something at that point, but solved it pretty simply. When diffing a cylinder from the N teeth, each tooth took up a small portion of the cylinder being diffed out. I had to raise the $fn on the cylinder or tube being used so that I got enough points in each tooth that diff or intersection was accurate. I kept raising it until the results stopped improving. I ended up with the 16*360 you see in the code.

After I have the raw teeth, I generate a cone that is diffed away to produce the chamfer at the top of the teeth. Then I add in the base. The base also adds the “chamfer” at the bottom of the groove. It’s half the size of the top chamfer to leave a little gap when the parts are joined.

When I comment out the everything but the raw teeth and import the STL into PrusaSlicer, it reports errors fixed, but appears to slice correctly when supports are added.

When I add the intersection to trim the raw teeth, the number of reported errors goes way up.

When I add the diff to remove the chamfer, the number goes way up again.

When I add in the base, the number goes up again and it starts reporting many open edges.

Throughout, OpenSCAD reports no errors. Using $fn at 16360, manifold renders in 4+ seconds. At 32360, it’s 53+ seconds. I did check CSG and it did not help.

Maybe the biggest hint is that the convex part uses almost identical code, but produces no errors. Very weird.

So, is this an OpenSCAD problem? Or something in my code?

It’s also possible that my math is off somewhere. My formal trig training was 60 years ago. However I doubt a math error is responsible for the slicing problem and STL errors.

-Bob

include <BOSL2/std.scad>
include <BOSL2/structs.scad>

// Number of Teeth
_n = 36;          // Number Of Teeth

// Inner Radius
_ir = 30;
// Outer Radius
_or = 50;
// Is the coupling conical?
_conic = 10;
// Tooth Profile Angle
_profile = 60; // [60, 90]
// Percentage of tooth height
_chamfer = 5; // Default 5%
_base = 1;

$fn = 180;
tiny = 1 / 1024;

hirth_concave();

_irRatio = _ir / _or;
_toothAngle = 360/_n;
_toothHeight = (sin(_toothAngle/2) * _or) / tan(_profile/2);
_chamferHeight = _chamfer * _toothHeight / 100;
_grooveAngle =  atan(((_toothHeight/2) + _conic) / _or);
_ridgeAngle = -atan(((_toothHeight/2) - _conic) / _or);
_innerCenterLine = (1 - _irRatio) * _conic;
_stackHeight  = _innerCenterLine + _toothHeight + 2*_base;
_tubeHeight = 2*_conic + 2*_base + 2*_toothHeight;

module hirth_concave() {
zrot(_toothAngle/2)
union() {
difference() {
intersection() {
union() {
for (i = [0 : 360/_n : 359])
zrot(i)
_profileF();
}
tube(ir = _ir, or = _or, anchor = CENTER, l = _tubeHeight, orient = UP, $fn = 16360);
}
_chamferF();
zcyl(r = _ir, h = _tubeHeight, $fn = 16
360, anchor = CENTER);
}
_baseF();
}
} // hirth_concave

module _profileF() {
IR = _ir * .5;
OR = _or * 1.5;
tI = [spherical_to_xyz(IR,  0,            _grooveAngle + 90),
spherical_to_xyz(IR,  _toothAngle/2, _ridgeAngle + 90),
spherical_to_xyz(IR, -_toothAngle/2, _ridgeAngle + 90)];

tO = [spherical_to_xyz(OR,   0,            _grooveAngle + 90),
      spherical_to_xyz(OR,  _toothAngle/2, _ridgeAngle + 90),
      spherical_to_xyz(OR, -_toothAngle/2, _ridgeAngle + 90)];
up(_conic)
skin([tI, tO], slices = 0);

}

module _chamferF() {
A = -_toothHeight/2 - .1;
B = -_toothHeight/2 + _chamferHeight;

pts = [[0, _conic], 
       [_or+tiny, A], 
       [_or+tiny, B]];

rotate_extrude(angle = 360, $fn = 16*360)
polygon(pts);

}

module _baseF() {
A = _base + _irRatio*_toothHeight/2 + _innerCenterLine;
B = _irRatio * (_toothHeight/2 - _chamferHeight/2) + _innerCenterLine;
C = _toothHeight/2 - _chamferHeight/2;
pts = [
[_ir, A],
[_ir, B],
[_or, C],
[_or, A]
];

rotate_extrude(angle = 360, $fn = 360*16)
polygon(pts);

}

I got really intrigued by the Hirth joint and have been working a library entry that would generate them. I have it fully working, apparently, because it renders perfectly as far as I can see. However when I load one of the parts (a concave part) into PrusaSlicer, it reports thousands of errors that it supposedly fixed. The visual rendering is fine, but when you look at the slice it is completely screwed up. First some explanation. When I looked up hirth joints I only saw flat ones mentioned. The one I have actually encountered though is a conical one. There is a concave part and a convex part. They fit together perfectly. I had to invent some terminology since I did not find terms for some things I found to be important. The outer center line is the plane that passes through the midpoint of the teeth at the outer radius. In a flat hirth joint all the teeth radiate from the center of this circle, call it the origin. If the origin of the teeth is above the outer center line, then joint has a conical shape and the two parts are concave and convex. Each tooth at every point has the same profile, the top of the tooth profile is either 60 or 90 degrees. The groove angle is the angle that the groove forms from the origin to the outer radius. It will pass below (for a convex part) the outer radius. It’s critical for making hirth joints because it forms the tool path. The ridge angle is the angle formed by the corresponding ridge. If the joint is conical, then there is an inner center line that passes through the center of the teeth at the inner radius. The tooth height is the critical number to calculate. It is dependent on the number of teeth, the profile angle and the inner and out radii. Something that really complicates the mental gymnastics is that the tooth height is smaller at the inner radius. My code adds a “base” of extra material at the bottom of the convex part and the top of the concave part. What’s tricky is positioning the base of the concave part relative to the inner center line. The concave parts base is relatively easy to place because it depends on the outer radius and center line. I generate the raw teeth using the groove and ridge angles and spherical coordinates to make two 2d tooth profiles. Then I complete a tooth using skin(). A for loop generates the full set of N teeth. Then intersection or difference is used the trim the teeth at the inner and outer radii. I discovered something at that point, but solved it pretty simply. When diffing a cylinder from the N teeth, each tooth took up a small portion of the cylinder being diffed out. I had to raise the $fn on the cylinder or tube being used so that I got enough points in each tooth that diff or intersection was accurate. I kept raising it until the results stopped improving. I ended up with the 16*360 you see in the code. After I have the raw teeth, I generate a cone that is diffed away to produce the chamfer at the top of the teeth. Then I add in the base. The base also adds the “chamfer” at the bottom of the groove. It’s half the size of the top chamfer to leave a little gap when the parts are joined. When I comment out the everything but the raw teeth and import the STL into PrusaSlicer, it reports errors fixed, but appears to slice correctly when supports are added. When I add the intersection to trim the raw teeth, the number of reported errors goes way up. When I add the diff to remove the chamfer, the number goes way up again. When I add in the base, the number goes up again and it starts reporting many open edges. Throughout, OpenSCAD reports no errors. Using $fn at 16*360, manifold renders in 4+ seconds. At 32*360, it’s 53+ seconds. I did check CSG and it did not help. Maybe the biggest hint is that the convex part uses almost identical code, but produces no errors. Very weird. So, is this an OpenSCAD problem? Or something in my code? It’s also possible that my math is off somewhere. My formal trig training was 60 years ago. However I doubt a math error is responsible for the slicing problem and STL errors. -Bob include <BOSL2/std.scad> include <BOSL2/structs.scad> // Number of Teeth _n = 36; // Number Of Teeth // Inner Radius _ir = 30; // Outer Radius _or = 50; // Is the coupling conical? _conic = 10; // Tooth Profile Angle _profile = 60; // [60, 90] // Percentage of tooth height _chamfer = 5; // Default 5% _base = 1; $fn = 180; tiny = 1 / 1024; hirth_concave(); _irRatio = _ir / _or; _toothAngle = 360/_n; _toothHeight = (sin(_toothAngle/2) * _or) / tan(_profile/2); _chamferHeight = _chamfer * _toothHeight / 100; _grooveAngle = atan(((_toothHeight/2) + _conic) / _or); _ridgeAngle = -atan(((_toothHeight/2) - _conic) / _or); _innerCenterLine = (1 - _irRatio) * _conic; _stackHeight = _innerCenterLine + _toothHeight + 2*_base; _tubeHeight = 2*_conic + 2*_base + 2*_toothHeight; module hirth_concave() { zrot(_toothAngle/2) union() { difference() { intersection() { union() { for (i = [0 : 360/_n : 359]) zrot(i) _profileF(); } tube(ir = _ir, or = _or, anchor = CENTER, l = _tubeHeight, orient = UP, $fn = 16*360); } _chamferF(); zcyl(r = _ir, h = _tubeHeight, $fn = 16*360, anchor = CENTER); } _baseF(); } } // hirth_concave module _profileF() { IR = _ir * .5; OR = _or * 1.5; tI = [spherical_to_xyz(IR, 0, _grooveAngle + 90), spherical_to_xyz(IR, _toothAngle/2, _ridgeAngle + 90), spherical_to_xyz(IR, -_toothAngle/2, _ridgeAngle + 90)]; tO = [spherical_to_xyz(OR, 0, _grooveAngle + 90), spherical_to_xyz(OR, _toothAngle/2, _ridgeAngle + 90), spherical_to_xyz(OR, -_toothAngle/2, _ridgeAngle + 90)]; up(_conic) skin([tI, tO], slices = 0); } module _chamferF() { A = -_toothHeight/2 - .1; B = -_toothHeight/2 + _chamferHeight; pts = [[0, _conic], [_or+tiny, A], [_or+tiny, B]]; rotate_extrude(angle = 360, $fn = 16*360) polygon(pts); } module _baseF() { A = _base + _irRatio*_toothHeight/2 + _innerCenterLine; B = _irRatio * (_toothHeight/2 - _chamferHeight/2) + _innerCenterLine; C = _toothHeight/2 - _chamferHeight/2; pts = [ [_ir, A], [_ir, B], [_or, C], [_or, A] ]; rotate_extrude(angle = 360, $fn = 360*16) polygon(pts); }
SP
Sanjeev Prabhakar
Sat, Oct 26, 2024 12:04 AM

Can you post a picture of this

I will try this as well in python.

It may not interest you but just want see how tough this is to model

On Sat, 26 Oct, 2024, 5:15 am Bob Carlson via Discuss, <
discuss@lists.openscad.org> wrote:

I got really intrigued by the Hirth joint and have been working a library
entry that would generate them. I have it fully working, apparently,
because it renders perfectly as far as I can see. However when I load one
of the parts (a concave part) into PrusaSlicer, it reports thousands of
errors that it supposedly fixed. The visual rendering is fine, but when you
look at the slice it is completely screwed up.

First some explanation. When I looked up hirth joints I only saw flat ones
mentioned. The one I have actually encountered though is a conical one.
There is a concave part and a convex part. They fit together perfectly. I
had to invent some terminology since I did not find terms for some things I
found to be important. The outer center line is the plane that passes
through the midpoint of the teeth at the outer radius. In a flat hirth
joint all the teeth radiate from the center of this circle, call it the
origin. If the origin of the teeth is above the outer center line, then
joint has a conical shape and the two parts are concave and convex.

Each tooth at every point has the same profile, the top of the tooth
profile is either 60 or 90 degrees. The groove angle is the angle that the
groove forms from the origin to the outer radius. It will pass below (for a
convex part) the outer radius. It’s critical for making hirth joints
because it forms the tool path. The ridge angle is the angle formed by the
corresponding ridge.

If the joint is conical, then there is an inner center line that passes
through the center of the teeth at the inner radius. The tooth height is
the critical number to calculate. It is dependent on the number of teeth,
the profile angle and the inner and out radii. Something that really
complicates the mental gymnastics is that the tooth height is smaller at
the inner radius. My code adds a “base” of extra material at the bottom of
the convex part and the top of the concave part. What’s tricky is
positioning the base of the concave part relative to the inner center line.
The concave parts base is relatively easy to place because it depends on
the outer radius and center line.

I generate the raw teeth using the groove and ridge angles and spherical
coordinates to make two 2d tooth profiles. Then I complete a tooth using
skin(). A for loop generates the full set of N teeth. Then intersection or
difference is used the trim the teeth at the inner and outer radii. I
discovered something at that point, but solved it pretty simply. When
diffing a cylinder from the N teeth, each tooth took up a small portion of
the cylinder being diffed out. I had to raise the $fn on the cylinder or
tube being used so that I got enough points in each tooth that diff or
intersection was accurate. I kept raising it until the results stopped
improving. I ended up with the 16*360 you see in the code.

After I have the raw teeth, I generate a cone that is diffed away to
produce the chamfer at the top of the teeth. Then I add in the base. The
base also adds the “chamfer” at the bottom of the groove. It’s half the
size of the top chamfer to leave a little gap when the parts are joined.

When I comment out the everything but the raw teeth and import the STL
into PrusaSlicer, it reports errors fixed, but appears to slice correctly
when supports are added.

When I add the intersection to trim the raw teeth, the number of reported
errors goes way up.

When I add the diff to remove the chamfer, the number goes way up again.

When I add in the base, the number goes up again and it starts reporting
many open edges.

Throughout, OpenSCAD reports no errors. Using $fn at 16360, manifold
renders in 4+ seconds. At 32
360, it’s 53+ seconds. I did check CSG and it
did not help.

Maybe the biggest hint is that the convex part uses almost identical code,
but produces no errors. Very weird.

So, is this an OpenSCAD problem? Or something in my code?

It’s also possible that my math is off somewhere. My formal trig training
was 60 years ago. However I doubt a math error is responsible for the
slicing problem and STL errors.

-Bob

include <BOSL2/std.scad>
include <BOSL2/structs.scad>

// Number of Teeth
_n = 36;          // Number Of Teeth

// Inner Radius
_ir = 30;
// Outer Radius
_or = 50;
// Is the coupling conical?
_conic = 10;
// Tooth Profile Angle
_profile = 60; // [60, 90]
// Percentage of tooth height
_chamfer = 5; // Default 5%
_base = 1;

$fn = 180;
tiny = 1 / 1024;

hirth_concave();

_irRatio = _ir / _or;
_toothAngle = 360/_n;
_toothHeight = (sin(_toothAngle/2) * _or) / tan(_profile/2);
_chamferHeight = _chamfer * _toothHeight / 100;
_grooveAngle =  atan(((_toothHeight/2) + _conic) / _or);
_ridgeAngle = -atan(((_toothHeight/2) - _conic) / _or);
_innerCenterLine = (1 - _irRatio) * _conic;
_stackHeight  = _innerCenterLine + _toothHeight + 2*_base;
_tubeHeight = 2*_conic + 2*_base + 2*_toothHeight;

module hirth_concave() {
zrot(_toothAngle/2)
union() {
difference() {
intersection() {
union() {
for (i = [0 : 360/_n : 359])
zrot(i)
_profileF();
}
tube(ir = _ir, or = _or, anchor = CENTER, l = _tubeHeight,
orient = UP, $fn = 16360);
}
_chamferF();
zcyl(r = _ir, h = _tubeHeight, $fn = 16
360, anchor = CENTER);
}
_baseF();
}
} // hirth_concave

module _profileF() {
IR = _ir * .5;
OR = _or * 1.5;
tI = [spherical_to_xyz(IR,  0,            _grooveAngle + 90),
spherical_to_xyz(IR,  _toothAngle/2, _ridgeAngle + 90),
spherical_to_xyz(IR, -_toothAngle/2, _ridgeAngle + 90)];

 tO = [spherical_to_xyz(OR,   0,            _grooveAngle + 90),
       spherical_to_xyz(OR,  _toothAngle/2, _ridgeAngle + 90),
       spherical_to_xyz(OR, -_toothAngle/2, _ridgeAngle + 90)];
 up(_conic)
 skin([tI, tO], slices = 0);

}

module _chamferF() {
A = -_toothHeight/2 - .1;
B = -_toothHeight/2 + _chamferHeight;

 pts = [[0, _conic],
        [_or+tiny, A],
        [_or+tiny, B]];

 rotate_extrude(angle = 360, $fn = 16*360)
 polygon(pts);

}

module _baseF() {
A = _base + _irRatio*_toothHeight/2 + _innerCenterLine;
B = _irRatio * (_toothHeight/2 - _chamferHeight/2) + _innerCenterLine;
C = _toothHeight/2 - _chamferHeight/2;
pts = [
[_ir, A],
[_ir, B],
[_or, C],
[_or, A]
];

 rotate_extrude(angle = 360, $fn = 360*16)
 polygon(pts);

}


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

Can you post a picture of this I will try this as well in python. It may not interest you but just want see how tough this is to model On Sat, 26 Oct, 2024, 5:15 am Bob Carlson via Discuss, < discuss@lists.openscad.org> wrote: > I got really intrigued by the Hirth joint and have been working a library > entry that would generate them. I have it fully working, apparently, > because it renders perfectly as far as I can see. However when I load one > of the parts (a concave part) into PrusaSlicer, it reports thousands of > errors that it supposedly fixed. The visual rendering is fine, but when you > look at the slice it is completely screwed up. > > First some explanation. When I looked up hirth joints I only saw flat ones > mentioned. The one I have actually encountered though is a conical one. > There is a concave part and a convex part. They fit together perfectly. I > had to invent some terminology since I did not find terms for some things I > found to be important. The outer center line is the plane that passes > through the midpoint of the teeth at the outer radius. In a flat hirth > joint all the teeth radiate from the center of this circle, call it the > origin. If the origin of the teeth is above the outer center line, then > joint has a conical shape and the two parts are concave and convex. > > Each tooth at every point has the same profile, the top of the tooth > profile is either 60 or 90 degrees. The groove angle is the angle that the > groove forms from the origin to the outer radius. It will pass below (for a > convex part) the outer radius. It’s critical for making hirth joints > because it forms the tool path. The ridge angle is the angle formed by the > corresponding ridge. > > If the joint is conical, then there is an inner center line that passes > through the center of the teeth at the inner radius. The tooth height is > the critical number to calculate. It is dependent on the number of teeth, > the profile angle and the inner and out radii. Something that really > complicates the mental gymnastics is that the tooth height is smaller at > the inner radius. My code adds a “base” of extra material at the bottom of > the convex part and the top of the concave part. What’s tricky is > positioning the base of the concave part relative to the inner center line. > The concave parts base is relatively easy to place because it depends on > the outer radius and center line. > > I generate the raw teeth using the groove and ridge angles and spherical > coordinates to make two 2d tooth profiles. Then I complete a tooth using > skin(). A for loop generates the full set of N teeth. Then intersection or > difference is used the trim the teeth at the inner and outer radii. I > discovered something at that point, but solved it pretty simply. When > diffing a cylinder from the N teeth, each tooth took up a small portion of > the cylinder being diffed out. I had to raise the $fn on the cylinder or > tube being used so that I got enough points in each tooth that diff or > intersection was accurate. I kept raising it until the results stopped > improving. I ended up with the 16*360 you see in the code. > > After I have the raw teeth, I generate a cone that is diffed away to > produce the chamfer at the top of the teeth. Then I add in the base. The > base also adds the “chamfer” at the bottom of the groove. It’s half the > size of the top chamfer to leave a little gap when the parts are joined. > > When I comment out the everything but the raw teeth and import the STL > into PrusaSlicer, it reports errors fixed, but appears to slice correctly > when supports are added. > > When I add the intersection to trim the raw teeth, the number of reported > errors goes way up. > > When I add the diff to remove the chamfer, the number goes way up again. > > When I add in the base, the number goes up again and it starts reporting > many open edges. > > Throughout, OpenSCAD reports no errors. Using $fn at 16*360, manifold > renders in 4+ seconds. At 32*360, it’s 53+ seconds. I did check CSG and it > did not help. > > Maybe the biggest hint is that the convex part uses almost identical code, > but produces no errors. Very weird. > > So, is this an OpenSCAD problem? Or something in my code? > > It’s also possible that my math is off somewhere. My formal trig training > was 60 years ago. However I doubt a math error is responsible for the > slicing problem and STL errors. > > -Bob > > > include <BOSL2/std.scad> > include <BOSL2/structs.scad> > > // Number of Teeth > _n = 36; // Number Of Teeth > > // Inner Radius > _ir = 30; > // Outer Radius > _or = 50; > // Is the coupling conical? > _conic = 10; > // Tooth Profile Angle > _profile = 60; // [60, 90] > // Percentage of tooth height > _chamfer = 5; // Default 5% > _base = 1; > > $fn = 180; > tiny = 1 / 1024; > > hirth_concave(); > > _irRatio = _ir / _or; > _toothAngle = 360/_n; > _toothHeight = (sin(_toothAngle/2) * _or) / tan(_profile/2); > _chamferHeight = _chamfer * _toothHeight / 100; > _grooveAngle = atan(((_toothHeight/2) + _conic) / _or); > _ridgeAngle = -atan(((_toothHeight/2) - _conic) / _or); > _innerCenterLine = (1 - _irRatio) * _conic; > _stackHeight = _innerCenterLine + _toothHeight + 2*_base; > _tubeHeight = 2*_conic + 2*_base + 2*_toothHeight; > > module hirth_concave() { > zrot(_toothAngle/2) > union() { > difference() { > intersection() { > union() { > for (i = [0 : 360/_n : 359]) > zrot(i) > _profileF(); > } > tube(ir = _ir, or = _or, anchor = CENTER, l = _tubeHeight, > orient = UP, $fn = 16*360); > } > _chamferF(); > zcyl(r = _ir, h = _tubeHeight, $fn = 16*360, anchor = CENTER); > } > _baseF(); > } > } // hirth_concave > > module _profileF() { > IR = _ir * .5; > OR = _or * 1.5; > tI = [spherical_to_xyz(IR, 0, _grooveAngle + 90), > spherical_to_xyz(IR, _toothAngle/2, _ridgeAngle + 90), > spherical_to_xyz(IR, -_toothAngle/2, _ridgeAngle + 90)]; > > tO = [spherical_to_xyz(OR, 0, _grooveAngle + 90), > spherical_to_xyz(OR, _toothAngle/2, _ridgeAngle + 90), > spherical_to_xyz(OR, -_toothAngle/2, _ridgeAngle + 90)]; > up(_conic) > skin([tI, tO], slices = 0); > } > > > module _chamferF() { > A = -_toothHeight/2 - .1; > B = -_toothHeight/2 + _chamferHeight; > > pts = [[0, _conic], > [_or+tiny, A], > [_or+tiny, B]]; > > rotate_extrude(angle = 360, $fn = 16*360) > polygon(pts); > } > > module _baseF() { > A = _base + _irRatio*_toothHeight/2 + _innerCenterLine; > B = _irRatio * (_toothHeight/2 - _chamferHeight/2) + _innerCenterLine; > C = _toothHeight/2 - _chamferHeight/2; > pts = [ > [_ir, A], > [_ir, B], > [_or, C], > [_or, A] > ]; > > rotate_extrude(angle = 360, $fn = 360*16) > polygon(pts); > } > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org >
DP
David Phillip Oster
Sat, Oct 26, 2024 12:19 AM

I may be misunderstanding your post, but I pasted the source code you
posted into OpenSCAD  2024.03.01 (git e96dd26d5) on macOS, and had no
trouble viewing, rendering it, saving it as an .obj file, and slicing the
result, without any indication of error in OpenSCAD or PrusaSlicer 2.8.1.

I may be misunderstanding your post, but I pasted the source code you posted into OpenSCAD 2024.03.01 (git e96dd26d5) on macOS, and had no trouble viewing, rendering it, saving it as an .obj file, and slicing the result, without any indication of error in OpenSCAD or PrusaSlicer 2.8.1.
BC
Bob Carlson
Sat, Oct 26, 2024 3:19 AM

I use .stl rather than .obj and have an OpenSCAD from about a month ago. I think that’s my PS version. I’ll try .obj tomorrow. I’ll also post a screen shot.

-Bob
Sent from my iPad

On Oct 25, 2024, at 17:20, David Phillip Oster via Discuss discuss@lists.openscad.org wrote:


I may be misunderstanding your post, but I pasted the source code you posted into OpenSCAD  2024.03.01 (git e96dd26d5) on macOS, and had no trouble viewing, rendering it, saving it as an .obj file, and slicing the result, without any indication of error in OpenSCAD or PrusaSlicer 2.8.1.


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

I use .stl rather than .obj and have an OpenSCAD from about a month ago. I think that’s my PS version. I’ll try .obj tomorrow. I’ll also post a screen shot. -Bob Sent from my iPad > On Oct 25, 2024, at 17:20, David Phillip Oster via Discuss <discuss@lists.openscad.org> wrote: > >  > I may be misunderstanding your post, but I pasted the source code you posted into OpenSCAD 2024.03.01 (git e96dd26d5) on macOS, and had no trouble viewing, rendering it, saving it as an .obj file, and slicing the result, without any indication of error in OpenSCAD or PrusaSlicer 2.8.1. > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org
BC
Bob Carlson
Sat, Oct 26, 2024 4:56 PM

This second picture shows some visual aids I have in my code to show the center lines, the origin and the groove and ridge angles.

On Oct 25, 2024, at 17:04, Sanjeev Prabhakar sprabhakar2006@gmail.com wrote:

Can you post a picture of this

I will try this as well in python.

It may not interest you but just want see how tough this is to model

On Sat, 26 Oct, 2024, 5:15 am Bob Carlson via Discuss, <discuss@lists.openscad.org mailto:discuss@lists.openscad.org> wrote:

I got really intrigued by the Hirth joint and have been working a library entry that would generate them. I have it fully working, apparently, because it renders perfectly as far as I can see. However when I load one of the parts (a concave part) into PrusaSlicer, it reports thousands of errors that it supposedly fixed. The visual rendering is fine, but when you look at the slice it is completely screwed up.

First some explanation. When I looked up hirth joints I only saw flat ones mentioned. The one I have actually encountered though is a conical one. There is a concave part and a convex part. They fit together perfectly. I had to invent some terminology since I did not find terms for some things I found to be important. The outer center line is the plane that passes through the midpoint of the teeth at the outer radius. In a flat hirth joint all the teeth radiate from the center of this circle, call it the origin. If the origin of the teeth is above the outer center line, then joint has a conical shape and the two parts are concave and convex.

Each tooth at every point has the same profile, the top of the tooth profile is either 60 or 90 degrees. The groove angle is the angle that the groove forms from the origin to the outer radius. It will pass below (for a convex part) the outer radius. It’s critical for making hirth joints because it forms the tool path. The ridge angle is the angle formed by the corresponding ridge.

If the joint is conical, then there is an inner center line that passes through the center of the teeth at the inner radius. The tooth height is the critical number to calculate. It is dependent on the number of teeth, the profile angle and the inner and out radii. Something that really complicates the mental gymnastics is that the tooth height is smaller at the inner radius. My code adds a “base” of extra material at the bottom of the convex part and the top of the concave part. What’s tricky is positioning the base of the concave part relative to the inner center line. The concave parts base is relatively easy to place because it depends on the outer radius and center line.

I generate the raw teeth using the groove and ridge angles and spherical coordinates to make two 2d tooth profiles. Then I complete a tooth using skin(). A for loop generates the full set of N teeth. Then intersection or difference is used the trim the teeth at the inner and outer radii. I discovered something at that point, but solved it pretty simply. When diffing a cylinder from the N teeth, each tooth took up a small portion of the cylinder being diffed out. I had to raise the $fn on the cylinder or tube being used so that I got enough points in each tooth that diff or intersection was accurate. I kept raising it until the results stopped improving. I ended up with the 16*360 you see in the code.

After I have the raw teeth, I generate a cone that is diffed away to produce the chamfer at the top of the teeth. Then I add in the base. The base also adds the “chamfer” at the bottom of the groove. It’s half the size of the top chamfer to leave a little gap when the parts are joined.

When I comment out the everything but the raw teeth and import the STL into PrusaSlicer, it reports errors fixed, but appears to slice correctly when supports are added.

When I add the intersection to trim the raw teeth, the number of reported errors goes way up.

When I add the diff to remove the chamfer, the number goes way up again.

When I add in the base, the number goes up again and it starts reporting many open edges.

Throughout, OpenSCAD reports no errors. Using $fn at 16360, manifold renders in 4+ seconds. At 32360, it’s 53+ seconds. I did check CSG and it did not help.

Maybe the biggest hint is that the convex part uses almost identical code, but produces no errors. Very weird.

So, is this an OpenSCAD problem? Or something in my code?

It’s also possible that my math is off somewhere. My formal trig training was 60 years ago. However I doubt a math error is responsible for the slicing problem and STL errors.

-Bob

include <BOSL2/std.scad>
include <BOSL2/structs.scad>

// Number of Teeth
_n = 36;          // Number Of Teeth

// Inner Radius
_ir = 30;
// Outer Radius
_or = 50;
// Is the coupling conical?
_conic = 10;
// Tooth Profile Angle
_profile = 60; // [60, 90]
// Percentage of tooth height
_chamfer = 5; // Default 5%
_base = 1;

$fn = 180;
tiny = 1 / 1024;

hirth_concave();

_irRatio = _ir / _or;
_toothAngle = 360/_n;
_toothHeight = (sin(_toothAngle/2) * _or) / tan(_profile/2);
_chamferHeight = _chamfer * _toothHeight / 100;
_grooveAngle =  atan(((_toothHeight/2) + _conic) / _or);
_ridgeAngle = -atan(((_toothHeight/2) - _conic) / _or);
_innerCenterLine = (1 - _irRatio) * _conic;
_stackHeight  = _innerCenterLine + _toothHeight + 2*_base;
_tubeHeight = 2*_conic + 2*_base + 2*_toothHeight;

module hirth_concave() {
zrot(_toothAngle/2)
union() {
difference() {
intersection() {
union() {
for (i = [0 : 360/_n : 359])
zrot(i)
_profileF();
}
tube(ir = _ir, or = _or, anchor = CENTER, l = _tubeHeight, orient = UP, $fn = 16360);
}
_chamferF();
zcyl(r = _ir, h = _tubeHeight, $fn = 16
360, anchor = CENTER);
}
_baseF();
}
} // hirth_concave

module _profileF() {
IR = _ir * .5;
OR = _or * 1.5;
tI = [spherical_to_xyz(IR,  0,            _grooveAngle + 90),
spherical_to_xyz(IR,  _toothAngle/2, _ridgeAngle + 90),
spherical_to_xyz(IR, -_toothAngle/2, _ridgeAngle + 90)];

 tO = [spherical_to_xyz(OR,   0,            _grooveAngle + 90),
       spherical_to_xyz(OR,  _toothAngle/2, _ridgeAngle + 90),
       spherical_to_xyz(OR, -_toothAngle/2, _ridgeAngle + 90)];
 up(_conic)
 skin([tI, tO], slices = 0);

}

module _chamferF() {
A = -_toothHeight/2 - .1;
B = -_toothHeight/2 + _chamferHeight;

 pts = [[0, _conic], 
        [_or+tiny, A], 
        [_or+tiny, B]];

 rotate_extrude(angle = 360, $fn = 16*360)
 polygon(pts);

}

module _baseF() {
A = _base + _irRatio*_toothHeight/2 + _innerCenterLine;
B = _irRatio * (_toothHeight/2 - _chamferHeight/2) + _innerCenterLine;
C = _toothHeight/2 - _chamferHeight/2;
pts = [
[_ir, A],
[_ir, B],
[_or, C],
[_or, A]
];

 rotate_extrude(angle = 360, $fn = 360*16)
 polygon(pts);

}


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

 This second picture shows some visual aids I have in my code to show the center lines, the origin and the groove and ridge angles.  > On Oct 25, 2024, at 17:04, Sanjeev Prabhakar <sprabhakar2006@gmail.com> wrote: > > Can you post a picture of this > > I will try this as well in python. > > It may not interest you but just want see how tough this is to model > > On Sat, 26 Oct, 2024, 5:15 am Bob Carlson via Discuss, <discuss@lists.openscad.org <mailto:discuss@lists.openscad.org>> wrote: >> I got really intrigued by the Hirth joint and have been working a library entry that would generate them. I have it fully working, apparently, because it renders perfectly as far as I can see. However when I load one of the parts (a concave part) into PrusaSlicer, it reports thousands of errors that it supposedly fixed. The visual rendering is fine, but when you look at the slice it is completely screwed up. >> >> First some explanation. When I looked up hirth joints I only saw flat ones mentioned. The one I have actually encountered though is a conical one. There is a concave part and a convex part. They fit together perfectly. I had to invent some terminology since I did not find terms for some things I found to be important. The outer center line is the plane that passes through the midpoint of the teeth at the outer radius. In a flat hirth joint all the teeth radiate from the center of this circle, call it the origin. If the origin of the teeth is above the outer center line, then joint has a conical shape and the two parts are concave and convex. >> >> Each tooth at every point has the same profile, the top of the tooth profile is either 60 or 90 degrees. The groove angle is the angle that the groove forms from the origin to the outer radius. It will pass below (for a convex part) the outer radius. It’s critical for making hirth joints because it forms the tool path. The ridge angle is the angle formed by the corresponding ridge. >> >> If the joint is conical, then there is an inner center line that passes through the center of the teeth at the inner radius. The tooth height is the critical number to calculate. It is dependent on the number of teeth, the profile angle and the inner and out radii. Something that really complicates the mental gymnastics is that the tooth height is smaller at the inner radius. My code adds a “base” of extra material at the bottom of the convex part and the top of the concave part. What’s tricky is positioning the base of the concave part relative to the inner center line. The concave parts base is relatively easy to place because it depends on the outer radius and center line. >> >> I generate the raw teeth using the groove and ridge angles and spherical coordinates to make two 2d tooth profiles. Then I complete a tooth using skin(). A for loop generates the full set of N teeth. Then intersection or difference is used the trim the teeth at the inner and outer radii. I discovered something at that point, but solved it pretty simply. When diffing a cylinder from the N teeth, each tooth took up a small portion of the cylinder being diffed out. I had to raise the $fn on the cylinder or tube being used so that I got enough points in each tooth that diff or intersection was accurate. I kept raising it until the results stopped improving. I ended up with the 16*360 you see in the code. >> >> After I have the raw teeth, I generate a cone that is diffed away to produce the chamfer at the top of the teeth. Then I add in the base. The base also adds the “chamfer” at the bottom of the groove. It’s half the size of the top chamfer to leave a little gap when the parts are joined. >> >> When I comment out the everything but the raw teeth and import the STL into PrusaSlicer, it reports errors fixed, but appears to slice correctly when supports are added. >> >> When I add the intersection to trim the raw teeth, the number of reported errors goes way up. >> >> When I add the diff to remove the chamfer, the number goes way up again. >> >> When I add in the base, the number goes up again and it starts reporting many open edges. >> >> Throughout, OpenSCAD reports no errors. Using $fn at 16*360, manifold renders in 4+ seconds. At 32*360, it’s 53+ seconds. I did check CSG and it did not help. >> >> Maybe the biggest hint is that the convex part uses almost identical code, but produces no errors. Very weird. >> >> So, is this an OpenSCAD problem? Or something in my code? >> >> It’s also possible that my math is off somewhere. My formal trig training was 60 years ago. However I doubt a math error is responsible for the slicing problem and STL errors. >> >> -Bob >> >> >> include <BOSL2/std.scad> >> include <BOSL2/structs.scad> >> >> // Number of Teeth >> _n = 36; // Number Of Teeth >> >> // Inner Radius >> _ir = 30; >> // Outer Radius >> _or = 50; >> // Is the coupling conical? >> _conic = 10; >> // Tooth Profile Angle >> _profile = 60; // [60, 90] >> // Percentage of tooth height >> _chamfer = 5; // Default 5% >> _base = 1; >> >> $fn = 180; >> tiny = 1 / 1024; >> >> hirth_concave(); >> >> _irRatio = _ir / _or; >> _toothAngle = 360/_n; >> _toothHeight = (sin(_toothAngle/2) * _or) / tan(_profile/2); >> _chamferHeight = _chamfer * _toothHeight / 100; >> _grooveAngle = atan(((_toothHeight/2) + _conic) / _or); >> _ridgeAngle = -atan(((_toothHeight/2) - _conic) / _or); >> _innerCenterLine = (1 - _irRatio) * _conic; >> _stackHeight = _innerCenterLine + _toothHeight + 2*_base; >> _tubeHeight = 2*_conic + 2*_base + 2*_toothHeight; >> >> module hirth_concave() { >> zrot(_toothAngle/2) >> union() { >> difference() { >> intersection() { >> union() { >> for (i = [0 : 360/_n : 359]) >> zrot(i) >> _profileF(); >> } >> tube(ir = _ir, or = _or, anchor = CENTER, l = _tubeHeight, orient = UP, $fn = 16*360); >> } >> _chamferF(); >> zcyl(r = _ir, h = _tubeHeight, $fn = 16*360, anchor = CENTER); >> } >> _baseF(); >> } >> } // hirth_concave >> >> module _profileF() { >> IR = _ir * .5; >> OR = _or * 1.5; >> tI = [spherical_to_xyz(IR, 0, _grooveAngle + 90), >> spherical_to_xyz(IR, _toothAngle/2, _ridgeAngle + 90), >> spherical_to_xyz(IR, -_toothAngle/2, _ridgeAngle + 90)]; >> >> tO = [spherical_to_xyz(OR, 0, _grooveAngle + 90), >> spherical_to_xyz(OR, _toothAngle/2, _ridgeAngle + 90), >> spherical_to_xyz(OR, -_toothAngle/2, _ridgeAngle + 90)]; >> up(_conic) >> skin([tI, tO], slices = 0); >> } >> >> >> module _chamferF() { >> A = -_toothHeight/2 - .1; >> B = -_toothHeight/2 + _chamferHeight; >> >> pts = [[0, _conic], >> [_or+tiny, A], >> [_or+tiny, B]]; >> >> rotate_extrude(angle = 360, $fn = 16*360) >> polygon(pts); >> } >> >> module _baseF() { >> A = _base + _irRatio*_toothHeight/2 + _innerCenterLine; >> B = _irRatio * (_toothHeight/2 - _chamferHeight/2) + _innerCenterLine; >> C = _toothHeight/2 - _chamferHeight/2; >> pts = [ >> [_ir, A], >> [_ir, B], >> [_or, C], >> [_or, A] >> ]; >> >> rotate_extrude(angle = 360, $fn = 360*16) >> polygon(pts); >> } >> _______________________________________________ >> OpenSCAD mailing list >> To unsubscribe send an email to discuss-leave@lists.openscad.org <mailto:discuss-leave@lists.openscad.org>
AM
Adrian Mariano
Sat, Oct 26, 2024 5:27 PM

This looks like a fairly simple shape and also sort of gear like. You will
get the best performance if you make it as one polyhedron instead of making
one tooth and turning it to geometry and replicating it after and adding
chamfers after.  Make the tooth point array and then rotate the point list
to make all the copies and use vnf_vertex_array one time at the end.  It
will run in 0.1 s

On Sat, Oct 26, 2024 at 12:57 Bob Carlson via Discuss <
discuss@lists.openscad.org> wrote:

[image: PastedGraphic-1.png]

This second picture shows some visual aids I have in my code to show the
center lines, the origin and the groove and ridge angles.

[image: PastedGraphic-2.png]

On Oct 25, 2024, at 17:04, Sanjeev Prabhakar sprabhakar2006@gmail.com
wrote:

Can you post a picture of this

I will try this as well in python.

It may not interest you but just want see how tough this is to model

On Sat, 26 Oct, 2024, 5:15 am Bob Carlson via Discuss, <
discuss@lists.openscad.org> wrote:

I got really intrigued by the Hirth joint and have been working a library
entry that would generate them. I have it fully working, apparently,
because it renders perfectly as far as I can see. However when I load one
of the parts (a concave part) into PrusaSlicer, it reports thousands of
errors that it supposedly fixed. The visual rendering is fine, but when you
look at the slice it is completely screwed up.

First some explanation. When I looked up hirth joints I only saw flat
ones mentioned. The one I have actually encountered though is a conical
one. There is a concave part and a convex part. They fit together
perfectly. I had to invent some terminology since I did not find terms for
some things I found to be important. The outer center line is the plane
that passes through the midpoint of the teeth at the outer radius. In a
flat hirth joint all the teeth radiate from the center of this circle, call
it the origin. If the origin of the teeth is above the outer center line,
then joint has a conical shape and the two parts are concave and convex.

Each tooth at every point has the same profile, the top of the tooth
profile is either 60 or 90 degrees. The groove angle is the angle that the
groove forms from the origin to the outer radius. It will pass below (for a
convex part) the outer radius. It’s critical for making hirth joints
because it forms the tool path. The ridge angle is the angle formed by the
corresponding ridge.

If the joint is conical, then there is an inner center line that passes
through the center of the teeth at the inner radius. The tooth height is
the critical number to calculate. It is dependent on the number of teeth,
the profile angle and the inner and out radii. Something that really
complicates the mental gymnastics is that the tooth height is smaller at
the inner radius. My code adds a “base” of extra material at the bottom of
the convex part and the top of the concave part. What’s tricky is
positioning the base of the concave part relative to the inner center line.
The concave parts base is relatively easy to place because it depends on
the outer radius and center line.

I generate the raw teeth using the groove and ridge angles and spherical
coordinates to make two 2d tooth profiles. Then I complete a tooth using
skin(). A for loop generates the full set of N teeth. Then intersection or
difference is used the trim the teeth at the inner and outer radii. I
discovered something at that point, but solved it pretty simply. When
diffing a cylinder from the N teeth, each tooth took up a small portion of
the cylinder being diffed out. I had to raise the $fn on the cylinder or
tube being used so that I got enough points in each tooth that diff or
intersection was accurate. I kept raising it until the results stopped
improving. I ended up with the 16*360 you see in the code.

After I have the raw teeth, I generate a cone that is diffed away to
produce the chamfer at the top of the teeth. Then I add in the base. The
base also adds the “chamfer” at the bottom of the groove. It’s half the
size of the top chamfer to leave a little gap when the parts are joined.

When I comment out the everything but the raw teeth and import the STL
into PrusaSlicer, it reports errors fixed, but appears to slice correctly
when supports are added.

When I add the intersection to trim the raw teeth, the number of reported
errors goes way up.

When I add the diff to remove the chamfer, the number goes way up again.

When I add in the base, the number goes up again and it starts reporting
many open edges.

Throughout, OpenSCAD reports no errors. Using $fn at 16360, manifold
renders in 4+ seconds. At 32
360, it’s 53+ seconds. I did check CSG and it
did not help.

Maybe the biggest hint is that the convex part uses almost identical
code, but produces no errors. Very weird.

So, is this an OpenSCAD problem? Or something in my code?

It’s also possible that my math is off somewhere. My formal trig training
was 60 years ago. However I doubt a math error is responsible for the
slicing problem and STL errors.

-Bob

include <BOSL2/std.scad>
include <BOSL2/structs.scad>

// Number of Teeth
_n = 36;          // Number Of Teeth

// Inner Radius
_ir = 30;
// Outer Radius
_or = 50;
// Is the coupling conical?
_conic = 10;
// Tooth Profile Angle
_profile = 60; // [60, 90]
// Percentage of tooth height
_chamfer = 5; // Default 5%
_base = 1;

$fn = 180;
tiny = 1 / 1024;

hirth_concave();

_irRatio = _ir / _or;
_toothAngle = 360/_n;
_toothHeight = (sin(_toothAngle/2) * _or) / tan(_profile/2);
_chamferHeight = _chamfer * _toothHeight / 100;
_grooveAngle =  atan(((_toothHeight/2) + _conic) / _or);
_ridgeAngle = -atan(((_toothHeight/2) - _conic) / _or);
_innerCenterLine = (1 - _irRatio) * _conic;
_stackHeight  = _innerCenterLine + _toothHeight + 2*_base;
_tubeHeight = 2*_conic + 2*_base + 2*_toothHeight;

module hirth_concave() {
zrot(_toothAngle/2)
union() {
difference() {
intersection() {
union() {
for (i = [0 : 360/_n : 359])
zrot(i)
_profileF();
}
tube(ir = _ir, or = _or, anchor = CENTER, l =
_tubeHeight, orient = UP, $fn = 16360);
}
_chamferF();
zcyl(r = _ir, h = _tubeHeight, $fn = 16
360, anchor = CENTER);
}
_baseF();
}
} // hirth_concave

module _profileF() {
IR = _ir * .5;
OR = _or * 1.5;
tI = [spherical_to_xyz(IR,  0,            _grooveAngle + 90),
spherical_to_xyz(IR,  _toothAngle/2, _ridgeAngle + 90),
spherical_to_xyz(IR, -_toothAngle/2, _ridgeAngle + 90)];

 tO = [spherical_to_xyz(OR,   0,            _grooveAngle + 90),
       spherical_to_xyz(OR,  _toothAngle/2, _ridgeAngle + 90),
       spherical_to_xyz(OR, -_toothAngle/2, _ridgeAngle + 90)];
 up(_conic)
 skin([tI, tO], slices = 0);

}

module _chamferF() {
A = -_toothHeight/2 - .1;
B = -_toothHeight/2 + _chamferHeight;

 pts = [[0, _conic],
        [_or+tiny, A],
        [_or+tiny, B]];

 rotate_extrude(angle = 360, $fn = 16*360)
 polygon(pts);

}

module _baseF() {
A = _base + _irRatio*_toothHeight/2 + _innerCenterLine;
B = _irRatio * (_toothHeight/2 - _chamferHeight/2) + _innerCenterLine;
C = _toothHeight/2 - _chamferHeight/2;
pts = [
[_ir, A],
[_ir, B],
[_or, C],
[_or, A]
];

 rotate_extrude(angle = 360, $fn = 360*16)
 polygon(pts);

}


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

This looks like a fairly simple shape and also sort of gear like. You will get the best performance if you make it as one polyhedron instead of making one tooth and turning it to geometry and replicating it after and adding chamfers after. Make the tooth point array and then rotate the point list to make all the copies and use vnf_vertex_array one time at the end. It will run in 0.1 s On Sat, Oct 26, 2024 at 12:57 Bob Carlson via Discuss < discuss@lists.openscad.org> wrote: > [image: PastedGraphic-1.png] > > This second picture shows some visual aids I have in my code to show the > center lines, the origin and the groove and ridge angles. > > [image: PastedGraphic-2.png] > > On Oct 25, 2024, at 17:04, Sanjeev Prabhakar <sprabhakar2006@gmail.com> > wrote: > > Can you post a picture of this > > I will try this as well in python. > > It may not interest you but just want see how tough this is to model > > On Sat, 26 Oct, 2024, 5:15 am Bob Carlson via Discuss, < > discuss@lists.openscad.org> wrote: > >> I got really intrigued by the Hirth joint and have been working a library >> entry that would generate them. I have it fully working, apparently, >> because it renders perfectly as far as I can see. However when I load one >> of the parts (a concave part) into PrusaSlicer, it reports thousands of >> errors that it supposedly fixed. The visual rendering is fine, but when you >> look at the slice it is completely screwed up. >> >> First some explanation. When I looked up hirth joints I only saw flat >> ones mentioned. The one I have actually encountered though is a conical >> one. There is a concave part and a convex part. They fit together >> perfectly. I had to invent some terminology since I did not find terms for >> some things I found to be important. The outer center line is the plane >> that passes through the midpoint of the teeth at the outer radius. In a >> flat hirth joint all the teeth radiate from the center of this circle, call >> it the origin. If the origin of the teeth is above the outer center line, >> then joint has a conical shape and the two parts are concave and convex. >> >> Each tooth at every point has the same profile, the top of the tooth >> profile is either 60 or 90 degrees. The groove angle is the angle that the >> groove forms from the origin to the outer radius. It will pass below (for a >> convex part) the outer radius. It’s critical for making hirth joints >> because it forms the tool path. The ridge angle is the angle formed by the >> corresponding ridge. >> >> If the joint is conical, then there is an inner center line that passes >> through the center of the teeth at the inner radius. The tooth height is >> the critical number to calculate. It is dependent on the number of teeth, >> the profile angle and the inner and out radii. Something that really >> complicates the mental gymnastics is that the tooth height is smaller at >> the inner radius. My code adds a “base” of extra material at the bottom of >> the convex part and the top of the concave part. What’s tricky is >> positioning the base of the concave part relative to the inner center line. >> The concave parts base is relatively easy to place because it depends on >> the outer radius and center line. >> >> I generate the raw teeth using the groove and ridge angles and spherical >> coordinates to make two 2d tooth profiles. Then I complete a tooth using >> skin(). A for loop generates the full set of N teeth. Then intersection or >> difference is used the trim the teeth at the inner and outer radii. I >> discovered something at that point, but solved it pretty simply. When >> diffing a cylinder from the N teeth, each tooth took up a small portion of >> the cylinder being diffed out. I had to raise the $fn on the cylinder or >> tube being used so that I got enough points in each tooth that diff or >> intersection was accurate. I kept raising it until the results stopped >> improving. I ended up with the 16*360 you see in the code. >> >> After I have the raw teeth, I generate a cone that is diffed away to >> produce the chamfer at the top of the teeth. Then I add in the base. The >> base also adds the “chamfer” at the bottom of the groove. It’s half the >> size of the top chamfer to leave a little gap when the parts are joined. >> >> When I comment out the everything but the raw teeth and import the STL >> into PrusaSlicer, it reports errors fixed, but appears to slice correctly >> when supports are added. >> >> When I add the intersection to trim the raw teeth, the number of reported >> errors goes way up. >> >> When I add the diff to remove the chamfer, the number goes way up again. >> >> When I add in the base, the number goes up again and it starts reporting >> many open edges. >> >> Throughout, OpenSCAD reports no errors. Using $fn at 16*360, manifold >> renders in 4+ seconds. At 32*360, it’s 53+ seconds. I did check CSG and it >> did not help. >> >> Maybe the biggest hint is that the convex part uses almost identical >> code, but produces no errors. Very weird. >> >> So, is this an OpenSCAD problem? Or something in my code? >> >> It’s also possible that my math is off somewhere. My formal trig training >> was 60 years ago. However I doubt a math error is responsible for the >> slicing problem and STL errors. >> >> -Bob >> >> >> include <BOSL2/std.scad> >> include <BOSL2/structs.scad> >> >> // Number of Teeth >> _n = 36; // Number Of Teeth >> >> // Inner Radius >> _ir = 30; >> // Outer Radius >> _or = 50; >> // Is the coupling conical? >> _conic = 10; >> // Tooth Profile Angle >> _profile = 60; // [60, 90] >> // Percentage of tooth height >> _chamfer = 5; // Default 5% >> _base = 1; >> >> $fn = 180; >> tiny = 1 / 1024; >> >> hirth_concave(); >> >> _irRatio = _ir / _or; >> _toothAngle = 360/_n; >> _toothHeight = (sin(_toothAngle/2) * _or) / tan(_profile/2); >> _chamferHeight = _chamfer * _toothHeight / 100; >> _grooveAngle = atan(((_toothHeight/2) + _conic) / _or); >> _ridgeAngle = -atan(((_toothHeight/2) - _conic) / _or); >> _innerCenterLine = (1 - _irRatio) * _conic; >> _stackHeight = _innerCenterLine + _toothHeight + 2*_base; >> _tubeHeight = 2*_conic + 2*_base + 2*_toothHeight; >> >> module hirth_concave() { >> zrot(_toothAngle/2) >> union() { >> difference() { >> intersection() { >> union() { >> for (i = [0 : 360/_n : 359]) >> zrot(i) >> _profileF(); >> } >> tube(ir = _ir, or = _or, anchor = CENTER, l = >> _tubeHeight, orient = UP, $fn = 16*360); >> } >> _chamferF(); >> zcyl(r = _ir, h = _tubeHeight, $fn = 16*360, anchor = CENTER); >> } >> _baseF(); >> } >> } // hirth_concave >> >> module _profileF() { >> IR = _ir * .5; >> OR = _or * 1.5; >> tI = [spherical_to_xyz(IR, 0, _grooveAngle + 90), >> spherical_to_xyz(IR, _toothAngle/2, _ridgeAngle + 90), >> spherical_to_xyz(IR, -_toothAngle/2, _ridgeAngle + 90)]; >> >> tO = [spherical_to_xyz(OR, 0, _grooveAngle + 90), >> spherical_to_xyz(OR, _toothAngle/2, _ridgeAngle + 90), >> spherical_to_xyz(OR, -_toothAngle/2, _ridgeAngle + 90)]; >> up(_conic) >> skin([tI, tO], slices = 0); >> } >> >> >> module _chamferF() { >> A = -_toothHeight/2 - .1; >> B = -_toothHeight/2 + _chamferHeight; >> >> pts = [[0, _conic], >> [_or+tiny, A], >> [_or+tiny, B]]; >> >> rotate_extrude(angle = 360, $fn = 16*360) >> polygon(pts); >> } >> >> module _baseF() { >> A = _base + _irRatio*_toothHeight/2 + _innerCenterLine; >> B = _irRatio * (_toothHeight/2 - _chamferHeight/2) + _innerCenterLine; >> C = _toothHeight/2 - _chamferHeight/2; >> pts = [ >> [_ir, A], >> [_ir, B], >> [_or, C], >> [_or, A] >> ]; >> >> rotate_extrude(angle = 360, $fn = 360*16) >> polygon(pts); >> } >> _______________________________________________ >> 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
Sat, Oct 26, 2024 6:45 PM

As I understand it, the math for that would be way beyond what I want to tax my brain with. In any case I am not concerned with performance. It’s fine as is.

-Bob

On Oct 26, 2024, at 10:27, Adrian Mariano avm4@cornell.edu wrote:

This looks like a fairly simple shape and also sort of gear like. You will get the best performance if you make it as one polyhedron instead of making one tooth and turning it to geometry and replicating it after and adding chamfers after.  Make the tooth point array and then rotate the point list to make all the copies and use vnf_vertex_array one time at the end.  It will run in 0.1 s

On Sat, Oct 26, 2024 at 12:57 Bob Carlson via Discuss <discuss@lists.openscad.org mailto:discuss@lists.openscad.org> wrote:

<PastedGraphic-1.png>

This second picture shows some visual aids I have in my code to show the center lines, the origin and the groove and ridge angles.

<PastedGraphic-2.png>

On Oct 25, 2024, at 17:04, Sanjeev Prabhakar <sprabhakar2006@gmail.com mailto:sprabhakar2006@gmail.com> wrote:

Can you post a picture of this

I will try this as well in python.

It may not interest you but just want see how tough this is to model

On Sat, 26 Oct, 2024, 5:15 am Bob Carlson via Discuss, <discuss@lists.openscad.org mailto:discuss@lists.openscad.org> wrote:

I got really intrigued by the Hirth joint and have been working a library entry that would generate them. I have it fully working, apparently, because it renders perfectly as far as I can see. However when I load one of the parts (a concave part) into PrusaSlicer, it reports thousands of errors that it supposedly fixed. The visual rendering is fine, but when you look at the slice it is completely screwed up.

First some explanation. When I looked up hirth joints I only saw flat ones mentioned. The one I have actually encountered though is a conical one. There is a concave part and a convex part. They fit together perfectly. I had to invent some terminology since I did not find terms for some things I found to be important. The outer center line is the plane that passes through the midpoint of the teeth at the outer radius. In a flat hirth joint all the teeth radiate from the center of this circle, call it the origin. If the origin of the teeth is above the outer center line, then joint has a conical shape and the two parts are concave and convex.

Each tooth at every point has the same profile, the top of the tooth profile is either 60 or 90 degrees. The groove angle is the angle that the groove forms from the origin to the outer radius. It will pass below (for a convex part) the outer radius. It’s critical for making hirth joints because it forms the tool path. The ridge angle is the angle formed by the corresponding ridge.

If the joint is conical, then there is an inner center line that passes through the center of the teeth at the inner radius. The tooth height is the critical number to calculate. It is dependent on the number of teeth, the profile angle and the inner and out radii. Something that really complicates the mental gymnastics is that the tooth height is smaller at the inner radius. My code adds a “base” of extra material at the bottom of the convex part and the top of the concave part. What’s tricky is positioning the base of the concave part relative to the inner center line. The concave parts base is relatively easy to place because it depends on the outer radius and center line.

I generate the raw teeth using the groove and ridge angles and spherical coordinates to make two 2d tooth profiles. Then I complete a tooth using skin(). A for loop generates the full set of N teeth. Then intersection or difference is used the trim the teeth at the inner and outer radii. I discovered something at that point, but solved it pretty simply. When diffing a cylinder from the N teeth, each tooth took up a small portion of the cylinder being diffed out. I had to raise the $fn on the cylinder or tube being used so that I got enough points in each tooth that diff or intersection was accurate. I kept raising it until the results stopped improving. I ended up with the 16*360 you see in the code.

After I have the raw teeth, I generate a cone that is diffed away to produce the chamfer at the top of the teeth. Then I add in the base. The base also adds the “chamfer” at the bottom of the groove. It’s half the size of the top chamfer to leave a little gap when the parts are joined.

When I comment out the everything but the raw teeth and import the STL into PrusaSlicer, it reports errors fixed, but appears to slice correctly when supports are added.

When I add the intersection to trim the raw teeth, the number of reported errors goes way up.

When I add the diff to remove the chamfer, the number goes way up again.

When I add in the base, the number goes up again and it starts reporting many open edges.

Throughout, OpenSCAD reports no errors. Using $fn at 16360, manifold renders in 4+ seconds. At 32360, it’s 53+ seconds. I did check CSG and it did not help.

Maybe the biggest hint is that the convex part uses almost identical code, but produces no errors. Very weird.

So, is this an OpenSCAD problem? Or something in my code?

It’s also possible that my math is off somewhere. My formal trig training was 60 years ago. However I doubt a math error is responsible for the slicing problem and STL errors.

-Bob

include <BOSL2/std.scad>
include <BOSL2/structs.scad>

// Number of Teeth
_n = 36;          // Number Of Teeth

// Inner Radius
_ir = 30;
// Outer Radius
_or = 50;
// Is the coupling conical?
_conic = 10;
// Tooth Profile Angle
_profile = 60; // [60, 90]
// Percentage of tooth height
_chamfer = 5; // Default 5%
_base = 1;

$fn = 180;
tiny = 1 / 1024;

hirth_concave();

_irRatio = _ir / _or;
_toothAngle = 360/_n;
_toothHeight = (sin(_toothAngle/2) * _or) / tan(_profile/2);
_chamferHeight = _chamfer * _toothHeight / 100;
_grooveAngle =  atan(((_toothHeight/2) + _conic) / _or);
_ridgeAngle = -atan(((_toothHeight/2) - _conic) / _or);
_innerCenterLine = (1 - _irRatio) * _conic;
_stackHeight  = _innerCenterLine + _toothHeight + 2*_base;
_tubeHeight = 2*_conic + 2*_base + 2*_toothHeight;

module hirth_concave() {
zrot(_toothAngle/2)
union() {
difference() {
intersection() {
union() {
for (i = [0 : 360/_n : 359])
zrot(i)
_profileF();
}
tube(ir = _ir, or = _or, anchor = CENTER, l = _tubeHeight, orient = UP, $fn = 16360);
}
_chamferF();
zcyl(r = _ir, h = _tubeHeight, $fn = 16
360, anchor = CENTER);
}
_baseF();
}
} // hirth_concave

module _profileF() {
IR = _ir * .5;
OR = _or * 1.5;
tI = [spherical_to_xyz(IR,  0,            _grooveAngle + 90),
spherical_to_xyz(IR,  _toothAngle/2, _ridgeAngle + 90),
spherical_to_xyz(IR, -_toothAngle/2, _ridgeAngle + 90)];

 tO = [spherical_to_xyz(OR,   0,            _grooveAngle + 90),
       spherical_to_xyz(OR,  _toothAngle/2, _ridgeAngle + 90),
       spherical_to_xyz(OR, -_toothAngle/2, _ridgeAngle + 90)];
 up(_conic)
 skin([tI, tO], slices = 0);

}

module _chamferF() {
A = -_toothHeight/2 - .1;
B = -_toothHeight/2 + _chamferHeight;

 pts = [[0, _conic], 
        [_or+tiny, A], 
        [_or+tiny, B]];

 rotate_extrude(angle = 360, $fn = 16*360)
 polygon(pts);

}

module _baseF() {
A = _base + _irRatio*_toothHeight/2 + _innerCenterLine;
B = _irRatio * (_toothHeight/2 - _chamferHeight/2) + _innerCenterLine;
C = _toothHeight/2 - _chamferHeight/2;
pts = [
[_ir, A],
[_ir, B],
[_or, C],
[_or, A]
];

 rotate_extrude(angle = 360, $fn = 360*16)
 polygon(pts);

}


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

As I understand it, the math for that would be way beyond what I want to tax my brain with. In any case I am not concerned with performance. It’s fine as is. -Bob > On Oct 26, 2024, at 10:27, Adrian Mariano <avm4@cornell.edu> wrote: > > This looks like a fairly simple shape and also sort of gear like. You will get the best performance if you make it as one polyhedron instead of making one tooth and turning it to geometry and replicating it after and adding chamfers after. Make the tooth point array and then rotate the point list to make all the copies and use vnf_vertex_array one time at the end. It will run in 0.1 s > > On Sat, Oct 26, 2024 at 12:57 Bob Carlson via Discuss <discuss@lists.openscad.org <mailto:discuss@lists.openscad.org>> wrote: >> <PastedGraphic-1.png> >> >> This second picture shows some visual aids I have in my code to show the center lines, the origin and the groove and ridge angles. >> >> <PastedGraphic-2.png> >> >>> On Oct 25, 2024, at 17:04, Sanjeev Prabhakar <sprabhakar2006@gmail.com <mailto:sprabhakar2006@gmail.com>> wrote: >>> >>> Can you post a picture of this >>> >>> I will try this as well in python. >>> >>> It may not interest you but just want see how tough this is to model >>> >>> On Sat, 26 Oct, 2024, 5:15 am Bob Carlson via Discuss, <discuss@lists.openscad.org <mailto:discuss@lists.openscad.org>> wrote: >>>> I got really intrigued by the Hirth joint and have been working a library entry that would generate them. I have it fully working, apparently, because it renders perfectly as far as I can see. However when I load one of the parts (a concave part) into PrusaSlicer, it reports thousands of errors that it supposedly fixed. The visual rendering is fine, but when you look at the slice it is completely screwed up. >>>> >>>> First some explanation. When I looked up hirth joints I only saw flat ones mentioned. The one I have actually encountered though is a conical one. There is a concave part and a convex part. They fit together perfectly. I had to invent some terminology since I did not find terms for some things I found to be important. The outer center line is the plane that passes through the midpoint of the teeth at the outer radius. In a flat hirth joint all the teeth radiate from the center of this circle, call it the origin. If the origin of the teeth is above the outer center line, then joint has a conical shape and the two parts are concave and convex. >>>> >>>> Each tooth at every point has the same profile, the top of the tooth profile is either 60 or 90 degrees. The groove angle is the angle that the groove forms from the origin to the outer radius. It will pass below (for a convex part) the outer radius. It’s critical for making hirth joints because it forms the tool path. The ridge angle is the angle formed by the corresponding ridge. >>>> >>>> If the joint is conical, then there is an inner center line that passes through the center of the teeth at the inner radius. The tooth height is the critical number to calculate. It is dependent on the number of teeth, the profile angle and the inner and out radii. Something that really complicates the mental gymnastics is that the tooth height is smaller at the inner radius. My code adds a “base” of extra material at the bottom of the convex part and the top of the concave part. What’s tricky is positioning the base of the concave part relative to the inner center line. The concave parts base is relatively easy to place because it depends on the outer radius and center line. >>>> >>>> I generate the raw teeth using the groove and ridge angles and spherical coordinates to make two 2d tooth profiles. Then I complete a tooth using skin(). A for loop generates the full set of N teeth. Then intersection or difference is used the trim the teeth at the inner and outer radii. I discovered something at that point, but solved it pretty simply. When diffing a cylinder from the N teeth, each tooth took up a small portion of the cylinder being diffed out. I had to raise the $fn on the cylinder or tube being used so that I got enough points in each tooth that diff or intersection was accurate. I kept raising it until the results stopped improving. I ended up with the 16*360 you see in the code. >>>> >>>> After I have the raw teeth, I generate a cone that is diffed away to produce the chamfer at the top of the teeth. Then I add in the base. The base also adds the “chamfer” at the bottom of the groove. It’s half the size of the top chamfer to leave a little gap when the parts are joined. >>>> >>>> When I comment out the everything but the raw teeth and import the STL into PrusaSlicer, it reports errors fixed, but appears to slice correctly when supports are added. >>>> >>>> When I add the intersection to trim the raw teeth, the number of reported errors goes way up. >>>> >>>> When I add the diff to remove the chamfer, the number goes way up again. >>>> >>>> When I add in the base, the number goes up again and it starts reporting many open edges. >>>> >>>> Throughout, OpenSCAD reports no errors. Using $fn at 16*360, manifold renders in 4+ seconds. At 32*360, it’s 53+ seconds. I did check CSG and it did not help. >>>> >>>> Maybe the biggest hint is that the convex part uses almost identical code, but produces no errors. Very weird. >>>> >>>> So, is this an OpenSCAD problem? Or something in my code? >>>> >>>> It’s also possible that my math is off somewhere. My formal trig training was 60 years ago. However I doubt a math error is responsible for the slicing problem and STL errors. >>>> >>>> -Bob >>>> >>>> >>>> include <BOSL2/std.scad> >>>> include <BOSL2/structs.scad> >>>> >>>> // Number of Teeth >>>> _n = 36; // Number Of Teeth >>>> >>>> // Inner Radius >>>> _ir = 30; >>>> // Outer Radius >>>> _or = 50; >>>> // Is the coupling conical? >>>> _conic = 10; >>>> // Tooth Profile Angle >>>> _profile = 60; // [60, 90] >>>> // Percentage of tooth height >>>> _chamfer = 5; // Default 5% >>>> _base = 1; >>>> >>>> $fn = 180; >>>> tiny = 1 / 1024; >>>> >>>> hirth_concave(); >>>> >>>> _irRatio = _ir / _or; >>>> _toothAngle = 360/_n; >>>> _toothHeight = (sin(_toothAngle/2) * _or) / tan(_profile/2); >>>> _chamferHeight = _chamfer * _toothHeight / 100; >>>> _grooveAngle = atan(((_toothHeight/2) + _conic) / _or); >>>> _ridgeAngle = -atan(((_toothHeight/2) - _conic) / _or); >>>> _innerCenterLine = (1 - _irRatio) * _conic; >>>> _stackHeight = _innerCenterLine + _toothHeight + 2*_base; >>>> _tubeHeight = 2*_conic + 2*_base + 2*_toothHeight; >>>> >>>> module hirth_concave() { >>>> zrot(_toothAngle/2) >>>> union() { >>>> difference() { >>>> intersection() { >>>> union() { >>>> for (i = [0 : 360/_n : 359]) >>>> zrot(i) >>>> _profileF(); >>>> } >>>> tube(ir = _ir, or = _or, anchor = CENTER, l = _tubeHeight, orient = UP, $fn = 16*360); >>>> } >>>> _chamferF(); >>>> zcyl(r = _ir, h = _tubeHeight, $fn = 16*360, anchor = CENTER); >>>> } >>>> _baseF(); >>>> } >>>> } // hirth_concave >>>> >>>> module _profileF() { >>>> IR = _ir * .5; >>>> OR = _or * 1.5; >>>> tI = [spherical_to_xyz(IR, 0, _grooveAngle + 90), >>>> spherical_to_xyz(IR, _toothAngle/2, _ridgeAngle + 90), >>>> spherical_to_xyz(IR, -_toothAngle/2, _ridgeAngle + 90)]; >>>> >>>> tO = [spherical_to_xyz(OR, 0, _grooveAngle + 90), >>>> spherical_to_xyz(OR, _toothAngle/2, _ridgeAngle + 90), >>>> spherical_to_xyz(OR, -_toothAngle/2, _ridgeAngle + 90)]; >>>> up(_conic) >>>> skin([tI, tO], slices = 0); >>>> } >>>> >>>> >>>> module _chamferF() { >>>> A = -_toothHeight/2 - .1; >>>> B = -_toothHeight/2 + _chamferHeight; >>>> >>>> pts = [[0, _conic], >>>> [_or+tiny, A], >>>> [_or+tiny, B]]; >>>> >>>> rotate_extrude(angle = 360, $fn = 16*360) >>>> polygon(pts); >>>> } >>>> >>>> module _baseF() { >>>> A = _base + _irRatio*_toothHeight/2 + _innerCenterLine; >>>> B = _irRatio * (_toothHeight/2 - _chamferHeight/2) + _innerCenterLine; >>>> C = _toothHeight/2 - _chamferHeight/2; >>>> pts = [ >>>> [_ir, A], >>>> [_ir, B], >>>> [_or, C], >>>> [_or, A] >>>> ]; >>>> >>>> rotate_extrude(angle = 360, $fn = 360*16) >>>> polygon(pts); >>>> } >>>> _______________________________________________ >>>> 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>
BC
Bob Carlson
Sat, Oct 26, 2024 6:47 PM

When I do the export as a .obj, the slice appears to work correctly. Apparently the error has something to do with the STL export.

-Bob

On Oct 25, 2024, at 17:19, David Phillip Oster via Discuss discuss@lists.openscad.org wrote:

I may be misunderstanding your post, but I pasted the source code you posted into OpenSCAD  2024.03.01 (git e96dd26d5) on macOS, and had no trouble viewing, rendering it, saving it as an .obj file, and slicing the result, without any indication of error in OpenSCAD or PrusaSlicer 2.8.1.


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

When I do the export as a .obj, the slice appears to work correctly. Apparently the error has something to do with the STL export. -Bob > On Oct 25, 2024, at 17:19, David Phillip Oster via Discuss <discuss@lists.openscad.org> wrote: > > I may be misunderstanding your post, but I pasted the source code you posted into OpenSCAD 2024.03.01 (git e96dd26d5) on macOS, and had no trouble viewing, rendering it, saving it as an .obj file, and slicing the result, without any indication of error in OpenSCAD or PrusaSlicer 2.8.1. > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org
AM
Adrian Mariano
Sat, Oct 26, 2024 7:08 PM

The math is the same. You just accumulate a point list in your for loop
instead of looping over geometry.  You have timing of 4s and then 53s which
sounds sort of slow.

On Sat, Oct 26, 2024 at 14:45 Bob Carlson bob@rjcarlson.com wrote:

As I understand it, the math for that would be way beyond what I want to
tax my brain with. In any case I am not concerned with performance. It’s
fine as is.

-Bob

On Oct 26, 2024, at 10:27, Adrian Mariano avm4@cornell.edu wrote:

This looks like a fairly simple shape and also sort of gear like. You will
get the best performance if you make it as one polyhedron instead of making
one tooth and turning it to geometry and replicating it after and adding
chamfers after.  Make the tooth point array and then rotate the point list
to make all the copies and use vnf_vertex_array one time at the end.  It
will run in 0.1 s

On Sat, Oct 26, 2024 at 12:57 Bob Carlson via Discuss <
discuss@lists.openscad.org> wrote:

<PastedGraphic-1.png>

This second picture shows some visual aids I have in my code to show the
center lines, the origin and the groove and ridge angles.

<PastedGraphic-2.png>

On Oct 25, 2024, at 17:04, Sanjeev Prabhakar sprabhakar2006@gmail.com
wrote:

Can you post a picture of this

I will try this as well in python.

It may not interest you but just want see how tough this is to model

On Sat, 26 Oct, 2024, 5:15 am Bob Carlson via Discuss, <
discuss@lists.openscad.org> wrote:

I got really intrigued by the Hirth joint and have been working a
library entry that would generate them. I have it fully working,
apparently, because it renders perfectly as far as I can see. However when
I load one of the parts (a concave part) into PrusaSlicer, it reports
thousands of errors that it supposedly fixed. The visual rendering is fine,
but when you look at the slice it is completely screwed up.

First some explanation. When I looked up hirth joints I only saw flat
ones mentioned. The one I have actually encountered though is a conical
one. There is a concave part and a convex part. They fit together
perfectly. I had to invent some terminology since I did not find terms for
some things I found to be important. The outer center line is the plane
that passes through the midpoint of the teeth at the outer radius. In a
flat hirth joint all the teeth radiate from the center of this circle, call
it the origin. If the origin of the teeth is above the outer center line,
then joint has a conical shape and the two parts are concave and convex.

Each tooth at every point has the same profile, the top of the tooth
profile is either 60 or 90 degrees. The groove angle is the angle that the
groove forms from the origin to the outer radius. It will pass below (for a
convex part) the outer radius. It’s critical for making hirth joints
because it forms the tool path. The ridge angle is the angle formed by the
corresponding ridge.

If the joint is conical, then there is an inner center line that passes
through the center of the teeth at the inner radius. The tooth height is
the critical number to calculate. It is dependent on the number of teeth,
the profile angle and the inner and out radii. Something that really
complicates the mental gymnastics is that the tooth height is smaller at
the inner radius. My code adds a “base” of extra material at the bottom of
the convex part and the top of the concave part. What’s tricky is
positioning the base of the concave part relative to the inner center line.
The concave parts base is relatively easy to place because it depends on
the outer radius and center line.

I generate the raw teeth using the groove and ridge angles and spherical
coordinates to make two 2d tooth profiles. Then I complete a tooth using
skin(). A for loop generates the full set of N teeth. Then intersection or
difference is used the trim the teeth at the inner and outer radii. I
discovered something at that point, but solved it pretty simply. When
diffing a cylinder from the N teeth, each tooth took up a small portion of
the cylinder being diffed out. I had to raise the $fn on the cylinder or
tube being used so that I got enough points in each tooth that diff or
intersection was accurate. I kept raising it until the results stopped
improving. I ended up with the 16*360 you see in the code.

After I have the raw teeth, I generate a cone that is diffed away to
produce the chamfer at the top of the teeth. Then I add in the base. The
base also adds the “chamfer” at the bottom of the groove. It’s half the
size of the top chamfer to leave a little gap when the parts are joined.

When I comment out the everything but the raw teeth and import the STL
into PrusaSlicer, it reports errors fixed, but appears to slice correctly
when supports are added.

When I add the intersection to trim the raw teeth, the number of
reported errors goes way up.

When I add the diff to remove the chamfer, the number goes way up again.

When I add in the base, the number goes up again and it starts reporting
many open edges.

Throughout, OpenSCAD reports no errors. Using $fn at 16360, manifold
renders in 4+ seconds. At 32
360, it’s 53+ seconds. I did check CSG and it
did not help.

Maybe the biggest hint is that the convex part uses almost identical
code, but produces no errors. Very weird.

So, is this an OpenSCAD problem? Or something in my code?

It’s also possible that my math is off somewhere. My formal trig
training was 60 years ago. However I doubt a math error is responsible for
the slicing problem and STL errors.

-Bob

include <BOSL2/std.scad>
include <BOSL2/structs.scad>

// Number of Teeth
_n = 36;          // Number Of Teeth

// Inner Radius
_ir = 30;
// Outer Radius
_or = 50;
// Is the coupling conical?
_conic = 10;
// Tooth Profile Angle
_profile = 60; // [60, 90]
// Percentage of tooth height
_chamfer = 5; // Default 5%
_base = 1;

$fn = 180;
tiny = 1 / 1024;

hirth_concave();

_irRatio = _ir / _or;
_toothAngle = 360/_n;
_toothHeight = (sin(_toothAngle/2) * _or) / tan(_profile/2);
_chamferHeight = _chamfer * _toothHeight / 100;
_grooveAngle =  atan(((_toothHeight/2) + _conic) / _or);
_ridgeAngle = -atan(((_toothHeight/2) - _conic) / _or);
_innerCenterLine = (1 - _irRatio) * _conic;
_stackHeight  = _innerCenterLine + _toothHeight + 2*_base;
_tubeHeight = 2*_conic + 2*_base + 2*_toothHeight;

module hirth_concave() {
zrot(_toothAngle/2)
union() {
difference() {
intersection() {
union() {
for (i = [0 : 360/_n : 359])
zrot(i)
_profileF();
}
tube(ir = _ir, or = _or, anchor = CENTER, l =
_tubeHeight, orient = UP, $fn = 16360);
}
_chamferF();
zcyl(r = _ir, h = _tubeHeight, $fn = 16
360, anchor =
CENTER);
}
_baseF();
}
} // hirth_concave

module _profileF() {
IR = _ir * .5;
OR = _or * 1.5;
tI = [spherical_to_xyz(IR,  0,            _grooveAngle + 90),
spherical_to_xyz(IR,  _toothAngle/2, _ridgeAngle + 90),
spherical_to_xyz(IR, -_toothAngle/2, _ridgeAngle + 90)];

 tO = [spherical_to_xyz(OR,   0,            _grooveAngle + 90),
       spherical_to_xyz(OR,  _toothAngle/2, _ridgeAngle + 90),
       spherical_to_xyz(OR, -_toothAngle/2, _ridgeAngle + 90)];
 up(_conic)
 skin([tI, tO], slices = 0);

}

module _chamferF() {
A = -_toothHeight/2 - .1;
B = -_toothHeight/2 + _chamferHeight;

 pts = [[0, _conic],
        [_or+tiny, A],
        [_or+tiny, B]];

 rotate_extrude(angle = 360, $fn = 16*360)
 polygon(pts);

}

module _baseF() {
A = _base + _irRatio*_toothHeight/2 + _innerCenterLine;
B = _irRatio * (_toothHeight/2 - _chamferHeight/2) +
_innerCenterLine;
C = _toothHeight/2 - _chamferHeight/2;
pts = [
[_ir, A],
[_ir, B],
[_or, C],
[_or, A]
];

 rotate_extrude(angle = 360, $fn = 360*16)
 polygon(pts);

}


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

The math is the same. You just accumulate a point list in your for loop instead of looping over geometry. You have timing of 4s and then 53s which sounds sort of slow. On Sat, Oct 26, 2024 at 14:45 Bob Carlson <bob@rjcarlson.com> wrote: > As I understand it, the math for that would be way beyond what I want to > tax my brain with. In any case I am not concerned with performance. It’s > fine as is. > > -Bob > > On Oct 26, 2024, at 10:27, Adrian Mariano <avm4@cornell.edu> wrote: > > This looks like a fairly simple shape and also sort of gear like. You will > get the best performance if you make it as one polyhedron instead of making > one tooth and turning it to geometry and replicating it after and adding > chamfers after. Make the tooth point array and then rotate the point list > to make all the copies and use vnf_vertex_array one time at the end. It > will run in 0.1 s > > On Sat, Oct 26, 2024 at 12:57 Bob Carlson via Discuss < > discuss@lists.openscad.org> wrote: > >> <PastedGraphic-1.png> >> >> This second picture shows some visual aids I have in my code to show the >> center lines, the origin and the groove and ridge angles. >> >> <PastedGraphic-2.png> >> > >> On Oct 25, 2024, at 17:04, Sanjeev Prabhakar <sprabhakar2006@gmail.com> >> wrote: >> >> Can you post a picture of this >> >> I will try this as well in python. >> >> It may not interest you but just want see how tough this is to model >> >> On Sat, 26 Oct, 2024, 5:15 am Bob Carlson via Discuss, < >> discuss@lists.openscad.org> wrote: >> >>> I got really intrigued by the Hirth joint and have been working a >>> library entry that would generate them. I have it fully working, >>> apparently, because it renders perfectly as far as I can see. However when >>> I load one of the parts (a concave part) into PrusaSlicer, it reports >>> thousands of errors that it supposedly fixed. The visual rendering is fine, >>> but when you look at the slice it is completely screwed up. >>> >>> First some explanation. When I looked up hirth joints I only saw flat >>> ones mentioned. The one I have actually encountered though is a conical >>> one. There is a concave part and a convex part. They fit together >>> perfectly. I had to invent some terminology since I did not find terms for >>> some things I found to be important. The outer center line is the plane >>> that passes through the midpoint of the teeth at the outer radius. In a >>> flat hirth joint all the teeth radiate from the center of this circle, call >>> it the origin. If the origin of the teeth is above the outer center line, >>> then joint has a conical shape and the two parts are concave and convex. >>> >>> Each tooth at every point has the same profile, the top of the tooth >>> profile is either 60 or 90 degrees. The groove angle is the angle that the >>> groove forms from the origin to the outer radius. It will pass below (for a >>> convex part) the outer radius. It’s critical for making hirth joints >>> because it forms the tool path. The ridge angle is the angle formed by the >>> corresponding ridge. >>> >>> If the joint is conical, then there is an inner center line that passes >>> through the center of the teeth at the inner radius. The tooth height is >>> the critical number to calculate. It is dependent on the number of teeth, >>> the profile angle and the inner and out radii. Something that really >>> complicates the mental gymnastics is that the tooth height is smaller at >>> the inner radius. My code adds a “base” of extra material at the bottom of >>> the convex part and the top of the concave part. What’s tricky is >>> positioning the base of the concave part relative to the inner center line. >>> The concave parts base is relatively easy to place because it depends on >>> the outer radius and center line. >>> >>> I generate the raw teeth using the groove and ridge angles and spherical >>> coordinates to make two 2d tooth profiles. Then I complete a tooth using >>> skin(). A for loop generates the full set of N teeth. Then intersection or >>> difference is used the trim the teeth at the inner and outer radii. I >>> discovered something at that point, but solved it pretty simply. When >>> diffing a cylinder from the N teeth, each tooth took up a small portion of >>> the cylinder being diffed out. I had to raise the $fn on the cylinder or >>> tube being used so that I got enough points in each tooth that diff or >>> intersection was accurate. I kept raising it until the results stopped >>> improving. I ended up with the 16*360 you see in the code. >>> >>> After I have the raw teeth, I generate a cone that is diffed away to >>> produce the chamfer at the top of the teeth. Then I add in the base. The >>> base also adds the “chamfer” at the bottom of the groove. It’s half the >>> size of the top chamfer to leave a little gap when the parts are joined. >>> >>> When I comment out the everything but the raw teeth and import the STL >>> into PrusaSlicer, it reports errors fixed, but appears to slice correctly >>> when supports are added. >>> >>> When I add the intersection to trim the raw teeth, the number of >>> reported errors goes way up. >>> >>> When I add the diff to remove the chamfer, the number goes way up again. >>> >>> When I add in the base, the number goes up again and it starts reporting >>> many open edges. >>> >>> Throughout, OpenSCAD reports no errors. Using $fn at 16*360, manifold >>> renders in 4+ seconds. At 32*360, it’s 53+ seconds. I did check CSG and it >>> did not help. >>> >>> Maybe the biggest hint is that the convex part uses almost identical >>> code, but produces no errors. Very weird. >>> >>> So, is this an OpenSCAD problem? Or something in my code? >>> >>> It’s also possible that my math is off somewhere. My formal trig >>> training was 60 years ago. However I doubt a math error is responsible for >>> the slicing problem and STL errors. >>> >>> -Bob >>> >>> >>> include <BOSL2/std.scad> >>> include <BOSL2/structs.scad> >>> >>> // Number of Teeth >>> _n = 36; // Number Of Teeth >>> >>> // Inner Radius >>> _ir = 30; >>> // Outer Radius >>> _or = 50; >>> // Is the coupling conical? >>> _conic = 10; >>> // Tooth Profile Angle >>> _profile = 60; // [60, 90] >>> // Percentage of tooth height >>> _chamfer = 5; // Default 5% >>> _base = 1; >>> >>> $fn = 180; >>> tiny = 1 / 1024; >>> >>> hirth_concave(); >>> >>> _irRatio = _ir / _or; >>> _toothAngle = 360/_n; >>> _toothHeight = (sin(_toothAngle/2) * _or) / tan(_profile/2); >>> _chamferHeight = _chamfer * _toothHeight / 100; >>> _grooveAngle = atan(((_toothHeight/2) + _conic) / _or); >>> _ridgeAngle = -atan(((_toothHeight/2) - _conic) / _or); >>> _innerCenterLine = (1 - _irRatio) * _conic; >>> _stackHeight = _innerCenterLine + _toothHeight + 2*_base; >>> _tubeHeight = 2*_conic + 2*_base + 2*_toothHeight; >>> >>> module hirth_concave() { >>> zrot(_toothAngle/2) >>> union() { >>> difference() { >>> intersection() { >>> union() { >>> for (i = [0 : 360/_n : 359]) >>> zrot(i) >>> _profileF(); >>> } >>> tube(ir = _ir, or = _or, anchor = CENTER, l = >>> _tubeHeight, orient = UP, $fn = 16*360); >>> } >>> _chamferF(); >>> zcyl(r = _ir, h = _tubeHeight, $fn = 16*360, anchor = >>> CENTER); >>> } >>> _baseF(); >>> } >>> } // hirth_concave >>> >>> module _profileF() { >>> IR = _ir * .5; >>> OR = _or * 1.5; >>> tI = [spherical_to_xyz(IR, 0, _grooveAngle + 90), >>> spherical_to_xyz(IR, _toothAngle/2, _ridgeAngle + 90), >>> spherical_to_xyz(IR, -_toothAngle/2, _ridgeAngle + 90)]; >>> >>> tO = [spherical_to_xyz(OR, 0, _grooveAngle + 90), >>> spherical_to_xyz(OR, _toothAngle/2, _ridgeAngle + 90), >>> spherical_to_xyz(OR, -_toothAngle/2, _ridgeAngle + 90)]; >>> up(_conic) >>> skin([tI, tO], slices = 0); >>> } >>> >>> >>> module _chamferF() { >>> A = -_toothHeight/2 - .1; >>> B = -_toothHeight/2 + _chamferHeight; >>> >>> pts = [[0, _conic], >>> [_or+tiny, A], >>> [_or+tiny, B]]; >>> >>> rotate_extrude(angle = 360, $fn = 16*360) >>> polygon(pts); >>> } >>> >>> module _baseF() { >>> A = _base + _irRatio*_toothHeight/2 + _innerCenterLine; >>> B = _irRatio * (_toothHeight/2 - _chamferHeight/2) + >>> _innerCenterLine; >>> C = _toothHeight/2 - _chamferHeight/2; >>> pts = [ >>> [_ir, A], >>> [_ir, B], >>> [_or, C], >>> [_or, A] >>> ]; >>> >>> rotate_extrude(angle = 360, $fn = 360*16) >>> polygon(pts); >>> } >>> _______________________________________________ >>> 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
Sat, Oct 26, 2024 9:42 PM

Maybe I misunderstand, but I don’t think it is at all the same. Doesn't your method require me to calculate the exact location of the vertices? Those at the chamfers are particularly complicated. The teeth are simple projections of a triangle. However the location of the points on the outer (and inner) periphery of the teeth are the points where the tooth intersects a cylinder. So, that outer triangle is not flat. It made my head hurt trying to figure out an easy way to get the shape right. Using diff or intersection with a cylinder let openSCAD do the nasty stuff for me.

I haven’t looked into it, but perhaps you can do all the same intersections and diffs with polyhedrons and then my method would roughly work with polyhedrons as well. However, it would take thousand of shorter renders to get back the time it would take to convert it.

As it is I went through at least 4 different methods of generating the teeth. I was delighted to discover skin() which along with spherical coordinates made it straightforward. I also went through several iterations of generating the base. The convex part base was easy, the concave base was not at all. The chamfer was pretty easy. Most of these were motivated not by performance, but by ease of understanding by me.

I’m now in the process of making the parts attachable and setting up the custom anchors. You should see an enhancement request in BOSL2 soon.

-Bob

On Oct 26, 2024, at 12:08, Adrian Mariano avm4@cornell.edu wrote:

The math is the same. You just accumulate a point list in your for loop instead of looping over geometry.  You have timing of 4s and then 53s which sounds sort of slow.

On Sat, Oct 26, 2024 at 14:45 Bob Carlson <bob@rjcarlson.com mailto:bob@rjcarlson.com> wrote:

As I understand it, the math for that would be way beyond what I want to tax my brain with. In any case I am not concerned with performance. It’s fine as is.

-Bob

On Oct 26, 2024, at 10:27, Adrian Mariano <avm4@cornell.edu mailto:avm4@cornell.edu> wrote:

This looks like a fairly simple shape and also sort of gear like. You will get the best performance if you make it as one polyhedron instead of making one tooth and turning it to geometry and replicating it after and adding chamfers after.  Make the tooth point array and then rotate the point list to make all the copies and use vnf_vertex_array one time at the end.  It will run in 0.1 s

On Sat, Oct 26, 2024 at 12:57 Bob Carlson via Discuss <discuss@lists.openscad.org mailto:discuss@lists.openscad.org> wrote:

<PastedGraphic-1.png>

This second picture shows some visual aids I have in my code to show the center lines, the origin and the groove and ridge angles.

<PastedGraphic-2.png>

On Oct 25, 2024, at 17:04, Sanjeev Prabhakar <sprabhakar2006@gmail.com mailto:sprabhakar2006@gmail.com> wrote:

Can you post a picture of this

I will try this as well in python.

It may not interest you but just want see how tough this is to model

On Sat, 26 Oct, 2024, 5:15 am Bob Carlson via Discuss, <discuss@lists.openscad.org mailto:discuss@lists.openscad.org> wrote:

I got really intrigued by the Hirth joint and have been working a library entry that would generate them. I have it fully working, apparently, because it renders perfectly as far as I can see. However when I load one of the parts (a concave part) into PrusaSlicer, it reports thousands of errors that it supposedly fixed. The visual rendering is fine, but when you look at the slice it is completely screwed up.

First some explanation. When I looked up hirth joints I only saw flat ones mentioned. The one I have actually encountered though is a conical one. There is a concave part and a convex part. They fit together perfectly. I had to invent some terminology since I did not find terms for some things I found to be important. The outer center line is the plane that passes through the midpoint of the teeth at the outer radius. In a flat hirth joint all the teeth radiate from the center of this circle, call it the origin. If the origin of the teeth is above the outer center line, then joint has a conical shape and the two parts are concave and convex.

Each tooth at every point has the same profile, the top of the tooth profile is either 60 or 90 degrees. The groove angle is the angle that the groove forms from the origin to the outer radius. It will pass below (for a convex part) the outer radius. It’s critical for making hirth joints because it forms the tool path. The ridge angle is the angle formed by the corresponding ridge.

If the joint is conical, then there is an inner center line that passes through the center of the teeth at the inner radius. The tooth height is the critical number to calculate. It is dependent on the number of teeth, the profile angle and the inner and out radii. Something that really complicates the mental gymnastics is that the tooth height is smaller at the inner radius. My code adds a “base” of extra material at the bottom of the convex part and the top of the concave part. What’s tricky is positioning the base of the concave part relative to the inner center line. The concave parts base is relatively easy to place because it depends on the outer radius and center line.

I generate the raw teeth using the groove and ridge angles and spherical coordinates to make two 2d tooth profiles. Then I complete a tooth using skin(). A for loop generates the full set of N teeth. Then intersection or difference is used the trim the teeth at the inner and outer radii. I discovered something at that point, but solved it pretty simply. When diffing a cylinder from the N teeth, each tooth took up a small portion of the cylinder being diffed out. I had to raise the $fn on the cylinder or tube being used so that I got enough points in each tooth that diff or intersection was accurate. I kept raising it until the results stopped improving. I ended up with the 16*360 you see in the code.

After I have the raw teeth, I generate a cone that is diffed away to produce the chamfer at the top of the teeth. Then I add in the base. The base also adds the “chamfer” at the bottom of the groove. It’s half the size of the top chamfer to leave a little gap when the parts are joined.

When I comment out the everything but the raw teeth and import the STL into PrusaSlicer, it reports errors fixed, but appears to slice correctly when supports are added.

When I add the intersection to trim the raw teeth, the number of reported errors goes way up.

When I add the diff to remove the chamfer, the number goes way up again.

When I add in the base, the number goes up again and it starts reporting many open edges.

Throughout, OpenSCAD reports no errors. Using $fn at 16360, manifold renders in 4+ seconds. At 32360, it’s 53+ seconds. I did check CSG and it did not help.

Maybe the biggest hint is that the convex part uses almost identical code, but produces no errors. Very weird.

So, is this an OpenSCAD problem? Or something in my code?

It’s also possible that my math is off somewhere. My formal trig training was 60 years ago. However I doubt a math error is responsible for the slicing problem and STL errors.

-Bob

include <BOSL2/std.scad>
include <BOSL2/structs.scad>

// Number of Teeth
_n = 36;          // Number Of Teeth

// Inner Radius
_ir = 30;
// Outer Radius
_or = 50;
// Is the coupling conical?
_conic = 10;
// Tooth Profile Angle
_profile = 60; // [60, 90]
// Percentage of tooth height
_chamfer = 5; // Default 5%
_base = 1;

$fn = 180;
tiny = 1 / 1024;

hirth_concave();

_irRatio = _ir / _or;
_toothAngle = 360/_n;
_toothHeight = (sin(_toothAngle/2) * _or) / tan(_profile/2);
_chamferHeight = _chamfer * _toothHeight / 100;
_grooveAngle =  atan(((_toothHeight/2) + _conic) / _or);
_ridgeAngle = -atan(((_toothHeight/2) - _conic) / _or);
_innerCenterLine = (1 - _irRatio) * _conic;
_stackHeight  = _innerCenterLine + _toothHeight + 2*_base;
_tubeHeight = 2*_conic + 2*_base + 2*_toothHeight;

module hirth_concave() {
zrot(_toothAngle/2)
union() {
difference() {
intersection() {
union() {
for (i = [0 : 360/_n : 359])
zrot(i)
_profileF();
}
tube(ir = _ir, or = _or, anchor = CENTER, l = _tubeHeight, orient = UP, $fn = 16360);
}
_chamferF();
zcyl(r = _ir, h = _tubeHeight, $fn = 16
360, anchor = CENTER);
}
_baseF();
}
} // hirth_concave

module _profileF() {
IR = _ir * .5;
OR = _or * 1.5;
tI = [spherical_to_xyz(IR,  0,            _grooveAngle + 90),
spherical_to_xyz(IR,  _toothAngle/2, _ridgeAngle + 90),
spherical_to_xyz(IR, -_toothAngle/2, _ridgeAngle + 90)];

 tO = [spherical_to_xyz(OR,   0,            _grooveAngle + 90),
       spherical_to_xyz(OR,  _toothAngle/2, _ridgeAngle + 90),
       spherical_to_xyz(OR, -_toothAngle/2, _ridgeAngle + 90)];
 up(_conic)
 skin([tI, tO], slices = 0);

}

module _chamferF() {
A = -_toothHeight/2 - .1;
B = -_toothHeight/2 + _chamferHeight;

 pts = [[0, _conic], 
        [_or+tiny, A], 
        [_or+tiny, B]];

 rotate_extrude(angle = 360, $fn = 16*360)
 polygon(pts);

}

module _baseF() {
A = _base + _irRatio*_toothHeight/2 + _innerCenterLine;
B = _irRatio * (_toothHeight/2 - _chamferHeight/2) + _innerCenterLine;
C = _toothHeight/2 - _chamferHeight/2;
pts = [
[_ir, A],
[_ir, B],
[_or, C],
[_or, A]
];

 rotate_extrude(angle = 360, $fn = 360*16)
 polygon(pts);

}


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

Maybe I misunderstand, but I don’t think it is at all the same. Doesn't your method require me to calculate the exact location of the vertices? Those at the chamfers are particularly complicated. The teeth are simple projections of a triangle. However the location of the points on the outer (and inner) periphery of the teeth are the points where the tooth intersects a cylinder. So, that outer triangle is not flat. It made my head hurt trying to figure out an easy way to get the shape right. Using diff or intersection with a cylinder let openSCAD do the nasty stuff for me. I haven’t looked into it, but perhaps you can do all the same intersections and diffs with polyhedrons and then my method would roughly work with polyhedrons as well. However, it would take thousand of shorter renders to get back the time it would take to convert it. As it is I went through at least 4 different methods of generating the teeth. I was delighted to discover skin() which along with spherical coordinates made it straightforward. I also went through several iterations of generating the base. The convex part base was easy, the concave base was not at all. The chamfer was pretty easy. Most of these were motivated not by performance, but by ease of understanding by me. I’m now in the process of making the parts attachable and setting up the custom anchors. You should see an enhancement request in BOSL2 soon. -Bob > On Oct 26, 2024, at 12:08, Adrian Mariano <avm4@cornell.edu> wrote: > > The math is the same. You just accumulate a point list in your for loop instead of looping over geometry. You have timing of 4s and then 53s which sounds sort of slow. > > On Sat, Oct 26, 2024 at 14:45 Bob Carlson <bob@rjcarlson.com <mailto:bob@rjcarlson.com>> wrote: >> As I understand it, the math for that would be way beyond what I want to tax my brain with. In any case I am not concerned with performance. It’s fine as is. >> >> -Bob >> >>> On Oct 26, 2024, at 10:27, Adrian Mariano <avm4@cornell.edu <mailto:avm4@cornell.edu>> wrote: >>> >>> This looks like a fairly simple shape and also sort of gear like. You will get the best performance if you make it as one polyhedron instead of making one tooth and turning it to geometry and replicating it after and adding chamfers after. Make the tooth point array and then rotate the point list to make all the copies and use vnf_vertex_array one time at the end. It will run in 0.1 s >>> >>> On Sat, Oct 26, 2024 at 12:57 Bob Carlson via Discuss <discuss@lists.openscad.org <mailto:discuss@lists.openscad.org>> wrote: >>>> <PastedGraphic-1.png> >>>> >>>> This second picture shows some visual aids I have in my code to show the center lines, the origin and the groove and ridge angles. >>>> >>>> <PastedGraphic-2.png> >> >>>> >>>>> On Oct 25, 2024, at 17:04, Sanjeev Prabhakar <sprabhakar2006@gmail.com <mailto:sprabhakar2006@gmail.com>> wrote: >>>>> >>>>> Can you post a picture of this >>>>> >>>>> I will try this as well in python. >>>>> >>>>> It may not interest you but just want see how tough this is to model >>>>> >>>>> On Sat, 26 Oct, 2024, 5:15 am Bob Carlson via Discuss, <discuss@lists.openscad.org <mailto:discuss@lists.openscad.org>> wrote: >>>>>> I got really intrigued by the Hirth joint and have been working a library entry that would generate them. I have it fully working, apparently, because it renders perfectly as far as I can see. However when I load one of the parts (a concave part) into PrusaSlicer, it reports thousands of errors that it supposedly fixed. The visual rendering is fine, but when you look at the slice it is completely screwed up. >>>>>> >>>>>> First some explanation. When I looked up hirth joints I only saw flat ones mentioned. The one I have actually encountered though is a conical one. There is a concave part and a convex part. They fit together perfectly. I had to invent some terminology since I did not find terms for some things I found to be important. The outer center line is the plane that passes through the midpoint of the teeth at the outer radius. In a flat hirth joint all the teeth radiate from the center of this circle, call it the origin. If the origin of the teeth is above the outer center line, then joint has a conical shape and the two parts are concave and convex. >>>>>> >>>>>> Each tooth at every point has the same profile, the top of the tooth profile is either 60 or 90 degrees. The groove angle is the angle that the groove forms from the origin to the outer radius. It will pass below (for a convex part) the outer radius. It’s critical for making hirth joints because it forms the tool path. The ridge angle is the angle formed by the corresponding ridge. >>>>>> >>>>>> If the joint is conical, then there is an inner center line that passes through the center of the teeth at the inner radius. The tooth height is the critical number to calculate. It is dependent on the number of teeth, the profile angle and the inner and out radii. Something that really complicates the mental gymnastics is that the tooth height is smaller at the inner radius. My code adds a “base” of extra material at the bottom of the convex part and the top of the concave part. What’s tricky is positioning the base of the concave part relative to the inner center line. The concave parts base is relatively easy to place because it depends on the outer radius and center line. >>>>>> >>>>>> I generate the raw teeth using the groove and ridge angles and spherical coordinates to make two 2d tooth profiles. Then I complete a tooth using skin(). A for loop generates the full set of N teeth. Then intersection or difference is used the trim the teeth at the inner and outer radii. I discovered something at that point, but solved it pretty simply. When diffing a cylinder from the N teeth, each tooth took up a small portion of the cylinder being diffed out. I had to raise the $fn on the cylinder or tube being used so that I got enough points in each tooth that diff or intersection was accurate. I kept raising it until the results stopped improving. I ended up with the 16*360 you see in the code. >>>>>> >>>>>> After I have the raw teeth, I generate a cone that is diffed away to produce the chamfer at the top of the teeth. Then I add in the base. The base also adds the “chamfer” at the bottom of the groove. It’s half the size of the top chamfer to leave a little gap when the parts are joined. >>>>>> >>>>>> When I comment out the everything but the raw teeth and import the STL into PrusaSlicer, it reports errors fixed, but appears to slice correctly when supports are added. >>>>>> >>>>>> When I add the intersection to trim the raw teeth, the number of reported errors goes way up. >>>>>> >>>>>> When I add the diff to remove the chamfer, the number goes way up again. >>>>>> >>>>>> When I add in the base, the number goes up again and it starts reporting many open edges. >>>>>> >>>>>> Throughout, OpenSCAD reports no errors. Using $fn at 16*360, manifold renders in 4+ seconds. At 32*360, it’s 53+ seconds. I did check CSG and it did not help. >>>>>> >>>>>> Maybe the biggest hint is that the convex part uses almost identical code, but produces no errors. Very weird. >>>>>> >>>>>> So, is this an OpenSCAD problem? Or something in my code? >>>>>> >>>>>> It’s also possible that my math is off somewhere. My formal trig training was 60 years ago. However I doubt a math error is responsible for the slicing problem and STL errors. >>>>>> >>>>>> -Bob >>>>>> >>>>>> >>>>>> include <BOSL2/std.scad> >>>>>> include <BOSL2/structs.scad> >>>>>> >>>>>> // Number of Teeth >>>>>> _n = 36; // Number Of Teeth >>>>>> >>>>>> // Inner Radius >>>>>> _ir = 30; >>>>>> // Outer Radius >>>>>> _or = 50; >>>>>> // Is the coupling conical? >>>>>> _conic = 10; >>>>>> // Tooth Profile Angle >>>>>> _profile = 60; // [60, 90] >>>>>> // Percentage of tooth height >>>>>> _chamfer = 5; // Default 5% >>>>>> _base = 1; >>>>>> >>>>>> $fn = 180; >>>>>> tiny = 1 / 1024; >>>>>> >>>>>> hirth_concave(); >>>>>> >>>>>> _irRatio = _ir / _or; >>>>>> _toothAngle = 360/_n; >>>>>> _toothHeight = (sin(_toothAngle/2) * _or) / tan(_profile/2); >>>>>> _chamferHeight = _chamfer * _toothHeight / 100; >>>>>> _grooveAngle = atan(((_toothHeight/2) + _conic) / _or); >>>>>> _ridgeAngle = -atan(((_toothHeight/2) - _conic) / _or); >>>>>> _innerCenterLine = (1 - _irRatio) * _conic; >>>>>> _stackHeight = _innerCenterLine + _toothHeight + 2*_base; >>>>>> _tubeHeight = 2*_conic + 2*_base + 2*_toothHeight; >>>>>> >>>>>> module hirth_concave() { >>>>>> zrot(_toothAngle/2) >>>>>> union() { >>>>>> difference() { >>>>>> intersection() { >>>>>> union() { >>>>>> for (i = [0 : 360/_n : 359]) >>>>>> zrot(i) >>>>>> _profileF(); >>>>>> } >>>>>> tube(ir = _ir, or = _or, anchor = CENTER, l = _tubeHeight, orient = UP, $fn = 16*360); >>>>>> } >>>>>> _chamferF(); >>>>>> zcyl(r = _ir, h = _tubeHeight, $fn = 16*360, anchor = CENTER); >>>>>> } >>>>>> _baseF(); >>>>>> } >>>>>> } // hirth_concave >>>>>> >>>>>> module _profileF() { >>>>>> IR = _ir * .5; >>>>>> OR = _or * 1.5; >>>>>> tI = [spherical_to_xyz(IR, 0, _grooveAngle + 90), >>>>>> spherical_to_xyz(IR, _toothAngle/2, _ridgeAngle + 90), >>>>>> spherical_to_xyz(IR, -_toothAngle/2, _ridgeAngle + 90)]; >>>>>> >>>>>> tO = [spherical_to_xyz(OR, 0, _grooveAngle + 90), >>>>>> spherical_to_xyz(OR, _toothAngle/2, _ridgeAngle + 90), >>>>>> spherical_to_xyz(OR, -_toothAngle/2, _ridgeAngle + 90)]; >>>>>> up(_conic) >>>>>> skin([tI, tO], slices = 0); >>>>>> } >>>>>> >>>>>> >>>>>> module _chamferF() { >>>>>> A = -_toothHeight/2 - .1; >>>>>> B = -_toothHeight/2 + _chamferHeight; >>>>>> >>>>>> pts = [[0, _conic], >>>>>> [_or+tiny, A], >>>>>> [_or+tiny, B]]; >>>>>> >>>>>> rotate_extrude(angle = 360, $fn = 16*360) >>>>>> polygon(pts); >>>>>> } >>>>>> >>>>>> module _baseF() { >>>>>> A = _base + _irRatio*_toothHeight/2 + _innerCenterLine; >>>>>> B = _irRatio * (_toothHeight/2 - _chamferHeight/2) + _innerCenterLine; >>>>>> C = _toothHeight/2 - _chamferHeight/2; >>>>>> pts = [ >>>>>> [_ir, A], >>>>>> [_ir, B], >>>>>> [_or, C], >>>>>> [_or, A] >>>>>> ]; >>>>>> >>>>>> rotate_extrude(angle = 360, $fn = 360*16) >>>>>> polygon(pts); >>>>>> } >>>>>> _______________________________________________ >>>>>> 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> >>
BC
Bob Carlson
Sat, Oct 26, 2024 9:44 PM

Submitted to OpenSCAD as issue
https://github.com/openscad/openscad/issues/5391
Errors apparently produced while exporting .stl · Issue #5391 · openscad/openscad
github.com

-Bob

On Oct 25, 2024, at 16:44, Bob Carlson via Discuss discuss@lists.openscad.org wrote:

I got really intrigued by the Hirth joint and have been working a library entry that would generate them. I have it fully working, apparently, because it renders perfectly as far as I can see. However when I load one of the parts (a concave part) into PrusaSlicer, it reports thousands of errors that it supposedly fixed. The visual rendering is fine, but when you look at the slice it is completely screwed up.

First some explanation. When I looked up hirth joints I only saw flat ones mentioned. The one I have actually encountered though is a conical one. There is a concave part and a convex part. They fit together perfectly. I had to invent some terminology since I did not find terms for some things I found to be important. The outer center line is the plane that passes through the midpoint of the teeth at the outer radius. In a flat hirth joint all the teeth radiate from the center of this circle, call it the origin. If the origin of the teeth is above the outer center line, then joint has a conical shape and the two parts are concave and convex.

Each tooth at every point has the same profile, the top of the tooth profile is either 60 or 90 degrees. The groove angle is the angle that the groove forms from the origin to the outer radius. It will pass below (for a convex part) the outer radius. It’s critical for making hirth joints because it forms the tool path. The ridge angle is the angle formed by the corresponding ridge.

If the joint is conical, then there is an inner center line that passes through the center of the teeth at the inner radius. The tooth height is the critical number to calculate. It is dependent on the number of teeth, the profile angle and the inner and out radii. Something that really complicates the mental gymnastics is that the tooth height is smaller at the inner radius. My code adds a “base” of extra material at the bottom of the convex part and the top of the concave part. What’s tricky is positioning the base of the concave part relative to the inner center line. The concave parts base is relatively easy to place because it depends on the outer radius and center line.

I generate the raw teeth using the groove and ridge angles and spherical coordinates to make two 2d tooth profiles. Then I complete a tooth using skin(). A for loop generates the full set of N teeth. Then intersection or difference is used the trim the teeth at the inner and outer radii. I discovered something at that point, but solved it pretty simply. When diffing a cylinder from the N teeth, each tooth took up a small portion of the cylinder being diffed out. I had to raise the $fn on the cylinder or tube being used so that I got enough points in each tooth that diff or intersection was accurate. I kept raising it until the results stopped improving. I ended up with the 16*360 you see in the code.

After I have the raw teeth, I generate a cone that is diffed away to produce the chamfer at the top of the teeth. Then I add in the base. The base also adds the “chamfer” at the bottom of the groove. It’s half the size of the top chamfer to leave a little gap when the parts are joined.

When I comment out the everything but the raw teeth and import the STL into PrusaSlicer, it reports errors fixed, but appears to slice correctly when supports are added.

When I add the intersection to trim the raw teeth, the number of reported errors goes way up.

When I add the diff to remove the chamfer, the number goes way up again.

When I add in the base, the number goes up again and it starts reporting many open edges.

Throughout, OpenSCAD reports no errors. Using $fn at 16360, manifold renders in 4+ seconds. At 32360, it’s 53+ seconds. I did check CSG and it did not help.

Maybe the biggest hint is that the convex part uses almost identical code, but produces no errors. Very weird.

So, is this an OpenSCAD problem? Or something in my code?

It’s also possible that my math is off somewhere. My formal trig training was 60 years ago. However I doubt a math error is responsible for the slicing problem and STL errors.

-Bob

include <BOSL2/std.scad>
include <BOSL2/structs.scad>

// Number of Teeth
_n = 36;          // Number Of Teeth

// Inner Radius
_ir = 30;
// Outer Radius
_or = 50;
// Is the coupling conical?
_conic = 10;
// Tooth Profile Angle
_profile = 60; // [60, 90]
// Percentage of tooth height
_chamfer = 5; // Default 5%
_base = 1;

$fn = 180;
tiny = 1 / 1024;

hirth_concave();

_irRatio = _ir / _or;
_toothAngle = 360/_n;
_toothHeight = (sin(_toothAngle/2) * _or) / tan(_profile/2);
_chamferHeight = _chamfer * _toothHeight / 100;
_grooveAngle =  atan(((_toothHeight/2) + _conic) / _or);
_ridgeAngle = -atan(((_toothHeight/2) - _conic) / _or);
_innerCenterLine = (1 - _irRatio) * _conic;
_stackHeight  = _innerCenterLine + _toothHeight + 2*_base;
_tubeHeight = 2*_conic + 2*_base + 2*_toothHeight;

module hirth_concave() {
zrot(_toothAngle/2)
union() {
difference() {
intersection() {
union() {
for (i = [0 : 360/_n : 359])
zrot(i)
_profileF();
}
tube(ir = _ir, or = _or, anchor = CENTER, l = _tubeHeight, orient = UP, $fn = 16360);
}
_chamferF();
zcyl(r = _ir, h = _tubeHeight, $fn = 16
360, anchor = CENTER);
}
_baseF();
}
} // hirth_concave

module _profileF() {
IR = _ir * .5;
OR = _or * 1.5;
tI = [spherical_to_xyz(IR,  0,            _grooveAngle + 90),
spherical_to_xyz(IR,  _toothAngle/2, _ridgeAngle + 90),
spherical_to_xyz(IR, -_toothAngle/2, _ridgeAngle + 90)];

tO = [spherical_to_xyz(OR,   0,            _grooveAngle + 90),
      spherical_to_xyz(OR,  _toothAngle/2, _ridgeAngle + 90),
      spherical_to_xyz(OR, -_toothAngle/2, _ridgeAngle + 90)];
up(_conic)
skin([tI, tO], slices = 0);

}

module _chamferF() {
A = -_toothHeight/2 - .1;
B = -_toothHeight/2 + _chamferHeight;

pts = [[0, _conic], 
       [_or+tiny, A], 
       [_or+tiny, B]];

rotate_extrude(angle = 360, $fn = 16*360)
polygon(pts);

}

module _baseF() {
A = _base + _irRatio*_toothHeight/2 + _innerCenterLine;
B = _irRatio * (_toothHeight/2 - _chamferHeight/2) + _innerCenterLine;
C = _toothHeight/2 - _chamferHeight/2;
pts = [
[_ir, A],
[_ir, B],
[_or, C],
[_or, A]
];

rotate_extrude(angle = 360, $fn = 360*16)
polygon(pts);

}


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

Submitted to OpenSCAD as issue https://github.com/openscad/openscad/issues/5391 Errors apparently produced while exporting .stl · Issue #5391 · openscad/openscad github.com -Bob > On Oct 25, 2024, at 16:44, Bob Carlson via Discuss <discuss@lists.openscad.org> wrote: > > I got really intrigued by the Hirth joint and have been working a library entry that would generate them. I have it fully working, apparently, because it renders perfectly as far as I can see. However when I load one of the parts (a concave part) into PrusaSlicer, it reports thousands of errors that it supposedly fixed. The visual rendering is fine, but when you look at the slice it is completely screwed up. > > First some explanation. When I looked up hirth joints I only saw flat ones mentioned. The one I have actually encountered though is a conical one. There is a concave part and a convex part. They fit together perfectly. I had to invent some terminology since I did not find terms for some things I found to be important. The outer center line is the plane that passes through the midpoint of the teeth at the outer radius. In a flat hirth joint all the teeth radiate from the center of this circle, call it the origin. If the origin of the teeth is above the outer center line, then joint has a conical shape and the two parts are concave and convex. > > Each tooth at every point has the same profile, the top of the tooth profile is either 60 or 90 degrees. The groove angle is the angle that the groove forms from the origin to the outer radius. It will pass below (for a convex part) the outer radius. It’s critical for making hirth joints because it forms the tool path. The ridge angle is the angle formed by the corresponding ridge. > > If the joint is conical, then there is an inner center line that passes through the center of the teeth at the inner radius. The tooth height is the critical number to calculate. It is dependent on the number of teeth, the profile angle and the inner and out radii. Something that really complicates the mental gymnastics is that the tooth height is smaller at the inner radius. My code adds a “base” of extra material at the bottom of the convex part and the top of the concave part. What’s tricky is positioning the base of the concave part relative to the inner center line. The concave parts base is relatively easy to place because it depends on the outer radius and center line. > > I generate the raw teeth using the groove and ridge angles and spherical coordinates to make two 2d tooth profiles. Then I complete a tooth using skin(). A for loop generates the full set of N teeth. Then intersection or difference is used the trim the teeth at the inner and outer radii. I discovered something at that point, but solved it pretty simply. When diffing a cylinder from the N teeth, each tooth took up a small portion of the cylinder being diffed out. I had to raise the $fn on the cylinder or tube being used so that I got enough points in each tooth that diff or intersection was accurate. I kept raising it until the results stopped improving. I ended up with the 16*360 you see in the code. > > After I have the raw teeth, I generate a cone that is diffed away to produce the chamfer at the top of the teeth. Then I add in the base. The base also adds the “chamfer” at the bottom of the groove. It’s half the size of the top chamfer to leave a little gap when the parts are joined. > > When I comment out the everything but the raw teeth and import the STL into PrusaSlicer, it reports errors fixed, but appears to slice correctly when supports are added. > > When I add the intersection to trim the raw teeth, the number of reported errors goes way up. > > When I add the diff to remove the chamfer, the number goes way up again. > > When I add in the base, the number goes up again and it starts reporting many open edges. > > Throughout, OpenSCAD reports no errors. Using $fn at 16*360, manifold renders in 4+ seconds. At 32*360, it’s 53+ seconds. I did check CSG and it did not help. > > Maybe the biggest hint is that the convex part uses almost identical code, but produces no errors. Very weird. > > So, is this an OpenSCAD problem? Or something in my code? > > It’s also possible that my math is off somewhere. My formal trig training was 60 years ago. However I doubt a math error is responsible for the slicing problem and STL errors. > > -Bob > > > include <BOSL2/std.scad> > include <BOSL2/structs.scad> > > // Number of Teeth > _n = 36; // Number Of Teeth > > // Inner Radius > _ir = 30; > // Outer Radius > _or = 50; > // Is the coupling conical? > _conic = 10; > // Tooth Profile Angle > _profile = 60; // [60, 90] > // Percentage of tooth height > _chamfer = 5; // Default 5% > _base = 1; > > $fn = 180; > tiny = 1 / 1024; > > hirth_concave(); > > _irRatio = _ir / _or; > _toothAngle = 360/_n; > _toothHeight = (sin(_toothAngle/2) * _or) / tan(_profile/2); > _chamferHeight = _chamfer * _toothHeight / 100; > _grooveAngle = atan(((_toothHeight/2) + _conic) / _or); > _ridgeAngle = -atan(((_toothHeight/2) - _conic) / _or); > _innerCenterLine = (1 - _irRatio) * _conic; > _stackHeight = _innerCenterLine + _toothHeight + 2*_base; > _tubeHeight = 2*_conic + 2*_base + 2*_toothHeight; > > module hirth_concave() { > zrot(_toothAngle/2) > union() { > difference() { > intersection() { > union() { > for (i = [0 : 360/_n : 359]) > zrot(i) > _profileF(); > } > tube(ir = _ir, or = _or, anchor = CENTER, l = _tubeHeight, orient = UP, $fn = 16*360); > } > _chamferF(); > zcyl(r = _ir, h = _tubeHeight, $fn = 16*360, anchor = CENTER); > } > _baseF(); > } > } // hirth_concave > > module _profileF() { > IR = _ir * .5; > OR = _or * 1.5; > tI = [spherical_to_xyz(IR, 0, _grooveAngle + 90), > spherical_to_xyz(IR, _toothAngle/2, _ridgeAngle + 90), > spherical_to_xyz(IR, -_toothAngle/2, _ridgeAngle + 90)]; > > tO = [spherical_to_xyz(OR, 0, _grooveAngle + 90), > spherical_to_xyz(OR, _toothAngle/2, _ridgeAngle + 90), > spherical_to_xyz(OR, -_toothAngle/2, _ridgeAngle + 90)]; > up(_conic) > skin([tI, tO], slices = 0); > } > > > module _chamferF() { > A = -_toothHeight/2 - .1; > B = -_toothHeight/2 + _chamferHeight; > > pts = [[0, _conic], > [_or+tiny, A], > [_or+tiny, B]]; > > rotate_extrude(angle = 360, $fn = 16*360) > polygon(pts); > } > > module _baseF() { > A = _base + _irRatio*_toothHeight/2 + _innerCenterLine; > B = _irRatio * (_toothHeight/2 - _chamferHeight/2) + _innerCenterLine; > C = _toothHeight/2 - _chamferHeight/2; > pts = [ > [_ir, A], > [_ir, B], > [_or, C], > [_or, A] > ]; > > rotate_extrude(angle = 360, $fn = 360*16) > polygon(pts); > } > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org
JB
Jordan Brown
Sat, Oct 26, 2024 11:21 PM

I notice that your _profileF() ends up generating an inside-out
polyhedron.  When viewed with View/Thrown Together, it's purple.  That
can cause problems for rendering.  (I'm a little surprised that it
didn't cause fatal problems.)  It looks like you can fix it by swapping
the second and third points in both tI and tO.

Another thing attracted my attention immediately.

Mostly, just don't use $fn except to create regular polygons.  Use $fs
and $fa; they are much less likely to lead you into silly settings.

You have $fn=16*360 = 5760.  Assuming that the units are millimeters,
the model is about 100mm in diameter, so its circumference is 314mm. 
That means that each side is 0.05mm.  Those tiny sides, and the even
tinier artifacts that they might cause, might well be a key part of your
geometry problems.  My bet is that you could use fewer than 100 sides
and still be unable to see or feel the individual sides when you print
it.  And if you can see them, bump it up to 300 or 500, and you've still
got 10x fewer sides than your version does.

Preview is (at least for me) horribly laggy when you try to move it, and
it has what look like convexity artifacts.

Removing all of the settings for $fn and adding in a single global
setting for $fa=1 and $fs=1, and it previews fast and fixes the
convexity artifacts.

Also, a tidbit:  _chamferF() generates a conical figure that might as
well be a cone. 

    up(_conic + _chamferHeight) scale(1.5) zcyl(h = _toothHeight/2 + _conic, r1 = _or, r2 = 0, anchor=TOP);

Since it's anchored at the top, I didn't have to fiddle with making sure
that it was slightly larger than the thing it's cutting from and could
just scale it up a bit.

I think your technique is responsible for generating micro flaws at the
outside edges.


Note:  I first tried this mod while I happened to be running an OpenSCAD
from January.  With my changes, rendering failed with manifold errors. 
When I switched to a recent build, it was OK again.  So if you're having
manifold problems, upgrade.

I notice that your _profileF() ends up generating an inside-out polyhedron.  When viewed with View/Thrown Together, it's purple.  That can cause problems for rendering.  (I'm a little surprised that it didn't cause fatal problems.)  It looks like you can fix it by swapping the second and third points in both tI and tO. Another thing attracted my attention immediately. Mostly, just don't use $fn except to create regular polygons.  Use $fs and $fa; they are much less likely to lead you into silly settings. You have $fn=16*360 = 5760.  Assuming that the units are millimeters, the model is about 100mm in diameter, so its circumference is 314mm.  That means that each side is 0.05mm.  Those tiny sides, and the even tinier artifacts that they might cause, might well be a key part of your geometry problems.  My bet is that you could use fewer than 100 sides and still be unable to see or feel the individual sides when you print it.  And if you can see them, bump it up to 300 or 500, and you've still got 10x fewer sides than your version does. Preview is (at least for me) horribly laggy when you try to move it, and it has what look like convexity artifacts. Removing all of the settings for $fn and adding in a single global setting for $fa=1 and $fs=1, and it previews fast and fixes the convexity artifacts. Also, a tidbit:  _chamferF() generates a conical figure that might as well be a cone.      up(_conic + _chamferHeight) scale(1.5) zcyl(h = _toothHeight/2 + _conic, r1 = _or, r2 = 0, anchor=TOP); Since it's anchored at the top, I didn't have to fiddle with making sure that it was slightly larger than the thing it's cutting from and could just scale it up a bit. I think your technique is responsible for generating micro flaws at the outside edges. --- Note:  I first tried this mod while I happened to be running an OpenSCAD from January.  With my changes, rendering failed with manifold errors.  When I switched to a recent build, it was OK again.  So if you're having manifold problems, upgrade.
BC
Bob Carlson
Sun, Oct 27, 2024 12:44 AM

Thanks! I hear about these point ordering problems. It seems a shame one has to deal with them. Why can’t they be fixed automatically?

-Bob

On Oct 26, 2024, at 16:21, Jordan Brown openscad@jordan.maileater.net wrote:

I notice that your _profileF() ends up generating an inside-out polyhedron.  When viewed with View/Thrown Together, it's purple.  That can cause problems for rendering.  (I'm a little surprised that it didn't cause fatal problems.)  It looks like you can fix it by swapping the second and third points in both tI and tO.

Another thing attracted my attention immediately.

Mostly, just don't use $fn except to create regular polygons.  Use $fs and $fa; they are much less likely to lead you into silly settings.

You have $fn=16*360 = 5760.  Assuming that the units are millimeters, the model is about 100mm in diameter, so its circumference is 314mm.  That means that each side is 0.05mm.  Those tiny sides, and the even tinier artifacts that they might cause, might well be a key part of your geometry problems.  My bet is that you could use fewer than 100 sides and still be unable to see or feel the individual sides when you print it.  And if you can see them, bump it up to 300 or 500, and you've still got 10x fewer sides than your version does.

Preview is (at least for me) horribly laggy when you try to move it, and it has what look like convexity artifacts.

Removing all of the settings for $fn and adding in a single global setting for $fa=1 and $fs=1, and it previews fast and fixes the convexity artifacts.

Also, a tidbit:  _chamferF() generates a conical figure that might as well be a cone.
up(_conic + _chamferHeight) scale(1.5) zcyl(h = _toothHeight/2 + _conic, r1 = _or, r2 = 0, anchor=TOP);
Since it's anchored at the top, I didn't have to fiddle with making sure that it was slightly larger than the thing it's cutting from and could just scale it up a bit.

I think your technique is responsible for generating micro flaws at the outside edges.
<YWbsxKvQ36n0OH8f.png>


Note:  I first tried this mod while I happened to be running an OpenSCAD from January.  With my changes, rendering failed with manifold errors.  When I switched to a recent build, it was OK again.  So if you're having manifold problems, upgrade.

Thanks! I hear about these point ordering problems. It seems a shame one has to deal with them. Why can’t they be fixed automatically? -Bob > On Oct 26, 2024, at 16:21, Jordan Brown <openscad@jordan.maileater.net> wrote: > > I notice that your _profileF() ends up generating an inside-out polyhedron. When viewed with View/Thrown Together, it's purple. That can cause problems for rendering. (I'm a little surprised that it didn't cause fatal problems.) It looks like you can fix it by swapping the second and third points in both tI and tO. > > > > Another thing attracted my attention immediately. > > Mostly, just don't use $fn except to create regular polygons. Use $fs and $fa; they are much less likely to lead you into silly settings. > > You have $fn=16*360 = 5760. Assuming that the units are millimeters, the model is about 100mm in diameter, so its circumference is 314mm. That means that each side is 0.05mm. Those tiny sides, and the even tinier artifacts that they might cause, might well be a key part of your geometry problems. My bet is that you could use fewer than 100 sides and still be unable to see or feel the individual sides when you print it. And if you can see them, bump it up to 300 or 500, and you've still got 10x fewer sides than your version does. > > Preview is (at least for me) horribly laggy when you try to move it, and it has what look like convexity artifacts. > > Removing all of the settings for $fn and adding in a single global setting for $fa=1 and $fs=1, and it previews fast and fixes the convexity artifacts. > > > > Also, a tidbit: _chamferF() generates a conical figure that might as well be a cone. > up(_conic + _chamferHeight) scale(1.5) zcyl(h = _toothHeight/2 + _conic, r1 = _or, r2 = 0, anchor=TOP); > Since it's anchored at the top, I didn't have to fiddle with making sure that it was slightly larger than the thing it's cutting from and could just scale it up a bit. > > I think your technique is responsible for generating micro flaws at the outside edges. > <YWbsxKvQ36n0OH8f.png> > > --- > Note: I first tried this mod while I happened to be running an OpenSCAD from January. With my changes, rendering failed with manifold errors. When I switched to a recent build, it was OK again. So if you're having manifold problems, upgrade.
SP
Sanjeev Prabhakar
Sun, Oct 27, 2024 2:50 AM

here is my version of this through python

https://youtu.be/Wp8q71eMqrE

On Sun, 27 Oct 2024 at 06:15, Bob Carlson via Discuss <
discuss@lists.openscad.org> wrote:

Thanks! I hear about these point ordering problems. It seems a shame one
has to deal with them. Why can’t they be fixed automatically?

-Bob

On Oct 26, 2024, at 16:21, Jordan Brown openscad@jordan.maileater.net

wrote:

I notice that your _profileF() ends up generating an inside-out

polyhedron.  When viewed with View/Thrown Together, it's purple.  That can
cause problems for rendering.  (I'm a little surprised that it didn't cause
fatal problems.)  It looks like you can fix it by swapping the second and
third points in both tI and tO.

Another thing attracted my attention immediately.

Mostly, just don't use $fn except to create regular polygons.  Use $fs

and $fa; they are much less likely to lead you into silly settings.

You have $fn=16*360 = 5760.  Assuming that the units are millimeters,

the model is about 100mm in diameter, so its circumference is 314mm.  That
means that each side is 0.05mm.  Those tiny sides, and the even tinier
artifacts that they might cause, might well be a key part of your geometry
problems.  My bet is that you could use fewer than 100 sides and still be
unable to see or feel the individual sides when you print it.  And if you
can see them, bump it up to 300 or 500, and you've still got 10x fewer
sides than your version does.

Preview is (at least for me) horribly laggy when you try to move it, and

it has what look like convexity artifacts.

Removing all of the settings for $fn and adding in a single global

setting for $fa=1 and $fs=1, and it previews fast and fixes the convexity
artifacts.

Also, a tidbit:  _chamferF() generates a conical figure that might as

well be a cone.

 up(_conic + _chamferHeight) scale(1.5) zcyl(h = _toothHeight/2 +

_conic, r1 = _or, r2 = 0, anchor=TOP);

Since it's anchored at the top, I didn't have to fiddle with making sure

that it was slightly larger than the thing it's cutting from and could just
scale it up a bit.

I think your technique is responsible for generating micro flaws at the

outside edges.

<YWbsxKvQ36n0OH8f.png>


Note:  I first tried this mod while I happened to be running an OpenSCAD

from January.  With my changes, rendering failed with manifold errors.
When I switched to a recent build, it was OK again.  So if you're having
manifold problems, upgrade.


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

here is my version of this through python https://youtu.be/Wp8q71eMqrE On Sun, 27 Oct 2024 at 06:15, Bob Carlson via Discuss < discuss@lists.openscad.org> wrote: > Thanks! I hear about these point ordering problems. It seems a shame one > has to deal with them. Why can’t they be fixed automatically? > > -Bob > > > On Oct 26, 2024, at 16:21, Jordan Brown <openscad@jordan.maileater.net> > wrote: > > > > I notice that your _profileF() ends up generating an inside-out > polyhedron. When viewed with View/Thrown Together, it's purple. That can > cause problems for rendering. (I'm a little surprised that it didn't cause > fatal problems.) It looks like you can fix it by swapping the second and > third points in both tI and tO. > > > > > > > > Another thing attracted my attention immediately. > > > > Mostly, just don't use $fn except to create regular polygons. Use $fs > and $fa; they are much less likely to lead you into silly settings. > > > > You have $fn=16*360 = 5760. Assuming that the units are millimeters, > the model is about 100mm in diameter, so its circumference is 314mm. That > means that each side is 0.05mm. Those tiny sides, and the even tinier > artifacts that they might cause, might well be a key part of your geometry > problems. My bet is that you could use fewer than 100 sides and still be > unable to see or feel the individual sides when you print it. And if you > can see them, bump it up to 300 or 500, and you've still got 10x fewer > sides than your version does. > > > > Preview is (at least for me) horribly laggy when you try to move it, and > it has what look like convexity artifacts. > > > > Removing all of the settings for $fn and adding in a single global > setting for $fa=1 and $fs=1, and it previews fast and fixes the convexity > artifacts. > > > > > > > > Also, a tidbit: _chamferF() generates a conical figure that might as > well be a cone. > > up(_conic + _chamferHeight) scale(1.5) zcyl(h = _toothHeight/2 + > _conic, r1 = _or, r2 = 0, anchor=TOP); > > Since it's anchored at the top, I didn't have to fiddle with making sure > that it was slightly larger than the thing it's cutting from and could just > scale it up a bit. > > > > I think your technique is responsible for generating micro flaws at the > outside edges. > > <YWbsxKvQ36n0OH8f.png> > > > > --- > > Note: I first tried this mod while I happened to be running an OpenSCAD > from January. With my changes, rendering failed with manifold errors. > When I switched to a recent build, it was OK again. So if you're having > manifold problems, upgrade. > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org >
JB
Jordan Brown
Sun, Oct 27, 2024 4:31 AM

On 10/26/2024 5:44 PM, Bob Carlson wrote:

Thanks! I hear about these point ordering problems. It seems a shame one has to deal with them. Why can’t they be fixed automatically?

I don't know for sure.

There are two levels to the question here:  first BOSL2 builds a
polyhedron, and then second OpenSCAD processes the polyhedron.

BOSL2 could generate the polyhedron "correctly".  I don't know how hard
that would be, but that's essentially what swapping the points does:  it
causes BOSL2 to build the polyhedron the other way 'round.  I don't know
enough about "skin" to know how easy it would be to detect being backwards.

And then when OpenSCAD receives the "inside-out" polyhedron, it could
perhaps fix it.  I think that if it's completely inside out then
detecting that and fixing it isn't hard.  (But right now I'm not sure
how to tell which way is "inside".)  If it's partially inside-out (like
one face is backwards)  then I think I know how to detect that, and I
guess that if you can detect it then you can flip faces until they are
all consistent, and then you might be inside-out but you've reduced it
to the case above.  So my not-a-geometry-wizard sense is that it's
doable.  (OCD note:  you need to watch out for Klein bottles, lest you
flip faces infinitely.)

Is anybody interested in spending the effort?  Obviously not so far. 
(And I think we can all agree that we'd rather have the geometry wizards
work on Manifold and its huge performance improvement.)

When I'm building a polyhedron, mostly I just turn on Thrown Together
and fix backward faces as required.  That's less of an imposition on DIY
polyhedra than it is when your polyhedron is coming out of a library.

On 10/26/2024 5:44 PM, Bob Carlson wrote: > Thanks! I hear about these point ordering problems. It seems a shame one has to deal with them. Why can’t they be fixed automatically? I don't know for sure. There are two levels to the question here:  first BOSL2 builds a polyhedron, and then second OpenSCAD processes the polyhedron. BOSL2 could generate the polyhedron "correctly".  I don't know how hard that would be, but that's essentially what swapping the points does:  it causes BOSL2 to build the polyhedron the other way 'round.  I don't know enough about "skin" to know how easy it would be to detect being backwards. And then when OpenSCAD receives the "inside-out" polyhedron, it could perhaps fix it.  I *think* that if it's completely inside out then detecting that and fixing it isn't hard.  (But right now I'm not sure how to tell which way is "inside".)  If it's partially inside-out (like one face is backwards)  then I think I know how to detect that, and I guess that if you can detect it then you can flip faces until they are all consistent, and then you might be inside-out but you've reduced it to the case above.  So my not-a-geometry-wizard sense is that it's doable.  (OCD note:  you need to watch out for Klein bottles, lest you flip faces infinitely.) Is anybody interested in spending the effort?  Obviously not so far.  (And I think we can all agree that we'd rather have the geometry wizards work on Manifold and its huge performance improvement.) When I'm building a polyhedron, mostly I just turn on Thrown Together and fix backward faces as required.  That's less of an imposition on DIY polyhedra than it is when your polyhedron is coming out of a library.
JD
John David
Sun, Oct 27, 2024 4:35 AM

Thank you, Jordan, I missed the email with the little spear points at the
bottom of the tooth profile, and the original pictures it was not clear
what the problem was.  This helps me look at what is going on...  The last
time I had something like this, I made a parametric profile and then
extruded it, and it worked around the issue.  Maybe a trick like that might
work to clean it up.  That said, your zoomed-in example might give folks a
go-to geometrical unit-test to track it down.  Not sure if there are
takers, but this should be archived as a potential debugging test.

Bob, I hear you.  If this is fit for your purpose, then it is "good
enough".  There comes a point where spending time fixing some things is a
diminishing returns game. I still think this should be formally submitted
in a bug report, and see if it can be reduced to 2 teeth profiles as the
whole of the part.  This would be small enough to be debuggable, and large
enough to expose the bug.

EBo --

On Sat, Oct 26, 2024 at 10:51 PM Sanjeev Prabhakar via Discuss <
discuss@lists.openscad.org> wrote:

here is my version of this through python

https://youtu.be/Wp8q71eMqrE

On Sun, 27 Oct 2024 at 06:15, Bob Carlson via Discuss <
discuss@lists.openscad.org> wrote:

Thanks! I hear about these point ordering problems. It seems a shame one
has to deal with them. Why can’t they be fixed automatically?

-Bob

On Oct 26, 2024, at 16:21, Jordan Brown openscad@jordan.maileater.net

wrote:

I notice that your _profileF() ends up generating an inside-out

polyhedron.  When viewed with View/Thrown Together, it's purple.  That can
cause problems for rendering.  (I'm a little surprised that it didn't cause
fatal problems.)  It looks like you can fix it by swapping the second and
third points in both tI and tO.

Another thing attracted my attention immediately.

Mostly, just don't use $fn except to create regular polygons.  Use $fs

and $fa; they are much less likely to lead you into silly settings.

You have $fn=16*360 = 5760.  Assuming that the units are millimeters,

the model is about 100mm in diameter, so its circumference is 314mm.  That
means that each side is 0.05mm.  Those tiny sides, and the even tinier
artifacts that they might cause, might well be a key part of your geometry
problems.  My bet is that you could use fewer than 100 sides and still be
unable to see or feel the individual sides when you print it.  And if you
can see them, bump it up to 300 or 500, and you've still got 10x fewer
sides than your version does.

Preview is (at least for me) horribly laggy when you try to move it,

and it has what look like convexity artifacts.

Removing all of the settings for $fn and adding in a single global

setting for $fa=1 and $fs=1, and it previews fast and fixes the convexity
artifacts.

Also, a tidbit:  _chamferF() generates a conical figure that might as

well be a cone.

 up(_conic + _chamferHeight) scale(1.5) zcyl(h = _toothHeight/2 +

_conic, r1 = _or, r2 = 0, anchor=TOP);

Since it's anchored at the top, I didn't have to fiddle with making

sure that it was slightly larger than the thing it's cutting from and could
just scale it up a bit.

I think your technique is responsible for generating micro flaws at the

outside edges.

<YWbsxKvQ36n0OH8f.png>


Note:  I first tried this mod while I happened to be running an

OpenSCAD from January.  With my changes, rendering failed with manifold
errors.  When I switched to a recent build, it was OK again.  So if you're
having manifold problems, upgrade.


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

Thank you, Jordan, I missed the email with the little spear points at the bottom of the tooth profile, and the original pictures it was not clear what the problem was. This helps me look at what is going on... The last time I had something like this, I made a parametric profile and then extruded it, and it worked around the issue. Maybe a trick like that might work to clean it up. That said, your zoomed-in example might give folks a go-to geometrical unit-test to track it down. Not sure if there are takers, but this should be archived as a potential debugging test. Bob, I hear you. If this is fit for your purpose, then it is "good enough". There comes a point where spending time fixing some things is a diminishing returns game. I still think this should be formally submitted in a bug report, and see if it can be reduced to 2 teeth profiles as the whole of the part. This would be small enough to be debuggable, and large enough to expose the bug. EBo -- On Sat, Oct 26, 2024 at 10:51 PM Sanjeev Prabhakar via Discuss < discuss@lists.openscad.org> wrote: > here is my version of this through python > > https://youtu.be/Wp8q71eMqrE > > On Sun, 27 Oct 2024 at 06:15, Bob Carlson via Discuss < > discuss@lists.openscad.org> wrote: > >> Thanks! I hear about these point ordering problems. It seems a shame one >> has to deal with them. Why can’t they be fixed automatically? >> >> -Bob >> >> > On Oct 26, 2024, at 16:21, Jordan Brown <openscad@jordan.maileater.net> >> wrote: >> > >> > I notice that your _profileF() ends up generating an inside-out >> polyhedron. When viewed with View/Thrown Together, it's purple. That can >> cause problems for rendering. (I'm a little surprised that it didn't cause >> fatal problems.) It looks like you can fix it by swapping the second and >> third points in both tI and tO. >> > >> > >> > >> > Another thing attracted my attention immediately. >> > >> > Mostly, just don't use $fn except to create regular polygons. Use $fs >> and $fa; they are much less likely to lead you into silly settings. >> > >> > You have $fn=16*360 = 5760. Assuming that the units are millimeters, >> the model is about 100mm in diameter, so its circumference is 314mm. That >> means that each side is 0.05mm. Those tiny sides, and the even tinier >> artifacts that they might cause, might well be a key part of your geometry >> problems. My bet is that you could use fewer than 100 sides and still be >> unable to see or feel the individual sides when you print it. And if you >> can see them, bump it up to 300 or 500, and you've still got 10x fewer >> sides than your version does. >> > >> > Preview is (at least for me) horribly laggy when you try to move it, >> and it has what look like convexity artifacts. >> > >> > Removing all of the settings for $fn and adding in a single global >> setting for $fa=1 and $fs=1, and it previews fast and fixes the convexity >> artifacts. >> > >> > >> > >> > Also, a tidbit: _chamferF() generates a conical figure that might as >> well be a cone. >> > up(_conic + _chamferHeight) scale(1.5) zcyl(h = _toothHeight/2 + >> _conic, r1 = _or, r2 = 0, anchor=TOP); >> > Since it's anchored at the top, I didn't have to fiddle with making >> sure that it was slightly larger than the thing it's cutting from and could >> just scale it up a bit. >> > >> > I think your technique is responsible for generating micro flaws at the >> outside edges. >> > <YWbsxKvQ36n0OH8f.png> >> > >> > --- >> > Note: I first tried this mod while I happened to be running an >> OpenSCAD from January. With my changes, rendering failed with manifold >> errors. When I switched to a recent build, it was OK again. So if you're >> having manifold problems, upgrade. >> _______________________________________________ >> 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 >
HW
Harvey white
Sun, Oct 27, 2024 2:15 PM

One way to do this might be pairs of hull plates.  use two narrow
diameter cylinders as rays, they don't have to meet.  That (once a hull)
becomes a plate.  Create another using the bottom (or top) and with a
matching side.  Has to be separate hull entities. Rotate as needed. 
Diameter of cylinder determines rounding of the tooth.

This gives you a crinkled surface.  To do a gear tooth, use three
cylinders, overlapping at the vertical extents (likely top).

Doesn't solve your problem, but it's an alternate way of doing things.

Harvey

On 10/27/2024 12:35 AM, John David via Discuss wrote:

Thank you, Jordan, I missed the email with the little spear points at
the bottom of the tooth profile, and the original pictures it was not
clear what the problem was.  This helps me look at what is going
on...  The last time I had something like this, I made a parametric
profile and then extruded it, and it worked around the issue.  Maybe a
trick like that might work to clean it up.  That said, your zoomed-in
example might give folks a go-to geometrical unit-test to track it
down. Not sure if there are takers, but this should be archived as a
potential debugging test.

Bob, I hear you.  If this is fit for your purpose, then it is "good
enough".  There comes a point where spending time fixing some things
is a diminishing returns game. I still think this should be formally
submitted in a bug report, and see if it can be reduced to 2 teeth
profiles as the whole of the part.  This would be small enough to be
debuggable, and large enough to expose the bug.

  EBo --

On Sat, Oct 26, 2024 at 10:51 PM Sanjeev Prabhakar via Discuss
discuss@lists.openscad.org wrote:

 here is my version of this through python

 https://youtu.be/Wp8q71eMqrE

 On Sun, 27 Oct 2024 at 06:15, Bob Carlson via Discuss
 <discuss@lists.openscad.org> wrote:

     Thanks! I hear about these point ordering problems. It seems a
     shame one has to deal with them. Why can’t they be fixed
     automatically?

     -Bob

On Oct 26, 2024, at 16:21, Jordan Brown

     <openscad@jordan.maileater.net> wrote:

I notice that your _profileF() ends up generating an

     inside-out polyhedron.  When viewed with View/Thrown Together,
     it's purple.  That can cause problems for rendering.  (I'm a
     little surprised that it didn't cause fatal problems.)  It
     looks like you can fix it by swapping the second and third
     points in both tI and tO.

Another thing attracted my attention immediately.

Mostly, just don't use $fn except to create regular

     polygons.  Use $fs and $fa; they are much less likely to lead
     you into silly settings.

You have $fn=16*360 = 5760.  Assuming that the units are

     millimeters, the model is about 100mm in diameter, so its
     circumference is 314mm.  That means that each side is 0.05mm. 
     Those tiny sides, and the even tinier artifacts that they
     might cause, might well be a key part of your geometry
     problems.  My bet is that you could use fewer than 100 sides
     and still be unable to see or feel the individual sides when
     you print it.  And if you can see them, bump it up to 300 or
     500, and you've still got 10x fewer sides than your version does.

Preview is (at least for me) horribly laggy when you try to

     move it, and it has what look like convexity artifacts.

Removing all of the settings for $fn and adding in a single

     global setting for $fa=1 and $fs=1, and it previews fast and
     fixes the convexity artifacts.

Also, a tidbit:  _chamferF() generates a conical figure that

     might as well be a cone.

     up(_conic + _chamferHeight) scale(1.5) zcyl(h =

     _toothHeight/2 + _conic, r1 = _or, r2 = 0, anchor=TOP);

Since it's anchored at the top, I didn't have to fiddle with

     making sure that it was slightly larger than the thing it's
     cutting from and could just scale it up a bit.

I think your technique is responsible for generating micro

     flaws at the outside edges.

<YWbsxKvQ36n0OH8f.png>


Note:  I first tried this mod while I happened to be running

     an OpenSCAD from January.  With my changes, rendering failed
     with manifold errors.  When I switched to a recent build, it
     was OK again.  So if you're having manifold problems, upgrade.
     _______________________________________________
     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

One way to do this might be pairs of hull plates.  use two narrow diameter cylinders as rays, they don't have to meet.  That (once a hull) becomes a plate.  Create another using the bottom (or top) and with a matching side.  Has to be separate hull entities. Rotate as needed.  Diameter of cylinder determines rounding of the tooth. This gives you a crinkled surface.  To do a gear tooth, use three cylinders, overlapping at the vertical extents (likely top). Doesn't solve your problem, but it's an alternate way of doing things. Harvey On 10/27/2024 12:35 AM, John David via Discuss wrote: > Thank you, Jordan, I missed the email with the little spear points at > the bottom of the tooth profile, and the original pictures it was not > clear what the problem was.  This helps me look at what is going > on...  The last time I had something like this, I made a parametric > profile and then extruded it, and it worked around the issue.  Maybe a > trick like that might work to clean it up.  That said, your zoomed-in > example might give folks a go-to geometrical unit-test to track it > down. Not sure if there are takers, but this should be archived as a > potential debugging test. > > Bob, I hear you.  If this is fit for your purpose, then it is "good > enough".  There comes a point where spending time fixing some things > is a diminishing returns game. I still think this should be formally > submitted in a bug report, and see if it can be reduced to 2 teeth > profiles as the whole of the part.  This would be small enough to be > debuggable, and large enough to expose the bug. > >   EBo -- > > On Sat, Oct 26, 2024 at 10:51 PM Sanjeev Prabhakar via Discuss > <discuss@lists.openscad.org> wrote: > > here is my version of this through python > > https://youtu.be/Wp8q71eMqrE > > On Sun, 27 Oct 2024 at 06:15, Bob Carlson via Discuss > <discuss@lists.openscad.org> wrote: > > Thanks! I hear about these point ordering problems. It seems a > shame one has to deal with them. Why can’t they be fixed > automatically? > > -Bob > > > On Oct 26, 2024, at 16:21, Jordan Brown > <openscad@jordan.maileater.net> wrote: > > > > I notice that your _profileF() ends up generating an > inside-out polyhedron.  When viewed with View/Thrown Together, > it's purple.  That can cause problems for rendering.  (I'm a > little surprised that it didn't cause fatal problems.)  It > looks like you can fix it by swapping the second and third > points in both tI and tO. > > > > > > > > Another thing attracted my attention immediately. > > > > Mostly, just don't use $fn except to create regular > polygons.  Use $fs and $fa; they are much less likely to lead > you into silly settings. > > > > You have $fn=16*360 = 5760.  Assuming that the units are > millimeters, the model is about 100mm in diameter, so its > circumference is 314mm.  That means that each side is 0.05mm.  > Those tiny sides, and the even tinier artifacts that they > might cause, might well be a key part of your geometry > problems.  My bet is that you could use fewer than 100 sides > and still be unable to see or feel the individual sides when > you print it.  And if you can see them, bump it up to 300 or > 500, and you've still got 10x fewer sides than your version does. > > > > Preview is (at least for me) horribly laggy when you try to > move it, and it has what look like convexity artifacts. > > > > Removing all of the settings for $fn and adding in a single > global setting for $fa=1 and $fs=1, and it previews fast and > fixes the convexity artifacts. > > > > > > > > Also, a tidbit:  _chamferF() generates a conical figure that > might as well be a cone. > >     up(_conic + _chamferHeight) scale(1.5) zcyl(h = > _toothHeight/2 + _conic, r1 = _or, r2 = 0, anchor=TOP); > > Since it's anchored at the top, I didn't have to fiddle with > making sure that it was slightly larger than the thing it's > cutting from and could just scale it up a bit. > > > > I think your technique is responsible for generating micro > flaws at the outside edges. > > <YWbsxKvQ36n0OH8f.png> > > > > --- > > Note:  I first tried this mod while I happened to be running > an OpenSCAD from January.  With my changes, rendering failed > with manifold errors.  When I switched to a recent build, it > was OK again.  So if you're having manifold problems, upgrade. > _______________________________________________ > 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
Sun, Oct 27, 2024 5:21 PM

An early iteration of the tooth building did about that, hulled 3 cylinders. However I never considered the idea that the “top” cylinder could form the chamfer. I should have thought of that. I got rid of hull and went to skin because the cylinders were fuzzy edges and that bothered me. Skinning 2 2D triangles gave me a precise shape and I am guessing it is extremely efficient. I’g guessing the result has only 8 faces per tooth.

-Bob

On Oct 27, 2024, at 07:15, Harvey white via Discuss discuss@lists.openscad.org wrote:

One way to do this might be pairs of hull plates.  use two narrow diameter cylinders as rays, they don't have to meet.  That (once a hull) becomes a plate.  Create another using the bottom (or top) and with a matching side.  Has to be separate hull entities. Rotate as needed.  Diameter of cylinder determines rounding of the tooth.

This gives you a crinkled surface.  To do a gear tooth, use three cylinders, overlapping at the vertical extents (likely top).

Doesn't solve your problem, but it's an alternate way of doing things.

Harvey

On 10/27/2024 12:35 AM, John David via Discuss wrote:

Thank you, Jordan, I missed the email with the little spear points at the bottom of the tooth profile, and the original pictures it was not clear what the problem was.  This helps me look at what is going on...  The last time I had something like this, I made a parametric profile and then extruded it, and it worked around the issue.  Maybe a trick like that might work to clean it up.  That said, your zoomed-in example might give folks a go-to geometrical unit-test to track it down. Not sure if there are takers, but this should be archived as a potential debugging test.

Bob, I hear you.  If this is fit for your purpose, then it is "good enough".  There comes a point where spending time fixing some things is a diminishing returns game. I still think this should be formally submitted in a bug report, and see if it can be reduced to 2 teeth profiles as the whole of the part.  This would be small enough to be debuggable, and large enough to expose the bug.

EBo --

On Sat, Oct 26, 2024 at 10:51 PM Sanjeev Prabhakar via Discuss discuss@lists.openscad.org wrote:

here is my version of this through python

https://youtu.be/Wp8q71eMqrE

On Sun, 27 Oct 2024 at 06:15, Bob Carlson via Discuss
<discuss@lists.openscad.org> wrote:

    Thanks! I hear about these point ordering problems. It seems a
    shame one has to deal with them. Why can’t they be fixed
    automatically?

    -Bob

On Oct 26, 2024, at 16:21, Jordan Brown

    <openscad@jordan.maileater.net> wrote:

I notice that your _profileF() ends up generating an

    inside-out polyhedron.  When viewed with View/Thrown Together,
    it's purple.  That can cause problems for rendering.  (I'm a
    little surprised that it didn't cause fatal problems.)  It
    looks like you can fix it by swapping the second and third
    points in both tI and tO.

Another thing attracted my attention immediately.

Mostly, just don't use $fn except to create regular

    polygons.  Use $fs and $fa; they are much less likely to lead
    you into silly settings.

You have $fn=16*360 = 5760.  Assuming that the units are

    millimeters, the model is about 100mm in diameter, so its
    circumference is 314mm.  That means that each side is 0.05mm. 
    Those tiny sides, and the even tinier artifacts that they
    might cause, might well be a key part of your geometry
    problems.  My bet is that you could use fewer than 100 sides
    and still be unable to see or feel the individual sides when
    you print it.  And if you can see them, bump it up to 300 or
    500, and you've still got 10x fewer sides than your version does.

Preview is (at least for me) horribly laggy when you try to

    move it, and it has what look like convexity artifacts.

Removing all of the settings for $fn and adding in a single

    global setting for $fa=1 and $fs=1, and it previews fast and
    fixes the convexity artifacts.

Also, a tidbit:  _chamferF() generates a conical figure that

    might as well be a cone.
 up(_conic + _chamferHeight) scale(1.5) zcyl(h =
    _toothHeight/2 + _conic, r1 = _or, r2 = 0, anchor=TOP);

Since it's anchored at the top, I didn't have to fiddle with

    making sure that it was slightly larger than the thing it's
    cutting from and could just scale it up a bit.

I think your technique is responsible for generating micro

    flaws at the outside edges.

<YWbsxKvQ36n0OH8f.png>


Note:  I first tried this mod while I happened to be running

    an OpenSCAD from January.  With my changes, rendering failed
    with manifold errors.  When I switched to a recent build, it
    was OK again.  So if you're having manifold problems, upgrade.
    _______________________________________________
    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


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

An early iteration of the tooth building did about that, hulled 3 cylinders. However I never considered the idea that the “top” cylinder could form the chamfer. I should have thought of that. I got rid of hull and went to skin because the cylinders were fuzzy edges and that bothered me. Skinning 2 2D triangles gave me a precise shape and I am guessing it is extremely efficient. I’g guessing the result has only 8 faces per tooth. -Bob > On Oct 27, 2024, at 07:15, Harvey white via Discuss <discuss@lists.openscad.org> wrote: > > One way to do this might be pairs of hull plates. use two narrow diameter cylinders as rays, they don't have to meet. That (once a hull) becomes a plate. Create another using the bottom (or top) and with a matching side. Has to be separate hull entities. Rotate as needed. Diameter of cylinder determines rounding of the tooth. > > This gives you a crinkled surface. To do a gear tooth, use three cylinders, overlapping at the vertical extents (likely top). > > > Doesn't solve your problem, but it's an alternate way of doing things. > > Harvey > > > On 10/27/2024 12:35 AM, John David via Discuss wrote: >> Thank you, Jordan, I missed the email with the little spear points at the bottom of the tooth profile, and the original pictures it was not clear what the problem was. This helps me look at what is going on... The last time I had something like this, I made a parametric profile and then extruded it, and it worked around the issue. Maybe a trick like that might work to clean it up. That said, your zoomed-in example might give folks a go-to geometrical unit-test to track it down. Not sure if there are takers, but this should be archived as a potential debugging test. >> >> Bob, I hear you. If this is fit for your purpose, then it is "good enough". There comes a point where spending time fixing some things is a diminishing returns game. I still think this should be formally submitted in a bug report, and see if it can be reduced to 2 teeth profiles as the whole of the part. This would be small enough to be debuggable, and large enough to expose the bug. >> >> EBo -- >> >> On Sat, Oct 26, 2024 at 10:51 PM Sanjeev Prabhakar via Discuss <discuss@lists.openscad.org> wrote: >> >> here is my version of this through python >> >> https://youtu.be/Wp8q71eMqrE >> >> On Sun, 27 Oct 2024 at 06:15, Bob Carlson via Discuss >> <discuss@lists.openscad.org> wrote: >> >> Thanks! I hear about these point ordering problems. It seems a >> shame one has to deal with them. Why can’t they be fixed >> automatically? >> >> -Bob >> >> > On Oct 26, 2024, at 16:21, Jordan Brown >> <openscad@jordan.maileater.net> wrote: >> > >> > I notice that your _profileF() ends up generating an >> inside-out polyhedron. When viewed with View/Thrown Together, >> it's purple. That can cause problems for rendering. (I'm a >> little surprised that it didn't cause fatal problems.) It >> looks like you can fix it by swapping the second and third >> points in both tI and tO. >> > >> > >> > >> > Another thing attracted my attention immediately. >> > >> > Mostly, just don't use $fn except to create regular >> polygons. Use $fs and $fa; they are much less likely to lead >> you into silly settings. >> > >> > You have $fn=16*360 = 5760. Assuming that the units are >> millimeters, the model is about 100mm in diameter, so its >> circumference is 314mm. That means that each side is 0.05mm. >> Those tiny sides, and the even tinier artifacts that they >> might cause, might well be a key part of your geometry >> problems. My bet is that you could use fewer than 100 sides >> and still be unable to see or feel the individual sides when >> you print it. And if you can see them, bump it up to 300 or >> 500, and you've still got 10x fewer sides than your version does. >> > >> > Preview is (at least for me) horribly laggy when you try to >> move it, and it has what look like convexity artifacts. >> > >> > Removing all of the settings for $fn and adding in a single >> global setting for $fa=1 and $fs=1, and it previews fast and >> fixes the convexity artifacts. >> > >> > >> > >> > Also, a tidbit: _chamferF() generates a conical figure that >> might as well be a cone. >> > up(_conic + _chamferHeight) scale(1.5) zcyl(h = >> _toothHeight/2 + _conic, r1 = _or, r2 = 0, anchor=TOP); >> > Since it's anchored at the top, I didn't have to fiddle with >> making sure that it was slightly larger than the thing it's >> cutting from and could just scale it up a bit. >> > >> > I think your technique is responsible for generating micro >> flaws at the outside edges. >> > <YWbsxKvQ36n0OH8f.png> >> > >> > --- >> > Note: I first tried this mod while I happened to be running >> an OpenSCAD from January. With my changes, rendering failed >> with manifold errors. When I switched to a recent build, it >> was OK again. So if you're having manifold problems, upgrade. >> _______________________________________________ >> 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 > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org
BC
Bob Carlson
Sun, Oct 27, 2024 5:24 PM

Thanks for the response.

On Oct 26, 2024, at 21:31, Jordan Brown openscad@jordan.maileater.net wrote:

And then when OpenSCAD receives the "inside-out" polyhedron, it could perhaps fix it.  I think that if it's completely inside out then detecting that and fixing it isn't hard.  (But right now I'm not sure how to tell which way is "inside".)  If it's partially inside-out (like one face is backwards)  then I think I know how to detect that, and I guess that if you can detect it then you can flip faces until they are all consistent, and then you might be inside-out but you've reduced it to the case above.  So my not-a-geometry-wizard sense is that it's doable.  (OCD note:  you need to watch out for Klein bottles, lest you flip faces infinitely.)

Being somewhat of a geek I read occasional math news in Quanta. This sounds suspiciously like a conjecture that someone will prove or disprove 16 years from now.

-Bob

Thanks for the response. > On Oct 26, 2024, at 21:31, Jordan Brown <openscad@jordan.maileater.net> wrote: > > And then when OpenSCAD receives the "inside-out" polyhedron, it could perhaps fix it. I *think* that if it's completely inside out then detecting that and fixing it isn't hard. (But right now I'm not sure how to tell which way is "inside".) If it's partially inside-out (like one face is backwards) then I think I know how to detect that, and I guess that if you can detect it then you can flip faces until they are all consistent, and then you might be inside-out but you've reduced it to the case above. So my not-a-geometry-wizard sense is that it's doable. (OCD note: you need to watch out for Klein bottles, lest you flip faces infinitely.) Being somewhat of a geek I read occasional math news in Quanta. This sounds suspiciously like a conjecture that someone will prove or disprove 16 years from now. -Bob
BC
Bob Carlson
Sun, Oct 27, 2024 5:37 PM

On Oct 26, 2024, at 16:21, Jordan Brown openscad@jordan.maileater.net wrote:

I notice that your _profileF() ends up generating an inside-out polyhedron.  When viewed with View/Thrown Together, it's purple.  That can cause problems for rendering.  (I'm a little surprised that it didn't cause fatal problems.)  It looks like you can fix it by swapping the second and third points in both tI and tO.

Excellent! Thanks! That fixed the problem! I still consider it a bug that OpenSCAD does not detect the problem. I’ll note that in the issue.

I’ll experiment with $fa and $fs. I tend to learn things when I have need for them. This just hadn’t come up before. And it’s why I’m on this email list.

-Bob

> On Oct 26, 2024, at 16:21, Jordan Brown <openscad@jordan.maileater.net> wrote: > > I notice that your _profileF() ends up generating an inside-out polyhedron. When viewed with View/Thrown Together, it's purple. That can cause problems for rendering. (I'm a little surprised that it didn't cause fatal problems.) It looks like you can fix it by swapping the second and third points in both tI and tO. Excellent! Thanks! That fixed the problem! I still consider it a bug that OpenSCAD does not detect the problem. I’ll note that in the issue. I’ll experiment with $fa and $fs. I tend to learn things when I have need for them. This just hadn’t come up before. And it’s why I’m on this email list. -Bob
BC
Bob Carlson
Sun, Oct 27, 2024 6:12 PM

On Oct 26, 2024, at 16:21, Jordan Brown openscad@jordan.maileater.net wrote:

Mostly, just don't use $fn except to create regular polygons.  Use $fs and $fa; they are much less likely to lead you into silly settings.

You have $fn=16*360 = 5760.  Assuming that the units are millimeters, the model is about 100mm in diameter, so its circumference is 314mm.  That means that each side is 0.05mm.  Those tiny sides, and the even tinier artifacts that they might cause, might well be a key part of your geometry problems.  My bet is that you could use fewer than 100 sides and still be unable to see or feel the individual sides when you print it.  And if you can see them, bump it up to 300 or 500, and you've still got 10x fewer sides than your version does.

Preview is (at least for me) horribly laggy when you try to move it, and it has what look like convexity artifacts.

Removing all of the settings for $fn and adding in a single global setting for $fa=1 and $fs=1, and it previews fast and fixes the convexity artifacts.

Switching to $fa and $fs produced a complete mess! However when I fixed the polyhedron, things looked much better. The minimum settings that produced no micro flaws that I could see was $fa = 1; $fs = 0.1;

The massive $fn apparently papered over the polyhedron problem temporarily.

Thanks, Bob

On Oct 26, 2024, at 16:21, Jordan Brown <openscad@jordan.maileater.net> wrote: > > Mostly, just don't use $fn except to create regular polygons. Use $fs and $fa; they are much less likely to lead you into silly settings. > > You have $fn=16*360 = 5760. Assuming that the units are millimeters, the model is about 100mm in diameter, so its circumference is 314mm. That means that each side is 0.05mm. Those tiny sides, and the even tinier artifacts that they might cause, might well be a key part of your geometry problems. My bet is that you could use fewer than 100 sides and still be unable to see or feel the individual sides when you print it. And if you can see them, bump it up to 300 or 500, and you've still got 10x fewer sides than your version does. > > Preview is (at least for me) horribly laggy when you try to move it, and it has what look like convexity artifacts. > > Removing all of the settings for $fn and adding in a single global setting for $fa=1 and $fs=1, and it previews fast and fixes the convexity artifacts. Switching to $fa and $fs produced a complete mess! However when I fixed the polyhedron, things looked much better. The minimum settings that produced no micro flaws that I could see was $fa = 1; $fs = 0.1; The massive $fn apparently papered over the polyhedron problem temporarily. Thanks, Bob
JB
Jordan Brown
Sun, Oct 27, 2024 7:19 PM

On 10/27/2024 11:12 AM, Bob Carlson wrote:

The minimum settings that produced no micro flaws that I could see was
$fa = 1; $fs = 0.1;

What you can see on the screen is very different from what you can see
in plastic.  Try some test prints.

On 10/27/2024 11:12 AM, Bob Carlson wrote: > The minimum settings that produced no micro flaws that I could see was > $fa = 1; $fs = 0.1; What you can see on the screen is very different from what you can see in plastic.  Try some test prints.
BC
Bob Carlson
Mon, Oct 28, 2024 12:36 AM

Of course, I still like it to look nice and performance isn’t an issue.

  • Bob

On Oct 27, 2024, at 12:19, Jordan Brown openscad@jordan.maileater.net wrote:

On 10/27/2024 11:12 AM, Bob Carlson wrote:

The minimum settings that produced no micro flaws that I could see was $fa = 1; $fs = 0.1;

What you can see on the screen is very different from what you can see in plastic.  Try some test prints.

Of course, I still like it to look nice and performance isn’t an issue. - Bob > On Oct 27, 2024, at 12:19, Jordan Brown <openscad@jordan.maileater.net> wrote: > > On 10/27/2024 11:12 AM, Bob Carlson wrote: >> The minimum settings that produced no micro flaws that I could see was $fa = 1; $fs = 0.1; > > What you can see on the screen is very different from what you can see in plastic. Try some test prints. >
JB
Jordan Brown
Mon, Oct 28, 2024 3:24 AM

On 10/27/2024 5:36 PM, Bob Carlson wrote:

What you can see on the screen is very different from what you can see in plastic.  Try some test prints.

Of course, I still like it to look nice and performance isn’t an issue.

Indeed, with Manifold performance is less of an issue than it once was. 
But remember that spheres have a complexity that is the square of the
number of sides, so it can get unreasonable pretty fast.

I took my own advice, and did some test prints.  I'd done some in the
past, but not very systematically.

I made three cylinders, each with several vertical sections with
different numbers of sides.  One disk is 100mm in diameter, one 50mm,
and one 25mm. The two smaller ones have 25, 50, 100, and 150 sides; the
larger one has 50, 100, 150, and 300 sides.  (I've enclosed the program
below, for those who might want to duplicate the experiment.)

Sides
Angle
Side length
25mm
50mm
100mm
25
14.4°
3.1mm
6.3mm

50
7.2°
1.6mm
3.1mm
6.3mm
100
3.6°
0.8mm
1.6mm
3.1mm
150
2.4°
0.5mm
1mm
2.1mm
300
1.2°

1mm

I've color-coded them red for obvious artifacts, yellow for subtle
artifacts, and green for no visible or feel-able artifacts.  Of course,
that's subjective, but it might give you an idea.

(For those who for whatever reason can't see the colors:  for the 25mm
cylinder the 25 is red and the rest are green. For the 50mm cylinder the
25 is red, 50 is yellow, and larger are green.  For the 100mm cylinder,
50 is red and the others are green.)

I should probably do additional samples for larger and smaller
cylinders, but this is still interesting. 

I was interested to see that the 50-gon was OK at a smaller size, but
increasingly bad as the size increased.  My intuition was that past some
size more sides doesn't help, because the angle between the sides is
what you'd perceive, but I don't seem to have found that size yet.

100mm isn't the largest circle I can print, and of course I can print
arcs that are arbitrarily large diameter, but this suggests that $fa=3
or so is good enough for most things, and that $fs doesn't need to be
less than about 1.  $fa might need to be smaller for still-larger
circles, and $fs might need to be smaller for smaller circles.

Here's what the test cylinders look like:

Here's the test program:

include <BOSL2/std.scad>

// For the text
$fa = 2;
$fs = 1;

sides = [ 150, 100, 50, 25 ];
layerT = 6;        // Thickness of each layer
d = 50;            // Diameter
textT = 0.4;        // Thickness of text on the side
topTextT = 0.6;    // Thickness of text on the top
topTextSize = 6;    // Size of text on the top

// Draw a label wrapped around the cylinder
module clabel(text) {
path = up(layerT/2, path3d(reverse(circle(d=d))));
path_text(path, text, size=layerT0.8, textmetrics=true, valign="center", h=textT2+2, offset=-1, center=true);
}

for (i=[0:len(sides)-1]) translate([0,0,ilayerT]) {
fn = sides[i];
zcyl(d=d, h=layerT, anchor=BOTTOM, $fn=fn);
rotate(0) clabel(str(fn));
rotate(120) clabel(str(round(360/fn
10)/10, "°"));
rotate(-120) clabel(str(round(PId/fn10)/10, "mm"));
}
up(len(sides)*layerT) text3d(str(d, "mm"), atype="ycenter", anchor=BOTTOM, h=topTextT, size=topTextSize);

On 10/27/2024 5:36 PM, Bob Carlson wrote: >> What you can see on the screen is very different from what you can see in plastic. Try some test prints. > Of course, I still like it to look nice and performance isn’t an issue. Indeed, with Manifold performance is less of an issue than it once was.  But remember that spheres have a complexity that is the square of the number of sides, so it can get unreasonable pretty fast. I took my own advice, and did some test prints.  I'd done some in the past, but not very systematically. I made three cylinders, each with several vertical sections with different numbers of sides.  One disk is 100mm in diameter, one 50mm, and one 25mm. The two smaller ones have 25, 50, 100, and 150 sides; the larger one has 50, 100, 150, and 300 sides.  (I've enclosed the program below, for those who might want to duplicate the experiment.) Sides Angle Side length 25mm 50mm 100mm 25 14.4° 3.1mm 6.3mm 50 7.2° 1.6mm 3.1mm 6.3mm 100 3.6° 0.8mm 1.6mm 3.1mm 150 2.4° 0.5mm 1mm 2.1mm 300 1.2° 1mm I've color-coded them red for obvious artifacts, yellow for subtle artifacts, and green for no visible or feel-able artifacts.  Of course, that's subjective, but it might give you an idea. (For those who for whatever reason can't see the colors:  for the 25mm cylinder the 25 is red and the rest are green. For the 50mm cylinder the 25 is red, 50 is yellow, and larger are green.  For the 100mm cylinder, 50 is red and the others are green.) I should probably do additional samples for larger and smaller cylinders, but this is still interesting.  I was interested to see that the 50-gon was OK at a smaller size, but increasingly bad as the size increased.  My intuition was that past some size more sides doesn't help, because the angle between the sides is what you'd perceive, but I don't seem to have found that size yet. 100mm isn't the largest circle I can print, and of course I can print arcs that are arbitrarily large diameter, but this suggests that $fa=3 or so is good enough for most things, and that $fs doesn't need to be less than about 1.  $fa might need to be smaller for still-larger circles, and $fs might need to be smaller for smaller circles. Here's what the test cylinders look like: Here's the test program: include <BOSL2/std.scad> // For the text $fa = 2; $fs = 1; sides = [ 150, 100, 50, 25 ]; layerT = 6; // Thickness of each layer d = 50; // Diameter textT = 0.4; // Thickness of text on the side topTextT = 0.6; // Thickness of text on the top topTextSize = 6; // Size of text on the top // Draw a label wrapped around the cylinder module clabel(text) { path = up(layerT/2, path3d(reverse(circle(d=d)))); path_text(path, text, size=layerT*0.8, textmetrics=true, valign="center", h=textT*2+2, offset=-1, center=true); } for (i=[0:len(sides)-1]) translate([0,0,i*layerT]) { fn = sides[i]; zcyl(d=d, h=layerT, anchor=BOTTOM, $fn=fn); rotate(0) clabel(str(fn)); rotate(120) clabel(str(round(360/fn*10)/10, "°")); rotate(-120) clabel(str(round(PI*d/fn*10)/10, "mm")); } up(len(sides)*layerT) text3d(str(d, "mm"), atype="ycenter", anchor=BOTTOM, h=topTextT, size=topTextSize);
NH
nop head
Mon, Oct 28, 2024 8:00 AM

How well the filament interpolates the curve depends on its viscosity and
the extrusion width. For example ABS smooths curves better than PLA.

How noticeable the facets are depends on how shiny the filament is as you
tend to notice the discontinuities in specular highlights more than a
subtle change in angle when looking from the edge.

I set $fs to half my extrusion width as it isn't really possible to print
details shorter than that and $fa to 6 for most things. I reduce $fa if I
am milling or printing things that have some aesthetic merit rather than
just functional.

On Mon, 28 Oct 2024 at 03:25, Jordan Brown via Discuss <
discuss@lists.openscad.org> wrote:

On 10/27/2024 5:36 PM, Bob Carlson wrote:

What you can see on the screen is very different from what you can see in plastic.  Try some test prints.

Of course, I still like it to look nice and performance isn’t an issue.

Indeed, with Manifold performance is less of an issue than it once was.
But remember that spheres have a complexity that is the square of the
number of sides, so it can get unreasonable pretty fast.

I took my own advice, and did some test prints.  I'd done some in the
past, but not very systematically.

I made three cylinders, each with several vertical sections with different
numbers of sides.  One disk is 100mm in diameter, one 50mm, and one 25mm.
The two smaller ones have 25, 50, 100, and 150 sides; the larger one has
50, 100, 150, and 300 sides.  (I've enclosed the program below, for those
who might want to duplicate the experiment.)

Sides
Angle
Side length
25mm
50mm
100mm
25
14.4°
3.1mm
6.3mm

50
7.2°
1.6mm
3.1mm
6.3mm
100
3.6°
0.8mm
1.6mm
3.1mm
150
2.4°
0.5mm
1mm
2.1mm
300
1.2°

1mm

I've color-coded them red for obvious artifacts, yellow for subtle
artifacts, and green for no visible or feel-able artifacts.  Of course,
that's subjective, but it might give you an idea.

(For those who for whatever reason can't see the colors:  for the 25mm
cylinder the 25 is red and the rest are green. For the 50mm cylinder the 25
is red, 50 is yellow, and larger are green.  For the 100mm cylinder, 50 is
red and the others are green.)

I should probably do additional samples for larger and smaller cylinders,
but this is still interesting.

I was interested to see that the 50-gon was OK at a smaller size, but
increasingly bad as the size increased.  My intuition was that past some
size more sides doesn't help, because the angle between the sides is what
you'd perceive, but I don't seem to have found that size yet.

100mm isn't the largest circle I can print, and of course I can print arcs
that are arbitrarily large diameter, but this suggests that $fa=3 or so is
good enough for most things, and that $fs doesn't need to be less than
about 1.  $fa might need to be smaller for still-larger circles, and $fs
might need to be smaller for smaller circles.

Here's what the test cylinders look like:

Here's the test program:

include <BOSL2/std.scad>

// For the text
$fa = 2;
$fs = 1;

sides = [ 150, 100, 50, 25 ];
layerT = 6;        // Thickness of each layer
d = 50;            // Diameter
textT = 0.4;        // Thickness of text on the side
topTextT = 0.6;    // Thickness of text on the top
topTextSize = 6;    // Size of text on the top

// Draw a label wrapped around the cylinder
module clabel(text) {
path = up(layerT/2, path3d(reverse(circle(d=d))));
path_text(path, text, size=layerT0.8, textmetrics=true, valign="center", h=textT2+2, offset=-1, center=true);
}

for (i=[0:len(sides)-1]) translate([0,0,ilayerT]) {
fn = sides[i];
zcyl(d=d, h=layerT, anchor=BOTTOM, $fn=fn);
rotate(0) clabel(str(fn));
rotate(120) clabel(str(round(360/fn
10)/10, "°"));
rotate(-120) clabel(str(round(PId/fn10)/10, "mm"));
}
up(len(sides)*layerT) text3d(str(d, "mm"), atype="ycenter", anchor=BOTTOM, h=topTextT, size=topTextSize);


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

How well the filament interpolates the curve depends on its viscosity and the extrusion width. For example ABS smooths curves better than PLA. How noticeable the facets are depends on how shiny the filament is as you tend to notice the discontinuities in specular highlights more than a subtle change in angle when looking from the edge. I set $fs to half my extrusion width as it isn't really possible to print details shorter than that and $fa to 6 for most things. I reduce $fa if I am milling or printing things that have some aesthetic merit rather than just functional. On Mon, 28 Oct 2024 at 03:25, Jordan Brown via Discuss < discuss@lists.openscad.org> wrote: > On 10/27/2024 5:36 PM, Bob Carlson wrote: > > What you can see on the screen is very different from what you can see in plastic. Try some test prints. > > Of course, I still like it to look nice and performance isn’t an issue. > > > Indeed, with Manifold performance is less of an issue than it once was. > But remember that spheres have a complexity that is the square of the > number of sides, so it can get unreasonable pretty fast. > > > I took my own advice, and did some test prints. I'd done some in the > past, but not very systematically. > > I made three cylinders, each with several vertical sections with different > numbers of sides. One disk is 100mm in diameter, one 50mm, and one 25mm. > The two smaller ones have 25, 50, 100, and 150 sides; the larger one has > 50, 100, 150, and 300 sides. (I've enclosed the program below, for those > who might want to duplicate the experiment.) > > Sides > Angle > Side length > 25mm > 50mm > 100mm > 25 > 14.4° > 3.1mm > 6.3mm > > 50 > 7.2° > 1.6mm > 3.1mm > 6.3mm > 100 > 3.6° > 0.8mm > 1.6mm > 3.1mm > 150 > 2.4° > 0.5mm > 1mm > 2.1mm > 300 > 1.2° > > > 1mm > > I've color-coded them red for obvious artifacts, yellow for subtle > artifacts, and green for no visible or feel-able artifacts. Of course, > that's subjective, but it might give you an idea. > > (For those who for whatever reason can't see the colors: for the 25mm > cylinder the 25 is red and the rest are green. For the 50mm cylinder the 25 > is red, 50 is yellow, and larger are green. For the 100mm cylinder, 50 is > red and the others are green.) > > I should probably do additional samples for larger and smaller cylinders, > but this is still interesting. > > I was interested to see that the 50-gon was OK at a smaller size, but > increasingly bad as the size increased. My intuition was that past some > size more sides doesn't help, because the angle between the sides is what > you'd perceive, but I don't seem to have found that size yet. > > 100mm isn't the largest circle I can print, and of course I can print arcs > that are arbitrarily large diameter, but this suggests that $fa=3 or so is > good enough for most things, and that $fs doesn't need to be less than > about 1. $fa might need to be smaller for still-larger circles, and $fs > might need to be smaller for smaller circles. > > Here's what the test cylinders look like: > > > Here's the test program: > > include <BOSL2/std.scad> > > // For the text > $fa = 2; > $fs = 1; > > sides = [ 150, 100, 50, 25 ]; > layerT = 6; // Thickness of each layer > d = 50; // Diameter > textT = 0.4; // Thickness of text on the side > topTextT = 0.6; // Thickness of text on the top > topTextSize = 6; // Size of text on the top > > // Draw a label wrapped around the cylinder > module clabel(text) { > path = up(layerT/2, path3d(reverse(circle(d=d)))); > path_text(path, text, size=layerT*0.8, textmetrics=true, valign="center", h=textT*2+2, offset=-1, center=true); > } > > for (i=[0:len(sides)-1]) translate([0,0,i*layerT]) { > fn = sides[i]; > zcyl(d=d, h=layerT, anchor=BOTTOM, $fn=fn); > rotate(0) clabel(str(fn)); > rotate(120) clabel(str(round(360/fn*10)/10, "°")); > rotate(-120) clabel(str(round(PI*d/fn*10)/10, "mm")); > } > up(len(sides)*layerT) text3d(str(d, "mm"), atype="ycenter", anchor=BOTTOM, h=topTextT, size=topTextSize); > > > > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org >
DP
Dan Perry
Mon, Oct 28, 2024 10:31 AM

PrusaSlicer has an Arc Fitting option that is default on in recent
versions.  It's not clear to me if it actually smooths the arcs (and
influences your results) or if the G2/G3 commands are just shorthand for a
large number of G1 commands.
Dan

On Mon, Oct 28, 2024 at 3:24 AM Jordan Brown via Discuss <
discuss@lists.openscad.org> wrote:

On 10/27/2024 5:36 PM, Bob Carlson wrote:

What you can see on the screen is very different from what you can see in plastic.  Try some test prints.

Of course, I still like it to look nice and performance isn’t an issue.

Indeed, with Manifold performance is less of an issue than it once was.
But remember that spheres have a complexity that is the square of the
number of sides, so it can get unreasonable pretty fast.

I took my own advice, and did some test prints.  I'd done some in the
past, but not very systematically.

I made three cylinders, each with several vertical sections with different
numbers of sides.  One disk is 100mm in diameter, one 50mm, and one 25mm.
The two smaller ones have 25, 50, 100, and 150 sides; the larger one has
50, 100, 150, and 300 sides.  (I've enclosed the program below, for those
who might want to duplicate the experiment.)

Sides
Angle
Side length
25mm
50mm
100mm
25
14.4°
3.1mm
6.3mm

50
7.2°
1.6mm
3.1mm
6.3mm
100
3.6°
0.8mm
1.6mm
3.1mm
150
2.4°
0.5mm
1mm
2.1mm
300
1.2°

1mm

I've color-coded them red for obvious artifacts, yellow for subtle
artifacts, and green for no visible or feel-able artifacts.  Of course,
that's subjective, but it might give you an idea.

(For those who for whatever reason can't see the colors:  for the 25mm
cylinder the 25 is red and the rest are green. For the 50mm cylinder the 25
is red, 50 is yellow, and larger are green.  For the 100mm cylinder, 50 is
red and the others are green.)

I should probably do additional samples for larger and smaller cylinders,
but this is still interesting.

I was interested to see that the 50-gon was OK at a smaller size, but
increasingly bad as the size increased.  My intuition was that past some
size more sides doesn't help, because the angle between the sides is what
you'd perceive, but I don't seem to have found that size yet.

100mm isn't the largest circle I can print, and of course I can print arcs
that are arbitrarily large diameter, but this suggests that $fa=3 or so is
good enough for most things, and that $fs doesn't need to be less than
about 1.  $fa might need to be smaller for still-larger circles, and $fs
might need to be smaller for smaller circles.

Here's what the test cylinders look like:

Here's the test program:

include <BOSL2/std.scad>

// For the text
$fa = 2;
$fs = 1;

sides = [ 150, 100, 50, 25 ];
layerT = 6;        // Thickness of each layer
d = 50;            // Diameter
textT = 0.4;        // Thickness of text on the side
topTextT = 0.6;    // Thickness of text on the top
topTextSize = 6;    // Size of text on the top

// Draw a label wrapped around the cylinder
module clabel(text) {
path = up(layerT/2, path3d(reverse(circle(d=d))));
path_text(path, text, size=layerT0.8, textmetrics=true, valign="center", h=textT2+2, offset=-1, center=true);
}

for (i=[0:len(sides)-1]) translate([0,0,ilayerT]) {
fn = sides[i];
zcyl(d=d, h=layerT, anchor=BOTTOM, $fn=fn);
rotate(0) clabel(str(fn));
rotate(120) clabel(str(round(360/fn
10)/10, "°"));
rotate(-120) clabel(str(round(PId/fn10)/10, "mm"));
}
up(len(sides)*layerT) text3d(str(d, "mm"), atype="ycenter", anchor=BOTTOM, h=topTextT, size=topTextSize);


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

PrusaSlicer has an Arc Fitting option that is default on in recent versions. It's not clear to me if it actually smooths the arcs (and influences your results) or if the G2/G3 commands are just shorthand for a large number of G1 commands. Dan On Mon, Oct 28, 2024 at 3:24 AM Jordan Brown via Discuss < discuss@lists.openscad.org> wrote: > On 10/27/2024 5:36 PM, Bob Carlson wrote: > > What you can see on the screen is very different from what you can see in plastic. Try some test prints. > > Of course, I still like it to look nice and performance isn’t an issue. > > > Indeed, with Manifold performance is less of an issue than it once was. > But remember that spheres have a complexity that is the square of the > number of sides, so it can get unreasonable pretty fast. > > > I took my own advice, and did some test prints. I'd done some in the > past, but not very systematically. > > I made three cylinders, each with several vertical sections with different > numbers of sides. One disk is 100mm in diameter, one 50mm, and one 25mm. > The two smaller ones have 25, 50, 100, and 150 sides; the larger one has > 50, 100, 150, and 300 sides. (I've enclosed the program below, for those > who might want to duplicate the experiment.) > > Sides > Angle > Side length > 25mm > 50mm > 100mm > 25 > 14.4° > 3.1mm > 6.3mm > > 50 > 7.2° > 1.6mm > 3.1mm > 6.3mm > 100 > 3.6° > 0.8mm > 1.6mm > 3.1mm > 150 > 2.4° > 0.5mm > 1mm > 2.1mm > 300 > 1.2° > > > 1mm > > I've color-coded them red for obvious artifacts, yellow for subtle > artifacts, and green for no visible or feel-able artifacts. Of course, > that's subjective, but it might give you an idea. > > (For those who for whatever reason can't see the colors: for the 25mm > cylinder the 25 is red and the rest are green. For the 50mm cylinder the 25 > is red, 50 is yellow, and larger are green. For the 100mm cylinder, 50 is > red and the others are green.) > > I should probably do additional samples for larger and smaller cylinders, > but this is still interesting. > > I was interested to see that the 50-gon was OK at a smaller size, but > increasingly bad as the size increased. My intuition was that past some > size more sides doesn't help, because the angle between the sides is what > you'd perceive, but I don't seem to have found that size yet. > > 100mm isn't the largest circle I can print, and of course I can print arcs > that are arbitrarily large diameter, but this suggests that $fa=3 or so is > good enough for most things, and that $fs doesn't need to be less than > about 1. $fa might need to be smaller for still-larger circles, and $fs > might need to be smaller for smaller circles. > > Here's what the test cylinders look like: > > > Here's the test program: > > include <BOSL2/std.scad> > > // For the text > $fa = 2; > $fs = 1; > > sides = [ 150, 100, 50, 25 ]; > layerT = 6; // Thickness of each layer > d = 50; // Diameter > textT = 0.4; // Thickness of text on the side > topTextT = 0.6; // Thickness of text on the top > topTextSize = 6; // Size of text on the top > > // Draw a label wrapped around the cylinder > module clabel(text) { > path = up(layerT/2, path3d(reverse(circle(d=d)))); > path_text(path, text, size=layerT*0.8, textmetrics=true, valign="center", h=textT*2+2, offset=-1, center=true); > } > > for (i=[0:len(sides)-1]) translate([0,0,i*layerT]) { > fn = sides[i]; > zcyl(d=d, h=layerT, anchor=BOTTOM, $fn=fn); > rotate(0) clabel(str(fn)); > rotate(120) clabel(str(round(360/fn*10)/10, "°")); > rotate(-120) clabel(str(round(PI*d/fn*10)/10, "mm")); > } > up(len(sides)*layerT) text3d(str(d, "mm"), atype="ycenter", anchor=BOTTOM, h=topTextT, size=topTextSize); > > > > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org >
JB
Jordan Brown
Mon, Oct 28, 2024 4:47 PM

On 10/28/2024 3:31 AM, Dan Perry via Discuss wrote:

PrusaSlicer has an Arc Fitting option that is default on in recent
versions.  It's not clear to me if it actually smooths the arcs (and
influences your results) or if the G2/G3 commands are just shorthand
for a large number of G1 commands. 

Hmm.  I did look for that, but for me it generated G1s.  I found the
option; it's disabled for me.

If it's generating a single G2/G3 for an arc, that's interpreted at the
printer and so can't be a shorthand for the original segments.  (Where
would the information about the segments be?)  The printer interprets it
as it chooses, probably close to its native resolution.

On 10/28/2024 3:31 AM, Dan Perry via Discuss wrote: > PrusaSlicer has an Arc Fitting option that is default on in recent > versions.  It's not clear to me if it actually smooths the arcs (and > influences your results) or if the G2/G3 commands are just shorthand > for a large number of G1 commands.  Hmm.  I did look for that, but for me it generated G1s.  I found the option; it's disabled for me. If it's generating a single G2/G3 for an arc, that's interpreted at the printer and so *can't* be a shorthand for the original segments.  (Where would the information about the segments be?)  The printer interprets it as it chooses, probably close to its native resolution.
NH
nop head
Mon, Oct 28, 2024 4:49 PM

Sounds like it would break polyholes which is what I use to get holes the
correct size.

On Mon, 28 Oct 2024 at 16:47, Jordan Brown via Discuss <
discuss@lists.openscad.org> wrote:

On 10/28/2024 3:31 AM, Dan Perry via Discuss wrote:

PrusaSlicer has an Arc Fitting option that is default on in recent
versions.  It's not clear to me if it actually smooths the arcs (and
influences your results) or if the G2/G3 commands are just shorthand for a
large number of G1 commands.

Hmm.  I did look for that, but for me it generated G1s.  I found the
option; it's disabled for me.

If it's generating a single G2/G3 for an arc, that's interpreted at the
printer and so can't be a shorthand for the original segments.  (Where
would the information about the segments be?)  The printer interprets it as
it chooses, probably close to its native resolution.


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

Sounds like it would break polyholes which is what I use to get holes the correct size. On Mon, 28 Oct 2024 at 16:47, Jordan Brown via Discuss < discuss@lists.openscad.org> wrote: > On 10/28/2024 3:31 AM, Dan Perry via Discuss wrote: > > PrusaSlicer has an Arc Fitting option that is default on in recent > versions. It's not clear to me if it actually smooths the arcs (and > influences your results) or if the G2/G3 commands are just shorthand for a > large number of G1 commands. > > > Hmm. I did look for that, but for me it generated G1s. I found the > option; it's disabled for me. > > If it's generating a single G2/G3 for an arc, that's interpreted at the > printer and so *can't* be a shorthand for the original segments. (Where > would the information about the segments be?) The printer interprets it as > it chooses, probably close to its native resolution. > > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org >
JB
Jordan Brown
Mon, Oct 28, 2024 5:22 PM

On 10/28/2024 1:00 AM, nop head via Discuss wrote:

How well the filament interpolates the curve depends on its viscosity
and the extrusion width. For example ABS smooths curves better than PLA.

How noticeable the facets are depends on how shiny the filament is as
you tend to notice the discontinuities in specular highlights more
than a subtle change in angle when looking from the edge.

Good points, thanks.

I set $fs to half my extrusion width as it isn't really possible to
print details shorter than that and $fa to 6 for most things. I reduce
$fa if I am milling or printing things that have some aesthetic merit
rather than just functional.

So your usual setting has you topping out at a 60-gon.

[ I know you know the following, but for those who are new to the
$fs/$fa relationship... ]

With those settings and the usual 0.4mm EW, you'll use a 60-gon for
anything larger than about 4mm diameter.  Below that (generally, at
360/$fa*$fs/π) ) you'll switch over to $fs being the limiting factor. 
Smaller EW, smaller switchover.

I need to do some sample prints at small sizes to convince myself that a
$fs that small makes a difference.

Technically https://xkcd.com/1475/, the documentation on $fs is
slightly wrong.  (Or the calculation is slightly wrong.)  The $fs
calculation measures along the arc, not along the chord, so for a given
$fs your segments will be a tiny bit shorter.

It would be good if somebody were to analyze the Prusaslicer arc fitter
to figure out what parameters are circular enough to trigger it -
because at that point you magically get printer resolution.

On 10/28/2024 1:00 AM, nop head via Discuss wrote: > How well the filament interpolates the curve depends on its viscosity > and the extrusion width. For example ABS smooths curves better than PLA. > > How noticeable the facets are depends on how shiny the filament is as > you tend to notice the discontinuities in specular highlights more > than a subtle change in angle when looking from the edge. Good points, thanks. > I set $fs to half my extrusion width as it isn't really possible to > print details shorter than that and $fa to 6 for most things. I reduce > $fa if I am milling or printing things that have some aesthetic merit > rather than just functional. So your usual setting has you topping out at a 60-gon. [ I know you know the following, but for those who are new to the $fs/$fa relationship... ] With those settings and the usual 0.4mm EW, you'll use a 60-gon for anything larger than about 4mm diameter.  Below that (generally, at 360/$fa*$fs/π) ) you'll switch over to $fs being the limiting factor.  Smaller EW, smaller switchover. I need to do some sample prints at small sizes to convince myself that a $fs that small makes a difference. Technically <https://xkcd.com/1475/>, the documentation on $fs is slightly wrong.  (Or the calculation is slightly wrong.)  The $fs calculation measures along the arc, not along the chord, so for a given $fs your segments will be a tiny bit shorter. It would be good if somebody were to analyze the Prusaslicer arc fitter to figure out what parameters are circular enough to trigger it - because at that point you magically get printer resolution.
TP
Torsten Paul
Mon, Oct 28, 2024 5:57 PM

On 28.10.24 17:49, nop head via Discuss wrote:

Sounds like it would break polyholes which is what I use to get holes
the correct size.

Yeah, I have to look at this too. I printed a test piece for checking
fit of M2.5 nuts and it looked like the smallest hex shaped holes did
actually turn into circles. Not so good for trapped nuts either.

ciao,
Torsten.

On 28.10.24 17:49, nop head via Discuss wrote: > Sounds like it would break polyholes which is what I use to get holes > the correct size. Yeah, I have to look at this too. I printed a test piece for checking fit of M2.5 nuts and it looked like the smallest hex shaped holes did actually turn into circles. Not so good for trapped nuts either. ciao, Torsten.
AM
Adrian Mariano
Mon, Oct 28, 2024 9:39 PM

BOSL2 could generate the polyhedron "correctly".  I don't know how hard

that would be, but that's essentially

what swapping the points does:  it causes BOSL2 to build the polyhedron

the other way 'round.  I don't know

enough about "skin" to know how easy it would be to detect being

backwards.

What skin() does is establish an association between points on a pair of 3d
polygons and then link the associated points together to make (part of) a
polyhedron.

I think the basic problem is determining which direction is out.  I'm not
sure I know how to do that.  It's easy to flip the polyhedron direction
from BOSL2.  I could have skin() force 2d profiles to go a certain
direction, though that runs the risk of ruining point alignment if for some
reason the user didn't want that to happen.  In other words, if you flip
one polygon but not the other one it changes the point association.  I'm
not sure if there's a use-case for that or not---weird twisted
self-intersecting structures that you can preview but now render?  In 3d
there's no notion of clockwise so it's not so obvious to me how to do a
similar thing with 3d inputs.

I generally make a polyhedron, check it with "thrown together" and reverse
it if it came out backwards.

On Sun, Oct 27, 2024 at 12:32 AM Jordan Brown via Discuss <
discuss@lists.openscad.org> wrote:

On 10/26/2024 5:44 PM, Bob Carlson wrote:

Thanks! I hear about these point ordering problems. It seems a shame one has to deal with them. Why can’t they be fixed automatically?

I don't know for sure.

There are two levels to the question here:  first BOSL2 builds a
polyhedron, and then second OpenSCAD processes the polyhedron.

BOSL2 could generate the polyhedron "correctly".  I don't know how hard
that would be, but that's essentially what swapping the points does:  it
causes BOSL2 to build the polyhedron the other way 'round.  I don't know
enough about "skin" to know how easy it would be to detect being backwards.

And then when OpenSCAD receives the "inside-out" polyhedron, it could
perhaps fix it.  I think that if it's completely inside out then
detecting that and fixing it isn't hard.  (But right now I'm not sure how
to tell which way is "inside".)  If it's partially inside-out (like one
face is backwards)  then I think I know how to detect that, and I guess
that if you can detect it then you can flip faces until they are all
consistent, and then you might be inside-out but you've reduced it to the
case above.  So my not-a-geometry-wizard sense is that it's doable.  (OCD
note:  you need to watch out for Klein bottles, lest you flip faces
infinitely.)

Is anybody interested in spending the effort?  Obviously not so far.  (And
I think we can all agree that we'd rather have the geometry wizards work on
Manifold and its huge performance improvement.)

When I'm building a polyhedron, mostly I just turn on Thrown Together and
fix backward faces as required.  That's less of an imposition on DIY
polyhedra than it is when your polyhedron is coming out of a library.


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

> BOSL2 could generate the polyhedron "correctly". I don't know how hard that would be, but that's essentially > what swapping the points does: it causes BOSL2 to build the polyhedron the other way 'round. I don't know > enough about "skin" to know how easy it would be to detect being backwards. What skin() does is establish an association between points on a pair of 3d polygons and then link the associated points together to make (part of) a polyhedron. I think the basic problem is determining which direction is out. I'm not sure I know how to do that. It's easy to flip the polyhedron direction from BOSL2. I could have skin() force 2d profiles to go a certain direction, though that runs the risk of ruining point alignment if for some reason the user didn't want that to happen. In other words, if you flip one polygon but not the other one it changes the point association. I'm not sure if there's a use-case for that or not---weird twisted self-intersecting structures that you can preview but now render? In 3d there's no notion of clockwise so it's not so obvious to me how to do a similar thing with 3d inputs. I generally make a polyhedron, check it with "thrown together" and reverse it if it came out backwards. On Sun, Oct 27, 2024 at 12:32 AM Jordan Brown via Discuss < discuss@lists.openscad.org> wrote: > On 10/26/2024 5:44 PM, Bob Carlson wrote: > > Thanks! I hear about these point ordering problems. It seems a shame one has to deal with them. Why can’t they be fixed automatically? > > > I don't know for sure. > > There are two levels to the question here: first BOSL2 builds a > polyhedron, and then second OpenSCAD processes the polyhedron. > > BOSL2 could generate the polyhedron "correctly". I don't know how hard > that would be, but that's essentially what swapping the points does: it > causes BOSL2 to build the polyhedron the other way 'round. I don't know > enough about "skin" to know how easy it would be to detect being backwards. > > And then when OpenSCAD receives the "inside-out" polyhedron, it could > perhaps fix it. I *think* that if it's completely inside out then > detecting that and fixing it isn't hard. (But right now I'm not sure how > to tell which way is "inside".) If it's partially inside-out (like one > face is backwards) then I think I know how to detect that, and I guess > that if you can detect it then you can flip faces until they are all > consistent, and then you might be inside-out but you've reduced it to the > case above. So my not-a-geometry-wizard sense is that it's doable. (OCD > note: you need to watch out for Klein bottles, lest you flip faces > infinitely.) > > Is anybody interested in spending the effort? Obviously not so far. (And > I think we can all agree that we'd rather have the geometry wizards work on > Manifold and its huge performance improvement.) > > When I'm building a polyhedron, mostly I just turn on Thrown Together and > fix backward faces as required. That's less of an imposition on DIY > polyhedra than it is when your polyhedron is coming out of a library. > > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org >
AM
Adrian Mariano
Tue, Oct 29, 2024 4:35 AM

So Bob, you have said you don't care about speed, which is your choice,
obviously.  But for me this code is intolerably slow.  Preview is useless
even after I remove the chamfering and intersection to make it have
cylindrical edges.  And render takes 20s with manifold.  Because the
original code was unpreviewable I couldn't easily assess how well my
rewrite matched, but it previews instantly and renders in 0.1s.  (Note: a
reason I care about preview is that I can color things that I overlay to
see for example if two things match.)

Another few things.  In BOSL2, global variables that start with underscore
are reserved for BOSL2 internal use, so you shouldn't be using those.  You
could clobber an internal definition.  (Not sure why anyone would use
variables that start with underscore as a choice---I find them very
annoying.)

The second is that I think your code measures tooth angle relative to the
vertical instead of relative to the tooth ridge.  This is not the normal
way that tooth angle would be measured, e.g. on a gear.  It means that
actual angle is never what you specify.

A third observation is that you should be chamfering the valleys just like
the peaks.  Internal corners are stress concentration points on an object
and will weaken it.  So my version can apply varying chamfers in both
places.

I personally find the rewritten code simpler than the original, as well as
much faster, and there's probably room to clean it up more.  (Could
probably compute inner shape from outer with a scale() computation for
example.)  It does produce a polygonal result and could be intersected
with a tube like the original to fix that if you think it's necessary.  I
imagine that one intersection wouldn't be a major drag on the speed.  I
agree that trying to compute the profile on a circular arc would be a
pain.

include <BOSL2/std.scad>

// Number of Teeth
_n = 36;          // Number Of Teeth

// Inner Radius
_ir = 30;
// Outer Radius
_or = 50;
// Is the coupling conical?
_conic = 15;
// Tooth Profile Angle
_profile = 90; // [60, 90]
// Percentage of tooth height
_chamfer = 5; // Default 5%
_base = 1;

function basic_profile(angle,chamfer_top, chamfer_bot) =
let(
width = tan(angle/2),
pts = [
[0,(-1+chamfer_bot)width,chamfer_bot],
[0,-chamfer_top
width,1-chamfer_top]
],
)
concat(pts, reverse(yflip(pts)));

profwidth = tan(_profile/2);
outside = _ortan(180/_n);
inside = _ir
tan(180/_n);

prof_out = right(_or,scale(outside/profwidth,basic_profile(_profile,
_chamfer/100, _chamfer/200)));
prof_in = right(_ir,scale(inside/profwidth,basic_profile(_profile,
_chamfer/100, _chamfer/200)));

offset = (_or-_ir) * tan(_conic);

outfull = up(offset,[for(i=lerpn(0,360,_n,endpoint=false))
each zrot(i,prof_out)]);
infull = [for(i=lerpn(0,360,_n,endpoint=false))
each zrot(i,prof_in)];

inbot = [for(val=infull) [val.x,val.y,-_base]];
outbot = [for(val=outfull) [val.x,val.y,-_base]];

vnf_polyhedron(vnf_vertex_array([outfull, infull, inbot, outbot],
reverse=true, col_wrap=true, row_wrap=true));

[image: image.png]

On Fri, Oct 25, 2024 at 7:45 PM Bob Carlson via Discuss <
discuss@lists.openscad.org> wrote:

I got really intrigued by the Hirth joint and have been working a library
entry that would generate them. I have it fully working, apparently,
because it renders perfectly as far as I can see. However when I load one
of the parts (a concave part) into PrusaSlicer, it reports thousands of
errors that it supposedly fixed. The visual rendering is fine, but when you
look at the slice it is completely screwed up.

First some explanation. When I looked up hirth joints I only saw flat ones
mentioned. The one I have actually encountered though is a conical one.
There is a concave part and a convex part. They fit together perfectly. I
had to invent some terminology since I did not find terms for some things I
found to be important. The outer center line is the plane that passes
through the midpoint of the teeth at the outer radius. In a flat hirth
joint all the teeth radiate from the center of this circle, call it the
origin. If the origin of the teeth is above the outer center line, then
joint has a conical shape and the two parts are concave and convex.

Each tooth at every point has the same profile, the top of the tooth
profile is either 60 or 90 degrees. The groove angle is the angle that the
groove forms from the origin to the outer radius. It will pass below (for a
convex part) the outer radius. It’s critical for making hirth joints
because it forms the tool path. The ridge angle is the angle formed by the
corresponding ridge.

If the joint is conical, then there is an inner center line that passes
through the center of the teeth at the inner radius. The tooth height is
the critical number to calculate. It is dependent on the number of teeth,
the profile angle and the inner and out radii. Something that really
complicates the mental gymnastics is that the tooth height is smaller at
the inner radius. My code adds a “base” of extra material at the bottom of
the convex part and the top of the concave part. What’s tricky is
positioning the base of the concave part relative to the inner center line.
The concave parts base is relatively easy to place because it depends on
the outer radius and center line.

I generate the raw teeth using the groove and ridge angles and spherical
coordinates to make two 2d tooth profiles. Then I complete a tooth using
skin(). A for loop generates the full set of N teeth. Then intersection or
difference is used the trim the teeth at the inner and outer radii. I
discovered something at that point, but solved it pretty simply. When
diffing a cylinder from the N teeth, each tooth took up a small portion of
the cylinder being diffed out. I had to raise the $fn on the cylinder or
tube being used so that I got enough points in each tooth that diff or
intersection was accurate. I kept raising it until the results stopped
improving. I ended up with the 16*360 you see in the code.

After I have the raw teeth, I generate a cone that is diffed away to
produce the chamfer at the top of the teeth. Then I add in the base. The
base also adds the “chamfer” at the bottom of the groove. It’s half the
size of the top chamfer to leave a little gap when the parts are joined.

When I comment out the everything but the raw teeth and import the STL
into PrusaSlicer, it reports errors fixed, but appears to slice correctly
when supports are added.

When I add the intersection to trim the raw teeth, the number of reported
errors goes way up.

When I add the diff to remove the chamfer, the number goes way up again.

When I add in the base, the number goes up again and it starts reporting
many open edges.

Throughout, OpenSCAD reports no errors. Using $fn at 16360, manifold
renders in 4+ seconds. At 32
360, it’s 53+ seconds. I did check CSG and it
did not help.

Maybe the biggest hint is that the convex part uses almost identical code,
but produces no errors. Very weird.

So, is this an OpenSCAD problem? Or something in my code?

It’s also possible that my math is off somewhere. My formal trig training
was 60 years ago. However I doubt a math error is responsible for the
slicing problem and STL errors.

-Bob

include <BOSL2/std.scad>
include <BOSL2/structs.scad>

// Number of Teeth
_n = 36;          // Number Of Teeth

// Inner Radius
_ir = 30;
// Outer Radius
_or = 50;
// Is the coupling conical?
_conic = 10;
// Tooth Profile Angle
_profile = 60; // [60, 90]
// Percentage of tooth height
_chamfer = 5; // Default 5%
_base = 1;

$fn = 180;
tiny = 1 / 1024;

hirth_concave();

_irRatio = _ir / _or;
_toothAngle = 360/_n;
_toothHeight = (sin(_toothAngle/2) * _or) / tan(_profile/2);
_chamferHeight = _chamfer * _toothHeight / 100;
_grooveAngle =  atan(((_toothHeight/2) + _conic) / _or);
_ridgeAngle = -atan(((_toothHeight/2) - _conic) / _or);
_innerCenterLine = (1 - _irRatio) * _conic;
_stackHeight  = _innerCenterLine + _toothHeight + 2*_base;
_tubeHeight = 2*_conic + 2*_base + 2*_toothHeight;

module hirth_concave() {
zrot(_toothAngle/2)
union() {
difference() {
intersection() {
union() {
for (i = [0 : 360/_n : 359])
zrot(i)
_profileF();
}
tube(ir = _ir, or = _or, anchor = CENTER, l = _tubeHeight,
orient = UP, $fn = 16360);
}
_chamferF();
zcyl(r = _ir, h = _tubeHeight, $fn = 16
360, anchor = CENTER);
}
_baseF();
}
} // hirth_concave

module _profileF() {
IR = _ir * .5;
OR = _or * 1.5;
tI = [spherical_to_xyz(IR,  0,            _grooveAngle + 90),
spherical_to_xyz(IR,  _toothAngle/2, _ridgeAngle + 90),
spherical_to_xyz(IR, -_toothAngle/2, _ridgeAngle + 90)];

 tO = [spherical_to_xyz(OR,   0,            _grooveAngle + 90),
       spherical_to_xyz(OR,  _toothAngle/2, _ridgeAngle + 90),
       spherical_to_xyz(OR, -_toothAngle/2, _ridgeAngle + 90)];
 up(_conic)
 skin([tI, tO], slices = 0);

}

module _chamferF() {
A = -_toothHeight/2 - .1;
B = -_toothHeight/2 + _chamferHeight;

 pts = [[0, _conic],
        [_or+tiny, A],
        [_or+tiny, B]];

 rotate_extrude(angle = 360, $fn = 16*360)
 polygon(pts);

}

module _baseF() {
A = _base + _irRatio*_toothHeight/2 + _innerCenterLine;
B = _irRatio * (_toothHeight/2 - _chamferHeight/2) + _innerCenterLine;
C = _toothHeight/2 - _chamferHeight/2;
pts = [
[_ir, A],
[_ir, B],
[_or, C],
[_or, A]
];

 rotate_extrude(angle = 360, $fn = 360*16)
 polygon(pts);

}


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

So Bob, you have said you don't care about speed, which is your choice, obviously. But for me this code is intolerably slow. Preview is useless even after I remove the chamfering and intersection to make it have cylindrical edges. And render takes 20s with manifold. Because the original code was unpreviewable I couldn't easily assess how well my rewrite matched, but it previews instantly and renders in 0.1s. (Note: a reason I care about preview is that I can color things that I overlay to see for example if two things match.) Another few things. In BOSL2, global variables that start with underscore are reserved for BOSL2 internal use, so you shouldn't be using those. You could clobber an internal definition. (Not sure why anyone would use variables that start with underscore as a choice---I find them very annoying.) The second is that I think your code measures tooth angle relative to the vertical instead of relative to the tooth ridge. This is not the normal way that tooth angle would be measured, e.g. on a gear. It means that actual angle is never what you specify. A third observation is that you should be chamfering the valleys just like the peaks. Internal corners are stress concentration points on an object and will weaken it. So my version can apply varying chamfers in both places. I personally find the rewritten code simpler than the original, as well as much faster, and there's probably room to clean it up more. (Could probably compute inner shape from outer with a scale() computation for example.) It does produce a polygonal result and could be intersected with a tube like the original to fix that if you think it's necessary. I imagine that one intersection wouldn't be a major drag on the speed. I agree that trying to compute the profile on a circular arc would be a pain. include <BOSL2/std.scad> // Number of Teeth _n = 36; // Number Of Teeth // Inner Radius _ir = 30; // Outer Radius _or = 50; // Is the coupling conical? _conic = 15; // Tooth Profile Angle _profile = 90; // [60, 90] // Percentage of tooth height _chamfer = 5; // Default 5% _base = 1; function basic_profile(angle,chamfer_top, chamfer_bot) = let( width = tan(angle/2), pts = [ [0,(-1+chamfer_bot)*width,chamfer_bot], [0,-chamfer_top*width,1-chamfer_top] ], ) concat(pts, reverse(yflip(pts))); profwidth = tan(_profile/2); outside = _or*tan(180/_n); inside = _ir*tan(180/_n); prof_out = right(_or,scale(outside/profwidth,basic_profile(_profile, _chamfer/100, _chamfer/200))); prof_in = right(_ir,scale(inside/profwidth,basic_profile(_profile, _chamfer/100, _chamfer/200))); offset = (_or-_ir) * tan(_conic); outfull = up(offset,[for(i=lerpn(0,360,_n,endpoint=false)) each zrot(i,prof_out)]); infull = [for(i=lerpn(0,360,_n,endpoint=false)) each zrot(i,prof_in)]; inbot = [for(val=infull) [val.x,val.y,-_base]]; outbot = [for(val=outfull) [val.x,val.y,-_base]]; vnf_polyhedron(vnf_vertex_array([outfull, infull, inbot, outbot], reverse=true, col_wrap=true, row_wrap=true)); [image: image.png] On Fri, Oct 25, 2024 at 7:45 PM Bob Carlson via Discuss < discuss@lists.openscad.org> wrote: > I got really intrigued by the Hirth joint and have been working a library > entry that would generate them. I have it fully working, apparently, > because it renders perfectly as far as I can see. However when I load one > of the parts (a concave part) into PrusaSlicer, it reports thousands of > errors that it supposedly fixed. The visual rendering is fine, but when you > look at the slice it is completely screwed up. > > First some explanation. When I looked up hirth joints I only saw flat ones > mentioned. The one I have actually encountered though is a conical one. > There is a concave part and a convex part. They fit together perfectly. I > had to invent some terminology since I did not find terms for some things I > found to be important. The outer center line is the plane that passes > through the midpoint of the teeth at the outer radius. In a flat hirth > joint all the teeth radiate from the center of this circle, call it the > origin. If the origin of the teeth is above the outer center line, then > joint has a conical shape and the two parts are concave and convex. > > Each tooth at every point has the same profile, the top of the tooth > profile is either 60 or 90 degrees. The groove angle is the angle that the > groove forms from the origin to the outer radius. It will pass below (for a > convex part) the outer radius. It’s critical for making hirth joints > because it forms the tool path. The ridge angle is the angle formed by the > corresponding ridge. > > If the joint is conical, then there is an inner center line that passes > through the center of the teeth at the inner radius. The tooth height is > the critical number to calculate. It is dependent on the number of teeth, > the profile angle and the inner and out radii. Something that really > complicates the mental gymnastics is that the tooth height is smaller at > the inner radius. My code adds a “base” of extra material at the bottom of > the convex part and the top of the concave part. What’s tricky is > positioning the base of the concave part relative to the inner center line. > The concave parts base is relatively easy to place because it depends on > the outer radius and center line. > > I generate the raw teeth using the groove and ridge angles and spherical > coordinates to make two 2d tooth profiles. Then I complete a tooth using > skin(). A for loop generates the full set of N teeth. Then intersection or > difference is used the trim the teeth at the inner and outer radii. I > discovered something at that point, but solved it pretty simply. When > diffing a cylinder from the N teeth, each tooth took up a small portion of > the cylinder being diffed out. I had to raise the $fn on the cylinder or > tube being used so that I got enough points in each tooth that diff or > intersection was accurate. I kept raising it until the results stopped > improving. I ended up with the 16*360 you see in the code. > > After I have the raw teeth, I generate a cone that is diffed away to > produce the chamfer at the top of the teeth. Then I add in the base. The > base also adds the “chamfer” at the bottom of the groove. It’s half the > size of the top chamfer to leave a little gap when the parts are joined. > > When I comment out the everything but the raw teeth and import the STL > into PrusaSlicer, it reports errors fixed, but appears to slice correctly > when supports are added. > > When I add the intersection to trim the raw teeth, the number of reported > errors goes way up. > > When I add the diff to remove the chamfer, the number goes way up again. > > When I add in the base, the number goes up again and it starts reporting > many open edges. > > Throughout, OpenSCAD reports no errors. Using $fn at 16*360, manifold > renders in 4+ seconds. At 32*360, it’s 53+ seconds. I did check CSG and it > did not help. > > Maybe the biggest hint is that the convex part uses almost identical code, > but produces no errors. Very weird. > > So, is this an OpenSCAD problem? Or something in my code? > > It’s also possible that my math is off somewhere. My formal trig training > was 60 years ago. However I doubt a math error is responsible for the > slicing problem and STL errors. > > -Bob > > > include <BOSL2/std.scad> > include <BOSL2/structs.scad> > > // Number of Teeth > _n = 36; // Number Of Teeth > > // Inner Radius > _ir = 30; > // Outer Radius > _or = 50; > // Is the coupling conical? > _conic = 10; > // Tooth Profile Angle > _profile = 60; // [60, 90] > // Percentage of tooth height > _chamfer = 5; // Default 5% > _base = 1; > > $fn = 180; > tiny = 1 / 1024; > > hirth_concave(); > > _irRatio = _ir / _or; > _toothAngle = 360/_n; > _toothHeight = (sin(_toothAngle/2) * _or) / tan(_profile/2); > _chamferHeight = _chamfer * _toothHeight / 100; > _grooveAngle = atan(((_toothHeight/2) + _conic) / _or); > _ridgeAngle = -atan(((_toothHeight/2) - _conic) / _or); > _innerCenterLine = (1 - _irRatio) * _conic; > _stackHeight = _innerCenterLine + _toothHeight + 2*_base; > _tubeHeight = 2*_conic + 2*_base + 2*_toothHeight; > > module hirth_concave() { > zrot(_toothAngle/2) > union() { > difference() { > intersection() { > union() { > for (i = [0 : 360/_n : 359]) > zrot(i) > _profileF(); > } > tube(ir = _ir, or = _or, anchor = CENTER, l = _tubeHeight, > orient = UP, $fn = 16*360); > } > _chamferF(); > zcyl(r = _ir, h = _tubeHeight, $fn = 16*360, anchor = CENTER); > } > _baseF(); > } > } // hirth_concave > > module _profileF() { > IR = _ir * .5; > OR = _or * 1.5; > tI = [spherical_to_xyz(IR, 0, _grooveAngle + 90), > spherical_to_xyz(IR, _toothAngle/2, _ridgeAngle + 90), > spherical_to_xyz(IR, -_toothAngle/2, _ridgeAngle + 90)]; > > tO = [spherical_to_xyz(OR, 0, _grooveAngle + 90), > spherical_to_xyz(OR, _toothAngle/2, _ridgeAngle + 90), > spherical_to_xyz(OR, -_toothAngle/2, _ridgeAngle + 90)]; > up(_conic) > skin([tI, tO], slices = 0); > } > > > module _chamferF() { > A = -_toothHeight/2 - .1; > B = -_toothHeight/2 + _chamferHeight; > > pts = [[0, _conic], > [_or+tiny, A], > [_or+tiny, B]]; > > rotate_extrude(angle = 360, $fn = 16*360) > polygon(pts); > } > > module _baseF() { > A = _base + _irRatio*_toothHeight/2 + _innerCenterLine; > B = _irRatio * (_toothHeight/2 - _chamferHeight/2) + _innerCenterLine; > C = _toothHeight/2 - _chamferHeight/2; > pts = [ > [_ir, A], > [_ir, B], > [_or, C], > [_or, A] > ]; > > rotate_extrude(angle = 360, $fn = 360*16) > polygon(pts); > } > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org >
M
mikeonenine@web.de
Wed, Oct 30, 2024 12:53 AM

Adrian Mariano wrote:

The second is that I think your code measures tooth angle relative to the
vertical instead of relative to the tooth ridge.  This is not the normal
way that tooth angle would be measured, e.g. on a gear.  It means that
actual angle is never what you specify.

A third observation is that you should be chamfering the valleys just like
the peaks.  Internal corners are stress concentration points on an object
and will weaken it.  So my version can apply varying chamfers in both
places.

Machining or grinding would produce flat peaks, forging might produce more rounded peaks. What is best for 3D printing? The code below gives a choice.

The valleys are best rounded to avoid stress concentrations.

A polygon is linear_extruded to give a spline:

r=100; // Radius outer

n=30; // No. of splines

rr=4; // Radius ridge

rv=1.5; // Radius valley

f=2; // Flat

a=60; // Angle between flanks

c=-20; // Conicity

function angle() = 90-a/2;

aa=angle();

function base() = r*tan(360/n/2);

b=base();

$fn=500;

module fspline()

{

translate([0,0,-r])

linear_extrude(r, scale=[0 ,0],convexity=3)

translate([0,-b*tan(aa)/2+c])

polygon([

/*

// Rounded ridge

for(i=[-60:60])

[rr*sin(i), rr*cos(i)+b*tan(a)-2*rr],

*/

// alternatively:

// Flat ridge

[-f/tan(aa), b*tan(aa)-f],

[f/tan(aa), b*tan(aa)-f],

for(i=[180:120-(60-a)/2])

[b+rv*sin(-i), rv*cos(-i)+rv/sin(a/2)],

[b, 0],

[-b, 0],

for(i=[180:240+(60-a)/2])

[-b+rv*sin(-i), rv*cos(-i)+rv/sin(a/2)],

]);

}

// Test spline

fspline();

Multiple splines are then arranged in a circle:

for(i=[1:n])

rotate([90,0,i*360/n])

The rest is just an intersection with a cylinder to round the splines and a hole in the middle.

Later versions of OpenSCAD seem to need a union() at some point for the above to work and i am not sure how it would print - I read somewhere that parts have to overlap slightly, to print as a whole.

Adrian Mariano wrote: > The second is that I think your code measures tooth angle relative to the > vertical instead of relative to the tooth ridge. This is not the normal > way that tooth angle would be measured, e.g. on a gear. It means that > actual angle is never what you specify. > > A third observation is that you should be chamfering the valleys just like > the peaks. Internal corners are stress concentration points on an object > and will weaken it. So my version can apply varying chamfers in both > places. Machining or grinding would produce flat peaks, forging might produce more rounded peaks. What is best for 3D printing? The code below gives a choice. The valleys are best rounded to avoid stress concentrations. A polygon is linear_extruded to give a spline: `r=100; // Radius outer` `n=30; // No. of splines` `rr=4; // Radius ridge` `rv=1.5; // Radius valley ` `f=2; // Flat ` `a=60; // Angle between flanks` `c=-20; // Conicity` `function angle() = 90-a/2;` `aa=angle();` `function base() = r*tan(360/n/2);` `b=base();` `$fn=500;` `module fspline()` `{` `translate([0,0,-r])` `linear_extrude(r, scale=[0 ,0],convexity=3)` `translate([0,-b*tan(aa)/2+c])` `polygon([` `/*` `// Rounded ridge` `for(i=[-60:60])` `[rr*sin(i), rr*cos(i)+b*tan(a)-2*rr],` `*/` `// alternatively:` `// Flat ridge` `[-f/tan(aa), b*tan(aa)-f],` `[f/tan(aa), b*tan(aa)-f],` `for(i=[180:120-(60-a)/2])` `[b+rv*sin(-i), rv*cos(-i)+rv/sin(a/2)],` `[b, 0],` `[-b, 0],` `for(i=[180:240+(60-a)/2])` `[-b+rv*sin(-i), rv*cos(-i)+rv/sin(a/2)],` `]);` `}` `// Test spline` `fspline();` Multiple splines are then arranged in a circle: `for(i=[1:n])` `rotate([90,0,i*360/n])` The rest is just an intersection with a cylinder to round the splines and a hole in the middle. Later versions of OpenSCAD seem to need a union() at some point for the above to work and i am not sure how it would print - I read somewhere that parts have to overlap slightly, to print as a whole.
BC
Bob Carlson
Thu, Oct 31, 2024 1:33 AM

On Oct 26, 2024, at 16:21, Jordan Brown openscad@jordan.maileater.net wrote:

Also, a tidbit:  _chamferF() generates a conical figure that might as well be a cone.
up(_conic + _chamferHeight) scale(1.5) zcyl(h = _toothHeight/2 + _conic, r1 = _or, r2 = 0, anchor=TOP);
Since it's anchored at the top, I didn't have to fiddle with making sure that it was slightly larger than the thing it's cutting from and could just scale it up a bit.

When I tried switching to a cone rather than rotate_extrude, the rendering time went up by about 50% (roughly a quarter second to .4 seconds). So, I’ve kept the current code.

-Bob

> On Oct 26, 2024, at 16:21, Jordan Brown <openscad@jordan.maileater.net> wrote: > > Also, a tidbit: _chamferF() generates a conical figure that might as well be a cone. > up(_conic + _chamferHeight) scale(1.5) zcyl(h = _toothHeight/2 + _conic, r1 = _or, r2 = 0, anchor=TOP); > Since it's anchored at the top, I didn't have to fiddle with making sure that it was slightly larger than the thing it's cutting from and could just scale it up a bit. When I tried switching to a cone rather than rotate_extrude, the rendering time went up by about 50% (roughly a quarter second to .4 seconds). So, I’ve kept the current code. -Bob
BC
Bob Carlson
Thu, Oct 31, 2024 1:51 AM

The current code renders 1 part in about 0.25 s, so I doubt you would have much problem with the current performance.

As it happens, I switched to using _name's in the code because I will be offering it for inclusion in BOSL2. It’s also good for use in my own library if that’s where it stays. I have full attachability working now and the output looks very good.

The valleys are chamfered too, at 50% of the ridge chamfer size so a proper gap is left when the parts are together. If you look closely you can see it in the demo code too.

There are 3 angles I calculate. Tooth Angle is the angle between teeth radially. It’s simple, 360/N. The other two are the groove angle and ridge angle. These are calculated relative to horizontal. In a flat hirth joint, they are plus and minus the same number. In a conical joint, it’s different, but still measured relative to the XY plane. When I use them in the code I believe it’s always in a call to a spherical transform. In those calls 0 degrees is vertical, so I have to add 90.

Adding the “bases” and getting the chamfers right in the conical cases was REALLY tricky. It’s the conical parts that cause all the problems.

You should see the finished code in an enhancement request to BOSL2 in a few days.

-Bob

On Oct 28, 2024, at 21:35, Adrian Mariano avm4@cornell.edu wrote:

So Bob, you have said you don't care about speed, which is your choice, obviously.  But for me this code is intolerably slow.  Preview is useless even after I remove the chamfering and intersection to make it have cylindrical edges.  And render takes 20s with manifold.  Because the original code was unpreviewable I couldn't easily assess how well my rewrite matched, but it previews instantly and renders in 0.1s.  (Note: a reason I care about preview is that I can color things that I overlay to see for example if two things match.)

Another few things.  In BOSL2, global variables that start with underscore are reserved for BOSL2 internal use, so you shouldn't be using those.  You could clobber an internal definition.  (Not sure why anyone would use variables that start with underscore as a choice---I find them very annoying.)

The second is that I think your code measures tooth angle relative to the vertical instead of relative to the tooth ridge.  This is not the normal way that tooth angle would be measured, e.g. on a gear.  It means that actual angle is never what you specify.

A third observation is that you should be chamfering the valleys just like the peaks.  Internal corners are stress concentration points on an object and will weaken it.  So my version can apply varying chamfers in both places.

I personally find the rewritten code simpler than the original, as well as much faster, and there's probably room to clean it up more.  (Could probably compute inner shape from outer with a scale() computation for example.)  It does produce a polygonal result and could be intersected with a tube like the original to fix that if you think it's necessary.  I imagine that one intersection wouldn't be a major drag on the speed.  I agree that trying to compute the profile on a circular arc would be a pain.

include <BOSL2/std.scad>

// Number of Teeth
_n = 36;          // Number Of Teeth

// Inner Radius
_ir = 30;
// Outer Radius
_or = 50;
// Is the coupling conical?
_conic = 15;
// Tooth Profile Angle
_profile = 90; // [60, 90]
// Percentage of tooth height
_chamfer = 5; // Default 5%
_base = 1;

function basic_profile(angle,chamfer_top, chamfer_bot) =
let(
width = tan(angle/2),
pts = [
[0,(-1+chamfer_bot)width,chamfer_bot],
[0,-chamfer_top
width,1-chamfer_top]
],
)
concat(pts, reverse(yflip(pts)));

profwidth = tan(_profile/2);
outside = _ortan(180/_n);
inside = _ir
tan(180/_n);

prof_out = right(_or,scale(outside/profwidth,basic_profile(_profile, _chamfer/100, _chamfer/200)));
prof_in = right(_ir,scale(inside/profwidth,basic_profile(_profile, _chamfer/100, _chamfer/200)));

offset = (_or-_ir) * tan(_conic);

outfull = up(offset,[for(i=lerpn(0,360,_n,endpoint=false))
each zrot(i,prof_out)]);
infull = [for(i=lerpn(0,360,_n,endpoint=false))
each zrot(i,prof_in)];

inbot = [for(val=infull) [val.x,val.y,-_base]];
outbot = [for(val=outfull) [val.x,val.y,-_base]];

vnf_polyhedron(vnf_vertex_array([outfull, infull, inbot, outbot], reverse=true, col_wrap=true, row_wrap=true));

<image.png>

The current code renders 1 part in about 0.25 s, so I doubt you would have much problem with the current performance. As it happens, I switched to using _name's in the code because I will be offering it for inclusion in BOSL2. It’s also good for use in my own library if that’s where it stays. I have full attachability working now and the output looks very good. The valleys are chamfered too, at 50% of the ridge chamfer size so a proper gap is left when the parts are together. If you look closely you can see it in the demo code too. There are 3 angles I calculate. Tooth Angle is the angle between teeth radially. It’s simple, 360/N. The other two are the groove angle and ridge angle. These are calculated relative to horizontal. In a flat hirth joint, they are plus and minus the same number. In a conical joint, it’s different, but still measured relative to the XY plane. When I use them in the code I believe it’s always in a call to a spherical transform. In those calls 0 degrees is vertical, so I have to add 90. Adding the “bases” and getting the chamfers right in the conical cases was REALLY tricky. It’s the conical parts that cause all the problems. You should see the finished code in an enhancement request to BOSL2 in a few days. -Bob > On Oct 28, 2024, at 21:35, Adrian Mariano <avm4@cornell.edu> wrote: > > So Bob, you have said you don't care about speed, which is your choice, obviously. But for me this code is intolerably slow. Preview is useless even after I remove the chamfering and intersection to make it have cylindrical edges. And render takes 20s with manifold. Because the original code was unpreviewable I couldn't easily assess how well my rewrite matched, but it previews instantly and renders in 0.1s. (Note: a reason I care about preview is that I can color things that I overlay to see for example if two things match.) > > Another few things. In BOSL2, global variables that start with underscore are reserved for BOSL2 internal use, so you shouldn't be using those. You could clobber an internal definition. (Not sure why anyone would use variables that start with underscore as a choice---I find them very annoying.) > > The second is that I think your code measures tooth angle relative to the vertical instead of relative to the tooth ridge. This is not the normal way that tooth angle would be measured, e.g. on a gear. It means that actual angle is never what you specify. > > A third observation is that you should be chamfering the valleys just like the peaks. Internal corners are stress concentration points on an object and will weaken it. So my version can apply varying chamfers in both places. > > I personally find the rewritten code simpler than the original, as well as much faster, and there's probably room to clean it up more. (Could probably compute inner shape from outer with a scale() computation for example.) It does produce a polygonal result and could be intersected with a tube like the original to fix that if you think it's necessary. I imagine that one intersection wouldn't be a major drag on the speed. I agree that trying to compute the profile on a circular arc would be a pain. > > include <BOSL2/std.scad> > > // Number of Teeth > _n = 36; // Number Of Teeth > > // Inner Radius > _ir = 30; > // Outer Radius > _or = 50; > // Is the coupling conical? > _conic = 15; > // Tooth Profile Angle > _profile = 90; // [60, 90] > // Percentage of tooth height > _chamfer = 5; // Default 5% > _base = 1; > > function basic_profile(angle,chamfer_top, chamfer_bot) = > let( > width = tan(angle/2), > pts = [ > [0,(-1+chamfer_bot)*width,chamfer_bot], > [0,-chamfer_top*width,1-chamfer_top] > ], > ) > concat(pts, reverse(yflip(pts))); > > profwidth = tan(_profile/2); > outside = _or*tan(180/_n); > inside = _ir*tan(180/_n); > > prof_out = right(_or,scale(outside/profwidth,basic_profile(_profile, _chamfer/100, _chamfer/200))); > prof_in = right(_ir,scale(inside/profwidth,basic_profile(_profile, _chamfer/100, _chamfer/200))); > > offset = (_or-_ir) * tan(_conic); > > outfull = up(offset,[for(i=lerpn(0,360,_n,endpoint=false)) > each zrot(i,prof_out)]); > infull = [for(i=lerpn(0,360,_n,endpoint=false)) > each zrot(i,prof_in)]; > > inbot = [for(val=infull) [val.x,val.y,-_base]]; > outbot = [for(val=outfull) [val.x,val.y,-_base]]; > > vnf_polyhedron(vnf_vertex_array([outfull, infull, inbot, outbot], reverse=true, col_wrap=true, row_wrap=true)); > > <image.png> > > > > >
AM
Adrian Mariano
Thu, Oct 31, 2024 3:21 AM

The only angles that really are needed to make this are the angle of
the teeth and one additional angle, the angle of the ridge line or the
tooth base (including any conical angle).  I'm not sure how that angle
is best defined.  Maybe it's different for the two halves of the joint?
Computing a bunch of other angles does not appear to be necessary,
though maybe for figuring out how to adjust the tooth angle you need
an extra computation.

I think the tooth angle should be defined relative to the top line
of the teeth (ridge line?), but your code defines it relative to
absolute vertical, so as you change the conical angle the tooth angle
changes.  And if the conical angle is zero the tooth angle is not the
specified
angle.  At least that appeared to be the case with the version you
posted.

When you organize the computation the way I did in my posted example
the chamfers are trivial regardless of the angle of anything, though if you
want to get the tooth angle relative to the ridge line some care is
required.
Did you look at how I did it?  Using roundings instead of chamfers might
be nice too, especially for joints at larger scale.  I guess another
question
is whether chamfers should be absolute values rather than proportional
to tooth size.

In BOSL2 the undercores are used only for private globals, and all the
global variables you have should actually be parameters in a library
implementation.  I mean, there's no harm in using underscores
internally; I just find them annoying and hard to read.  One reason to
use them for internals is that nobody in their right mind would CHOOSE
to prefix their variables with them.  :)

How fast does your existing code preview?  Because the preview
performance of the code I tried made preview unusable, even when I
removed the chamfers and intersection with the tube.  I assumed this
was the result of having 36 objects unioned together, though even so
it seemed oddly sluggish.  I also noticed that intersecting with a tube
produces a potential issue: the $fn for the tube needs to be a multiple
of the tooth count, or the result looks funny.

The Hirth joint looks interesting and useful so I think we'll get it
into BOSL2 one way or another.  Do you use this joint by gluing at
the joint?  Or by holding parts captive somehow so that shafts are
locked at the joint?

On Wed, Oct 30, 2024 at 9:52 PM Bob Carlson bob@rjcarlson.com wrote:

The current code renders 1 part in about 0.25 s, so I doubt you would have
much problem with the current performance.

As it happens, I switched to using _name's in the code because I will be
offering it for inclusion in BOSL2. It’s also good for use in my own
library if that’s where it stays. I have full attachability working now and
the output looks very good.

The valleys are chamfered too, at 50% of the ridge chamfer size so a
proper gap is left when the parts are together. If you look closely you can
see it in the demo code too.

There are 3 angles I calculate. Tooth Angle is the angle between teeth
radially. It’s simple, 360/N. The other two are the groove angle and ridge
angle. These are calculated relative to horizontal. In a flat hirth joint,
they are plus and minus the same number. In a conical joint, it’s
different, but still measured relative to the XY plane. When I use them in
the code I believe it’s always in a call to a spherical transform. In those
calls 0 degrees is vertical, so I have to add 90.

Adding the “bases” and getting the chamfers right in the conical cases was
REALLY tricky. It’s the conical parts that cause all the problems.

You should see the finished code in an enhancement request to BOSL2 in a
few days.

-Bob

On Oct 28, 2024, at 21:35, Adrian Mariano avm4@cornell.edu wrote:

So Bob, you have said you don't care about speed, which is your choice,

obviously.  But for me this code is intolerably slow.  Preview is useless
even after I remove the chamfering and intersection to make it have
cylindrical edges.  And render takes 20s with manifold.  Because the
original code was unpreviewable I couldn't easily assess how well my
rewrite matched, but it previews instantly and renders in 0.1s.  (Note: a
reason I care about preview is that I can color things that I overlay to
see for example if two things match.)

Another few things.  In BOSL2, global variables that start with

underscore are reserved for BOSL2 internal use, so you shouldn't be using
those.  You could clobber an internal definition.  (Not sure why anyone
would use variables that start with underscore as a choice---I find them
very annoying.)

The second is that I think your code measures tooth angle relative to

the vertical instead of relative to the tooth ridge.  This is not the
normal way that tooth angle would be measured, e.g. on a gear.  It means
that actual angle is never what you specify.

A third observation is that you should be chamfering the valleys just

like the peaks.  Internal corners are stress concentration points on an
object and will weaken it.  So my version can apply varying chamfers in
both places.

I personally find the rewritten code simpler than the original, as well

as much faster, and there's probably room to clean it up more.  (Could
probably compute inner shape from outer with a scale() computation for
example.)  It does produce a polygonal result and could be intersected
with a tube like the original to fix that if you think it's necessary.  I
imagine that one intersection wouldn't be a major drag on the speed.  I
agree that trying to compute the profile on a circular arc would be a pain.

include <BOSL2/std.scad>

// Number of Teeth
_n = 36;          // Number Of Teeth

// Inner Radius
_ir = 30;
// Outer Radius
_or = 50;
// Is the coupling conical?
_conic = 15;
// Tooth Profile Angle
_profile = 90; // [60, 90]
// Percentage of tooth height
_chamfer = 5; // Default 5%
_base = 1;

function basic_profile(angle,chamfer_top, chamfer_bot) =
let(
width = tan(angle/2),
pts = [
[0,(-1+chamfer_bot)width,chamfer_bot],
[0,-chamfer_top
width,1-chamfer_top]
],
)
concat(pts, reverse(yflip(pts)));

profwidth = tan(_profile/2);
outside = _ortan(180/_n);
inside = _ir
tan(180/_n);

prof_out = right(_or,scale(outside/profwidth,basic_profile(_profile,

_chamfer/100, _chamfer/200)));

prof_in = right(_ir,scale(inside/profwidth,basic_profile(_profile,

_chamfer/100, _chamfer/200)));

offset = (_or-_ir) * tan(_conic);

outfull = up(offset,[for(i=lerpn(0,360,_n,endpoint=false))
each zrot(i,prof_out)]);
infull = [for(i=lerpn(0,360,_n,endpoint=false))
each zrot(i,prof_in)];

inbot = [for(val=infull) [val.x,val.y,-_base]];
outbot = [for(val=outfull) [val.x,val.y,-_base]];

vnf_polyhedron(vnf_vertex_array([outfull, infull, inbot, outbot],

reverse=true, col_wrap=true, row_wrap=true));

<image.png>

The only angles that really are needed to make this are the angle of the teeth and one additional angle, the angle of the ridge line or the tooth base (including any conical angle). I'm not sure how that angle is best defined. Maybe it's different for the two halves of the joint? Computing a bunch of other angles does not appear to be necessary, though maybe for figuring out how to adjust the tooth angle you need an extra computation. I think the tooth angle *should* be defined relative to the top line of the teeth (ridge line?), but your code defines it relative to absolute vertical, so as you change the conical angle the tooth angle changes. And if the conical angle is zero the tooth angle is not the specified angle. At least that appeared to be the case with the version you posted. When you organize the computation the way I did in my posted example the chamfers are trivial regardless of the angle of anything, though if you want to get the tooth angle relative to the ridge line some care is required. Did you look at how I did it? Using roundings instead of chamfers might be nice too, especially for joints at larger scale. I guess another question is whether chamfers should be absolute values rather than proportional to tooth size. In BOSL2 the undercores are used only for private globals, and all the global variables you have should actually be parameters in a library implementation. I mean, there's no harm in using underscores internally; I just find them annoying and hard to read. One reason to use them for internals is that nobody in their right mind would CHOOSE to prefix their variables with them. :) How fast does your existing code preview? Because the preview performance of the code I tried made preview unusable, even when I removed the chamfers and intersection with the tube. I assumed this was the result of having 36 objects unioned together, though even so it seemed oddly sluggish. I also noticed that intersecting with a tube produces a potential issue: the $fn for the tube needs to be a multiple of the tooth count, or the result looks funny. The Hirth joint looks interesting and useful so I think we'll get it into BOSL2 one way or another. Do you use this joint by gluing at the joint? Or by holding parts captive somehow so that shafts are locked at the joint? On Wed, Oct 30, 2024 at 9:52 PM Bob Carlson <bob@rjcarlson.com> wrote: > The current code renders 1 part in about 0.25 s, so I doubt you would have > much problem with the current performance. > > As it happens, I switched to using _name's in the code because I will be > offering it for inclusion in BOSL2. It’s also good for use in my own > library if that’s where it stays. I have full attachability working now and > the output looks very good. > > The valleys are chamfered too, at 50% of the ridge chamfer size so a > proper gap is left when the parts are together. If you look closely you can > see it in the demo code too. > > There are 3 angles I calculate. Tooth Angle is the angle between teeth > radially. It’s simple, 360/N. The other two are the groove angle and ridge > angle. These are calculated relative to horizontal. In a flat hirth joint, > they are plus and minus the same number. In a conical joint, it’s > different, but still measured relative to the XY plane. When I use them in > the code I believe it’s always in a call to a spherical transform. In those > calls 0 degrees is vertical, so I have to add 90. > > Adding the “bases” and getting the chamfers right in the conical cases was > REALLY tricky. It’s the conical parts that cause all the problems. > > You should see the finished code in an enhancement request to BOSL2 in a > few days. > > -Bob > > > On Oct 28, 2024, at 21:35, Adrian Mariano <avm4@cornell.edu> wrote: > > > > So Bob, you have said you don't care about speed, which is your choice, > obviously. But for me this code is intolerably slow. Preview is useless > even after I remove the chamfering and intersection to make it have > cylindrical edges. And render takes 20s with manifold. Because the > original code was unpreviewable I couldn't easily assess how well my > rewrite matched, but it previews instantly and renders in 0.1s. (Note: a > reason I care about preview is that I can color things that I overlay to > see for example if two things match.) > > > > Another few things. In BOSL2, global variables that start with > underscore are reserved for BOSL2 internal use, so you shouldn't be using > those. You could clobber an internal definition. (Not sure why anyone > would use variables that start with underscore as a choice---I find them > very annoying.) > > > > The second is that I think your code measures tooth angle relative to > the vertical instead of relative to the tooth ridge. This is not the > normal way that tooth angle would be measured, e.g. on a gear. It means > that actual angle is never what you specify. > > > > A third observation is that you should be chamfering the valleys just > like the peaks. Internal corners are stress concentration points on an > object and will weaken it. So my version can apply varying chamfers in > both places. > > > > I personally find the rewritten code simpler than the original, as well > as much faster, and there's probably room to clean it up more. (Could > probably compute inner shape from outer with a scale() computation for > example.) It does produce a polygonal result and could be intersected > with a tube like the original to fix that if you think it's necessary. I > imagine that one intersection wouldn't be a major drag on the speed. I > agree that trying to compute the profile on a circular arc would be a pain. > > > > include <BOSL2/std.scad> > > > > // Number of Teeth > > _n = 36; // Number Of Teeth > > > > // Inner Radius > > _ir = 30; > > // Outer Radius > > _or = 50; > > // Is the coupling conical? > > _conic = 15; > > // Tooth Profile Angle > > _profile = 90; // [60, 90] > > // Percentage of tooth height > > _chamfer = 5; // Default 5% > > _base = 1; > > > > function basic_profile(angle,chamfer_top, chamfer_bot) = > > let( > > width = tan(angle/2), > > pts = [ > > [0,(-1+chamfer_bot)*width,chamfer_bot], > > [0,-chamfer_top*width,1-chamfer_top] > > ], > > ) > > concat(pts, reverse(yflip(pts))); > > > > profwidth = tan(_profile/2); > > outside = _or*tan(180/_n); > > inside = _ir*tan(180/_n); > > > > prof_out = right(_or,scale(outside/profwidth,basic_profile(_profile, > _chamfer/100, _chamfer/200))); > > prof_in = right(_ir,scale(inside/profwidth,basic_profile(_profile, > _chamfer/100, _chamfer/200))); > > > > offset = (_or-_ir) * tan(_conic); > > > > outfull = up(offset,[for(i=lerpn(0,360,_n,endpoint=false)) > > each zrot(i,prof_out)]); > > infull = [for(i=lerpn(0,360,_n,endpoint=false)) > > each zrot(i,prof_in)]; > > > > inbot = [for(val=infull) [val.x,val.y,-_base]]; > > outbot = [for(val=outfull) [val.x,val.y,-_base]]; > > > > vnf_polyhedron(vnf_vertex_array([outfull, infull, inbot, outbot], > reverse=true, col_wrap=true, row_wrap=true)); > > > > <image.png> > > > > > > > > > > > >
M
mikeonenine@web.de
Thu, Oct 31, 2024 4:02 AM

Adrian Mariano wrote:

I think the tooth angle should be defined relative to the top line
of the teeth (ridge line?), but your code defines it relative to
absolute vertical, so as you change the conical angle the tooth angle
changes.  And if the conical angle is zero the tooth angle is not the
specified
angle.  At least that appeared to be the case with the version you
posted.

On Wed, Oct 30, 2024 at 9:52 PM Bob Carlson bob@rjcarlson.com wrote:

There are 3 angles I calculate. Tooth Angle is the angle between teeth
radially. It’s simple, 360/N. The other two are the groove angle and ridge
angle. These are calculated relative to horizontal. In a flat hirth joint,
they are plus and minus the same number. In a conical joint, it’s
different, but

Translating a polygon section of a spline up or down in the z-direction to get a conical Hirth joint would seem to save a lot of trouble. The ridge and groove angles stay the same, the spline width remains 360/n and the diameter doesn’t change, so the intersection is “straight” and you are only cutting off the apices of the polygon and not other bits and you know what you will get.

Adrian Mariano wrote: > I think the tooth angle *should* be defined relative to the top line > of the teeth (ridge line?), but your code defines it relative to > absolute vertical, so as you change the conical angle the tooth angle > changes. And if the conical angle is zero the tooth angle is not the > specified > angle. At least that appeared to be the case with the version you > posted. > > On Wed, Oct 30, 2024 at 9:52 PM Bob Carlson [bob@rjcarlson.com](mailto:bob@rjcarlson.com) wrote: > > > There are 3 angles I calculate. Tooth Angle is the angle between teeth > > radially. It’s simple, 360/N. The other two are the groove angle and ridge > > angle. These are calculated relative to horizontal. In a flat hirth joint, > > they are plus and minus the same number. In a conical joint, it’s > > different, but Translating a polygon section of a spline up or down in the z-direction to get a conical Hirth joint would seem to save a lot of trouble. The ridge and groove angles stay the same, the spline width remains 360/n and the diameter doesn’t change, so the intersection is “straight” and you are only cutting off the apices of the polygon and not other bits and you know what you will get.
JB
Jordan Brown
Thu, Oct 31, 2024 4:57 AM

On 10/30/2024 6:33 PM, Bob Carlson wrote:

On Oct 26, 2024, at 16:21, Jordan Brown
openscad@jordan.maileater.net wrote:

Also, a tidbit:  _chamferF() generates a conical figure that might as
well be a cone.  
    up(_conic + _chamferHeight) scale(1.5) zcyl(h = _toothHeight/2 + _conic, r1 = _or, r2 = 0, anchor=TOP);
Since it's anchored at the top, I didn't have to fiddle with making
sure that it was slightly larger than the thing it's cutting from and
could just scale it up a bit.

When I tried switching to a cone rather than rotate_extrude, the
rendering time went up by about 50% (roughly a quarter second to .4
seconds). So, I’ve kept the current code.

My gut reaction was that they should be almost identical, but then I
realized that I don't know how rotate_extrude decides how many sides to
put on an object.  Without looking at the sources, it looks like it
probably looks at the maximum X value to determine the radius and then
uses $fa/$fs/$fn as usual.  I would look at how many sides each is
ending up with, and why.

But a rotate_extrude of a triangle with one side on the Y axis produces
a cone, and if you put the top point of the triangle at [0,0] then
you'll get the same effect I wanted - scaling it up leaves the top part
all the same.

On 10/30/2024 6:33 PM, Bob Carlson wrote: > >> On Oct 26, 2024, at 16:21, Jordan Brown >> <openscad@jordan.maileater.net> wrote: >> >> Also, a tidbit:  _chamferF() generates a conical figure that might as >> well be a cone.   >>     up(_conic + _chamferHeight) scale(1.5) zcyl(h = _toothHeight/2 + _conic, r1 = _or, r2 = 0, anchor=TOP); >> Since it's anchored at the top, I didn't have to fiddle with making >> sure that it was slightly larger than the thing it's cutting from and >> could just scale it up a bit. > > When I tried switching to a cone rather than rotate_extrude, the > rendering time went up by about 50% (roughly a quarter second to .4 > seconds). So, I’ve kept the current code. > My gut reaction was that they should be almost identical, but then I realized that I don't know how rotate_extrude decides how many sides to put on an object.  Without looking at the sources, it looks like it probably looks at the maximum X value to determine the radius and then uses $fa/$fs/$fn as usual.  I would look at how many sides each is ending up with, and why. But a rotate_extrude of a triangle with one side on the Y axis produces a cone, and if you put the top point of the triangle at [0,0] then you'll get the same effect I wanted - scaling it up leaves the top part all the same.
M
mikeonenine@web.de
Thu, Oct 31, 2024 5:32 AM

Jordan Brown wrote:

On 10/30/2024 6:33 PM, Bob Carlson wrote:

On Oct 26, 2024, at 16:21, Jordan Brown
openscad@jordan.maileater.net wrote:

Also, a tidbit:  _chamferF() generates a conical figure that might as
well be a cone.  
    up(_conic + _chamferHeight) scale(1.5) zcyl(h = _toothHeight/2 + _conic, r1 = _or, r2 = 0, anchor=TOP);
Since it's anchored at the top, I didn't have to fiddle with making
sure that it was slightly larger than the thing it's cutting from and
could just scale it up a bit.

When I tried switching to a cone rather than rotate_extrude, the
rendering time went up by about 50% (roughly a quarter second to .4
seconds). So, I’ve kept the current code.

My gut reaction was that they should be almost identical, but then I
realized that I don't know how rotate_extrude decides how many sides to
put on an object.  Without looking at the sources, it looks like it
probably looks at the maximum X value to determine the radius and then
uses $fa/$fs/$fn as usual.  I would look at how many sides each is
ending up with, and why.

But a rotate_extrude of a triangle with one side on the Y axis produces
a cone, and if you put the top point of the triangle at [0,0] then
you'll get the same effect I wanted - scaling it up leaves the top part
all the same.

An anticone needs rotate_extrude?

$fn=100;

//Cone:

translate([-110, 0, 0])

rotate_extrude()

polygon([

[60, 0],

[60, 10],

[100, 0],

[100, 0],

]);

//Anticone:

translate([110, 0, 0])

rotate_extrude()

polygon([

[60, 0],

[60, 0],

[100, 10],

[100, 0],

]);

Jordan Brown wrote: > On 10/30/2024 6:33 PM, Bob Carlson wrote: > > > > On Oct 26, 2024, at 16:21, Jordan Brown > > > [openscad@jordan.maileater.net](mailto:openscad@jordan.maileater.net) wrote: > > > > > > Also, a tidbit:  _chamferF() generates a conical figure that might as > > > well be a cone.   > > >     up(_conic + _chamferHeight) scale(1.5) zcyl(h = _toothHeight/2 + _conic, r1 = _or, r2 = 0, anchor=TOP); > > > Since it's anchored at the top, I didn't have to fiddle with making > > > sure that it was slightly larger than the thing it's cutting from and > > > could just scale it up a bit. > > > > When I tried switching to a cone rather than rotate_extrude, the > > rendering time went up by about 50% (roughly a quarter second to .4 > > seconds). So, I’ve kept the current code. > > My gut reaction was that they should be almost identical, but then I > realized that I don't know how rotate_extrude decides how many sides to > put on an object.  Without looking at the sources, it looks like it > probably looks at the maximum X value to determine the radius and then > uses $fa/$fs/$fn as usual.  I would look at how many sides each is > ending up with, and why. > > But a rotate_extrude of a triangle with one side on the Y axis produces > a cone, and if you put the top point of the triangle at \[0,0\] then > you'll get the same effect I wanted - scaling it up leaves the top part > all the same. An anticone needs rotate_extrude? `$fn=100;` `//Cone:` `translate([-110, 0, 0])` `rotate_extrude()` `polygon([` `[60, 0],` `[60, 10],` `[100, 0],` `[100, 0],` `]);` `//Anticone:` `translate([110, 0, 0])` `rotate_extrude()` `polygon([` `[60, 0],` `[60, 0],` `[100, 10],` `[100, 0],` `]);`
JB
Jordan Brown
Thu, Oct 31, 2024 6:58 AM

On 10/30/2024 10:32 PM, Caddiy via Discuss wrote:

An anticone needs rotate_extrude?

I wouldn't call either of those shapes cones; I would call the first a
cylinder from which a point-down cone has been subtracted, and the
second a point-up cone from which a cylinder has been subtracted.

You could build either of them with rotate_extrude(), as you have, or
you could build them as the differences above.  Which is "best" probably
depends on whether what you have convenient is the coordinates of the
inner edge, or the coordinates of the point of the cone.

I'd give you difference-between-cone-and-cylinder examples, but I don't
have the coordinates of the point of the cone handy.  I'd have to
extrapolate from the upper side of the triangles.  That's not hard, but
it's midnight and I don't wanna :-)

On 10/30/2024 10:32 PM, Caddiy via Discuss wrote: > > An anticone needs rotate_extrude? > I wouldn't call either of those shapes cones; I would call the first a cylinder from which a point-down cone has been subtracted, and the second a point-up cone from which a cylinder has been subtracted. You could build either of them with rotate_extrude(), as you have, or you could build them as the differences above.  Which is "best" probably depends on whether what you have convenient is the coordinates of the inner edge, or the coordinates of the point of the cone. I'd give you difference-between-cone-and-cylinder examples, but I don't have the coordinates of the point of the cone handy.  I'd have to extrapolate from the upper side of the triangles.  That's not hard, but it's midnight and I don't wanna :-)
JD
John David
Thu, Oct 31, 2024 10:51 AM

This discussion on the cone is interesting.  I had to look it up:

"The meaning of CONE is a solid generated by rotating a right triangle
about one of its legs —called also right circular cone."
-- Merriam-Webster  Dictionary

But in the smithy we used to use both solid and hollow "cones" and not all
of them went to a full point. Then I remembered that a truncated cone is
called a 'frustum'...

All that said, I can see defining a primitive which creates both solid and
hollow cones and frustums, and the code snippet above shows how simple that
code can be.  Maybe it would even be fast ;-)

EBo --

On Thu, Oct 31, 2024 at 2:58 AM Jordan Brown via Discuss <
discuss@lists.openscad.org> wrote:

On 10/30/2024 10:32 PM, Caddiy via Discuss wrote:

An anticone needs rotate_extrude?

I wouldn't call either of those shapes cones; I would call the first a
cylinder from which a point-down cone has been subtracted, and the second a
point-up cone from which a cylinder has been subtracted.

You could build either of them with rotate_extrude(), as you have, or you
could build them as the differences above.  Which is "best" probably
depends on whether what you have convenient is the coordinates of the inner
edge, or the coordinates of the point of the cone.

I'd give you difference-between-cone-and-cylinder examples, but I don't
have the coordinates of the point of the cone handy.  I'd have to
extrapolate from the upper side of the triangles.  That's not hard, but
it's midnight and I don't wanna :-)


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

This discussion on the cone is interesting. I had to look it up: "The meaning of CONE is a solid generated by rotating a right triangle about one of its legs —called also right circular cone." -- Merriam-Webster Dictionary But in the smithy we used to use both solid and hollow "cones" and not all of them went to a full point. Then I remembered that a truncated cone is called a 'frustum'... All that said, I can see defining a primitive which creates both solid and hollow cones and frustums, and the code snippet above shows how simple that code can be. Maybe it would even be fast ;-) EBo -- On Thu, Oct 31, 2024 at 2:58 AM Jordan Brown via Discuss < discuss@lists.openscad.org> wrote: > On 10/30/2024 10:32 PM, Caddiy via Discuss wrote: > > An anticone needs rotate_extrude? > > > I wouldn't call either of those shapes cones; I would call the first a > cylinder from which a point-down cone has been subtracted, and the second a > point-up cone from which a cylinder has been subtracted. > > You could build either of them with rotate_extrude(), as you have, or you > could build them as the differences above. Which is "best" probably > depends on whether what you have convenient is the coordinates of the inner > edge, or the coordinates of the point of the cone. > > I'd give you difference-between-cone-and-cylinder examples, but I don't > have the coordinates of the point of the cone handy. I'd have to > extrapolate from the upper side of the triangles. That's not hard, but > it's midnight and I don't wanna :-) > > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org >
NH
nop head
Thu, Oct 31, 2024 11:22 AM

I think cylinder already does that. If you specify two radii you get a
frustum. I can't remember if zero is allowed for a cone.

On Thu, 31 Oct 2024, 10:51 John David via Discuss, <
discuss@lists.openscad.org> wrote:

This discussion on the cone is interesting.  I had to look it up:

"The meaning of CONE is a solid generated by rotating a right triangle
about one of its legs —called also right circular cone."
-- Merriam-Webster  Dictionary

But in the smithy we used to use both solid and hollow "cones" and not all
of them went to a full point. Then I remembered that a truncated cone is
called a 'frustum'...

All that said, I can see defining a primitive which creates both solid and
hollow cones and frustums, and the code snippet above shows how simple that
code can be.  Maybe it would even be fast ;-)

EBo --

On Thu, Oct 31, 2024 at 2:58 AM Jordan Brown via Discuss <
discuss@lists.openscad.org> wrote:

On 10/30/2024 10:32 PM, Caddiy via Discuss wrote:

An anticone needs rotate_extrude?

I wouldn't call either of those shapes cones; I would call the first a
cylinder from which a point-down cone has been subtracted, and the second a
point-up cone from which a cylinder has been subtracted.

You could build either of them with rotate_extrude(), as you have, or you
could build them as the differences above.  Which is "best" probably
depends on whether what you have convenient is the coordinates of the inner
edge, or the coordinates of the point of the cone.

I'd give you difference-between-cone-and-cylinder examples, but I don't
have the coordinates of the point of the cone handy.  I'd have to
extrapolate from the upper side of the triangles.  That's not hard, but
it's midnight and I don't wanna :-)


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 think cylinder already does that. If you specify two radii you get a frustum. I can't remember if zero is allowed for a cone. On Thu, 31 Oct 2024, 10:51 John David via Discuss, < discuss@lists.openscad.org> wrote: > This discussion on the cone is interesting. I had to look it up: > > "The meaning of CONE is a solid generated by rotating a right triangle > about one of its legs —called also right circular cone." > -- Merriam-Webster Dictionary > > But in the smithy we used to use both solid and hollow "cones" and not all > of them went to a full point. Then I remembered that a truncated cone is > called a 'frustum'... > > All that said, I can see defining a primitive which creates both solid and > hollow cones and frustums, and the code snippet above shows how simple that > code can be. Maybe it would even be fast ;-) > > EBo -- > > On Thu, Oct 31, 2024 at 2:58 AM Jordan Brown via Discuss < > discuss@lists.openscad.org> wrote: > >> On 10/30/2024 10:32 PM, Caddiy via Discuss wrote: >> >> An anticone needs rotate_extrude? >> >> >> I wouldn't call either of those shapes cones; I would call the first a >> cylinder from which a point-down cone has been subtracted, and the second a >> point-up cone from which a cylinder has been subtracted. >> >> You could build either of them with rotate_extrude(), as you have, or you >> could build them as the differences above. Which is "best" probably >> depends on whether what you have convenient is the coordinates of the inner >> edge, or the coordinates of the point of the cone. >> >> I'd give you difference-between-cone-and-cylinder examples, but I don't >> have the coordinates of the point of the cone handy. I'd have to >> extrapolate from the upper side of the triangles. That's not hard, but >> it's midnight and I don't wanna :-) >> >> _______________________________________________ >> 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
Thu, Oct 31, 2024 12:49 PM

On 31/10/2024 10:51, John David via Discuss wrote:

This discussion on the cone is interesting.  I had to look it up:

  "The meaning of CONE is a solid generated by rotating a right
triangle about one of its legs —called also right circular cone."
        -- Merriam-Webster  Dictionary

But in the smithy we used to use both solid and hollow "cones" and not
all of them went to a full point. Then I remembered that a truncated
cone is called a 'frustum'...

All that said, I can see defining a primitive which creates both solid
and hollow cones and frustums, and the code snippet above shows how
simple that code can be.  Maybe it would even be fast ;-)

  EBo --

Being pedantic...

I've no idea what a 'leg' of a triangle is, and if there is more than one.

Referring to the Oxford English Dictionary,  (this is for the English
language, not American English)

'A cone is defined as a solid figure with a circular (or other curved)
plane base, tapering to a point.'

(It does not state that the point has to be above the centre of the base)

As NopHead mentioned openscad allows two diameters, so some frustums can
be created.

 A frustum is defined as 'the part of a cone or pyramid intercepted
between two planes'.

Openscad can not directly implement all versions of cones, since in
cone() the point is above the centre of the plane,  nor frustums, since
the planes in cone() are parallel.

https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Primitive_Solids

Of course, applying various translations and differences, etc., you can
generate the whole range of cones and fustrums.

The openscad names are a bit awry, in some cases, since  cone() refers
only to a subset of cones,  cubes() are cuboids, etc.

On 31/10/2024 10:51, John David via Discuss wrote: > This discussion on the cone is interesting.  I had to look it up: > >   "The meaning of CONE is a solid generated by rotating a right > triangle about one of its legs —called also right circular cone." >         -- Merriam-Webster  Dictionary > > But in the smithy we used to use both solid and hollow "cones" and not > all of them went to a full point. Then I remembered that a truncated > cone is called a 'frustum'... > > All that said, I can see defining a primitive which creates both solid > and hollow cones and frustums, and the code snippet above shows how > simple that code can be.  Maybe it would even be fast ;-) > >   EBo -- Being pedantic... I've no idea what a 'leg' of a triangle is, and if there is more than one. Referring to the Oxford English Dictionary,  (this is for the English language, not American English) 'A cone is defined as a solid figure with a circular (or other curved) plane base, tapering to a point.' (It does not state that the point has to be above the centre of the base) As NopHead mentioned openscad allows two diameters, so some frustums can be created.  A frustum is defined as 'the part of a cone or pyramid intercepted between two planes'. Openscad can not directly implement all versions of cones, since in cone() the point is above the centre of the plane,  nor frustums, since the planes in cone() are parallel. https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Primitive_Solids Of course, applying various translations and differences, etc., you can generate the whole range of cones and fustrums. The openscad names are a bit awry, in some cases, since  cone() refers only to a subset of cones,  cubes() are cuboids, etc.
M
mikeonenine@web.de
Thu, Oct 31, 2024 1:52 PM

Jordan Brown wrote:

On 10/30/2024 10:32 PM, Caddiy via Discuss wrote:

An anticone needs rotate_extrude?

You could build either of them with rotate_extrude(), as you have, or
you could build them as the differences above.  Which is "best" probably
depends on whether what you have convenient is the coordinates of the
inner edge, or the coordinates of the point of the cone.

What you have is the height by which you have raised or lowered the spline polygon (+10 for example here), an inside radius (60) and an outside radius (100). The angle would be arctan 10 / (100-60) if that was of interest, but I think it would be easier to deal with linear measurements. To get the anticone from the cone, just swap the coordinates around a bit.

In the code above, two of the coordinates are the same, giving 4 coordinates for a triangle, which is one more than is required to define a triangle, as I originally had in mind to extend the base, but changed my mind and forgot to remove the extra coordinate. 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.

See, and be amazed:

$fn=100;

//Cone:

rotate_extrude()

polygon([

[60, 0],

[60, 10+20],

[100, 0+20],

[100, 0],

]);

Jordan Brown wrote: > On 10/30/2024 10:32 PM, Caddiy via Discuss wrote: > > > An anticone needs rotate_extrude? > > You could build either of them with rotate_extrude(), as you have, or > you could build them as the differences above.  Which is "best" probably > depends on whether what you have convenient is the coordinates of the > inner edge, or the coordinates of the point of the cone. What you have is the height by which you have raised or lowered the spline polygon (+10 for example here), an inside radius (60) and an outside radius (100). The angle would be arctan 10 / (100-60) if that was of interest, but I think it would be easier to deal with linear measurements. To get the anticone from the cone, just swap the coordinates around a bit. In the code above, two of the coordinates are the same, giving 4 coordinates for a triangle, which is one more than is required to define a triangle, as I originally had in mind to extend the base, but changed my mind and forgot to remove the extra coordinate. 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. See, and be amazed: `$fn=100;` `//Cone:` `rotate_extrude()` `polygon([` `[60, 0],` `[60, 10+20],` `[100, 0+20],` `[100, 0],` `]);`
JB
Jordan Brown
Thu, Oct 31, 2024 4:54 PM

On 10/31/2024 4:22 AM, nop head via Discuss wrote:

I think cylinder already does that. If you specify two radii you get a
frustum. I can't remember if zero is allowed for a cone.

Yes, and yes.

On 10/31/2024 4:22 AM, nop head via Discuss wrote: > > I think cylinder already does that. If you specify two radii you get a > frustum. I can't remember if zero is allowed for a cone. > Yes, and yes.
JB
Jordan Brown
Thu, Oct 31, 2024 5:16 PM

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.

> 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.
M
mikeonenine@web.de
Thu, Oct 31, 2024 7:36 PM

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.

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.
JB
Jordan Brown
Thu, Oct 31, 2024 8:19 PM

On 10/31/2024 12:36 PM, Caddiy via Discuss wrote:

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”.

I don't know beans about a conical face spline joint, and am having a
hard time following your description.

I just know that the OP's model had teeth with bottoms that touched a
cone, that needed to have the bottom little bit differenced off.  The OP
did this using a rotate-extruded triangle, when a plain old cone would
work fine and be simpler.

OP's solution:

module _chamferF() {
    A = -_toothHeight/2 - .1;
    B = -_toothHeight/2 + _chamferHeight;
    
    pts = [[0, _conic], 
           [_or+tiny, A], 
           [_or+tiny, B]];
    #rotate_extrude(angle = 360)
    polygon(pts);
}

Note:  that's a "hollow" cone.

Simpler solution:

module _chamferF() {
#up(_conic + _chamferHeight)
scale(1.5)
zcyl(h = _toothHeight/2 + _conic, r1 = _or, r2 = 0, anchor=TOP);
}

On 10/31/2024 12:36 PM, Caddiy via Discuss wrote: > > 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”. > I don't know beans about a conical face spline joint, and am having a hard time following your description. I just know that the OP's model had teeth with bottoms that touched a cone, that needed to have the bottom little bit differenced off.  The OP did this using a rotate-extruded triangle, when a plain old cone would work fine and be simpler. OP's solution: module _chamferF() {     A = -_toothHeight/2 - .1;     B = -_toothHeight/2 + _chamferHeight;          pts = [[0, _conic],            [_or+tiny, A],            [_or+tiny, B]];     #rotate_extrude(angle = 360)     polygon(pts); } Note:  that's a "hollow" cone. Simpler solution: module _chamferF() { #up(_conic + _chamferHeight) scale(1.5) zcyl(h = _toothHeight/2 + _conic, r1 = _or, r2 = 0, anchor=TOP); }
BC
Bob Carlson
Thu, Oct 31, 2024 8:27 PM

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 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

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> 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>
AM
Adrian Mariano
Thu, Oct 31, 2024 8:39 PM

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> 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
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


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

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> 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> > 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 > > > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org >