[Code] Skew Transformation from axes
-
In some of my plugins I've needed skewed Transformations (where all axes aren't perpendicular to each other) and so far just created a Transformation from an array where I needed it. However now I finally did what a programmer is supposed to do and made a separate method for it. Thought you guys could have use for it too!
Note that enable_skewing is by default false and must be set to true for the method not to generate identical result as the native Transformation.axes.
# Creates a Transformation defined by an origin and three axes. # Unlike native Transformation.axes this also allows optional scaling and # skewing to be enabled. # # origin - The origin as Point3d. # xaxis - The X axis as Vector3d. # yaxis - The X axis as Vector3d. # zaxis - The X axis as Vector3d. # enable_scaling - Use lengths of axes for scale (default; false). # enable_skewing - Do not force axes to be perpendicular (default; false). # # Returns a Transformation. def transformation_axes(origin, xaxis, yaxis, zaxis, enable_scaling = false, enable_skewing = false) if xaxis.parallel?(yaxis) || yaxis.parallel?(zaxis) || zaxis.parallel?(xaxis) raise ArgumentError, "Axes must not be parallel." end # Create new Vectors instead of manipulating existing. xaxis = xaxis.clone yaxis = yaxis.clone zaxis = zaxis.clone # Mimic behavior of native Transformation.axes when skewing is disabled. # Behavior found through trial and error. unless enable_skewing if (xaxis*yaxis).angle_between(zaxis) < 90.degrees # Right handed coordinate system. yaxis = zaxis*xaxis xaxis = yaxis*zaxis else # Left handed coordinate system. xaxis = zaxis*yaxis yaxis = xaxis*zaxis end end unless enable_scaling xaxis.normalize! yaxis.normalize! zaxis.normalize! end Geom;;Transformation.new([ xaxis.x, xaxis.y, xaxis.z, 0, yaxis.x, yaxis.y, yaxis.z, 0, zaxis.x, zaxis.y, zaxis.z, 0, origin.x, origin.y, origin.z, 1, ]) end
EDIT: Since Sketchucation can't display white spaces in code properly I attach the script as a file too.
-
Thanks!
-
Thanks.
PS: Use[code]
rather than [ruby:1g3n3drk]
I edited the OP... -
Thanks TIG!
-
Thanks for posting. Good to know. I think I may have come across this case some time ago, but did not think of encapsulate it as a Transformation, which is an elegant solution.
One small remark: you can check the orientation of 2 vectors by
(xaxis*yaxis) % zaxis > 0
which is equivalent, but faster than
xaxis*yaxis).angle_between(zaxis) < 90.degrees
Fredo
-
@fredo6 said:
Thanks for posting. Good to know. I think I may have come across this case some time ago, but did not think of encapsulate it as a Transformation, which is an elegant solution.
One small remark: you can check the orientation of 2 vectors by
(xaxis*yaxis) % zaxis > 0
which is equivalent, but faster than
xaxis*yaxis).angle_between(zaxis) < 90.degrees
Fredo
Thanks!
I had the feeling there had to be a more idiomatic way but didn't know it. It's at times like these I wish I had studied more math. There is no math at my school of architecture despite it being a part of the faculty of engineering at the university . All I know about cross products and matrices have I learned by making plugins and I don't think I've ever used a dot product before .
Well, at least I'm making progress. Before I even know of cross multiplication I used to offset the origin point in one axis and apply a 90 degree rotation transformation using the other axis to get a new point that I then could subtract the origin from to get a perpendicular vector.
-
...and there is the magic formula by thomthom to check if two faces are coplanar (actually have parallel planes)
face1.normal % face2.normal > 0.9999999991
Fredo
-
@fredo6 said:
...and there is the magic formula by thomthom to check if two faces are coplanar (actually have parallel planes)
face1.normal % face2.normal > 0.9999999991
Fredo
That's a nice one! When making my upright extruder I first tried the samedirection? method but it has some issues with the precision and see faces as co-planar sometimes when they aren't (just as the built in Soften Edges feature). Instead I looped the vertices on one face and used classify_point on the other face to see if any vertex position were considered not on plane. In the future I'll use this instead!
-
@fredo6 said:
...and there is the magic formula by thomthom to check if two faces are coplanar (actually have parallel planes)
face1.normal % face2.normal > 0.9999999991
Fredo
I have never known this operator "%" on vectors. Fredo, could you explain to me how it works....
-
@icehuli said:
I have never known this operator "
%
" on vectors....., could you explain to me how it works....Geom::Vector3d#%()
is an alias for thedot()
method, ie:
Geom::Vector3d#dot()@unknownuser said:
(https://en.wikipedia.org/wiki/Dot_product)":dlvmfrbf]
Geometrically, it is the product of the Euclidean magnitudes of the two vectors and the cosine of the angle between them. The name "dot product" is derived from the centered dot " ยท " that is often used to designate this operation; the alternative name "scalar product" emphasizes that the result is a scalar (rather than a vector). -
Dot product is 0 if the vectors are perpendicular.
It is 1 if they have the same direction (assuming they are normalized) and -1 for opposite direction.Fredo
-
@fredo6 said:
"assuming they are normalized"
Does normalizing first remove any variance that could throw off the comparison (with -1, 0 or 1) afterward ?
Or would it be safer to use:
vec1.perpendicular?(vec2)
vec1.parallel?(vec2) && vec1.samedirection?(vec2)
vec1.parallel?(vec2) && ! vec1.samedirection?(vec2)
I also wonder about ThomThom's magic comparison.
Is it the same on 64-bit SketchUp ?
I mean why 10 decimal places ? Is it SketchUp's internal tolerance ?
Ie, (0.001 x 0.001 x 0.001) ... which is 9 decimal places.
-
If you have a component instance that has been skewed, how do you determine which axis is skewed?
-
@fredo6 said:
...and there is the magic formula by thomthom to check if two faces are coplanar (actually have parallel planes)
face1.normal % face2.normal > 0.9999999991
Fredo
hm... this must be something from and old version of CleanUp? It was never reliable. What I do now is take all the vertices of the faces and generate a best-fit plane - then I check if each of the vertices is on the plane.
-
Well, I think I found it it an old post!. And it seems to work fine for the purpose.
Indeed there are alternate methods, the problem being to detect the false positive, that is faces that would be co-planar by the formula, but would not in the model drawn by Sketchup.
Fredo
-
@thomthom said:
@fredo6 said:
...and there is the magic formula by thomthom to check if two faces are coplanar (actually have parallel planes)
face1.normal % face2.normal > 0.9999999991
hm... It was never reliable.
I was hoping you'd answer the questions I posed (above) in this post:
http://sketchucation.com/forums/viewtopic.php?f=180%26amp;t=65068%26amp;view=unread#p597160 -
Face.normal returns a normalized vector.
-
@fredo6 said:
Well, I think I found it it an old post!. And it seems to work fine for the purpose.
Indeed there are alternate methods, the problem being to detect the false positive, that is faces that would be co-planar by the formula, but would not in the model drawn by Sketchup.
Fredo
Checking the plane might in some cases yield false for some cases where SU is able to merge. But this is rare. Comparing normal had the opposite of yielding true in cases where SU would not be able to merge.
-
@dan rathbun said:
@thomthom said:
@fredo6 said:
...and there is the magic formula by thomthom to check if two faces are coplanar (actually have parallel planes)
face1.normal % face2.normal > 0.9999999991
hm... It was never reliable.
I was hoping you'd answer the questions I posed (above) in this post:
http://sketchucation.com/forums/viewtopic.php?f=180%26amp;t=65068%26amp;view=unread#p597160As Fredo mentions, face.normal already return a unit vector. The issue is that comparing vectors is too unreliable in edge cases.
-
So what is the solution here?
Is it some extra text in the API docs explaining how best to test for face coplanarity ?
Or would it be a new API method for the
Sketchup::Face
class:
face.coplanar_with?(other_face)
or a module method?:
Geom::faces_coplanar?(face1,face2)
Advertisement