discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

Simple polygon triangulation

R
Ronaldo
Mon, Apr 4, 2016 12:34 AM

Nice tip, Tolsten! (Except that "each" is not available for all yet :) )

My sum_list was a bit more general than yours:

function sum_list0(p, from=0, to) = 
   let(til = (to==undef) ? len(p)-1 : to )
   from==til ? 
      p[til] : 
      sum_list0( p, from+1, til );

So I tried to adhere to your tip with:

function sum_list1(p, from=0, to, sum=0) = 
   let(til = (to==undef) ? len(p)-1 : to )
   from>til? 
      sum : 
      sum_list1( p, from+1, til, sum + p[from] );

No success. No tail recursion was done. So I changed it to:

function sum_list2(p, from=0, to, sum=0) = 
   from>( (to==undef) ? len(p)-1 : to ) ? 
      sum : 
      sum_list2( p, from+1, ( (to==undef) ? len(p)-1 : to ), sum+p[from]

);

And this doesn't work at all: it returns 1 if to is given and 0 otherwise !
Why???

I finally got the correct result with:

function sum_list3( p, from=0, to ) = 
    __sum_list(p, from, (to==undef) ? len(p)-1 : to, 0 );

function __sum_list( p, from, to, sum ) = 
   (from>to) ? 
      sum : 
      __sum_list( p, from+1, to, sum+p[from] );

Very tricky!

--
View this message in context: http://forum.openscad.org/Simple-polygon-triangulation-tp16755p16942.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

Nice tip, Tolsten! (Except that "each" is not available for all yet :) ) My sum_list was a bit more general than yours: function sum_list0(p, from=0, to) = let(til = (to==undef) ? len(p)-1 : to ) from==til ? p[til] : sum_list0( p, from+1, til ); So I tried to adhere to your tip with: function sum_list1(p, from=0, to, sum=0) = let(til = (to==undef) ? len(p)-1 : to ) from>til? sum : sum_list1( p, from+1, til, sum + p[from] ); No success. No tail recursion was done. So I changed it to: function sum_list2(p, from=0, to, sum=0) = from>( (to==undef) ? len(p)-1 : to ) ? sum : sum_list2( p, from+1, ( (to==undef) ? len(p)-1 : to ), sum+p[from] ); And this doesn't work at all: it returns 1 if to is given and 0 otherwise ! Why??? I finally got the correct result with: function sum_list3( p, from=0, to ) = __sum_list(p, from, (to==undef) ? len(p)-1 : to, 0 ); function __sum_list( p, from, to, sum ) = (from>to) ? sum : __sum_list( p, from+1, to, sum+p[from] ); Very tricky! -- View this message in context: http://forum.openscad.org/Simple-polygon-triangulation-tp16755p16942.html Sent from the OpenSCAD mailing list archive at Nabble.com.
TP
Torsten Paul
Mon, Apr 4, 2016 12:45 AM

On 04/04/2016 02:34 AM, Ronaldo wrote:

 function sum_list0(p, from=0, to) = 
    let(til = (to==undef) ? len(p)-1 : to )
    from==til ? 
       p[til] : 
       sum_list0( p, from+1, til );

Hmm, right, the tail recursion handling is very basic and
does not consider let(). I think that should be possible
and would be a useful extension.

ciao,
Torsten.

On 04/04/2016 02:34 AM, Ronaldo wrote: > function sum_list0(p, from=0, to) = > let(til = (to==undef) ? len(p)-1 : to ) > from==til ? > p[til] : > sum_list0( p, from+1, til ); > Hmm, right, the tail recursion handling is very basic and does not consider let(). I think that should be possible and would be a useful extension. ciao, Torsten.
R
Ronaldo
Mon, Apr 4, 2016 1:49 AM

The bad news first: my previous sum_list worked with any uniform list of
numbers, vectors or even matrices. The tail recursion version no! You have
to know the list element type to initialize the sum. :(

The good news: with the tail recursion version of sum_list for vectors, the
least square fitting became a lot faster! With 10000 points, it takes 0.28
sec : 4.5 times less than the previous version.

Thank you again, Tolsten!

--
View this message in context: http://forum.openscad.org/Simple-polygon-triangulation-tp16755p16944.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

The bad news first: my previous sum_list worked with any uniform list of numbers, vectors or even matrices. The tail recursion version no! You have to know the list element type to initialize the sum. :( The good news: with the tail recursion version of sum_list for vectors, the least square fitting became a lot faster! With 10000 points, it takes 0.28 sec : 4.5 times less than the previous version. Thank you again, Tolsten! -- View this message in context: http://forum.openscad.org/Simple-polygon-triangulation-tp16755p16944.html Sent from the OpenSCAD mailing list archive at Nabble.com.
R
Ronaldo
Mon, Apr 4, 2016 1:52 AM

Sorry, Torsten. I think I need new glasses...

Do you know why sum_list2 doesn't work at all?

--
View this message in context: http://forum.openscad.org/Simple-polygon-triangulation-tp16755p16945.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

Sorry, Torsten. I think I need new glasses... Do you know why sum_list2 doesn't work at all? -- View this message in context: http://forum.openscad.org/Simple-polygon-triangulation-tp16755p16945.html Sent from the OpenSCAD mailing list archive at Nabble.com.
TP
Torsten Paul
Mon, Apr 4, 2016 2:12 AM

On 04/04/2016 03:52 AM, Ronaldo wrote:

Do you know why sum_list2 doesn't work at all?

Not work how? Those examples looks fine to me:

function sum_list2(p, from=0, to, sum=0) =
from > ( (to==undef) ? len(p)-1 : to ) ?
sum :
sum_list2( p, from+1, ( (to==undef) ? len(p)-1 : to ), sum+p[from]);

echo(sum_list2([1,2,3,4,5,6,7,8,9,10]));
ECHO: 55

echo(sum_list2([1,2,3,4,5,6,7,8,9,10], 2));
ECHO: 52

echo(sum_list2([1,2,3,4,5,6,7,8,9,10], 2, 6));
ECHO: 25

ciao,
Torsten.

On 04/04/2016 03:52 AM, Ronaldo wrote: > Do you know why sum_list2 doesn't work at all? > Not work how? Those examples looks fine to me: function sum_list2(p, from=0, to, sum=0) = from > ( (to==undef) ? len(p)-1 : to ) ? sum : sum_list2( p, from+1, ( (to==undef) ? len(p)-1 : to ), sum+p[from]); echo(sum_list2([1,2,3,4,5,6,7,8,9,10])); ECHO: 55 echo(sum_list2([1,2,3,4,5,6,7,8,9,10], 2)); ECHO: 52 echo(sum_list2([1,2,3,4,5,6,7,8,9,10], 2, 6)); ECHO: 25 ciao, Torsten.
DM
doug moen
Mon, Apr 4, 2016 3:06 AM

@torsten: There are two use cases for echo(). One is debugging, which is
the 99% use case. The other is stuff like BOM, or runsun's in-console
documentation, which is the 1% use case. I think these two use cases are
sufficiently different that they need different interfaces.

For debugging, we should keep the existing echo() interface. It takes a
list of values, and prints each value as unambiguous source code. It's
simple and easy to use for the common case of printing out some values in
the program.

For debugging, echo() needs to work in every evaluation context, which is
why we are talking about making it work in functions and list
comprehensions. It needs to print a string value as a string literal, and
there are some bugs in this that need to be fixed: within a string literal,
print \ as \, print " as ", and don't interpret HTML.

For the other 1% use case, the requirement is for 100% control over what
gets printed, and maybe some support for fancy formatting options. Runsun's
in-console documentation needs HTML support, while I assume that BOM needs
HTML turned off.

For the 1% use case, let's introduce another command called print(). It
takes a list of arguments, and outputs them as strings using the same
conversion as the str() function. No commas are printed between arguments,
and the "ECHO: " prefix is not printed. An optional keyword argument,
html=true, enables HTML. No other keyword arguments are accepted, for now.

To do fancy formatting in print(), we'll rely on some auxiliary functions
that convert values into strings in different ways, rather than hard-wiring
formatting features into print() itself. It's better and more flexible to
keep print() orthogonal to formatting. This design is inspired by Python; I
think this aspect of Python is well designed. So here are two auxiliary
formatting functions, repr() and fmt():
repr(val)
convert val into a string, which is the source code for reproducing
the value. Like repr() in Python.
repr(arg1,arg2,...)
convert the argument list into a string, in exactly the same way that
echo() converts its arguments for printing (but there is no ECHO: prefix)
fmt(printf_format_string, [val1,val2,...])
format a list of values into a string using a printf-like format
string. Similar to the % operator in Python. The %r format converts the
value like repr(), while the %s format converts the argument like str().

repr() is useful for duplicating the behaviour of echo() within print(). Eg,
echo(a,b,c) <=> print("ECHO: ",repr(a,b,c))

The repr() function would need to be implemented in C++, since it has a
variable # of positional and keyword arguments, but fmt() could be
implemented directly in OpenSCAD. Additional formatting functions may be
invented and coded in OpenSCAD. Since print() is a 1% use case, it's
reasonable to keep print() simple and to leave the fancy formatting to
library functions, rather than code everything in C++. Printf-style
formatting in particular is something that can be endlessly elaborated, so
I'd rather keep that in a library to facilitate development.

print() needs to be available as a module (called in statement context).
For BOM and in-console documentation, it doesn't need to be callable from
expressions or list comprehensions. It might not be needed in those
contexts.

Now let's consider which of these might be deprecated in the future.

OpenSCAD is a declarative language. In a declarative language, order of
evaluation doesn't matter. We have discussed using 3 techniques: parallel
evaluation, lazy evaluation, and cacheing, to speed up evaluation in a
future version of the evaluator. These techniques change the order of
evaluation, change the number of times a given expression or statement is
evaluated, and make evaluation order hard or impossible to predict.

Since echo() is used for debugging, it needs to expose the order of
evaluation, whatever that happens to be.

The print() command is used for BOM, which requires determinism and
predictability in what gets printed. So maybe the use of print() disables
optimizations, which is inappropriate for echo(). Or, more likely, we might
not be able to guarantee print() determinism in a future version of the
evaluator. So print() might eventually be deprecated, or restricted to only
being used for debugging. By this time, we should have better ways to do
BOM, eg as described in the OpenSCAD2 proposal.

@torsten: There are two use cases for echo(). One is debugging, which is the 99% use case. The other is stuff like BOM, or runsun's in-console documentation, which is the 1% use case. I think these two use cases are sufficiently different that they need different interfaces. For debugging, we should keep the existing echo() interface. It takes a list of values, and prints each value as unambiguous source code. It's simple and easy to use for the common case of printing out some values in the program. For debugging, echo() needs to work in every evaluation context, which is why we are talking about making it work in functions and list comprehensions. It needs to print a string value as a string literal, and there are some bugs in this that need to be fixed: within a string literal, print \ as \\, print " as \", and don't interpret HTML. For the other 1% use case, the requirement is for 100% control over what gets printed, and maybe some support for fancy formatting options. Runsun's in-console documentation needs HTML support, while I assume that BOM needs HTML turned off. For the 1% use case, let's introduce another command called print(). It takes a list of arguments, and outputs them as strings using the same conversion as the str() function. No commas are printed between arguments, and the "ECHO: " prefix is not printed. An optional keyword argument, html=true, enables HTML. No other keyword arguments are accepted, for now. To do fancy formatting in print(), we'll rely on some auxiliary functions that convert values into strings in different ways, rather than hard-wiring formatting features into print() itself. It's better and more flexible to keep print() orthogonal to formatting. This design is inspired by Python; I think this aspect of Python is well designed. So here are two auxiliary formatting functions, repr() and fmt(): repr(val) convert val into a string, which is the source code for reproducing the value. Like repr() in Python. repr(arg1,arg2,...) convert the argument list into a string, in exactly the same way that echo() converts its arguments for printing (but there is no ECHO: prefix) fmt(printf_format_string, [val1,val2,...]) format a list of values into a string using a printf-like format string. Similar to the % operator in Python. The %r format converts the value like repr(), while the %s format converts the argument like str(). repr() is useful for duplicating the behaviour of echo() within print(). Eg, echo(a,b,c) <=> print("ECHO: ",repr(a,b,c)) The repr() function would need to be implemented in C++, since it has a variable # of positional and keyword arguments, but fmt() could be implemented directly in OpenSCAD. Additional formatting functions may be invented and coded in OpenSCAD. Since print() is a 1% use case, it's reasonable to keep print() simple and to leave the fancy formatting to library functions, rather than code everything in C++. Printf-style formatting in particular is something that can be endlessly elaborated, so I'd rather keep that in a library to facilitate development. print() needs to be available as a module (called in statement context). For BOM and in-console documentation, it doesn't need to be callable from expressions or list comprehensions. It might not be needed in those contexts. Now let's consider which of these might be deprecated in the future. OpenSCAD is a declarative language. In a declarative language, order of evaluation doesn't matter. We have discussed using 3 techniques: parallel evaluation, lazy evaluation, and cacheing, to speed up evaluation in a future version of the evaluator. These techniques change the order of evaluation, change the number of times a given expression or statement is evaluated, and make evaluation order hard or impossible to predict. Since echo() is used for debugging, it needs to expose the order of evaluation, whatever that happens to be. The print() command is used for BOM, which requires determinism and predictability in what gets printed. So maybe the use of print() disables optimizations, which is inappropriate for echo(). Or, more likely, we might not be able to guarantee print() determinism in a future version of the evaluator. So print() might eventually be deprecated, or restricted to only being used for debugging. By this time, we should have better ways to do BOM, eg as described in the OpenSCAD2 proposal.
P
Parkinbot
Mon, Apr 4, 2016 11:03 AM

@doug
good points. Additionally it might be a good idea to direct the output of a
print(), or why not call it output(), to a new window e.g. called "output"
using C++ libraries' built-in support for this.
If html/xml output will be addressed one day, this separation would avoid a
lot of confusion by design and relieve people from writing their own parsers
to post process OpenSCAD output.

--
View this message in context: http://forum.openscad.org/Simple-polygon-triangulation-tp16755p16950.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

@doug good points. Additionally it might be a good idea to direct the output of a print(), or why not call it output(), to a new window e.g. called "output" using C++ libraries' built-in support for this. If html/xml output will be addressed one day, this separation would avoid a lot of confusion by design and relieve people from writing their own parsers to post process OpenSCAD output. -- View this message in context: http://forum.openscad.org/Simple-polygon-triangulation-tp16755p16950.html Sent from the OpenSCAD mailing list archive at Nabble.com.
R
runsun
Mon, Apr 4, 2016 1:59 PM

Parkinbot wrote

@doug
good points. Additionally it might be a good idea to direct the output of
a print(), or why not call it output(), to a new window e.g. called
"output" using C++ libraries' built-in support for this.
If html/xml output will be addressed one day, this separation would avoid
a lot of confusion by design and relieve people from writing their own
parsers to post process OpenSCAD output.

Separated console and output is what the SynWrite editor has.

Furthermore, a file-based directive can be implanted to direct the output of
current file to a file:

//# SAVE_OUTPUT = <file_path>

Or console:

//# SAVE_CONSOLE_OUTPUT = <file_path>


$  Runsun Pan, PhD $ libs: doctest , faces ( git ), offline doc ( git ), runscad.py( 1 , 2 , git ), synwrite( 1 , 2 );  $ tips: hash( 1 , 2 ), matrix( 1 , 2 ),sweep( 1 , 2 ), var( 1 , 2 ), lerp , animation ( gif , prodVid ), precision( 1 , 2 ), xl-control , type , rounded polygon , chfont

--
View this message in context: http://forum.openscad.org/Simple-polygon-triangulation-tp16755p16951.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

Parkinbot wrote > @doug > good points. Additionally it might be a good idea to direct the output of > a print(), or why not call it output(), to a new window e.g. called > "output" using C++ libraries' built-in support for this. > If html/xml output will be addressed one day, this separation would avoid > a lot of confusion by design and relieve people from writing their own > parsers to post process OpenSCAD output. Separated console and output is what the SynWrite editor has. Furthermore, a file-based directive can be implanted to direct the output of current file to a file: //# SAVE_OUTPUT = <file_path> Or console: //# SAVE_CONSOLE_OUTPUT = <file_path> ----- $ Runsun Pan, PhD $ libs: doctest , faces ( git ), offline doc ( git ), runscad.py( 1 , 2 , git ), synwrite( 1 , 2 ); $ tips: hash( 1 , 2 ), matrix( 1 , 2 ),sweep( 1 , 2 ), var( 1 , 2 ), lerp , animation ( gif , prodVid ), precision( 1 , 2 ), xl-control , type , rounded polygon , chfont -- View this message in context: http://forum.openscad.org/Simple-polygon-triangulation-tp16755p16951.html Sent from the OpenSCAD mailing list archive at Nabble.com.
R
runsun
Mon, Apr 4, 2016 2:16 PM

Ronaldo wrote

 function sum_list0(p, from=0, to) = 
    let(til = (to==undef) ? len(p)-1 : to )
    from==til ? 
       p[til] : 
       sum_list0( p, from+1, til );

This one doesn't work AT ALL, 'cos it didn't actually sum up things:

a=[3,4,5,6];
echo( sum_list0(a)) ==> 6

Ronaldo wrote

 function sum_list1(p, from=0, to, sum=0) = 
    let(til = (to==undef) ? len(p)-1 : to )
    from>til? 
       sum : 
       sum_list1( p, from+1, til, sum + p[from] );

No success. No tail recursion was done.

This one looks like a tail recursion to me, and seems to be working:

a=[3,4,5,6];
echo( sum_list1(a)); ==> 18

Ronaldo wrote

 function sum_list2(p, from=0, to, sum=0) = 
    from>( (to==undef) ? len(p)-1 : to ) ? 
       sum : 
       sum_list2( p, from+1, ( (to==undef) ? len(p)-1 : to ),

sum+p[from] );

And this doesn't work at all: it returns 1 if to is given and 0 otherwise
! Why???

This one works in my computer:

a=[3,4,5,6];
echo( sum_list2(a)); ==> 18
echo( sum_list2(a, to=2)); ==> 12


$  Runsun Pan, PhD $ libs: doctest , faces ( git ), offline doc ( git ), runscad.py( 1 , 2 , git ), synwrite( 1 , 2 );  $ tips: hash( 1 , 2 ), matrix( 1 , 2 ),sweep( 1 , 2 ), var( 1 , 2 ), lerp , animation ( gif , prodVid ), precision( 1 , 2 ), xl-control , type , rounded polygon , chfont

--
View this message in context: http://forum.openscad.org/Simple-polygon-triangulation-tp16755p16952.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

Ronaldo wrote > function sum_list0(p, from=0, to) = > let(til = (to==undef) ? len(p)-1 : to ) > from==til ? > p[til] : > sum_list0( p, from+1, til ); This one doesn't work AT ALL, 'cos it didn't actually sum up things: a=[3,4,5,6]; echo( sum_list0(a)) ==> 6 Ronaldo wrote > function sum_list1(p, from=0, to, sum=0) = > let(til = (to==undef) ? len(p)-1 : to ) > from>til? > sum : > sum_list1( p, from+1, til, sum + p[from] ); > No success. No tail recursion was done. This one looks like a tail recursion to me, and seems to be working: a=[3,4,5,6]; echo( sum_list1(a)); ==> 18 Ronaldo wrote > function sum_list2(p, from=0, to, sum=0) = > from>( (to==undef) ? len(p)-1 : to ) ? > sum : > sum_list2( p, from+1, ( (to==undef) ? len(p)-1 : to ), > sum+p[from] ); > > And this doesn't work at all: it returns 1 if to is given and 0 otherwise > ! Why??? This one works in my computer: a=[3,4,5,6]; echo( sum_list2(a)); ==> 18 echo( sum_list2(a, to=2)); ==> 12 ----- $ Runsun Pan, PhD $ libs: doctest , faces ( git ), offline doc ( git ), runscad.py( 1 , 2 , git ), synwrite( 1 , 2 ); $ tips: hash( 1 , 2 ), matrix( 1 , 2 ),sweep( 1 , 2 ), var( 1 , 2 ), lerp , animation ( gif , prodVid ), precision( 1 , 2 ), xl-control , type , rounded polygon , chfont -- View this message in context: http://forum.openscad.org/Simple-polygon-triangulation-tp16755p16952.html Sent from the OpenSCAD mailing list archive at Nabble.com.
TP
Torsten Paul
Mon, Apr 4, 2016 2:56 PM

On 04/04/2016 03:59 PM, runsun wrote:

Furthermore, a file-based directive can be implanted to direct
the output of current file to a file:

I don't think that belongs into the script. That's inherently
not portable to other systems. While probably not very relevant
anymore, just think of a user working on Windows with user
partition as D: sending the files over to someone who has
the D: drive as DVD writer. We certainly don't want to log
directly to DVD ;).

There could be a GUI option and/or a "save console content"
maybe.

ciao,
Torsten.

On 04/04/2016 03:59 PM, runsun wrote: > Furthermore, a file-based directive can be implanted to direct > the output of current file to a file: > I don't think that belongs into the script. That's inherently not portable to other systems. While probably not very relevant anymore, just think of a user working on Windows with user partition as D: sending the files over to someone who has the D: drive as DVD writer. We certainly don't want to log directly to DVD ;). There could be a GUI option and/or a "save console content" maybe. ciao, Torsten.