On 3/4/2019 8:40 AM, Kevin Toppenberg wrote:
One reason to what to know the global coordinates would be for
labeling. I posted questions about this recently and got good feedback.
For example, if I want to produce a printable schematic or design
document for translating the on-screen object into a real-world object
through traditional machining techniques, I need to know real world
coordinates. So if a particular edge or point is the result of
multiple transformations, it is difficult to determine that location
for labeling.
Position isn't everything. An object is rendered in a coordinate space
that is the result of the stack of transformations that are on top of
that object. Translation is one of the transformations, but only one.
Even if you could retrieve the absolute position, if you drew text at
that location it would be rotated, scaled, et cetera, and you probably
wouldn't want any of that. Even if you could retrieve the current
origin in absolute coordinates, you couldn't do much with it - if you
tried to translate( ) back to the origin, that translation would itself
be subject to the stack of transformations.
scale([5,1,1]) translate([1,1,1]) {
// the origin for this block is at [5,1,1]
origin=[5,1,1]; // imagine we could get this back from OpenSCAD
sphere(1);
translate(-origin) text("hello");
}
Note that our sphere is stretched because of the scale, but is centered
on [5,1,1].
Note that even though we attempted to translate the text back to the
origin, we failed because -[5,1,1] times the scale of [5,1,1] is
-[25,1,1], plus the "origin" is [-20,0,0]. (I don't immediately know
why it ended up starting at -15.)
Note that the text is stretched in the X axis because of the scale.
Similarly, if you tried to translate back to the origin in a rotated
frame of reference, you won't get what you expect.
rotate([0,0,90]) translate([2,0,0]) {
// the origin for this block is at [0,2,0]
origin=[0,2,0]; // imagine we could get this back from OpenSCAD
sphere(1);
translate(-origin) cube(1,center=true);
}
Note that the cube that was supposed to be translated back to the origin
ended up nowhere near the origin, because the translate(-origin) is
itself relative to a rotated coordinate system.
JordanBrown wrote
It was a thought experiment, not a real-world example. The point was
that not only is it impossible to retrieve the absolute position from
inside a series of transformations, but it is also impossible to
specify an absolute position for whatever reason.
I'm loomking for the same thing.
Is there an solution on this issue?
I have a model of a builing in openscad, an need to put markers at a number
of known locations.
The easiest way to to it would be to add them to my model, and during
compilation of the model have it echo the marker-id and location to the
console. Having x,y,z would be ok for me, but having all other details as
rotations and scale wouldn't hurt.
Some time ago I made a model of a IKEA-kitchen, that echoed a complete list
of what I had put into my model.
I then put the echoed item-numbers thru a script that fetched pricing etc
from ikea.com and ended up showing me a complete list of everything I needed
to buy including price and weight ;-)
/Henning
--
Sent from: http://forum.openscad.org/
On 2/28/2020 7:51 AM, wangerin wrote:
The easiest way to to it would be to add them to my model, and during
compilation of the model have it echo the marker-id and location to
the console. Having x,y,z would be ok for me, but having all other
details as rotations and scale wouldn't hurt.
Hey, OpenSCAD internals people...
How practical would it be to have a function that "rendered" an [x,y,z]
triple and returned an [x,y,z] triple in the top-level coordinate system?
At the time that functions and echo( ) are executed, has OpenSCAD even
constructed all of the "parent" transformations? Would it be possible
to walk up the work-in-progress tree transforming a point, at execution
time?
Not quite as general, but would it be possible to have an "object" that
didn't actually generate any geometry, but that got transformed like
geometry and, at the time that one would otherwise output geometry,
would print a value to the console?
Does OpenSCAD pass objects, transforms, and boolean operations to CGAL
for execution, or does it do the transforms itself and only pass objects
and boolean operations to CGAL? (Boolean operations are "distributive"
with respect to transforms, right? That is, transform(boolean(obj,
obj)) is the same as boolean(transform(obj), transform(obj)), right?)
I have started to look at doing actual hands-on development. I got
OpenSCAD to build under Windows, and the executable that I built ran.
Yay! But I am very far from being familiar enough with it to look at
this aspect. My first project is to try to figure out how to meld the
desires of the multi-tab-editor people with my desires as a multi-window
user so that we can both be happy.
Hi!
How practical would it be to have a function that "rendered"
an [x,y,z] triple and returned an [x,y,z] triple in the
top-level coordinate system?
Not sure, seems difficult to express that.
At the time that functions and echo( ) are executed, has
OpenSCAD even constructed all of the "parent" transformations?
No.
Would it be possible to walk up the work-in-progress tree
transforming a point, at execution time?
There's no execution time as such. It's a multi-step process.
https://github.com/openscad/openscad/blob/master/doc/OpenSCAD-compile.pdf
It might be possible to get that information at some point.
Not quite as general, but would it be possible to have an
"object" that didn't actually generate any geometry, but
that got transformed like geometry and, at the time that
one would otherwise output geometry, would print a value
to the console?
I certainly hope so, some initial discussion in this issue:
https://github.com/openscad/openscad/pull/3087
There's a number of topics to clarify, and help with that
would be appreciated.
ciao,
Torsten.
Given a set of functions identity(), rotate([xa,ya,za]),
translate([x,y,z]), et cetera, which return transformation matrices, one
could imagine:
$m = identity();
module xrot(a) {
$m = $m * rotate(a);
rotate(a) children();
}
module xtrans(off) {
$m = $m * translate(off);
translate(off) children();
}
function prender(p) = $m * p;
... and if you used xrot() and xtrans() instead of rotate() and
translate(), you could at any point
echo(prender([0,0,0]));
to print the "global" coordinates of the local origin.
Does that make sense? (See a more complete example at the bottom.)
Other notes:
So it seems pretty clear that one could construct such a mechanism on
top of current OpenSCAD, entirely in userspace. The question is whether
OpenSCAD has equivalent data already available to it.
To prove to myself that the $m scheme above was actually viable, I
implemented some of it. As long as I've written it...
ECHO: "marker", [21.2132, 21.2132, 10, 1]
Note that the unit cube emitted by whoami() has been transformed - it's
rotated and elongated - but the label is aligned with the axes and is
undistorted.
Here's the source:
$m = identity();
xrot([0,0,45]) xscale([3,1,1]) xtrans([10,0,10]) whereami("marker");
function identity() = [
[1,0,0,0],
[0,1,0,0],
[0,0,1,0],
[0,0,0,1]
];
function translate(p) = [
[1,0,0,p.x],
[0,1,0,p.y],
[0,0,1,p.z],
[0,0,0, 1]
];
function scale(s) = [
[s.x, 0, 0, 0],
[ 0, s.y, 0, 0],
[ 0, 0, s.z, 0],
[ 0, 0, 0, 1]
];
function rotatex(a) = [
[ 1, 0, 0, 0 ],
[ 0, cos(a), -sin(a), 0 ],
[ 0, sin(a), cos(a), 0 ],
[ 0, 0, 0, 1 ]
];
function rotatey(a) = [
[ cos(a), 0, sin(a), 0 ],
[ 0, 1, 0, 0 ],
[ -sin(a), 0, cos(a), 0 ],
[ 0, 0, 0, 1 ]
];
function rotatez(a) = [
[ cos(a), -sin(a), 0, 0 ],
[ sin(a), cos(a), 0, 0 ],
[ 0, 0, 1, 0 ],
[ 0, 0, 0, 1 ]
];
function rotate(xyz) =
rotatex(xyz[0])
* rotatey(xyz[1])
* rotatez(xyz[2]);
module xrot(xyz) {
$m = $m * rotate(xyz);
rotate(xyz) children();
}
module xtrans(off) {
$m = $m * translate(off);
translate(off) children();
}
module xscale(s) {
$m = $m * scale(s);
scale(s) children();
}
// Place a unit cube (in local coordinates) at the origin.
// Place a label (with global-default parameters) at that point.
// Echo the label and the global coordinates.
module whereami(label) {
p = $m * [0,0,0,1];
echo(label,p);
cube(1, center=true);
multmatrix(matrix_invert($m)) translate([p.x,p.y,p.z]) text(label);
}
// Matrix inversion, from
//https://github.com/openscad/scad-utils/pull/1/files
function remove(list, i) = [for (i_=[0:1:len(list)-2]) list[i_ < i ? i_ : i_ + 1]];
function det(m) = let(r=[for(i=[0:1:len(m)-1]) i]) det_help(m, 0, r);
function det_help(m, i, r) = len(r) == 0 ? 1 :
m[len(m)-len(r)][r[i]]*det_help(m,0,remove(r,i)) - (i+1<len(r)? det_help(m, i+1, r) : 0);
function matrix_invert(m) = let(r=[for(i=[0:len(m)-1]) i]) [for(i=r) [for(j=r)
((i+j)%2==0 ? 1:-1) * matrix_minor(m,0,remove(r,j),remove(r,i))]] / det(m);
function matrix_minor(m,k,ri, rj) = let(len_r=len(ri)) len_r == 0 ? 1 :
m[ri[0]][rj[k]]*matrix_minor(m,0,remove(ri,0),remove(rj,k)) - (k+1<len_r?matrix_minor(m,k+1,ri,rj) : 0);
The question is whether OpenSCAD has equivalent data already available to
it.
I think the answer is no at the time variables are evaluated, although I
could be wrong.
In OpenSCAD you define variables and expressions and then geometry is
instantiated with known constant values after all expressions have been
evaluated.
On Sun, 1 Mar 2020 at 23:01, Jordan Brown openscad@jordan.maileater.net
wrote:
Given a set of functions identity(), rotate([xa,ya,za]),
translate([x,y,z]), et cetera, which return transformation matrices, one
could imagine:
$m = identity();
module xrot(a) {
$m = $m * rotate(a);
rotate(a) children();
}
module xtrans(off) {
$m = $m * translate(off);
translate(off) children();
}
function prender(p) = $m * p;
... and if you used xrot() and xtrans() instead of rotate() and
translate(), you could at any point
echo(prender([0,0,0]));
to print the "global" coordinates of the local origin.
Does that make sense? (See a more complete example at the bottom.)
Other notes:
- At any point you could set $m to the identity matrix to "reset" it
for the children, so that they would report coordinates relative to *that*
coordinate system.
- Given $m, you can invert it to get a global-to-local transformation,
allowing you to then do things like add labels that are described in terms
of the global coordinate system.
So it seems pretty clear that one could construct such a mechanism on top
of current OpenSCAD, entirely in userspace. The question is whether
OpenSCAD has equivalent data already available to it.
To prove to myself that the $m scheme above was actually viable, I
implemented some of it. As long as I've written it...
ECHO: "marker", [21.2132, 21.2132, 10, 1]
Note that the unit cube emitted by whoami() has been transformed - it's
rotated and elongated - but the label is aligned with the axes and is
undistorted.
Here's the source:
$m = identity();
xrot([0,0,45]) xscale([3,1,1]) xtrans([10,0,10]) whereami("marker");
function identity() = [
[1,0,0,0],
[0,1,0,0],
[0,0,1,0],
[0,0,0,1]
];
function translate(p) = [
[1,0,0,p.x],
[0,1,0,p.y],
[0,0,1,p.z],
[0,0,0, 1]
];
function scale(s) = [
[s.x, 0, 0, 0],
[ 0, s.y, 0, 0],
[ 0, 0, s.z, 0],
[ 0, 0, 0, 1]
];
function rotatex(a) = [
[ 1, 0, 0, 0 ],
[ 0, cos(a), -sin(a), 0 ],
[ 0, sin(a), cos(a), 0 ],
[ 0, 0, 0, 1 ]
];
function rotatey(a) = [
[ cos(a), 0, sin(a), 0 ],
[ 0, 1, 0, 0 ],
[ -sin(a), 0, cos(a), 0 ],
[ 0, 0, 0, 1 ]
];
function rotatez(a) = [
[ cos(a), -sin(a), 0, 0 ],
[ sin(a), cos(a), 0, 0 ],
[ 0, 0, 1, 0 ],
[ 0, 0, 0, 1 ]
];
function rotate(xyz) =
rotatex(xyz[0])
* rotatey(xyz[1])
* rotatez(xyz[2]);
module xrot(xyz) {
$m = $m * rotate(xyz);
rotate(xyz) children();
}
module xtrans(off) {
$m = $m * translate(off);
translate(off) children();
}
module xscale(s) {
$m = $m * scale(s);
scale(s) children();
}
// Place a unit cube (in local coordinates) at the origin.
// Place a label (with global-default parameters) at that point.
// Echo the label and the global coordinates.
module whereami(label) {
p = $m * [0,0,0,1];
echo(label,p);
cube(1, center=true);
multmatrix(matrix_invert($m)) translate([p.x,p.y,p.z]) text(label);
}
// Matrix inversion, from
//https://github.com/openscad/scad-utils/pull/1/files
function remove(list, i) = [for (i_=[0:1:len(list)-2]) list[i_ < i ? i_ : i_ + 1]];
function det(m) = let(r=[for(i=[0:1:len(m)-1]) i]) det_help(m, 0, r);
function det_help(m, i, r) = len(r) == 0 ? 1 :
m[len(m)-len(r)][r[i]]*det_help(m,0,remove(r,i)) - (i+1<len(r)? det_help(m, i+1, r) : 0);
function matrix_invert(m) = let(r=[for(i=[0:len(m)-1]) i]) [for(i=r) [for(j=r)
((i+j)%2==0 ? 1:-1) * matrix_minor(m,0,remove(r,j),remove(r,i))]] / det(m);
function matrix_minor(m,k,ri, rj) = let(len_r=len(ri)) len_r == 0 ? 1 :
m[ri[0]][rj[k]]*matrix_minor(m,0,remove(ri,0),remove(rj,k)) - (k+1<len_r?matrix_minor(m,k+1,ri,rj) : 0);
OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org