Rotate face to be perpendicular to a vector

rotation
geometry
face
vector
camera

#1

I have created a 1 sq.ft face along the XY plane using the eye of a camera as its centroid:

  model = Sketchup.active_model
  entities = model.active_entities
  view = model.active_view
  cam = view.camera
  eye = cam.eye
  target = cam.target

  pts = [
    Geom::Point3d.new(eye[0] - 0.5.feet, eye[1] - 0.5.feet, eye[2]),
    Geom::Point3d.new(eye[0] + 0.5.feet, eye[1] - 0.5.feet, eye[2]),
    Geom::Point3d.new(eye[0] + 0.5.feet, eye[1] + 0.5.feet, eye[2]),
    Geom::Point3d.new(eye[0] - 0.5.feet, eye[1] + 0.5.feet, eye[2])
  ]

  gr = entities.add_group
  square = gr.entities.add_face ( pts )

I want the square to be perpendicular to the eye-target vector, i.e., rotating the square so the eye-target vector is a normal to its plane. I’ve tried the following geometry equations with no success:

  n = [0, 0, 1] # Current normal vector to the square
  v = [target[0] - eye[0], target[1] - eye[1], target[2] - eye[2]]  # eye-target vector
  axis = [v[1], -v[0], 0] # Axis of rotation given by vectorial product (v x n)
  magnitude = Math.sqrt( axis[0]**2 + axis[1]**2 + axis[2]**2 ) # Magnitude of axis
  u = [axis[0]/magnitude , axis[1]/magnitude , axis[2]/magnitude ] # Normalized axis
  theta = -Math.acos( v[2] / Math.sqrt(v[0]**2 + v[1]**2 + v[2]**2) ) # Angle of rotation given by scalar product (v · n)

The current normal vector to the square is n = [0,0,1] since it is generated along the XY plane. To calculate the new axis of rotation, a vectorial product (v x n) is needed, and then the axis is normalized. In the same way, I calculate the angle of rotation theta by the scalar product (v · n).

Having the point, the axis, and the angle, I can set the transformation:

  tr = Geom::Transformation.rotation( eye, u, theta )
  gr.transform!(tr)

But the result is not the expected. Could you help me to localize my mistake? Any other idea to solve the issue will be very welcomed too.


#2

You might try something like this:

    model = Sketchup.active_model
    entities = model.active_entities
    view = model.active_view
    cam = view.camera
    eye = cam.eye
    target = cam.target
    pts = [
      Geom::Point3d.new(eye.x - 0.5.feet, eye.y - 0.5.feet, eye.z),
      Geom::Point3d.new(eye.x + 0.5.feet, eye.y - 0.5.feet, eye.z),
      Geom::Point3d.new(eye.x + 0.5.feet, eye.y + 0.5.feet, eye.z),
      Geom::Point3d.new(eye.x - 0.5.feet, eye.y + 0.5.feet, eye.z)
    ]
    gr = entities.add_group
    square = gr.entities.add_face ( pts )
    v1 = Geom::Vector3d.new(target.x - eye.x,target.y - eye.y,target.z - eye.z)
    v2 = square.normal
    angle = v1.angle_between(v2)
    v3 = v1 * v2
    if(v3.length != 0)
      rot = Geom::Transformation.rotation(eye,v3,-angle)
      gr.transform!(rot)
    end

Note that the square is nominally not displayed since the eye point is in the centroid of the square. Resizing the view will fix this.


#3

Thank you. Actually I realized that my equations are ok, but Geom::Transformation is only working if eye and u are Point3D and Vector3D types respectively, and not if they are standard arrays as I was using.