Linear Algebra & Analytic Geometry
-
Hi Guys, I have an agony-problem with a 3D rotation.
Suppose to have a face placed generically in space, with its normal vectorv = [vx,vy,vz]
How you could rotate this face in order to put is for example in the XY plane (or anywhere else)?
-
First you have to decide the point that anchors the proposed rotation...
Perhapspt=face.bounds.center
, orpt=ORIGIN
? but you choose...
Then decide the axis of rotation.
Perhapsaxis=Y_AXIS
? [or X_ or Z_ etc]
From the face you can extractnormal=face.normal
to get its current orientation.
Soangle=normal.angle_between(axis)
Now make a:
transformation=Geom::Transformation.rotation(pt, axis, angle)
Or-angle
depending on the desired result ?
Then apply that to the geometry:
face.parent.entities.transform_entities(transformation, face)
The face should now be transformed as you hoped.
But of course, if it's connected to other geometry it could skew other things unexpectedly.
Remember you can use groups/components to separate geometry... -
Try the following --
module SUMath def self.transVector2Vector (vStart, vEnd) v1 = vStart.normalize v2 = vEnd.normalize return Geom;;Transformation.new if v1.samedirection?(v2) v3 = v2.cross(v1) v4 = v3.cross(v1) c = v2.dot(v1) s = v2.dot(v4.normalize) m1 = Geom;;Transformation.axes( [0,0,0], v1, v4, v3) m2 = Geom;;Transformation.axes( [0,0,0], [c,s,0], [-s,c,0], [0,0,1] ) mT = m1 * m2 * m1.inverse end def self.rotateFace(s_vector_end) vector_end = s_vector_end.split(",").collect { |i| i.to_f } entities = Sketchup.active_model.entities faces = entities.grep(Sketchup;;Face) face = faces[0] face_normal = face.normal t = transVector2Vector(face_normal, vector_end) entities.transform_entities(t, face) par = face.normal.samedirection?(vector_end) puts "face.normal.samedirection?([#{s_vector_end}]) = #{par}" end end # load module thru console # type SUMath.rotateFace("0,0,1") into console, or use whatever vector, # you can type repeatedly. Best to have just one face in the model...
Greg
-
@bomastudio said:
Hi Guys, I have an agony-problem with a 3D rotation.
The transform that TIG suggested (rotation) works for your need. The docs on transformations aren’t very clear, especially for people who aren’t familiar with 3D transforms or linear algebra. They’re also a little quirky, as the trans.to_a method returns a matrix that is the transpose of what I would expect. FWIW, I had a lot of linear algebra (long time ago)...
Anyway, the rotation method returns a transformation based on a rotation in a plane, which is defined by the ‘axis’ parameter, which should be the normal to the plane of rotation.
If the start and end vectors are parallel, they do not define a unique plane, hence, both my original ‘linear algebra’ algorithm and the rotation method fail. The code below accounts for that –
Greg
module SUMath def self.transVector2Vector(vStart, vEnd, pt = nil) ptRot = pt || [0,0,0] if vStart.samedirection?(vEnd) # return identity transformation, vectors are in the same direction Geom;;Transformation.new elsif vStart.parallel?(vEnd) #return 180 transformation, vStart and vEnd in opposite direction Geom;;Transformation.axes(ptRot, [-1,0,0], [0,-1,0], [0,0,-1] ) else # return rotation transform based on vStart and vEnd # vCross is normal to plane of rotation vCross = vStart.cross(vEnd) ang = vStart.angle_between(vEnd) Geom;;Transformation.rotation(ptRot, vCross, ang) end end def self.rotateFace(face, vector_end, pt = nil) # for demo purposes, the next 2 statements chose an arbitrary face # if no face passed unless face entities = Sketchup.active_model.entities faces = entities.grep(Sketchup;;Face) face = faces[0] end face_normal = face.normal t = transVector2Vector(face_normal, vector_end, pt) entities.transform_entities(t, face) # below is just for a demo confirmation sd = face.normal.samedirection?(vector_end) sVEnd = "[#{vector_end.join(",")}]" puts "face.normal.samedirection?(#{sVEnd}) = #{sd}" end end # load module thru console # type SUMath.rotateFace(nil, [0,0,1]) into console with whatever vector # you want, it can be typed as often as you'd like. # As a demo, best done with one face in the model
Advertisement