Scale Definition all model components via Ruby

Continuing the discussion from "Scale Definition" via Ruby:

I made this code that rescale all the textures of the model, its works but take long due its iterating the definition’s instances twice, I’veen noticed, it also have identation problems, but as I’m not a programer I couldn’t rewrite it.

I’ll apreciate if someone can give me hand here:

instance = Sketchup.active_model.definitions.each do |definition|
definition.instances.each do |instance|
old_transformation = instance.transformation

# We now create a new transformation that uses the origin and axes directions,
# but normalize them to unit vectors (removes the scaling).
new_transformation = Geom::Transformation.axes(
  old_transformation.origin,
  old_transformation.xaxis.normalize,
  old_transformation.yaxis.normalize,
  old_transformation.zaxis.normalize
)
# Represents the difference between the old and the new desired transformation.
transformation = new_transformation.inverse * old_transformation

instance.definition.instances.each do |i|
  i.transformation *= transformation.inverse
end

entities = instance.definition.entities
entities.transform_entities(transformation, entities.to_a)
end
end

Thanks.

The code properly indented …

... (click to expand) ...
Sketchup.active_model.definitions.each do |definition|
  definition.instances.each do |instance|
    old_transformation = instance.transformation

    # We now create a new transformation that uses the origin and axes
    # directions, but normalize them to unit vectors (removes the scaling).
    new_transformation = Geom::Transformation.axes(
      old_transformation.origin,
      old_transformation.xaxis.normalize,
      old_transformation.yaxis.normalize,
      old_transformation.zaxis.normalize
    )
    # Represents the difference between the old and the new desired transformation.
    transformation = new_transformation.inverse * old_transformation

    # Double iteration below ...
    instance.definition.instances.each do |i|
      i.transformation *= transformation.inverse
    end

    entities = instance.definition.entities
    entities.transform_entities(transformation, entities.to_a)
  end
end

Also the instance = assignment on the first line (as you have it) will not be pointing at any instance. The #each iterator for a collection always returns that collection object when done. So the reference would be pointing at the active model’s DefinitionList object.

3 Likes

Thanks DanRathbun, it works much better.

Really?

Strange as I did not really change anything, but added some spaces to the start of a few lines.

I would have thought that …

    # Double iteration below ...
    instance.definition.instances.each do |i|
      i.transformation *= transformation.inverse
    end

… should be replaced with …

    instance.transformation *= transformation.inverse

But I didn’t have a model to test on.