Detecting a flipped transform.
-
@unknownuser said:
> t = transformation.to_a > p t[0] < 0 # flipped on red? > p t[5] < 0 # flipped on green? > p t[9] < 0 # flipped on blue? >
I wish it was that easy. But it only works if the object hasn't been rotated.
Select something:
Sketchup.active_model.selection[0].transformation.to_a[0] #get red flip. Pos value.
Flip selection along red.
Sketchup.active_model.selection[0].transformation.to_a[0] #works. value is neg
Now rotate selection 180 around blue
Sketchup.active_model.selection[0].transformation.to_a[0] #fails. value is pos.Unless I am missing something?
Chris -
but if you flip red and rotate blue 180 it is not the same as doing a flip on green ?
-
Sketchup uses a righthanded coordinate system. Flipping (scale by -1) of an axis makes it like a lefthanded system, so why don't you just check that xaxis * yaxis == zaxis and yaxis * zaxis == xaxis. In fact you're only interested in the sign so (xaxis * yaxis).dot(zaxis) < 0 means its flipped.
-
@adamb said:
Sketchup uses a righthanded coordinate system. Flipping (scale by -1) of an axis makes it like a lefthanded system, so why don't you just check that xaxis * yaxis == zaxis and yaxis * zaxis == xaxis. In fact you're only interested in the sign so (xaxis * yaxis).dot(zaxis) < 0 means its flipped.
Ah! That is the sort of thing I am looking for. But it only works to a point. If I flip blue and then green it says the object isnt flipped. Also how can I tell which axis it is flipped around?
Thanks for the help Adam. I am a bit weak in 3d math.
Chris
-
Ah but if you 'flip' in blue and then green the object isn't flipped! You've performed a 180 around x. The math is telling the truth.. The cross product of the axes will give you the handedness of the coordinate system. Sounds like you almost want some kind of history of what happened - thats something the coordinate frame cannot give you.
Stepping back.. What are you trying to do? Is it face winding order you want? ie Whats 'front' and whats 'back'?
Adam
-
Hmm. You sure sound convincing. Let me test it out tonight and see if I can make it work. If not Ill post an example.
Thanks
Chris -
@adamb said:
Ah but if you 'flip' in blue and then green the object isn't flipped! You've performed a 180 around x. The math is telling the truth.. The cross product of the axes will give you the handedness of the coordinate system. Sounds like you almost want some kind of history of what happened - thats something the coordinate frame cannot give you.
Stepping back.. What are you trying to do? Is it face winding order you want? ie Whats 'front' and whats 'back'?
Adam
This is for my SketchyPhysics plugin. It uses the Newton physics engine and it expects its transforms to be without scale. So I am trying to produce a reliable way to convert SU objects with scaled transforms to Newton objects without.
I have figured out how to pull simple scale out of a SU transform by transforming 3 unit vectors and then checking the length. But flipped objects have eluded me. Probably because I don't fully understand whats going on when something is "flipped".
Are you saying that once an transform has been flipped more than once you cant be sure what axis it has been flipped around?
-
OK, I think I can help. First off, don't get hung up on the flipped thing. Its not a 'magic' operation - how many times have I multiplied the following number by -1?
123
You can't know. An even number of multiplies (aka flips) gets you back to where you started. Its the same with multiplying an axis.
OK, some background. The basic building block of almost all this stuff is dot product. Dot product is actually projecting 1 vector onto another to see how far along it lies. The transforms in SU are made of 4 things. An xaxis, yaxis, zaxis and a position stored in a Geom::Transformation. When you do "object.transform aMatrix" what you're actually doing is calculating how far along those 3 axes "object" lies. If you look at a vector matrix multiply it is composed of 3 dot products because all you're doing is projecting the vector onto those 3 axes in turn to give 3 numbers to make your 3d coordinate. (Its very simple but I'm amazed the number of engineers I've interviewed for jobs that haven't understood this!)
The scale of an SU transform is in the axis,yaxis,zaxis of the Transformation. So, the length of the xaxis,yaxis and zaxis tell you much scaling there is in each direction.
object.transformation.to_a[0..2] is the xaxis
object.transformation.to_a[4..6] is the yaxis
object.transformation.to_a[8..10] is the zaxis(Rather unhelpfully if you do object.transformation.xaxis you get a unit length vector..)
A normal matrix has axes of unit length (aka no scaling)
An orthogonal matrix has axes at right-angles to each other.
A orthonormal matrix is both unit length AND at right-angles.Physics systems often want orthonormal matrices. This means you'll need to record the length of each axis then normalize followed by ensuring its orthogonal by ensuring z = x * y and x = y * z
A note on crossproduct
a * b gives a vector perpendicular to a and b and of length absin(theta) where theta is the angle between a & b. What this means is if a and b are unit length but NOT perpendicular, you'll get a vector that is not unit length and it needs re-normalizing.
You can see that Orthonormalization of matrices is expensive but the quality of your results depends on it.
There's something to be going on...
Adam
-
A basic vector tutorial/refresher http://chortle.ccsu.edu/VectorLessons/vectorIndex.html
-
@adamb said:
OK, I think I can help. First off, don't get hung up on the flipped thing. Its not a 'magic' operation - how many times have I multiplied the following number by -1?
123
You can't know. An even number of multiplies (aka flips) gets you back to where you started. Its the same with multiplying an axis.
OK, some background. The basic building block of almost all this stuff is dot product. Dot product is actually projecting 1 vector onto another to see how far along it lies. The transforms in SU are made of 4 things. An xaxis, yaxis, zaxis and a position stored in a Geom::Transformation. When you do "object.transform aMatrix" what you're actually doing is calculating how far along those 3 axes "object" lies. If you look at a vector matrix multiply it is composed of 3 dot products because all you're doing is projecting the vector onto those 3 axes in turn to give 3 numbers to make your 3d coordinate. (Its very simple but I'm amazed the number of engineers I've interviewed for jobs that haven't understood this!)
The scale of an SU transform is in the axis,yaxis,zaxis of the Transformation. So, the length of the xaxis,yaxis and zaxis tell you much scaling there is in each direction.
object.transformation.to_a[0..2] is the xaxis
object.transformation.to_a[4..6] is the yaxis
object.transformation.to_a[8..10] is the zaxis(Rather unhelpfully if you do object.transformation.xaxis you get a unit length vector..)
A normal matrix has axes of unit length (aka no scaling)
An orthogonal matrix has axes at right-angles to each other.
A orthonormal matrix is both unit length AND at right-angles.Physics systems often want orthonormal matrices. This means you'll need to record the length of each axis then normalize followed by ensuring its orthogonal by ensuring z = x * y and x = y * z
A note on crossproduct
a * b gives a vector perpendicular to a and b and of length absin(theta) where theta is the angle between a & b. What this means is if a and b are unit length but NOT perpendicular, you'll get a vector that is not unit length and it needs re-normalizing.
You can see that Orthonormalization of matrices is expensive but the quality of your results depends on it.
There's something to be going on...
Adam
Thanks Adam! I am taking a fresh look at my code and I think I am beginning to understand.
Chris
-
This is digging up an old thread, but here's a snippet I think should work:
<span class="syntaxdefault"><br />module TransformationHelper<br /><br /> def flipped_x</span><span class="syntaxkeyword">?<br /> </span><span class="syntaxdefault">dot_x</span><span class="syntaxkeyword">, </span><span class="syntaxdefault">dot_y</span><span class="syntaxkeyword">, </span><span class="syntaxdefault">dot_z </span><span class="syntaxkeyword">= </span><span class="syntaxdefault">axes_dot_products</span><span class="syntaxkeyword">()<br /> </span><span class="syntaxdefault">dot_x </span><span class="syntaxkeyword">< </span><span class="syntaxdefault">0 </span><span class="syntaxkeyword">&& </span><span class="syntaxdefault">flipped</span><span class="syntaxkeyword">?(</span><span class="syntaxdefault">dot_x</span><span class="syntaxkeyword">, </span><span class="syntaxdefault">dot_y</span><span class="syntaxkeyword">, </span><span class="syntaxdefault">dot_z</span><span class="syntaxkeyword">)<br /> </span><span class="syntaxdefault">end<br /><br /> def flipped_y</span><span class="syntaxkeyword">?<br /> </span><span class="syntaxdefault">dot_x</span><span class="syntaxkeyword">, </span><span class="syntaxdefault">dot_y</span><span class="syntaxkeyword">, </span><span class="syntaxdefault">dot_z </span><span class="syntaxkeyword">= </span><span class="syntaxdefault">axes_dot_products</span><span class="syntaxkeyword">()<br /> </span><span class="syntaxdefault">dot_y </span><span class="syntaxkeyword">< </span><span class="syntaxdefault">0 </span><span class="syntaxkeyword">&& </span><span class="syntaxdefault">flipped</span><span class="syntaxkeyword">?(</span><span class="syntaxdefault">dot_x</span><span class="syntaxkeyword">, </span><span class="syntaxdefault">dot_y</span><span class="syntaxkeyword">, </span><span class="syntaxdefault">dot_z</span><span class="syntaxkeyword">)<br /> </span><span class="syntaxdefault">end<br /><br /> def flipped_z</span><span class="syntaxkeyword">?<br /> </span><span class="syntaxdefault">dot_x</span><span class="syntaxkeyword">, </span><span class="syntaxdefault">dot_y</span><span class="syntaxkeyword">, </span><span class="syntaxdefault">dot_z </span><span class="syntaxkeyword">= </span><span class="syntaxdefault">axes_dot_products</span><span class="syntaxkeyword">()<br /> </span><span class="syntaxdefault">dot_z </span><span class="syntaxkeyword">< </span><span class="syntaxdefault">0 </span><span class="syntaxkeyword">&& </span><span class="syntaxdefault">flipped</span><span class="syntaxkeyword">?(</span><span class="syntaxdefault">dot_x</span><span class="syntaxkeyword">, </span><span class="syntaxdefault">dot_y</span><span class="syntaxkeyword">, </span><span class="syntaxdefault">dot_z</span><span class="syntaxkeyword">)<br /> </span><span class="syntaxdefault">end<br /><br /> </span><span class="syntaxkeyword">private<br /><br /> </span><span class="syntaxdefault">def axes_dot_products<br /> </span><span class="syntaxkeyword">[<br /> </span><span class="syntaxdefault">xaxis</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">dot</span><span class="syntaxkeyword">(</span><span class="syntaxdefault">X_AXIS</span><span class="syntaxkeyword">),<br /> </span><span class="syntaxdefault">yaxis</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">dot</span><span class="syntaxkeyword">(</span><span class="syntaxdefault">Y_AXIS</span><span class="syntaxkeyword">),<br /> </span><span class="syntaxdefault">zaxis</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">dot</span><span class="syntaxkeyword">(</span><span class="syntaxdefault">Z_AXIS</span><span class="syntaxkeyword">)<br /> ]<br /> </span><span class="syntaxdefault">end<br /><br /> def flipped</span><span class="syntaxkeyword">?(</span><span class="syntaxdefault">dot_x</span><span class="syntaxkeyword">, </span><span class="syntaxdefault">dot_y</span><span class="syntaxkeyword">, </span><span class="syntaxdefault">dot_z</span><span class="syntaxkeyword">)<br /> </span><span class="syntaxdefault">dot_x </span><span class="syntaxkeyword">* </span><span class="syntaxdefault">dot_y </span><span class="syntaxkeyword">* </span><span class="syntaxdefault">dot_z </span><span class="syntaxkeyword">< </span><span class="syntaxdefault">0<br /> end<br /><br />end<br /><br /><br />module Example<br /><br /> def self</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">inspect_flipped<br /> tr </span><span class="syntaxkeyword">= </span><span class="syntaxdefault">Sketchup</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">active_model</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">selection</span><span class="syntaxkeyword">[</span><span class="syntaxdefault">0</span><span class="syntaxkeyword">].</span><span class="syntaxdefault">transformation<br /> tr</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">extend</span><span class="syntaxkeyword">(</span><span class="syntaxdefault">TransformationHelper</span><span class="syntaxkeyword">)<br /><br /> </span><span class="syntaxdefault">p tr</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">flipped_x</span><span class="syntaxkeyword">?<br /> </span><span class="syntaxdefault">p tr</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">flipped_y</span><span class="syntaxkeyword">?<br /> </span><span class="syntaxdefault">p tr</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">flipped_z</span><span class="syntaxkeyword">?<br /> </span><span class="syntaxdefault">end<br /><br />end<br /></span>
Advertisement