

I want to have a series of labels positioned around a center like spokes on a bicycle wheel.
So I could do this:
for (angle = [0:15:359]) rotate([0,0,angle]) translate([30,0,0]) text("MyLabel");
When I do this, the text "MyLabel" is rotated in addition to the position being rotated. But I want them all facing the same way. So what I really want is just for the position to be rotated.
It seems that this ought to be possible (but it is a syntax error):
for (angle = [0:15:359]) { pos = rotate([0,0,angle]) [30,0,0]; translate(pos) text("MyLabel"); }
I know the code below works, but it seems clunky to me. What I really want is to be able to calculate the rotated position, and then put whatever I want at that point.
At one point, I figured out how to build up an array at runtime. But it involved recursive code and I can't remember now how I did it. But if I figured that out again, I suppose I could build up the rotated points in the array, and then iterate through that.
Questions: 1. How would I best achieve this?
2. Why doesn't my solution of pos = rotate([0,0,angle]) [30,0,0]; work? Does Rotate() only act on objects? What makes an object?
3. What can be assigned to a variable?
Thanks in advance
Kevin T
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org


1. I would do that as rotate, translate, rotate as you have done but I would use rotate(angle) as a shortcut. When passed a single number rotate rotates around z.
You could make a module that does it.
module rotate_to(pos, angle) rotate(angle) translate(pos) rotate(angle) children();
for (angle = [0:15:359]) rotate_to([0, 0, 30], angle) text("MyLabel");
2. It does not work because you can only assign an expression to a variable but rotate() is a module that acts on its children. Its children are other modules that do transformations or create geometry. You can't assign geometry to variables but you can encapsulate it a module and reuse it. Similarly you can put expressions in functions and reuse them.
3. Only expressions can be assigned to variables. The result must be a number or a string, list, range, etc. On Wed, 20 Feb 2019 at 16:27, Kevin Toppenberg < [hidden email]> wrote: I want to have a series of labels positioned around a center like spokes on a bicycle wheel.
So I could do this:
for (angle = [0:15:359]) rotate([0,0,angle]) translate([30,0,0]) text("MyLabel");
When I do this, the text "MyLabel" is rotated in addition to the position being rotated. But I want them all facing the same way. So what I really want is just for the position to be rotated.
It seems that this ought to be possible (but it is a syntax error):
for (angle = [0:15:359]) { pos = rotate([0,0,angle]) [30,0,0]; translate(pos) text("MyLabel"); }
I know the code below works, but it seems clunky to me. What I really want is to be able to calculate the rotated position, and then put whatever I want at that point.
At one point, I figured out how to build up an array at runtime. But it involved recursive code and I can't remember now how I did it. But if I figured that out again, I suppose I could build up the rotated points in the array, and then iterate through that.
Questions: 1. How would I best achieve this?
2. Why doesn't my solution of pos = rotate([0,0,angle]) [30,0,0]; work? Does Rotate() only act on objects? What makes an object?
3. What can be assigned to a variable?
Thanks in advance
Kevin T
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org


1. How would I best achieve this?
function rotZ(a,p) = [[cos(a), sin(a),0],[sin(a),cos(a),0],[0,0,1]]*p;
for (angle = [0:15:359]) { pos = rotZ(angle,[30,0,0]); translate(pos) text("MyLabel"); }
2. Why doesn't my solution of pos = rotate([0,0,angle]) [30,0,0]; work? Does Rotate() only act on objects? What makes an object?
rotate() is a module and only applies to objects, things like modules or primitive solids (like cube()). 3. What can be assigned to a variable?
Just values like numbers, strings, lists.
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org


I see that others have already answered, so at the risk of repetition here's
my approach which has some things in common with previously posted answers
but is also a little bit different.
module circle_distribute(radius, number)
{
for(angle=[0:360/number:359])
translate([radius*cos(angle), radius*sin(angle)])
children();
}
circle_distribute(30,24) text("label");
The circle_distribute module can operate on any object or collection of
objects in braces and will distribute them around the circle.

Sent from: http://forum.openscad.org/_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org


On 2/20/2019 8:25 AM, Kevin Toppenberg
wrote:
I know the code below works, but it seems clunky to
me. What I really want is to be able to calculate the rotated
position, and then put whatever I want at that point.
That's the simplest answer I come up with. For more complex
scenarios involving multiple transformations, I'm not sure but a
scheme like you describe might be simpler.
OpenSCAD could, but does not, have a way to feed a point through
a series of translations to return a new point. You can do the
math yourself. If you want to do the math yourself, read up on
transformation matrices. The Wikipedia
article is a bit mathheavy but gives some examples. The OpenSCAD
documentation on multmatrix gives a few examples in the
context of the multmatrix operator. OpenSCAD will do the matrix
multiplication required.
It would be easy to build up a function library that did
transformations. The various transformation matrices are
straightforward to look up, and you combine them and apply them to
points with matrix multiplication. At the risk of betraying my
somewhat weak math, just for fun, I threw together such a library
at the end of this message. I supply only rotate, translate, and
scale; the rest are left as an exercise for the reader.
At one point, I figured out how to build up an array at
runtime. But it involved recursive code and I can't
remember now how I did it. But if I figured that out again,
I suppose I could build up the rotated points in the array,
and then iterate through that.
You could. And there's a decent chance that you could do it with
a list
comprehension rather than recursion.
But I suspect that building up an array and then walking through
it would be more work than just generating the objects while you
iterate the first time.
Questions:
1. How would I best achieve this?
The double rotate scheme is the best I come up with for this
simple case.
2. Why doesn't my solution of pos = rotate([0,0,angle])
[30,0,0]; work? Does Rotate() only act on objects? What
makes an object?
Rotate is a transformation operator, not a function. Yes, it
acts only on objects. Objects are the 3D and 2D primitives (cube,
sphere, et cetera) and userdefined modules made up of those
things.
This is a fundamental dichotomy in OpenSCAD. Objects represent
2D and 3D "things" in the resulting model. Values are ... not;
although you can echo them out to the console they don't directly
represent results in the model.
3. What can be assigned to a variable?
Values :)
Numbers, strings, booleans, ranges, vectors, and the undefined
value.
Not objects, though of course you can represent protoobjects in
coordinate form in vectors.
Here's that library...
//
// Library to perform various transformations on an [x,y,z] point.
//
// Define the various transformation matrices.
function matrix_rotate_x(a) = [
[ 1, 0, 0, 0 ],
[ 0, cos(a), sin(a), 0 ],
[ 0, sin(a), cos(a), 0 ],
[ 0, 0, 0, 1 ]
];
function matrix_rotate_y(a) = [
[ cos(a), 0, sin(a), 0 ],
[ 0, 1, 0, 0 ],
[ sin(a), 0, cos(a), 0 ],
[ 0, 0, 0, 1 ]
];
function matrix_rotate_z(a) = [
[ cos(a), sin(a), 0, 0 ],
[ sin(a), cos(a), 0, 0 ],
[ 0, 0, 1, 0 ],
[ 0, 0, 0, 1 ]
];
function matrix_translate(o) = [
[ 1, 0, 0, o.x ],
[ 0, 1, 0, o.y ],
[ 0, 0, 1, o.z ],
[ 0, 0, 0, 1 ]
];
function matrix_scale(s) = [
[ s.x, 0, 0, 0 ],
[ 0, s.y, 0, 0 ],
[ 0, 0, s.z, 0 ],
[ 0, 0, 0, 1 ]
];
// Transform a point to and from the 1x4 form needed for transformation.
function p34(p) = concat(p, 1);
function p43(p4) = [ for(i=[0:2]) p4[i] ];
// Rotate a point around the origin according to the specified angles.
// Angles are rotation around the x axis, y axis, and z axis.
// Rotations are applied in that order.
// The righthand rule is used.
function rotate(p, angles) = p43(
matrix_rotate_z(angles.z)
*matrix_rotate_y(angles.y)
*matrix_rotate_x(angles.x)
*p34(p));
// Translate a point by a specified offset.
function translate(p, o) = p43(matrix_translate(o) * p34(p));
// Translate a point by a specified [scalex, scaley, scalez].
function scale(p, s) = p43(matrix_scale(s) * p34(p));
angles = [0, 90, 0];
p = [1,1,1];
echo(rotate(p, [0, 0, 90]));
echo(translate(p, [1, 2, 3]));
echo(scale(p, [1, 2, 3]));
My transformation matrix math is really rusty... I'd be
interested in code review of the above.
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org


nophead wrote
> 1. I would do that as rotate, translate, rotate as you have done but I
> would use rotate(angle) as a shortcut. When passed a single number rotate
> rotates around z.
>
> module rotate_to(pos, angle)
> rotate(angle)
> translate(pos)
> rotate(angle)
> children();
>
> for (angle = [0:15:359])
> rotate_to([0, 0, 30], angle)
> text("MyLabel");
Nice! I already made something useful with it.
module rotate_to(pos, angle) {
rotate(angle)
translate(pos)
rotate(angle)
children();
}
for (angle = [1:1:12])
rotate_to([0, 100, 0], (angle * 30))
scale([2,2,2])
text(str(angle));

Sent from: http://forum.openscad.org/_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org


On 3/5/2019 8:38 AM, lar3ry wrote:
Nice! I already made
something useful with it.
module rotate_to(pos, angle) {
rotate(angle)
translate(pos)
rotate(angle)
children();
}
for (angle = [1:1:12])
rotate_to([0, 100, 0], (angle * 30))
scale([2,2,2])
text(str(angle));
Cool. Suggest adding halign="center" and valign="center" to the
text( ) invocation so that the numbers are centered on their
target locations.
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

