@DanRathbun @dezmo
I have created a solution that works using some code I found here and I also added some code in to elucidate what exactly it is that I am doing. I haven’t tried it yet on multiple faces but this solution should work for anyone where the bottom face is on a single plane.
SKETCHUP_CONSOLE.clear
Sketchup.file_new
module Example
extend self
# Default code, use or delete...
mod = Sketchup.active_model # Open model
ent = mod.entities # All entities in model
sel = mod.selection # Current selection
# add first group
group = ent.add_group
# add face to first group and get the edges to be followed.
face = group.entities.add_face [0,0,0],[0,10,0],[10,10,0],[10,0,0]
face.reverse! unless face.normal.z == 1
edges_to_follow = face.edges
# from a different part of the program
inversion = true
# add group2
group2 = ent.add_group
face_g2 = group2.entities.add_face [[-1,-1,-1], [-1,11,-1], [11,11,-1], [11,-1,-1]]
face_g2.reverse! unless face_g2.normal == 1
face_g2.pushpull 2
# find the e1_direction
e1_dir = edges_to_follow[0].line[1]
# move the edges out of the way.
transform = Geom::Transformation.new([0,0,10])
group.entities.transform_entities(transform, edges_to_follow)
# minimum xy corner value
min_v = [0,0,0]
# various modifiers
d = 1
z = 1
o = 0
# vectors for cuts
cut_vector = [-d,d,-z-o]
up_vector = [d,d,z-o]
down_vector = [d,d,-z-o]
trim_vector = [-d,d,z-o]
# add trimmer_group
trimmer_group = ent.add_group
trimmer_pts = [ min_v.offset(cut_vector),min_v.offset(trim_vector),min_v.offset(up_vector),min_v.offset(down_vector)]
trim_face = trimmer_group.entities.add_face trimmer_pts
p " trim_face direction = #{trim_face.normal}"
trim_face.reverse! unless trim_face.normal.samedirection?(e1_dir)
p " trim_face direction = #{trim_face.normal}"
trim_face.followme edges_to_follow
pts = [ min_v.offset(cut_vector),min_v.offset(down_vector),min_v.offset(up_vector)]
# add cut face
cut = group.entities.add_face pts
p " cut direction = #{cut.normal}"
# make cut face follow edges
cut.reverse! unless cut.normal.samedirection?(e1_dir)
p " cut direction = #{cut.normal}"
cut.followme edges_to_follow
group.entities.erase_entities(edges_to_follow)
def getOtherFace(e, f)
f1 = e.faces[0] == f ? e.faces[1] : e.faces[0]
return nil if f == f1
return e.reversed_in?(f) == e.reversed_in?(f1) ? f1.reverse! : f1
end
def getShell(start_face)
front_q = [] #unprocessed shell faces
face_h = {} #hash with expanded faces
edge_h = {} #Hash with expanded edges
shell_h = {} #final shell
#push start face
front_q.push(start_face)
face_h[start_face] = nil
while front_q.length > 0 do
f = front_q.pop
shell_h[f] = nil
f.edges.each { |e|
next if edge_h.has_key?(e) || e.faces.length <= 1
edge_h[e] = nil
f1 = getOtherFace(e, f)
unless f1 == nil || face_h.has_key?(f1)
front_q.push(f1)
face_h[f1] = nil
end
}
end
return shell_h
end
# get all faces
c_faces = group.entities.grep(Sketchup::Face)
if trimmer_group
t_faces = trimmer_group.entities.grep(Sketchup::Face)
end
if inversion == true
# for cut
b_face = c_faces.find{|f| f.normal.parallel?(Z_AXIS)}
b_face.reverse! unless b_face.normal.z == -1
getShell(b_face)
# for trimmer group.
if trimmer_group
b_face_t = t_faces.find{|f| f.normal.parallel?(Z_AXIS) && [1,2,4].include?(f.classify_point(min_v.offset(cut_vector)))}
b_face_t.reverse! unless b_face_t.normal.z == -1
getShell(b_face_t)
end
else
# for cut
t_face = c_faces.find{|f| f.normal.parallel?(Z_AXIS)}
t_face.reverse! unless t_face.normal.z == 1
getShell(t_face)
# for trimmer_group
if trimmer_group
b_face_t = t_faces.find{|f| f.normal.parallel?(Z_AXIS) && [1,2,4].include?(f.classify_point(min_v.offset(cut_vector)))}
b_face_t.reverse! unless b_face_t.normal.z == 1
getShell(b_face_t)
end
end
g2 = trimmer_group.subtract(group2)
group.outer_shell(g2)
end