Creating decking with intersect_with

I’m trying to convert a face into deck boards but can’t seem to figure out the proper way to use intersect_with and work with the result. Here is the sample code I’m using to figure out how to do it. I create the faces of the deck boards (boardgroup), and the shape of the deck that I want it to be in (outlinegroup). I call intersect_with and put the results into a third group (newgroup). I’m not sure how to remove the parts of the boards that are outside of the outline.

model = Sketchup.active_model
entities = model.active_entities
selection = model.selection

def face_make (group, pts, material)
  normal = [0,0,1]
 
  face = group.entities.add_face(pts)
 
  dot = face.normal.dot normal
  if dot < 0.0
    face.reverse!
  end
  
  face.material = material
  
  face
end


pts = []

#make the outline shape that we want to conform to
pts[0] = [5, 5, 0]
pts[1] = [5, 24, 0]
pts[2] = [63, 24, 0]
pts[3] = [63, 0, 0]
outlinegroup = entities.add_group
outline = face_make(outlinegroup, pts, "blue")

pts[0] = [0, 0, 0]
pts[1] = [0, 36, 0]
pts[2] = [5.5, 36, 0]
pts[3] = [5.5, 0, 0]

boardgroup = entities.add_group

for i in 0..10
  face_make(boardgroup, pts, "red")
  
  pts[0].x += 6
  pts[1].x += 6
  pts[2].x += 6
  pts[3].x += 6
end

newgroup = entities.add_group

boardgroup.entities.intersect_with(true, IDENTITY, newgroup.entities, IDENTITY, false, outlinegroup)

You need to give your groups some thickness before the intersect.

boardgroup.entities.grep(Sketchup::Face).each { |f| f.pushpull 1 }
outlinegroup.entities.grep(Sketchup::Face).each { |f| f.pushpull 1 }
newgroup = boardgroup.intersect(outlinegroup)
newgroup.entities.grep(Sketchup::Face).each { |f| f.material = "red" }

Thanks so much for your help! This accomplishes my goal. You used intersect() instead of intersect_with(). I don’t really understand the difference. The documentation is a bit fuzzy; it says intersect() “is used to compute the boolean intersection of two groups.” I interpreted this as meaning it would not change the geometry but instead would return some values.

See …

… and a video …

1 Like

Here are the UI equivalents of the two methods.
image

In the Ruby API documentation, intersect_with is not explained very well, which can cause confusion. It has quite a bit more power and flexibility than Group#intersect. Here’s some discussion that might help you to understand how to use it.

There are two sets of Faces involved. The method will generate all of the Edges where a Face from the receiver of the method (the Entities collection on which you invoke the method) intersects a Face from the Array of Entities passed as the final argument, “entities2”. The resulting new Edges are added to the argument “entities1” Entities collection. In my experience, the method may or may not also create all the Faces associated with the new Edges, so it is wise to follow up with find_faces or similar to force their creation.

Like the Intersect Faces with… method in the GUI, the intersect_with API method does not do any cleanup for you. If your intent is to mimic a Solid Tools operation that removes geometry, you will have to program that separately yourself.

Contrary to the documentation, the method never returns nil though it might raise an exception for incorrect arguments. It returns an Array containing any new Edges created. As noted, these Edges are actually added to entities1. Returning them lets you identify them without having to search entities1, a potentially error-prone task if entities1 was not previously empty. The Array will be empty if no intersection Edges were found.

The purpose of the two Transformation arguments is not explained well.

The first one (“transform1”) maps the coordinates of the receiver into the coordinates of the “entities2” objects. Note that this implies that all the objects in entities2 must be in the same coordinates else confusing errors will occur. However, making you provide this Transformation explicitly allows you to deal with situations in which neither the receiver nor entities2 are in the model’s global coordinates. You will have to concatenate step-by-step Transformations or their inverses in such cases to create what is required.

The second Transformation (“transform2”) maps the coordinates of “entities1” into the coordinates of entities2. This is used (actually its inverse) to convert the new Edges from the (implicit) coordinates of entities2 into the coordinates of entities1. Again, except in simple cases you will have to build this Transformation.

The “recurse” Boolean argument specifies whether Faces in nested objects in the receiver will be recursively included. It is all or nothing; there is no way to descend only part way into the nest. Nested objects in entities2 are always included, regardless of the value of recurse.

The “hidden” Boolean argument affects both the receiver and entities2. There is no way to specify them separately.

2 Likes