When getting the center point to a bounding box, it appears to always be relative to the group’s coordinate system, not the global coordinate system. Then, if you select the group the object is contained in, and check the bound center again, it’s now globally aligned.
In the above image, the left cube’s center X is at -1.24m. However, selecting the cube and checking the bounds gives me the following incorrect, relative center:
Is there a way to get the correct global bounding center for an object contained within a group?
I’d rather not just simply apply the transformation for the parent group, since the actual models I’m working with will likely have many levels of groups, and I’m guessing right now that the issue will continue to compound. Not to mention that you can’t simply find the parent group either.
The purpose of this is collision detection between various objects anywhere in the model, where I need the accurate global position of each object.
Applying the outer group’s “transformation” to a position in its local coordinate system converts it to the outside coordinate system. Your code above shows that you want the outer bounding box of the nested entity (there also is a “local_bounds” method for a group).
I did not use your “…selection[0]” statement in my code, as that is trickier. The only way that the selection tool can select a group inside another group is if your are in edit mode on the outer group. Your included image does not appear to be in group edit, in that case your selection statement obtains the X coordinate of the bounding box center of the outer group.
For collision detection, you might consider using the bounding box class’s “intersect” method.
“For collision detection, you might consider using the bounding box class’s “intersect” method.”
Except that if I push the front legs of my chair under the dining table, to 2 objects are not colliding, but their bounding boxes intersect. And so on for many real world objects.
mod = Sketchup.active_model
ent = mod.entities
grp = ent.grep(Sketchup::Group)
intersections = []
for i in 0...grp.length - 1
grp.each{ |g| next if g == grp[i] # skip comparing to self
bb = Geom::BoundingBox.new.add(g.bounds.intersect(grp[i].bounds))
if bb.valid?
puts "#{g.name} and #{grp[i].name} intersect "
sz1 = g.entities.grep(Sketchup::Face).length + grp[i].entities.grep(Sketchup::Face).length
intersections << [g,grp[i],sz1]
else
puts "#{g.name} and #{grp[i].name} do not intersect"
end
bb.clear
}
end
puts "but do they overlap?\n"
returns
chair two and chair one do not intersect
Table and chair one intersect
chair three and chair one do not intersect
chair one and chair two do not intersect
Table and chair two intersect
chair three and chair two do not intersect
chair one and Table intersect
chair two and Table intersect
chair three and Table intersect
but do they overlap?
then using
intersections.each{|g|
if g[0].valid? and g[1].valid?
a = g[0].name.dup
b = g[1].name.dup
sz1 = g[2]
mod.start_operation("test using outer shell")
new_grp = g[0].outer_shell(g[1])
sz2 = new_grp.entities.grep(Sketchup::Face).length
puts "Geometry Overlaps in #{a} and #{b}" if sz1!= sz2
mod.abort_operation()
end
}
nil
The code above is using the outer bounding boxes of the groups. It will work well when their transformation axes line up with the world axes. I have a plugin that I developed that can show me both the outer bounding box and the local one. You could consider using the local bounding boxes. I opened @john_drivenupthewall’s file, changed the style to simple, and rotated the end chair more. Below are two images that my tool provides. The left dashed cyan one in is an outer bounding box, while the right solid yellow one is the “local bounds”. (The local bounds appears to be what the selection tool outlines):
The local bounds corners are in local coordinates, so to work with them would require converting all local bounding boxes to outer coordinates.
Note: The solid magenta line is the transformation’s local X axis, and the neon green one the Y axis. They connect at the transformation’s origin.
In my scenario, I’m doing the collision detection in a separate library, not directly in Ruby. Currently, the center point is the only data point that is coming back incorrect due to groups.
@BruceYoung If the entity I’m calculating the center for is 5 groups deep for instance, I’m guessing I need to apply all 5 transforms, in order, to get the accurate center point?
@john_drivenupthewall
The first loop worked okay (Sketchup 2015 on Windows 7). The second loop, worked after I ran it the third time. Each time I run it I’m also observing:
@weddins
Yes, you will need to apply all transformations. The order that they are applied is the from the most inner to the most outer. For example, three transformations be combined into one with:
total_transform = outer_t * middle_t * inner_t
You can skip the entity’s own transformation if you are using the outer bounds. You may not need to proceed all the way to the outer most world coordinates if you intend to compare entities that are in a common group (as long as they are relative to the same coordinate system).
Okay, the nil is suppressing the “abort_operation” output.
I reloaded and ran it multiple times. I’m seeing the same problem of the final result only being displayed one out of three runs or so. I added an extra “puts” before the intersection loop to state the “intersections” array length. It is usually 5 and always non-zero, but the odd time I’m seeing it a length of 3.
The actual bounding boxes of instances can very depending upon their rotation. The bounding boxes are always aligned with the “world” axes. So they get bigger as the instance is rotated, and the center point changes.