Help fixing a transformation to place a component instance

Hello.
I need some help fixing a transformation to place a component instance.
I have a group within which there is:

  • a curve that is not necessarily flat.
  • A “target” component instance.

I want to place at each point of the curve a “camera” component instance that points to the origin of the “target” instance.
I created a transformation to place the instance. The instance is placed in the right place, looking straight at the target, but has had an unwanted rotation around its X axis. I would like the horizon line of the camera instance to remain horizontal.


Here is my code


def self.place_camera(group,cam_point,target)
  # cam_point is a point in the curve
  # target is the origin of the instance target

      cam_def = Sketchup.active_model.definitions.select{|d| d.name=="Camera"}[0]
      if cam_def == nil
        url = Sketchup.find_support_file("Camera.skp", "Plugins/" + FOLDER + "/skp/")
        cam_def = Sketchup.active_model.definitions.load(url)
      end

      vector = cam_point.vector_to(target)

      if vector.parallel?(X_AXIS)
        t_rot = Geom::Transformation.rotation cam_point,vector,0
      else
        t_rot = Geom::Transformation.rotation cam_point, vector * X_AXIS, vector.angle_between(X_AXIS)
      end

      vecteur_origine = cam_point.vector_to(ORIGIN)
      t_tra = Geom::Transformation.translation(vecteur_origine)
      t = t_tra * t_rot
      ti = t.inverse

      camera = group.entities.add_instance(cam_def,ti)

      return camera

    end

Thanks in advance for your help.
Simon

A model
camera.skp (84.9 KB)

and the Ruby code to manipulate the model. Open the model and paste this code into the Ruby console

module SW
  module Transformer

    # Given a start point and an end point, calculate a
    # transformation that will rotate an edge or object lying on the
    # X axis to coincide with the line from the start point 
    # to the end point. This does not rotate around the X axis
    #
    def self.calc_transform(start_point, end_point)

      # a vector from start to end
      axis1 = start_point.vector_to(end_point) 

      # create a plane perpendicular to axis1
      plane1 = [start_point, axis1]

      # define a second plane parallel to the X_Y plane at Z height
      plane2 =  [[0, 0, end_point.z] , Z_AXIS]

      # find the intersection of the two planes and calculate the cross product.
      # Note that if we are drawing on the Z_axis we use the X_AXIS for axis2
      line = Geom.intersect_plane_plane(plane1, plane2)
      axis2 = line.nil? ? X_AXIS : line[1]
      axis3 = axis1 * axis2
      
      tr = Geom::Transformation.axes(ORIGIN, axis1, axis2.reverse, axis3.reverse)
      tr = Geom::Transformation.translation(start_point) * tr
    end
  end
end

model = Sketchup.active_model
ents = model.active_entities
grp = ents[0]
model.start_operation('place cameras', true)

pts = [
  [100, -100, 0],
  [100, 0, 0],
  [100, 100, 0],
  [0, 100, 0],
  [-100, -100, 0],
  [-100, 0, 0],
  [-100, 100, 0],
  [0, -100, 0],
  [100, -100, 100],
  [100, 0, 100],
  [100, 100, 100],
  [0, 100, 100],
  [-100, -100, 100],
  [-100, 0, 100],
  [-100, 100, 100],
  [0, -100, 100],
  [100, -100, -100],
  [100, 0, -100],
  [100, 100, -100],
  [0, 100, -100],
  [-100, -100, -100],
  [-100, 0, -100],
  [-100, 100, -100],
  [0, -100, -100],
]
  
pts.each { | pt |
  tr = SW::Transformer.calc_transform( pt, [0,0,0] )
  grp2 = grp.copy
  grp2.transform!(tr)
}
  
model.commit_operation
nil
1 Like

Thanks sWilliams !
Thanks for the responsiveness!
It works Nickel!
I will adapt the concept to my code.
Good evening (here in France)!