How to find the current x, y, z location

classic Classic list List threaded Threaded
26 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Re: How to find the current x, y, z location

JordanBrown
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.



_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: How to find the current x, y, z location

wangerin
In reply to this post by JordanBrown
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/

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: How to find the current x, y, z location

JordanBrown
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.

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
tp3
Reply | Threaded
Open this post in threaded view
|

Re: How to find the current x, y, z location

tp3
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.


_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
-- Torsten
Reply | Threaded
Open this post in threaded view
|

Re: How to find the current x, y, z location

JordanBrown
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
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: How to find the current x, y, z location

nophead
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 <[hidden email]> 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
[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
12