How to find all components or entities in a given layer

I need to find all the specified components in the model, the current method I am using iterates through all the entities and can cause slowdown, here is my code:

ent.each do |entity|
  if entity.typename=="ComponentInstance"
    if entity.description=="#{faceIds[i]}"
      aa = entity.get_attribute "coordinate","allcoordinate"
      finalInfo_renew[i]<<aa            
    end
  end    
end

Now that the model is built with components placed in the same layer, how can you quickly find all the components in a layer without having to traverse the entire model.

You don’t have to create more than one thread, if you made a mistake or you want to add something you can edit it, but its not necessary to create a new one it´s against the forum rules.

1 Like

This should work. Change “Existente” by your target layer name.

model = Sketchup.active_model

desiredData = [] 
layerNameToMatch = 'Existente'

model.entities.grep(Sketchup::ComponentInstance).each do |entity|
  desiredData.append(entity) if entity.layer == layerNameToMatch
end

all your components will be in “desiredData” array

https://www.thomthom.net/thoughts/2011/12/never-ever-use-typename/

Much better to use grep as @rtches suggesting. However:

layerNameToMatch is a String, Comparing it to Sketchup::Layer will not give the desired result.
It should be like:

model = Sketchup.active_model

desiredData = [] 
layerToMatch = model.layers[ 'Existente' ]

model.entities.grep(Sketchup::ComponentInstance).each do |entity|
  desiredData.append(entity) if entity.layer == layerToMatch
end

or ( but I guess, it is less effective because string comparison always slow)

model = Sketchup.active_model

desiredData = [] 
layerNameToMatch = 'Existente'

model.entities.grep(Sketchup::ComponentInstance).each do |entity|
  desiredData.append(entity) if entity.layer.name == layerNameToMatch
end

My idea, contrary to Rafa, is not only the root entities but instances in the entire model will be considered.

model = Sketchup.active_model
layerToMatch = model.layers['Existente']
definitions = model.definitions
desiredData = definitions.flat_map(&:instances).select{|instance|
  instance.layer == layerToMatch
}

desiredData is an Array of all the instances of components and groups in the model, which has been associated to Tag (Layer) named as ‘Existente’.

Some References:
The Model #definitions method retrieves a definition list containing all of the component definitions in the model.

The ComponentDefinition #instances method is used to return any array of ComponentInstancesfor this ComponentDefinition.

https://ruby-doc.org/core-2.7.1/Enumerable.html#method-i-flat_map

https://ruby-doc.org/core-2.7.1/Array.html#method-i-select

2 Likes

BTW.:

Components are not placed in Layer (Tag) but Layer (Tag) is associated or set to it…

1 Like

Thank you all for your answers, I need to make sure of one thing: can I find all the entities in a layer by the layer name

Again wrong wording: entities are NOT “in a layer”! See:
Class: Sketchup::Layer — SketchUp Ruby API Documentation
By default, a SketchUp model has one layer, Layer 0 (Named “Untagged” in the UI since SketchUp 2020), which is the base layer. You can’t delete or rename Layer 0. Unlike certain other CAD software packages, entities associated with different layers in SketchUp still intersect with each other. (If you want collections of entities to not intersect, place them in Groups instead.)


You can find all entities where the layer of the entity is set to that layer which have a certain name.

for example, something like this:

def find_ents_by_layer( ents, layer_to_match )
  ents.each{|ent|
    next unless ent.respond_to?(:layer)
    @ents_associated_to_layer<<ent if ent.layer == layer_to_match
    if ent.is_a?(Sketchup::Group) || ent.is_a?(Sketchup::ComponentInstance)
      ent.make_unique if ent.is_a?(Sketchup::Group)
      definition = ent.definition
      if !@used_defs.include?(definition)
        find_ents_by_layer( definition.entities, layer_to_match )
        @used_defs<<definition
      end
    end
  }
end

def collect_ents_by_layer( layer_name )
  model = Sketchup.active_model
  entities = model.entities
  layer_to_match = model.layers[layer_name]
  @ents_associated_to_layer = []
  @used_defs = []
  find_ents_by_layer( entities, layer_to_match )
  @ents_associated_to_layer
end
my_ents = collect_ents_by_layer( 'My_layername' )
1 Like