On 9/2/2022 5:53 PM, Andy Little via Discuss wrote:
For now, accessing the member assignments of a module_alias with
parameters without instantiation into the CSG tree is just a case of
reusing the same syntax that you can use to access the assignments of
a module:
module television(size, b) { diagonal = sqrt( size.x^2 + size.y^2);}
|diagonal = module m([30,20]).diagonal; // an anonymous module_alias|
|m = module (size) television(size, 2); // named alias diagonal1 =
module m([30,20]).diagonal;|
So I think we're getting at least sort of close to a mutual understanding.
I see a couple of points there where I have trouble.
That last one is the hardest.
In any other OpenSCAD context, anywhere that you can have a module
invocation, you can have a { ... } block with any number of assignments
and module invocations. Also, a single module invocation is equivalent
to that same module invocation with braces around it.
That is:
translate([10,0,0]) cube(10);
translate([10,0,0]) { cube(10); }
are equivalent. Similarly:
module box(size) cube(size);
module box(size) { cube(size); }
are equivalent.
So if you can have
m = module (size) television(size);
then you could also have
m = module (size) { television(size); };
and
m = module (size) { television(size); credenza(size); };
and then what would m([30,20]).xxx mean? Would it peek inside
television's local variables, or credenza's? Or the (empty in this
case) local variables for the { ... } block?
And if there's no good answer for that (and I don't think there is), then
m = module (size) { television(size); };
is also in trouble. And if that's in trouble, by the equivalence above,
m = module (size) television(size);
is in trouble.
What I've played with so far is
o = { diagonal = sqrt(16^2 + 9^2); square([16,9]); };
which is not a module; it's an expression that evaluates some
assignments and some geometry and returns the result as an object. You
can then say "o.diagonal" and get 18-point-something.
That alone has some interesting effects, because since it is an
expression it can be returned by a function and it can use a function's
arguments in its evaluation:
function television(size) = {
diagonal = sqrt( size.x^2 + size.y^2);
square(size);
};
and then you could talk about television(size).diagonal, which would
evaluate the function, evaluate the object, evaluate the assignment and
the geometry, return "diagonal" and the square, discard the square, and
return "diagonal".
In the discussion above I've concentrated on retrieving the values
from the evaluation, and ignored the geometry. Given o above, or
the television() function, how would you get the geometry added to
the model? So far the best answer seems to be that the render()
module would be extended to accept such an object as an argument,
and would add it to the model. (Furiously handwaving whether it
would actually *render* the object, as it is defined in OpenSCAD, or
just pass it through into the CSG tree.)
It would be nice if you could take a module defined in the traditional
way, and use it directly in an expression. But that would introduce a
number of problems, and I don't immediately see any real advantages.
On 9/2/2022 8:33 PM, Jordan Brown wrote:
Clarification: when I say "That does happen", I mean evaluating a
block's assignments without evaluating its geometry. (That's changed
since 2021.01; kudos if you can identify the case and the change.)
I think the best thing to do is to try implementing this a little more, to see what is possible and what isnt . So far I have implemented some (most?) ofthe syntax, but not done much on the evaluation.
I hope that some questions are answered by the example linked below
Note that the example is running in the fork executable, but passing syntax only. Evaluation is the next part to do some work on!
module television(diagonal, thickness) {
// Ratio for a wide-screen TV
nominal_h = 9;
nominal_w = 16;
nominal_diagonal = sqrt(nominal_h^2 + nominal_w^2);
// Multiplier for *this* TV
ratio = diagonal/nominal_diagonal;
// Resulting height and width
h = nominal_h * ratio;
w = nominal_w * ratio;
cube([w, thickness, h]);
// add some feet
translate([0,0,-1]) cube([1,thickness,1]);
translate([w-1,0,-1]) cube([1,thickness,1]);
echo(h=h, w=w, diagonal=diagonal);
}
// module_alias to television
m = module (d) television(d,5);
ratio = module m(20).ratio;
// module_alias to anonymous module
m1 = module (params) { television(params.d, params.t); };
// module_alias to anonymous module
m2 = module (params, size) { television(params.d, params.t); credenza(size); };
// a module alias referring to an anonymous module
// containing a member module named member
m3 = module (params, size = [1,2] ) {
params = params;
size = size;
telly = module m2(params,size);
cube([size.x,params.d,size.y]);
module member() {
c = module cube([1,2,3]);
x = 1;
}
f = function (a,b) a+b;
};
m4 = module m3([20,20]);
diagonal = module m3([1,2]). module telly.diagonal;
telly = module m3([1,2]). module telly;
telly();
x1 = module m3([1,2]). module member.x;
c_x = module m3([1,2,3]). module member.c.x;
m3_member = module m3([1,2]). module member();
m3_member3 = module m3([1,2]). module member;
m4_size = module m4().size;
m4_sizex = module m4.size.x;