sketchucation logo sketchucation
    • Login
    ℹ️ Licensed Extensions | FredoBatch, ElevationProfile, FredoSketch, LayOps, MatSim and Pic2Shape will require license from Sept 1st More Info

    Linear Algebra & Analytic Geometry

    Scheduled Pinned Locked Moved Developers' Forum
    4 Posts 3 Posters 585 Views 3 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • bomastudioB Offline
      bomastudio
      last edited by

      Hi Guys, I have an agony-problem with a 3D rotation.
      Suppose to have a face placed generically in space, with its normal vector

      v = [vx,vy,vz]

      How you could rotate this face in order to put is for example in the XY plane (or anywhere else)?

      1 Reply Last reply Reply Quote 0
      • TIGT Offline
        TIG Moderator
        last edited by

        First you have to decide the point that anchors the proposed rotation...
        Perhaps pt=face.bounds.center, or pt=ORIGIN ? but you choose...
        Then decide the axis of rotation.
        Perhaps axis=Y_AXIS ? [or X_ or Z_ etc]
        From the face you can extract normal=face.normal to get its current orientation.
        So angle=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...

        TIG

        1 Reply Last reply Reply Quote 0
        • M Offline
          MSP_Greg
          last edited by

          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

          1 Reply Last reply Reply Quote 0
          • M Offline
            MSP_Greg
            last edited by

            @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
            
            1 Reply Last reply Reply Quote 0
            • 1 / 1
            • First post
              Last post
            Buy SketchPlus
            Buy SUbD
            Buy WrapR
            Buy eBook
            Buy Modelur
            Buy Vertex Tools
            Buy SketchCuisine
            Buy FormFonts

            Advertisement