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