discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

Convexity & difference()

AM
Adrian Mariano
Thu, Jan 25, 2024 4:50 AM

You might find it instructive to take a look at the code for BOSL2, which
may give you some insight into how you might write more sophisticated code.

It's possible to implement total_animation_steps_up_to and
total_animation_steps without recursion at all:

total_animation_steps = animation_durations *
[for(i=[0:len(animation_durations)-1]) 1];

function total_animation_steps_up_to(partnum) =
partnum==1 ? 0
: [for(i=[0:1:partnum-2]) animation_durations[i]] *
[for(i=[0:1:partnum-2]) 1];

But get_part_number needs recursion. Using 1 based indexing in a 0 based
language is a questionable complication.  Why not start with part 0?

On Wed, Jan 24, 2024 at 11:35 PM neri-engineering via Discuss <
discuss@lists.openscad.org> wrote:

Well that certainly makes things easier, thanks.  This syntax is
reminiscent of TinyScheme, which I used inside of GIMP image tool.

Sent with Proton Mail https://proton.me/ secure email.

On Wednesday, January 24th, 2024 at 10:04 PM, Father Horton via Discuss <
discuss@lists.openscad.org> wrote:

Also note that you can have multiple assignments in a let statement. Just
separate them with commas. I assume they evaluate left-to-right, though I
don't think I've ever put that to the test.

On Wed, Jan 24, 2024 at 9:50 PM Father Horton fatherhorton@gmail.com
wrote:

Actually you can declare local variables. It's just not obvious how.

From the manual:

function get_square_triangle_perimeter(p1, p2) =  let (hypotenuse = sqrt(p1p1+p2p2))    p1 + p2 + hypotenuse;

On Wed, Jan 24, 2024 at 9:47 PM neri-engineering via Discuss <
discuss@lists.openscad.org> wrote:

It's because in functions you can't declare local variables. So many
times you end up writing helper functions which take the semi-compiled form
of equations/data. This is one of the reasons why recursive functions in
OpenSCAD are difficult to write. It certainly takes some getting used to.
That's why I call it "sorcery". It's good mental gymnastics to keep you
sharp, to prevent the ole Alzheimer's from setting in. We keep our bodies
sharp by working out and we keep our minds sharp by writing recursive
functions in OpenSCAD. Some examples I can give you which demonstrate my
point. With a standard iterative process we would accomplish the following
with simpler code.

// There are 21 steps currently.
animation_durations=[1, // # 1 slipper_back_plate()
1, // # 2 slipper_bearing()
2, // # 3 top_shaft()
1, // # 4 slipper_back_plate_pin()
2, // # 5 spur_gear() & left_slipper_pad()
1, // # 6 right_slipper_pad()
1, // # 7 slipper_front_plate()
1, // # 8 slipper_spring()
3, // # 9 slipper_nut()
1, // #10 slipper_to_drive_gear_spacer()
1, // #11 drive_gear()
1, // #12 top_shaft_left_spacer() &
// left_top_shaft_bearing()
1, // #13 top_shaft_right_spacer() &
// right_top_shaft_bearing()
2, // #14 top_shaft_end_screw()
2]; // # ending()

// Returns a 1-based part number. Does not start from zero. Identifies
the
// part being "introduced" in its introductory animation.
function get_part_number(tick,index)=
(tick<0)?index:
(get_part_number(tick-animation_durations[index],
index+1));

function total_animation_steps(index,step_count)=
(index>=len(animation_durations))?
step_count:
total_animation_steps(index+1,
step_count+animation_durations[index]);

// Parameter 'partnum' is one-based. Returns the number of animation
steps
// that have preceded the beginning of part intro animation for
specified part.
function total_animation_steps_up_to(partnum,index,step_count)=
(index>=(partnum-1))?
step_count:
total_animation_steps_up_to(partnum,index+1,
step_count+animation_durations[index]);

// The input parameter is 1-based and represents the part #.
function part_animation_steps(partnum)=
animation_durations[partnum-1];

// Value 't' is a value in [0,1), it increases linearly with time to
span the
// entirety of animation.
t=0.34; // For example, we're a bit more than 1/3 of the way through the
anim.

// Parameter 'i' is the animation ticker, zero-based.
i=floor(t*total_animation_steps(0,0)); // Start from 0.
p=get_part_number(i,0);

// Parameter 'w' is like 't', meaning it is in the range 0 <= w < 1, but
it
// is specific to the part intro animation. The part intro animation
begins
// at w=0 and is already over at w=1.
pre_w=(t*total_animation_steps(0,0)
-total_animation_steps_up_to(p,0,0))/part_animation_steps(p);

// First it will print out a one-based index describing the part we're
on.
echo(p);

// Next it will print out which fraction of this part's scene we've done.
echo(pre_w);

Sent with Proton Mail https://proton.me/ secure email.

On Wednesday, January 24th, 2024 at 7:21 PM, Adrian Mariano via Discuss <
discuss@lists.openscad.org> wrote:

I don't understand why it's any trickier to assemble the order of points
with recursive programming. In either case, if you have a growing list (the
result) you compute new values and add them to the end of the list.
Normally I write a recursive function something like

function func(result,info) =
done ? result
: func(concat(result, more_results_based_on_info),
new_info));

The result grows in an obvious way and there is no "trickery" or
"sorcery" involved. It's as straight forward as any other kind of coding,
though it can get annoying if "info" contains many things, and I can't say
anything good about the speed of execution.

On Wed, Jan 24, 2024 at 3:30 PM neri-engineering via Discuss <
discuss@lists.openscad.org> wrote:

With recursive functions it's a bit tricky to figure out the order of
points after they're all assembled. The problem I had was that the
recursive function which called concat() on two lists did it in an order
that resulted in the final list having its points in a reverse order from
what I expected. There is always "trickery" and a fair bit of "sorcery"
involved in getting recursive functions to do the right thing. Anyhow this
reverse order (from what I was assuming) is what caused the
clockwise/counterclockwise polygon traversal situation.

Sent with Proton Mail https://proton.me/ secure email.

On Wednesday, January 24th, 2024 at 2:06 PM, David Phillip Oster via
Discuss discuss@lists.openscad.org wrote:

Thank you for that neri-engineering, and nop head. That’s a fun example.


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

You might find it instructive to take a look at the code for BOSL2, which may give you some insight into how you might write more sophisticated code. It's possible to implement total_animation_steps_up_to and total_animation_steps without recursion at all: total_animation_steps = animation_durations * [for(i=[0:len(animation_durations)-1]) 1]; function total_animation_steps_up_to(partnum) = partnum==1 ? 0 : [for(i=[0:1:partnum-2]) animation_durations[i]] * [for(i=[0:1:partnum-2]) 1]; But get_part_number needs recursion. Using 1 based indexing in a 0 based language is a questionable complication. Why not start with part 0? On Wed, Jan 24, 2024 at 11:35 PM neri-engineering via Discuss < discuss@lists.openscad.org> wrote: > Well that certainly makes things easier, thanks. This syntax is > reminiscent of TinyScheme, which I used inside of GIMP image tool. > > Sent with Proton Mail <https://proton.me/> secure email. > > On Wednesday, January 24th, 2024 at 10:04 PM, Father Horton via Discuss < > discuss@lists.openscad.org> wrote: > > Also note that you can have multiple assignments in a let statement. Just > separate them with commas. I assume they evaluate left-to-right, though I > don't think I've ever put that to the test. > > On Wed, Jan 24, 2024 at 9:50 PM Father Horton <fatherhorton@gmail.com> > wrote: > >> Actually you can declare local variables. It's just not obvious how. >> >> From the manual: >> >> function get_square_triangle_perimeter(p1, p2) = let (hypotenuse = sqrt(p1*p1+p2*p2)) p1 + p2 + hypotenuse; >> >> >> On Wed, Jan 24, 2024 at 9:47 PM neri-engineering via Discuss < >> discuss@lists.openscad.org> wrote: >> >>> It's because in functions you can't declare local variables. So many >>> times you end up writing helper functions which take the semi-compiled form >>> of equations/data. This is one of the reasons why recursive functions in >>> OpenSCAD are difficult to write. It certainly takes some getting used to. >>> That's why I call it "sorcery". It's good mental gymnastics to keep you >>> sharp, to prevent the ole Alzheimer's from setting in. We keep our bodies >>> sharp by working out and we keep our minds sharp by writing recursive >>> functions in OpenSCAD. Some examples I can give you which demonstrate my >>> point. With a standard iterative process we would accomplish the following >>> with simpler code. >>> >>> >>> // There are 21 steps currently. >>> animation_durations=[1, // # 1 slipper_back_plate() >>> 1, // # 2 slipper_bearing() >>> 2, // # 3 top_shaft() >>> 1, // # 4 slipper_back_plate_pin() >>> 2, // # 5 spur_gear() & left_slipper_pad() >>> 1, // # 6 right_slipper_pad() >>> 1, // # 7 slipper_front_plate() >>> 1, // # 8 slipper_spring() >>> 3, // # 9 slipper_nut() >>> 1, // #10 slipper_to_drive_gear_spacer() >>> 1, // #11 drive_gear() >>> 1, // #12 top_shaft_left_spacer() & >>> // left_top_shaft_bearing() >>> 1, // #13 top_shaft_right_spacer() & >>> // right_top_shaft_bearing() >>> 2, // #14 top_shaft_end_screw() >>> 2]; // # ending() >>> >>> // Returns a 1-based part number. Does not start from zero. Identifies >>> the >>> // part being "introduced" in its introductory animation. >>> function get_part_number(tick,index)= >>> (tick<0)?index: >>> (get_part_number(tick-animation_durations[index], >>> index+1)); >>> >>> function total_animation_steps(index,step_count)= >>> (index>=len(animation_durations))? >>> step_count: >>> total_animation_steps(index+1, >>> step_count+animation_durations[index]); >>> >>> // Parameter 'partnum' is one-based. Returns the number of animation >>> steps >>> // that have preceded the beginning of part intro animation for >>> specified part. >>> function total_animation_steps_up_to(partnum,index,step_count)= >>> (index>=(partnum-1))? >>> step_count: >>> total_animation_steps_up_to(partnum,index+1, >>> step_count+animation_durations[index]); >>> >>> // The input parameter is 1-based and represents the part #. >>> function part_animation_steps(partnum)= >>> animation_durations[partnum-1]; >>> >>> // Value 't' is a value in [0,1), it increases linearly with time to >>> span the >>> // entirety of animation. >>> t=0.34; // For example, we're a bit more than 1/3 of the way through the >>> anim. >>> >>> // Parameter 'i' is the animation ticker, zero-based. >>> i=floor(t*total_animation_steps(0,0)); // Start from 0. >>> p=get_part_number(i,0); >>> >>> // Parameter 'w' is like 't', meaning it is in the range 0 <= w < 1, but >>> it >>> // is specific to the part intro animation. The part intro animation >>> begins >>> // at w=0 and is already over at w=1. >>> pre_w=(t*total_animation_steps(0,0) >>> -total_animation_steps_up_to(p,0,0))/part_animation_steps(p); >>> >>> // First it will print out a one-based index describing the part we're >>> on. >>> echo(p); >>> >>> // Next it will print out which fraction of this part's scene we've done. >>> echo(pre_w); >>> >>> >>> Sent with Proton Mail <https://proton.me/> secure email. >>> >>> On Wednesday, January 24th, 2024 at 7:21 PM, Adrian Mariano via Discuss < >>> discuss@lists.openscad.org> wrote: >>> >>> I don't understand why it's any trickier to assemble the order of points >>> with recursive programming. In either case, if you have a growing list (the >>> result) you compute new values and add them to the end of the list. >>> Normally I write a recursive function something like >>> >>> function func(result,info) = >>> done ? result >>> : func(concat(result, more_results_based_on_info), >>> new_info)); >>> >>> The result grows in an obvious way and there is no "trickery" or >>> "sorcery" involved. It's as straight forward as any other kind of coding, >>> though it can get annoying if "info" contains many things, and I can't say >>> anything good about the speed of execution. >>> >>> On Wed, Jan 24, 2024 at 3:30 PM neri-engineering via Discuss < >>> discuss@lists.openscad.org> wrote: >>> >>>> With recursive functions it's a bit tricky to figure out the order of >>>> points after they're all assembled. The problem I had was that the >>>> recursive function which called concat() on two lists did it in an order >>>> that resulted in the final list having its points in a reverse order from >>>> what I expected. There is always "trickery" and a fair bit of "sorcery" >>>> involved in getting recursive functions to do the right thing. Anyhow this >>>> reverse order (from what I was assuming) is what caused the >>>> clockwise/counterclockwise polygon traversal situation. >>>> >>>> Sent with Proton Mail <https://proton.me/> secure email. >>>> >>>> On Wednesday, January 24th, 2024 at 2:06 PM, David Phillip Oster via >>>> Discuss <discuss@lists.openscad.org> wrote: >>>> >>>> Thank you for that neri-engineering, and nop head. That’s a fun example. >>>> >>>> >>>> _______________________________________________ >>>> 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 >
N
neri-engineering
Thu, Jan 25, 2024 5:07 AM

I'm actually tidying up my OpenSCAD code but I'm moving into CadQuery - that is my next main focus. I need more of the abilities that that tool provides. A completely different paradigm is used there, namely Python, which exposes ability to use a richer language and libs.

I may share my optimized OpenSCAD thread library on this mailing list. Would there be an interest in that? I just managed to squeeze out at least a 5x performance increase in F5 mode because I construct a subtrahend plug out of a single polyhedron.

Sent with Proton Mail secure email.

On Wednesday, January 24th, 2024 at 10:50 PM, Adrian Mariano via Discuss discuss@lists.openscad.org wrote:

You might find it instructive to take a look at the code for BOSL2, which may give you some insight into how you might write more sophisticated code.

It's possible to implement total_animation_steps_up_to and total_animation_steps without recursion at all:

total_animation_steps = animation_durations * [for(i=[0:len(animation_durations)-1]) 1];

function total_animation_steps_up_to(partnum) =
partnum==1 ? 0
: [for(i=[0:1:partnum-2]) animation_durations[i]] * [for(i=[0:1:partnum-2]) 1];
But get_part_number needs recursion. Using 1 based indexing in a 0 based language is a questionable complication. Why not start with part 0?

On Wed, Jan 24, 2024 at 11:35 PM neri-engineering via Discuss discuss@lists.openscad.org wrote:

Well that certainly makes things easier, thanks. This syntax is reminiscent of TinyScheme, which I used inside of GIMP image tool.

Sent with Proton Mail secure email.

On Wednesday, January 24th, 2024 at 10:04 PM, Father Horton via Discuss discuss@lists.openscad.org wrote:

Also note that you can have multiple assignments in a let statement. Just separate them with commas. I assume they evaluate left-to-right, though I don't think I've ever put that to the test.

On Wed, Jan 24, 2024 at 9:50 PM Father Horton fatherhorton@gmail.com wrote:

Actually you can declare local variables. It's just not obvious how.

From the manual:

function

get_square_triangle_perimeter

(

p1

,

p2

)

=

let

(

hypotenuse

=

sqrt

(

p1

p1

p2

p2

))

p1

p2

hypotenuse

;

On Wed, Jan 24, 2024 at 9:47 PM neri-engineering via Discuss discuss@lists.openscad.org wrote:

It's because in functions you can't declare local variables. So many times you end up writing helper functions which take the semi-compiled form of equations/data. This is one of the reasons why recursive functions in OpenSCAD are difficult to write. It certainly takes some getting used to. That's why I call it "sorcery". It's good mental gymnastics to keep you sharp, to prevent the ole Alzheimer's from setting in. We keep our bodies sharp by working out and we keep our minds sharp by writing recursive functions in OpenSCAD. Some examples I can give you which demonstrate my point. With a standard iterative process we would accomplish the following with simpler code.

// There are 21 steps currently.
animation_durations=[1, // # 1 slipper_back_plate()
1, // # 2 slipper_bearing()
2, // # 3 top_shaft()
1, // # 4 slipper_back_plate_pin()
2, // # 5 spur_gear() & left_slipper_pad()
1, // # 6 right_slipper_pad()
1, // # 7 slipper_front_plate()
1, // # 8 slipper_spring()
3, // # 9 slipper_nut()
1, // #10 slipper_to_drive_gear_spacer()
1, // #11 drive_gear()
1, // #12 top_shaft_left_spacer() &
// left_top_shaft_bearing()
1, // #13 top_shaft_right_spacer() &
// right_top_shaft_bearing()
2, // #14 top_shaft_end_screw()
2]; // # ending()

// Returns a 1-based part number. Does not start from zero. Identifies the
// part being "introduced" in its introductory animation.
function get_part_number(tick,index)=
(tick<0)?index:
(get_part_number(tick-animation_durations[index],
index+1));

function total_animation_steps(index,step_count)=
(index>=len(animation_durations))?
step_count:
total_animation_steps(index+1,
step_count+animation_durations[index]);

// Parameter 'partnum' is one-based. Returns the number of animation steps
// that have preceded the beginning of part intro animation for specified part.
function total_animation_steps_up_to(partnum,index,step_count)=
(index>=(partnum-1))?
step_count:
total_animation_steps_up_to(partnum,index+1,
step_count+animation_durations[index]);

// The input parameter is 1-based and represents the part #.
function part_animation_steps(partnum)=
animation_durations[partnum-1];

// Value 't' is a value in [0,1), it increases linearly with time to span the
// entirety of animation.
t=0.34; // For example, we're a bit more than 1/3 of the way through the anim.

// Parameter 'i' is the animation ticker, zero-based.
i=floor(t*total_animation_steps(0,0)); // Start from 0.
p=get_part_number(i,0);

// Parameter 'w' is like 't', meaning it is in the range 0 <= w < 1, but it
// is specific to the part intro animation. The part intro animation begins
// at w=0 and is already over at w=1.
pre_w=(t*total_animation_steps(0,0)
-total_animation_steps_up_to(p,0,0))/part_animation_steps(p);

// First it will print out a one-based index describing the part we're on.
echo(p);

// Next it will print out which fraction of this part's scene we've done.echo(pre_w);

Sent with Proton Mail secure email.

On Wednesday, January 24th, 2024 at 7:21 PM, Adrian Mariano via Discuss discuss@lists.openscad.org wrote:

I don't understand why it's any trickier to assemble the order of points with recursive programming. In either case, if you have a growing list (the result) you compute new values and add them to the end of the list. Normally I write a recursive function something like

function func(result,info) =
done ? result
: func(concat(result, more_results_based_on_info),
new_info));

The result grows in an obvious way and there is no "trickery" or "sorcery" involved. It's as straight forward as any other kind of coding, though it can get annoying if "info" contains many things, and I can't say anything good about the speed of execution.

On Wed, Jan 24, 2024 at 3:30 PM neri-engineering via Discuss discuss@lists.openscad.org wrote:

With recursive functions it's a bit tricky to figure out the order of points after they're all assembled. The problem I had was that the recursive function which called concat() on two lists did it in an order that resulted in the final list having its points in a reverse order from what I expected. There is always "trickery" and a fair bit of "sorcery" involved in getting recursive functions to do the right thing. Anyhow this reverse order (from what I was assuming) is what caused the clockwise/counterclockwise polygon traversal situation.

Sent with Proton Mail secure email.

On Wednesday, January 24th, 2024 at 2:06 PM, David Phillip Oster via Discuss discuss@lists.openscad.org wrote:

Thank you for that neri-engineering, and nop head. That’s a fun example.


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


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


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

I'm actually tidying up my OpenSCAD code but I'm moving into CadQuery - that is my next main focus. I need more of the abilities that that tool provides. A completely different paradigm is used there, namely Python, which exposes ability to use a richer language and libs. I may share my optimized OpenSCAD thread library on this mailing list. Would there be an interest in that? I just managed to squeeze out at least a 5x performance increase in F5 mode because I construct a subtrahend plug out of a single polyhedron. Sent with [Proton Mail](https://proton.me/) secure email. On Wednesday, January 24th, 2024 at 10:50 PM, Adrian Mariano via Discuss <discuss@lists.openscad.org> wrote: > You might find it instructive to take a look at the code for BOSL2, which may give you some insight into how you might write more sophisticated code. > > It's possible to implement total_animation_steps_up_to and total_animation_steps without recursion at all: > > total_animation_steps = animation_durations * [for(i=[0:len(animation_durations)-1]) 1]; > > function total_animation_steps_up_to(partnum) = > partnum==1 ? 0 > : [for(i=[0:1:partnum-2]) animation_durations[i]] * [for(i=[0:1:partnum-2]) 1]; > But get_part_number needs recursion. Using 1 based indexing in a 0 based language is a questionable complication. Why not start with part 0? > > On Wed, Jan 24, 2024 at 11:35 PM neri-engineering via Discuss <discuss@lists.openscad.org> wrote: > >> Well that certainly makes things easier, thanks. This syntax is reminiscent of TinyScheme, which I used inside of GIMP image tool. >> >> Sent with [Proton Mail](https://proton.me/) secure email. >> >> On Wednesday, January 24th, 2024 at 10:04 PM, Father Horton via Discuss <discuss@lists.openscad.org> wrote: >> >>> Also note that you can have multiple assignments in a let statement. Just separate them with commas. I assume they evaluate left-to-right, though I don't think I've ever put that to the test. >>> >>> On Wed, Jan 24, 2024 at 9:50 PM Father Horton <fatherhorton@gmail.com> wrote: >>> >>>> Actually you can declare local variables. It's just not obvious how. >>>> >>>> From the manual: >>>> >>>> function >>>> >>>> get_square_triangle_perimeter >>>> >>>> ( >>>> >>>> p1 >>>> >>>> , >>>> >>>> p2 >>>> >>>> ) >>>> >>>> = >>>> >>>> let >>>> >>>> ( >>>> >>>> hypotenuse >>>> >>>> = >>>> >>>> sqrt >>>> >>>> ( >>>> >>>> p1 >>>> >>>> * >>>> >>>> p1 >>>> >>>> + >>>> >>>> p2 >>>> >>>> * >>>> >>>> p2 >>>> >>>> )) >>>> >>>> p1 >>>> >>>> + >>>> >>>> p2 >>>> >>>> + >>>> >>>> hypotenuse >>>> >>>> ; >>>> >>>> On Wed, Jan 24, 2024 at 9:47 PM neri-engineering via Discuss <discuss@lists.openscad.org> wrote: >>>> >>>>> It's because in functions you can't declare local variables. So many times you end up writing helper functions which take the semi-compiled form of equations/data. This is one of the reasons why recursive functions in OpenSCAD are difficult to write. It certainly takes some getting used to. That's why I call it "sorcery". It's good mental gymnastics to keep you sharp, to prevent the ole Alzheimer's from setting in. We keep our bodies sharp by working out and we keep our minds sharp by writing recursive functions in OpenSCAD. Some examples I can give you which demonstrate my point. With a standard iterative process we would accomplish the following with simpler code. >>>>> >>>>> // There are 21 steps currently. >>>>> animation_durations=[1, // # 1 slipper_back_plate() >>>>> 1, // # 2 slipper_bearing() >>>>> 2, // # 3 top_shaft() >>>>> 1, // # 4 slipper_back_plate_pin() >>>>> 2, // # 5 spur_gear() & left_slipper_pad() >>>>> 1, // # 6 right_slipper_pad() >>>>> 1, // # 7 slipper_front_plate() >>>>> 1, // # 8 slipper_spring() >>>>> 3, // # 9 slipper_nut() >>>>> 1, // #10 slipper_to_drive_gear_spacer() >>>>> 1, // #11 drive_gear() >>>>> 1, // #12 top_shaft_left_spacer() & >>>>> // left_top_shaft_bearing() >>>>> 1, // #13 top_shaft_right_spacer() & >>>>> // right_top_shaft_bearing() >>>>> 2, // #14 top_shaft_end_screw() >>>>> 2]; // # ending() >>>>> >>>>> // Returns a 1-based part number. Does not start from zero. Identifies the >>>>> // part being "introduced" in its introductory animation. >>>>> function get_part_number(tick,index)= >>>>> (tick<0)?index: >>>>> (get_part_number(tick-animation_durations[index], >>>>> index+1)); >>>>> >>>>> function total_animation_steps(index,step_count)= >>>>> (index>=len(animation_durations))? >>>>> step_count: >>>>> total_animation_steps(index+1, >>>>> step_count+animation_durations[index]); >>>>> >>>>> // Parameter 'partnum' is one-based. Returns the number of animation steps >>>>> // that have preceded the beginning of part intro animation for specified part. >>>>> function total_animation_steps_up_to(partnum,index,step_count)= >>>>> (index>=(partnum-1))? >>>>> step_count: >>>>> total_animation_steps_up_to(partnum,index+1, >>>>> step_count+animation_durations[index]); >>>>> >>>>> // The input parameter is 1-based and represents the part #. >>>>> function part_animation_steps(partnum)= >>>>> animation_durations[partnum-1]; >>>>> >>>>> // Value 't' is a value in [0,1), it increases linearly with time to span the >>>>> // entirety of animation. >>>>> t=0.34; // For example, we're a bit more than 1/3 of the way through the anim. >>>>> >>>>> // Parameter 'i' is the animation ticker, zero-based. >>>>> i=floor(t*total_animation_steps(0,0)); // Start from 0. >>>>> p=get_part_number(i,0); >>>>> >>>>> // Parameter 'w' is like 't', meaning it is in the range 0 <= w < 1, but it >>>>> // is specific to the part intro animation. The part intro animation begins >>>>> // at w=0 and is already over at w=1. >>>>> pre_w=(t*total_animation_steps(0,0) >>>>> -total_animation_steps_up_to(p,0,0))/part_animation_steps(p); >>>>> >>>>> // First it will print out a one-based index describing the part we're on. >>>>> echo(p); >>>>> >>>>> // Next it will print out which fraction of this part's scene we've done.echo(pre_w); >>>>> >>>>> Sent with [Proton Mail](https://proton.me/) secure email. >>>>> >>>>> On Wednesday, January 24th, 2024 at 7:21 PM, Adrian Mariano via Discuss <discuss@lists.openscad.org> wrote: >>>>> >>>>>> I don't understand why it's any trickier to assemble the order of points with recursive programming. In either case, if you have a growing list (the result) you compute new values and add them to the end of the list. Normally I write a recursive function something like >>>>>> >>>>>> function func(result,info) = >>>>>> done ? result >>>>>> : func(concat(result, more_results_based_on_info), >>>>>> new_info)); >>>>>> >>>>>> The result grows in an obvious way and there is no "trickery" or "sorcery" involved. It's as straight forward as any other kind of coding, though it can get annoying if "info" contains many things, and I can't say anything good about the speed of execution. >>>>>> >>>>>> On Wed, Jan 24, 2024 at 3:30 PM neri-engineering via Discuss <discuss@lists.openscad.org> wrote: >>>>>> >>>>>>> With recursive functions it's a bit tricky to figure out the order of points after they're all assembled. The problem I had was that the recursive function which called concat() on two lists did it in an order that resulted in the final list having its points in a reverse order from what I expected. There is always "trickery" and a fair bit of "sorcery" involved in getting recursive functions to do the right thing. Anyhow this reverse order (from what I was assuming) is what caused the clockwise/counterclockwise polygon traversal situation. >>>>>>> >>>>>>> Sent with [Proton Mail](https://proton.me/) secure email. >>>>>>> >>>>>>> On Wednesday, January 24th, 2024 at 2:06 PM, David Phillip Oster via Discuss <discuss@lists.openscad.org> wrote: >>>>>>> >>>>>>>> Thank you for that neri-engineering, and nop head. That’s a fun example. >>>>>>> >>>>>>> _______________________________________________ >>>>>>> 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
Thu, Jan 25, 2024 4:47 PM

I'm actually tidying up my OpenSCAD code but I'm moving into CadQuery -
that is my next main focus.

good luck

On Thu, 25 Jan 2024 at 10:37, neri-engineering via Discuss <
discuss@lists.openscad.org> wrote:

I'm actually tidying up my OpenSCAD code but I'm moving into CadQuery -
that is my next main focus.  I need more of the abilities that that tool
provides.  A completely different paradigm is used there, namely Python,
which exposes ability to use a richer language and libs.

I may share my optimized OpenSCAD thread library on this mailing list.
Would there be an interest in that?  I just managed to squeeze out at least
a 5x performance increase in F5 mode because I construct a subtrahend plug
out of a single polyhedron.

Sent with Proton Mail https://proton.me/ secure email.

On Wednesday, January 24th, 2024 at 10:50 PM, Adrian Mariano via Discuss <
discuss@lists.openscad.org> wrote:

You might find it instructive to take a look at the code for BOSL2, which
may give you some insight into how you might write more sophisticated code.

It's possible to implement total_animation_steps_up_to and
total_animation_steps without recursion at all:

total_animation_steps = animation_durations *
[for(i=[0:len(animation_durations)-1]) 1];

function total_animation_steps_up_to(partnum) =
partnum==1 ? 0
: [for(i=[0:1:partnum-2]) animation_durations[i]] *
[for(i=[0:1:partnum-2]) 1];

But get_part_number needs recursion. Using 1 based indexing in a 0 based
language is a questionable complication. Why not start with part 0?

On Wed, Jan 24, 2024 at 11:35 PM neri-engineering via Discuss <
discuss@lists.openscad.org> wrote:

Well that certainly makes things easier, thanks. This syntax is
reminiscent of TinyScheme, which I used inside of GIMP image tool.

Sent with Proton Mail https://proton.me/ secure email.

On Wednesday, January 24th, 2024 at 10:04 PM, Father Horton via Discuss <
discuss@lists.openscad.org> wrote:

Also note that you can have multiple assignments in a let statement. Just
separate them with commas. I assume they evaluate left-to-right, though I
don't think I've ever put that to the test.

On Wed, Jan 24, 2024 at 9:50 PM Father Horton fatherhorton@gmail.com
wrote:

Actually you can declare local variables. It's just not obvious how.

From the manual:

function get_square_triangle_perimeter(p1, p2) =  let (hypotenuse = sqrt(p1p1+p2p2))    p1 + p2 + hypotenuse;

On Wed, Jan 24, 2024 at 9:47 PM neri-engineering via Discuss <
discuss@lists.openscad.org> wrote:

It's because in functions you can't declare local variables. So many
times you end up writing helper functions which take the semi-compiled form
of equations/data. This is one of the reasons why recursive functions in
OpenSCAD are difficult to write. It certainly takes some getting used to.
That's why I call it "sorcery". It's good mental gymnastics to keep you
sharp, to prevent the ole Alzheimer's from setting in. We keep our bodies
sharp by working out and we keep our minds sharp by writing recursive
functions in OpenSCAD. Some examples I can give you which demonstrate my
point. With a standard iterative process we would accomplish the following
with simpler code.

// There are 21 steps currently.
animation_durations=[1, // # 1 slipper_back_plate()
1, // # 2 slipper_bearing()
2, // # 3 top_shaft()
1, // # 4 slipper_back_plate_pin()
2, // # 5 spur_gear() & left_slipper_pad()
1, // # 6 right_slipper_pad()
1, // # 7 slipper_front_plate()
1, // # 8 slipper_spring()
3, // # 9 slipper_nut()
1, // #10 slipper_to_drive_gear_spacer()
1, // #11 drive_gear()
1, // #12 top_shaft_left_spacer() &
// left_top_shaft_bearing()
1, // #13 top_shaft_right_spacer() &
// right_top_shaft_bearing()
2, // #14 top_shaft_end_screw()
2]; // # ending()

// Returns a 1-based part number. Does not start from zero. Identifies
the
// part being "introduced" in its introductory animation.
function get_part_number(tick,index)=
(tick<0)?index:
(get_part_number(tick-animation_durations[index],
index+1));

function total_animation_steps(index,step_count)=
(index>=len(animation_durations))?
step_count:
total_animation_steps(index+1,
step_count+animation_durations[index]);

// Parameter 'partnum' is one-based. Returns the number of animation
steps
// that have preceded the beginning of part intro animation for
specified part.
function total_animation_steps_up_to(partnum,index,step_count)=
(index>=(partnum-1))?
step_count:
total_animation_steps_up_to(partnum,index+1,
step_count+animation_durations[index]);

// The input parameter is 1-based and represents the part #.
function part_animation_steps(partnum)=
animation_durations[partnum-1];

// Value 't' is a value in [0,1), it increases linearly with time to
span the
// entirety of animation.
t=0.34; // For example, we're a bit more than 1/3 of the way through
the anim.

// Parameter 'i' is the animation ticker, zero-based.
i=floor(t*total_animation_steps(0,0)); // Start from 0.
p=get_part_number(i,0);

// Parameter 'w' is like 't', meaning it is in the range 0 <= w < 1,
but it
// is specific to the part intro animation. The part intro animation
begins
// at w=0 and is already over at w=1.
pre_w=(t*total_animation_steps(0,0)
-total_animation_steps_up_to(p,0,0))/part_animation_steps(p);

// First it will print out a one-based index describing the part we're
on.
echo(p);

// Next it will print out which fraction of this part's scene we've
done.
echo(pre_w);

Sent with Proton Mail https://proton.me/ secure email.

On Wednesday, January 24th, 2024 at 7:21 PM, Adrian Mariano via Discuss
discuss@lists.openscad.org wrote:

I don't understand why it's any trickier to assemble the order of
points with recursive programming. In either case, if you have a growing
list (the result) you compute new values and add them to the end of the
list. Normally I write a recursive function something like

function func(result,info) =
done ? result
: func(concat(result, more_results_based_on_info),
new_info));

The result grows in an obvious way and there is no "trickery" or
"sorcery" involved. It's as straight forward as any other kind of coding,
though it can get annoying if "info" contains many things, and I can't say
anything good about the speed of execution.

On Wed, Jan 24, 2024 at 3:30 PM neri-engineering via Discuss <
discuss@lists.openscad.org> wrote:

With recursive functions it's a bit tricky to figure out the order of
points after they're all assembled. The problem I had was that the
recursive function which called concat() on two lists did it in an order
that resulted in the final list having its points in a reverse order from
what I expected. There is always "trickery" and a fair bit of "sorcery"
involved in getting recursive functions to do the right thing. Anyhow this
reverse order (from what I was assuming) is what caused the
clockwise/counterclockwise polygon traversal situation.

Sent with Proton Mail https://proton.me/ secure email.

On Wednesday, January 24th, 2024 at 2:06 PM, David Phillip Oster via
Discuss discuss@lists.openscad.org wrote:

Thank you for that neri-engineering, and nop head. That’s a fun
example.


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

I'm actually tidying up my OpenSCAD code but I'm moving into CadQuery - that is my next main focus. good luck On Thu, 25 Jan 2024 at 10:37, neri-engineering via Discuss < discuss@lists.openscad.org> wrote: > I'm actually tidying up my OpenSCAD code but I'm moving into CadQuery - > that is my next main focus. I need more of the abilities that that tool > provides. A completely different paradigm is used there, namely Python, > which exposes ability to use a richer language and libs. > > I may share my optimized OpenSCAD thread library on this mailing list. > Would there be an interest in that? I just managed to squeeze out at least > a 5x performance increase in F5 mode because I construct a subtrahend plug > out of a single polyhedron. > > > > Sent with Proton Mail <https://proton.me/> secure email. > > On Wednesday, January 24th, 2024 at 10:50 PM, Adrian Mariano via Discuss < > discuss@lists.openscad.org> wrote: > > You might find it instructive to take a look at the code for BOSL2, which > may give you some insight into how you might write more sophisticated code. > > It's possible to implement total_animation_steps_up_to and > total_animation_steps without recursion at all: > > total_animation_steps = animation_durations * > [for(i=[0:len(animation_durations)-1]) 1]; > > function total_animation_steps_up_to(partnum) = > partnum==1 ? 0 > : [for(i=[0:1:partnum-2]) animation_durations[i]] * > [for(i=[0:1:partnum-2]) 1]; > > But get_part_number needs recursion. Using 1 based indexing in a 0 based > language is a questionable complication. Why not start with part 0? > > On Wed, Jan 24, 2024 at 11:35 PM neri-engineering via Discuss < > discuss@lists.openscad.org> wrote: > >> Well that certainly makes things easier, thanks. This syntax is >> reminiscent of TinyScheme, which I used inside of GIMP image tool. >> >> Sent with Proton Mail <https://proton.me/> secure email. >> >> On Wednesday, January 24th, 2024 at 10:04 PM, Father Horton via Discuss < >> discuss@lists.openscad.org> wrote: >> >> Also note that you can have multiple assignments in a let statement. Just >> separate them with commas. I assume they evaluate left-to-right, though I >> don't think I've ever put that to the test. >> >> On Wed, Jan 24, 2024 at 9:50 PM Father Horton <fatherhorton@gmail.com> >> wrote: >> >>> Actually you can declare local variables. It's just not obvious how. >>> >>> From the manual: >>> >>> function get_square_triangle_perimeter(p1, p2) = let (hypotenuse = sqrt(p1*p1+p2*p2)) p1 + p2 + hypotenuse; >>> >>> >>> On Wed, Jan 24, 2024 at 9:47 PM neri-engineering via Discuss < >>> discuss@lists.openscad.org> wrote: >>> >>>> It's because in functions you can't declare local variables. So many >>>> times you end up writing helper functions which take the semi-compiled form >>>> of equations/data. This is one of the reasons why recursive functions in >>>> OpenSCAD are difficult to write. It certainly takes some getting used to. >>>> That's why I call it "sorcery". It's good mental gymnastics to keep you >>>> sharp, to prevent the ole Alzheimer's from setting in. We keep our bodies >>>> sharp by working out and we keep our minds sharp by writing recursive >>>> functions in OpenSCAD. Some examples I can give you which demonstrate my >>>> point. With a standard iterative process we would accomplish the following >>>> with simpler code. >>>> >>>> >>>> // There are 21 steps currently. >>>> animation_durations=[1, // # 1 slipper_back_plate() >>>> 1, // # 2 slipper_bearing() >>>> 2, // # 3 top_shaft() >>>> 1, // # 4 slipper_back_plate_pin() >>>> 2, // # 5 spur_gear() & left_slipper_pad() >>>> 1, // # 6 right_slipper_pad() >>>> 1, // # 7 slipper_front_plate() >>>> 1, // # 8 slipper_spring() >>>> 3, // # 9 slipper_nut() >>>> 1, // #10 slipper_to_drive_gear_spacer() >>>> 1, // #11 drive_gear() >>>> 1, // #12 top_shaft_left_spacer() & >>>> // left_top_shaft_bearing() >>>> 1, // #13 top_shaft_right_spacer() & >>>> // right_top_shaft_bearing() >>>> 2, // #14 top_shaft_end_screw() >>>> 2]; // # ending() >>>> >>>> // Returns a 1-based part number. Does not start from zero. Identifies >>>> the >>>> // part being "introduced" in its introductory animation. >>>> function get_part_number(tick,index)= >>>> (tick<0)?index: >>>> (get_part_number(tick-animation_durations[index], >>>> index+1)); >>>> >>>> function total_animation_steps(index,step_count)= >>>> (index>=len(animation_durations))? >>>> step_count: >>>> total_animation_steps(index+1, >>>> step_count+animation_durations[index]); >>>> >>>> // Parameter 'partnum' is one-based. Returns the number of animation >>>> steps >>>> // that have preceded the beginning of part intro animation for >>>> specified part. >>>> function total_animation_steps_up_to(partnum,index,step_count)= >>>> (index>=(partnum-1))? >>>> step_count: >>>> total_animation_steps_up_to(partnum,index+1, >>>> step_count+animation_durations[index]); >>>> >>>> // The input parameter is 1-based and represents the part #. >>>> function part_animation_steps(partnum)= >>>> animation_durations[partnum-1]; >>>> >>>> // Value 't' is a value in [0,1), it increases linearly with time to >>>> span the >>>> // entirety of animation. >>>> t=0.34; // For example, we're a bit more than 1/3 of the way through >>>> the anim. >>>> >>>> // Parameter 'i' is the animation ticker, zero-based. >>>> i=floor(t*total_animation_steps(0,0)); // Start from 0. >>>> p=get_part_number(i,0); >>>> >>>> // Parameter 'w' is like 't', meaning it is in the range 0 <= w < 1, >>>> but it >>>> // is specific to the part intro animation. The part intro animation >>>> begins >>>> // at w=0 and is already over at w=1. >>>> pre_w=(t*total_animation_steps(0,0) >>>> -total_animation_steps_up_to(p,0,0))/part_animation_steps(p); >>>> >>>> // First it will print out a one-based index describing the part we're >>>> on. >>>> echo(p); >>>> >>>> // Next it will print out which fraction of this part's scene we've >>>> done. >>>> echo(pre_w); >>>> >>>> >>>> Sent with Proton Mail <https://proton.me/> secure email. >>>> >>>> On Wednesday, January 24th, 2024 at 7:21 PM, Adrian Mariano via Discuss >>>> <discuss@lists.openscad.org> wrote: >>>> >>>> I don't understand why it's any trickier to assemble the order of >>>> points with recursive programming. In either case, if you have a growing >>>> list (the result) you compute new values and add them to the end of the >>>> list. Normally I write a recursive function something like >>>> >>>> function func(result,info) = >>>> done ? result >>>> : func(concat(result, more_results_based_on_info), >>>> new_info)); >>>> >>>> The result grows in an obvious way and there is no "trickery" or >>>> "sorcery" involved. It's as straight forward as any other kind of coding, >>>> though it can get annoying if "info" contains many things, and I can't say >>>> anything good about the speed of execution. >>>> >>>> On Wed, Jan 24, 2024 at 3:30 PM neri-engineering via Discuss < >>>> discuss@lists.openscad.org> wrote: >>>> >>>>> With recursive functions it's a bit tricky to figure out the order of >>>>> points after they're all assembled. The problem I had was that the >>>>> recursive function which called concat() on two lists did it in an order >>>>> that resulted in the final list having its points in a reverse order from >>>>> what I expected. There is always "trickery" and a fair bit of "sorcery" >>>>> involved in getting recursive functions to do the right thing. Anyhow this >>>>> reverse order (from what I was assuming) is what caused the >>>>> clockwise/counterclockwise polygon traversal situation. >>>>> >>>>> Sent with Proton Mail <https://proton.me/> secure email. >>>>> >>>>> On Wednesday, January 24th, 2024 at 2:06 PM, David Phillip Oster via >>>>> Discuss <discuss@lists.openscad.org> wrote: >>>>> >>>>> Thank you for that neri-engineering, and nop head. That’s a fun >>>>> example. >>>>> >>>>> >>>>> _______________________________________________ >>>>> 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 >
N
neri-engineering
Sun, Jan 28, 2024 12:11 AM

Indeed the 'let' construct is a life-saver to make code much clearer whereas it would have taken additional recursive helper functions to achieve the same level of clarity. This is an example that is working for me now.

echo(__invol_gear_path_builder(0,3,false));

// Parameter 'i' should be initialized to zero. Some examples:
// segs=3,q=true: [0,2,4,6,8,9,7,5,3,1]
// segs=3,q=false: [0, 4,6,8,9,7,5, 1]
function __invol_gear_path_builder(i,segs,q)=
((i==-1)?[]:
let(even=((i%2)==0),
flip=(even&&(i==((segs+1)*2))),
incr=(flip?1:(even?2:-2)),
omit=((!q)&&((i==2)||(i==3))))
concat(omit?[]:[i], __invol_gear_path_builder(i+incr,segs,q)));

Sent with Proton Mail secure email.

On Wednesday, January 24th, 2024 at 9:50 PM, Father Horton via Discuss discuss@lists.openscad.org wrote:

Actually you can declare local variables. It's just not obvious how.

From the manual:

function

get_square_triangle_perimeter

(

p1

,

p2

)

=

let

(

hypotenuse

=

sqrt

(

p1

p1

p2

p2

))

p1

p2

hypotenuse

;

On Wed, Jan 24, 2024 at 9:47 PM neri-engineering via Discuss discuss@lists.openscad.org wrote:

It's because in functions you can't declare local variables. So many times you end up writing helper functions which take the semi-compiled form of equations/data. This is one of the reasons why recursive functions in OpenSCAD are difficult to write. It certainly takes some getting used to. That's why I call it "sorcery". It's good mental gymnastics to keep you sharp, to prevent the ole Alzheimer's from setting in. We keep our bodies sharp by working out and we keep our minds sharp by writing recursive functions in OpenSCAD. Some examples I can give you which demonstrate my point. With a standard iterative process we would accomplish the following with simpler code.

// There are 21 steps currently.
animation_durations=[1, // # 1 slipper_back_plate()
1, // # 2 slipper_bearing()
2, // # 3 top_shaft()
1, // # 4 slipper_back_plate_pin()
2, // # 5 spur_gear() & left_slipper_pad()
1, // # 6 right_slipper_pad()
1, // # 7 slipper_front_plate()
1, // # 8 slipper_spring()
3, // # 9 slipper_nut()
1, // #10 slipper_to_drive_gear_spacer()
1, // #11 drive_gear()
1, // #12 top_shaft_left_spacer() &
// left_top_shaft_bearing()
1, // #13 top_shaft_right_spacer() &
// right_top_shaft_bearing()
2, // #14 top_shaft_end_screw()
2]; // # ending()

// Returns a 1-based part number. Does not start from zero. Identifies the
// part being "introduced" in its introductory animation.
function get_part_number(tick,index)=
(tick<0)?index:
(get_part_number(tick-animation_durations[index],
index+1));

function total_animation_steps(index,step_count)=
(index>=len(animation_durations))?
step_count:
total_animation_steps(index+1,
step_count+animation_durations[index]);

// Parameter 'partnum' is one-based. Returns the number of animation steps
// that have preceded the beginning of part intro animation for specified part.
function total_animation_steps_up_to(partnum,index,step_count)=
(index>=(partnum-1))?
step_count:
total_animation_steps_up_to(partnum,index+1,
step_count+animation_durations[index]);

// The input parameter is 1-based and represents the part #.
function part_animation_steps(partnum)=
animation_durations[partnum-1];

// Value 't' is a value in [0,1), it increases linearly with time to span the
// entirety of animation.
t=0.34; // For example, we're a bit more than 1/3 of the way through the anim.

// Parameter 'i' is the animation ticker, zero-based.
i=floor(t*total_animation_steps(0,0)); // Start from 0.
p=get_part_number(i,0);

// Parameter 'w' is like 't', meaning it is in the range 0 <= w < 1, but it
// is specific to the part intro animation. The part intro animation begins
// at w=0 and is already over at w=1.
pre_w=(t*total_animation_steps(0,0)
-total_animation_steps_up_to(p,0,0))/part_animation_steps(p);

// First it will print out a one-based index describing the part we're on.
echo(p);

// Next it will print out which fraction of this part's scene we've done.echo(pre_w);

Sent with Proton Mail secure email.

On Wednesday, January 24th, 2024 at 7:21 PM, Adrian Mariano via Discuss discuss@lists.openscad.org wrote:

I don't understand why it's any trickier to assemble the order of points with recursive programming. In either case, if you have a growing list (the result) you compute new values and add them to the end of the list. Normally I write a recursive function something like

function func(result,info) =
done ? result
: func(concat(result, more_results_based_on_info),
new_info));

The result grows in an obvious way and there is no "trickery" or "sorcery" involved. It's as straight forward as any other kind of coding, though it can get annoying if "info" contains many things, and I can't say anything good about the speed of execution.

On Wed, Jan 24, 2024 at 3:30 PM neri-engineering via Discuss discuss@lists.openscad.org wrote:

With recursive functions it's a bit tricky to figure out the order of points after they're all assembled. The problem I had was that the recursive function which called concat() on two lists did it in an order that resulted in the final list having its points in a reverse order from what I expected. There is always "trickery" and a fair bit of "sorcery" involved in getting recursive functions to do the right thing. Anyhow this reverse order (from what I was assuming) is what caused the clockwise/counterclockwise polygon traversal situation.

Sent with Proton Mail secure email.

On Wednesday, January 24th, 2024 at 2:06 PM, David Phillip Oster via Discuss discuss@lists.openscad.org wrote:

Thank you for that neri-engineering, and nop head. That’s a fun example.


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

Indeed the 'let' construct is a life-saver to make code much clearer whereas it would have taken additional recursive helper functions to achieve the same level of clarity. This is an example that is working for me now. echo(__invol_gear_path_builder(0,3,false)); // Parameter 'i' should be initialized to zero. Some examples: // segs=3,q=true: [0,2,4,6,8,9,7,5,3,1] // segs=3,q=false: [0, 4,6,8,9,7,5, 1] function __invol_gear_path_builder(i,segs,q)= ((i==-1)?[]: let(even=((i%2)==0), flip=(even&&(i==((segs+1)*2))), incr=(flip?1:(even?2:-2)), omit=((!q)&&((i==2)||(i==3)))) concat(omit?[]:[i], __invol_gear_path_builder(i+incr,segs,q))); Sent with [Proton Mail](https://proton.me/) secure email. On Wednesday, January 24th, 2024 at 9:50 PM, Father Horton via Discuss <discuss@lists.openscad.org> wrote: > Actually you can declare local variables. It's just not obvious how. > > From the manual: > > function > > get_square_triangle_perimeter > > ( > > p1 > > , > > p2 > > ) > > = > > let > > ( > > hypotenuse > > = > > sqrt > > ( > > p1 > > * > > p1 > > + > > p2 > > * > > p2 > > )) > > p1 > > + > > p2 > > + > > hypotenuse > > ; > > On Wed, Jan 24, 2024 at 9:47 PM neri-engineering via Discuss <discuss@lists.openscad.org> wrote: > >> It's because in functions you can't declare local variables. So many times you end up writing helper functions which take the semi-compiled form of equations/data. This is one of the reasons why recursive functions in OpenSCAD are difficult to write. It certainly takes some getting used to. That's why I call it "sorcery". It's good mental gymnastics to keep you sharp, to prevent the ole Alzheimer's from setting in. We keep our bodies sharp by working out and we keep our minds sharp by writing recursive functions in OpenSCAD. Some examples I can give you which demonstrate my point. With a standard iterative process we would accomplish the following with simpler code. >> >> // There are 21 steps currently. >> animation_durations=[1, // # 1 slipper_back_plate() >> 1, // # 2 slipper_bearing() >> 2, // # 3 top_shaft() >> 1, // # 4 slipper_back_plate_pin() >> 2, // # 5 spur_gear() & left_slipper_pad() >> 1, // # 6 right_slipper_pad() >> 1, // # 7 slipper_front_plate() >> 1, // # 8 slipper_spring() >> 3, // # 9 slipper_nut() >> 1, // #10 slipper_to_drive_gear_spacer() >> 1, // #11 drive_gear() >> 1, // #12 top_shaft_left_spacer() & >> // left_top_shaft_bearing() >> 1, // #13 top_shaft_right_spacer() & >> // right_top_shaft_bearing() >> 2, // #14 top_shaft_end_screw() >> 2]; // # ending() >> >> // Returns a 1-based part number. Does not start from zero. Identifies the >> // part being "introduced" in its introductory animation. >> function get_part_number(tick,index)= >> (tick<0)?index: >> (get_part_number(tick-animation_durations[index], >> index+1)); >> >> function total_animation_steps(index,step_count)= >> (index>=len(animation_durations))? >> step_count: >> total_animation_steps(index+1, >> step_count+animation_durations[index]); >> >> // Parameter 'partnum' is one-based. Returns the number of animation steps >> // that have preceded the beginning of part intro animation for specified part. >> function total_animation_steps_up_to(partnum,index,step_count)= >> (index>=(partnum-1))? >> step_count: >> total_animation_steps_up_to(partnum,index+1, >> step_count+animation_durations[index]); >> >> // The input parameter is 1-based and represents the part #. >> function part_animation_steps(partnum)= >> animation_durations[partnum-1]; >> >> // Value 't' is a value in [0,1), it increases linearly with time to span the >> // entirety of animation. >> t=0.34; // For example, we're a bit more than 1/3 of the way through the anim. >> >> // Parameter 'i' is the animation ticker, zero-based. >> i=floor(t*total_animation_steps(0,0)); // Start from 0. >> p=get_part_number(i,0); >> >> // Parameter 'w' is like 't', meaning it is in the range 0 <= w < 1, but it >> // is specific to the part intro animation. The part intro animation begins >> // at w=0 and is already over at w=1. >> pre_w=(t*total_animation_steps(0,0) >> -total_animation_steps_up_to(p,0,0))/part_animation_steps(p); >> >> // First it will print out a one-based index describing the part we're on. >> echo(p); >> >> // Next it will print out which fraction of this part's scene we've done.echo(pre_w); >> >> Sent with [Proton Mail](https://proton.me/) secure email. >> >> On Wednesday, January 24th, 2024 at 7:21 PM, Adrian Mariano via Discuss <discuss@lists.openscad.org> wrote: >> >>> I don't understand why it's any trickier to assemble the order of points with recursive programming. In either case, if you have a growing list (the result) you compute new values and add them to the end of the list. Normally I write a recursive function something like >>> >>> function func(result,info) = >>> done ? result >>> : func(concat(result, more_results_based_on_info), >>> new_info)); >>> >>> The result grows in an obvious way and there is no "trickery" or "sorcery" involved. It's as straight forward as any other kind of coding, though it can get annoying if "info" contains many things, and I can't say anything good about the speed of execution. >>> >>> On Wed, Jan 24, 2024 at 3:30 PM neri-engineering via Discuss <discuss@lists.openscad.org> wrote: >>> >>>> With recursive functions it's a bit tricky to figure out the order of points after they're all assembled. The problem I had was that the recursive function which called concat() on two lists did it in an order that resulted in the final list having its points in a reverse order from what I expected. There is always "trickery" and a fair bit of "sorcery" involved in getting recursive functions to do the right thing. Anyhow this reverse order (from what I was assuming) is what caused the clockwise/counterclockwise polygon traversal situation. >>>> >>>> Sent with [Proton Mail](https://proton.me/) secure email. >>>> >>>> On Wednesday, January 24th, 2024 at 2:06 PM, David Phillip Oster via Discuss <discuss@lists.openscad.org> wrote: >>>> >>>>> Thank you for that neri-engineering, and nop head. That’s a fun example. >>>> >>>> _______________________________________________ >>>> 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
FH
Father Horton
Sun, Jan 28, 2024 12:55 AM

How crazy do you want to get? If you call parameters by name, you can have
it initialize the value of i for you with a default.

On Sat, Jan 27, 2024 at 6:11 PM neri-engineering <
neri-engineering@protonmail.com> wrote:

Indeed the 'let' construct is a life-saver to make code much clearer
whereas it would have taken additional recursive helper functions to
achieve the same level of clarity.  This is an example that is working for
me now.

echo(__invol_gear_path_builder(0,3,false));

// Parameter 'i' should be initialized to zero.  Some examples:
//  segs=3,q=true:  [0,2,4,6,8,9,7,5,3,1]
//  segs=3,q=false: [0,  4,6,8,9,7,5,  1]
function __invol_gear_path_builder(i,segs,q)=
((i==-1)?[]:
let(even=((i%2)==0),
flip=(even&&(i==((segs+1)*2))),
incr=(flip?1:(even?2:-2)),
omit=((!q)&&((i==2)||(i==3))))
concat(omit?[]:[i],
__invol_gear_path_builder(i+incr,segs,q)));

Sent with Proton Mail https://proton.me/ secure email.

On Wednesday, January 24th, 2024 at 9:50 PM, Father Horton via Discuss <
discuss@lists.openscad.org> wrote:

Actually you can declare local variables. It's just not obvious how.

From the manual:

function get_square_triangle_perimeter(p1, p2) =  let (hypotenuse = sqrt(p1p1+p2p2))    p1 + p2 + hypotenuse;

On Wed, Jan 24, 2024 at 9:47 PM neri-engineering via Discuss <
discuss@lists.openscad.org> wrote:

It's because in functions you can't declare local variables. So many
times you end up writing helper functions which take the semi-compiled form
of equations/data. This is one of the reasons why recursive functions in
OpenSCAD are difficult to write. It certainly takes some getting used to.
That's why I call it "sorcery". It's good mental gymnastics to keep you
sharp, to prevent the ole Alzheimer's from setting in. We keep our bodies
sharp by working out and we keep our minds sharp by writing recursive
functions in OpenSCAD. Some examples I can give you which demonstrate my
point. With a standard iterative process we would accomplish the following
with simpler code.

// There are 21 steps currently.
animation_durations=[1, // # 1 slipper_back_plate()
1, // # 2 slipper_bearing()
2, // # 3 top_shaft()
1, // # 4 slipper_back_plate_pin()
2, // # 5 spur_gear() & left_slipper_pad()
1, // # 6 right_slipper_pad()
1, // # 7 slipper_front_plate()
1, // # 8 slipper_spring()
3, // # 9 slipper_nut()
1, // #10 slipper_to_drive_gear_spacer()
1, // #11 drive_gear()
1, // #12 top_shaft_left_spacer() &
// left_top_shaft_bearing()
1, // #13 top_shaft_right_spacer() &
// right_top_shaft_bearing()
2, // #14 top_shaft_end_screw()
2]; // # ending()

// Returns a 1-based part number. Does not start from zero. Identifies the
// part being "introduced" in its introductory animation.
function get_part_number(tick,index)=
(tick<0)?index:
(get_part_number(tick-animation_durations[index],
index+1));

function total_animation_steps(index,step_count)=
(index>=len(animation_durations))?
step_count:
total_animation_steps(index+1,
step_count+animation_durations[index]);

// Parameter 'partnum' is one-based. Returns the number of animation steps
// that have preceded the beginning of part intro animation for specified
part.
function total_animation_steps_up_to(partnum,index,step_count)=
(index>=(partnum-1))?
step_count:
total_animation_steps_up_to(partnum,index+1,
step_count+animation_durations[index]);

// The input parameter is 1-based and represents the part #.
function part_animation_steps(partnum)=
animation_durations[partnum-1];

// Value 't' is a value in [0,1), it increases linearly with time to span
the
// entirety of animation.
t=0.34; // For example, we're a bit more than 1/3 of the way through the
anim.

// Parameter 'i' is the animation ticker, zero-based.
i=floor(t*total_animation_steps(0,0)); // Start from 0.
p=get_part_number(i,0);

// Parameter 'w' is like 't', meaning it is in the range 0 <= w < 1, but
it
// is specific to the part intro animation. The part intro animation
begins
// at w=0 and is already over at w=1.
pre_w=(t*total_animation_steps(0,0)
-total_animation_steps_up_to(p,0,0))/part_animation_steps(p);

// First it will print out a one-based index describing the part we're on.
echo(p);

// Next it will print out which fraction of this part's scene we've done.
echo(pre_w);

Sent with Proton Mail https://proton.me/ secure email.

On Wednesday, January 24th, 2024 at 7:21 PM, Adrian Mariano via Discuss <
discuss@lists.openscad.org> wrote:

I don't understand why it's any trickier to assemble the order of points
with recursive programming. In either case, if you have a growing list (the
result) you compute new values and add them to the end of the list.
Normally I write a recursive function something like

function func(result,info) =
done ? result
: func(concat(result, more_results_based_on_info),
new_info));

The result grows in an obvious way and there is no "trickery" or
"sorcery" involved. It's as straight forward as any other kind of coding,
though it can get annoying if "info" contains many things, and I can't say
anything good about the speed of execution.

On Wed, Jan 24, 2024 at 3:30 PM neri-engineering via Discuss <
discuss@lists.openscad.org> wrote:

With recursive functions it's a bit tricky to figure out the order of
points after they're all assembled. The problem I had was that the
recursive function which called concat() on two lists did it in an order
that resulted in the final list having its points in a reverse order from
what I expected. There is always "trickery" and a fair bit of "sorcery"
involved in getting recursive functions to do the right thing. Anyhow this
reverse order (from what I was assuming) is what caused the
clockwise/counterclockwise polygon traversal situation.

Sent with Proton Mail https://proton.me/ secure email.

On Wednesday, January 24th, 2024 at 2:06 PM, David Phillip Oster via
Discuss discuss@lists.openscad.org wrote:

Thank you for that neri-engineering, and nop head. That’s a fun example.


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

How crazy do you want to get? If you call parameters by name, you can have it initialize the value of i for you with a default. On Sat, Jan 27, 2024 at 6:11 PM neri-engineering < neri-engineering@protonmail.com> wrote: > Indeed the 'let' construct is a life-saver to make code much clearer > whereas it would have taken additional recursive helper functions to > achieve the same level of clarity. This is an example that is working for > me now. > > echo(__invol_gear_path_builder(0,3,false)); > > // Parameter 'i' should be initialized to zero. Some examples: > // segs=3,q=true: [0,2,4,6,8,9,7,5,3,1] > // segs=3,q=false: [0, 4,6,8,9,7,5, 1] > function __invol_gear_path_builder(i,segs,q)= > ((i==-1)?[]: > let(even=((i%2)==0), > flip=(even&&(i==((segs+1)*2))), > incr=(flip?1:(even?2:-2)), > omit=((!q)&&((i==2)||(i==3)))) > concat(omit?[]:[i], > __invol_gear_path_builder(i+incr,segs,q))); > > Sent with Proton Mail <https://proton.me/> secure email. > > On Wednesday, January 24th, 2024 at 9:50 PM, Father Horton via Discuss < > discuss@lists.openscad.org> wrote: > > Actually you can declare local variables. It's just not obvious how. > > From the manual: > > function get_square_triangle_perimeter(p1, p2) = let (hypotenuse = sqrt(p1*p1+p2*p2)) p1 + p2 + hypotenuse; > > > On Wed, Jan 24, 2024 at 9:47 PM neri-engineering via Discuss < > discuss@lists.openscad.org> wrote: > >> It's because in functions you can't declare local variables. So many >> times you end up writing helper functions which take the semi-compiled form >> of equations/data. This is one of the reasons why recursive functions in >> OpenSCAD are difficult to write. It certainly takes some getting used to. >> That's why I call it "sorcery". It's good mental gymnastics to keep you >> sharp, to prevent the ole Alzheimer's from setting in. We keep our bodies >> sharp by working out and we keep our minds sharp by writing recursive >> functions in OpenSCAD. Some examples I can give you which demonstrate my >> point. With a standard iterative process we would accomplish the following >> with simpler code. >> >> >> // There are 21 steps currently. >> animation_durations=[1, // # 1 slipper_back_plate() >> 1, // # 2 slipper_bearing() >> 2, // # 3 top_shaft() >> 1, // # 4 slipper_back_plate_pin() >> 2, // # 5 spur_gear() & left_slipper_pad() >> 1, // # 6 right_slipper_pad() >> 1, // # 7 slipper_front_plate() >> 1, // # 8 slipper_spring() >> 3, // # 9 slipper_nut() >> 1, // #10 slipper_to_drive_gear_spacer() >> 1, // #11 drive_gear() >> 1, // #12 top_shaft_left_spacer() & >> // left_top_shaft_bearing() >> 1, // #13 top_shaft_right_spacer() & >> // right_top_shaft_bearing() >> 2, // #14 top_shaft_end_screw() >> 2]; // # ending() >> >> // Returns a 1-based part number. Does not start from zero. Identifies the >> // part being "introduced" in its introductory animation. >> function get_part_number(tick,index)= >> (tick<0)?index: >> (get_part_number(tick-animation_durations[index], >> index+1)); >> >> function total_animation_steps(index,step_count)= >> (index>=len(animation_durations))? >> step_count: >> total_animation_steps(index+1, >> step_count+animation_durations[index]); >> >> // Parameter 'partnum' is one-based. Returns the number of animation steps >> // that have preceded the beginning of part intro animation for specified >> part. >> function total_animation_steps_up_to(partnum,index,step_count)= >> (index>=(partnum-1))? >> step_count: >> total_animation_steps_up_to(partnum,index+1, >> step_count+animation_durations[index]); >> >> // The input parameter is 1-based and represents the part #. >> function part_animation_steps(partnum)= >> animation_durations[partnum-1]; >> >> // Value 't' is a value in [0,1), it increases linearly with time to span >> the >> // entirety of animation. >> t=0.34; // For example, we're a bit more than 1/3 of the way through the >> anim. >> >> // Parameter 'i' is the animation ticker, zero-based. >> i=floor(t*total_animation_steps(0,0)); // Start from 0. >> p=get_part_number(i,0); >> >> // Parameter 'w' is like 't', meaning it is in the range 0 <= w < 1, but >> it >> // is specific to the part intro animation. The part intro animation >> begins >> // at w=0 and is already over at w=1. >> pre_w=(t*total_animation_steps(0,0) >> -total_animation_steps_up_to(p,0,0))/part_animation_steps(p); >> >> // First it will print out a one-based index describing the part we're on. >> echo(p); >> >> // Next it will print out which fraction of this part's scene we've done. >> echo(pre_w); >> >> >> Sent with Proton Mail <https://proton.me/> secure email. >> >> On Wednesday, January 24th, 2024 at 7:21 PM, Adrian Mariano via Discuss < >> discuss@lists.openscad.org> wrote: >> >> I don't understand why it's any trickier to assemble the order of points >> with recursive programming. In either case, if you have a growing list (the >> result) you compute new values and add them to the end of the list. >> Normally I write a recursive function something like >> >> function func(result,info) = >> done ? result >> : func(concat(result, more_results_based_on_info), >> new_info)); >> >> The result grows in an obvious way and there is no "trickery" or >> "sorcery" involved. It's as straight forward as any other kind of coding, >> though it can get annoying if "info" contains many things, and I can't say >> anything good about the speed of execution. >> >> On Wed, Jan 24, 2024 at 3:30 PM neri-engineering via Discuss < >> discuss@lists.openscad.org> wrote: >> >>> With recursive functions it's a bit tricky to figure out the order of >>> points after they're all assembled. The problem I had was that the >>> recursive function which called concat() on two lists did it in an order >>> that resulted in the final list having its points in a reverse order from >>> what I expected. There is always "trickery" and a fair bit of "sorcery" >>> involved in getting recursive functions to do the right thing. Anyhow this >>> reverse order (from what I was assuming) is what caused the >>> clockwise/counterclockwise polygon traversal situation. >>> >>> Sent with Proton Mail <https://proton.me/> secure email. >>> >>> On Wednesday, January 24th, 2024 at 2:06 PM, David Phillip Oster via >>> Discuss <discuss@lists.openscad.org> wrote: >>> >>> Thank you for that neri-engineering, and nop head. That’s a fun example. >>> >>> >>> _______________________________________________ >>> 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 >> > >
N
neri-engineering
Sun, Jan 28, 2024 4:10 AM

Are you American? Your ways involve "taking swipes at people" without fully comprehending how something is used. If you can belittle someone else, even in the case where that person you are belittling specifically chose the methodology for his approach with a very good reason, then all the better for you. In the same way the American two year old temper tantrum baby is destroying the world around itself, internationally, by taking swipes at people everywhere, because it is going through its "terrible twos", but in this case it's more like two centuries of the Roman fucking Empire version 2.0, the original of which had Jesus of Nazareth put to death. These religious retards, who pretend to praise this man but are secretly worshiping the killers of this man, are especially to blame for this problem.

Yet another reason I'm moving away from OpenSCAD. It's because many of the participants on this list are mental fucking retards.

Now I could go into how similar the Roman Catholic Church is to the GPL license, both in its monopolistic, forceful, and contaminating strategy and by whom it was invented, but I will save my fingers and breath and focus instead on doing good work.

Sent with Proton Mail secure email.

On Saturday, January 27th, 2024 at 6:55 PM, Father Horton via Discuss discuss@lists.openscad.org wrote:

How crazy do you want to get? If you call parameters by name, you can have it initialize the value of i for you with a default.

On Sat, Jan 27, 2024 at 6:11 PM neri-engineering neri-engineering@protonmail.com wrote:

Indeed the 'let' construct is a life-saver to make code much clearer whereas it would have taken additional recursive helper functions to achieve the same level of clarity. This is an example that is working for me now.

echo(__invol_gear_path_builder(0,3,false));

// Parameter 'i' should be initialized to zero. Some examples:
// segs=3,q=true: [0,2,4,6,8,9,7,5,3,1]
// segs=3,q=false: [0, 4,6,8,9,7,5, 1]
function __invol_gear_path_builder(i,segs,q)=
((i==-1)?[]:
let(even=((i%2)==0),
flip=(even&&(i==((segs+1)*2))),
incr=(flip?1:(even?2:-2)),
omit=((!q)&&((i==2)||(i==3))))
concat(omit?[]:[i], __invol_gear_path_builder(i+incr,segs,q)));

Sent with Proton Mail secure email.

On Wednesday, January 24th, 2024 at 9:50 PM, Father Horton via Discuss discuss@lists.openscad.org wrote:

Actually you can declare local variables. It's just not obvious how.

From the manual:

function

get_square_triangle_perimeter

(

p1

,

p2

)

=

let

(

hypotenuse

=

sqrt

(

p1

p1

p2

p2

))

p1

p2

hypotenuse

;

On Wed, Jan 24, 2024 at 9:47 PM neri-engineering via Discuss discuss@lists.openscad.org wrote:

It's because in functions you can't declare local variables. So many times you end up writing helper functions which take the semi-compiled form of equations/data. This is one of the reasons why recursive functions in OpenSCAD are difficult to write. It certainly takes some getting used to. That's why I call it "sorcery". It's good mental gymnastics to keep you sharp, to prevent the ole Alzheimer's from setting in. We keep our bodies sharp by working out and we keep our minds sharp by writing recursive functions in OpenSCAD. Some examples I can give you which demonstrate my point. With a standard iterative process we would accomplish the following with simpler code.

// There are 21 steps currently.
animation_durations=[1, // # 1 slipper_back_plate()
1, // # 2 slipper_bearing()
2, // # 3 top_shaft()
1, // # 4 slipper_back_plate_pin()
2, // # 5 spur_gear() & left_slipper_pad()
1, // # 6 right_slipper_pad()
1, // # 7 slipper_front_plate()
1, // # 8 slipper_spring()
3, // # 9 slipper_nut()
1, // #10 slipper_to_drive_gear_spacer()
1, // #11 drive_gear()
1, // #12 top_shaft_left_spacer() &
// left_top_shaft_bearing()
1, // #13 top_shaft_right_spacer() &
// right_top_shaft_bearing()
2, // #14 top_shaft_end_screw()
2]; // # ending()

// Returns a 1-based part number. Does not start from zero. Identifies the
// part being "introduced" in its introductory animation.
function get_part_number(tick,index)=
(tick<0)?index:
(get_part_number(tick-animation_durations[index],
index+1));

function total_animation_steps(index,step_count)=
(index>=len(animation_durations))?
step_count:
total_animation_steps(index+1,
step_count+animation_durations[index]);

// Parameter 'partnum' is one-based. Returns the number of animation steps
// that have preceded the beginning of part intro animation for specified part.
function total_animation_steps_up_to(partnum,index,step_count)=
(index>=(partnum-1))?
step_count:
total_animation_steps_up_to(partnum,index+1,
step_count+animation_durations[index]);

// The input parameter is 1-based and represents the part #.
function part_animation_steps(partnum)=
animation_durations[partnum-1];

// Value 't' is a value in [0,1), it increases linearly with time to span the
// entirety of animation.
t=0.34; // For example, we're a bit more than 1/3 of the way through the anim.

// Parameter 'i' is the animation ticker, zero-based.
i=floor(t*total_animation_steps(0,0)); // Start from 0.
p=get_part_number(i,0);

// Parameter 'w' is like 't', meaning it is in the range 0 <= w < 1, but it
// is specific to the part intro animation. The part intro animation begins
// at w=0 and is already over at w=1.
pre_w=(t*total_animation_steps(0,0)
-total_animation_steps_up_to(p,0,0))/part_animation_steps(p);

// First it will print out a one-based index describing the part we're on.
echo(p);

// Next it will print out which fraction of this part's scene we've done.echo(pre_w);

Sent with Proton Mail secure email.

On Wednesday, January 24th, 2024 at 7:21 PM, Adrian Mariano via Discuss discuss@lists.openscad.org wrote:

I don't understand why it's any trickier to assemble the order of points with recursive programming. In either case, if you have a growing list (the result) you compute new values and add them to the end of the list. Normally I write a recursive function something like

function func(result,info) =
done ? result
: func(concat(result, more_results_based_on_info),
new_info));

The result grows in an obvious way and there is no "trickery" or "sorcery" involved. It's as straight forward as any other kind of coding, though it can get annoying if "info" contains many things, and I can't say anything good about the speed of execution.

On Wed, Jan 24, 2024 at 3:30 PM neri-engineering via Discuss discuss@lists.openscad.org wrote:

With recursive functions it's a bit tricky to figure out the order of points after they're all assembled. The problem I had was that the recursive function which called concat() on two lists did it in an order that resulted in the final list having its points in a reverse order from what I expected. There is always "trickery" and a fair bit of "sorcery" involved in getting recursive functions to do the right thing. Anyhow this reverse order (from what I was assuming) is what caused the clockwise/counterclockwise polygon traversal situation.

Sent with Proton Mail secure email.

On Wednesday, January 24th, 2024 at 2:06 PM, David Phillip Oster via Discuss discuss@lists.openscad.org wrote:

Thank you for that neri-engineering, and nop head. That’s a fun example.


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

Are you American? Your ways involve "taking swipes at people" without fully comprehending how something is used. If you can belittle someone else, even in the case where that person you are belittling specifically chose the methodology for his approach with a very good reason, then all the better for you. In the same way the American two year old temper tantrum baby is destroying the world around itself, internationally, by taking swipes at people everywhere, because it is going through its "terrible twos", but in this case it's more like two centuries of the Roman fucking Empire version 2.0, the original of which had Jesus of Nazareth put to death. These religious retards, who pretend to praise this man but are secretly worshiping the killers of this man, are especially to blame for this problem. Yet another reason I'm moving away from OpenSCAD. It's because many of the participants on this list are mental fucking retards. Now I could go into how similar the Roman Catholic Church is to the GPL license, both in its monopolistic, forceful, and contaminating strategy _and_ by whom it was invented, but I will save my fingers and breath and focus instead on doing good work. Sent with [Proton Mail](https://proton.me/) secure email. On Saturday, January 27th, 2024 at 6:55 PM, Father Horton via Discuss <discuss@lists.openscad.org> wrote: > How crazy do you want to get? If you call parameters by name, you can have it initialize the value of i for you with a default. > > On Sat, Jan 27, 2024 at 6:11 PM neri-engineering <neri-engineering@protonmail.com> wrote: > >> Indeed the 'let' construct is a life-saver to make code much clearer whereas it would have taken additional recursive helper functions to achieve the same level of clarity. This is an example that is working for me now. >> >> echo(__invol_gear_path_builder(0,3,false)); >> >> // Parameter 'i' should be initialized to zero. Some examples: >> // segs=3,q=true: [0,2,4,6,8,9,7,5,3,1] >> // segs=3,q=false: [0, 4,6,8,9,7,5, 1] >> function __invol_gear_path_builder(i,segs,q)= >> ((i==-1)?[]: >> let(even=((i%2)==0), >> flip=(even&&(i==((segs+1)*2))), >> incr=(flip?1:(even?2:-2)), >> omit=((!q)&&((i==2)||(i==3)))) >> concat(omit?[]:[i], __invol_gear_path_builder(i+incr,segs,q))); >> >> Sent with [Proton Mail](https://proton.me/) secure email. >> >> On Wednesday, January 24th, 2024 at 9:50 PM, Father Horton via Discuss <discuss@lists.openscad.org> wrote: >> >>> Actually you can declare local variables. It's just not obvious how. >>> >>> From the manual: >>> >>> function >>> >>> get_square_triangle_perimeter >>> >>> ( >>> >>> p1 >>> >>> , >>> >>> p2 >>> >>> ) >>> >>> = >>> >>> let >>> >>> ( >>> >>> hypotenuse >>> >>> = >>> >>> sqrt >>> >>> ( >>> >>> p1 >>> >>> * >>> >>> p1 >>> >>> + >>> >>> p2 >>> >>> * >>> >>> p2 >>> >>> )) >>> >>> p1 >>> >>> + >>> >>> p2 >>> >>> + >>> >>> hypotenuse >>> >>> ; >>> >>> On Wed, Jan 24, 2024 at 9:47 PM neri-engineering via Discuss <discuss@lists.openscad.org> wrote: >>> >>>> It's because in functions you can't declare local variables. So many times you end up writing helper functions which take the semi-compiled form of equations/data. This is one of the reasons why recursive functions in OpenSCAD are difficult to write. It certainly takes some getting used to. That's why I call it "sorcery". It's good mental gymnastics to keep you sharp, to prevent the ole Alzheimer's from setting in. We keep our bodies sharp by working out and we keep our minds sharp by writing recursive functions in OpenSCAD. Some examples I can give you which demonstrate my point. With a standard iterative process we would accomplish the following with simpler code. >>>> >>>> // There are 21 steps currently. >>>> animation_durations=[1, // # 1 slipper_back_plate() >>>> 1, // # 2 slipper_bearing() >>>> 2, // # 3 top_shaft() >>>> 1, // # 4 slipper_back_plate_pin() >>>> 2, // # 5 spur_gear() & left_slipper_pad() >>>> 1, // # 6 right_slipper_pad() >>>> 1, // # 7 slipper_front_plate() >>>> 1, // # 8 slipper_spring() >>>> 3, // # 9 slipper_nut() >>>> 1, // #10 slipper_to_drive_gear_spacer() >>>> 1, // #11 drive_gear() >>>> 1, // #12 top_shaft_left_spacer() & >>>> // left_top_shaft_bearing() >>>> 1, // #13 top_shaft_right_spacer() & >>>> // right_top_shaft_bearing() >>>> 2, // #14 top_shaft_end_screw() >>>> 2]; // # ending() >>>> >>>> // Returns a 1-based part number. Does not start from zero. Identifies the >>>> // part being "introduced" in its introductory animation. >>>> function get_part_number(tick,index)= >>>> (tick<0)?index: >>>> (get_part_number(tick-animation_durations[index], >>>> index+1)); >>>> >>>> function total_animation_steps(index,step_count)= >>>> (index>=len(animation_durations))? >>>> step_count: >>>> total_animation_steps(index+1, >>>> step_count+animation_durations[index]); >>>> >>>> // Parameter 'partnum' is one-based. Returns the number of animation steps >>>> // that have preceded the beginning of part intro animation for specified part. >>>> function total_animation_steps_up_to(partnum,index,step_count)= >>>> (index>=(partnum-1))? >>>> step_count: >>>> total_animation_steps_up_to(partnum,index+1, >>>> step_count+animation_durations[index]); >>>> >>>> // The input parameter is 1-based and represents the part #. >>>> function part_animation_steps(partnum)= >>>> animation_durations[partnum-1]; >>>> >>>> // Value 't' is a value in [0,1), it increases linearly with time to span the >>>> // entirety of animation. >>>> t=0.34; // For example, we're a bit more than 1/3 of the way through the anim. >>>> >>>> // Parameter 'i' is the animation ticker, zero-based. >>>> i=floor(t*total_animation_steps(0,0)); // Start from 0. >>>> p=get_part_number(i,0); >>>> >>>> // Parameter 'w' is like 't', meaning it is in the range 0 <= w < 1, but it >>>> // is specific to the part intro animation. The part intro animation begins >>>> // at w=0 and is already over at w=1. >>>> pre_w=(t*total_animation_steps(0,0) >>>> -total_animation_steps_up_to(p,0,0))/part_animation_steps(p); >>>> >>>> // First it will print out a one-based index describing the part we're on. >>>> echo(p); >>>> >>>> // Next it will print out which fraction of this part's scene we've done.echo(pre_w); >>>> >>>> Sent with [Proton Mail](https://proton.me/) secure email. >>>> >>>> On Wednesday, January 24th, 2024 at 7:21 PM, Adrian Mariano via Discuss <discuss@lists.openscad.org> wrote: >>>> >>>>> I don't understand why it's any trickier to assemble the order of points with recursive programming. In either case, if you have a growing list (the result) you compute new values and add them to the end of the list. Normally I write a recursive function something like >>>>> >>>>> function func(result,info) = >>>>> done ? result >>>>> : func(concat(result, more_results_based_on_info), >>>>> new_info)); >>>>> >>>>> The result grows in an obvious way and there is no "trickery" or "sorcery" involved. It's as straight forward as any other kind of coding, though it can get annoying if "info" contains many things, and I can't say anything good about the speed of execution. >>>>> >>>>> On Wed, Jan 24, 2024 at 3:30 PM neri-engineering via Discuss <discuss@lists.openscad.org> wrote: >>>>> >>>>>> With recursive functions it's a bit tricky to figure out the order of points after they're all assembled. The problem I had was that the recursive function which called concat() on two lists did it in an order that resulted in the final list having its points in a reverse order from what I expected. There is always "trickery" and a fair bit of "sorcery" involved in getting recursive functions to do the right thing. Anyhow this reverse order (from what I was assuming) is what caused the clockwise/counterclockwise polygon traversal situation. >>>>>> >>>>>> Sent with [Proton Mail](https://proton.me/) secure email. >>>>>> >>>>>> On Wednesday, January 24th, 2024 at 2:06 PM, David Phillip Oster via Discuss <discuss@lists.openscad.org> wrote: >>>>>> >>>>>>> Thank you for that neri-engineering, and nop head. That’s a fun example. >>>>>> >>>>>> _______________________________________________ >>>>>> 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
L
larry
Sun, Jan 28, 2024 6:11 AM

On Sun, 2024-01-28 at 04:10 +0000, neri-engineering via Discuss wrote:

Are you American?  Your ways involve "taking swipes at people"
without fully comprehending how something is used.  If you can
belittle someone else, even in the case where that person you are
belittling specifically chose the methodology for his approach with a
very good reason, then all the better for you.  In the same way the
American two year old temper tantrum baby is destroying the world
around itself, internationally, by taking swipes at people
everywhere, because it is going through its "terrible twos", but in
this case it's more like two centuries of the Roman fucking Empire
version 2.0, the original of which had Jesus of Nazareth put to
death.  These religious retards, who pretend to praise this man but
are secretly worshiping the killers of this man, are especially to
blame for this problem.

Yet another reason I'm moving away from OpenSCAD.  It's because many
of the participants on this list are mental fucking retards.

Now I could go into how similar the Roman Catholic Church is to the
GPL license, both in its monopolistic, forceful, and contaminating
strategy and by whom it was invented, but I will save my fingers
and breath and focus instead on doing good work.

All of that was uncalled-for. You were not being belittled in any
response. I am not an American, nor am I religious, but I find the
content and the attitude of your post to be offensive and small-minded.

Don't bother replying, as I won't see it. You are going directly into
my killfile.

 Sent with Proton Mail secure email.

 On Saturday, January 27th, 2024 at 6:55 PM, Father Horton via
Discuss discuss@lists.openscad.org wrote:
 

How crazy do you want to get? If you call parameters by name, you
can have it initialize the value of i for you with a default.

On Sat, Jan 27, 2024 at 6:11 PM neri-engineering
neri-engineering@protonmail.com wrote:

Indeed the 'let' construct is a life-saver to make code much
clearer whereas it would have taken additional recursive helper
functions to achieve the same level of clarity. This is an
example that is working for me now.

echo(__invol_gear_path_builder(0,3,false));

// Parameter 'i' should be initialized to zero. Some examples:
// segs=3,q=true: [0,2,4,6,8,9,7,5,3,1]
// segs=3,q=false: [0, 4,6,8,9,7,5, 1]
function __invol_gear_path_builder(i,segs,q)=
 ((i==-1)?[]:
 let(even=((i%2)==0),
 flip=(even&&(i==((segs+1)*2))),
 incr=(flip?1:(even?2:-2)),
 omit=((!q)&&((i==2)||(i==3))))
 concat(omit?[]:[i],
 __invol_gear_path_builder(i+incr,segs,q)));

 Sent with Proton Mail secure email.

 On Wednesday, January 24th, 2024 at 9:50 PM, Father Horton via
Discuss discuss@lists.openscad.org wrote:
 

Actually you can declare local variables. It's just not obvious
how.

From the manual:

function get_square_triangle_perimeter(p1, p2) =
  let (hypotenuse = sqrt(p1p1+p2p2))
    p1 + p2 + hypotenuse;

On Wed, Jan 24, 2024 at 9:47 PM neri-engineering via Discuss
discuss@lists.openscad.org wrote:

It's because in functions you can't declare local variables.
So many times you end up writing helper functions which take
the semi-compiled form of equations/data. This is one of the
reasons why recursive functions in OpenSCAD are difficult to
write. It certainly takes some getting used to. That's why I
call it "sorcery". It's good mental gymnastics to keep you
sharp, to prevent the ole Alzheimer's from setting in. We
keep our bodies sharp by working out and we keep our minds
sharp by writing recursive functions in OpenSCAD. Some
examples I can give you which demonstrate my point. With a
standard iterative process we would accomplish the following
with simpler code.

// There are 21 steps currently.
animation_durations=[1, // # 1 slipper_back_plate()
 1, // # 2 slipper_bearing()
 2, // # 3 top_shaft()
 1, // # 4 slipper_back_plate_pin()
 2, // # 5 spur_gear() & left_slipper_pad()
 1, // # 6 right_slipper_pad()
 1, // # 7 slipper_front_plate()
 1, // # 8 slipper_spring()
 3, // # 9 slipper_nut()
 1, // #10 slipper_to_drive_gear_spacer()
 1, // #11 drive_gear()
 1, // #12 top_shaft_left_spacer() &
 // left_top_shaft_bearing()
 1, // #13 top_shaft_right_spacer() &
 // right_top_shaft_bearing()
 2, // #14 top_shaft_end_screw()
 2]; // # ending()

// Returns a 1-based part number. Does not start from zero.
Identifies the
// part being "introduced" in its introductory animation.
function get_part_number(tick,index)=
 (tick<0)?index:
 (get_part_number(tick-animation_durations[index],
 index+1));

function total_animation_steps(index,step_count)=
 (index>=len(animation_durations))?
 step_count:
 total_animation_steps(index+1,
 step_count+animation_durations[index]);

// Parameter 'partnum' is one-based. Returns the number of
animation steps
// that have preceded the beginning of part intro animation
for specified part.
function
total_animation_steps_up_to(partnum,index,step_count)=
 (index>=(partnum-1))?
 step_count:
 total_animation_steps_up_to(partnum,index+1,
 step_count+animation_durations[index]);

// The input parameter is 1-based and represents the part #.
function part_animation_steps(partnum)=
 animation_durations[partnum-1];

// Value 't' is a value in [0,1), it increases linearly with
time to span the
// entirety of animation.
t=0.34; // For example, we're a bit more than 1/3 of the way
through the anim.

// Parameter 'i' is the animation ticker, zero-based.
i=floor(t*total_animation_steps(0,0)); // Start from 0.
p=get_part_number(i,0);

// Parameter 'w' is like 't', meaning it is in the range 0 <=
w < 1, but it
// is specific to the part intro animation. The part intro
animation begins
// at w=0 and is already over at w=1.
pre_w=(t*total_animation_steps(0,0)
 -
total_animation_steps_up_to(p,0,0))/part_animation_steps(p);

// First it will print out a one-based index describing the
part we're on.
echo(p);

// Next it will print out which fraction of this part's scene
we've done.
echo(pre_w);

 Sent with Proton Mail secure email.

 On Wednesday, January 24th, 2024 at 7:21 PM, Adrian Mariano
via Discuss discuss@lists.openscad.org wrote:
 

I don't understand why it's any trickier to assemble the
order of points with recursive programming. In either case,
if you have a growing list (the result) you compute new
values and add them to the end of the list. Normally I
write a recursive function something like

function func(result,info) =
 done ? result
 : func(concat(result, more_results_based_on_info),
 new_info));

The result grows in an obvious way and there is no
"trickery" or "sorcery" involved. It's as straight forward
as any other kind of coding, though it can get annoying if
"info" contains many things, and I can't say anything good
about the speed of execution.

On Wed, Jan 24, 2024 at 3:30 PM neri-engineering via
Discuss discuss@lists.openscad.org wrote:

With recursive functions it's a bit tricky to figure out
the order of points after they're all assembled. The
problem I had was that the recursive function which
called concat() on two lists did it in an order that
resulted in the final list having its points in a reverse
order from what I expected. There is always "trickery"
and a fair bit of "sorcery" involved in getting recursive
functions to do the right thing. Anyhow this reverse
order (from what I was assuming) is what caused the
clockwise/counterclockwise polygon traversal situation.

 Sent with Proton Mail secure email.

 On Wednesday, January 24th, 2024 at 2:06 PM, David
Phillip Oster via Discuss discuss@lists.openscad.org
wrote:
 

Thank you for that neri-engineering, and nop head.
That’s a fun example.


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

On Sun, 2024-01-28 at 04:10 +0000, neri-engineering via Discuss wrote: > Are you American?  Your ways involve "taking swipes at people" > without fully comprehending how something is used.  If you can > belittle someone else, even in the case where that person you are > belittling specifically chose the methodology for his approach with a > very good reason, then all the better for you.  In the same way the > American two year old temper tantrum baby is destroying the world > around itself, internationally, by taking swipes at people > everywhere, because it is going through its "terrible twos", but in > this case it's more like two centuries of the Roman fucking Empire > version 2.0, the original of which had Jesus of Nazareth put to > death.  These religious retards, who pretend to praise this man but > are secretly worshiping the killers of this man, are especially to > blame for this problem. > > Yet another reason I'm moving away from OpenSCAD.  It's because many > of the participants on this list are mental fucking retards. > > Now I could go into how similar the Roman Catholic Church is to the > GPL license, both in its monopolistic, forceful, and contaminating > strategy _and_ by whom it was invented, but I will save my fingers > and breath and focus instead on doing good work. > All of that was uncalled-for. You were not being belittled in any response. I am not an American, nor am I religious, but I find the content and the attitude of your post to be offensive and small-minded. Don't bother replying, as I won't see it. You are going directly into my killfile. >  Sent with Proton Mail secure email. > >  On Saturday, January 27th, 2024 at 6:55 PM, Father Horton via > Discuss <discuss@lists.openscad.org> wrote: >   > > How crazy do you want to get? If you call parameters by name, you > > can have it initialize the value of i for you with a default. > > > > On Sat, Jan 27, 2024 at 6:11 PM neri-engineering > > <neri-engineering@protonmail.com> wrote: > > > Indeed the 'let' construct is a life-saver to make code much > > > clearer whereas it would have taken additional recursive helper > > > functions to achieve the same level of clarity. This is an > > > example that is working for me now. > > > > > > echo(__invol_gear_path_builder(0,3,false)); > > > > > > // Parameter 'i' should be initialized to zero. Some examples: > > > // segs=3,q=true: [0,2,4,6,8,9,7,5,3,1] > > > // segs=3,q=false: [0, 4,6,8,9,7,5, 1] > > > function __invol_gear_path_builder(i,segs,q)= > > >  ((i==-1)?[]: > > >  let(even=((i%2)==0), > > >  flip=(even&&(i==((segs+1)*2))), > > >  incr=(flip?1:(even?2:-2)), > > >  omit=((!q)&&((i==2)||(i==3)))) > > >  concat(omit?[]:[i], > > >  __invol_gear_path_builder(i+incr,segs,q))); > > > > > >  Sent with Proton Mail secure email. > > > > > >  On Wednesday, January 24th, 2024 at 9:50 PM, Father Horton via > > > Discuss <discuss@lists.openscad.org> wrote: > > >   > > > > Actually you can declare local variables. It's just not obvious > > > > how. > > > > > > > > From the manual: > > > > > > > > function get_square_triangle_perimeter(p1, p2) = > > > >   let (hypotenuse = sqrt(p1*p1+p2*p2)) > > > >     p1 + p2 + hypotenuse; > > > > > > > > On Wed, Jan 24, 2024 at 9:47 PM neri-engineering via Discuss > > > > <discuss@lists.openscad.org> wrote: > > > > > It's because in functions you can't declare local variables. > > > > > So many times you end up writing helper functions which take > > > > > the semi-compiled form of equations/data. This is one of the > > > > > reasons why recursive functions in OpenSCAD are difficult to > > > > > write. It certainly takes some getting used to. That's why I > > > > > call it "sorcery". It's good mental gymnastics to keep you > > > > > sharp, to prevent the ole Alzheimer's from setting in. We > > > > > keep our bodies sharp by working out and we keep our minds > > > > > sharp by writing recursive functions in OpenSCAD. Some > > > > > examples I can give you which demonstrate my point. With a > > > > > standard iterative process we would accomplish the following > > > > > with simpler code. > > > > > > > > > > > > > > > // There are 21 steps currently. > > > > > animation_durations=[1, // # 1 slipper_back_plate() > > > > >  1, // # 2 slipper_bearing() > > > > >  2, // # 3 top_shaft() > > > > >  1, // # 4 slipper_back_plate_pin() > > > > >  2, // # 5 spur_gear() & left_slipper_pad() > > > > >  1, // # 6 right_slipper_pad() > > > > >  1, // # 7 slipper_front_plate() > > > > >  1, // # 8 slipper_spring() > > > > >  3, // # 9 slipper_nut() > > > > >  1, // #10 slipper_to_drive_gear_spacer() > > > > >  1, // #11 drive_gear() > > > > >  1, // #12 top_shaft_left_spacer() & > > > > >  // left_top_shaft_bearing() > > > > >  1, // #13 top_shaft_right_spacer() & > > > > >  // right_top_shaft_bearing() > > > > >  2, // #14 top_shaft_end_screw() > > > > >  2]; // # ending() > > > > > > > > > > // Returns a 1-based part number. Does not start from zero. > > > > > Identifies the > > > > > // part being "introduced" in its introductory animation. > > > > > function get_part_number(tick,index)= > > > > >  (tick<0)?index: > > > > >  (get_part_number(tick-animation_durations[index], > > > > >  index+1)); > > > > > > > > > > function total_animation_steps(index,step_count)= > > > > >  (index>=len(animation_durations))? > > > > >  step_count: > > > > >  total_animation_steps(index+1, > > > > >  step_count+animation_durations[index]); > > > > > > > > > > // Parameter 'partnum' is one-based. Returns the number of > > > > > animation steps > > > > > // that have preceded the beginning of part intro animation > > > > > for specified part. > > > > > function > > > > > total_animation_steps_up_to(partnum,index,step_count)= > > > > >  (index>=(partnum-1))? > > > > >  step_count: > > > > >  total_animation_steps_up_to(partnum,index+1, > > > > >  step_count+animation_durations[index]); > > > > > > > > > > // The input parameter is 1-based and represents the part #. > > > > > function part_animation_steps(partnum)= > > > > >  animation_durations[partnum-1]; > > > > > > > > > > // Value 't' is a value in [0,1), it increases linearly with > > > > > time to span the > > > > > // entirety of animation. > > > > > t=0.34; // For example, we're a bit more than 1/3 of the way > > > > > through the anim. > > > > > > > > > > // Parameter 'i' is the animation ticker, zero-based. > > > > > i=floor(t*total_animation_steps(0,0)); // Start from 0. > > > > > p=get_part_number(i,0); > > > > > > > > > > // Parameter 'w' is like 't', meaning it is in the range 0 <= > > > > > w < 1, but it > > > > > // is specific to the part intro animation. The part intro > > > > > animation begins > > > > > // at w=0 and is already over at w=1. > > > > > pre_w=(t*total_animation_steps(0,0) > > > > >  - > > > > > total_animation_steps_up_to(p,0,0))/part_animation_steps(p); > > > > > > > > > > // First it will print out a one-based index describing the > > > > > part we're on. > > > > > echo(p); > > > > > > > > > > // Next it will print out which fraction of this part's scene > > > > > we've done. > > > > > echo(pre_w); > > > > > > > > > > > > > > >  Sent with Proton Mail secure email. > > > > > > > > > >  On Wednesday, January 24th, 2024 at 7:21 PM, Adrian Mariano > > > > > via Discuss <discuss@lists.openscad.org> wrote: > > > > >   > > > > > > I don't understand why it's any trickier to assemble the > > > > > > order of points with recursive programming. In either case, > > > > > > if you have a growing list (the result) you compute new > > > > > > values and add them to the end of the list. Normally I > > > > > > write a recursive function something like > > > > > > > > > > > > function func(result,info) = > > > > > >  done ? result > > > > > >  : func(concat(result, more_results_based_on_info), > > > > > >  new_info)); > > > > > > > > > > > > The result grows in an obvious way and there is no > > > > > > "trickery" or "sorcery" involved. It's as straight forward > > > > > > as any other kind of coding, though it can get annoying if > > > > > > "info" contains many things, and I can't say anything good > > > > > > about the speed of execution. > > > > > > > > > > > > On Wed, Jan 24, 2024 at 3:30 PM neri-engineering via > > > > > > Discuss <discuss@lists.openscad.org> wrote: > > > > > > > With recursive functions it's a bit tricky to figure out > > > > > > > the order of points after they're all assembled. The > > > > > > > problem I had was that the recursive function which > > > > > > > called concat() on two lists did it in an order that > > > > > > > resulted in the final list having its points in a reverse > > > > > > > order from what I expected. There is always "trickery" > > > > > > > and a fair bit of "sorcery" involved in getting recursive > > > > > > > functions to do the right thing. Anyhow this reverse > > > > > > > order (from what I was assuming) is what caused the > > > > > > > clockwise/counterclockwise polygon traversal situation. > > > > > > > > > > > > > >  Sent with Proton Mail secure email. > > > > > > > > > > > > > >  On Wednesday, January 24th, 2024 at 2:06 PM, David > > > > > > > Phillip Oster via Discuss <discuss@lists.openscad.org> > > > > > > > wrote: > > > > > > >   > > > > > > > > Thank you for that neri-engineering, and nop head. > > > > > > > > That’s a fun example. > > > > > > > > > > > > > > _______________________________________________ > > > > > > > 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
J
jon
Sun, Jan 28, 2024 11:34 AM

I believe that you misunderstood what Father Horton was trying to say. 
The "crazy" was intended as "complex" or "challenging" or "intricate". 
Like "how complex do you want to get".  No one was attacking you.

On 1/27/2024 11:10 PM, neri-engineering via Discuss wrote:

Are you American?  Your ways involve "taking swipes at people" without
fully comprehending how something is used.  If you can belittle
someone else, even in the case where that person you are belittling
specifically chose the methodology for his approach with a very good
reason, then all the better for you. In the same way the American two
year old temper tantrum baby is destroying the world around itself,
internationally, by taking swipes at people everywhere, because it is
going through its "terrible twos", but in this case it's more like two
centuries of the Roman fucking Empire version 2.0, the original of
which had Jesus of Nazareth put to death.  These religious retards,
who pretend to praise this man but are secretly worshiping the killers
of this man, are especially to blame for this problem.

Yet another reason I'm moving away from OpenSCAD.  It's because many
of the participants on this list are mental fucking retards.

Now I could go into how similar the Roman Catholic Church is to the
GPL license, both in its monopolistic, forceful, and contaminating
strategy and by whom it was invented, but I will save my fingers and
breath and focus instead on doing good work.

Sent with Proton Mail https://proton.me/ secure email.

On Saturday, January 27th, 2024 at 6:55 PM, Father Horton via Discuss
discuss@lists.openscad.org wrote:

How crazy do you want to get? If you call parameters by name, you can
have it initialize the value of i for you with a default.

On Sat, Jan 27, 2024 at 6:11 PM neri-engineering
neri-engineering@protonmail.com wrote:

 Indeed the 'let' construct is a life-saver to make code much
 clearer whereas it would have taken additional recursive helper
 functions to achieve the same level of clarity. This is an
 example that is working for me now.

 echo(__invol_gear_path_builder(0,3,false));

 // Parameter 'i' should be initialized to zero. Some examples:
 // segs=3,q=true: [0,2,4,6,8,9,7,5,3,1]
 // segs=3,q=false: [0, 4,6,8,9,7,5, 1]
 function __invol_gear_path_builder(i,segs,q)=
 ((i==-1)?[]:
 let(even=((i%2)==0),
 flip=(even&&(i==((segs+1)*2))),
 incr=(flip?1:(even?2:-2)),
 omit=((!q)&&((i==2)||(i==3))))
 concat(omit?[]:[i],
 __invol_gear_path_builder(i+incr,segs,q)));

 Sent with Proton Mail <https://proton.me/> secure email.

 On Wednesday, January 24th, 2024 at 9:50 PM, Father Horton via
 Discuss <discuss@lists.openscad.org> wrote:
 Actually you can declare local variables. It's just not obvious how.

 From the manual:

 functionget_square_triangle_perimeter(p1,p2)=
 let(hypotenuse=sqrt(p1*p1+p2*p2))
 p1+p2+hypotenuse;

 On Wed, Jan 24, 2024 at 9:47 PM neri-engineering via Discuss
 <discuss@lists.openscad.org> wrote:

     It's because in functions you can't declare local variables.
     So many times you end up writing helper functions which take
     the semi-compiled form of equations/data. This is one of the
     reasons why recursive functions in OpenSCAD are difficult to
     write. It certainly takes some getting used to. That's why I
     call it "sorcery". It's good mental gymnastics to keep you
     sharp, to prevent the ole Alzheimer's from setting in. We
     keep our bodies sharp by working out and we keep our minds
     sharp by writing recursive functions in OpenSCAD. Some
     examples I can give you which demonstrate my point. With a
     standard iterative process we would accomplish the following
     with simpler code.


     // There are 21 steps currently.
     animation_durations=[1, // # 1 slipper_back_plate()
     1, // # 2 slipper_bearing()
     2, // # 3 top_shaft()
     1, // # 4 slipper_back_plate_pin()
     2, // # 5 spur_gear() & left_slipper_pad()
     1, // # 6 right_slipper_pad()
     1, // # 7 slipper_front_plate()
     1, // # 8 slipper_spring()
     3, // # 9 slipper_nut()
     1, // #10 slipper_to_drive_gear_spacer()
     1, // #11 drive_gear()
     1, // #12 top_shaft_left_spacer() &
     // left_top_shaft_bearing()
     1, // #13 top_shaft_right_spacer() &
     // right_top_shaft_bearing()
     2, // #14 top_shaft_end_screw()
     2]; // # ending()

     // Returns a 1-based part number. Does not start from zero.
     Identifies the
     // part being "introduced" in its introductory animation.
     function get_part_number(tick,index)=
     (tick<0)?index:
     (get_part_number(tick-animation_durations[index],
     index+1));

     function total_animation_steps(index,step_count)=
     (index>=len(animation_durations))?
     step_count:
     total_animation_steps(index+1,
     step_count+animation_durations[index]);

     // Parameter 'partnum' is one-based. Returns the number of
     animation steps
     // that have preceded the beginning of part intro animation
     for specified part.
     function total_animation_steps_up_to(partnum,index,step_count)=
     (index>=(partnum-1))?
     step_count:
     total_animation_steps_up_to(partnum,index+1,
     step_count+animation_durations[index]);

     // The input parameter is 1-based and represents the part #.
     function part_animation_steps(partnum)=
     animation_durations[partnum-1];

     // Value 't' is a value in [0,1), it increases linearly with
     time to span the
     // entirety of animation.
     t=0.34; // For example, we're a bit more than 1/3 of the way
     through the anim.

     // Parameter 'i' is the animation ticker, zero-based.
     i=floor(t*total_animation_steps(0,0)); // Start from 0.
     p=get_part_number(i,0);

     // Parameter 'w' is like 't', meaning it is in the range 0
     <= w < 1, but it
     // is specific to the part intro animation. The part intro
     animation begins
     // at w=0 and is already over at w=1.
     pre_w=(t*total_animation_steps(0,0)
     -total_animation_steps_up_to(p,0,0))/part_animation_steps(p);

     // First it will print out a one-based index describing the
     part we're on.
     echo(p);

     // Next it will print out which fraction of this part's
     scene we've done.
     echo(pre_w);


     Sent with Proton Mail <https://proton.me/> secure email.

     On Wednesday, January 24th, 2024 at 7:21 PM, Adrian Mariano
     via Discuss <discuss@lists.openscad.org> wrote:
     I don't understand why it's any trickier to assemble the
     order of points with recursive programming. In either case,
     if you have a growing list (the result) you compute new
     values and add them to the end of the list. Normally I
     write a recursive function something like

     function func(result,info) =
     done ? result
     : func(concat(result, more_results_based_on_info),
     new_info));

     The result grows in an obvious way and there is no
     "trickery" or "sorcery" involved. It's as straight forward
     as any other kind of coding, though it can get annoying if
     "info" contains many things, and I can't say anything good
     about the speed of execution.

     On Wed, Jan 24, 2024 at 3:30 PM neri-engineering via
     Discuss <discuss@lists.openscad.org> wrote:

         With recursive functions it's a bit tricky to figure
         out the order of points after they're all assembled.
         The problem I had was that the recursive function which
         called concat() on two lists did it in an order that
         resulted in the final list having its points in a
         reverse order from what I expected. There is always
         "trickery" and a fair bit of "sorcery" involved in
         getting recursive functions to do the right thing.
         Anyhow this reverse order (from what I was assuming) is
         what caused the clockwise/counterclockwise polygon
         traversal situation.

         Sent with Proton Mail <https://proton.me/> secure email.

         On Wednesday, January 24th, 2024 at 2:06 PM, David
         Phillip Oster via Discuss <discuss@lists.openscad.org>
         wrote:
         Thank you for that neri-engineering, and nop head.
         That’s a fun example.
         _______________________________________________
         OpenSCAD mailing list
         To unsubscribe send an email to
         discuss-leave@lists.openscad.org
     _______________________________________________
     OpenSCAD mailing list
     To unsubscribe send an email to discuss-leave@lists.openscad.org

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

--
This email has been checked for viruses by AVG antivirus software.
www.avg.com

I believe that you misunderstood what Father Horton was trying to say.  The "crazy" was intended as "complex" or "challenging" or "intricate".  Like "how complex do you want to get".  No one was attacking you. On 1/27/2024 11:10 PM, neri-engineering via Discuss wrote: > Are you American?  Your ways involve "taking swipes at people" without > fully comprehending how something is used.  If you can belittle > someone else, even in the case where that person you are belittling > specifically chose the methodology for his approach with a very good > reason, then all the better for you. In the same way the American two > year old temper tantrum baby is destroying the world around itself, > internationally, by taking swipes at people everywhere, because it is > going through its "terrible twos", but in this case it's more like two > centuries of the Roman fucking Empire version 2.0, the original of > which had Jesus of Nazareth put to death.  These religious retards, > who pretend to praise this man but are secretly worshiping the killers > of this man, are especially to blame for this problem. > > Yet another reason I'm moving away from OpenSCAD.  It's because many > of the participants on this list are mental fucking retards. > > Now I could go into how similar the Roman Catholic Church is to the > GPL license, both in its monopolistic, forceful, and contaminating > strategy _and_ by whom it was invented, but I will save my fingers and > breath and focus instead on doing good work. > > Sent with Proton Mail <https://proton.me/> secure email. > > On Saturday, January 27th, 2024 at 6:55 PM, Father Horton via Discuss > <discuss@lists.openscad.org> wrote: >> How crazy do you want to get? If you call parameters by name, you can >> have it initialize the value of i for you with a default. >> >> On Sat, Jan 27, 2024 at 6:11 PM neri-engineering >> <neri-engineering@protonmail.com> wrote: >> >> Indeed the 'let' construct is a life-saver to make code much >> clearer whereas it would have taken additional recursive helper >> functions to achieve the same level of clarity. This is an >> example that is working for me now. >> >> echo(__invol_gear_path_builder(0,3,false)); >> >> // Parameter 'i' should be initialized to zero. Some examples: >> // segs=3,q=true: [0,2,4,6,8,9,7,5,3,1] >> // segs=3,q=false: [0, 4,6,8,9,7,5, 1] >> function __invol_gear_path_builder(i,segs,q)= >> ((i==-1)?[]: >> let(even=((i%2)==0), >> flip=(even&&(i==((segs+1)*2))), >> incr=(flip?1:(even?2:-2)), >> omit=((!q)&&((i==2)||(i==3)))) >> concat(omit?[]:[i], >> __invol_gear_path_builder(i+incr,segs,q))); >> >> Sent with Proton Mail <https://proton.me/> secure email. >> >> On Wednesday, January 24th, 2024 at 9:50 PM, Father Horton via >> Discuss <discuss@lists.openscad.org> wrote: >>> Actually you can declare local variables. It's just not obvious how. >>> >>> From the manual: >>> >>> functionget_square_triangle_perimeter(p1,p2)= >>> let(hypotenuse=sqrt(p1*p1+p2*p2)) >>> p1+p2+hypotenuse; >>> >>> On Wed, Jan 24, 2024 at 9:47 PM neri-engineering via Discuss >>> <discuss@lists.openscad.org> wrote: >>> >>> It's because in functions you can't declare local variables. >>> So many times you end up writing helper functions which take >>> the semi-compiled form of equations/data. This is one of the >>> reasons why recursive functions in OpenSCAD are difficult to >>> write. It certainly takes some getting used to. That's why I >>> call it "sorcery". It's good mental gymnastics to keep you >>> sharp, to prevent the ole Alzheimer's from setting in. We >>> keep our bodies sharp by working out and we keep our minds >>> sharp by writing recursive functions in OpenSCAD. Some >>> examples I can give you which demonstrate my point. With a >>> standard iterative process we would accomplish the following >>> with simpler code. >>> >>> >>> // There are 21 steps currently. >>> animation_durations=[1, // # 1 slipper_back_plate() >>> 1, // # 2 slipper_bearing() >>> 2, // # 3 top_shaft() >>> 1, // # 4 slipper_back_plate_pin() >>> 2, // # 5 spur_gear() & left_slipper_pad() >>> 1, // # 6 right_slipper_pad() >>> 1, // # 7 slipper_front_plate() >>> 1, // # 8 slipper_spring() >>> 3, // # 9 slipper_nut() >>> 1, // #10 slipper_to_drive_gear_spacer() >>> 1, // #11 drive_gear() >>> 1, // #12 top_shaft_left_spacer() & >>> // left_top_shaft_bearing() >>> 1, // #13 top_shaft_right_spacer() & >>> // right_top_shaft_bearing() >>> 2, // #14 top_shaft_end_screw() >>> 2]; // # ending() >>> >>> // Returns a 1-based part number. Does not start from zero. >>> Identifies the >>> // part being "introduced" in its introductory animation. >>> function get_part_number(tick,index)= >>> (tick<0)?index: >>> (get_part_number(tick-animation_durations[index], >>> index+1)); >>> >>> function total_animation_steps(index,step_count)= >>> (index>=len(animation_durations))? >>> step_count: >>> total_animation_steps(index+1, >>> step_count+animation_durations[index]); >>> >>> // Parameter 'partnum' is one-based. Returns the number of >>> animation steps >>> // that have preceded the beginning of part intro animation >>> for specified part. >>> function total_animation_steps_up_to(partnum,index,step_count)= >>> (index>=(partnum-1))? >>> step_count: >>> total_animation_steps_up_to(partnum,index+1, >>> step_count+animation_durations[index]); >>> >>> // The input parameter is 1-based and represents the part #. >>> function part_animation_steps(partnum)= >>> animation_durations[partnum-1]; >>> >>> // Value 't' is a value in [0,1), it increases linearly with >>> time to span the >>> // entirety of animation. >>> t=0.34; // For example, we're a bit more than 1/3 of the way >>> through the anim. >>> >>> // Parameter 'i' is the animation ticker, zero-based. >>> i=floor(t*total_animation_steps(0,0)); // Start from 0. >>> p=get_part_number(i,0); >>> >>> // Parameter 'w' is like 't', meaning it is in the range 0 >>> <= w < 1, but it >>> // is specific to the part intro animation. The part intro >>> animation begins >>> // at w=0 and is already over at w=1. >>> pre_w=(t*total_animation_steps(0,0) >>> -total_animation_steps_up_to(p,0,0))/part_animation_steps(p); >>> >>> // First it will print out a one-based index describing the >>> part we're on. >>> echo(p); >>> >>> // Next it will print out which fraction of this part's >>> scene we've done. >>> echo(pre_w); >>> >>> >>> Sent with Proton Mail <https://proton.me/> secure email. >>> >>> On Wednesday, January 24th, 2024 at 7:21 PM, Adrian Mariano >>> via Discuss <discuss@lists.openscad.org> wrote: >>>> I don't understand why it's any trickier to assemble the >>>> order of points with recursive programming. In either case, >>>> if you have a growing list (the result) you compute new >>>> values and add them to the end of the list. Normally I >>>> write a recursive function something like >>>> >>>> function func(result,info) = >>>> done ? result >>>> : func(concat(result, more_results_based_on_info), >>>> new_info)); >>>> >>>> The result grows in an obvious way and there is no >>>> "trickery" or "sorcery" involved. It's as straight forward >>>> as any other kind of coding, though it can get annoying if >>>> "info" contains many things, and I can't say anything good >>>> about the speed of execution. >>>> >>>> On Wed, Jan 24, 2024 at 3:30 PM neri-engineering via >>>> Discuss <discuss@lists.openscad.org> wrote: >>>> >>>> With recursive functions it's a bit tricky to figure >>>> out the order of points after they're all assembled. >>>> The problem I had was that the recursive function which >>>> called concat() on two lists did it in an order that >>>> resulted in the final list having its points in a >>>> reverse order from what I expected. There is always >>>> "trickery" and a fair bit of "sorcery" involved in >>>> getting recursive functions to do the right thing. >>>> Anyhow this reverse order (from what I was assuming) is >>>> what caused the clockwise/counterclockwise polygon >>>> traversal situation. >>>> >>>> Sent with Proton Mail <https://proton.me/> secure email. >>>> >>>> On Wednesday, January 24th, 2024 at 2:06 PM, David >>>> Phillip Oster via Discuss <discuss@lists.openscad.org> >>>> wrote: >>>>> Thank you for that neri-engineering, and nop head. >>>>> That’s a fun example. >>>> >>>> _______________________________________________ >>>> OpenSCAD mailing list >>>> To unsubscribe send an email to >>>> discuss-leave@lists.openscad.org >>>> >>> >>> _______________________________________________ >>> OpenSCAD mailing list >>> To unsubscribe send an email to discuss-leave@lists.openscad.org >>> >> > > > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email todiscuss-leave@lists.openscad.org -- This email has been checked for viruses by AVG antivirus software. www.avg.com
FH
Father Horton
Sun, Jan 28, 2024 12:05 PM

This is correct.

On Sun, Jan 28, 2024 at 5:34 AM jon jon@jonbondy.com wrote:

I believe that you misunderstood what Father Horton was trying to say.
The "crazy" was intended as "complex" or "challenging" or "intricate".
Like "how complex do you want to get".  No one was attacking you.
On 1/27/2024 11:10 PM, neri-engineering via Discuss wrote:

Are you American?  Your ways involve "taking swipes at people" without
fully comprehending how something is used.  If you can belittle someone
else, even in the case where that person you are belittling specifically
chose the methodology for his approach with a very good reason, then all
the better for you.  In the same way the American two year old temper
tantrum baby is destroying the world around itself, internationally, by
taking swipes at people everywhere, because it is going through its
"terrible twos", but in this case it's more like two centuries of the Roman
fucking Empire version 2.0, the original of which had Jesus of Nazareth put
to death.  These religious retards, who pretend to praise this man but are
secretly worshiping the killers of this man, are especially to blame for
this problem.

Yet another reason I'm moving away from OpenSCAD.  It's because many of
the participants on this list are mental fucking retards.

Now I could go into how similar the Roman Catholic Church is to the GPL
license, both in its monopolistic, forceful, and contaminating strategy
and by whom it was invented, but I will save my fingers and breath and
focus instead on doing good work.

Sent with Proton Mail https://proton.me/ secure email.

On Saturday, January 27th, 2024 at 6:55 PM, Father Horton via Discuss
discuss@lists.openscad.org discuss@lists.openscad.org wrote:

How crazy do you want to get? If you call parameters by name, you can have
it initialize the value of i for you with a default.

On Sat, Jan 27, 2024 at 6:11 PM neri-engineering <
neri-engineering@protonmail.com> wrote:

Indeed the 'let' construct is a life-saver to make code much clearer
whereas it would have taken additional recursive helper functions to
achieve the same level of clarity. This is an example that is working for
me now.

echo(__invol_gear_path_builder(0,3,false));

// Parameter 'i' should be initialized to zero. Some examples:
// segs=3,q=true: [0,2,4,6,8,9,7,5,3,1]
// segs=3,q=false: [0, 4,6,8,9,7,5, 1]
function __invol_gear_path_builder(i,segs,q)=
((i==-1)?[]:
let(even=((i%2)==0),
flip=(even&&(i==((segs+1)*2))),
incr=(flip?1:(even?2:-2)),
omit=((!q)&&((i==2)||(i==3))))
concat(omit?[]:[i],
__invol_gear_path_builder(i+incr,segs,q)));

Sent with Proton Mail https://proton.me/ secure email.

On Wednesday, January 24th, 2024 at 9:50 PM, Father Horton via Discuss <
discuss@lists.openscad.org> wrote:

Actually you can declare local variables. It's just not obvious how.

From the manual:

function get_square_triangle_perimeter(p1, p2) =  let (hypotenuse = sqrt(p1p1+p2p2))    p1 + p2 + hypotenuse;

On Wed, Jan 24, 2024 at 9:47 PM neri-engineering via Discuss <
discuss@lists.openscad.org> wrote:

It's because in functions you can't declare local variables. So many
times you end up writing helper functions which take the semi-compiled form
of equations/data. This is one of the reasons why recursive functions in
OpenSCAD are difficult to write. It certainly takes some getting used to.
That's why I call it "sorcery". It's good mental gymnastics to keep you
sharp, to prevent the ole Alzheimer's from setting in. We keep our bodies
sharp by working out and we keep our minds sharp by writing recursive
functions in OpenSCAD. Some examples I can give you which demonstrate my
point. With a standard iterative process we would accomplish the following
with simpler code.

// There are 21 steps currently.
animation_durations=[1, // # 1 slipper_back_plate()
1, // # 2 slipper_bearing()
2, // # 3 top_shaft()
1, // # 4 slipper_back_plate_pin()
2, // # 5 spur_gear() & left_slipper_pad()
1, // # 6 right_slipper_pad()
1, // # 7 slipper_front_plate()
1, // # 8 slipper_spring()
3, // # 9 slipper_nut()
1, // #10 slipper_to_drive_gear_spacer()
1, // #11 drive_gear()
1, // #12 top_shaft_left_spacer() &
// left_top_shaft_bearing()
1, // #13 top_shaft_right_spacer() &
// right_top_shaft_bearing()
2, // #14 top_shaft_end_screw()
2]; // # ending()

// Returns a 1-based part number. Does not start from zero. Identifies
the
// part being "introduced" in its introductory animation.
function get_part_number(tick,index)=
(tick<0)?index:
(get_part_number(tick-animation_durations[index],
index+1));

function total_animation_steps(index,step_count)=
(index>=len(animation_durations))?
step_count:
total_animation_steps(index+1,
step_count+animation_durations[index]);

// Parameter 'partnum' is one-based. Returns the number of animation
steps
// that have preceded the beginning of part intro animation for
specified part.
function total_animation_steps_up_to(partnum,index,step_count)=
(index>=(partnum-1))?
step_count:
total_animation_steps_up_to(partnum,index+1,
step_count+animation_durations[index]);

// The input parameter is 1-based and represents the part #.
function part_animation_steps(partnum)=
animation_durations[partnum-1];

// Value 't' is a value in [0,1), it increases linearly with time to
span the
// entirety of animation.
t=0.34; // For example, we're a bit more than 1/3 of the way through the
anim.

// Parameter 'i' is the animation ticker, zero-based.
i=floor(t*total_animation_steps(0,0)); // Start from 0.
p=get_part_number(i,0);

// Parameter 'w' is like 't', meaning it is in the range 0 <= w < 1, but
it
// is specific to the part intro animation. The part intro animation
begins
// at w=0 and is already over at w=1.
pre_w=(t*total_animation_steps(0,0)
-total_animation_steps_up_to(p,0,0))/part_animation_steps(p);

// First it will print out a one-based index describing the part we're
on.
echo(p);

// Next it will print out which fraction of this part's scene we've done.
echo(pre_w);

Sent with Proton Mail https://proton.me/ secure email.

On Wednesday, January 24th, 2024 at 7:21 PM, Adrian Mariano via Discuss <
discuss@lists.openscad.org> wrote:

I don't understand why it's any trickier to assemble the order of points
with recursive programming. In either case, if you have a growing list (the
result) you compute new values and add them to the end of the list.
Normally I write a recursive function something like

function func(result,info) =
done ? result
: func(concat(result, more_results_based_on_info),
new_info));

The result grows in an obvious way and there is no "trickery" or
"sorcery" involved. It's as straight forward as any other kind of coding,
though it can get annoying if "info" contains many things, and I can't say
anything good about the speed of execution.

On Wed, Jan 24, 2024 at 3:30 PM neri-engineering via Discuss <
discuss@lists.openscad.org> wrote:

With recursive functions it's a bit tricky to figure out the order of
points after they're all assembled. The problem I had was that the
recursive function which called concat() on two lists did it in an order
that resulted in the final list having its points in a reverse order from
what I expected. There is always "trickery" and a fair bit of "sorcery"
involved in getting recursive functions to do the right thing. Anyhow this
reverse order (from what I was assuming) is what caused the
clockwise/counterclockwise polygon traversal situation.

Sent with Proton Mail https://proton.me/ secure email.

On Wednesday, January 24th, 2024 at 2:06 PM, David Phillip Oster via
Discuss discuss@lists.openscad.org wrote:

Thank you for that neri-engineering, and nop head. That’s a fun example.


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 is correct. On Sun, Jan 28, 2024 at 5:34 AM jon <jon@jonbondy.com> wrote: > I believe that you misunderstood what Father Horton was trying to say. > The "crazy" was intended as "complex" or "challenging" or "intricate". > Like "how complex do you want to get". No one was attacking you. > On 1/27/2024 11:10 PM, neri-engineering via Discuss wrote: > > Are you American? Your ways involve "taking swipes at people" without > fully comprehending how something is used. If you can belittle someone > else, even in the case where that person you are belittling specifically > chose the methodology for his approach with a very good reason, then all > the better for you. In the same way the American two year old temper > tantrum baby is destroying the world around itself, internationally, by > taking swipes at people everywhere, because it is going through its > "terrible twos", but in this case it's more like two centuries of the Roman > fucking Empire version 2.0, the original of which had Jesus of Nazareth put > to death. These religious retards, who pretend to praise this man but are > secretly worshiping the killers of this man, are especially to blame for > this problem. > > Yet another reason I'm moving away from OpenSCAD. It's because many of > the participants on this list are mental fucking retards. > > Now I could go into how similar the Roman Catholic Church is to the GPL > license, both in its monopolistic, forceful, and contaminating strategy > _and_ by whom it was invented, but I will save my fingers and breath and > focus instead on doing good work. > > Sent with Proton Mail <https://proton.me/> secure email. > > On Saturday, January 27th, 2024 at 6:55 PM, Father Horton via Discuss > <discuss@lists.openscad.org> <discuss@lists.openscad.org> wrote: > > How crazy do you want to get? If you call parameters by name, you can have > it initialize the value of i for you with a default. > > On Sat, Jan 27, 2024 at 6:11 PM neri-engineering < > neri-engineering@protonmail.com> wrote: > >> Indeed the 'let' construct is a life-saver to make code much clearer >> whereas it would have taken additional recursive helper functions to >> achieve the same level of clarity. This is an example that is working for >> me now. >> >> echo(__invol_gear_path_builder(0,3,false)); >> >> // Parameter 'i' should be initialized to zero. Some examples: >> // segs=3,q=true: [0,2,4,6,8,9,7,5,3,1] >> // segs=3,q=false: [0, 4,6,8,9,7,5, 1] >> function __invol_gear_path_builder(i,segs,q)= >> ((i==-1)?[]: >> let(even=((i%2)==0), >> flip=(even&&(i==((segs+1)*2))), >> incr=(flip?1:(even?2:-2)), >> omit=((!q)&&((i==2)||(i==3)))) >> concat(omit?[]:[i], >> __invol_gear_path_builder(i+incr,segs,q))); >> >> Sent with Proton Mail <https://proton.me/> secure email. >> >> On Wednesday, January 24th, 2024 at 9:50 PM, Father Horton via Discuss < >> discuss@lists.openscad.org> wrote: >> >> Actually you can declare local variables. It's just not obvious how. >> >> From the manual: >> >> function get_square_triangle_perimeter(p1, p2) = let (hypotenuse = sqrt(p1*p1+p2*p2)) p1 + p2 + hypotenuse; >> >> >> On Wed, Jan 24, 2024 at 9:47 PM neri-engineering via Discuss < >> discuss@lists.openscad.org> wrote: >> >>> It's because in functions you can't declare local variables. So many >>> times you end up writing helper functions which take the semi-compiled form >>> of equations/data. This is one of the reasons why recursive functions in >>> OpenSCAD are difficult to write. It certainly takes some getting used to. >>> That's why I call it "sorcery". It's good mental gymnastics to keep you >>> sharp, to prevent the ole Alzheimer's from setting in. We keep our bodies >>> sharp by working out and we keep our minds sharp by writing recursive >>> functions in OpenSCAD. Some examples I can give you which demonstrate my >>> point. With a standard iterative process we would accomplish the following >>> with simpler code. >>> >>> >>> // There are 21 steps currently. >>> animation_durations=[1, // # 1 slipper_back_plate() >>> 1, // # 2 slipper_bearing() >>> 2, // # 3 top_shaft() >>> 1, // # 4 slipper_back_plate_pin() >>> 2, // # 5 spur_gear() & left_slipper_pad() >>> 1, // # 6 right_slipper_pad() >>> 1, // # 7 slipper_front_plate() >>> 1, // # 8 slipper_spring() >>> 3, // # 9 slipper_nut() >>> 1, // #10 slipper_to_drive_gear_spacer() >>> 1, // #11 drive_gear() >>> 1, // #12 top_shaft_left_spacer() & >>> // left_top_shaft_bearing() >>> 1, // #13 top_shaft_right_spacer() & >>> // right_top_shaft_bearing() >>> 2, // #14 top_shaft_end_screw() >>> 2]; // # ending() >>> >>> // Returns a 1-based part number. Does not start from zero. Identifies >>> the >>> // part being "introduced" in its introductory animation. >>> function get_part_number(tick,index)= >>> (tick<0)?index: >>> (get_part_number(tick-animation_durations[index], >>> index+1)); >>> >>> function total_animation_steps(index,step_count)= >>> (index>=len(animation_durations))? >>> step_count: >>> total_animation_steps(index+1, >>> step_count+animation_durations[index]); >>> >>> // Parameter 'partnum' is one-based. Returns the number of animation >>> steps >>> // that have preceded the beginning of part intro animation for >>> specified part. >>> function total_animation_steps_up_to(partnum,index,step_count)= >>> (index>=(partnum-1))? >>> step_count: >>> total_animation_steps_up_to(partnum,index+1, >>> step_count+animation_durations[index]); >>> >>> // The input parameter is 1-based and represents the part #. >>> function part_animation_steps(partnum)= >>> animation_durations[partnum-1]; >>> >>> // Value 't' is a value in [0,1), it increases linearly with time to >>> span the >>> // entirety of animation. >>> t=0.34; // For example, we're a bit more than 1/3 of the way through the >>> anim. >>> >>> // Parameter 'i' is the animation ticker, zero-based. >>> i=floor(t*total_animation_steps(0,0)); // Start from 0. >>> p=get_part_number(i,0); >>> >>> // Parameter 'w' is like 't', meaning it is in the range 0 <= w < 1, but >>> it >>> // is specific to the part intro animation. The part intro animation >>> begins >>> // at w=0 and is already over at w=1. >>> pre_w=(t*total_animation_steps(0,0) >>> -total_animation_steps_up_to(p,0,0))/part_animation_steps(p); >>> >>> // First it will print out a one-based index describing the part we're >>> on. >>> echo(p); >>> >>> // Next it will print out which fraction of this part's scene we've done. >>> echo(pre_w); >>> >>> >>> Sent with Proton Mail <https://proton.me/> secure email. >>> >>> On Wednesday, January 24th, 2024 at 7:21 PM, Adrian Mariano via Discuss < >>> discuss@lists.openscad.org> wrote: >>> >>> I don't understand why it's any trickier to assemble the order of points >>> with recursive programming. In either case, if you have a growing list (the >>> result) you compute new values and add them to the end of the list. >>> Normally I write a recursive function something like >>> >>> function func(result,info) = >>> done ? result >>> : func(concat(result, more_results_based_on_info), >>> new_info)); >>> >>> The result grows in an obvious way and there is no "trickery" or >>> "sorcery" involved. It's as straight forward as any other kind of coding, >>> though it can get annoying if "info" contains many things, and I can't say >>> anything good about the speed of execution. >>> >>> On Wed, Jan 24, 2024 at 3:30 PM neri-engineering via Discuss < >>> discuss@lists.openscad.org> wrote: >>> >>>> With recursive functions it's a bit tricky to figure out the order of >>>> points after they're all assembled. The problem I had was that the >>>> recursive function which called concat() on two lists did it in an order >>>> that resulted in the final list having its points in a reverse order from >>>> what I expected. There is always "trickery" and a fair bit of "sorcery" >>>> involved in getting recursive functions to do the right thing. Anyhow this >>>> reverse order (from what I was assuming) is what caused the >>>> clockwise/counterclockwise polygon traversal situation. >>>> >>>> Sent with Proton Mail <https://proton.me/> secure email. >>>> >>>> On Wednesday, January 24th, 2024 at 2:06 PM, David Phillip Oster via >>>> Discuss <discuss@lists.openscad.org> wrote: >>>> >>>> Thank you for that neri-engineering, and nop head. That’s a fun example. >>>> >>>> >>>> _______________________________________________ >>>> 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 > > > > <http://www.avg.com/email-signature?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=emailclient> > Virus-free.www.avg.com > <http://www.avg.com/email-signature?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=emailclient> > <#m_6491922885982119548_DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2> >
FH
Father Horton
Sun, Jan 28, 2024 12:14 PM

I do apologize for the unintentional apparent slight, and I thank Jon for
explaining what I meant.

I do apologize for the unintentional apparent slight, and I thank Jon for explaining what I meant.