Count the total number of faces in a model of a really complex model?


#1

Hi guys! I need to count the total number of faces on the entire model of a very complex architectural model, With probably hundreds of groups and layers. I Have tried : looping though the model’s entities but the face count doesn’t seem to tally with the Model info-Statistics. I am very new to all of this, Can you guys help with a snippet? Thanks in advance.


#2

if they are all groups and components, something like…


model = Sketchup.active_model
defs = model.definitions
list =[]
defs.each{|d|
            next if d.image?
            ins=[]
            d.instances.each{|i|ins << i}
            list << d.instances unless ins.empty?
          }
faces = []

list.each{|c| c[0].definition.entities.grep(Sketchup::Face).find_all{|e| faces << e } }

faces.length

john


#3

@john_drivenupthewall, Thanks a lot man! One more question. Will it also take into account the faces that are not currenly in any groups? If not how can I get the total counts of all of them?


#4

You maybe could do that too:

faces = 0
Sketchup.active_model.entities.each do |e|
  faces += 1 if e.is_a?(Sketchup::Face)
  if e.is_a?(Sketchup::ComponentInstance)
    e.definition.entities.each do |ent|
      faces += 1 if ent.is_a?(Sketchup::Face)
      faces += ent.definition.entities.grep(Sketchup::Face).size if ent.is_a?(Sketchup::ComponentInstance) || ent.is_a?(Sketchup::Group)
    end
  end
end
puts "Total faces:  #{faces}"

#5

Without using any code [yes TIG did say that!]
Open Model Info > Statistics
Set the top drop-down to ‘Entire model’ and tick the adjacent check-box 'Show nested components'
The second item in the list shows the count of ALL Faces in the Model and in any component-instances/groups [even if they are nested].


#7

The snippet seems to be failing when the enities are inside a group, any Idea why it returns 0?


#8

Try changing the first if:

if e.is_a?(Sketchup::ComponentInstance)

to:

if e.is_a?(Sketchup::ComponentInstance) || if e.is_a?(Sketchup::Group)

#9

Could the sage direct me as to how to get the same value programatically, the Total face count as shown in the Model info window? :grinning: , the model I am working on as hundreds of nested groups/components. Here’s a Screen shot of the Model info window.


#10

The group with more levels of group inside, have how many groups as child?


#11

Yes the groups and components are nested in the model. There are 947 groups totally with 150+ Component defs.


#12

@prz87,

I’m not @TIG but between the two other snippets you have all you need…
my first snippets drills all groups and components while @kimpastro gave you loose faces…
this finds all when combined…

model = Sketchup.active_model
defs = model.definitions
list = []
faces = 0
defs.each{|d|
            next if d.image?
            ins=[]
            d.instances.each{|i|ins << i}
            list << d.instances unless ins.empty?
          }
faces = Sketchup.active_model.entities.grep(Sketchup::Face).count

list.each{|c| c[0].definition.entities.grep(Sketchup::Face).find_all{|f| faces +=1 if f != nil} }

faces

it’s purely a count not a collection like my first example so it’s quite fast in my test’s…

saying what you need would help us help you…

john


#13

In Ruby you have to recursively examine each ComponentDefinition’s entities collection to see whether it contains any nested ComponentInstances or Groups, count them and then follow to their ComponentDefinitions and repeat until you reach the deepest nest (sorry if that isn’t clear - I have to leave for a meeting and don’t have time to provide code right now).


#14

Yeah, this definitely it’s working here.


#15

I’ve made it recursively:

def count_faces(entity, faces)
  faces += 1 if entity.is_a?(Sketchup::Face)
  if entity.is_a?(Sketchup::ComponentInstance) || entity.is_a?(Sketchup::Group)
    entity.definition.entities.each do |ent|
      faces = count_faces(ent, faces)
    end
  end
  return faces
end

total_faces = 0
Sketchup.active_model.entities.each { |ent| total_faces = count_faces(ent, total_faces) }
puts total_faces

#16

@kimpastro, grep is much faster for finding things in ruby, and if you don’t skip any images it can lead to problems…

have a look over on the SketchUcation Developer Forum…

I think you’ll find lots to interest you…

john


#17

@john_drivenupthewall Thanks for your help , I ran a quick test but the count generated by the above snippet still doesn’t seem to tally with the model info window value . See output -

I wonder whats causing that, the 1st line of console output is from the Counter I wrote using your snippet earlier (I simply added the free faces count using a loop), the 2nd line is the current block you supplied.


#18

Alright, thanks for warnings and I’m already a SketchUcation forum member :grinning:


#19

your model…

it’s hard to guess without it, I find I sometime need to collect the defs in a hash, appending the key with a count to get all copies of same named items…

can you provide the skp?

john


#20

ok, I found the answer in a bit of modified TT code found at SketchUcation…
I just added the .count…

  def process_model()
    return walk_faces( Sketchup.active_model.entities )
  end
 
  def walk_faces( entities, transformation = Geom::Transformation.new )
    faces = []
    entities.each { |e|
      if e.is_a?( Sketchup::Face )
        faces << e
      elsif e.is_a?( Sketchup::Group )
        faces.concat( walk_faces( e.entities, transformation * e.transformation ) )
      elsif e.is_a?( Sketchup::ComponentInstance )
        faces.concat( walk_faces( e.definition.entities, transformation * e.transformation ) )
      end
    }
    return faces
  end
 process_model().count


#21

Wouldn’t it just be easier to do:

total_faces = Sketchup.active_model.number_faces

?

See API: Sketchup::Model#number_faces

:bulb: