问题
I'm writing a script to make a simple flute in SketchUp (free version, Mac). I want to make a tube and and then cylinders which poke through the tube, draw the intersection lines between the tube and the cylinders, then erase the cylinders, leaving circles to cut out of the tube.
This works if I do it with the mouse, but I found it difficult to be precise about placement and measurement with the mouse. So far, though, I haven't been able to make it work with a script. Currently I am stuck with it drawing incomplete circles on the tube, so I am unable to find the face and erase it. You should be able to run the following script in the ruby console and see what I mean. What am I doing wrong?
entities = Sketchup.active_model.entities
# make tube
tube = entities.add_group
tube_inner = tube.entities.add_circle Geom::Point3d.new(0,0,0), Geom::Vector3d.new(0,0,1), 5, 360
tube_outer = tube.entities.add_circle Geom::Point3d.new(0,0,0), Geom::Vector3d.new(0,0,1), 6, 360
cross_section_face = tube.entities.add_face tube_outer
inner_face = tube.entities.add_face tube_inner
tube.entities.erase_entities inner_face
cross_section_face.pushpull -10, false
# make a cylinder that punches through the wall
hole_punch = entities.add_group
hole_outer = hole_punch.entities.add_circle Geom::Point3d.new(0,0, 5), Geom::Vector3d.new(0,1,0), 3, 360
face = hole_punch.entities.add_face hole_outer
face.pushpull 10, false
# draw the intersection lines and erase the hole punch
entities.intersect_with true, hole_punch.transformation, tube, tube.transformation, true, hole_punch
hole_punch.erase!
回答1:
Determining the correct faces to erase after intersecting can be very tricky.
But since you are working with cylinder shapes - which are solids - I would recommend you use the solid boolean operations that was introduced in SketchUp 8 Pro. You can use Group.subtract
for instance. http://www.sketchup.com/intl/en/developer/docs/ourdoc/group#subtract
However, is you are not using SketchUp 8 Pro or newer then you won't have these methods available.
Alternative solution - avoiding the Solid Tools methods of the Pro version:
entities = Sketchup.active_model.entities
# (!) You created a circle with so many edges that at the scale
# you drew it they where pushing the boundary of how small
# units SketchUp can handle. (1/1000th inch).
# If you has Edge Outline style enabled you could see that
# not all edges where fully merged.
# I reduced the curve segments from 360 to 180.
# (Do you really need such a high mesh density anyway?)
# make tube
tube = entities.add_group
tube_inner = tube.entities.add_circle Geom::Point3d.new(0,0,0), Geom::Vector3d.new(0,0,1), 5, 180
tube_outer = tube.entities.add_circle Geom::Point3d.new(0,0,0), Geom::Vector3d.new(0,0,1), 6, 180
cross_section_face = tube.entities.add_face tube_outer
inner_face = tube.entities.add_face tube_inner
tube.entities.erase_entities inner_face
cross_section_face.pushpull -10, false
# make a cylinder that punches through the wall
hole_punch = entities.add_group
hole_outer = hole_punch.entities.add_circle Geom::Point3d.new(0,0, 5), Geom::Vector3d.new(0,1,0), 3, 180
face = hole_punch.entities.add_face hole_outer
face.pushpull 10, false
# draw the intersection lines and erase the hole punch
entities.intersect_with true, hole_punch.transformation, tube, tube.transformation, true, hole_punch
hole_punch.erase!
# Find all the edges that belong to the Circle elements drawn
# earlier (including the ones push-pulled).
# (Could also collect these earlier before intersecting by
# collecting all non-smooth edges.)
circles = tube.entities.grep(Sketchup::Edge).select { |e| e.curve }.uniq
# Then we pick out all the faces that isn't connected to these edges and erase them.
new_faces = tube.entities.grep(Sketchup::Face).select { |f| (f.edges & circles).empty? }
entities.erase_entities( new_faces )
If you really want 360 segment circles you can scale the content of the group up - while you scale the group instance down. That way the group definition is at a much bigger scale. (See this article on instances and definitions in SketchUp: http://www.thomthom.net/thoughts/2012/02/definitions-and-instances-in-sketchup/)
Also, if you want faces to fill the hole between the inner and outer skin you need to intersect that part as well.
Note about the Entities.intersect_with
description - the current docs doesn't explain well all the arguments. There are two entities
arguments.
The first one should be a Sketchup::Entities
object where the intersected objects should appear. (I'm a bit surprised it worked by feeding it a Sketchup::Group
object.)
The second should not be Sketchup::Entities
- that will fail. It must be an Sketchup:Entity
or array of Sketchup:Entity
objects.
来源:https://stackoverflow.com/questions/15694777/punching-a-hole-through-a-cylinder-using-sketchup-ruby-api