Entities.add_group takes about 9 seconds when adding a face

My code is working, but in some SketchUp models it is extremly slow.

faces ||= Sketchup.active_model.selection.select{ |e| e.is_a?(Sketchup::Face) }
faces.each_with_index{ |face,index| label_face(face, index) }

def entities
    @entities ||= Sketchup.active_model.entities

def label_face(face, index)
	# The following code line takes up to 9 seconds
	group = entities.add_group(face)

    # Some more code

I have no idea why the statement “entities.add_group(face)” takes so much time. Can anyone help or has a workaround? It would be very appreciated.

I’d look at it more like this…

@model = Sketchup.active_model
@entities = @model.active_entities # it's safe - selection is in entities context
@model.selection.grep(Sketchup::Face).each_with_index{|face, index|
  label_face(face, index)
def label_face(face, index)
  group = @entities.add_group(face)
  # Some more code - 
  # like adding some text to the now grouped face, using index ?

Obviously you need to wrap it in an ‘operation’ so it’s one-step undo-able…

Thanks for your reply! I changed to code as you recommeded, but the execution time did not decrease. The code is wrapped in an operation and the disable_ui flag is true. The file im working with is 300 MB big. In a smaller test file the group = @entities.add_group(face) command runs fast. But why should the filesize affect the execution time of this command? I don’t see the problem.

split the array into chunks of less than 1000 faces and see if that helps…


Since I use selection, I can select just one face. The execution time per face is not affected by the number of faces selected. I checked with ‘faces.length’ that really just one element is selected.

When I have labled just a few faces, the code runs fast, in every model. It runs slower as more faces are labled. If you do the ‘entities.add_group(face)’ command maybe a thousand times it takes at the end over 20 seconds.

I solved the problem. Instead of:
group = entities.add_group(face)
I used:
group = entities.add_group
group.entities.add_face(face.vertices.map{ |v| Geom::Point3d.new([v.position.x, v.position.y, v.position.z]) })
and deleted the face afterwards. This is much much faster.

The method call to Sketchup::Vertex#position returns a new Geom::Point3d object, so there is no need to explicitly call the Geom::Point3d#new constructor.

Can be shortened to:

group.entities.add_face( face.vertices.map {|v| v.position } )

… which can be further shortened to …

group.entities.add_face( face.vertices.map(&:position) )

Other interesting details of creating Geom::Point3d objects ...

Also the Geom::Point3d#new constructor does not need a literal array, it can take a list of 3 numeric objects for coordinates. Ie …

Geom::Point3d.new( v.position.x, v.position.y, v.position.z )

… or, better because it can take an array is to leverage a #to_a method …

Geom::Point3d.new( v.position.to_a )

… or …

Geom::Point3d.new( *v.position.to_a ) # convert array to parameter list

However, the Geom::Point3d#new constructor also can take a Geom::Point3d object to clone …

Geom::Point3d.new( v.position )

… and even simpler, it can create a point object directly from a Sketchup::Vertex object …

Geom::Point3d.new( v )
1 Like