Fix Oddly sized bounding boxes for FaceMe components

I have a lot of files. Each file contains a single groups. This group in turn consists of two further groups one of which has FaceMe behavior. Due to this the outer group gets a way too big bounding box. See image.

The problem here is to tighten the bounding box for the outer group in every file in a bulk operation. For some reason this seems very difficult to do in a simple way. The only reliable way I’ve found is to change the camera to orthographic front view, then wait (timer + observer) for Sketchup to pick up the new view. After this a very long edge is added to the group which is then removed and this makes Sketchup recalculate the bounding box correctly. (and yes…it seems bizarre that the correct bounding box calculation is dependent on the camera, but it really seems to be the case when dealing with FaceMe behavior…)

I don’t like this workflow because it introduces observers and timers and this does not work well since this is just a small part of a larger bulk operation and it forces other unrelated parts to work in an asynchronous manner. I want a normal linear script.

So, the question is, does anyone have a better solution?

I’m not understanding the ‘context’ but can you use behaviour on/off…

b = componentdefinition.behavior.always_face_camera?
componentdefinition.behavior.always_face_camera = false if b
## <do work>
componentdefinition.behavior.always_face_camera = true if b

john

This was one of the things I tried and it didn’t work. The size of the bounding box does not change from this even though I force Sketchup to recompute it in various ways after the face_me behavior is turned off. It might be that the box is recomputed again when the behavior is turned on.

I’m using this to get the ‘tightest’ bounds in one I’m working on…

      bb  = Geom::BoundingBox.new
      all = sel.to_a  # sel contains the internal entities
      bb.add(all.map(&:bounds))

john

If you look in the image I provided, Sketchup has computed (and uses) an oversized box for the outer group due to there being a faceMe group inside. The blue box around the two silhouettes can be much tighter. What I want is to force Sketchup to recompute a tight bounding box. It’s possible to do, but I haven’t found an elegant way to do it in linear code. It’s for some reason surprisingly difficult to get Sketchup to tighten up the bounding box if faceMe components/groups are involved…

can you upload or PM an example file?

it seems to work if I group a face-me from component sampler…

model   = Sketchup.active_model
ents    = model.entities
sel     = model.selection # I select a grouped face-me component
wrapper = sel.to_a[0]

p wrapper.bounds.width
sel.clear

item = wrapper.entities.to_a[0]
sel.add(item)
item.definition.bounds.width

# returns
64.01654778310211
51.5354

but, I may be missing the point…

john

What about using ComponentDefinition#invalidate_bounds ? …

Invalidates the bounding box of your definition. This command forces the update of the bounding box of definition while inside an operation. See Model.start_operation for how to start an operation.

This method is useful if you make changes to your geometry using the Ruby API and then need to know your bounding box size. This method forces SketchUp to recalculate the definition’s bounding box when you choose.

model = Sketchup.active_model
cdef = cinst.definition # The face camera component definition
model.start_operation("Recalc Bounds",true)
  #
  cdef.invalidate_bounds
  # do other stuff ?
  # 
mode.commit_operation

Here’s a file and an image showing the problem more clearly. What I’m after is a piece of code that tightens the bounding box to the left so that it gets the size of the bounding box to the right.

oversized.skp (2.5 MB)

Invalidates the bounding box of your definition

I’ve tried this but it does not work. There is a reason why Sketchup oversizes the bounding box to begin with (this reason is unknown to me but it seems related to the faceMe behavior of the group’s contents). When Sketchup is asked to recompute the box this reason comes into play and we get the same oversized bounding box again…

with your model item.definition.bounds.width works…

model = Sketchup.active_model
ents  = model.entities
sel   = model.selection 
sel.clear

wrapper = ents.to_a[0]
p wrapper.bounds.width

items = wrapper.entities
sel.add(items.to_a)

items.map{|item| item.definition.bounds.width}
# =>
65.56987013547283
[63.66016113834077, 63.9114446819393]

but I would more likely use the definitions directly…

model   = Sketchup.active_model
ents    = model.entities
defns   = model.definitions
defns.map { |item|
  next unless item.behavior.always_face_camera?
  item.bounds.width
}.compact

# =>
[63.66016113834077, 63.66016113834074]

To my knowledge the ‘displayed’ bounds always includes hidden items, the face-me uses hidden items ‘under the hood’…

john

John, the thing here is not to calculate the bounding box but to force Sketchup to change its internal representation of the bounding box. That is, when a group is selected I want Sketchup to show the outline to the right in the image above.

There’s definitely something off in the behind-the-scenes handling of those groups’ bounding boxes by SketchUp. Some things I’ve noticed in the GUI:

  • When I first open your file, both groups have oversized bounding boxes.
  • opening the groups for edit down to the innermost nested level and then closing without changing anything fixes the bounding boxes.
  • saving the file, close, and then reopen also fixes the bounding boxes (I’m on SU 2019 so the save also converted the file from your 2017 original. I don’t know if that’s relevant).

But I also find that invalidate_bounds doesn’t seem to work.

1 Like

Argghhh, well, that makes this whole exercise pointless. The solution is probably that there is no solution…

I’m still curious as to why the boxes are oversized though.

is this what you want???

my code with an observer…

john

I seem to remember something about faceme component bounds getting overhauled in one of the recent update cycles (ie, past few years.) But I cannot find it looking through the past few years of release notes.

@tt_su Thomas can you recall some work being done about this?

I don’t recall any changes related to that.

Can you provide any insight into why Sketchup oversizes the boundingbox if there is a faceme component inside? It’s obvious that the outer box needs space to accomodate the rotation of the faceme component, but it’s not clear why it must be oversized.

I’ve tried to find clues in the source, but so far I haven’t found anything.
I might have to ask around when I get back from DevCamp.

1 Like

In the situation where a component contains a face-me subcomponent: the bonding box will be recalculated each time the user exits from the Edit mode of the component. The dimensions of the bounding box will vary depending on the direction the camera is looking at the component.

I’m a bit uncertain if the camera location is what makes this so difficult from the Ruby side of things.

2 Likes

I noted this too and in my script the only reliable way of tightening the box was:

  1. Change the camera view to front parallel projection
  2. Wait for Sketchup to pick up this view (in an observer)
  3. Make an idle edit to the group (add and remove an edge).

However, in the end this was all futile since Sketchup will recalculate the box when the file is opened so the change is not persistent.

(Your gif illustrates the problem nicely!)