Is there a way to create a copy of all component instances and combine them into one group/component

Say I have 4 component instances. Is there a way I can combine them into one group or component while leaving the instance intact.

component1 # component instance
component2 # component instance
component3 # component instance
component4 # component instance

components = [component1,component2,component3,component4]
copies = [] # empty array to recieve copies.
components.map{|c| copies.push(c.copy)} # create copies of all components
# stuck here

Once again you are using the map iterator incorrectly. The map iterator itself returns the new array object. So you do not create an empty array first, and in the iterator block the code returns new members that are stuffed into the result array.

In other words, you are mapping the components array to a new array, using the result of each block iteration.

copies = components.map { |c| c.copy }
Re: block spacing (click to expand) ...

(BTW, according to good coding styles, you are supposed to space curly brace blocks the same as we would doend blocks. This means a space before and after the {, and a space between the parameter list | and the expression, and a space before the closing }. Running all your statements together omitting as much spaces as you can just serves to make your code less readable [sight fatigue] and does not really help the parser.)

Now as you noticed there really is not a copy method (yet) for component instances (although it has been requested.)

So this means you must code your own and yes there is a way (and it’s straight forward and basically simple.)

I want you to at least try to solve this on your own. So give it a go and post your attempt here.

I’ll give you a hint. Both group instances and component instances are located in 3D space using a transformation. So you will need to reference and use each original instance’s transformation.

If the component instances to be copied are in model coordinates then you would do well to have the new group container’s origin at the model origin.

I tried this. But I can’t get it to produce a manifold that I can use to trim the group I am trying to trim.

def make_group_from_copies(copies)
  model = Sketchup.active_model
  ents = model.entities
  temp = ents.add_group
  copies.map{|c|
    temp.entities.add_instance(c.definition,IDENTITY)
  }
  return temp.component if temp.manifold?
  #return temp if temp.manifold?
end

# get existing components
components = ents.grep(Sketchup::ComponentInstance)

# make a copy of the components
copies = components.map{|c| c.copy}

# create a new group
group_to_be_trimmed = Sketchup.active_model.entities.add_group

### make group solid here ###

# combine all copies into one group
temp = make_group_from_copies(copies)

#use the combined group to trim group_to_be_trimmed 
temp.trim(group_to_be_trimmed)

(1) If you want a trim component, then just create a component definition and add your instances to it’s entities, then add an instance of the component to the model’s entities.

(2) You’ve written a method that needs to get called, so it’s code gets executed.

(3) The temp reference is local to the method. Your snippet is referencing it out of scope.

(4) Why are you still using the map iterator ?

(5) In order to use boolean trim, all the copies must themselves be manifold, and they must be exploded within the new trim context. Ie, you cannot have nested solids. The act of exploding them must also not cause the resultant trim context (whether it be a component instance or a group instance) to become non-manifold.

Sorry, I just made that snippet so you could see what I am doing. I think the outer_shell method is what I was looking for. I really only need to combine two instances that I will use to trim something else.