144 MB model went blank - can't find model, axes, or horizon

Copy and Paste this Ruby code into the Ruby Console and your model will be magically restored.
RescueMyModel v12.rb (4.2 KB)

# Rescue My Model version 12 - 2/2/2019
# A short bit of code to recover, in situ, models that
# have become unviewable after a Zoom Extents Operation
# due to bugs in the Sketchup core logic.
# 
# Usage: copy and paste the text into Sketchup's Ruby Console and press the Enter key.
# Undo: use the standard Sketchup Edit>Undo menu command
#
# The known causes of this problem are:
#   Text with an X, Y, or Z location of nan
#   Edge vertices, Groups, or Components located a very long distance from the origin.
#   Camera lost in space
#  
# The code repairs these problems by deleting faulty Edges, and relocating faulty Groups
# and Components to the origin [0,0,0] of their parent container.
#
# The code also executes several View.zoom() operations which cause Sketchup to reorient the 
# clipping plane and other unknowable variables. After completion the model will be functional.

module SW
module RescueMyModel
  MaximumXYZ = 63360000 # Limit points to One Thousand Miles from the container origin
    
  def self.start_recovery()
    puts 'Starting to rescue your invisible model'
    number_of_problems = scan_model()

    if number_of_problems == 0 
      puts "\nNo Problems Found"
    else
      puts "\nFound #{number_of_problems} problems"
    end
    
    puts 'Starting the Camera Reset Procedure'
    Sketchup.active_model.active_view.camera.set([0,0,0],[1,1,1],[0,0,1])

    #set up a deferred operation for the final zoom operations
    id = UI.start_timer(0.0, false) {deferred_camera_zooms()}
    puts 'Passing Control to the Deferred Operations'
    #end
  end  

  def self.deferred_camera_zooms()
    model = Sketchup.active_model
    view = model.active_view
    
    #these simple zoom operations could take quite sometime in a large model
    puts 'Executing Deferred Operation 1'
    view.zoom(model.active_entities[0])

    puts 'Executing Deferred Operation 2'
    begin
      view.zoom(model.active_entities[1])
    rescue # if there is no second entity 
    end
    
    puts 'Executing Deferred Operation Zoom All'
    view.zoom_extents
    id = UI.start_timer(0.0, false) {print_completed_message()}
  end
  
  #This block will be called AFTER the final zoom_extents has completed
  def self.print_completed_message()
      puts "\nRescue My Model.\nYour model should be visible.\nPlease save this file with a new filename"
  end
  
  #Scan the Model's entities and return the count of problem entities that have been modified
  def self.scan_model()
    @number_of_problems = 0 
    @entities_to_delete = []
    search_entities(Sketchup.active_model.entities)
    @entities_to_delete.each(&:erase!) #this can leave a container with zero entities
    return @number_of_problems
  end
  
  def self.search_entities(ents)
    ents.each do |e|
      if e.is_a?(Sketchup::Edge)
        if e.vertices.find{|p| p.position.to_a.any?{|n| n.abs>MaximumXYZ}}
          print "\nDeleting #{e}"
          @entities_to_delete << e
          @number_of_problems += 1
        end 

      elsif e.is_a?(Sketchup::Text)
        if e.point.to_a.any?(&:nan?)
          print "\nMoving #{e} to the Container Origin" 
          e.point = ORIGIN
          @number_of_problems += 1
        end  
    
      elsif e.is_a?(Sketchup::ComponentInstance)
        print '.'
        check_transformation(e)
        search_entities(e.definition.entities)

      elsif e.is_a?(Sketchup::Group)
        print '.'
        check_transformation(e)
        search_entities(e.entities)
      end

    end
  end
  
  # Check a container's transformation for valid translation values. Then move the 
  # container to [0,0,0] of the parent container if there is a problem
  # TODO: check for insane scaling of container contents.
  #        
  def self.check_transformation(e)
    if e.transformation.to_a[12..14].any?{|n| n.abs>MaximumXYZ}
      print "\nMoving #{e} to the Container Origin"
      tra = e.transformation.to_a
      #puts tra
      tra[12] = 0.0; tra[13] = 0.0; tra[14] = 0.0
      e.transformation= Geom::Transformation.new(tra)
      @number_of_problems += 1
    end
  end
  
  #
  #Entry Point
  #
  start_recovery()
  nil # return nil to the Ruby console
end
end