Bounding Box of Multiple Entities

I’m trying to figure how to get the bounding box of multiple entities (edges and faces) within a group. Is there a way to do this?

Ultimately I am actually only trying to the find the min and max point of this bounding box inside or within the group’s coordinate system. However, I need to include all of the geometry within the group so that I end up with the correct min and max point. For some reason I can’t seem to do this.

Hello,

You can build it recursively by merging the bounding box formed by each face and edge.

Example, with face only :

1 Like

It seems like there should be an easier way to do this. I will dig into the Github example though.

It might be simpler if we limit the search to the geometry contained in the group and don’t try to exclude hidden elements.

This code is the one I use in OpenCutList, so it follows the logic OCL need. So it’s not exactly what you are asking for.

1 Like

If you only want to include edges and faces to bounding box, you really need to add only the edges, since faces can not exists without bounding edges, but edges can be there without faces.

This snippet will return you new bounding box object containing only edges within a given group as parameter, its corners and min max will be in a global coordinates.

def bb_of_edges_in_group(group)
  tr = group.transformation
  ents = group.entities
  pts = ents.grep(Sketchup::Edge).flat_map{|e|
    e.vertices.map{|v| v.position.transform(tr)}
  }
  bb = Geom::BoundingBox.new
  bb.add(pts)
end
mod = Sketchup.active_model
entities = model.active_entities
sel = mod.selection
bb = bb_of_edges_in_group(sel.first)
eg = sel.first.entities
mod.start_operation("test")
8.times{|i| entities.add_cpoint(bb.corner(i))}
mod.commit_operation

This one will be inside the group coordinate system

def bb_of_edges_in_group(group)
  ents = group.entities
  pts = ents.grep(Sketchup::Edge).flat_map{|e|
    e.vertices.map{|v| v.position}
  }
  bb = Geom::BoundingBox.new
  bb.add(pts)
end
mod = Sketchup.active_model
sel = mod.selection
bb = bb_of_edges_in_group(sel.first)
eg = sel.first.entities
mod.start_operation("test")
8.times{|i| eg.add_cpoint(bb.corner(i))}
mod.commit_operation

Demonstrating by adding cpoints of bb corners to model and into group.

bb_group_edges

2 Likes

Thank-you, I will study these blocks of code.

Let us say that the entities in question are in an array referenced as targets:

bounds = targets.map(&:bounds)
bbox = Geom::BoundingBox.new.add(*bounds)

max = bbox.max
min = bbox.min

If the active edit context is the group, the API methods return points in model coordinates. If the parent of the group is the edit context, the API methods return points in the parent’s coordinate system, and so on …

So you would need to transform the points.

active = Sketchup.active_model.active_path
if active # nil if at top-level
  path = Sketchup::InstancePath.new(active)
  t = path.transformation.inverse
  # Use the bang method to modify the points:
  max.transform!(t)
  min.transform!(t)
end

BTW, if supporting earlier than SU2017, you can use Sketchup::Model#edit_transform rather than Sketchup::InstancePath. Ie:

model = Sketchup.active_model
active = model.active_path
if active # nil if at top-level
  t = model.edit_transform.inverse
  # Use the bang method to modify the points:
  max.transform!(t)
  min.transform!(t)
end
3 Likes