Z axis transformation


I’m working on a simple script that randomizes the z axis for an array of components between set floor and ceiling values and I’ve got everything down except for the part where the individual entities actually make the transformation. Here’s what I’ve got so far.

model = Sketchup.active_model # Open model
entities = model.entities # All entities in model
selection = model.selection # Current selection

selection.each do |entity|
  point = Geom::Point3d.new 0, 0, rand(10) * -1
  t = Geom::Transformation.new point
  z = t.zaxis
  puts entity

At this point I get lost. What I would expect to do if I were working in a vacuum would be to find the variable wherein the coordinates of the entity’s model space origin are stored, after which I would adjust the z-axis value appropriately. Ideas?


Most primitive Entities do not have an associated Transformation. Groups and ComponentInstances have a Transformation and can be altered using the #transform! or #transformation= method. Note also that there are some kinds of Entities that can not be Transformed. Depending how you selected, this might not be a problem, but be aware that it could cause a method not found exception in your .each iterator.

To apply a Transformation to primitive Entities (Edges, Faces, Curves), you have to access their parent Entities collection and invoke either Entities#transform_entities or Entities#transform_by_vectors. The latter might be best for your situation since it accepts an Array of entities and an Array of vectors by which to move each Entity. The vectors could be z-direction offsets.

So, you should filter the Entities in your selection according to Class and then apply the appropriate method to each kind.


Filtering. The Ruby Enumerable module is mixed into most collection classes. It’s grep method is quite fast.

groups = entities.grep(Sketchup::Group)
compis = entities.grep(Sketchup::ComponentInstance)
others = ( entities.to_a - groups ) - compis

The grep method also has a block form, which you can use to process the filtered set.

entities.grep(Sketchup::Group) {|grp|
  base_pt = grp.transformation.origin
  dist = Sketchup.format_length(ORIGIN.distance(base_pt))
  puts "Distance from World Origin to Group #{grp.object_id}, is #{dist}"

BTW, there is also an srand() global defined in module Kernel, to seed the random number generator.