How to reverse a lot of faces?

Hi,
I have a heavy model and it contains a lot of flipped faces.
When I do
face.reverse!
If I do this for every face then Sketchup hangs and went to not responding state.

I’m afraid there isn’t any other ways to reverse faces in the Ruby API.

Can you provide an example model and a complete minimal script to illustrate the performance you are seeing?

Here is the script snippet

def start_reverse_op
    	model = Sketchup.active_model
    	begin
    		model.start_operation('Reverse Faces', true, false, true)
    		check_and_reverse_face(model.entities)
    		model.commit_operation
    	rescue
    		model.abort_opertion
    	end
    end

    def check_and_reverse_face(entities)
    	entities.each {|e|
    		if e.is_a?(Sketchup::Face)
    			puts "Face"
    			reverse_face(e)
    		elsif e.is_a? (Sketchup::Group)
    			puts "Group"
    			check_and_reverse_face(e.entities)
    		elsif e.is_a? (Sketchup::ComponentInstance)
    			puts "ComponentInstance"
    			check_and_reverse_face(e.definition.entities)
    		end
    	}
    		
    end

    def reverse_face(face)
    	puts "Reversing the face"
    	back_mat = face.back_material
    	front_mat = face.material
    	if(front_mat.nil? && !back_mat.nil?)
    		face.reverse!
    		face.material = back_mat
    		face.back_material = nil
    	end
    end

I could not upload the model as it is more than 4MB.
Here is the link : https://files.fm/u/9nhd4qpg

Thanks - I’ll have a closer look.


A little side note:

Don’t make operations transparent unless they are meant to chain to the previous operation. For instance, if you do model changes in an observer than you should be making the operation transparent. But by default operations should not be transparent.

I just ran through your example with your attached model:

module Example

  # Example.start_reverse_op
  def self.start_reverse_op
      model = Sketchup.active_model
      begin
        t = Time.now
        model.start_operation('Reverse Faces', true, false)
        check_and_reverse_face(model.entities)
        model.commit_operation
        puts "Elapsed time: #{Time.now - t}s"
      rescue
        model.abort_opertion
      end
    end

    def self.check_and_reverse_face(entities)
      entities.each {|e|
        if e.is_a?(Sketchup::Face)
          # puts "Face"
          reverse_face(e)
        elsif e.is_a? (Sketchup::Group)
          # puts "Group"
          check_and_reverse_face(e.entities)
        elsif e.is_a? (Sketchup::ComponentInstance)
          # puts "ComponentInstance"
          check_and_reverse_face(e.definition.entities)
        end
      }

    end

    def self.reverse_face(face)
      # puts "Reversing the face"
      back_mat = face.back_material
      front_mat = face.material
      if(front_mat.nil? && !back_mat.nil?)
        face.reverse!
        face.material = back_mat
        face.back_material = nil
      end
    end

end

It completed in a fraction of a second: Elapsed time: 0.248182s

Note that I removed your puts statements. Those are expensive - and should be avoided in inner loops. If I run your script with the puts statements I see the same as what you describe.

So the issues here isn’t face.reverse! - but your puts debugging statements. When running into performance issues it’s worth making timing tests to assert what is actually causing the slow-down.

Btw, for debugging you might want to look into the debugger: https://github.com/SketchUp/sketchup-ruby-debugger
Can often save you from modifying your source code with puts when you want to inspect what is going on.

We have a VSCode example project that demonstrate how to set up VSCode for debugging with SketchUp: https://github.com/SketchUp/sketchup-extension-vscode-project

3 Likes

Thanks a ton @tt_su.
Will remember the points.