Create Section Plane Programmatically?

ruby
sectionplanes

#1

I would like to do the following programmatically in Ruby:

  • select a section plane by choosing one with a specific name
  • create a group of section lines using Sketchup’s native “Create Group from Slice” feature or similar
  • name the group something predictable for later use/retrieval
  • fill all of the sub group object, presumably by looping through points and tracing or something

The API however, only seems to offer very remedial methods for dealing with Section Planes… getting.setting the name, determining if its active, etc.

I think I can handle most of the grunt work but does anyone know how I could access or at least simulate the Create Group from Slice method?


#2

See previous topic thread …


#3

Thanks Dan but I was looking for “under the hood” info on Section Planes. Nonetheless, I muddled through so below is my Script.

The idea here was to do sort of a Skalp Lite that makes a very remedial Section Plane we can use to distinguish between existing (EXIST) and proposed (PROP) geometry in our floor plans. We do a lot of renovation work and we can use a dedicated section view to overlay views to that end.

Obviously, we are working in a controlled environment where we can define and anticipate the names of groups, scenes, layers, etc. Something commercial like Skalp has to deal with many possible scenarios so needs to be much more sophisticated but also HEAVY. We had problems with it bogging down. Staff was going crazy.

One slightly hacky thing I had to do was to create a temporary circle entity we use as the cutting plane. Ideally, I would have just selected the Section Plane and used that to run intersect_with but that did not seem to be working out. Input welcome.

Anyway, hopefully this helps someone with Section Plane.

require 'sketchup.rb'

# requires:
# groups in the model with instance names such as "EXIST" and "PROP" that are the target objects to be cut
# section planes at different (at least one) levels with the name format "P" (for "plan") + "LEVEL_NUMBER" (P1,P2,P3 and so on)
# a folder containing styles named EXIST.style and PROP.style
# a file name z_section_materials.skp containing materials EXIST and PROP

module ZCode
module ZSectionModule

#################################################################

def self.z_section(target_name)

# start undo tracking
Sketchup.active_model.start_operation('ZSection', true)

# ask user for target level
prompts = ["Create/Update Section on what level?"]
defaults = ["1"]
list = ["1|2"]
$target_level = UI.inputbox(prompts, defaults, list, "Z SECTION")[0]

# get objects to be cut
Sketchup.active_model.entities.grep(Sketchup::Group).each{|entity|
        
    # look for target group
    if(entity.name == target_name)
        #print "target group #{target_name} found\n"
        $group_to_be_sectioned = entity
    # or delete prior sections
    elsif(entity.name == "#{target_name}#{$target_level}_CUT")
        entity.erase!
    end

}

# get section plane which is always named P for "plan level"
Sketchup.active_model.entities.grep(Sketchup::SectionPlane).each{|entity|
    if(entity.name == "P#{$target_level}")
        $su_section_plane = entity.get_plane
    end
}

# get section plane elevation relative to origin
section_z = ORIGIN.project_to_plane($su_section_plane)

# define parameters of a circle large enough to capture anything in the model
$radius = [Sketchup.active_model.bounds.width,Sketchup.active_model.bounds.depth].max
center_xy = Sketchup.active_model.bounds.center
$center = [center_xy[0],center_xy[1],section_z[2]]
$normal = Geom::Vector3d.new(0,0,1) # a vector that runs up the Z axis.

# create a group to receive the section circle geometry
z_section_circle = Sketchup.active_model.entities.add_group
z_section_circle.name = "Z_SECTION_CIRCLE"
z_section_circle.transformation = ORIGIN

# add the section geometry to the group
z_section_circle.entities.add_circle($center, $normal, $radius)

# fill in the section circle from its points
z_section_circle.entities.grep(Sketchup::Edge).each{|e|
    e.find_faces
}

# create a group within the appropriate target group to receive the section geometry
$z_section_container = Sketchup.active_model.entities.add_group
$z_section_container_trans = $z_section_container.transformation
$z_section_container.name = "#{target_name}#{$target_level}_CUT"
$z_section_container.transformation = ORIGIN
$z_section_container.layer = "#{target_name}"

# create section points and edges
z_section_circle.entities.intersect_with(
    false,
    z_section_circle.transformation,
    $z_section_container,
    $z_section_container.transformation,
    false,
    $group_to_be_sectioned
)

# fill in the section plane from the section points
$z_section_container.entities.grep(Sketchup::Edge).each{|e|
    e.find_faces
}

# load default materials from file
material_path = File.join(ENV['HOME'],'Dropbox/support/_sketchup/plugins/z_section_materials.skp')
Sketchup.active_model.definitions.load material_path

#apply a material to the section face
$z_section_container.material = target_name

#delete the section circle
z_section_circle.erase!

## setup a view that displays only the new section

#position new camera
camera = Sketchup::Camera.new
status = camera.perspective = false
eye = [0,0,20000]
target = [0,0,0]
up = Geom::Vector3d.new(0,1,0) # a vector that runs up the Y (north) axis.
camera.set eye, target, up
Sketchup.active_model.active_view.camera = camera

# zoom to the extents of the new section
#new_view = Sketchup.active_model.active_view.zoom_extents
new_view = Sketchup.active_model.active_view.zoom($z_section_container)

# load styles from file and set current style
style_path = File.join(ENV['HOME'],"Dropbox/support/_sketchup/styles/#{target_name}.style")
Sketchup.active_model.styles.add_style(style_path, true) # true sets loaded style as active
#Sketchup.active_model.styles.selected_style = Sketchup.active_model.styles["#{target_name}"] 

#hide everything but the new $z_section_container
Sketchup.active_model.entities.each{|all|
    if(all.is_a?(Sketchup::Group))
        if(all.name != "#{target_name}#{$target_level}_CUT")
            all.hidden = true
        end
    else
        all.hidden = true
    end
}

#delete old scene
Sketchup.active_model.pages.each{|p|
    if(p.name == "#{target_name}#{$target_level}_CUT")
        Sketchup.active_model.pages.erase(p)
    end
}

#create a new scene
page = Sketchup.active_model.pages.add("#{target_name}#{$target_level}_CUT")

#hide $z_section_container on all other scenes
Sketchup.active_model.pages.each{|op|
    if(op.name != "#{target_name}#{$target_level}_CUT")
        Sketchup.active_model.pages.selected_page = op
        $z_section_container.hidden = true
        op.update(16)
    end
}

#set the active page to the one just created
Sketchup.active_model.pages.selected_page = Sketchup.active_model.pages["#{target_name}#{$target_level}_CUT"]

# end undo tracking
Sketchup.active_model.commit_operation

end #def

#################################################################

end # ZSectionModule
end # end of Module ZCode