I have a question that will seem to you to be stupid after all the way we have traveled together hand in hand.
To find all the definitions of the entities present in the selection, we can write this:
def all_entities(ents)
ents.grep(Sketchup::ComponentInstance).each do |e|
p e.definition.name
all_entities(e.definition.entities)
end
end
mod = Sketchup.active_model
sel = mod.selection
selection = sel.grep(Sketchup::ComponentInstance)
all_entities(selection)
This method displays all the definitions in all nesting levels.
But I only want to display the names of the entities that are nested at the deepest level in the parent component.
Definitions are not nested, … instances are.
And your “search” method is not efficient as it iterates over the same definitions and entities multiple times.
def last_nested_entity(ents, defname)
ents.grep(Sketchup::ComponentInstance).each do |e|
e.definition.entities.grep(Sketchup::Face).each do |f|
defname << f.parent.name
end
last_nested_entity(e.definition.entities, defname)
end
end
defname = []
mod = Sketchup.active_model
sel = mod.selection
selection = sel.grep(Sketchup::ComponentInstance)
last_nested_entity(selection, defname)
p defname.uniq
nil
The array of entities is not empty because a list is given with my previous method.
and if you have a thousand faces you’ll push the parent name 1000 times…
try this…
def all_entities(ents)
ents.each do |e|
dents = e.grep(Sketchup::ComponentInstance)
if dents.empty?
p e.definition.name
else
all_entities(dents)
end
end
end
mod = Sketchup.active_model
sel = mod.selection
selection = sel.grep(Sketchup::ComponentInstance)
all_entities(selection)
I’m not certain I fully understand what you are looking for, but I think you need to test your code out on more examples. I find that it lists any definition that contains a face, not just the most deeply nested “leaf” instances.
And John is right about the high level of inefficiency when using faces to look for nested instances.
String comnparisions are slow in Ruby. First it checks if the first characters is the same. If it is Ruby checks if the next is the same. If it is Ruby checks the one after and so on.
Slightly easier to read and understand with the same results.
def last_nested_entity(ents, defname)
ents.grep(Sketchup::ComponentInstance).each do |e|
# Add definition.name if the component.definiton.entities contains any faces.
# All of David's dynamic components conform to this design requirement
# i.e. faces only exist on the terminal leaves
defname << e.definition.name if e.definition.entities.grep(Sketchup::Face).length > 0
last_nested_entity(e.definition.entities, defname)
end
end
defname = []
mod = Sketchup.active_model
sel = mod.selection
selection = sel.grep(Sketchup::ComponentInstance)
last_nested_entity(selection, defname)
p defname
p defname.length
nil
Very good case Slbaumgartner!
Yes I get what I wanted because each of the facades directly refer to the superior component name.
I agree!
There are many ways to write a method and we can always make things easier and clearer.
But the main one and that method works.
If the user create components their definitions names will be included in the array.
If facades or lines are added in the dynamic components, the parent components are quoted several times but purged thanks to “defname.uniq”!