Hi fellow seniors, I now want to implement the function of “generating a group from a section”, which is the function that appears when you right-click on a section in the scene. It perfectly meets the effect I need: the plane intersects with the object at the level of the plane, and the Groups are created as a result. And it runs very fast. I noticed a previous post on the forum, but there was no solution. The intersect_with method mentioned in it was not easy to use. So now I can only write my own sectioning function to achieve this function? Similar to S4U’s Slice? That will be a big project. .
The topic moved to [Developers] [Ruby API] section. (Again and again and again … )
I do not think you can avoid the intersect_with method.
I opened API requests 4 years ago …
I wish there was a way to vote for new API methods, these both sound just dandy.
First stab at writing the Section Create Group From Slice
slice from group all.rb (2.8 KB)
and a file to test with:
test slice.skp (104.8 KB)
The Code:
# In this implementation I have ignored any geometry in the top level entities collection
# and leave that to the reader to resolve.
# Slice every Component and Group in the model
# saving the geometry in a new groups (under the group named 'Slice Group')
#
module SW
def self.create_slice()
model = Sketchup.active_model
top_level_ents = model.active_entities
model.start_operation('Create Slice', true)
dest = top_level_ents.add_group
dest.name = 'Slice Group'
# find all of the visible groups and components
cgs = dig(top_level_ents)
hide_all(cgs)
# slice each component or group at height z
z = model.bounds.center.z
cgs.each {| ent |
slice(model, dest, ent, z)
}
# unhide all of the components and groups
unhide_all(cgs)
model.commit_operation
# move the destinaiton group off to the side so that we can see it
#tr = Geom::Transformation.translation([0, 400, 0])
#dest.transform!(tr)
end
def self.hide_all(cgs)
cgs.each {| cg | cg.hidden = true }
end
def self.unhide_all(cgs)
cgs.each {| cg | cg.hidden = false }
end
# find all of the visible components and groups
def self.dig(ents)
cgs = []
ents.each { | ent |
next if
if ent.class == Sketchup::ComponentInstance
cps << ent if !ent.hidden?
dig(ent.definition.entities)
elsif ent.class == Sketchup::Group
cgs << ent if !ent.hidden?
dig(ent.entities)
end
}
return cgs
end
# create a slice of the entity at the height z
# by unhiding the entity and applying intersect_with to the whole model
#
def self.slice(top_level_ent, dest, ent, z)
case top_level_ent
when Sketchup::Group
ents = top_level_ent.entities
when Sketchup::ComponentInstance
ents = ent.definition.entities
when Sketchup::Model
ents = Sketchup.active_model.active_entities
end
# create a face that is slightly larger than the current bound box
bb = top_level_ent.bounds
pt = bb.corner(4)
p1 = [pt.x - 20, pt.y - 20, z]
pt = bb.corner(5)
p2 = [pt.x + 20, pt.y - 20, z]
pt = bb.corner(7)
p3 = [pt.x + 20, pt.y + 20, z]
pt = bb.corner(6)
p4 = [pt.x - 20, pt.y + 20, z]
# add the face to the current entities
temp_face = ents.add_face(p1, p2, p3, p4)
temp_edges = temp_face.edges
# add a destination group to receive all of the intersection lines
grp = dest.entities.add_group()
grp.name = ent.name
# Intersect the the current entities object with the temp_face,
# placing the resulting lines in the destination group
ent.hidden = false
ents.intersect_with(true, IDENTITY, grp.entities, IDENTITY, false, temp_face)
# remove the temp_face
ents.erase_entities(temp_edges)
ent.hidden = true
end
end
SW::create_slice()
The result of running the demo code should look like this:
What is the brute force hiding and unhiding for ?
If the user has some stuff hidden and other not, this would not restore things as they were.
The dig()
method might have issues.
There is a statement line next if
that has no conditional expression as the 1st line in the each
loop.
Secondly, the results of the recursive call(s) are not returned. Ie, each recursive method call has it’s own cgs
array that is not applied to the top level cgs
array (from the first call to dig()
.
I did not test it, so if it works the way it is, then perhaps there is no need to reclusively dig down into nested objects?
The basic idea here is to draw a temporary face that is larger than the geometry we wish to section. Then we call upon Sketchup to intersect all of the geometry in the specified entities collection, the model.active_entities in this example, with the temporary face. Note the recurse flag is set to true. After making the intersect_with() call the destination group will contain a line at each location that a face in any group or component intersected our temporary face. Since we specified recurse, any visible geometry in the children containers of our top level entities will be included in the intersection.
- To create separate slices for each child container, as the native Sketchup tool does, we must hide everything in the model and then unhide and perform the intersection on a single container at a time.
The ents.intersect_with method call is the workhorse of the whole algorithm which eliminates our needing to calculate any transformation matrices.
# Intersect the the entities object with the temp_face,
# placing the resulting lines in the destination group
ents.intersect_with(true, IDENTITY, grp.entities, IDENTITY, false, temp_face)
As you mentioned, the dig method does need to be revisited to return a tree of containers that may be traversed while making the slices. Not knowing the ultimate use of this code, I stopped refining the code once the basic example was working properly.
Thank you for the feedback!