Carsten,
A module is not a function by any name. a function ALWAYS return a value, a module does not.
Maybe you meant a procedure.
Just my $0.02,
Jean-Paul
N1JPL
On Feb 25, 2016, at 3:38 AM, arnholm@arnholm.org wrote:
On 2016-02-24 23:59, Torsten Paul wrote:
On 02/24/2016 11:35 PM, Carsten Arnholm wrote:
Aetig wrote
Somehow, at least for me, it would be easier to read and write code using
shapes as variables and manipulating them incrementally, and the same code
could look something like this:
myShape = difference() {cube(12, center=true); sphere(8);};
myShape = union() {myShape; cylinder(15, 7);};
In this case first shapes are first in the code, and they are
incrementally developed.
So is it possible to write code like in second imaginary example?
You cannot do it in the OpenSCAD language, as you are not allowed to modify
variables, and you cannot store shapes in variables.
Sure you can incrementally build objects, even with OpenSCAD
currently not being able to assign shapes to a variable.
Using modules can be even more flexible as they can be
parameterized.
Modules are functions by another name. Most languages have them, including OpenSCAD and AngelScript. Functions are named algorithms, variables are named object instances, functions and object instances are not generally interchangeable. Modifiable variables are useful for incrementally building objects like Aetig asked for, by iteration or other methods, or as sources for further duplication. Plus much more. Most languages have this ability as it is a generally useful thing.
Carsten Arnholm
OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
I have come across an odd problem.
I have a box out of which I cut various holes using difference() which is for a drill guide.
This works fine, but the side of the thing over which the guide fits is slightly slanted, making it not fit well.
So I made the cut out which creates the hole for the to-be-drilled-box into a polyhedron, so the floor could have the matching slant.
This works fine when I cut out a cube. But when I cut out a polyhedron, the bottom surface of the shape cut from the cube is see through.
Any insights would be much appreciated.
This is the code..
/////////////////////////////////
//
// Drill guide for Attenuator holes
//
////////////////////////////////
// A box with the bottom slanted, to match the slanted side of the Hammond 1590B, which is 112mm long
// on the base and 111mm long on the top. To be cut out of the main lump of plastic.
module slanted_side_box(width, depth, height, slant) {
polyhedron(
points=[[0,0,0],[0,depth,slant],[width,depth,slant],[width,0,0], [0,0,height+4],[0,depth,height+4],[width,depth,height+4],[width,0,height+4]],
faces=[[0,1,2,3],[0,4,7,3],[0,1,5,4],[1,2,6,5],[3,7,6,2],[4,5,6,7]], convexity = 10);
}
// The main box, out of which the slanted box, the kerf relief space, the guide holes and
// A couple of material saving holes are cut.
module box(height, depth, width, wall_thickness, guide_thickness, guide_radius, slant) {
$fn=100;
difference() {
// The box out of which we chop the holes
cube([width+(wall_thickness*2),depth+(wall_thickness*2),height+guide_thickness]);
union() {
// The hole into which the box fits
//translate([wall_thickness,wall_thickness,guide_thickness]) cube([width,depth,height+2]); //<--- this works.
translate([wall_thickness,wall_thickness,guide_thickness]) slanted_side_box(width, depth, height, 0.5); // <-- this not so much.
// A dip in the floor to allow shavings to not rub against the box
translate([wall_thickness*2,wall_thickness*2,guide_thickness-2]) cube([width-(wall_thickness*2),depth-(wall_thickness*2),height+8]);
// One of the bushing holes
translate([wall_thickness+20.34, wall_thickness+19,-1]) cylinder(r=guide_radius, h=guide_thickness+4);
// The other bushing hole
translate([wall_thickness+20.34+20.32, wall_thickness+19, -1]) cylinder(r=guide_radius, h=guide_thickness+4);
// Saving some print material..
translate([wall_thickness*1.5,wall_thickness*2,-1]) cube([6,depth-(wall_thickness*2), guide_thickness+2]);
// Saving some print material..
translate([width+2-wall_thickness*1.1,wall_thickness*2,-1]) cube([6,depth-(wall_thickness*2), guide_thickness+2]);
// Bottom text
translate([13,1,10]) rotate([90,0,0]) linear_extrude(2) text(text="Bottom", size=10, $fn=100);
// Top text
translate([45,depth+wall_thickness+wall_thickness-1,10]) rotate([90,0,180]) linear_extrude(2) text(text="Top", size=10, $fn=100);
};
};
};
box(height=15, width=61, depth=31.7, wall_thickness=5,guide_thickness=15,guide_radius=6.5, slant=0); // For 1/4" drill bushing
Hi David,
It's a good idea to start a new topic rather than replying to someone
else's.
You problem isa face is inside-out. You see this in View/Thrown-together as
purple;
http://forum.openscad.org/file/n16248/davidJohnson.jpg
See Point ordering for faces in
https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Primitive_Solids#polyhedron
Admin - PM me if you need anything, or if I've done something stupid...
Unless specifically shown otherwise above, my contribution is in the Public Domain; to the extent possible under law, I have waived all copyright and related or neighbouring rights to this work. Obviously inclusion of works of previous authors is not included in the above.
View this message in context: http://forum.openscad.org/Is-it-possible-to-use-shapes-as-variables-tp16223p16248.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
Hi David,
It's a good idea to start a new topic rather than replying to someone
else's.
You problem isa face is inside-out. You see this in View/Thrown-together
as
purple;
http://forum.openscad.org/file/n16248/davidJohnson.jpg
See Point ordering for faces in
https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Primitive_Solids#polyhedron
Ah. That got quite counterintuitive. The polyhedron is declared all CW on
all faces, but when taking a difference and the face becomes the inside,
so needs to be run CCW.
So constructing the polyhedron as a solid first (so you can see what
you're making) then stuffing into your solid as a difference, doesn't
work. You have to CCWize the formerly outside faces that are now inside.
Changing the first face (the bottom) to CCW works..
faces=[[0,1,2,3],[0,4,7,3],[0,1,5,4],[1,2,6,5],[3,7,6,2],[4,5,6,7]],
convexity = 10);
to
faces=[[0,3,2,1],[0,4,7,3],[0,1,5,4],[1,2,6,5],[3,7,6,2],[4,5,6,7]],
convexity = 10);
I.E. [[CCW],[CW],[CW],[CW],[CW].[CW]]
Thank you.
David
No that isn't true. You don't have to construct a polyhedron differently
when it is used in a difference. You simply had the bottom face CCW and it
needs to be CW looking from the outside, i.e. viewed from underneath.
I.e. [0,1,2,3]
is CW.
On 26 February 2016 at 05:50, dj@deadhat.com wrote:
Hi David,
It's a good idea to start a new topic rather than replying to someone
else's.
You problem isa face is inside-out. You see this in View/Thrown-together
as
purple;
http://forum.openscad.org/file/n16248/davidJohnson.jpg
See Point ordering for faces in
Ah. That got quite counterintuitive. The polyhedron is declared all CW on
all faces, but when taking a difference and the face becomes the inside,
so needs to be run CCW.
So constructing the polyhedron as a solid first (so you can see what
you're making) then stuffing into your solid as a difference, doesn't
work. You have to CCWize the formerly outside faces that are now inside.
Changing the first face (the bottom) to CCW works..
faces=[[0,1,2,3],[0,4,7,3],[0,1,5,4],[1,2,6,5],[3,7,6,2],[4,5,6,7]],
convexity = 10);
to
faces=[[0,3,2,1],[0,4,7,3],[0,1,5,4],[1,2,6,5],[3,7,6,2],[4,5,6,7]],
convexity = 10);
I.E. [[CCW],[CW],[CW],[CW],[CW].[CW]]
Thank you.
David
OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
On 2016-02-26 04:42, Jean-Paul Louis wrote:
Carsten,
A module is not a function by any name. a function ALWAYS return a
value, a module does not.
Jean-Paul,
You are of course correct about function/module strictly within the
OpenSCAD language, but I was speaking generally. Also, a module in
OpenSCAD definitely returns a value, it returns a geometric object. It
is just that it is returned implicitly rather than explicitly and you
cannot store the result in a variable.
Maybe you meant a procedure.
Not really. An OpenSCAD module maps to a function in AngelScript CSG.
Similarly, in C or C++ functions may or may not return values. There are
no procedures in either of these languages. The difference in
terminology and similarity of concept was my point ("A module is a
function by another name"). The terminology is slightly different in
different languages (Pascal has procedures, Fortran has subroutines).
All of them are named algorithms in one way or another.
Carsten Arnholm
Aetig wrote
You cannot currently write
myShape = difference() {cube(12, center=true); sphere(8);};
although that is being considered as a future extension.
Instead, you must write
module myShape() difference() {cube(12, center=true); sphere(8);};
and write "myShape()" instead of "myShape" to reference the definition.
This is more verbose, but is otherwise equivalent to "myShape = ..."
cylinder(15, 7);
difference() {cube(12, center=true); sphere(8);}
Yes, but you need to use a slightly different style than you are used to.
OpenSCAD is a declarative, "single-assignment" language. A variable can
only be assigned once. Another way to think of this: "x = y;" is a
definition of x.
You can still write a sequence of definitions, and define your shape
incrementally, but each definition must have a different name. That's only
a small change from the way you'd code this in an imperative language.
If we supported shape variables, you'd write:
myShape = difference() {cube(12, center=true); sphere(8);};
myShape2 = union() {myShape; cylinder(15, 7);};
But since you need to use module definitions, you instead will write:
module myShape() difference() {cube(12, center=true); sphere(8);};
module myShape2() union() {myShape(); cylinder(15, 7);};
You need to know 2 more things to make the transition from an imperative to
a declarative style: how to code incremental definitions involving
conditionals, and involving loops.
In an imperative language, using conditionals you might write:
myShape = difference() {cube(12, center=true); sphere(8);};
if (flag) myShape = union() {myShape; cylinder(15, 7);};
In OpenSCAD, you can't update a variable from inside an if statement, but
you can do something equivalent by rearranging the code. First, in variable
form (not yet valid OpenSCAD):
myShape = difference() {cube(12, center=true); sphere(8);};
myShape2 = union() {myShape; if (flag) cylinder(15, 7); }
In the second definition, union has 1 argument if flag is false, or 2
arguments if flag is true.
And now in module form:
module myShape() difference() {cube(12, center=true); sphere(8);};
module myShape2() union() {myShape(); if (flag) cylinder(15, 7); }
In an imperative language, using a loop, you might write:
myShape = sphere(10, center=true);
for (i = [0:60:300]) {
bump = rotate(i) translate([10,0,0]) sphere(2, center=true);
myShape = union() {myShape; bump;};
}
In OpenSCAD, you can't update a variable from inside a loop, but by
rearranging the code, you can do something equivalent. First in variable
form (not yet valid OpenSCAD):
myShape = sphere(10, center=true);
bumps = for (i = [0:60:300]) {
rotate(i) translate([10,0,0]) sphere(2, center=true);
}
myShape2 = union() {myShape; bumps;}
and now in module form:
module myShape() sphere(10, center=true);
module bumps() for (i = [0:60:300]) {
rotate(i) translate([10,0,0]) sphere(2, center=true);
}
module myShape2() union() {myShape(); bumps();}
To summarize, there are 3 basic idioms involved in incrementally defining a
shape: sequences of definitions, conditionals, and loops. I've shown how to
translate those 3 idioms from an imperative language to a declarative
language like OpenSCAD. There's nothing missing from OpenSCAD, relative to
an imperative language, you just need to write your code slightly
differently.
Carsten said: "You cannot do it in the OpenSCAD language, as you are not
allowed to modify variables, and you cannot store shapes in variables."
That may be overstating the issue. The same concepts can be expressed; it's
just that the idioms and syntax are different. Once we have shape
variables, we'll be able to write terser code, but the issue here is
verbosity, not expressibility.
Yes, well that pretty much explains the model differences in the two
previous examples.
On 25. feb. 2016 15:02, arnholm@arnholm.org wrote:
On 2016-02-25 13:53, Stefan Göttsche wrote:
so I would have assumed that when writing cylinder(15,7); openSCAD
interprets the single r as r=r1=r2 and gives me a cylinder, 15 high, 7
in diameter?
cylinder(15,7) in OpenSCAD is equivalent to cylinder(15,r1=7) which
will give you a cone with default r2=1. You can, however, write
cylinder(15,r=7) to get a proper cylinder (constant radius).
What manual does not state here, although perhaps it should, is that to use
alternates such as r, d, d1, d2 they must be named, as they are in the
examples.
In AngelScript CSG, cone and cylinder are distinct types, a cylinder
will always have constant radius:
cylinder@ c1 = cylinder(15,7); // a cylinder: h, r
cone@ c2 = cone(15,7,1); // a cone: h, r1, r2
Carsten Arnholm
http://arnholm.org/
OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org