discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

simple BOSL question

J
jon
Thu, Dec 31, 2020 6:53 PM

I clearly do not understand what is going on here.  This works


include <BOSL2/std.scad>
include <BOSL2/rounding.scad>
include <BOSL2/skin.scad>

myScale = [1,  2,  4];
myZ =     [0, 11, 22];
myProfs = [for (x=[0, 1, 2])
    xscale(x/15, circle(d = 15, $fn = 80))];

skin(myProfs, z=myZ, slices=10, method="reindex");


but if I add the "right(1)", below, in myProfs, this fails with a syntax
error:


include <BOSL2/std.scad>
include <BOSL2/rounding.scad>
include <BOSL2/skin.scad>

myScale = [1,  2,  4];
myZ =     [0, 11, 22];
myProfs = [for (x=[0, 1, 2])
    right(1) xscale(x/15, circle(d = 15, $fn = 80))];

skin(myProfs, z=myZ, slices=10, method="reindex");


If I try wrapping the right() and the xscale() together, as

module RightAndXScale(x)
    right(x) xscale(x/15, circle(d = 15, $fn = 80));

then

myProfs = [for (x=[0, 1, 2])
    RightAndXScale(x);

fails with a syntax error


and if I try

function RightAndXScale(x)
    right(x) xscale(x/15, circle(d = 15, $fn = 80));

then the function fails with a syntax error.

I clearly do not understand what is going on here.  This works --- include <BOSL2/std.scad> include <BOSL2/rounding.scad> include <BOSL2/skin.scad> myScale = [1,  2,  4]; myZ =     [0, 11, 22]; myProfs = [for (x=[0, 1, 2])     xscale(x/15, circle(d = 15, $fn = 80))]; skin(myProfs, z=myZ, slices=10, method="reindex"); --- but if I add the "right(1)", below, in myProfs, this fails with a syntax error: --- include <BOSL2/std.scad> include <BOSL2/rounding.scad> include <BOSL2/skin.scad> myScale = [1,  2,  4]; myZ =     [0, 11, 22]; myProfs = [for (x=[0, 1, 2])     right(1) xscale(x/15, circle(d = 15, $fn = 80))]; skin(myProfs, z=myZ, slices=10, method="reindex"); --- If I try wrapping the right() and the xscale() together, as module RightAndXScale(x)     right(x) xscale(x/15, circle(d = 15, $fn = 80)); then myProfs = [for (x=[0, 1, 2])     RightAndXScale(x); fails with a syntax error --- and if I try function RightAndXScale(x)     right(x) xscale(x/15, circle(d = 15, $fn = 80)); then the function fails with a syntax error.
A
adrianv
Thu, Dec 31, 2020 7:14 PM

The problem is your mixing up the module versions and function versions of
the transformation commands.

If you do right(1) without other arguments then it can be a module, in which
case you need some geometry next or it can be a function, which returns the
transformation matrix that shifts right by 1, in which case you need to do
something with it, like perhaps pass it to multmatrix.  (But see below.)

In your "working" example (which actually doesn't work in the latest BOSL2)
you're doing

xscale(value, circle(...));

In this code, circle is the functional form of circle supplied by BOSL2.
It's giving you a point list which is being passed as the second arg to
xscale.  To make this work robustly you should change it to

xscale(value,p=circle(...));

A new argument was added to xscale (centerpoint) so the second arg changed,
and for most of the other transformation functions the position of the point
list argument is not fixed.  So if you want to add right(1) to this you can
do it like this:

right(1, p=xscale(value, p=circle(...)));

Now that's kind of messy.  I recommend only using the "p=" form when you are
applying just one transformation.  If you want several, it's cleaner to use
apply().  If you use a transformation without a point list it gives you the
transformation matrix, and apply applies it to a point list, like multmatrix
for point lists.  So that would look like:

apply(right(1)*xscale(x/15), circle(....));

Does that help?  You can now stack transformations using multiplication
similar to how you do it in plain OpenSCAD.

jon_bondy wrote

I clearly do not understand what is going on here.  This works


include <BOSL2/std.scad>
include <BOSL2/rounding.scad>
include <BOSL2/skin.scad>

myScale = [1,  2,  4];
myZ =     [0, 11, 22];
myProfs = [for (x=[0, 1, 2])
    xscale(x/15, circle(d = 15, $fn = 80))];

skin(myProfs, z=myZ, slices=10, method="reindex");


but if I add the "right(1)", below, in myProfs, this fails with a syntax
error:


include <BOSL2/std.scad>
include <BOSL2/rounding.scad>
include <BOSL2/skin.scad>

myScale = [1,  2,  4];
myZ =     [0, 11, 22];
myProfs = [for (x=[0, 1, 2])
    right(1) xscale(x/15, circle(d = 15, $fn = 80))];

skin(myProfs, z=myZ, slices=10, method="reindex");


If I try wrapping the right() and the xscale() together, as

module RightAndXScale(x)
    right(x) xscale(x/15, circle(d = 15, $fn = 80));

then

myProfs = [for (x=[0, 1, 2])
    RightAndXScale(x);

fails with a syntax error


and if I try

function RightAndXScale(x)
    right(x) xscale(x/15, circle(d = 15, $fn = 80));

then the function fails with a syntax error.


OpenSCAD mailing list

Discuss@.openscad

The problem is your mixing up the module versions and function versions of the transformation commands. If you do right(1) without other arguments then it can be a module, in which case you need some geometry next or it can be a function, which returns the transformation matrix that shifts right by 1, in which case you need to do something with it, like perhaps pass it to multmatrix. (But see below.) In your "working" example (which actually doesn't work in the latest BOSL2) you're doing xscale(value, circle(...)); In this code, circle is the functional form of circle supplied by BOSL2. It's giving you a point list which is being passed as the second arg to xscale. To make this work robustly you should change it to xscale(value,p=circle(...)); A new argument was added to xscale (centerpoint) so the second arg changed, and for most of the other transformation functions the position of the point list argument is not fixed. So if you want to add right(1) to this you can do it like this: right(1, p=xscale(value, p=circle(...))); Now that's kind of messy. I recommend only using the "p=" form when you are applying just one transformation. If you want several, it's cleaner to use apply(). If you use a transformation without a point list it gives you the transformation matrix, and apply applies it to a point list, like multmatrix for point lists. So that would look like: apply(right(1)*xscale(x/15), circle(....)); Does that help? You can now stack transformations using multiplication similar to how you do it in plain OpenSCAD. jon_bondy wrote > I clearly do not understand what is going on here.  This works > > --- > > include &lt;BOSL2/std.scad&gt; > include &lt;BOSL2/rounding.scad&gt; > include &lt;BOSL2/skin.scad&gt; > > myScale = [1,  2,  4]; > myZ =     [0, 11, 22]; > myProfs = [for (x=[0, 1, 2]) >     xscale(x/15, circle(d = 15, $fn = 80))]; > > skin(myProfs, z=myZ, slices=10, method="reindex"); > > --- > > but if I add the "right(1)", below, in myProfs, this fails with a syntax > error: > > --- > > include &lt;BOSL2/std.scad&gt; > include &lt;BOSL2/rounding.scad&gt; > include &lt;BOSL2/skin.scad&gt; > > myScale = [1,  2,  4]; > myZ =     [0, 11, 22]; > myProfs = [for (x=[0, 1, 2]) >     right(1) xscale(x/15, circle(d = 15, $fn = 80))]; > > skin(myProfs, z=myZ, slices=10, method="reindex"); > > --- > > If I try wrapping the right() and the xscale() together, as > > module RightAndXScale(x) >     right(x) xscale(x/15, circle(d = 15, $fn = 80)); > > then > > myProfs = [for (x=[0, 1, 2]) >     RightAndXScale(x); > > fails with a syntax error > > --- > > and if I try > > function RightAndXScale(x) >     right(x) xscale(x/15, circle(d = 15, $fn = 80)); > > then the function fails with a syntax error. > > > _______________________________________________ > OpenSCAD mailing list > Discuss@.openscad > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org -- Sent from: http://forum.openscad.org/
J
jon
Thu, Dec 31, 2020 7:17 PM

Excellent explanation!  Thanks so much!

Jon

On 12/31/2020 2:14 PM, adrianv wrote:

The problem is your mixing up the module versions and function versions of
the transformation commands.

If you do right(1) without other arguments then it can be a module, in which
case you need some geometry next or it can be a function, which returns the
transformation matrix that shifts right by 1, in which case you need to do
something with it, like perhaps pass it to multmatrix.  (But see below.)

In your "working" example (which actually doesn't work in the latest BOSL2)
you're doing

xscale(value, circle(...));

In this code, circle is the functional form of circle supplied by BOSL2.
It's giving you a point list which is being passed as the second arg to
xscale.  To make this work robustly you should change it to

xscale(value,p=circle(...));

A new argument was added to xscale (centerpoint) so the second arg changed,
and for most of the other transformation functions the position of the point
list argument is not fixed.  So if you want to add right(1) to this you can
do it like this:

right(1, p=xscale(value, p=circle(...)));

Now that's kind of messy.  I recommend only using the "p=" form when you are
applying just one transformation.  If you want several, it's cleaner to use
apply().  If you use a transformation without a point list it gives you the
transformation matrix, and apply applies it to a point list, like multmatrix
for point lists.  So that would look like:

apply(right(1)*xscale(x/15), circle(....));

Does that help?  You can now stack transformations using multiplication
similar to how you do it in plain OpenSCAD.

jon_bondy wrote

I clearly do not understand what is going on here.  This works


include <BOSL2/std.scad>
include <BOSL2/rounding.scad>
include <BOSL2/skin.scad>

myScale = [1,  2,  4];
myZ =     [0, 11, 22];
myProfs = [for (x=[0, 1, 2])
    xscale(x/15, circle(d = 15, $fn = 80))];

skin(myProfs, z=myZ, slices=10, method="reindex");


but if I add the "right(1)", below, in myProfs, this fails with a syntax
error:


include <BOSL2/std.scad>
include <BOSL2/rounding.scad>
include <BOSL2/skin.scad>

myScale = [1,  2,  4];
myZ =     [0, 11, 22];
myProfs = [for (x=[0, 1, 2])
    right(1) xscale(x/15, circle(d = 15, $fn = 80))];

skin(myProfs, z=myZ, slices=10, method="reindex");


If I try wrapping the right() and the xscale() together, as

module RightAndXScale(x)
    right(x) xscale(x/15, circle(d = 15, $fn = 80));

then

myProfs = [for (x=[0, 1, 2])
    RightAndXScale(x);

fails with a syntax error


and if I try

function RightAndXScale(x)
    right(x) xscale(x/15, circle(d = 15, $fn = 80));

then the function fails with a syntax error.


OpenSCAD mailing list
Discuss@.openscad
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

Excellent explanation!  Thanks so much! Jon On 12/31/2020 2:14 PM, adrianv wrote: > The problem is your mixing up the module versions and function versions of > the transformation commands. > > If you do right(1) without other arguments then it can be a module, in which > case you need some geometry next or it can be a function, which returns the > transformation matrix that shifts right by 1, in which case you need to do > something with it, like perhaps pass it to multmatrix. (But see below.) > > In your "working" example (which actually doesn't work in the latest BOSL2) > you're doing > > xscale(value, circle(...)); > > In this code, circle is the functional form of circle supplied by BOSL2. > It's giving you a point list which is being passed as the second arg to > xscale. To make this work robustly you should change it to > > xscale(value,p=circle(...)); > > A new argument was added to xscale (centerpoint) so the second arg changed, > and for most of the other transformation functions the position of the point > list argument is not fixed. So if you want to add right(1) to this you can > do it like this: > > right(1, p=xscale(value, p=circle(...))); > > Now that's kind of messy. I recommend only using the "p=" form when you are > applying just one transformation. If you want several, it's cleaner to use > apply(). If you use a transformation without a point list it gives you the > transformation matrix, and apply applies it to a point list, like multmatrix > for point lists. So that would look like: > > apply(right(1)*xscale(x/15), circle(....)); > > Does that help? You can now stack transformations using multiplication > similar to how you do it in plain OpenSCAD. > > > jon_bondy wrote >> I clearly do not understand what is going on here.  This works >> >> --- >> >> include &lt;BOSL2/std.scad&gt; >> include &lt;BOSL2/rounding.scad&gt; >> include &lt;BOSL2/skin.scad&gt; >> >> myScale = [1,  2,  4]; >> myZ =     [0, 11, 22]; >> myProfs = [for (x=[0, 1, 2]) >>     xscale(x/15, circle(d = 15, $fn = 80))]; >> >> skin(myProfs, z=myZ, slices=10, method="reindex"); >> >> --- >> >> but if I add the "right(1)", below, in myProfs, this fails with a syntax >> error: >> >> --- >> >> include &lt;BOSL2/std.scad&gt; >> include &lt;BOSL2/rounding.scad&gt; >> include &lt;BOSL2/skin.scad&gt; >> >> myScale = [1,  2,  4]; >> myZ =     [0, 11, 22]; >> myProfs = [for (x=[0, 1, 2]) >>     right(1) xscale(x/15, circle(d = 15, $fn = 80))]; >> >> skin(myProfs, z=myZ, slices=10, method="reindex"); >> >> --- >> >> If I try wrapping the right() and the xscale() together, as >> >> module RightAndXScale(x) >>     right(x) xscale(x/15, circle(d = 15, $fn = 80)); >> >> then >> >> myProfs = [for (x=[0, 1, 2]) >>     RightAndXScale(x); >> >> fails with a syntax error >> >> --- >> >> and if I try >> >> function RightAndXScale(x) >>     right(x) xscale(x/15, circle(d = 15, $fn = 80)); >> >> then the function fails with a syntax error. >> >> >> _______________________________________________ >> OpenSCAD mailing list >> Discuss@.openscad >> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > > > > > -- > Sent from: http://forum.openscad.org/ > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
J
jon
Fri, Jan 1, 2021 11:27 PM

So, if I want to do

shell2d(2, p=circle(20))

I am out of luck, because shell2d() only exists as a module and not as a
function?

And my attempt to convert this into a function

function xxx() =  shell2d(2) circle(d = 20, $fn = 80);

also fails.  Is there a way to convert this into a function which
returns a point list?

Jon

On 12/31/2020 2:14 PM, adrianv wrote:

The problem is your mixing up the module versions and function versions of
the transformation commands.

If you do right(1) without other arguments then it can be a module, in which
case you need some geometry next or it can be a function, which returns the
transformation matrix that shifts right by 1, in which case you need to do
something with it, like perhaps pass it to multmatrix.  (But see below.)

In your "working" example (which actually doesn't work in the latest BOSL2)
you're doing

xscale(value, circle(...));

In this code, circle is the functional form of circle supplied by BOSL2.
It's giving you a point list which is being passed as the second arg to
xscale.  To make this work robustly you should change it to

xscale(value,p=circle(...));

A new argument was added to xscale (centerpoint) so the second arg changed,
and for most of the other transformation functions the position of the point
list argument is not fixed.  So if you want to add right(1) to this you can
do it like this:

right(1, p=xscale(value, p=circle(...)));

Now that's kind of messy.  I recommend only using the "p=" form when you are
applying just one transformation.  If you want several, it's cleaner to use
apply().  If you use a transformation without a point list it gives you the
transformation matrix, and apply applies it to a point list, like multmatrix
for point lists.  So that would look like:

apply(right(1)*xscale(x/15), circle(....));

Does that help?  You can now stack transformations using multiplication
similar to how you do it in plain OpenSCAD.

jon_bondy wrote

I clearly do not understand what is going on here.  This works


include <BOSL2/std.scad>
include <BOSL2/rounding.scad>
include <BOSL2/skin.scad>

myScale = [1,  2,  4];
myZ =     [0, 11, 22];
myProfs = [for (x=[0, 1, 2])
    xscale(x/15, circle(d = 15, $fn = 80))];

skin(myProfs, z=myZ, slices=10, method="reindex");


but if I add the "right(1)", below, in myProfs, this fails with a syntax
error:


include <BOSL2/std.scad>
include <BOSL2/rounding.scad>
include <BOSL2/skin.scad>

myScale = [1,  2,  4];
myZ =     [0, 11, 22];
myProfs = [for (x=[0, 1, 2])
    right(1) xscale(x/15, circle(d = 15, $fn = 80))];

skin(myProfs, z=myZ, slices=10, method="reindex");


If I try wrapping the right() and the xscale() together, as

module RightAndXScale(x)
    right(x) xscale(x/15, circle(d = 15, $fn = 80));

then

myProfs = [for (x=[0, 1, 2])
    RightAndXScale(x);

fails with a syntax error


and if I try

function RightAndXScale(x)
    right(x) xscale(x/15, circle(d = 15, $fn = 80));

then the function fails with a syntax error.


OpenSCAD mailing list
Discuss@.openscad
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

So, if I want to do shell2d(2, p=circle(20)) I am out of luck, because shell2d() only exists as a module and not as a function? And my attempt to convert this into a function function xxx() =  shell2d(2) circle(d = 20, $fn = 80); also fails.  Is there a way to convert this into a function which returns a point list? Jon On 12/31/2020 2:14 PM, adrianv wrote: > The problem is your mixing up the module versions and function versions of > the transformation commands. > > If you do right(1) without other arguments then it can be a module, in which > case you need some geometry next or it can be a function, which returns the > transformation matrix that shifts right by 1, in which case you need to do > something with it, like perhaps pass it to multmatrix. (But see below.) > > In your "working" example (which actually doesn't work in the latest BOSL2) > you're doing > > xscale(value, circle(...)); > > In this code, circle is the functional form of circle supplied by BOSL2. > It's giving you a point list which is being passed as the second arg to > xscale. To make this work robustly you should change it to > > xscale(value,p=circle(...)); > > A new argument was added to xscale (centerpoint) so the second arg changed, > and for most of the other transformation functions the position of the point > list argument is not fixed. So if you want to add right(1) to this you can > do it like this: > > right(1, p=xscale(value, p=circle(...))); > > Now that's kind of messy. I recommend only using the "p=" form when you are > applying just one transformation. If you want several, it's cleaner to use > apply(). If you use a transformation without a point list it gives you the > transformation matrix, and apply applies it to a point list, like multmatrix > for point lists. So that would look like: > > apply(right(1)*xscale(x/15), circle(....)); > > Does that help? You can now stack transformations using multiplication > similar to how you do it in plain OpenSCAD. > > > jon_bondy wrote >> I clearly do not understand what is going on here.  This works >> >> --- >> >> include &lt;BOSL2/std.scad&gt; >> include &lt;BOSL2/rounding.scad&gt; >> include &lt;BOSL2/skin.scad&gt; >> >> myScale = [1,  2,  4]; >> myZ =     [0, 11, 22]; >> myProfs = [for (x=[0, 1, 2]) >>     xscale(x/15, circle(d = 15, $fn = 80))]; >> >> skin(myProfs, z=myZ, slices=10, method="reindex"); >> >> --- >> >> but if I add the "right(1)", below, in myProfs, this fails with a syntax >> error: >> >> --- >> >> include &lt;BOSL2/std.scad&gt; >> include &lt;BOSL2/rounding.scad&gt; >> include &lt;BOSL2/skin.scad&gt; >> >> myScale = [1,  2,  4]; >> myZ =     [0, 11, 22]; >> myProfs = [for (x=[0, 1, 2]) >>     right(1) xscale(x/15, circle(d = 15, $fn = 80))]; >> >> skin(myProfs, z=myZ, slices=10, method="reindex"); >> >> --- >> >> If I try wrapping the right() and the xscale() together, as >> >> module RightAndXScale(x) >>     right(x) xscale(x/15, circle(d = 15, $fn = 80)); >> >> then >> >> myProfs = [for (x=[0, 1, 2]) >>     RightAndXScale(x); >> >> fails with a syntax error >> >> --- >> >> and if I try >> >> function RightAndXScale(x) >>     right(x) xscale(x/15, circle(d = 15, $fn = 80)); >> >> then the function fails with a syntax error. >> >> >> _______________________________________________ >> OpenSCAD mailing list >> Discuss@.openscad >> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > > > > > -- > Sent from: http://forum.openscad.org/ > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
A
adrianv
Sat, Jan 2, 2021 1:07 AM

What does shell2d actually do when you write shell2d(2) circle(20)?  It runs
offset to expand the circle by 2 and then subtracts the original circle.
The resulting shell shape has two boundaries, an internal one which is
circle(20) and an external one, circle(22).  If you're planning to use
skin() then you can only have one boundary.  (Note that path_sweep and sweep
will work on "regions" which can have multiple boundaries, but due to the
complexity of point association, skin requires just a single boundary, so it
only works on paths.)

So the previous question that I'm guessing inspired your question, the
poster wanted a shape that wasn't enclosed, like a circle with a slot cut in
it.  That sort of shape has only one boundary path so you can make it by
concating the inside and outside boundaries (one reversed).  But assuming
you're interested in the two-boundary shape of a tube of some sort, then
you'll need to construct the inside and outside separately as 3d objects and
then difference them.

If you are actually using circles it's easy to construct the outer boundary
by changing the radius.  If you have in mind something more complex then the
way to construct the other boundary is with the offset() function (part of
BOSL2) which will take a point list input and produce the offset point list
as output.

jon_bondy wrote

So, if I want to do

shell2d(2, p=circle(20))

I am out of luck, because shell2d() only exists as a module and not as a
function?

And my attempt to convert this into a function

function xxx() =  shell2d(2) circle(d = 20, $fn = 80);

also fails.  Is there a way to convert this into a function which
returns a point list?

Jon

On 12/31/2020 2:14 PM, adrianv wrote:

The problem is your mixing up the module versions and function versions
of
the transformation commands.

If you do right(1) without other arguments then it can be a module, in
which
case you need some geometry next or it can be a function, which returns
the
transformation matrix that shifts right by 1, in which case you need to
do
something with it, like perhaps pass it to multmatrix.  (But see below.)

In your "working" example (which actually doesn't work in the latest
BOSL2)
you're doing

xscale(value, circle(...));

In this code, circle is the functional form of circle supplied by BOSL2.
It's giving you a point list which is being passed as the second arg to
xscale.  To make this work robustly you should change it to

xscale(value,p=circle(...));

A new argument was added to xscale (centerpoint) so the second arg
changed,
and for most of the other transformation functions the position of the
point
list argument is not fixed.  So if you want to add right(1) to this you
can
do it like this:

right(1, p=xscale(value, p=circle(...)));

Now that's kind of messy.  I recommend only using the "p=" form when you
are
applying just one transformation.  If you want several, it's cleaner to
use
apply().  If you use a transformation without a point list it gives you
the
transformation matrix, and apply applies it to a point list, like
multmatrix
for point lists.  So that would look like:

apply(right(1)*xscale(x/15), circle(....));

Does that help?  You can now stack transformations using multiplication
similar to how you do it in plain OpenSCAD.

jon_bondy wrote

I clearly do not understand what is going on here.  This works


include <BOSL2/std.scad>
include <BOSL2/rounding.scad>
include <BOSL2/skin.scad>

myScale = [1,  2,  4];
myZ =     [0, 11, 22];
myProfs = [for (x=[0, 1, 2])
    xscale(x/15, circle(d = 15, $fn = 80))];

skin(myProfs, z=myZ, slices=10, method="reindex");


but if I add the "right(1)", below, in myProfs, this fails with a syntax
error:


include <BOSL2/std.scad>
include <BOSL2/rounding.scad>
include <BOSL2/skin.scad>

myScale = [1,  2,  4];
myZ =     [0, 11, 22];
myProfs = [for (x=[0, 1, 2])
    right(1) xscale(x/15, circle(d = 15, $fn = 80))];

skin(myProfs, z=myZ, slices=10, method="reindex");


If I try wrapping the right() and the xscale() together, as

module RightAndXScale(x)
    right(x) xscale(x/15, circle(d = 15, $fn = 80));

then

myProfs = [for (x=[0, 1, 2])
    RightAndXScale(x);

fails with a syntax error


and if I try

function RightAndXScale(x)
    right(x) xscale(x/15, circle(d = 15, $fn = 80));

then the function fails with a syntax error.


OpenSCAD mailing list
Discuss@.openscad
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

--
Sent from: http://forum.openscad.org/


OpenSCAD mailing list

Discuss@.openscad

Discuss@.openscad

What does shell2d actually do when you write shell2d(2) circle(20)? It runs offset to expand the circle by 2 and then subtracts the original circle. The resulting shell shape has two boundaries, an internal one which is circle(20) and an external one, circle(22). If you're planning to use skin() then you can only have one boundary. (Note that path_sweep and sweep will work on "regions" which can have multiple boundaries, but due to the complexity of point association, skin requires just a single boundary, so it only works on paths.) So the previous question that I'm guessing inspired your question, the poster wanted a shape that wasn't enclosed, like a circle with a slot cut in it. That sort of shape has only one boundary path so you can make it by concating the inside and outside boundaries (one reversed). But assuming you're interested in the two-boundary shape of a tube of some sort, then you'll need to construct the inside and outside separately as 3d objects and then difference them. If you are actually using circles it's easy to construct the outer boundary by changing the radius. If you have in mind something more complex then the way to construct the other boundary is with the offset() function (part of BOSL2) which will take a point list input and produce the offset point list as output. jon_bondy wrote > So, if I want to do > > shell2d(2, p=circle(20)) > > I am out of luck, because shell2d() only exists as a module and not as a > function? > > And my attempt to convert this into a function > > function xxx() =  shell2d(2) circle(d = 20, $fn = 80); > > also fails.  Is there a way to convert this into a function which > returns a point list? > > Jon > > > On 12/31/2020 2:14 PM, adrianv wrote: >> The problem is your mixing up the module versions and function versions >> of >> the transformation commands. >> >> If you do right(1) without other arguments then it can be a module, in >> which >> case you need some geometry next or it can be a function, which returns >> the >> transformation matrix that shifts right by 1, in which case you need to >> do >> something with it, like perhaps pass it to multmatrix. (But see below.) >> >> In your "working" example (which actually doesn't work in the latest >> BOSL2) >> you're doing >> >> xscale(value, circle(...)); >> >> In this code, circle is the functional form of circle supplied by BOSL2. >> It's giving you a point list which is being passed as the second arg to >> xscale. To make this work robustly you should change it to >> >> xscale(value,p=circle(...)); >> >> A new argument was added to xscale (centerpoint) so the second arg >> changed, >> and for most of the other transformation functions the position of the >> point >> list argument is not fixed. So if you want to add right(1) to this you >> can >> do it like this: >> >> right(1, p=xscale(value, p=circle(...))); >> >> Now that's kind of messy. I recommend only using the "p=" form when you >> are >> applying just one transformation. If you want several, it's cleaner to >> use >> apply(). If you use a transformation without a point list it gives you >> the >> transformation matrix, and apply applies it to a point list, like >> multmatrix >> for point lists. So that would look like: >> >> apply(right(1)*xscale(x/15), circle(....)); >> >> Does that help? You can now stack transformations using multiplication >> similar to how you do it in plain OpenSCAD. >> >> >> jon_bondy wrote >>> I clearly do not understand what is going on here.  This works >>> >>> --- >>> >>> include &lt;BOSL2/std.scad&gt; >>> include &lt;BOSL2/rounding.scad&gt; >>> include &lt;BOSL2/skin.scad&gt; >>> >>> myScale = [1,  2,  4]; >>> myZ =     [0, 11, 22]; >>> myProfs = [for (x=[0, 1, 2]) >>>     xscale(x/15, circle(d = 15, $fn = 80))]; >>> >>> skin(myProfs, z=myZ, slices=10, method="reindex"); >>> >>> --- >>> >>> but if I add the "right(1)", below, in myProfs, this fails with a syntax >>> error: >>> >>> --- >>> >>> include &lt;BOSL2/std.scad&gt; >>> include &lt;BOSL2/rounding.scad&gt; >>> include &lt;BOSL2/skin.scad&gt; >>> >>> myScale = [1,  2,  4]; >>> myZ =     [0, 11, 22]; >>> myProfs = [for (x=[0, 1, 2]) >>>     right(1) xscale(x/15, circle(d = 15, $fn = 80))]; >>> >>> skin(myProfs, z=myZ, slices=10, method="reindex"); >>> >>> --- >>> >>> If I try wrapping the right() and the xscale() together, as >>> >>> module RightAndXScale(x) >>>     right(x) xscale(x/15, circle(d = 15, $fn = 80)); >>> >>> then >>> >>> myProfs = [for (x=[0, 1, 2]) >>>     RightAndXScale(x); >>> >>> fails with a syntax error >>> >>> --- >>> >>> and if I try >>> >>> function RightAndXScale(x) >>>     right(x) xscale(x/15, circle(d = 15, $fn = 80)); >>> >>> then the function fails with a syntax error. >>> >>> >>> _______________________________________________ >>> OpenSCAD mailing list >>> Discuss@.openscad >>> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >> >> >> >> >> -- >> Sent from: http://forum.openscad.org/ >> >> _______________________________________________ >> OpenSCAD mailing list >> > Discuss@.openscad >> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > > _______________________________________________ > OpenSCAD mailing list > Discuss@.openscad > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org -- Sent from: http://forum.openscad.org/
J
jon
Sat, Jan 2, 2021 2:36 PM

Still flailing around...

This works fine:

left_half(planar = true) circle(1);

This

left_half(planar = true, circle(1));

fails with

WARNING: vector*matrix requires vector length to match matrix row count
(3 != 100) in file
C:/Users/jon/Documents/OpenSCAD/libraries/BOSL2/mutators.scad, line 139

And this

module Bowl() {
    myZB = [for (i=[0:14]) -5*i];
    myProfsB = [for (i=[0:14])
        xscale(1, p = left_half(planar = true, circle(d = wB[i], $fn =
80)))];
    skin(myProfsB, z=myZB, slices=10, method="reindex");
    }

fails with

WARNING: Ignoring unknown function 'left_half' in file Spoon.scad, line 134

Why is left_half() recognized as a function in the 2nd example, but not
in the 3rd?

At some point, it may be easier for me to just explain what I'm trying
to do, rather than keep beating my head against this.

Jon

Still flailing around... This works fine: left_half(planar = true) circle(1); This left_half(planar = true, circle(1)); fails with WARNING: vector*matrix requires vector length to match matrix row count (3 != 100) in file C:/Users/jon/Documents/OpenSCAD/libraries/BOSL2/mutators.scad, line 139 And this module Bowl() {     myZB = [for (i=[0:14]) -5*i];     myProfsB = [for (i=[0:14])         xscale(1, p = left_half(planar = true, circle(d = wB[i], $fn = 80)))];     skin(myProfsB, z=myZB, slices=10, method="reindex");     } fails with WARNING: Ignoring unknown function 'left_half' in file Spoon.scad, line 134 Why is left_half() recognized as a function in the 2nd example, but not in the 3rd? At some point, it may be easier for me to just explain what I'm trying to do, rather than keep beating my head against this. Jon
NH
nop head
Sat, Jan 2, 2021 3:22 PM

left_half() must be a module in your first two examples. You can only call
a function in an expression, modules are statements.

On Sat, 2 Jan 2021 at 14:37, jon jon@jonbondy.com wrote:

Still flailing around...

This works fine:

left_half(planar = true) circle(1);

This

left_half(planar = true, circle(1));

fails with

WARNING: vector*matrix requires vector length to match matrix row count (3
!= 100) in file
C:/Users/jon/Documents/OpenSCAD/libraries/BOSL2/mutators.scad, line 139

And this

module Bowl() {
myZB = [for (i=[0:14]) -5*i];
myProfsB = [for (i=[0:14])
xscale(1, p = left_half(planar = true, circle(d = wB[i], $fn =
80)))];
skin(myProfsB, z=myZB, slices=10, method="reindex");
}

fails with

WARNING: Ignoring unknown function 'left_half' in file Spoon.scad, line 134

Why is left_half() recognized as a function in the 2nd example, but not in
the 3rd?

At some point, it may be easier for me to just explain what I'm trying to
do, rather than keep beating my head against this.

Jon


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

left_half() must be a module in your first two examples. You can only call a function in an expression, modules are statements. On Sat, 2 Jan 2021 at 14:37, jon <jon@jonbondy.com> wrote: > Still flailing around... > > This works fine: > > left_half(planar = true) circle(1); > > This > > left_half(planar = true, circle(1)); > > fails with > > WARNING: vector*matrix requires vector length to match matrix row count (3 > != 100) in file > C:/Users/jon/Documents/OpenSCAD/libraries/BOSL2/mutators.scad, line 139 > > And this > > module Bowl() { > myZB = [for (i=[0:14]) -5*i]; > myProfsB = [for (i=[0:14]) > xscale(1, p = left_half(planar = true, circle(d = wB[i], $fn = > 80)))]; > skin(myProfsB, z=myZB, slices=10, method="reindex"); > } > > fails with > > WARNING: Ignoring unknown function 'left_half' in file Spoon.scad, line 134 > > Why is left_half() recognized as a function in the 2nd example, but not in > the 3rd? > > At some point, it may be easier for me to just explain what I'm trying to > do, rather than keep beating my head against this. > > Jon > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
A
adrianv
Sat, Jan 2, 2021 4:02 PM

I have this feeling that you're experimenting with different variations but
that you don't understand what's really going on.  Revar is trying to write
tutorials now for BOSL2, and it would be good if we could understand why you
don't understand and what to say to help you (and others) understand better.
The tutorials are here:  https://github.com/revarbat/BOSL2/wiki/Tutorials
and maybe the Paths and Regions tutorial would help?

OpenSCAD has modules that create geometry and other modules that operate on
geometry.  In core OpenSCAD if you invoke circle() it creates 2d geometry.
If you give it to linear_extrude as a child then you get  a cylinder.

It is impossible to get the points out of geometry, so doing more
interesting manipulations requires that we work in a different way.  To this
end, BOSL2 provides function versions of the core geometry modules. They
look the same, but what happens depends on context.  So with BOSL2 loaded,
circle() will sometimes make geometry (in a module context) and sometimes
produce a "path" (in a function context).    A path is BOSL2 term for an
ordered list of points.  Operating on paths requires that you use functions,
not modules.  So this is the difference between
newpath=xscale(factor,p=some_path); and xscale(factor) some_geomety();  The
former version is passing a path (point list) to a function and getting a
new path out.  The latter is generating geometry in a module and passing it
as a child to xscale, resulting finally in geometry as the result.  If you
run the first one you won't see anything because no geometry has yet been
created.  You need to convert the output, newpath, into geometry, perhaps
with polygon(newpath);

So let's take a look at what you're doing below:

left_half(planar=true) circle(1);

You've used the core circle module to create geometry and you're giving it
as a child to the left_half module which shows just the left part.

left_half(planar=true, circle(1));

You're invoking the module left_half.  We know it's a module because you
didn't assign a return value to something.  The circle(1) invocation is the
function version of circle, so it produces a path.  So you're invoking the
module with planar=true and a list of points.  But if you check the manual,
you'll see that the module version does not accept a path, only two scalars.
So you've given invalid input.  The error message need to be improved.

If you change it to

lcirc=left_half(....);

then you will get the functional form.  However, the functional form of the
"half" operators was added recently and appears to be seriously buggy.  So
for now....don't try to use it.  It looks like your version of BOSL2
predates the existence of the functional form of left_half because in your
example below you show an error, "unknown function left_half".

I think maybe your code would do what you want if you use arc() instead of
circle(), since arc() can create a half circle directly.

Here's your code with arc inserted.  You didn't define wB so I'm not sure
what you're after.  You might want to explain what you're trying to do as
there might possibly be a completely different approach.

module Bowl() {
myZB = [for (i=[0:14]) -5*i];
myProfsB = [for (i=[0:14])
xscale(1, p=arc(angle=[180,360],d = wB[i], $fn = 80))];
skin(myProfsB, z=myZB, slices=10, method="reindex");
}

jon_bondy wrote

Still flailing around...

This works fine:

left_half(planar = true) circle(1);

This

left_half(planar = true, circle(1));

fails with

WARNING: vector*matrix requires vector length to match matrix row count
(3 != 100) in file
C:/Users/jon/Documents/OpenSCAD/libraries/BOSL2/mutators.scad, line 139

And this

module Bowl() {
    myZB = [for (i=[0:14]) -5*i];
    myProfsB = [for (i=[0:14])
        xscale(1, p = left_half(planar = true, circle(d = wB[i], $fn =
80)))];
    skin(myProfsB, z=myZB, slices=10, method="reindex");
    }

fails with

WARNING: Ignoring unknown function 'left_half' in file Spoon.scad, line
134

Why is left_half() recognized as a function in the 2nd example, but not
in the 3rd?

At some point, it may be easier for me to just explain what I'm trying
to do, rather than keep beating my head against this.

Jon


OpenSCAD mailing list

Discuss@.openscad

I have this feeling that you're experimenting with different variations but that you don't understand what's really going on. Revar is trying to write tutorials now for BOSL2, and it would be good if we could understand why you don't understand and what to say to help you (and others) understand better. The tutorials are here: https://github.com/revarbat/BOSL2/wiki/Tutorials and maybe the Paths and Regions tutorial would help? OpenSCAD has modules that create geometry and other modules that operate on geometry. In core OpenSCAD if you invoke circle() it creates 2d geometry. If you give it to linear_extrude as a child then you get a cylinder. It is impossible to get the points out of geometry, so doing more interesting manipulations requires that we work in a different way. To this end, BOSL2 provides function versions of the core geometry modules. They look the same, but what happens depends on context. So with BOSL2 loaded, circle() will sometimes make geometry (in a module context) and sometimes produce a "path" (in a function context). A path is BOSL2 term for an ordered list of points. Operating on paths requires that you use functions, not modules. So this is the difference between newpath=xscale(factor,p=some_path); and xscale(factor) some_geomety(); The former version is passing a path (point list) to a function and getting a new path out. The latter is generating geometry in a module and passing it as a child to xscale, resulting finally in geometry as the result. If you run the first one you won't see anything because no geometry has yet been created. You need to convert the output, newpath, into geometry, perhaps with polygon(newpath); So let's take a look at what you're doing below: left_half(planar=true) circle(1); You've used the core circle module to create geometry and you're giving it as a child to the left_half module which shows just the left part. left_half(planar=true, circle(1)); You're invoking the module left_half. We know it's a module because you didn't assign a return value to something. The circle(1) invocation is the function version of circle, so it produces a path. So you're invoking the module with planar=true and a list of points. But if you check the manual, you'll see that the module version does not accept a path, only two scalars. So you've given invalid input. The error message need to be improved. If you change it to lcirc=left_half(....); then you will get the functional form. However, the functional form of the "half" operators was added recently and appears to be seriously buggy. So for now....don't try to use it. It looks like your version of BOSL2 predates the existence of the functional form of left_half because in your example below you show an error, "unknown function left_half". I think maybe your code would do what you want if you use arc() instead of circle(), since arc() can create a half circle directly. Here's your code with arc inserted. You didn't define wB so I'm not sure what you're after. You might want to explain what you're trying to do as there might possibly be a completely different approach. module Bowl() { myZB = [for (i=[0:14]) -5*i]; myProfsB = [for (i=[0:14]) xscale(1, p=arc(angle=[180,360],d = wB[i], $fn = 80))]; skin(myProfsB, z=myZB, slices=10, method="reindex"); } jon_bondy wrote > Still flailing around... > > This works fine: > > left_half(planar = true) circle(1); > > This > > left_half(planar = true, circle(1)); > > fails with > > WARNING: vector*matrix requires vector length to match matrix row count > (3 != 100) in file > C:/Users/jon/Documents/OpenSCAD/libraries/BOSL2/mutators.scad, line 139 > > And this > > module Bowl() { >     myZB = [for (i=[0:14]) -5*i]; >     myProfsB = [for (i=[0:14]) >         xscale(1, p = left_half(planar = true, circle(d = wB[i], $fn = > 80)))]; >     skin(myProfsB, z=myZB, slices=10, method="reindex"); >     } > > fails with > > WARNING: Ignoring unknown function 'left_half' in file Spoon.scad, line > 134 > > Why is left_half() recognized as a function in the 2nd example, but not > in the 3rd? > > At some point, it may be easier for me to just explain what I'm trying > to do, rather than keep beating my head against this. > > Jon > > > > _______________________________________________ > OpenSCAD mailing list > Discuss@.openscad > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org -- Sent from: http://forum.openscad.org/
J
jon
Sat, Jan 2, 2021 4:03 PM

The documentation says that left_half() can be used as a function and
provides examples...

On 1/2/2021 10:22 AM, nop head wrote:

left_half() must be a module in your first two examples. You can only
call a function in an expression, modules are statements.

The documentation says that left_half() can be used as a function and provides examples... On 1/2/2021 10:22 AM, nop head wrote: > left_half() must be a module in your first two examples. You can only > call a function in an expression, modules are statements. >
A
adrianv
Sat, Jan 2, 2021 4:44 PM

Yes, but you didn't use it as a function.  You used it as a module.  There
are in fact no examples in the manual of using it as a function.  Here's an
example:

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

dodecahedron = regular_polyhedron_info("vnf","dodecahedron",side=10);  //
Get something to use as input
half_dodec = left_half(dodecahedron);
vnf_wireframe(half_dodec,$fn=32,r=0.2);

Note that based on your previous post, your BOSL2 is probably older than the
introduction of the functional form of left_half.  Also note that the above
code actually gives the right half.  Like I said:  the function version is
buggy.

jon_bondy wrote

The documentation says that left_half() can be used as a function and
provides examples...

On 1/2/2021 10:22 AM, nop head wrote:

left_half() must be a module in your first two examples. You can only
call a function in an expression, modules are statements.


OpenSCAD mailing list

Discuss@.openscad

Yes, but you didn't use it as a function. You used it as a module. There are in fact no examples in the manual of using it as a function. Here's an example: include <BOSL2/std.scad> include <BOSL2/polyhedra.scad> dodecahedron = regular_polyhedron_info("vnf","dodecahedron",side=10); // Get something to use as input half_dodec = left_half(dodecahedron); vnf_wireframe(half_dodec,$fn=32,r=0.2); Note that based on your previous post, your BOSL2 is probably older than the introduction of the functional form of left_half. Also note that the above code actually gives the right half. Like I said: the function version is buggy. jon_bondy wrote > The documentation says that left_half() can be used as a function and > provides examples... > > On 1/2/2021 10:22 AM, nop head wrote: >> left_half() must be a module in your first two examples. You can only >> call a function in an expression, modules are statements. >> > > _______________________________________________ > OpenSCAD mailing list > Discuss@.openscad > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org -- Sent from: http://forum.openscad.org/
J
jon
Sat, Jan 2, 2021 5:12 PM

"you don't understand what's really going on"

Yes.  Totally.

Thank you for taking so much time to explain things to me (and, I hope,
to others).

The idea that a given named entity ("circle") behaves differently in
different contexts (and in fact comes from the language intrinsics in
one case and from a library in another), and produces different output
in different contexts is powerful, but also confusing.  At least to me. 
If I had written the library, I would have created circleM() for the
module and circleF() for the function, for my own sanity.  I grew up
with Pascal, with strong type checking, so I never encountered these
puns during my career.  I understand that others in the OpenSCAD
community see things differently.

For example, at one point you say "You've used the core circle module". 
If you say so.  In a previous email you mentioned
"xscale(value,p=circle(...));" where that circle() came from BOSL2.  One
important issue for me is that I have no way of knowing which circle() I
am using.  For example, there is no way to query the compiler or the IDE
to see how it resolved those characters, is there?  Your familiarity
with the library and the underlying issues allows you to see the code
with more clarity than I do.  This may be an issue for newbies,
depending on the path they took to arrive at OpenSCAD.

It seems that there is no easy way to look at an entity and know whether
it emits geometry or lists-of-points.  Sure, you can look it up in the
documentation (if you can be SURE that the entity in question came from
that library), but I said "easy".  So maybe circleG() and circleP() for
geometry and points.

And, no, I am not implying that I believe that any of these entities
will be renamed for my benefit.  I am merely explaining how I see things.

In some languages (Pascal),  an entity is either a function or a
procedure (module).  In others (C, I believe), a function can be used as
a procedure (discarding the returned result) so there are no
procedures/modules.  So I was not expecting

x = fred()

to behave differently than

fred()

although I did expect

fred(x, p=joe)

to behave differently, because of the "p" parameter name.

It seems that if one can keep in the company of functions, then one can
always have lists-of-points.  I need to create a shape like a "C".  One
thought was to take a circle, offset it larger, subtract the original
from the larger to get a washer, and then take half of that object.  The
problem is that the offset (and maybe difference) operators are modules,
so once I leave the list-of-points domain, I am out of luck.

Maybe one useful addition to the documentation (for me) would be a
separate list of entities that emit lists-of-points.  Then I would take
that list as a the palette from which I would choose operations in my
quest for the "C" shape.

You say "It looks like your version of BOSL2 predates the existence of
the functional form of left_half because in your example below you show
an error, "unknown function left_half"." But in fact left_half() is
present, because, as I said

left_half(planar = true) circle(1);

works fine.  Confusing.  This may well be a bug.

So.  I am trying to design a configurable spoon.  The code in question
is trying to create the bowl of the spoon.  I started off trying to use
semi-circular shapes with a parametrized thickness and diameter, but
could not figure out how to generate those shapes as lists-of-points. I
assume that eventually I will refine the shape a bit.

Thanks, again, for being so helpful

Jon

On 1/2/2021 11:02 AM, adrianv wrote:

I have this feeling that you're experimenting with different variations but
that you don't understand what's really going on.  Revar is trying to write
tutorials now for BOSL2, and it would be good if we could understand why you
don't understand and what to say to help you (and others) understand better.
The tutorials are here:  https://github.com/revarbat/BOSL2/wiki/Tutorials
and maybe the Paths and Regions tutorial would help?

OpenSCAD has modules that create geometry and other modules that operate on
geometry.  In core OpenSCAD if you invoke circle() it creates 2d geometry.
If you give it to linear_extrude as a child then you get  a cylinder.

It is impossible to get the points out of geometry, so doing more
interesting manipulations requires that we work in a different way.  To this
end, BOSL2 provides function versions of the core geometry modules. They
look the same, but what happens depends on context.  So with BOSL2 loaded,
circle() will sometimes make geometry (in a module context) and sometimes
produce a "path" (in a function context).    A path is BOSL2 term for an
ordered list of points.  Operating on paths requires that you use functions,
not modules.  So this is the difference between
newpath=xscale(factor,p=some_path); and xscale(factor) some_geomety();  The
former version is passing a path (point list) to a function and getting a
new path out.  The latter is generating geometry in a module and passing it
as a child to xscale, resulting finally in geometry as the result.  If you
run the first one you won't see anything because no geometry has yet been
created.  You need to convert the output, newpath, into geometry, perhaps
with polygon(newpath);

So let's take a look at what you're doing below:

left_half(planar=true) circle(1);

You've used the core circle module to create geometry and you're giving it
as a child to the left_half module which shows just the left part.

left_half(planar=true, circle(1));

You're invoking the module left_half.  We know it's a module because you
didn't assign a return value to something.  The circle(1) invocation is the
function version of circle, so it produces a path.  So you're invoking the
module with planar=true and a list of points.  But if you check the manual,
you'll see that the module version does not accept a path, only two scalars.
So you've given invalid input.  The error message need to be improved.

If you change it to

lcirc=left_half(....);

then you will get the functional form.  However, the functional form of the
"half" operators was added recently and appears to be seriously buggy.  So
for now....don't try to use it.  It looks like your version of BOSL2
predates the existence of the functional form of left_half because in your
example below you show an error, "unknown function left_half".

I think maybe your code would do what you want if you use arc() instead of
circle(), since arc() can create a half circle directly.

Here's your code with arc inserted.  You didn't define wB so I'm not sure
what you're after.  You might want to explain what you're trying to do as
there might possibly be a completely different approach.

module Bowl() {
myZB = [for (i=[0:14]) -5*i];
myProfsB = [for (i=[0:14])
xscale(1, p=arc(angle=[180,360],d = wB[i], $fn = 80))];
skin(myProfsB, z=myZB, slices=10, method="reindex");
}

jon_bondy wrote

Still flailing around...

This works fine:

left_half(planar = true) circle(1);

This

left_half(planar = true, circle(1));

fails with

WARNING: vector*matrix requires vector length to match matrix row count
(3 != 100) in file
C:/Users/jon/Documents/OpenSCAD/libraries/BOSL2/mutators.scad, line 139

And this

module Bowl() {
    myZB = [for (i=[0:14]) -5*i];
    myProfsB = [for (i=[0:14])
        xscale(1, p = left_half(planar = true, circle(d = wB[i], $fn =
80)))];
    skin(myProfsB, z=myZB, slices=10, method="reindex");
    }

fails with

WARNING: Ignoring unknown function 'left_half' in file Spoon.scad, line
134

Why is left_half() recognized as a function in the 2nd example, but not
in the 3rd?

At some point, it may be easier for me to just explain what I'm trying
to do, rather than keep beating my head against this.

Jon

"you don't understand what's really going on" Yes.  Totally. Thank you for taking so much time to explain things to me (and, I hope, to others). The idea that a given named entity ("circle") behaves differently in different contexts (and in fact comes from the language intrinsics in one case and from a library in another), and produces different output in different contexts is powerful, but also confusing.  At least to me.  If I had written the library, I would have created circleM() for the module and circleF() for the function, for my own sanity.  I grew up with Pascal, with strong type checking, so I never encountered these puns during my career.  I understand that others in the OpenSCAD community see things differently. For example, at one point you say "You've used the core circle module".  If you say so.  In a previous email you mentioned "xscale(value,p=circle(...));" where that circle() came from BOSL2.  One important issue for me is that I have no way of knowing which circle() I am using.  For example, there is no way to query the compiler or the IDE to see how it resolved those characters, is there?  Your familiarity with the library and the underlying issues allows you to see the code with more clarity than I do.  This may be an issue for newbies, depending on the path they took to arrive at OpenSCAD. It seems that there is no easy way to look at an entity and know whether it emits geometry or lists-of-points.  Sure, you can look it up in the documentation (if you can be SURE that the entity in question came from that library), but I said "easy".  So maybe circleG() and circleP() for geometry and points. And, no, I am not implying that I believe that any of these entities will be renamed for my benefit.  I am merely explaining how I see things. In some languages (Pascal),  an entity is either a function or a procedure (module).  In others (C, I believe), a function can be used as a procedure (discarding the returned result) so there are no procedures/modules.  So I was not expecting x = fred() to behave differently than fred() although I did expect fred(x, p=joe) to behave differently, because of the "p" parameter name. It seems that if one can keep in the company of functions, then one can always have lists-of-points.  I need to create a shape like a "C".  One thought was to take a circle, offset it larger, subtract the original from the larger to get a washer, and then take half of that object.  The problem is that the offset (and maybe difference) operators are modules, so once I leave the list-of-points domain, I am out of luck. Maybe one useful addition to the documentation (for me) would be a separate list of entities that emit lists-of-points.  Then I would take that list as a the palette from which I would choose operations in my quest for the "C" shape. You say "It looks like your version of BOSL2 predates the existence of the functional form of left_half because in your example below you show an error, "unknown function left_half"." But in fact left_half() is present, because, as I said left_half(planar = true) circle(1); works fine.  Confusing.  This may well be a bug. So.  I am trying to design a configurable spoon.  The code in question is trying to create the bowl of the spoon.  I started off trying to use semi-circular shapes with a parametrized thickness and diameter, but could not figure out how to generate those shapes as lists-of-points. I assume that eventually I will refine the shape a bit. Thanks, again, for being so helpful Jon On 1/2/2021 11:02 AM, adrianv wrote: > I have this feeling that you're experimenting with different variations but > that you don't understand what's really going on. Revar is trying to write > tutorials now for BOSL2, and it would be good if we could understand why you > don't understand and what to say to help you (and others) understand better. > The tutorials are here: https://github.com/revarbat/BOSL2/wiki/Tutorials > and maybe the Paths and Regions tutorial would help? > > OpenSCAD has modules that create geometry and other modules that operate on > geometry. In core OpenSCAD if you invoke circle() it creates 2d geometry. > If you give it to linear_extrude as a child then you get a cylinder. > > It is impossible to get the points out of geometry, so doing more > interesting manipulations requires that we work in a different way. To this > end, BOSL2 provides function versions of the core geometry modules. They > look the same, but what happens depends on context. So with BOSL2 loaded, > circle() will sometimes make geometry (in a module context) and sometimes > produce a "path" (in a function context). A path is BOSL2 term for an > ordered list of points. Operating on paths requires that you use functions, > not modules. So this is the difference between > newpath=xscale(factor,p=some_path); and xscale(factor) some_geomety(); The > former version is passing a path (point list) to a function and getting a > new path out. The latter is generating geometry in a module and passing it > as a child to xscale, resulting finally in geometry as the result. If you > run the first one you won't see anything because no geometry has yet been > created. You need to convert the output, newpath, into geometry, perhaps > with polygon(newpath); > > So let's take a look at what you're doing below: > > left_half(planar=true) circle(1); > > You've used the core circle module to create geometry and you're giving it > as a child to the left_half module which shows just the left part. > > left_half(planar=true, circle(1)); > > You're invoking the module left_half. We know it's a module because you > didn't assign a return value to something. The circle(1) invocation is the > function version of circle, so it produces a path. So you're invoking the > module with planar=true and a list of points. But if you check the manual, > you'll see that the module version does not accept a path, only two scalars. > So you've given invalid input. The error message need to be improved. > > If you change it to > > lcirc=left_half(....); > > then you will get the functional form. However, the functional form of the > "half" operators was added recently and appears to be seriously buggy. So > for now....don't try to use it. It looks like your version of BOSL2 > predates the existence of the functional form of left_half because in your > example below you show an error, "unknown function left_half". > > I think maybe your code would do what you want if you use arc() instead of > circle(), since arc() can create a half circle directly. > > Here's your code with arc inserted. You didn't define wB so I'm not sure > what you're after. You might want to explain what you're trying to do as > there might possibly be a completely different approach. > > module Bowl() { > myZB = [for (i=[0:14]) -5*i]; > myProfsB = [for (i=[0:14]) > xscale(1, p=arc(angle=[180,360],d = wB[i], $fn = 80))]; > skin(myProfsB, z=myZB, slices=10, method="reindex"); > } > > > > > > jon_bondy wrote >> Still flailing around... >> >> This works fine: >> >> left_half(planar = true) circle(1); >> >> This >> >> left_half(planar = true, circle(1)); >> >> fails with >> >> WARNING: vector*matrix requires vector length to match matrix row count >> (3 != 100) in file >> C:/Users/jon/Documents/OpenSCAD/libraries/BOSL2/mutators.scad, line 139 >> >> And this >> >> module Bowl() { >>     myZB = [for (i=[0:14]) -5*i]; >>     myProfsB = [for (i=[0:14]) >>         xscale(1, p = left_half(planar = true, circle(d = wB[i], $fn = >> 80)))]; >>     skin(myProfsB, z=myZB, slices=10, method="reindex"); >>     } >> >> fails with >> >> WARNING: Ignoring unknown function 'left_half' in file Spoon.scad, line >> 134 >> >> Why is left_half() recognized as a function in the 2nd example, but not >> in the 3rd? >> >> At some point, it may be easier for me to just explain what I'm trying >> to do, rather than keep beating my head against this. >> >> Jon >> >>
NH
nop head
Sat, Jan 2, 2021 5:30 PM

There is never any ambiguity whether you are using a function or a module
even if they have the same name because functions can only be used in
expressions and modules can only be used in statements.

fred() circle(); // Must be a module operating on geometry.
x = fred(circle()); // Fred must be a function and so must circle,
functions cannot return geometry but that can return lists of points
representing geometry,
fred(circle()); // Fred must be a module and circle must be a function.

On Sat, 2 Jan 2021 at 17:13, jon jon@jonbondy.com wrote:

"you don't understand what's really going on"

Yes.  Totally.

Thank you for taking so much time to explain things to me (and, I hope,
to others).

The idea that a given named entity ("circle") behaves differently in
different contexts (and in fact comes from the language intrinsics in
one case and from a library in another), and produces different output
in different contexts is powerful, but also confusing.  At least to me.
If I had written the library, I would have created circleM() for the
module and circleF() for the function, for my own sanity.  I grew up
with Pascal, with strong type checking, so I never encountered these
puns during my career.  I understand that others in the OpenSCAD
community see things differently.

For example, at one point you say "You've used the core circle module".
If you say so.  In a previous email you mentioned
"xscale(value,p=circle(...));" where that circle() came from BOSL2.  One
important issue for me is that I have no way of knowing which circle() I
am using.  For example, there is no way to query the compiler or the IDE
to see how it resolved those characters, is there?  Your familiarity
with the library and the underlying issues allows you to see the code
with more clarity than I do.  This may be an issue for newbies,
depending on the path they took to arrive at OpenSCAD.

It seems that there is no easy way to look at an entity and know whether
it emits geometry or lists-of-points.  Sure, you can look it up in the
documentation (if you can be SURE that the entity in question came from
that library), but I said "easy".  So maybe circleG() and circleP() for
geometry and points.

And, no, I am not implying that I believe that any of these entities
will be renamed for my benefit.  I am merely explaining how I see things.

In some languages (Pascal),  an entity is either a function or a
procedure (module).  In others (C, I believe), a function can be used as
a procedure (discarding the returned result) so there are no
procedures/modules.  So I was not expecting

x = fred()

to behave differently than

fred()

although I did expect

fred(x, p=joe)

to behave differently, because of the "p" parameter name.

It seems that if one can keep in the company of functions, then one can
always have lists-of-points.  I need to create a shape like a "C".  One
thought was to take a circle, offset it larger, subtract the original
from the larger to get a washer, and then take half of that object.  The
problem is that the offset (and maybe difference) operators are modules,
so once I leave the list-of-points domain, I am out of luck.

Maybe one useful addition to the documentation (for me) would be a
separate list of entities that emit lists-of-points.  Then I would take
that list as a the palette from which I would choose operations in my
quest for the "C" shape.

You say "It looks like your version of BOSL2 predates the existence of
the functional form of left_half because in your example below you show
an error, "unknown function left_half"." But in fact left_half() is
present, because, as I said

left_half(planar = true) circle(1);

works fine.  Confusing.  This may well be a bug.

So.  I am trying to design a configurable spoon.  The code in question
is trying to create the bowl of the spoon.  I started off trying to use
semi-circular shapes with a parametrized thickness and diameter, but
could not figure out how to generate those shapes as lists-of-points. I
assume that eventually I will refine the shape a bit.

Thanks, again, for being so helpful

Jon

On 1/2/2021 11:02 AM, adrianv wrote:

I have this feeling that you're experimenting with different variations

but

that you don't understand what's really going on.  Revar is trying to

write

tutorials now for BOSL2, and it would be good if we could understand why

you

don't understand and what to say to help you (and others) understand

better.

The tutorials are here:

and maybe the Paths and Regions tutorial would help?

OpenSCAD has modules that create geometry and other modules that operate

on

geometry.  In core OpenSCAD if you invoke circle() it creates 2d

geometry.

If you give it to linear_extrude as a child then you get  a cylinder.

It is impossible to get the points out of geometry, so doing more
interesting manipulations requires that we work in a different way.  To

this

end, BOSL2 provides function versions of the core geometry modules. They
look the same, but what happens depends on context.  So with BOSL2

loaded,

circle() will sometimes make geometry (in a module context) and sometimes
produce a "path" (in a function context).    A path is BOSL2 term for an
ordered list of points.  Operating on paths requires that you use

functions,

not modules.  So this is the difference between
newpath=xscale(factor,p=some_path); and xscale(factor) some_geomety();

The

former version is passing a path (point list) to a function and getting a
new path out.  The latter is generating geometry in a module and passing

it

as a child to xscale, resulting finally in geometry as the result.  If

you

run the first one you won't see anything because no geometry has yet been
created.  You need to convert the output, newpath, into geometry, perhaps
with polygon(newpath);

So let's take a look at what you're doing below:

left_half(planar=true) circle(1);

You've used the core circle module to create geometry and you're giving

it

as a child to the left_half module which shows just the left part.

left_half(planar=true, circle(1));

You're invoking the module left_half.  We know it's a module because you
didn't assign a return value to something.  The circle(1) invocation is

the

function version of circle, so it produces a path.  So you're invoking

the

module with planar=true and a list of points.  But if you check the

manual,

you'll see that the module version does not accept a path, only two

scalars.

So you've given invalid input.  The error message need to be improved.

If you change it to

lcirc=left_half(....);

then you will get the functional form.  However, the functional form of

the

"half" operators was added recently and appears to be seriously buggy.

So

for now....don't try to use it.  It looks like your version of BOSL2
predates the existence of the functional form of left_half because in

your

example below you show an error, "unknown function left_half".

I think maybe your code would do what you want if you use arc() instead

of

circle(), since arc() can create a half circle directly.

Here's your code with arc inserted.  You didn't define wB so I'm not sure
what you're after.  You might want to explain what you're trying to do as
there might possibly be a completely different approach.

module Bowl() {
myZB = [for (i=[0:14]) -5*i];
myProfsB = [for (i=[0:14])
xscale(1, p=arc(angle=[180,360],d = wB[i], $fn = 80))];
skin(myProfsB, z=myZB, slices=10, method="reindex");
}

jon_bondy wrote

Still flailing around...

This works fine:

left_half(planar = true) circle(1);

This

left_half(planar = true, circle(1));

fails with

WARNING: vector*matrix requires vector length to match matrix row count
(3 != 100) in file
C:/Users/jon/Documents/OpenSCAD/libraries/BOSL2/mutators.scad, line 139

And this

module Bowl() {
myZB = [for (i=[0:14]) -5*i];
myProfsB = [for (i=[0:14])
xscale(1, p = left_half(planar = true, circle(d = wB[i], $fn =
80)))];
skin(myProfsB, z=myZB, slices=10, method="reindex");
}

fails with

WARNING: Ignoring unknown function 'left_half' in file Spoon.scad, line
134

Why is left_half() recognized as a function in the 2nd example, but not
in the 3rd?

At some point, it may be easier for me to just explain what I'm trying
to do, rather than keep beating my head against this.

Jon

There is never any ambiguity whether you are using a function or a module even if they have the same name because functions can only be used in expressions and modules can only be used in statements. fred() circle(); // Must be a module operating on geometry. x = fred(circle()); // Fred must be a function and so must circle, functions cannot return geometry but that can return lists of points representing geometry, fred(circle()); // Fred must be a module and circle must be a function. On Sat, 2 Jan 2021 at 17:13, jon <jon@jonbondy.com> wrote: > "you don't understand what's really going on" > > Yes. Totally. > > Thank you for taking so much time to explain things to me (and, I hope, > to others). > > > The idea that a given named entity ("circle") behaves differently in > different contexts (and in fact comes from the language intrinsics in > one case and from a library in another), and produces different output > in different contexts is powerful, but also confusing. At least to me. > If I had written the library, I would have created circleM() for the > module and circleF() for the function, for my own sanity. I grew up > with Pascal, with strong type checking, so I never encountered these > puns during my career. I understand that others in the OpenSCAD > community see things differently. > > For example, at one point you say "You've used the core circle module". > If you say so. In a previous email you mentioned > "xscale(value,p=circle(...));" where that circle() came from BOSL2. One > important issue for me is that I have no way of knowing which circle() I > am using. For example, there is no way to query the compiler or the IDE > to see how it resolved those characters, is there? Your familiarity > with the library and the underlying issues allows you to see the code > with more clarity than I do. This may be an issue for newbies, > depending on the path they took to arrive at OpenSCAD. > > It seems that there is no easy way to look at an entity and know whether > it emits geometry or lists-of-points. Sure, you can look it up in the > documentation (if you can be SURE that the entity in question came from > that library), but I said "easy". So maybe circleG() and circleP() for > geometry and points. > > And, no, I am not implying that I believe that any of these entities > will be renamed for my benefit. I am merely explaining how I see things. > > In some languages (Pascal), an entity is either a function or a > procedure (module). In others (C, I believe), a function can be used as > a procedure (discarding the returned result) so there are no > procedures/modules. So I was not expecting > > x = fred() > > to behave differently than > > fred() > > although I did expect > > fred(x, p=joe) > > to behave differently, because of the "p" parameter name. > > It seems that if one can keep in the company of functions, then one can > always have lists-of-points. I need to create a shape like a "C". One > thought was to take a circle, offset it larger, subtract the original > from the larger to get a washer, and then take half of that object. The > problem is that the offset (and maybe difference) operators are modules, > so once I leave the list-of-points domain, I am out of luck. > > Maybe one useful addition to the documentation (for me) would be a > separate list of entities that emit lists-of-points. Then I would take > that list as a the palette from which I would choose operations in my > quest for the "C" shape. > > You say "It looks like your version of BOSL2 predates the existence of > the functional form of left_half because in your example below you show > an error, "unknown function left_half"." But in fact left_half() is > present, because, as I said > > left_half(planar = true) circle(1); > > works fine. Confusing. This may well be a bug. > > > So. I am trying to design a configurable spoon. The code in question > is trying to create the bowl of the spoon. I started off trying to use > semi-circular shapes with a parametrized thickness and diameter, but > could not figure out how to generate those shapes as lists-of-points. I > assume that eventually I will refine the shape a bit. > > Thanks, again, for being so helpful > > Jon > > > On 1/2/2021 11:02 AM, adrianv wrote: > > I have this feeling that you're experimenting with different variations > but > > that you don't understand what's really going on. Revar is trying to > write > > tutorials now for BOSL2, and it would be good if we could understand why > you > > don't understand and what to say to help you (and others) understand > better. > > The tutorials are here: > https://github.com/revarbat/BOSL2/wiki/Tutorials > > and maybe the Paths and Regions tutorial would help? > > > > OpenSCAD has modules that create geometry and other modules that operate > on > > geometry. In core OpenSCAD if you invoke circle() it creates 2d > geometry. > > If you give it to linear_extrude as a child then you get a cylinder. > > > > It is impossible to get the points out of geometry, so doing more > > interesting manipulations requires that we work in a different way. To > this > > end, BOSL2 provides function versions of the core geometry modules. They > > look the same, but what happens depends on context. So with BOSL2 > loaded, > > circle() will sometimes make geometry (in a module context) and sometimes > > produce a "path" (in a function context). A path is BOSL2 term for an > > ordered list of points. Operating on paths requires that you use > functions, > > not modules. So this is the difference between > > newpath=xscale(factor,p=some_path); and xscale(factor) some_geomety(); > The > > former version is passing a path (point list) to a function and getting a > > new path out. The latter is generating geometry in a module and passing > it > > as a child to xscale, resulting finally in geometry as the result. If > you > > run the first one you won't see anything because no geometry has yet been > > created. You need to convert the output, newpath, into geometry, perhaps > > with polygon(newpath); > > > > So let's take a look at what you're doing below: > > > > left_half(planar=true) circle(1); > > > > You've used the core circle module to create geometry and you're giving > it > > as a child to the left_half module which shows just the left part. > > > > left_half(planar=true, circle(1)); > > > > You're invoking the module left_half. We know it's a module because you > > didn't assign a return value to something. The circle(1) invocation is > the > > function version of circle, so it produces a path. So you're invoking > the > > module with planar=true and a list of points. But if you check the > manual, > > you'll see that the module version does not accept a path, only two > scalars. > > So you've given invalid input. The error message need to be improved. > > > > If you change it to > > > > lcirc=left_half(....); > > > > then you will get the functional form. However, the functional form of > the > > "half" operators was added recently and appears to be seriously buggy. > So > > for now....don't try to use it. It looks like your version of BOSL2 > > predates the existence of the functional form of left_half because in > your > > example below you show an error, "unknown function left_half". > > > > I think maybe your code would do what you want if you use arc() instead > of > > circle(), since arc() can create a half circle directly. > > > > Here's your code with arc inserted. You didn't define wB so I'm not sure > > what you're after. You might want to explain what you're trying to do as > > there might possibly be a completely different approach. > > > > module Bowl() { > > myZB = [for (i=[0:14]) -5*i]; > > myProfsB = [for (i=[0:14]) > > xscale(1, p=arc(angle=[180,360],d = wB[i], $fn = 80))]; > > skin(myProfsB, z=myZB, slices=10, method="reindex"); > > } > > > > > > > > > > > > jon_bondy wrote > >> Still flailing around... > >> > >> This works fine: > >> > >> left_half(planar = true) circle(1); > >> > >> This > >> > >> left_half(planar = true, circle(1)); > >> > >> fails with > >> > >> WARNING: vector*matrix requires vector length to match matrix row count > >> (3 != 100) in file > >> C:/Users/jon/Documents/OpenSCAD/libraries/BOSL2/mutators.scad, line 139 > >> > >> And this > >> > >> module Bowl() { > >> myZB = [for (i=[0:14]) -5*i]; > >> myProfsB = [for (i=[0:14]) > >> xscale(1, p = left_half(planar = true, circle(d = wB[i], $fn = > >> 80)))]; > >> skin(myProfsB, z=myZB, slices=10, method="reindex"); > >> } > >> > >> fails with > >> > >> WARNING: Ignoring unknown function 'left_half' in file Spoon.scad, line > >> 134 > >> > >> Why is left_half() recognized as a function in the 2nd example, but not > >> in the 3rd? > >> > >> At some point, it may be easier for me to just explain what I'm trying > >> to do, rather than keep beating my head against this. > >> > >> Jon > >> > >> > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
J
jon
Sat, Jan 2, 2021 5:32 PM

If I go here

https://github.com/revarbat/BOSL2/wiki/mutators.scad#left_half

I see this

  left_half()

Type: Function/Module

Usage: as module

  • left_half(<s>, <x>) ...
  • left_half(planar=true, <s>, <x>) ...

Usage: as function

  • left_half(<s>, <x>, path)
  • left_half(<s>, <x>, region)
  • left_half(<s>, <x>, vnf)

No wonder I thought that you could use it as a function without
assigning it to anything.

Jon

On 1/2/2021 11:44 AM, adrianv wrote:

Yes, but you didn't use it as a function.  You used it as a module.  There
are in fact no examples in the manual of using it as a function.  Here's an
example:

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

dodecahedron = regular_polyhedron_info("vnf","dodecahedron",side=10);  //
Get something to use as input
half_dodec = left_half(dodecahedron);
vnf_wireframe(half_dodec,$fn=32,r=0.2);

Note that based on your previous post, your BOSL2 is probably older than the
introduction of the functional form of left_half.  Also note that the above
code actually gives the right half.  Like I said:  the function version is
buggy.

jon_bondy wrote

The documentation says that left_half() can be used as a function and
provides examples...

On 1/2/2021 10:22 AM, nop head wrote:

left_half() must be a module in your first two examples. You can only
call a function in an expression, modules are statements.

If I go here https://github.com/revarbat/BOSL2/wiki/mutators.scad#left_half I see this left_half() *Type:* Function/Module *Usage:* as module * left_half(<s>, <x>) ... * left_half(planar=true, <s>, <x>) ... *Usage:* as function * left_half(<s>, <x>, path) * left_half(<s>, <x>, region) * left_half(<s>, <x>, vnf) No wonder I thought that you could use it as a function without assigning it to anything. Jon On 1/2/2021 11:44 AM, adrianv wrote: > Yes, but you didn't use it as a function. You used it as a module. There > are in fact no examples in the manual of using it as a function. Here's an > example: > > include <BOSL2/std.scad> > include <BOSL2/polyhedra.scad> > > dodecahedron = regular_polyhedron_info("vnf","dodecahedron",side=10); // > Get something to use as input > half_dodec = left_half(dodecahedron); > vnf_wireframe(half_dodec,$fn=32,r=0.2); > > Note that based on your previous post, your BOSL2 is probably older than the > introduction of the functional form of left_half. Also note that the above > code actually gives the right half. Like I said: the function version is > buggy. > > > jon_bondy wrote >> The documentation says that left_half() can be used as a function and >> provides examples... >> >> On 1/2/2021 10:22 AM, nop head wrote: >>> left_half() must be a module in your first two examples. You can only >>> call a function in an expression, modules are statements. >>> >>
NH
nop head
Sat, Jan 2, 2021 5:37 PM

Library documentation assumes that you know the OpenSCAD language.

On Sat, 2 Jan 2021 at 17:33, jon jon@jonbondy.com wrote:

If I go here

https://github.com/revarbat/BOSL2/wiki/mutators.scad#left_half

I see this

left_half()

Type: Function/Module

Usage: as module

- left_half(<s>, <x>) ...
- left_half(planar=true, <s>, <x>) ...

Usage: as function

- left_half(<s>, <x>, path)
- left_half(<s>, <x>, region)
- left_half(<s>, <x>, vnf)

No wonder I thought that you could use it as a function without assigning
it to anything.

Jon

On 1/2/2021 11:44 AM, adrianv wrote:

Yes, but you didn't use it as a function.  You used it as a module.  There
are in fact no examples in the manual of using it as a function.  Here's an
example:

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

dodecahedron = regular_polyhedron_info("vnf","dodecahedron",side=10);  //
Get something to use as input
half_dodec = left_half(dodecahedron);
vnf_wireframe(half_dodec,$fn=32,r=0.2);

Note that based on your previous post, your BOSL2 is probably older than the
introduction of the functional form of left_half.  Also note that the above
code actually gives the right half.  Like I said:  the function version is
buggy.

jon_bondy wrote

The documentation says that left_half() can be used as a function and
provides examples...

On 1/2/2021 10:22 AM, nop head wrote:

left_half() must be a module in your first two examples. You can only
call a function in an expression, modules are statements.


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

Library documentation assumes that you know the OpenSCAD language. On Sat, 2 Jan 2021 at 17:33, jon <jon@jonbondy.com> wrote: > If I go here > > https://github.com/revarbat/BOSL2/wiki/mutators.scad#left_half > > I see this > > > left_half() > > *Type:* Function/Module > > *Usage:* as module > > - left_half(<s>, <x>) ... > - left_half(planar=true, <s>, <x>) ... > > *Usage:* as function > > - left_half(<s>, <x>, path) > - left_half(<s>, <x>, region) > - left_half(<s>, <x>, vnf) > > > No wonder I thought that you could use it as a function without assigning > it to anything. > > Jon > > > On 1/2/2021 11:44 AM, adrianv wrote: > > Yes, but you didn't use it as a function. You used it as a module. There > are in fact no examples in the manual of using it as a function. Here's an > example: > > include <BOSL2/std.scad> > include <BOSL2/polyhedra.scad> > > dodecahedron = regular_polyhedron_info("vnf","dodecahedron",side=10); // > Get something to use as input > half_dodec = left_half(dodecahedron); > vnf_wireframe(half_dodec,$fn=32,r=0.2); > > Note that based on your previous post, your BOSL2 is probably older than the > introduction of the functional form of left_half. Also note that the above > code actually gives the right half. Like I said: the function version is > buggy. > > > jon_bondy wrote > > The documentation says that left_half() can be used as a function and > provides examples... > > On 1/2/2021 10:22 AM, nop head wrote: > > left_half() must be a module in your first two examples. You can only > call a function in an expression, modules are statements. > > > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
J
jon
Sat, Jan 2, 2021 5:43 PM

Understood, nop head, but the usage as a function could have been more
like "x = left_half(<x>, <x>, path)".  More clarity at a modest cost.

:)

On 1/2/2021 12:37 PM, nop head wrote:

Library documentation assumes that you know the OpenSCAD language.

On Sat, 2 Jan 2021 at 17:33, jon <jon@jonbondy.com
mailto:jon@jonbondy.com> wrote:

 If I go here

 https://github.com/revarbat/BOSL2/wiki/mutators.scad#left_half
 <https://github.com/revarbat/BOSL2/wiki/mutators.scad#left_half>

 I see this


       left_half()

 *Type:* Function/Module

 *Usage:* as module

   * left_half(<s>, <x>) ...
   * left_half(planar=true, <s>, <x>) ...

 *Usage:* as function

   * left_half(<s>, <x>, path)
   * left_half(<s>, <x>, region)
   * left_half(<s>, <x>, vnf)


 No wonder I thought that you could use it as a function without
 assigning it to anything.

 Jon
Understood, nop head, but the usage as a function could have been more like "x = left_half(<x>, <x>, path)".  More clarity at a modest cost. :) On 1/2/2021 12:37 PM, nop head wrote: > Library documentation assumes that you know the OpenSCAD language. > > On Sat, 2 Jan 2021 at 17:33, jon <jon@jonbondy.com > <mailto:jon@jonbondy.com>> wrote: > > If I go here > > https://github.com/revarbat/BOSL2/wiki/mutators.scad#left_half > <https://github.com/revarbat/BOSL2/wiki/mutators.scad#left_half> > > I see this > > > left_half() > > *Type:* Function/Module > > *Usage:* as module > > * left_half(<s>, <x>) ... > * left_half(planar=true, <s>, <x>) ... > > *Usage:* as function > > * left_half(<s>, <x>, path) > * left_half(<s>, <x>, region) > * left_half(<s>, <x>, vnf) > > > No wonder I thought that you could use it as a function without > assigning it to anything. > > Jon > >
A
adrianv
Sat, Jan 2, 2021 6:33 PM

The difference between functions and modules is syntactic.  If you write

return_value = foo(...);

then it means foo() is a function.

If you write

foo(...);

or

foo(...) something_else();

then it means foo() is a module.  It actually much more important to
understand the module-function distinction than to know what's core OpenSCAD
and what's a BOSL2 extension.  Core OpenSCAD only supplies modules for
manipulating your geometry.  BOSL2 provides matching functions.  And BOSL2,
when it provides an extension very often provides it as both a module and
function.  It would be annoying to have to give two names to almost every
module in the library.

So any time you use or assign a return value it's a function.  In these
examples foo is a function:

return = foo(...);
polygon(foo(...));  // return value is input argument to polygon
x=somefunction(arg1,foo(...),arg2,...);

If you do not assign a return value then it's a module.  In all of these
examples foo is a module.

foo(...);
linear_extrude(..) foo(...);
difference() { cube(...); foo(...);}

So yes, you do have a way of knowing whether the circle module or circle
function is used: examine the syntax of your code and see if it indicates
that circle is a module or a function in that context.  As I said, it's not
so important whether something is core OpenSCAD or not.  There's no way that
I know of to figure that out.  And it's possible for libraries to redefine
core modules.  BOSL2 does this, but it's supposed to be transparent.

Regarding left_half, the module form has been in BOSL2 for a long time, but
the function form was just contributed by somebody recently and, as I said,
is buggy.  You previously posted an example error that said "left_half" was
an unknown function.  So I expect that you'll find:

left_half() circle(1);

works because the module is defined, but

x=left_half(path3d(circle(1));

fails because you don't have the function in your BOSL2 version.  Note I
forced the circle to 3d because left_half fails on 2d inputs right now.

Almost every module in BOSL2 has a function form, so a list of "everything
that emits points" doesn't seem particularly useful.  Hmmm.  I wonder if it
would be worthwhile to write "error catcher" functions for the cases that
don't that print a message like "<foo> is only available as a module but you
used it in a function context".  I agree with you that the documentation
should show functions used in a function context.

Since you want to use skin you need to stay in the domain of paths, so you
need to use functions, as you realized, which operate on paths (point
lists).

You can get your point list any way you want.  You can write a loop and
construct it with sin and cos or other mathematical functions.  I would
imagine that using beziers might be desirable to get different spoon shapes.
But for the most basic concept of a spoon as an arc, the way to do it is to
construct the top side of the spoon and the bottom side of the spoon and
then concat them together.

include <BOSL2/std.scad>

$fn=64;

bottom = arc(angle=[210,330], d=20);
top = offset(bottom, r=1);
shape = concat(top,reverse(bottom));
polygon(shape);

Note that the top and bottom both traverse the arc in the same direction, so
you have to reverse one of the lists so that the concatenated list goes in
the right order.

jon_bondy wrote

"you don't understand what's really going on"

Yes.  Totally.

Thank you for taking so much time to explain things to me (and, I hope,
to others).

The idea that a given named entity ("circle") behaves differently in
different contexts (and in fact comes from the language intrinsics in
one case and from a library in another), and produces different output
in different contexts is powerful, but also confusing.  At least to me. 
If I had written the library, I would have created circleM() for the
module and circleF() for the function, for my own sanity.  I grew up
with Pascal, with strong type checking, so I never encountered these
puns during my career.  I understand that others in the OpenSCAD
community see things differently.

For example, at one point you say "You've used the core circle module". 
If you say so.  In a previous email you mentioned
"xscale(value,p=circle(...));" where that circle() came from BOSL2.  One
important issue for me is that I have no way of knowing which circle() I
am using.  For example, there is no way to query the compiler or the IDE
to see how it resolved those characters, is there?  Your familiarity
with the library and the underlying issues allows you to see the code
with more clarity than I do.  This may be an issue for newbies,
depending on the path they took to arrive at OpenSCAD.

It seems that there is no easy way to look at an entity and know whether
it emits geometry or lists-of-points.  Sure, you can look it up in the
documentation (if you can be SURE that the entity in question came from
that library), but I said "easy".  So maybe circleG() and circleP() for
geometry and points.

And, no, I am not implying that I believe that any of these entities
will be renamed for my benefit.  I am merely explaining how I see things.

In some languages (Pascal),  an entity is either a function or a
procedure (module).  In others (C, I believe), a function can be used as
a procedure (discarding the returned result) so there are no
procedures/modules.  So I was not expecting

x = fred()

to behave differently than

fred()

although I did expect

fred(x, p=joe)

to behave differently, because of the "p" parameter name.

It seems that if one can keep in the company of functions, then one can
always have lists-of-points.  I need to create a shape like a "C".  One
thought was to take a circle, offset it larger, subtract the original
from the larger to get a washer, and then take half of that object.  The
problem is that the offset (and maybe difference) operators are modules,
so once I leave the list-of-points domain, I am out of luck.

Maybe one useful addition to the documentation (for me) would be a
separate list of entities that emit lists-of-points.  Then I would take
that list as a the palette from which I would choose operations in my
quest for the "C" shape.

You say "It looks like your version of BOSL2 predates the existence of
the functional form of left_half because in your example below you show
an error, "unknown function left_half"." But in fact left_half() is
present, because, as I said

left_half(planar = true) circle(1);

works fine.  Confusing.  This may well be a bug.

So.  I am trying to design a configurable spoon.  The code in question
is trying to create the bowl of the spoon.  I started off trying to use
semi-circular shapes with a parametrized thickness and diameter, but
could not figure out how to generate those shapes as lists-of-points. I
assume that eventually I will refine the shape a bit.

Thanks, again, for being so helpful

Jon

On 1/2/2021 11:02 AM, adrianv wrote:

I have this feeling that you're experimenting with different variations
but
that you don't understand what's really going on.  Revar is trying to
write
tutorials now for BOSL2, and it would be good if we could understand why
you
don't understand and what to say to help you (and others) understand
better.
The tutorials are here:  https://github.com/revarbat/BOSL2/wiki/Tutorials
and maybe the Paths and Regions tutorial would help?

OpenSCAD has modules that create geometry and other modules that operate
on
geometry.  In core OpenSCAD if you invoke circle() it creates 2d
geometry.
If you give it to linear_extrude as a child then you get  a cylinder.

It is impossible to get the points out of geometry, so doing more
interesting manipulations requires that we work in a different way.  To
this
end, BOSL2 provides function versions of the core geometry modules. They
look the same, but what happens depends on context.  So with BOSL2
loaded,
circle() will sometimes make geometry (in a module context) and sometimes
produce a "path" (in a function context).    A path is BOSL2 term for an
ordered list of points.  Operating on paths requires that you use
functions,
not modules.  So this is the difference between
newpath=xscale(factor,p=some_path); and xscale(factor) some_geomety();
The
former version is passing a path (point list) to a function and getting a
new path out.  The latter is generating geometry in a module and passing
it
as a child to xscale, resulting finally in geometry as the result.  If
you
run the first one you won't see anything because no geometry has yet been
created.  You need to convert the output, newpath, into geometry, perhaps
with polygon(newpath);

So let's take a look at what you're doing below:

left_half(planar=true) circle(1);

You've used the core circle module to create geometry and you're giving
it
as a child to the left_half module which shows just the left part.

left_half(planar=true, circle(1));

You're invoking the module left_half.  We know it's a module because you
didn't assign a return value to something.  The circle(1) invocation is
the
function version of circle, so it produces a path.  So you're invoking
the
module with planar=true and a list of points.  But if you check the
manual,
you'll see that the module version does not accept a path, only two
scalars.
So you've given invalid input.  The error message need to be improved.

If you change it to

lcirc=left_half(....);

then you will get the functional form.  However, the functional form of
the
"half" operators was added recently and appears to be seriously buggy.
So
for now....don't try to use it.  It looks like your version of BOSL2
predates the existence of the functional form of left_half because in
your
example below you show an error, "unknown function left_half".

I think maybe your code would do what you want if you use arc() instead
of
circle(), since arc() can create a half circle directly.

Here's your code with arc inserted.  You didn't define wB so I'm not sure
what you're after.  You might want to explain what you're trying to do as
there might possibly be a completely different approach.

module Bowl() {
myZB = [for (i=[0:14]) -5*i];
myProfsB = [for (i=[0:14])
xscale(1, p=arc(angle=[180,360],d = wB[i], $fn = 80))];
skin(myProfsB, z=myZB, slices=10, method="reindex");
}

jon_bondy wrote

Still flailing around...

This works fine:

left_half(planar = true) circle(1);

This

left_half(planar = true, circle(1));

fails with

WARNING: vector*matrix requires vector length to match matrix row count
(3 != 100) in file
C:/Users/jon/Documents/OpenSCAD/libraries/BOSL2/mutators.scad, line 139

And this

module Bowl() {
    myZB = [for (i=[0:14]) -5*i];
    myProfsB = [for (i=[0:14])
        xscale(1, p = left_half(planar = true, circle(d = wB[i], $fn =
80)))];
    skin(myProfsB, z=myZB, slices=10, method="reindex");
    }

fails with

WARNING: Ignoring unknown function 'left_half' in file Spoon.scad, line
134

Why is left_half() recognized as a function in the 2nd example, but not
in the 3rd?

At some point, it may be easier for me to just explain what I'm trying
to do, rather than keep beating my head against this.

Jon


OpenSCAD mailing list

Discuss@.openscad

The difference between functions and modules is syntactic. If you write return_value = foo(...); then it means foo() is a function. If you write foo(...); or foo(...) something_else(); then it means foo() is a module. It actually much more important to understand the module-function distinction than to know what's core OpenSCAD and what's a BOSL2 extension. Core OpenSCAD only supplies modules for manipulating your geometry. BOSL2 provides matching functions. And BOSL2, when it provides an extension very often provides it as both a module and function. It would be annoying to have to give two names to almost every module in the library. So any time you use or assign a return value it's a function. In these examples foo is a function: return = foo(...); polygon(foo(...)); // return value is input argument to polygon x=somefunction(arg1,foo(...),arg2,...); If you do not assign a return value then it's a module. In all of these examples foo is a module. foo(...); linear_extrude(..) foo(...); difference() { cube(...); foo(...);} So yes, you do have a way of knowing whether the circle module or circle function is used: examine the syntax of your code and see if it indicates that circle is a module or a function in that context. As I said, it's not so important whether something is core OpenSCAD or not. There's no way that I know of to figure that out. And it's possible for libraries to redefine core modules. BOSL2 does this, but it's supposed to be transparent. Regarding left_half, the module form has been in BOSL2 for a long time, but the function form was just contributed by somebody recently and, as I said, is buggy. You previously posted an example error that said "left_half" was an unknown function. So I expect that you'll find: left_half() circle(1); works because the module is defined, but x=left_half(path3d(circle(1)); fails because you don't have the function in your BOSL2 version. Note I forced the circle to 3d because left_half fails on 2d inputs right now. Almost every module in BOSL2 has a function form, so a list of "everything that emits points" doesn't seem particularly useful. Hmmm. I wonder if it would be worthwhile to write "error catcher" functions for the cases that don't that print a message like "<foo> is only available as a module but you used it in a function context". I agree with you that the documentation should show functions used in a function context. Since you want to use skin you need to stay in the domain of paths, so you need to use functions, as you realized, which operate on paths (point lists). You can get your point list any way you want. You can write a loop and construct it with sin and cos or other mathematical functions. I would imagine that using beziers might be desirable to get different spoon shapes. But for the most basic concept of a spoon as an arc, the way to do it is to construct the top side of the spoon and the bottom side of the spoon and then concat them together. include <BOSL2/std.scad> $fn=64; bottom = arc(angle=[210,330], d=20); top = offset(bottom, r=1); shape = concat(top,reverse(bottom)); polygon(shape); Note that the top and bottom both traverse the arc in the same direction, so you have to reverse one of the lists so that the concatenated list goes in the right order. jon_bondy wrote > "you don't understand what's really going on" > > Yes.  Totally. > > Thank you for taking so much time to explain things to me (and, I hope, > to others). > > > The idea that a given named entity ("circle") behaves differently in > different contexts (and in fact comes from the language intrinsics in > one case and from a library in another), and produces different output > in different contexts is powerful, but also confusing.  At least to me.  > If I had written the library, I would have created circleM() for the > module and circleF() for the function, for my own sanity.  I grew up > with Pascal, with strong type checking, so I never encountered these > puns during my career.  I understand that others in the OpenSCAD > community see things differently. > > For example, at one point you say "You've used the core circle module".  > If you say so.  In a previous email you mentioned > "xscale(value,p=circle(...));" where that circle() came from BOSL2.  One > important issue for me is that I have no way of knowing which circle() I > am using.  For example, there is no way to query the compiler or the IDE > to see how it resolved those characters, is there?  Your familiarity > with the library and the underlying issues allows you to see the code > with more clarity than I do.  This may be an issue for newbies, > depending on the path they took to arrive at OpenSCAD. > > It seems that there is no easy way to look at an entity and know whether > it emits geometry or lists-of-points.  Sure, you can look it up in the > documentation (if you can be SURE that the entity in question came from > that library), but I said "easy".  So maybe circleG() and circleP() for > geometry and points. > > And, no, I am not implying that I believe that any of these entities > will be renamed for my benefit.  I am merely explaining how I see things. > > In some languages (Pascal),  an entity is either a function or a > procedure (module).  In others (C, I believe), a function can be used as > a procedure (discarding the returned result) so there are no > procedures/modules.  So I was not expecting > > x = fred() > > to behave differently than > > fred() > > although I did expect > > fred(x, p=joe) > > to behave differently, because of the "p" parameter name. > > It seems that if one can keep in the company of functions, then one can > always have lists-of-points.  I need to create a shape like a "C".  One > thought was to take a circle, offset it larger, subtract the original > from the larger to get a washer, and then take half of that object.  The > problem is that the offset (and maybe difference) operators are modules, > so once I leave the list-of-points domain, I am out of luck. > > Maybe one useful addition to the documentation (for me) would be a > separate list of entities that emit lists-of-points.  Then I would take > that list as a the palette from which I would choose operations in my > quest for the "C" shape. > > You say "It looks like your version of BOSL2 predates the existence of > the functional form of left_half because in your example below you show > an error, "unknown function left_half"." But in fact left_half() is > present, because, as I said > > left_half(planar = true) circle(1); > > works fine.  Confusing.  This may well be a bug. > > > So.  I am trying to design a configurable spoon.  The code in question > is trying to create the bowl of the spoon.  I started off trying to use > semi-circular shapes with a parametrized thickness and diameter, but > could not figure out how to generate those shapes as lists-of-points. I > assume that eventually I will refine the shape a bit. > > Thanks, again, for being so helpful > > Jon > > > On 1/2/2021 11:02 AM, adrianv wrote: >> I have this feeling that you're experimenting with different variations >> but >> that you don't understand what's really going on. Revar is trying to >> write >> tutorials now for BOSL2, and it would be good if we could understand why >> you >> don't understand and what to say to help you (and others) understand >> better. >> The tutorials are here: https://github.com/revarbat/BOSL2/wiki/Tutorials >> and maybe the Paths and Regions tutorial would help? >> >> OpenSCAD has modules that create geometry and other modules that operate >> on >> geometry. In core OpenSCAD if you invoke circle() it creates 2d >> geometry. >> If you give it to linear_extrude as a child then you get a cylinder. >> >> It is impossible to get the points out of geometry, so doing more >> interesting manipulations requires that we work in a different way. To >> this >> end, BOSL2 provides function versions of the core geometry modules. They >> look the same, but what happens depends on context. So with BOSL2 >> loaded, >> circle() will sometimes make geometry (in a module context) and sometimes >> produce a "path" (in a function context). A path is BOSL2 term for an >> ordered list of points. Operating on paths requires that you use >> functions, >> not modules. So this is the difference between >> newpath=xscale(factor,p=some_path); and xscale(factor) some_geomety(); >> The >> former version is passing a path (point list) to a function and getting a >> new path out. The latter is generating geometry in a module and passing >> it >> as a child to xscale, resulting finally in geometry as the result. If >> you >> run the first one you won't see anything because no geometry has yet been >> created. You need to convert the output, newpath, into geometry, perhaps >> with polygon(newpath); >> >> So let's take a look at what you're doing below: >> >> left_half(planar=true) circle(1); >> >> You've used the core circle module to create geometry and you're giving >> it >> as a child to the left_half module which shows just the left part. >> >> left_half(planar=true, circle(1)); >> >> You're invoking the module left_half. We know it's a module because you >> didn't assign a return value to something. The circle(1) invocation is >> the >> function version of circle, so it produces a path. So you're invoking >> the >> module with planar=true and a list of points. But if you check the >> manual, >> you'll see that the module version does not accept a path, only two >> scalars. >> So you've given invalid input. The error message need to be improved. >> >> If you change it to >> >> lcirc=left_half(....); >> >> then you will get the functional form. However, the functional form of >> the >> "half" operators was added recently and appears to be seriously buggy. >> So >> for now....don't try to use it. It looks like your version of BOSL2 >> predates the existence of the functional form of left_half because in >> your >> example below you show an error, "unknown function left_half". >> >> I think maybe your code would do what you want if you use arc() instead >> of >> circle(), since arc() can create a half circle directly. >> >> Here's your code with arc inserted. You didn't define wB so I'm not sure >> what you're after. You might want to explain what you're trying to do as >> there might possibly be a completely different approach. >> >> module Bowl() { >> myZB = [for (i=[0:14]) -5*i]; >> myProfsB = [for (i=[0:14]) >> xscale(1, p=arc(angle=[180,360],d = wB[i], $fn = 80))]; >> skin(myProfsB, z=myZB, slices=10, method="reindex"); >> } >> >> >> >> >> >> jon_bondy wrote >>> Still flailing around... >>> >>> This works fine: >>> >>> left_half(planar = true) circle(1); >>> >>> This >>> >>> left_half(planar = true, circle(1)); >>> >>> fails with >>> >>> WARNING: vector*matrix requires vector length to match matrix row count >>> (3 != 100) in file >>> C:/Users/jon/Documents/OpenSCAD/libraries/BOSL2/mutators.scad, line 139 >>> >>> And this >>> >>> module Bowl() { >>>     myZB = [for (i=[0:14]) -5*i]; >>>     myProfsB = [for (i=[0:14]) >>>         xscale(1, p = left_half(planar = true, circle(d = wB[i], $fn = >>> 80)))]; >>>     skin(myProfsB, z=myZB, slices=10, method="reindex"); >>>     } >>> >>> fails with >>> >>> WARNING: Ignoring unknown function 'left_half' in file Spoon.scad, line >>> 134 >>> >>> Why is left_half() recognized as a function in the 2nd example, but not >>> in the 3rd? >>> >>> At some point, it may be easier for me to just explain what I'm trying >>> to do, rather than keep beating my head against this. >>> >>> Jon >>> >>> > > _______________________________________________ > OpenSCAD mailing list > Discuss@.openscad > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org -- Sent from: http://forum.openscad.org/
J
jon
Sat, Jan 2, 2021 6:57 PM

In the code you provided, below, you use all functions except at the very end:

$fn=64;

bottom = arc(angle=[210,330], d=20);
top = offset(bottom, r=1);
shape = concat(top,reverse(bottom));
polygon(shape);

the result is that this fails because polygon() is not a function

myProfsB = [for (i=[0:14])
xscale(1, polygon(concat(offset(bottom, r=1), reverse(arc(angle=[210,330], d=wB[i])))))];

Any hints?

In the code you provided, below, you use all functions except at the very end: $fn=64; bottom = arc(angle=[210,330], d=20); top = offset(bottom, r=1); shape = concat(top,reverse(bottom)); polygon(shape); the result is that this fails because polygon() is not a function myProfsB = [for (i=[0:14]) xscale(1, polygon(concat(offset(bottom, r=1), reverse(arc(angle=[210,330], d=wB[i])))))]; Any hints?
A
adrianv
Sat, Jan 2, 2021 7:30 PM

If you want to see something in OpenSCAD you have to eventually run a module
that creates geometry.  In my example below I create the shape and then I
show it with polygon, which converts the point list into something you can
view.  If you want to do something else with the point list then you
shouldn't invoke polygon on it, because polygon turns the point list into
geometry.  The point list, shape, is what you were after.

In your example below remove the reference to polygon and change your second
arg to xscale to say p= to ensure it works in other BOSL2 versions.

jon_bondy wrote

In the code you provided, below, you use all functions except at the very
end:

$fn=64;

bottom = arc(angle=[210,330], d=20);
top = offset(bottom, r=1);
shape = concat(top,reverse(bottom));
polygon(shape);

the result is that this fails because polygon() is not a function

myProfsB = [for (i=[0:14])
xscale(1, polygon(concat(offset(bottom, r=1),
reverse(arc(angle=[210,330], d=wB[i])))))];

Any hints?


OpenSCAD mailing list

Discuss@.openscad

If you want to see something in OpenSCAD you have to eventually run a module that creates geometry. In my example below I create the shape and then I show it with polygon, which converts the point list into something you can view. If you want to do something else with the point list then you shouldn't invoke polygon on it, because polygon turns the point list into geometry. The point list, shape, is what you were after. In your example below remove the reference to polygon and change your second arg to xscale to say p= to ensure it works in other BOSL2 versions. jon_bondy wrote > In the code you provided, below, you use all functions except at the very > end: > > $fn=64; > > bottom = arc(angle=[210,330], d=20); > top = offset(bottom, r=1); > shape = concat(top,reverse(bottom)); > polygon(shape); > > the result is that this fails because polygon() is not a function > > myProfsB = [for (i=[0:14]) > xscale(1, polygon(concat(offset(bottom, r=1), > reverse(arc(angle=[210,330], d=wB[i])))))]; > > Any hints? > > > _______________________________________________ > OpenSCAD mailing list > Discuss@.openscad > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org -- Sent from: http://forum.openscad.org/
J
jon
Sat, Jan 2, 2021 7:51 PM

LOL.  As soon as I sent that to you, I took a walk, and almost
immediately thought "the polygon() was just there to reveal the geometry".

Thanks!

On 1/2/2021 2:30 PM, adrianv wrote:

If you want to see something in OpenSCAD you have to eventually run a module
that creates geometry.  In my example below I create the shape and then I
show it with polygon, which converts the point list into something you can
view.  If you want to do something else with the point list then you
shouldn't invoke polygon on it, because polygon turns the point list into
geometry.  The point list, shape, is what you were after.

In your example below remove the reference to polygon and change your second
arg to xscale to say p= to ensure it works in other BOSL2 versions.

jon_bondy wrote

In the code you provided, below, you use all functions except at the very
end:

$fn=64;

bottom = arc(angle=[210,330], d=20);
top = offset(bottom, r=1);
shape = concat(top,reverse(bottom));
polygon(shape);

the result is that this fails because polygon() is not a function

myProfsB = [for (i=[0:14])
xscale(1, polygon(concat(offset(bottom, r=1),
reverse(arc(angle=[210,330], d=wB[i])))))];

Any hints?


OpenSCAD mailing list
Discuss@.openscad
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

LOL.  As soon as I sent that to you, I took a walk, and almost immediately thought "the polygon() was just there to reveal the geometry". Thanks! On 1/2/2021 2:30 PM, adrianv wrote: > If you want to see something in OpenSCAD you have to eventually run a module > that creates geometry. In my example below I create the shape and then I > show it with polygon, which converts the point list into something you can > view. If you want to do something else with the point list then you > shouldn't invoke polygon on it, because polygon turns the point list into > geometry. The point list, shape, is what you were after. > > In your example below remove the reference to polygon and change your second > arg to xscale to say p= to ensure it works in other BOSL2 versions. > > > > jon_bondy wrote >> In the code you provided, below, you use all functions except at the very >> end: >> >> $fn=64; >> >> bottom = arc(angle=[210,330], d=20); >> top = offset(bottom, r=1); >> shape = concat(top,reverse(bottom)); >> polygon(shape); >> >> the result is that this fails because polygon() is not a function >> >> myProfsB = [for (i=[0:14]) >> xscale(1, polygon(concat(offset(bottom, r=1), >> reverse(arc(angle=[210,330], d=wB[i])))))]; >> >> Any hints? >> >> >> _______________________________________________ >> OpenSCAD mailing list >> Discuss@.openscad >> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > > > > > -- > Sent from: http://forum.openscad.org/ > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
J
jon
Tue, Jan 5, 2021 5:50 PM

I tried to write a function that returns a list-of-points, but I get
this error

ERROR: Assertion '(len(bad) == 0)' failed: "Profiles [1] are not a paths
or have length less than 3", in file
C:/Users/jon/Documents/OpenSCAD/libraries/BOSL2/skin.scad, line 366

TRACE: called by 'skin' in file
C:/Users/jon/Documents/OpenSCAD/libraries/BOSL2/skin.scad, line 353

TRACE: called by 'skin' in file Skin Test.scad, line 14

with this code:

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

od = 101.75;
id = od - 2 * 3.2;
th = 3;

function Semi() =
    difference(
        circle(d = id - 3*th),
        // cut out just over 1/2
        move([-990, -500], square(1000)));

skin(
    [square([2,.2], center=true), Semi()], z=[0,3],
    slices=40,sampling="length",method="reindex");

I tried to write a function that returns a list-of-points, but I get this error ERROR: Assertion '(len(bad) == 0)' failed: "Profiles [1] are not a paths or have length less than 3", in file C:/Users/jon/Documents/OpenSCAD/libraries/BOSL2/skin.scad, line 366 TRACE: called by 'skin' in file C:/Users/jon/Documents/OpenSCAD/libraries/BOSL2/skin.scad, line 353 TRACE: called by 'skin' in file Skin Test.scad, line 14 with this code: include <BOSL2/std.scad> include <BOSL2/skin.scad> od = 101.75; id = od - 2 * 3.2; th = 3; function Semi() =     difference(         circle(d = id - 3*th),         // cut out just over 1/2         move([-990, -500], square(1000))); skin(     [square([2,.2], center=true), Semi()], z=[0,3],     slices=40,sampling="length",method="reindex");