I read that doing an add_instance inside a group.entities is bad. I ran the following code without any obvious problems arising. Is this ok or is there a gothcha! The variable selected_group is a group of groups in the model.
model = Sketchup.active_model
selected_group = model.selection.grep(Sketchup::Group).first
if selected_group
groups_array = selected_group.entities.grep(Sketchup::Group)
puts groups_array
new_group = Sketchup.active_model.active_entities.add_group
groups_array.each{|grp| new_group.entities.add_instance grp.definition, grp.transformation}
bounds = new_group.bounds
width = bounds.width
height = bounds.height
puts width
puts height
new_group.erase!
end
`
You can’t add an instance of a group into its own entities, as that would cause an infinite recursion (nested in itself which is nested in itself…). But I don’t think that is what you are doing here, since new_group is distinct from any of the pre-existing groups in groups_array. There is nothing that requires all the instances of a group to be in the same entities collection.
However, be aware that the transformation when you add an instance into new_group.entities will act relative to those entities’ coordinates, not to the coordinates where the original instance of grp was found. That could cause the nested groups to be located differently than you expected in some cases.
One hazard I see is that SketchUp will erase an empty group the first chance it gets. That means there is a race between adding the first nested instance to new_group in the iteration and SketchUp erasing the empty new_group. The code might work one time and then mysteriously fail on others. The usual workaround is to immediately add a cpoint to a new group’s entities and then erase that cpoint later.
1 Like
That is interesting. Might that cause a bugsplat or mess up the undo stack and cause a bugsplat at a user undo? It didn’t for me but if it is intermittant I might just have been lucky.
It would cause a Ruby error when the method is invoked on an invalid object. That would stop your code and report the problem in the Ruby Console, but would not cause a BugSplat. Because it’s a race condition it most likely wouldn’t happen consistently, maybe even only rarely.
Thank you for the information. I was curious.
Now let’s talk about what your snippet was achieving. You are wanting to get the height and width of a set of all the nested groups within a selected group, omitting any primitive geometry or component instances, regardless of the selected groups location and orientation (ie, it’s transform.)
So why create new instances which modify the model ?
Instead, I would suggest instantiating a bounding box object, and add the bounds of each group in the set to this bounding box.
model = Sketchup.active_model
selected_group = model.selection.grep(Sketchup::Group).first
if selected_group
groups_array = selected_group.entities.grep(Sketchup::Group)
all_bounds = groups_array.map(&:bounds)
bb = Geom::BoundingBox.new.add(all_bounds)
width = bb.width
height = bb.height
puts width
puts height
end

2 Likes
That is exactly what I wanted. Somehow I just didn’t think of a bounding box as being a programatically modifiable object but rather as something you use only to interrogate the model. Thank you.
1 Like