Having some transformation problems

I’ve written a script that puts down a progression of a component when it transitions from one transformation to another. It works fairly well, except if the axis in the component is different from the selection start axis as can be seen in this vid:

I’m thinking that my starting transformation is wrong, but I can’t for the life of me figure out how I can transform the initial transform so that it’s right. And if I have to change the initial, I will definitely need to change the final to agree with the change.

Anyone have any ideas? Here is the relivant code:

        # I probably need to use this somewhere, right?
        t1 = @component_instance.transformation

        from = Geom::Transformation.new(
                @ps[START ][ORIGIN],
                @ps[START ][X_AXIS] - @ps[START ][ORIGIN],
                @ps[START ][Y_AXIS] - @ps[START ][ORIGIN])

        to   = Geom::Transformation.new(
                @ps[FINISH][ORIGIN],
                @ps[FINISH][X_AXIS] - @ps[FINISH][ORIGIN],
                @ps[FINISH][Y_AXIS] - @ps[FINISH][ORIGIN])
        
        for i in (0..@@segments) # TODO: remember to change 0 back to 1
            t2 = Geom::Transformation.interpolate(from, to, i.to_f/@@segments)

            instance = entities.add_instance(component_def, t2)
        end

In case it’s not clear, @ps[START] is an array of the 1st three points picked, and @ps[FINISH] are the last.

I’m thinking that I need to do something like transform the from through t1 and have to go through an intermediate transform, but I’m still not exactly sure.

Yes.

With your tool, the user will get two points. Then likely they’ll enter a number of copies in the VCB.

(In SketchUp it’s tranditional to allow the user to type “x3” (ie a “x” prefix" to denote number of times. So your tool’s onUserText callback may need to strip off preceding characters.)

    def translate_components(start_pt, end_pt, num_copies, comp_instance)
      # Make sure the number the user gave in the VCB is an integer:
      num_copies = num_copies.to_i
      # Get a vector from the two points the user gave the tool:
      copy_vector = start_pt.vector_to(end_pt)
      # Divide this vector by the number of copies:
      incremental_length = copy_vector.length / num_copies.to_l
      # Clone the copy_vector for each translation:
      translational_vector = copy_vector.clone
      # Set the translational vector's length:
      translational_vector.length= incremental_length
      # Now use it to create a new incremental translational transform:
      t_incr = Geom::Transformation.translation(translational_vector)
      # Start with the original's transformation:
      t_copy = comp_instance.transformation
      # The model's active entities context:
      ents = Sketchup.active_model.active_entities
      # Iterate for the number of copies applying the incremental transform:
      for n in 1..num_copies
        # Multiply the previous transform by one the incremental transforms:
        t_copy = t_copy * t_incr
        # Add a new instance of the definition:
        ents.add_instance(comp_instance.definition, t_copy)
      end
    end

Now, looking at the above, we could just reuse the copy_vector and shorten it’s length rather than clone it to a new vector. But I don’t know what you might need that complete copy vector path for afterward.

Anyway … this should give you ideas.


Be aware that this copy actually creates new instances, but does not copy the current instance’s properties or any attribute dictionaries that may be attached to the original.

Since I didn’t really use the increment n variable, we could also just use …

      # Iterate for the number of copies applying the incremental transform:
      num_copies.times do
        # Multiply the previous transform by one the incremental transforms:
        t_copy = t_copy * t_incr
        # Add a new instance of the definition:
        ents.add_instance(definition, t_copy)
      end

See Integer#times

Thanks. I’ll take a look.

Great. However, outside of my simple example, it seems to go badly. Seems to be the enclosing component having a different axis? I probably have to do something with the nested component transformation, but I’m having trouble finding how to get that.

Sketchup::Model#active_path

Sketchup::Model#edit_transform

Sketchup::ComponentInstance#transformation


Be careful. When the user is within an edit context, many of the API methods return world coordinates rather than local coordinates.

Actually, I found the actual problem. However, I’m not sure of the solution. The problem wasn’t enclosing a component into another with different axes. The actual problem is that the transform being calculated is from the axes that I am selecting.

For instance, in the video, the component’s axes is the top left corner, positive xy going bottom right. The axes that I select in the first example is in the top right corner, so everything is fine. However, in the second example, I select the axes with Z pointing downwards. The interpolate function is using that axes for the transform. So, the very first interpolate (at 0) will place the component starting at the starting axes (which is at the same point, but rotated upside down). The third example, the axes is at the bottom right corner with Z pointing up, positive xy pointing top left. The component is started in that direction. Multiplying the component’s transformation by my selected one doesn’t work.

So, I need to somehow transform my specified axes to coincide with with the component’s axes.

Here is another vid showing this. The square is above the xy plane and is going down to the rectangle located on the xy plane.

Note that the component’s axes are at the bottom left, but by putting the axes at the bottom right, the new components will start at the bottom right corner of the square.