Hi,

Guest

DH

Daniel Harvey

Tue, Feb 14, 2023 4:27 AM

Hello,

It's possible that I have re-invented the wheel here, but I thought I would

share a simple solution I came up with to create fillets for the

intersection of two objects. It requires the objects to be defined with a

parametric size-offset, and it uses an iterative approach with hull() to

create a fillet. Here's an example with a cuboid (box()) embedded in a

cylinder (shaft()).

module shaft(dd=0) {

rotate([0,0,-10]) rotate([0,90,0]) cylinder(d=22+dd, h=100, $fn=60,

center=true);

}

module box(dd=0) {

translate([0,5,5]) cube([15+dd,18+dd,25+dd], center=true);

}

module filletSlice(ro, ang) {

p = ro * [(1-cos(ang)), (1-sin(ang))];

intersection() {

shaft(p.x);

box(p.y);

}

}

da = 10;

for (a=[0:da:90-da]) {

hull() {

filletSlice(2, a);

filletSlice(2, a+da);

}

}

shaft();

box();

Hello,
It's possible that I have re-invented the wheel here, but I thought I would
share a simple solution I came up with to create fillets for the
intersection of two objects. It requires the objects to be defined with a
parametric size-offset, and it uses an iterative approach with hull() to
create a fillet. Here's an example with a cuboid (box()) embedded in a
cylinder (shaft()).
module shaft(dd=0) {
rotate([0,0,-10]) rotate([0,90,0]) cylinder(d=22+dd, h=100, $fn=60,
center=true);
}
module box(dd=0) {
translate([0,5,5]) cube([15+dd,18+dd,25+dd], center=true);
}
module filletSlice(ro, ang) {
p = ro * [(1-cos(ang)), (1-sin(ang))];
intersection() {
shaft(p.x);
box(p.y);
}
}
da = 10;
for (a=[0:da:90-da]) {
hull() {
filletSlice(2, a);
filletSlice(2, a+da);
}
}
shaft();
box();

SP

Sanjeev Prabhakar

Tue, Feb 14, 2023 12:20 PM

It looks great, although not gone in detail.

Does it work for all type of solid to solid intersections?

On Tue, 14 Feb, 2023, 9:58 am Daniel Harvey, dwaharvey@gmail.com wrote:

Hello,

It's possible that I have re-invented the wheel here, but I thought I

would share a simple solution I came up with to create fillets for the

intersection of two objects. It requires the objects to be defined with a

parametric size-offset, and it uses an iterative approach with hull() to

create a fillet. Here's an example with a cuboid (box()) embedded in a

cylinder (shaft()).

module shaft(dd=0) {

rotate([0,0,-10]) rotate([0,90,0]) cylinder(d=22+dd, h=100, $fn=60,

center=true);

}

module box(dd=0) {

translate([0,5,5]) cube([15+dd,18+dd,25+dd], center=true);

}

module filletSlice(ro, ang) {

p = ro * [(1-cos(ang)), (1-sin(ang))];

intersection() {

shaft(p.x);

box(p.y);

}

}

da = 10;

for (a=[0:da:90-da]) {

hull() {

filletSlice(2, a);

filletSlice(2, a+da);

}

}

shaft();

box();

OpenSCAD mailing list

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

It looks great, although not gone in detail.
Does it work for all type of solid to solid intersections?
On Tue, 14 Feb, 2023, 9:58 am Daniel Harvey, <dwaharvey@gmail.com> wrote:
> Hello,
> It's possible that I have re-invented the wheel here, but I thought I
> would share a simple solution I came up with to create fillets for the
> intersection of two objects. It requires the objects to be defined with a
> parametric size-offset, and it uses an iterative approach with hull() to
> create a fillet. Here's an example with a cuboid (box()) embedded in a
> cylinder (shaft()).
>
> module shaft(dd=0) {
> rotate([0,0,-10]) rotate([0,90,0]) cylinder(d=22+dd, h=100, $fn=60,
> center=true);
> }
>
> module box(dd=0) {
> translate([0,5,5]) cube([15+dd,18+dd,25+dd], center=true);
> }
>
> module filletSlice(ro, ang) {
> p = ro * [(1-cos(ang)), (1-sin(ang))];
> intersection() {
> shaft(p.x);
> box(p.y);
> }
> }
>
> da = 10;
> for (a=[0:da:90-da]) {
> hull() {
> filletSlice(2, a);
> filletSlice(2, a+da);
> }
> }
> shaft();
> box();
>
> _______________________________________________
> OpenSCAD mailing list
> To unsubscribe send an email to discuss-leave@lists.openscad.org
>

DH

Daniel Harvey

Tue, Feb 14, 2023 3:14 PM

There's the obvious limitation that if the area of intersection has native

curvature then the fillet will pull away from the part (because hull() {

object1() } != object1() in that area). So if eg object1() had a wave

pattern, like some corrugated decking material... the result would not be

good.

On a case by case basis this sort of thing could probably be dealt with by

iterating over another parameter, and intersecting with a third parametric

object that creates small interpolations of the negative curve. But I am

not sure how this will affect the computation time (geometric increase in

calls to hull(), though each call on a much smaller object).

On Tue, Feb 14, 2023 at 5:20 AM Sanjeev Prabhakar sprabhakar2006@gmail.com

wrote:

It looks great, although not gone in detail.

Does it work for all type of solid to solid intersections?

On Tue, 14 Feb, 2023, 9:58 am Daniel Harvey, dwaharvey@gmail.com wrote:

Hello,

It's possible that I have re-invented the wheel here, but I thought I

would share a simple solution I came up with to create fillets for the

intersection of two objects. It requires the objects to be defined with a

parametric size-offset, and it uses an iterative approach with hull() to

create a fillet. Here's an example with a cuboid (box()) embedded in a

cylinder (shaft()).

module shaft(dd=0) {

rotate([0,0,-10]) rotate([0,90,0]) cylinder(d=22+dd, h=100, $fn=60,

center=true);

}

module box(dd=0) {

translate([0,5,5]) cube([15+dd,18+dd,25+dd], center=true);

}

module filletSlice(ro, ang) {

p = ro * [(1-cos(ang)), (1-sin(ang))];

intersection() {

shaft(p.x);

box(p.y);

}

}

da = 10;

for (a=[0:da:90-da]) {

hull() {

filletSlice(2, a);

filletSlice(2, a+da);

}

}

shaft();

box();

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

There's the obvious limitation that if the area of intersection has native
curvature then the fillet will pull away from the part (because hull() {
object1() } != object1() in that area). So if eg object1() had a wave
pattern, like some corrugated decking material... the result would not be
good.
On a case by case basis this sort of thing could probably be dealt with by
iterating over another parameter, and intersecting with a third parametric
object that creates small interpolations of the negative curve. But I am
not sure how this will affect the computation time (geometric increase in
calls to hull(), though each call on a much smaller object).
On Tue, Feb 14, 2023 at 5:20 AM Sanjeev Prabhakar <sprabhakar2006@gmail.com>
wrote:
> It looks great, although not gone in detail.
> Does it work for all type of solid to solid intersections?
>
> On Tue, 14 Feb, 2023, 9:58 am Daniel Harvey, <dwaharvey@gmail.com> wrote:
>
>> Hello,
>> It's possible that I have re-invented the wheel here, but I thought I
>> would share a simple solution I came up with to create fillets for the
>> intersection of two objects. It requires the objects to be defined with a
>> parametric size-offset, and it uses an iterative approach with hull() to
>> create a fillet. Here's an example with a cuboid (box()) embedded in a
>> cylinder (shaft()).
>>
>> module shaft(dd=0) {
>> rotate([0,0,-10]) rotate([0,90,0]) cylinder(d=22+dd, h=100, $fn=60,
>> center=true);
>> }
>>
>> module box(dd=0) {
>> translate([0,5,5]) cube([15+dd,18+dd,25+dd], center=true);
>> }
>>
>> module filletSlice(ro, ang) {
>> p = ro * [(1-cos(ang)), (1-sin(ang))];
>> intersection() {
>> shaft(p.x);
>> box(p.y);
>> }
>> }
>>
>> da = 10;
>> for (a=[0:da:90-da]) {
>> hull() {
>> filletSlice(2, a);
>> filletSlice(2, a+da);
>> }
>> }
>> shaft();
>> box();
>>
>> _______________________________________________
>> 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
>

AM

Adrian Mariano

Tue, Feb 14, 2023 10:01 PM

Daniel, I think what you really mean is that if the object is not convex in

the area around the intersection then you're in trouble. There's no good

solution to this problem. The hull() operation is called CONVEX hull for a

reason. But I think this is an interesting approach, and I, at least, have

not seen it before. (And I'm really interested in rounding.)

I wrote a version that assumes you have two children at unit scale and uses

scale() to make the joined object. That doesn't require having a

parametrized module for each object, though it's limited in other ways.

With BOSL2 it would be natural to combine at least the translate and rotate

operators into a single matrix that you pass in. I also added a chamfer

option. (Note that there's no way to avoid the code duplication because

you can't pass children separately to a submodule.)

// Invoke with 2 children that are at unit scale and create a

// fillet joint between them, while applying specified transformations.

//

// r = radius of fillet (relative to scale of children)

// T0,R0,S0 = translation, rotation and scaling for object 0

// T1,R1,S1 = translation, rotation and scaling for object 1

// steps = number of steps in fillet

// chamfer = set true to get chamfer instead of rounding

module fillet_join(r, T0,R0,S0, T1,R1,S1, steps=10, chamfer=false)

{

assert($children==2);

da=1/steps;

for(a=[0:da:1-da/2]){

hull() {

first_offset = chamfer ? r * [a,1-a]

: r * [1-cos(90*a), 1-sin(90*a)];

first_scale0 = [for(s=S0) first_offset[0]+s];

first_scale1 = [for(s=S1) first_offset[1]+s];

second_offset = chamfer ? r * [a+da, 1-a-da]

: r * [1-cos(90*(a+da)),

1-sin(90*(a+da))];

second_scale0 = [for(s=S0) second_offset[0]+s];

second_scale1 = [for(s=S1) second_offset[1]+s];

intersection(){

translate(T0)rotate(R0)scale(first_scale0) children(0);

translate(T1)rotate(R1)scale(first_scale1) children(1);

}

intersection(){

translate(T0)rotate(R0)scale(second_scale0) children(0);

translate(T1)rotate(R1)scale(second_scale1) children(1);

}

}

}

translate(T0)rotate(R0)scale(S0) children(0);

translate(T1)rotate(R1)scale(S1) children(1);

}

fillet_join(3,[0,0,3], [0,90,-10], [22,22,100],

[0,6,6], [0,20,0], [15,20,28],chamfer=false)

{

cylinder(d=1,center=true,$fn=64);

cube(center=true);

}

[image: image.png]

On Tue, Feb 14, 2023 at 10:15 AM Daniel Harvey dwaharvey@gmail.com wrote:

There's the obvious limitation that if the area of intersection has native

curvature then the fillet will pull away from the part (because hull() {

object1() } != object1() in that area). So if eg object1() had a wave

pattern, like some corrugated decking material... the result would not be

good.

On a case by case basis this sort of thing could probably be dealt with by

iterating over another parameter, and intersecting with a third parametric

object that creates small interpolations of the negative curve. But I am

not sure how this will affect the computation time (geometric increase in

calls to hull(), though each call on a much smaller object).

On Tue, Feb 14, 2023 at 5:20 AM Sanjeev Prabhakar <

sprabhakar2006@gmail.com> wrote:

It looks great, although not gone in detail.

Does it work for all type of solid to solid intersections?

On Tue, 14 Feb, 2023, 9:58 am Daniel Harvey, dwaharvey@gmail.com wrote:

It's possible that I have re-invented the wheel here, but I thought I

would share a simple solution I came up with to create fillets for the

intersection of two objects. It requires the objects to be defined with a

parametric size-offset, and it uses an iterative approach with hull() to

create a fillet. Here's an example with a cuboid (box()) embedded in a

cylinder (shaft()).

rotate([0,0,-10]) rotate([0,90,0]) cylinder(d=22+dd, h=100, $fn=60,

center=true);

}

module box(dd=0) {

translate([0,5,5]) cube([15+dd,18+dd,25+dd], center=true);

}

p = ro * [(1-cos(ang)), (1-sin(ang))];

intersection() {

shaft(p.x);

box(p.y);

}

}

for (a=[0:da:90-da]) {

hull() {

filletSlice(2, a);

filletSlice(2, a+da);

}

}

shaft();

box();

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

Daniel, I think what you really mean is that if the object is not convex in
the area around the intersection then you're in trouble. There's no good
solution to this problem. The hull() operation is called CONVEX hull for a
reason. But I think this is an interesting approach, and I, at least, have
not seen it before. (And I'm really interested in rounding.)
I wrote a version that assumes you have two children at unit scale and uses
scale() to make the joined object. That doesn't require having a
parametrized module for each object, though it's limited in other ways.
With BOSL2 it would be natural to combine at least the translate and rotate
operators into a single matrix that you pass in. I also added a chamfer
option. (Note that there's no way to avoid the code duplication because
you can't pass children separately to a submodule.)
// Invoke with 2 children that are at unit scale and create a
// fillet joint between them, while applying specified transformations.
//
// r = radius of fillet (relative to scale of children)
// T0,R0,S0 = translation, rotation and scaling for object 0
// T1,R1,S1 = translation, rotation and scaling for object 1
// steps = number of steps in fillet
// chamfer = set true to get chamfer instead of rounding
module fillet_join(r, T0,R0,S0, T1,R1,S1, steps=10, chamfer=false)
{
assert($children==2);
da=1/steps;
for(a=[0:da:1-da/2]){
hull() {
first_offset = chamfer ? r * [a,1-a]
: r * [1-cos(90*a), 1-sin(90*a)];
first_scale0 = [for(s=S0) first_offset[0]+s];
first_scale1 = [for(s=S1) first_offset[1]+s];
second_offset = chamfer ? r * [a+da, 1-a-da]
: r * [1-cos(90*(a+da)),
1-sin(90*(a+da))];
second_scale0 = [for(s=S0) second_offset[0]+s];
second_scale1 = [for(s=S1) second_offset[1]+s];
intersection(){
translate(T0)rotate(R0)scale(first_scale0) children(0);
translate(T1)rotate(R1)scale(first_scale1) children(1);
}
intersection(){
translate(T0)rotate(R0)scale(second_scale0) children(0);
translate(T1)rotate(R1)scale(second_scale1) children(1);
}
}
}
translate(T0)rotate(R0)scale(S0) children(0);
translate(T1)rotate(R1)scale(S1) children(1);
}
fillet_join(3,[0,0,3], [0,90,-10], [22,22,100],
[0,6,6], [0,20,0], [15,20,28],chamfer=false)
{
cylinder(d=1,center=true,$fn=64);
cube(center=true);
}
[image: image.png]
On Tue, Feb 14, 2023 at 10:15 AM Daniel Harvey <dwaharvey@gmail.com> wrote:
> There's the obvious limitation that if the area of intersection has native
> curvature then the fillet will pull away from the part (because hull() {
> object1() } != object1() in that area). So if eg object1() had a wave
> pattern, like some corrugated decking material... the result would not be
> good.
> On a case by case basis this sort of thing could probably be dealt with by
> iterating over another parameter, and intersecting with a third parametric
> object that creates small interpolations of the negative curve. But I am
> not sure how this will affect the computation time (geometric increase in
> calls to hull(), though each call on a much smaller object).
>
> On Tue, Feb 14, 2023 at 5:20 AM Sanjeev Prabhakar <
> sprabhakar2006@gmail.com> wrote:
>
>> It looks great, although not gone in detail.
>> Does it work for all type of solid to solid intersections?
>>
>> On Tue, 14 Feb, 2023, 9:58 am Daniel Harvey, <dwaharvey@gmail.com> wrote:
>>
>>> Hello,
>>> It's possible that I have re-invented the wheel here, but I thought I
>>> would share a simple solution I came up with to create fillets for the
>>> intersection of two objects. It requires the objects to be defined with a
>>> parametric size-offset, and it uses an iterative approach with hull() to
>>> create a fillet. Here's an example with a cuboid (box()) embedded in a
>>> cylinder (shaft()).
>>>
>>> module shaft(dd=0) {
>>> rotate([0,0,-10]) rotate([0,90,0]) cylinder(d=22+dd, h=100, $fn=60,
>>> center=true);
>>> }
>>>
>>> module box(dd=0) {
>>> translate([0,5,5]) cube([15+dd,18+dd,25+dd], center=true);
>>> }
>>>
>>> module filletSlice(ro, ang) {
>>> p = ro * [(1-cos(ang)), (1-sin(ang))];
>>> intersection() {
>>> shaft(p.x);
>>> box(p.y);
>>> }
>>> }
>>>
>>> da = 10;
>>> for (a=[0:da:90-da]) {
>>> hull() {
>>> filletSlice(2, a);
>>> filletSlice(2, a+da);
>>> }
>>> }
>>> shaft();
>>> box();
>>>
>>> _______________________________________________
>>> 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
>

SP

Sanjeev Prabhakar

Wed, Feb 15, 2023 1:49 AM

If the points of intersection between the 2 solids can be found then

creating fillet would be possible.

3 list of intersection points would be required

a. both the solids at their original dimensions

b.1st solid at original dimension and 2nd solid at offset = the fillet

radius (approximate)

c.1st solid at offset= the fillet radius and 2nd solid at original dimension

with the above 3 list of points

group the points e.g. first point of each list and create a fillet arc and

so on

finally create a polyheadron with all the fillet arcs

this works in most of the cases

On Wed, 15 Feb 2023, 03:32 Adrian Mariano, avm4@cornell.edu wrote:

Daniel, I think what you really mean is that if the object is not convex

in the area around the intersection then you're in trouble. There's no

good solution to this problem. The hull() operation is called CONVEX hull

for a reason. But I think this is an interesting approach, and I, at

least, have not seen it before. (And I'm really interested in rounding.)

I wrote a version that assumes you have two children at unit scale and

uses scale() to make the joined object. That doesn't require having a

parametrized module for each object, though it's limited in other ways.

With BOSL2 it would be natural to combine at least the translate and rotate

operators into a single matrix that you pass in. I also added a chamfer

option. (Note that there's no way to avoid the code duplication because

you can't pass children separately to a submodule.)

// Invoke with 2 children that are at unit scale and create a

// fillet joint between them, while applying specified transformations.

//

// r = radius of fillet (relative to scale of children)

// T0,R0,S0 = translation, rotation and scaling for object 0

// T1,R1,S1 = translation, rotation and scaling for object 1

// steps = number of steps in fillet

// chamfer = set true to get chamfer instead of rounding

module fillet_join(r, T0,R0,S0, T1,R1,S1, steps=10, chamfer=false)

{

assert($children==2);

da=1/steps;

for(a=[0:da:1-da/2]){

hull() {

first_offset = chamfer ? r * [a,1-a]

: r * [1-cos(90*a), 1-sin(90*a)];

first_scale0 = [for(s=S0) first_offset[0]+s];

first_scale1 = [for(s=S1) first_offset[1]+s];

second_offset = chamfer ? r * [a+da, 1-a-da]

: r * [1-cos(90*(a+da)),

1-sin(90*(a+da))];

second_scale0 = [for(s=S0) second_offset[0]+s];

second_scale1 = [for(s=S1) second_offset[1]+s];

intersection(){

translate(T0)rotate(R0)scale(first_scale0) children(0);

translate(T1)rotate(R1)scale(first_scale1) children(1);

}

intersection(){

translate(T0)rotate(R0)scale(second_scale0) children(0);

translate(T1)rotate(R1)scale(second_scale1) children(1);

}

}

}

translate(T0)rotate(R0)scale(S0) children(0);

translate(T1)rotate(R1)scale(S1) children(1);

}

fillet_join(3,[0,0,3], [0,90,-10], [22,22,100],

[0,6,6], [0,20,0], [15,20,28],chamfer=false)

{

cylinder(d=1,center=true,$fn=64);

cube(center=true);

}

[image: image.png]

On Tue, Feb 14, 2023 at 10:15 AM Daniel Harvey dwaharvey@gmail.com

wrote:

There's the obvious limitation that if the area of intersection has

native curvature then the fillet will pull away from the part (because

hull() { object1() } != object1() in that area). So if eg object1() had a

wave pattern, like some corrugated decking material... the result would not

be good.

On a case by case basis this sort of thing could probably be dealt with

by iterating over another parameter, and intersecting with a third

parametric object that creates small interpolations of the negative curve.

But I am not sure how this will affect the computation time (geometric

increase in calls to hull(), though each call on a much smaller object).

On Tue, Feb 14, 2023 at 5:20 AM Sanjeev Prabhakar <

sprabhakar2006@gmail.com> wrote:

Does it work for all type of solid to solid intersections?

On Tue, 14 Feb, 2023, 9:58 am Daniel Harvey, dwaharvey@gmail.com

wrote:

It's possible that I have re-invented the wheel here, but I thought I

would share a simple solution I came up with to create fillets for the

intersection of two objects. It requires the objects to be defined with a

parametric size-offset, and it uses an iterative approach with hull() to

create a fillet. Here's an example with a cuboid (box()) embedded in a

cylinder (shaft()).

rotate([0,0,-10]) rotate([0,90,0]) cylinder(d=22+dd, h=100, $fn=60,

center=true);

}

module box(dd=0) {

translate([0,5,5]) cube([15+dd,18+dd,25+dd], center=true);

}

p = ro * [(1-cos(ang)), (1-sin(ang))];

intersection() {

shaft(p.x);

box(p.y);

}

}

for (a=[0:da:90-da]) {

hull() {

filletSlice(2, a);

filletSlice(2, a+da);

}

}

shaft();

box();

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

If the points of intersection between the 2 solids can be found then
creating fillet would be possible.
3 list of intersection points would be required
a. both the solids at their original dimensions
b.1st solid at original dimension and 2nd solid at offset = the fillet
radius (approximate)
c.1st solid at offset= the fillet radius and 2nd solid at original dimension
with the above 3 list of points
group the points e.g. first point of each list and create a fillet arc and
so on
finally create a polyheadron with all the fillet arcs
this works in most of the cases
On Wed, 15 Feb 2023, 03:32 Adrian Mariano, <avm4@cornell.edu> wrote:
> Daniel, I think what you really mean is that if the object is not convex
> in the area around the intersection then you're in trouble. There's no
> good solution to this problem. The hull() operation is called CONVEX hull
> for a reason. But I think this is an interesting approach, and I, at
> least, have not seen it before. (And I'm really interested in rounding.)
>
> I wrote a version that assumes you have two children at unit scale and
> uses scale() to make the joined object. That doesn't require having a
> parametrized module for each object, though it's limited in other ways.
> With BOSL2 it would be natural to combine at least the translate and rotate
> operators into a single matrix that you pass in. I also added a chamfer
> option. (Note that there's no way to avoid the code duplication because
> you can't pass children separately to a submodule.)
>
> // Invoke with 2 children that are at unit scale and create a
> // fillet joint between them, while applying specified transformations.
> //
> // r = radius of fillet (relative to scale of children)
> // T0,R0,S0 = translation, rotation and scaling for object 0
> // T1,R1,S1 = translation, rotation and scaling for object 1
> // steps = number of steps in fillet
> // chamfer = set true to get chamfer instead of rounding
>
> module fillet_join(r, T0,R0,S0, T1,R1,S1, steps=10, chamfer=false)
> {
> assert($children==2);
> da=1/steps;
> for(a=[0:da:1-da/2]){
> hull() {
> first_offset = chamfer ? r * [a,1-a]
> : r * [1-cos(90*a), 1-sin(90*a)];
> first_scale0 = [for(s=S0) first_offset[0]+s];
> first_scale1 = [for(s=S1) first_offset[1]+s];
> second_offset = chamfer ? r * [a+da, 1-a-da]
> : r * [1-cos(90*(a+da)),
> 1-sin(90*(a+da))];
> second_scale0 = [for(s=S0) second_offset[0]+s];
> second_scale1 = [for(s=S1) second_offset[1]+s];
> intersection(){
> translate(T0)rotate(R0)scale(first_scale0) children(0);
> translate(T1)rotate(R1)scale(first_scale1) children(1);
> }
> intersection(){
> translate(T0)rotate(R0)scale(second_scale0) children(0);
> translate(T1)rotate(R1)scale(second_scale1) children(1);
> }
> }
> }
> translate(T0)rotate(R0)scale(S0) children(0);
> translate(T1)rotate(R1)scale(S1) children(1);
> }
>
>
> fillet_join(3,[0,0,3], [0,90,-10], [22,22,100],
> [0,6,6], [0,20,0], [15,20,28],chamfer=false)
> {
> cylinder(d=1,center=true,$fn=64);
> cube(center=true);
> }
>
> [image: image.png]
>
>
> On Tue, Feb 14, 2023 at 10:15 AM Daniel Harvey <dwaharvey@gmail.com>
> wrote:
>
>> There's the obvious limitation that if the area of intersection has
>> native curvature then the fillet will pull away from the part (because
>> hull() { object1() } != object1() in that area). So if eg object1() had a
>> wave pattern, like some corrugated decking material... the result would not
>> be good.
>> On a case by case basis this sort of thing could probably be dealt with
>> by iterating over another parameter, and intersecting with a third
>> parametric object that creates small interpolations of the negative curve.
>> But I am not sure how this will affect the computation time (geometric
>> increase in calls to hull(), though each call on a much smaller object).
>>
>> On Tue, Feb 14, 2023 at 5:20 AM Sanjeev Prabhakar <
>> sprabhakar2006@gmail.com> wrote:
>>
>>> It looks great, although not gone in detail.
>>> Does it work for all type of solid to solid intersections?
>>>
>>> On Tue, 14 Feb, 2023, 9:58 am Daniel Harvey, <dwaharvey@gmail.com>
>>> wrote:
>>>
>>>> Hello,
>>>> It's possible that I have re-invented the wheel here, but I thought I
>>>> would share a simple solution I came up with to create fillets for the
>>>> intersection of two objects. It requires the objects to be defined with a
>>>> parametric size-offset, and it uses an iterative approach with hull() to
>>>> create a fillet. Here's an example with a cuboid (box()) embedded in a
>>>> cylinder (shaft()).
>>>>
>>>> module shaft(dd=0) {
>>>> rotate([0,0,-10]) rotate([0,90,0]) cylinder(d=22+dd, h=100, $fn=60,
>>>> center=true);
>>>> }
>>>>
>>>> module box(dd=0) {
>>>> translate([0,5,5]) cube([15+dd,18+dd,25+dd], center=true);
>>>> }
>>>>
>>>> module filletSlice(ro, ang) {
>>>> p = ro * [(1-cos(ang)), (1-sin(ang))];
>>>> intersection() {
>>>> shaft(p.x);
>>>> box(p.y);
>>>> }
>>>> }
>>>>
>>>> da = 10;
>>>> for (a=[0:da:90-da]) {
>>>> hull() {
>>>> filletSlice(2, a);
>>>> filletSlice(2, a+da);
>>>> }
>>>> }
>>>> shaft();
>>>> box();
>>>>
>>>> _______________________________________________
>>>> 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
>

DH

Daniel Harvey

Wed, Feb 15, 2023 2:31 AM

Thanks for the embellishments Adrian. It is a pity that OpenSCAD doesn't

allow you to pass one module definition as an argument to another, as

Python does - and I was grasping for. Your approach cleans that up nicely.

Given the limitations of what OpenSCAD gives you access to, this seemed to

be like the simplest and most direct way to achieve this outcome.

On Tue, Feb 14, 2023 at 3:02 PM Adrian Mariano avm4@cornell.edu wrote:

Daniel, I think what you really mean is that if the object is not convex

in the area around the intersection then you're in trouble. There's no

good solution to this problem. The hull() operation is called CONVEX hull

for a reason. But I think this is an interesting approach, and I, at

least, have not seen it before. (And I'm really interested in rounding.)

I wrote a version that assumes you have two children at unit scale and

uses scale() to make the joined object. That doesn't require having a

parametrized module for each object, though it's limited in other ways.

With BOSL2 it would be natural to combine at least the translate and rotate

operators into a single matrix that you pass in. I also added a chamfer

option. (Note that there's no way to avoid the code duplication because

you can't pass children separately to a submodule.)

// Invoke with 2 children that are at unit scale and create a

// fillet joint between them, while applying specified transformations.

//

// r = radius of fillet (relative to scale of children)

// T0,R0,S0 = translation, rotation and scaling for object 0

// T1,R1,S1 = translation, rotation and scaling for object 1

// steps = number of steps in fillet

// chamfer = set true to get chamfer instead of rounding

module fillet_join(r, T0,R0,S0, T1,R1,S1, steps=10, chamfer=false)

{

assert($children==2);

da=1/steps;

for(a=[0:da:1-da/2]){

hull() {

first_offset = chamfer ? r * [a,1-a]

: r * [1-cos(90*a), 1-sin(90*a)];

first_scale0 = [for(s=S0) first_offset[0]+s];

first_scale1 = [for(s=S1) first_offset[1]+s];

second_offset = chamfer ? r * [a+da, 1-a-da]

: r * [1-cos(90*(a+da)),

1-sin(90*(a+da))];

second_scale0 = [for(s=S0) second_offset[0]+s];

second_scale1 = [for(s=S1) second_offset[1]+s];

intersection(){

translate(T0)rotate(R0)scale(first_scale0) children(0);

translate(T1)rotate(R1)scale(first_scale1) children(1);

}

intersection(){

translate(T0)rotate(R0)scale(second_scale0) children(0);

translate(T1)rotate(R1)scale(second_scale1) children(1);

}

}

}

translate(T0)rotate(R0)scale(S0) children(0);

translate(T1)rotate(R1)scale(S1) children(1);

}

fillet_join(3,[0,0,3], [0,90,-10], [22,22,100],

[0,6,6], [0,20,0], [15,20,28],chamfer=false)

{

cylinder(d=1,center=true,$fn=64);

cube(center=true);

}

[image: image.png]

On Tue, Feb 14, 2023 at 10:15 AM Daniel Harvey dwaharvey@gmail.com

wrote:

native curvature then the fillet will pull away from the part (because

hull() { object1() } != object1() in that area). So if eg object1() had a

wave pattern, like some corrugated decking material... the result would not

be good.

On a case by case basis this sort of thing could probably be dealt with

by iterating over another parameter, and intersecting with a third

parametric object that creates small interpolations of the negative curve.

But I am not sure how this will affect the computation time (geometric

increase in calls to hull(), though each call on a much smaller object).

On Tue, Feb 14, 2023 at 5:20 AM Sanjeev Prabhakar <

sprabhakar2006@gmail.com> wrote:

Does it work for all type of solid to solid intersections?

On Tue, 14 Feb, 2023, 9:58 am Daniel Harvey, dwaharvey@gmail.com

wrote:

It's possible that I have re-invented the wheel here, but I thought I

would share a simple solution I came up with to create fillets for the

intersection of two objects. It requires the objects to be defined with a

parametric size-offset, and it uses an iterative approach with hull() to

create a fillet. Here's an example with a cuboid (box()) embedded in a

cylinder (shaft()).

rotate([0,0,-10]) rotate([0,90,0]) cylinder(d=22+dd, h=100, $fn=60,

center=true);

}

module box(dd=0) {

translate([0,5,5]) cube([15+dd,18+dd,25+dd], center=true);

}

p = ro * [(1-cos(ang)), (1-sin(ang))];

intersection() {

shaft(p.x);

box(p.y);

}

}

for (a=[0:da:90-da]) {

hull() {

filletSlice(2, a);

filletSlice(2, a+da);

}

}

shaft();

box();

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

Thanks for the embellishments Adrian. It is a pity that OpenSCAD doesn't
allow you to pass one module definition as an argument to another, as
Python does - and I was grasping for. Your approach cleans that up nicely.
Given the limitations of what OpenSCAD gives you access to, this seemed to
be like the simplest and most direct way to achieve this outcome.
On Tue, Feb 14, 2023 at 3:02 PM Adrian Mariano <avm4@cornell.edu> wrote:
> Daniel, I think what you really mean is that if the object is not convex
> in the area around the intersection then you're in trouble. There's no
> good solution to this problem. The hull() operation is called CONVEX hull
> for a reason. But I think this is an interesting approach, and I, at
> least, have not seen it before. (And I'm really interested in rounding.)
>
> I wrote a version that assumes you have two children at unit scale and
> uses scale() to make the joined object. That doesn't require having a
> parametrized module for each object, though it's limited in other ways.
> With BOSL2 it would be natural to combine at least the translate and rotate
> operators into a single matrix that you pass in. I also added a chamfer
> option. (Note that there's no way to avoid the code duplication because
> you can't pass children separately to a submodule.)
>
> // Invoke with 2 children that are at unit scale and create a
> // fillet joint between them, while applying specified transformations.
> //
> // r = radius of fillet (relative to scale of children)
> // T0,R0,S0 = translation, rotation and scaling for object 0
> // T1,R1,S1 = translation, rotation and scaling for object 1
> // steps = number of steps in fillet
> // chamfer = set true to get chamfer instead of rounding
>
> module fillet_join(r, T0,R0,S0, T1,R1,S1, steps=10, chamfer=false)
> {
> assert($children==2);
> da=1/steps;
> for(a=[0:da:1-da/2]){
> hull() {
> first_offset = chamfer ? r * [a,1-a]
> : r * [1-cos(90*a), 1-sin(90*a)];
> first_scale0 = [for(s=S0) first_offset[0]+s];
> first_scale1 = [for(s=S1) first_offset[1]+s];
> second_offset = chamfer ? r * [a+da, 1-a-da]
> : r * [1-cos(90*(a+da)),
> 1-sin(90*(a+da))];
> second_scale0 = [for(s=S0) second_offset[0]+s];
> second_scale1 = [for(s=S1) second_offset[1]+s];
> intersection(){
> translate(T0)rotate(R0)scale(first_scale0) children(0);
> translate(T1)rotate(R1)scale(first_scale1) children(1);
> }
> intersection(){
> translate(T0)rotate(R0)scale(second_scale0) children(0);
> translate(T1)rotate(R1)scale(second_scale1) children(1);
> }
> }
> }
> translate(T0)rotate(R0)scale(S0) children(0);
> translate(T1)rotate(R1)scale(S1) children(1);
> }
>
>
> fillet_join(3,[0,0,3], [0,90,-10], [22,22,100],
> [0,6,6], [0,20,0], [15,20,28],chamfer=false)
> {
> cylinder(d=1,center=true,$fn=64);
> cube(center=true);
> }
>
> [image: image.png]
>
>
> On Tue, Feb 14, 2023 at 10:15 AM Daniel Harvey <dwaharvey@gmail.com>
> wrote:
>
>> There's the obvious limitation that if the area of intersection has
>> native curvature then the fillet will pull away from the part (because
>> hull() { object1() } != object1() in that area). So if eg object1() had a
>> wave pattern, like some corrugated decking material... the result would not
>> be good.
>> On a case by case basis this sort of thing could probably be dealt with
>> by iterating over another parameter, and intersecting with a third
>> parametric object that creates small interpolations of the negative curve.
>> But I am not sure how this will affect the computation time (geometric
>> increase in calls to hull(), though each call on a much smaller object).
>>
>> On Tue, Feb 14, 2023 at 5:20 AM Sanjeev Prabhakar <
>> sprabhakar2006@gmail.com> wrote:
>>
>>> It looks great, although not gone in detail.
>>> Does it work for all type of solid to solid intersections?
>>>
>>> On Tue, 14 Feb, 2023, 9:58 am Daniel Harvey, <dwaharvey@gmail.com>
>>> wrote:
>>>
>>>> Hello,
>>>> It's possible that I have re-invented the wheel here, but I thought I
>>>> would share a simple solution I came up with to create fillets for the
>>>> intersection of two objects. It requires the objects to be defined with a
>>>> parametric size-offset, and it uses an iterative approach with hull() to
>>>> create a fillet. Here's an example with a cuboid (box()) embedded in a
>>>> cylinder (shaft()).
>>>>
>>>> module shaft(dd=0) {
>>>> rotate([0,0,-10]) rotate([0,90,0]) cylinder(d=22+dd, h=100, $fn=60,
>>>> center=true);
>>>> }
>>>>
>>>> module box(dd=0) {
>>>> translate([0,5,5]) cube([15+dd,18+dd,25+dd], center=true);
>>>> }
>>>>
>>>> module filletSlice(ro, ang) {
>>>> p = ro * [(1-cos(ang)), (1-sin(ang))];
>>>> intersection() {
>>>> shaft(p.x);
>>>> box(p.y);
>>>> }
>>>> }
>>>>
>>>> da = 10;
>>>> for (a=[0:da:90-da]) {
>>>> hull() {
>>>> filletSlice(2, a);
>>>> filletSlice(2, a+da);
>>>> }
>>>> }
>>>> shaft();
>>>> box();
>>>>
>>>> _______________________________________________
>>>> 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
>

DH

Daniel Harvey

Wed, Feb 15, 2023 2:33 AM

Sanjay, I agree with you, and getting a list of the intersection points was

what I was originally thinking about, but I'm not aware of any OpenSCAD way

to obtain that information. I imagine in a python notebook one could do it

(?), but I am doing everything in OpenSCAD directly and was looking for a

good/simple way to get this done.

On Tue, Feb 14, 2023 at 6:50 PM Sanjeev Prabhakar sprabhakar2006@gmail.com

wrote:

If the points of intersection between the 2 solids can be found then

creating fillet would be possible.

3 list of intersection points would be required

a. both the solids at their original dimensions

b.1st solid at original dimension and 2nd solid at offset = the fillet

radius (approximate)

c.1st solid at offset= the fillet radius and 2nd solid at original

dimension

with the above 3 list of points

group the points e.g. first point of each list and create a fillet arc and

so on

finally create a polyheadron with all the fillet arcs

this works in most of the cases

On Wed, 15 Feb 2023, 03:32 Adrian Mariano, avm4@cornell.edu wrote:

in the area around the intersection then you're in trouble. There's no

good solution to this problem. The hull() operation is called CONVEX hull

for a reason. But I think this is an interesting approach, and I, at

least, have not seen it before. (And I'm really interested in rounding.)

uses scale() to make the joined object. That doesn't require having a

parametrized module for each object, though it's limited in other ways.

With BOSL2 it would be natural to combine at least the translate and rotate

operators into a single matrix that you pass in. I also added a chamfer

option. (Note that there's no way to avoid the code duplication because

you can't pass children separately to a submodule.)

// fillet joint between them, while applying specified transformations.

//

// r = radius of fillet (relative to scale of children)

// T0,R0,S0 = translation, rotation and scaling for object 0

// T1,R1,S1 = translation, rotation and scaling for object 1

// steps = number of steps in fillet

// chamfer = set true to get chamfer instead of rounding

{

assert($children==2);

da=1/steps;

for(a=[0:da:1-da/2]){

hull() {

first_offset = chamfer ? r * [a,1-a]

: r * [1-cos(90*a), 1-sin(90*a)];

first_scale0 = [for(s=S0) first_offset[0]+s];

first_scale1 = [for(s=S1) first_offset[1]+s];

second_offset = chamfer ? r * [a+da, 1-a-da]

: r * [1-cos(90*(a+da)),

1-sin(90*(a+da))];

second_scale0 = [for(s=S0) second_offset[0]+s];

second_scale1 = [for(s=S1) second_offset[1]+s];

intersection(){

translate(T0)rotate(R0)scale(first_scale0) children(0);

translate(T1)rotate(R1)scale(first_scale1) children(1);

}

intersection(){

translate(T0)rotate(R0)scale(second_scale0) children(0);

translate(T1)rotate(R1)scale(second_scale1) children(1);

}

}

}

translate(T0)rotate(R0)scale(S0) children(0);

translate(T1)rotate(R1)scale(S1) children(1);

}

[0,6,6], [0,20,0], [15,20,28],chamfer=false)

{

cylinder(d=1,center=true,$fn=64);

cube(center=true);

}

[image: image.png]

On Tue, Feb 14, 2023 at 10:15 AM Daniel Harvey dwaharvey@gmail.com

wrote:

native curvature then the fillet will pull away from the part (because

hull() { object1() } != object1() in that area). So if eg object1() had a

wave pattern, like some corrugated decking material... the result would not

be good.

On a case by case basis this sort of thing could probably be dealt with

by iterating over another parameter, and intersecting with a third

parametric object that creates small interpolations of the negative curve.

But I am not sure how this will affect the computation time (geometric

increase in calls to hull(), though each call on a much smaller object).

On Tue, Feb 14, 2023 at 5:20 AM Sanjeev Prabhakar <

sprabhakar2006@gmail.com> wrote:

Does it work for all type of solid to solid intersections?

On Tue, 14 Feb, 2023, 9:58 am Daniel Harvey, dwaharvey@gmail.com

wrote:

It's possible that I have re-invented the wheel here, but I thought I

would share a simple solution I came up with to create fillets for the

intersection of two objects. It requires the objects to be defined with a

parametric size-offset, and it uses an iterative approach with hull() to

create a fillet. Here's an example with a cuboid (box()) embedded in a

cylinder (shaft()).

rotate([0,0,-10]) rotate([0,90,0]) cylinder(d=22+dd, h=100,

$fn=60, center=true);

}

module box(dd=0) {

translate([0,5,5]) cube([15+dd,18+dd,25+dd], center=true);

}

p = ro * [(1-cos(ang)), (1-sin(ang))];

intersection() {

shaft(p.x);

box(p.y);

}

}

for (a=[0:da:90-da]) {

hull() {

filletSlice(2, a);

filletSlice(2, a+da);

}

}

shaft();

box();

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

OpenSCAD mailing list

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

Sanjay, I agree with you, and getting a list of the intersection points was
what I was originally thinking about, but I'm not aware of any OpenSCAD way
to obtain that information. I imagine in a python notebook one could do it
(?), but I am doing everything in OpenSCAD directly and was looking for a
good/simple way to get this done.
On Tue, Feb 14, 2023 at 6:50 PM Sanjeev Prabhakar <sprabhakar2006@gmail.com>
wrote:
> If the points of intersection between the 2 solids can be found then
> creating fillet would be possible.
> 3 list of intersection points would be required
> a. both the solids at their original dimensions
> b.1st solid at original dimension and 2nd solid at offset = the fillet
> radius (approximate)
> c.1st solid at offset= the fillet radius and 2nd solid at original
> dimension
>
> with the above 3 list of points
> group the points e.g. first point of each list and create a fillet arc and
> so on
>
> finally create a polyheadron with all the fillet arcs
>
> this works in most of the cases
>
> On Wed, 15 Feb 2023, 03:32 Adrian Mariano, <avm4@cornell.edu> wrote:
>
>> Daniel, I think what you really mean is that if the object is not convex
>> in the area around the intersection then you're in trouble. There's no
>> good solution to this problem. The hull() operation is called CONVEX hull
>> for a reason. But I think this is an interesting approach, and I, at
>> least, have not seen it before. (And I'm really interested in rounding.)
>>
>> I wrote a version that assumes you have two children at unit scale and
>> uses scale() to make the joined object. That doesn't require having a
>> parametrized module for each object, though it's limited in other ways.
>> With BOSL2 it would be natural to combine at least the translate and rotate
>> operators into a single matrix that you pass in. I also added a chamfer
>> option. (Note that there's no way to avoid the code duplication because
>> you can't pass children separately to a submodule.)
>>
>> // Invoke with 2 children that are at unit scale and create a
>> // fillet joint between them, while applying specified transformations.
>> //
>> // r = radius of fillet (relative to scale of children)
>> // T0,R0,S0 = translation, rotation and scaling for object 0
>> // T1,R1,S1 = translation, rotation and scaling for object 1
>> // steps = number of steps in fillet
>> // chamfer = set true to get chamfer instead of rounding
>>
>> module fillet_join(r, T0,R0,S0, T1,R1,S1, steps=10, chamfer=false)
>> {
>> assert($children==2);
>> da=1/steps;
>> for(a=[0:da:1-da/2]){
>> hull() {
>> first_offset = chamfer ? r * [a,1-a]
>> : r * [1-cos(90*a), 1-sin(90*a)];
>> first_scale0 = [for(s=S0) first_offset[0]+s];
>> first_scale1 = [for(s=S1) first_offset[1]+s];
>> second_offset = chamfer ? r * [a+da, 1-a-da]
>> : r * [1-cos(90*(a+da)),
>> 1-sin(90*(a+da))];
>> second_scale0 = [for(s=S0) second_offset[0]+s];
>> second_scale1 = [for(s=S1) second_offset[1]+s];
>> intersection(){
>> translate(T0)rotate(R0)scale(first_scale0) children(0);
>> translate(T1)rotate(R1)scale(first_scale1) children(1);
>> }
>> intersection(){
>> translate(T0)rotate(R0)scale(second_scale0) children(0);
>> translate(T1)rotate(R1)scale(second_scale1) children(1);
>> }
>> }
>> }
>> translate(T0)rotate(R0)scale(S0) children(0);
>> translate(T1)rotate(R1)scale(S1) children(1);
>> }
>>
>>
>> fillet_join(3,[0,0,3], [0,90,-10], [22,22,100],
>> [0,6,6], [0,20,0], [15,20,28],chamfer=false)
>> {
>> cylinder(d=1,center=true,$fn=64);
>> cube(center=true);
>> }
>>
>> [image: image.png]
>>
>>
>> On Tue, Feb 14, 2023 at 10:15 AM Daniel Harvey <dwaharvey@gmail.com>
>> wrote:
>>
>>> There's the obvious limitation that if the area of intersection has
>>> native curvature then the fillet will pull away from the part (because
>>> hull() { object1() } != object1() in that area). So if eg object1() had a
>>> wave pattern, like some corrugated decking material... the result would not
>>> be good.
>>> On a case by case basis this sort of thing could probably be dealt with
>>> by iterating over another parameter, and intersecting with a third
>>> parametric object that creates small interpolations of the negative curve.
>>> But I am not sure how this will affect the computation time (geometric
>>> increase in calls to hull(), though each call on a much smaller object).
>>>
>>> On Tue, Feb 14, 2023 at 5:20 AM Sanjeev Prabhakar <
>>> sprabhakar2006@gmail.com> wrote:
>>>
>>>> It looks great, although not gone in detail.
>>>> Does it work for all type of solid to solid intersections?
>>>>
>>>> On Tue, 14 Feb, 2023, 9:58 am Daniel Harvey, <dwaharvey@gmail.com>
>>>> wrote:
>>>>
>>>>> Hello,
>>>>> It's possible that I have re-invented the wheel here, but I thought I
>>>>> would share a simple solution I came up with to create fillets for the
>>>>> intersection of two objects. It requires the objects to be defined with a
>>>>> parametric size-offset, and it uses an iterative approach with hull() to
>>>>> create a fillet. Here's an example with a cuboid (box()) embedded in a
>>>>> cylinder (shaft()).
>>>>>
>>>>> module shaft(dd=0) {
>>>>> rotate([0,0,-10]) rotate([0,90,0]) cylinder(d=22+dd, h=100,
>>>>> $fn=60, center=true);
>>>>> }
>>>>>
>>>>> module box(dd=0) {
>>>>> translate([0,5,5]) cube([15+dd,18+dd,25+dd], center=true);
>>>>> }
>>>>>
>>>>> module filletSlice(ro, ang) {
>>>>> p = ro * [(1-cos(ang)), (1-sin(ang))];
>>>>> intersection() {
>>>>> shaft(p.x);
>>>>> box(p.y);
>>>>> }
>>>>> }
>>>>>
>>>>> da = 10;
>>>>> for (a=[0:da:90-da]) {
>>>>> hull() {
>>>>> filletSlice(2, a);
>>>>> filletSlice(2, a+da);
>>>>> }
>>>>> }
>>>>> shaft();
>>>>> box();
>>>>>
>>>>> _______________________________________________
>>>>> 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
>>
> _______________________________________________
> OpenSCAD mailing list
> To unsubscribe send an email to discuss-leave@lists.openscad.org
>

AM

Adrian Mariano

Wed, Feb 15, 2023 2:43 AM

Daniel, it's not that you need to be able to pass modules, but at least it

would be cleaner if you could pass the children rather than just the union

of all the children to a called module. Maybe there is a way to streamline

my code a bit by applying the transformation to each object separately in a

module---I think it would only be a slight improvement. Of course, the

real ideal is to have access to the geometry data explicitly in your

modules, which is not (yet?) possible. Note that a few months ago, Sanjeev

and I had a lengthy discussion about rounding the joint between two

objects. Both Sanjeev and I wrote code to do it, but Sanjeev has moved to

doing everything in Python and using OpenSCAD just as a display engine.

Both of us assumed that the objects were available as point lists, not as

OpenSCAD geometry, so it was possible to actually compute those

intersections and make fillets work even for concave objects, though there

are some complications that can still arise when your fillet ends up

self-intersecting. To see my results take a a look at join_prism() from

the BOSL2 library:

https://github.com/revarbat/BOSL2/wiki/rounding.scad#functionmodule-join_prism

There are 55 examples to show how it works. :) But for convex objects

your approach can handle cases that my code cannot, like objects that

half-intersect each other. And it doesn't require that the objects be one

of prism, plane or sphere.

On Tue, Feb 14, 2023 at 9:34 PM Daniel Harvey dwaharvey@gmail.com wrote:

Sanjay, I agree with you, and getting a list of the intersection points

was what I was originally thinking about, but I'm not aware of any OpenSCAD

way to obtain that information. I imagine in a python notebook one could do

it (?), but I am doing everything in OpenSCAD directly and was looking for

a good/simple way to get this done.

On Tue, Feb 14, 2023 at 6:50 PM Sanjeev Prabhakar <

sprabhakar2006@gmail.com> wrote:

If the points of intersection between the 2 solids can be found then

creating fillet would be possible.

3 list of intersection points would be required

a. both the solids at their original dimensions

b.1st solid at original dimension and 2nd solid at offset = the fillet

radius (approximate)

c.1st solid at offset= the fillet radius and 2nd solid at original

dimension

with the above 3 list of points

group the points e.g. first point of each list and create a fillet arc

and so on

finally create a polyheadron with all the fillet arcs

this works in most of the cases

On Wed, 15 Feb 2023, 03:32 Adrian Mariano, avm4@cornell.edu wrote:

in the area around the intersection then you're in trouble. There's no

good solution to this problem. The hull() operation is called CONVEX hull

for a reason. But I think this is an interesting approach, and I, at

least, have not seen it before. (And I'm really interested in rounding.)

uses scale() to make the joined object. That doesn't require having a

parametrized module for each object, though it's limited in other ways.

With BOSL2 it would be natural to combine at least the translate and rotate

operators into a single matrix that you pass in. I also added a chamfer

option. (Note that there's no way to avoid the code duplication because

you can't pass children separately to a submodule.)

// fillet joint between them, while applying specified transformations.

//

// r = radius of fillet (relative to scale of children)

// T0,R0,S0 = translation, rotation and scaling for object 0

// T1,R1,S1 = translation, rotation and scaling for object 1

// steps = number of steps in fillet

// chamfer = set true to get chamfer instead of rounding

{

assert($children==2);

da=1/steps;

for(a=[0:da:1-da/2]){

hull() {

first_offset = chamfer ? r * [a,1-a]

: r * [1-cos(90*a), 1-sin(90*a)];

first_scale0 = [for(s=S0) first_offset[0]+s];

first_scale1 = [for(s=S1) first_offset[1]+s];

second_offset = chamfer ? r * [a+da, 1-a-da]

: r * [1-cos(90*(a+da)),

1-sin(90*(a+da))];

second_scale0 = [for(s=S0) second_offset[0]+s];

second_scale1 = [for(s=S1) second_offset[1]+s];

intersection(){

translate(T0)rotate(R0)scale(first_scale0) children(0);

translate(T1)rotate(R1)scale(first_scale1) children(1);

}

intersection(){

translate(T0)rotate(R0)scale(second_scale0) children(0);

translate(T1)rotate(R1)scale(second_scale1) children(1);

}

}

}

translate(T0)rotate(R0)scale(S0) children(0);

translate(T1)rotate(R1)scale(S1) children(1);

}

[0,6,6], [0,20,0], [15,20,28],chamfer=false)

{

cylinder(d=1,center=true,$fn=64);

cube(center=true);

}

[image: image.png]

On Tue, Feb 14, 2023 at 10:15 AM Daniel Harvey dwaharvey@gmail.com

wrote:

native curvature then the fillet will pull away from the part (because

hull() { object1() } != object1() in that area). So if eg object1() had a

wave pattern, like some corrugated decking material... the result would not

be good.

On a case by case basis this sort of thing could probably be dealt with

by iterating over another parameter, and intersecting with a third

parametric object that creates small interpolations of the negative curve.

But I am not sure how this will affect the computation time (geometric

increase in calls to hull(), though each call on a much smaller object).

On Tue, Feb 14, 2023 at 5:20 AM Sanjeev Prabhakar <

sprabhakar2006@gmail.com> wrote:

Does it work for all type of solid to solid intersections?

On Tue, 14 Feb, 2023, 9:58 am Daniel Harvey, dwaharvey@gmail.com

wrote:

It's possible that I have re-invented the wheel here, but I thought I

would share a simple solution I came up with to create fillets for the

intersection of two objects. It requires the objects to be defined with a

parametric size-offset, and it uses an iterative approach with hull() to

create a fillet. Here's an example with a cuboid (box()) embedded in a

cylinder (shaft()).

rotate([0,0,-10]) rotate([0,90,0]) cylinder(d=22+dd, h=100,

$fn=60, center=true);

}

module box(dd=0) {

translate([0,5,5]) cube([15+dd,18+dd,25+dd], center=true);

}

p = ro * [(1-cos(ang)), (1-sin(ang))];

intersection() {

shaft(p.x);

box(p.y);

}

}

for (a=[0:da:90-da]) {

hull() {

filletSlice(2, a);

filletSlice(2, a+da);

}

}

shaft();

box();

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

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

Daniel, it's not that you need to be able to pass modules, but at least it
would be cleaner if you could pass the children rather than just the union
of all the children to a called module. Maybe there is a way to streamline
my code a bit by applying the transformation to each object separately in a
module---I think it would only be a slight improvement. Of course, the
real ideal is to have access to the geometry data explicitly in your
modules, which is not (yet?) possible. Note that a few months ago, Sanjeev
and I had a lengthy discussion about rounding the joint between two
objects. Both Sanjeev and I wrote code to do it, but Sanjeev has moved to
doing everything in Python and using OpenSCAD just as a display engine.
Both of us assumed that the objects were available as point lists, not as
OpenSCAD geometry, so it was possible to actually compute those
intersections and make fillets work even for concave objects, though there
are some complications that can still arise when your fillet ends up
self-intersecting. To see my results take a a look at join_prism() from
the BOSL2 library:
https://github.com/revarbat/BOSL2/wiki/rounding.scad#functionmodule-join_prism
There are 55 examples to show how it works. :) But for convex objects
your approach can handle cases that my code cannot, like objects that
half-intersect each other. And it doesn't require that the objects be one
of prism, plane or sphere.
On Tue, Feb 14, 2023 at 9:34 PM Daniel Harvey <dwaharvey@gmail.com> wrote:
> Sanjay, I agree with you, and getting a list of the intersection points
> was what I was originally thinking about, but I'm not aware of any OpenSCAD
> way to obtain that information. I imagine in a python notebook one could do
> it (?), but I am doing everything in OpenSCAD directly and was looking for
> a good/simple way to get this done.
>
> On Tue, Feb 14, 2023 at 6:50 PM Sanjeev Prabhakar <
> sprabhakar2006@gmail.com> wrote:
>
>> If the points of intersection between the 2 solids can be found then
>> creating fillet would be possible.
>> 3 list of intersection points would be required
>> a. both the solids at their original dimensions
>> b.1st solid at original dimension and 2nd solid at offset = the fillet
>> radius (approximate)
>> c.1st solid at offset= the fillet radius and 2nd solid at original
>> dimension
>>
>> with the above 3 list of points
>> group the points e.g. first point of each list and create a fillet arc
>> and so on
>>
>> finally create a polyheadron with all the fillet arcs
>>
>> this works in most of the cases
>>
>> On Wed, 15 Feb 2023, 03:32 Adrian Mariano, <avm4@cornell.edu> wrote:
>>
>>> Daniel, I think what you really mean is that if the object is not convex
>>> in the area around the intersection then you're in trouble. There's no
>>> good solution to this problem. The hull() operation is called CONVEX hull
>>> for a reason. But I think this is an interesting approach, and I, at
>>> least, have not seen it before. (And I'm really interested in rounding.)
>>>
>>> I wrote a version that assumes you have two children at unit scale and
>>> uses scale() to make the joined object. That doesn't require having a
>>> parametrized module for each object, though it's limited in other ways.
>>> With BOSL2 it would be natural to combine at least the translate and rotate
>>> operators into a single matrix that you pass in. I also added a chamfer
>>> option. (Note that there's no way to avoid the code duplication because
>>> you can't pass children separately to a submodule.)
>>>
>>> // Invoke with 2 children that are at unit scale and create a
>>> // fillet joint between them, while applying specified transformations.
>>> //
>>> // r = radius of fillet (relative to scale of children)
>>> // T0,R0,S0 = translation, rotation and scaling for object 0
>>> // T1,R1,S1 = translation, rotation and scaling for object 1
>>> // steps = number of steps in fillet
>>> // chamfer = set true to get chamfer instead of rounding
>>>
>>> module fillet_join(r, T0,R0,S0, T1,R1,S1, steps=10, chamfer=false)
>>> {
>>> assert($children==2);
>>> da=1/steps;
>>> for(a=[0:da:1-da/2]){
>>> hull() {
>>> first_offset = chamfer ? r * [a,1-a]
>>> : r * [1-cos(90*a), 1-sin(90*a)];
>>> first_scale0 = [for(s=S0) first_offset[0]+s];
>>> first_scale1 = [for(s=S1) first_offset[1]+s];
>>> second_offset = chamfer ? r * [a+da, 1-a-da]
>>> : r * [1-cos(90*(a+da)),
>>> 1-sin(90*(a+da))];
>>> second_scale0 = [for(s=S0) second_offset[0]+s];
>>> second_scale1 = [for(s=S1) second_offset[1]+s];
>>> intersection(){
>>> translate(T0)rotate(R0)scale(first_scale0) children(0);
>>> translate(T1)rotate(R1)scale(first_scale1) children(1);
>>> }
>>> intersection(){
>>> translate(T0)rotate(R0)scale(second_scale0) children(0);
>>> translate(T1)rotate(R1)scale(second_scale1) children(1);
>>> }
>>> }
>>> }
>>> translate(T0)rotate(R0)scale(S0) children(0);
>>> translate(T1)rotate(R1)scale(S1) children(1);
>>> }
>>>
>>>
>>> fillet_join(3,[0,0,3], [0,90,-10], [22,22,100],
>>> [0,6,6], [0,20,0], [15,20,28],chamfer=false)
>>> {
>>> cylinder(d=1,center=true,$fn=64);
>>> cube(center=true);
>>> }
>>>
>>> [image: image.png]
>>>
>>>
>>> On Tue, Feb 14, 2023 at 10:15 AM Daniel Harvey <dwaharvey@gmail.com>
>>> wrote:
>>>
>>>> There's the obvious limitation that if the area of intersection has
>>>> native curvature then the fillet will pull away from the part (because
>>>> hull() { object1() } != object1() in that area). So if eg object1() had a
>>>> wave pattern, like some corrugated decking material... the result would not
>>>> be good.
>>>> On a case by case basis this sort of thing could probably be dealt with
>>>> by iterating over another parameter, and intersecting with a third
>>>> parametric object that creates small interpolations of the negative curve.
>>>> But I am not sure how this will affect the computation time (geometric
>>>> increase in calls to hull(), though each call on a much smaller object).
>>>>
>>>> On Tue, Feb 14, 2023 at 5:20 AM Sanjeev Prabhakar <
>>>> sprabhakar2006@gmail.com> wrote:
>>>>
>>>>> It looks great, although not gone in detail.
>>>>> Does it work for all type of solid to solid intersections?
>>>>>
>>>>> On Tue, 14 Feb, 2023, 9:58 am Daniel Harvey, <dwaharvey@gmail.com>
>>>>> wrote:
>>>>>
>>>>>> Hello,
>>>>>> It's possible that I have re-invented the wheel here, but I thought I
>>>>>> would share a simple solution I came up with to create fillets for the
>>>>>> intersection of two objects. It requires the objects to be defined with a
>>>>>> parametric size-offset, and it uses an iterative approach with hull() to
>>>>>> create a fillet. Here's an example with a cuboid (box()) embedded in a
>>>>>> cylinder (shaft()).
>>>>>>
>>>>>> module shaft(dd=0) {
>>>>>> rotate([0,0,-10]) rotate([0,90,0]) cylinder(d=22+dd, h=100,
>>>>>> $fn=60, center=true);
>>>>>> }
>>>>>>
>>>>>> module box(dd=0) {
>>>>>> translate([0,5,5]) cube([15+dd,18+dd,25+dd], center=true);
>>>>>> }
>>>>>>
>>>>>> module filletSlice(ro, ang) {
>>>>>> p = ro * [(1-cos(ang)), (1-sin(ang))];
>>>>>> intersection() {
>>>>>> shaft(p.x);
>>>>>> box(p.y);
>>>>>> }
>>>>>> }
>>>>>>
>>>>>> da = 10;
>>>>>> for (a=[0:da:90-da]) {
>>>>>> hull() {
>>>>>> filletSlice(2, a);
>>>>>> filletSlice(2, a+da);
>>>>>> }
>>>>>> }
>>>>>> shaft();
>>>>>> box();
>>>>>>
>>>>>> _______________________________________________
>>>>>> 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
>>>
>> _______________________________________________
>> 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
>

SP

Sanjeev Prabhakar

Wed, Feb 15, 2023 3:38 AM

It is possible to get intersection points if you create objects (or solid)

with defined points list rather than openscad primitives like cylinders and

cubes.

It is slightly complicated to work that way initially but soon it becomes

natural.

For intersection you need simply a method to calculate intersection point

between a plane (maybe an enclosed section lying in a plane) and a line in

3d space. This is possible in openscad.

I shifted to python as it is a little simpler to do geometric calculations,

but I think everything can be done in openscad as well.

On Wed, 15 Feb, 2023, 8:04 am Daniel Harvey, dwaharvey@gmail.com wrote:

Sanjay, I agree with you, and getting a list of the intersection points

was what I was originally thinking about, but I'm not aware of any OpenSCAD

way to obtain that information. I imagine in a python notebook one could do

it (?), but I am doing everything in OpenSCAD directly and was looking for

a good/simple way to get this done.

On Tue, Feb 14, 2023 at 6:50 PM Sanjeev Prabhakar <

sprabhakar2006@gmail.com> wrote:

creating fillet would be possible.

3 list of intersection points would be required

a. both the solids at their original dimensions

b.1st solid at original dimension and 2nd solid at offset = the fillet

radius (approximate)

c.1st solid at offset= the fillet radius and 2nd solid at original

dimension

group the points e.g. first point of each list and create a fillet arc

and so on

finally create a polyheadron with all the fillet arcs

this works in most of the cases

On Wed, 15 Feb 2023, 03:32 Adrian Mariano, avm4@cornell.edu wrote:

in the area around the intersection then you're in trouble. There's no

good solution to this problem. The hull() operation is called CONVEX hull

for a reason. But I think this is an interesting approach, and I, at

least, have not seen it before. (And I'm really interested in rounding.)

uses scale() to make the joined object. That doesn't require having a

parametrized module for each object, though it's limited in other ways.

With BOSL2 it would be natural to combine at least the translate and rotate

operators into a single matrix that you pass in. I also added a chamfer

option. (Note that there's no way to avoid the code duplication because

you can't pass children separately to a submodule.)

// fillet joint between them, while applying specified transformations.

//

// r = radius of fillet (relative to scale of children)

// T0,R0,S0 = translation, rotation and scaling for object 0

// T1,R1,S1 = translation, rotation and scaling for object 1

// steps = number of steps in fillet

// chamfer = set true to get chamfer instead of rounding

{

assert($children==2);

da=1/steps;

for(a=[0:da:1-da/2]){

hull() {

first_offset = chamfer ? r * [a,1-a]

: r * [1-cos(90*a), 1-sin(90*a)];

first_scale0 = [for(s=S0) first_offset[0]+s];

first_scale1 = [for(s=S1) first_offset[1]+s];

second_offset = chamfer ? r * [a+da, 1-a-da]

: r * [1-cos(90*(a+da)),

1-sin(90*(a+da))];

second_scale0 = [for(s=S0) second_offset[0]+s];

second_scale1 = [for(s=S1) second_offset[1]+s];

intersection(){

translate(T0)rotate(R0)scale(first_scale0) children(0);

translate(T1)rotate(R1)scale(first_scale1) children(1);

}

intersection(){

translate(T0)rotate(R0)scale(second_scale0) children(0);

translate(T1)rotate(R1)scale(second_scale1) children(1);

}

}

}

translate(T0)rotate(R0)scale(S0) children(0);

translate(T1)rotate(R1)scale(S1) children(1);

}

[0,6,6], [0,20,0], [15,20,28],chamfer=false)

{

cylinder(d=1,center=true,$fn=64);

cube(center=true);

}

[image: image.png]

On Tue, Feb 14, 2023 at 10:15 AM Daniel Harvey dwaharvey@gmail.com

wrote:

native curvature then the fillet will pull away from the part (because

hull() { object1() } != object1() in that area). So if eg object1() had a

wave pattern, like some corrugated decking material... the result would not

be good.

On a case by case basis this sort of thing could probably be dealt with

by iterating over another parameter, and intersecting with a third

parametric object that creates small interpolations of the negative curve.

But I am not sure how this will affect the computation time (geometric

increase in calls to hull(), though each call on a much smaller object).

On Tue, Feb 14, 2023 at 5:20 AM Sanjeev Prabhakar <

sprabhakar2006@gmail.com> wrote:

Does it work for all type of solid to solid intersections?

On Tue, 14 Feb, 2023, 9:58 am Daniel Harvey, dwaharvey@gmail.com

wrote:

It's possible that I have re-invented the wheel here, but I thought I

would share a simple solution I came up with to create fillets for the

intersection of two objects. It requires the objects to be defined with a

parametric size-offset, and it uses an iterative approach with hull() to

create a fillet. Here's an example with a cuboid (box()) embedded in a

cylinder (shaft()).

rotate([0,0,-10]) rotate([0,90,0]) cylinder(d=22+dd, h=100,

$fn=60, center=true);

}

module box(dd=0) {

translate([0,5,5]) cube([15+dd,18+dd,25+dd], center=true);

}

p = ro * [(1-cos(ang)), (1-sin(ang))];

intersection() {

shaft(p.x);

box(p.y);

}

}

for (a=[0:da:90-da]) {

hull() {

filletSlice(2, a);

filletSlice(2, a+da);

}

}

shaft();

box();

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

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

It is possible to get intersection points if you create objects (or solid)
with defined points list rather than openscad primitives like cylinders and
cubes.
It is slightly complicated to work that way initially but soon it becomes
natural.
For intersection you need simply a method to calculate intersection point
between a plane (maybe an enclosed section lying in a plane) and a line in
3d space. This is possible in openscad.
I shifted to python as it is a little simpler to do geometric calculations,
but I think everything can be done in openscad as well.
On Wed, 15 Feb, 2023, 8:04 am Daniel Harvey, <dwaharvey@gmail.com> wrote:
> Sanjay, I agree with you, and getting a list of the intersection points
> was what I was originally thinking about, but I'm not aware of any OpenSCAD
> way to obtain that information. I imagine in a python notebook one could do
> it (?), but I am doing everything in OpenSCAD directly and was looking for
> a good/simple way to get this done.
>
> On Tue, Feb 14, 2023 at 6:50 PM Sanjeev Prabhakar <
> sprabhakar2006@gmail.com> wrote:
>
>> If the points of intersection between the 2 solids can be found then
>> creating fillet would be possible.
>> 3 list of intersection points would be required
>> a. both the solids at their original dimensions
>> b.1st solid at original dimension and 2nd solid at offset = the fillet
>> radius (approximate)
>> c.1st solid at offset= the fillet radius and 2nd solid at original
>> dimension
>>
>> with the above 3 list of points
>> group the points e.g. first point of each list and create a fillet arc
>> and so on
>>
>> finally create a polyheadron with all the fillet arcs
>>
>> this works in most of the cases
>>
>> On Wed, 15 Feb 2023, 03:32 Adrian Mariano, <avm4@cornell.edu> wrote:
>>
>>> Daniel, I think what you really mean is that if the object is not convex
>>> in the area around the intersection then you're in trouble. There's no
>>> good solution to this problem. The hull() operation is called CONVEX hull
>>> for a reason. But I think this is an interesting approach, and I, at
>>> least, have not seen it before. (And I'm really interested in rounding.)
>>>
>>> I wrote a version that assumes you have two children at unit scale and
>>> uses scale() to make the joined object. That doesn't require having a
>>> parametrized module for each object, though it's limited in other ways.
>>> With BOSL2 it would be natural to combine at least the translate and rotate
>>> operators into a single matrix that you pass in. I also added a chamfer
>>> option. (Note that there's no way to avoid the code duplication because
>>> you can't pass children separately to a submodule.)
>>>
>>> // Invoke with 2 children that are at unit scale and create a
>>> // fillet joint between them, while applying specified transformations.
>>> //
>>> // r = radius of fillet (relative to scale of children)
>>> // T0,R0,S0 = translation, rotation and scaling for object 0
>>> // T1,R1,S1 = translation, rotation and scaling for object 1
>>> // steps = number of steps in fillet
>>> // chamfer = set true to get chamfer instead of rounding
>>>
>>> module fillet_join(r, T0,R0,S0, T1,R1,S1, steps=10, chamfer=false)
>>> {
>>> assert($children==2);
>>> da=1/steps;
>>> for(a=[0:da:1-da/2]){
>>> hull() {
>>> first_offset = chamfer ? r * [a,1-a]
>>> : r * [1-cos(90*a), 1-sin(90*a)];
>>> first_scale0 = [for(s=S0) first_offset[0]+s];
>>> first_scale1 = [for(s=S1) first_offset[1]+s];
>>> second_offset = chamfer ? r * [a+da, 1-a-da]
>>> : r * [1-cos(90*(a+da)),
>>> 1-sin(90*(a+da))];
>>> second_scale0 = [for(s=S0) second_offset[0]+s];
>>> second_scale1 = [for(s=S1) second_offset[1]+s];
>>> intersection(){
>>> translate(T0)rotate(R0)scale(first_scale0) children(0);
>>> translate(T1)rotate(R1)scale(first_scale1) children(1);
>>> }
>>> intersection(){
>>> translate(T0)rotate(R0)scale(second_scale0) children(0);
>>> translate(T1)rotate(R1)scale(second_scale1) children(1);
>>> }
>>> }
>>> }
>>> translate(T0)rotate(R0)scale(S0) children(0);
>>> translate(T1)rotate(R1)scale(S1) children(1);
>>> }
>>>
>>>
>>> fillet_join(3,[0,0,3], [0,90,-10], [22,22,100],
>>> [0,6,6], [0,20,0], [15,20,28],chamfer=false)
>>> {
>>> cylinder(d=1,center=true,$fn=64);
>>> cube(center=true);
>>> }
>>>
>>> [image: image.png]
>>>
>>>
>>> On Tue, Feb 14, 2023 at 10:15 AM Daniel Harvey <dwaharvey@gmail.com>
>>> wrote:
>>>
>>>> There's the obvious limitation that if the area of intersection has
>>>> native curvature then the fillet will pull away from the part (because
>>>> hull() { object1() } != object1() in that area). So if eg object1() had a
>>>> wave pattern, like some corrugated decking material... the result would not
>>>> be good.
>>>> On a case by case basis this sort of thing could probably be dealt with
>>>> by iterating over another parameter, and intersecting with a third
>>>> parametric object that creates small interpolations of the negative curve.
>>>> But I am not sure how this will affect the computation time (geometric
>>>> increase in calls to hull(), though each call on a much smaller object).
>>>>
>>>> On Tue, Feb 14, 2023 at 5:20 AM Sanjeev Prabhakar <
>>>> sprabhakar2006@gmail.com> wrote:
>>>>
>>>>> It looks great, although not gone in detail.
>>>>> Does it work for all type of solid to solid intersections?
>>>>>
>>>>> On Tue, 14 Feb, 2023, 9:58 am Daniel Harvey, <dwaharvey@gmail.com>
>>>>> wrote:
>>>>>
>>>>>> Hello,
>>>>>> It's possible that I have re-invented the wheel here, but I thought I
>>>>>> would share a simple solution I came up with to create fillets for the
>>>>>> intersection of two objects. It requires the objects to be defined with a
>>>>>> parametric size-offset, and it uses an iterative approach with hull() to
>>>>>> create a fillet. Here's an example with a cuboid (box()) embedded in a
>>>>>> cylinder (shaft()).
>>>>>>
>>>>>> module shaft(dd=0) {
>>>>>> rotate([0,0,-10]) rotate([0,90,0]) cylinder(d=22+dd, h=100,
>>>>>> $fn=60, center=true);
>>>>>> }
>>>>>>
>>>>>> module box(dd=0) {
>>>>>> translate([0,5,5]) cube([15+dd,18+dd,25+dd], center=true);
>>>>>> }
>>>>>>
>>>>>> module filletSlice(ro, ang) {
>>>>>> p = ro * [(1-cos(ang)), (1-sin(ang))];
>>>>>> intersection() {
>>>>>> shaft(p.x);
>>>>>> box(p.y);
>>>>>> }
>>>>>> }
>>>>>>
>>>>>> da = 10;
>>>>>> for (a=[0:da:90-da]) {
>>>>>> hull() {
>>>>>> filletSlice(2, a);
>>>>>> filletSlice(2, a+da);
>>>>>> }
>>>>>> }
>>>>>> shaft();
>>>>>> box();
>>>>>>
>>>>>> _______________________________________________
>>>>>> 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
>>>
>> _______________________________________________
>> 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
>

JB

Jordan Brown

Wed, Feb 15, 2023 8:19 AM

On 2/14/2023 6:31 PM, Daniel Harvey wrote:

It is a pity that OpenSCAD doesn't allow you to pass one module

definition as an argument to another, as Python does - and I was

grasping for.

Excuse me for a moment while I get pedantic. People often get confused

about what "module" means, and especially with the upcoming work in

PR#4478 https://github.com/openscad/openscad/pull/4478 it's important

to keep the concepts straight.

Modules are executable subprograms. They might happen to always produce

the same output, but they may not. "cube" is a module - sometimes it

produces 1x1x1 cubes, sometimes 10x10x10, and sometimes 9x4x1.

Geometric objects (still looking for a good phrase there) are the
*results* of executing modules. Once you have executed cube(1), the

result is a 1x1 cube (in the current coordinate system) and nothing will

ever change that.

By way of analogy, consider this function:

```
function five() = 5;
```

This function will always return the number 5, but it is not the number

5 - it is an executable subprogram that happens to always yield the same

result.

Today's OpenSCAD does have one form for passing something in this area -

the "child" mechanism:

```
rotate(45) cube(10);
```

That looks like it's passing a geometric object to rotate, but really

it's not - it's passing something that's more like a parameter-less

module. This is most easily seen with modules that invoke their

children more than once:

```
module dup(dx) {
children();
translate([dx,0,0]) children();
}
```

If you invoke this with a simple child, it could be working on geometric

objects:

```
dup(5) cube(2);
```

does the obvious thing.

But what do these do?

```
dup(5) echo("hello");
dup(5) cube(rands(1,3,1)[0]);
```

The "passing a geometric object" model would say that the first would

echo "hello", while the second would generate a random-sized cube, and

then duplicate it... but that's not what happens. Instead, each

invocation of "children()" causes the children to be evaluated, so what

you get are two echos of "hello" and two independently random cubes.

The same is true if you set $ variables in the parent module; the child

can receive them and take action based on them.

The children may not be evaluated at all...

```
module maybe(bool) {
if (bool) children();
}
maybe(false) echo("you never see this");
```

4478 includes several mechanisms offering more features for both kinds

of constructs, and it becomes even more important to keep them straight.

4478 lets you use geometric objects as data values:

```
c = {{ cube(rands(1,3,1)[0]); }} // Maybe not final syntax.
```

and then because it's just a data value, you can put it in an array,

pass it as a parameter, return it from a function, and so on.

You can later add it to the model:

```
c;
```

Note that that geometric value gets evaluated *once*, so "c" represents

some one random-sized cube. No matter how many times you add it to the

model, it's always the same size. (In the current coordinate system, of

course.)

4478 also lets you use modules as data values (as you can with functions

today):

```
m = module () { cube(rands(1,3,1)[0]); };
```

Again, this "module reference" is a data value. You can put it in an

array, pass it as a parameter, et cetera. At some later point you can

invoke it and add the resulting geometry to the model:

```
m();
```

But it's a module. Until you invoke it, it isn't geometry. *Each* time

you invoke it, it gets evaluated and produces whatever geometry it

produces. Here, each time you invoke it you get a random-sized cube,

and two invocations will yield different results.

I hope that makes the distinction a little clearer, and makes it clear

why I want people to understand the distinction.

On 2/14/2023 6:31 PM, Daniel Harvey wrote:
> It is a pity that OpenSCAD doesn't allow you to pass one module
> definition as an argument to another, as Python does - and I was
> grasping for.
Excuse me for a moment while I get pedantic. People often get confused
about what "module" means, and especially with the upcoming work in
PR#4478 <https://github.com/openscad/openscad/pull/4478> it's important
to keep the concepts straight.
Modules are executable subprograms. They might happen to always produce
the same output, but they may not. "cube" is a module - sometimes it
produces 1x1x1 cubes, sometimes 10x10x10, and sometimes 9x4x1.
Geometric objects (still looking for a good phrase there) are the
*results* of executing modules. Once you have executed cube(1), the
result is a 1x1 cube (in the current coordinate system) and nothing will
ever change that.
By way of analogy, consider this function:
function five() = 5;
This function will always return the number 5, but it is not the number
5 - it is an executable subprogram that happens to always yield the same
result.
------------------------------------------------------------------------
Today's OpenSCAD does have one form for passing something in this area -
the "child" mechanism:
rotate(45) cube(10);
That looks like it's passing a geometric object to rotate, but really
it's not - it's passing something that's more like a parameter-less
module. This is most easily seen with modules that invoke their
children more than once:
module dup(dx) {
children();
translate([dx,0,0]) children();
}
If you invoke this with a simple child, it could be working on geometric
objects:
dup(5) cube(2);
does the obvious thing.
But what do these do?
dup(5) echo("hello");
dup(5) cube(rands(1,3,1)[0]);
The "passing a geometric object" model would say that the first would
echo "hello", while the second would generate a random-sized cube, and
then duplicate it... but that's not what happens. Instead, each
invocation of "children()" causes the children to be evaluated, so what
you get are two echos of "hello" and two independently random cubes.
The same is true if you set $ variables in the parent module; the child
can receive them and take action based on them.
The children may not be evaluated at all...
module maybe(bool) {
if (bool) children();
}
maybe(false) echo("you never see this");
------------------------------------------------------------------------
4478 includes several mechanisms offering more features for both kinds
of constructs, and it becomes even more important to keep them straight.
4478 lets you use geometric objects as data values:
c = {{ cube(rands(1,3,1)[0]); }} // Maybe not final syntax.
and then because it's just a data value, you can put it in an array,
pass it as a parameter, return it from a function, and so on.
You can later add it to the model:
c;
Note that that geometric value gets evaluated *once*, so "c" represents
some one random-sized cube. No matter how many times you add it to the
model, it's always the same size. (In the current coordinate system, of
course.)
4478 also lets you use modules as data values (as you can with functions
today):
m = module () { cube(rands(1,3,1)[0]); };
Again, this "module reference" is a data value. You can put it in an
array, pass it as a parameter, et cetera. At some later point you can
invoke it and add the resulting geometry to the model:
m();
But it's a module. Until you invoke it, it isn't geometry. *Each* time
you invoke it, it gets evaluated and produces whatever geometry it
produces. Here, each time you invoke it you get a random-sized cube,
and two invocations will yield different results.
I hope that makes the distinction a little clearer, and makes it clear
why I want people to understand the distinction.

Replying to:

Empathy v1.0
2023 ©Harmonylists.com