Adding labels to specific faces of a model

As part of our business process, my company exports an image of our model to present to the customer with labels on specific faces of the model. I have already solved the image export part of the process (see this post for the question I asked and some possible solutions, including the one I implemented), but I am a little bit stuck on adding labels because I am having trouble selecting the specific faces that need to be labeled.

To give a little background on this, our models will look similar to this screenshot below (this shows the default orientation; up is north and the z-axis is coming out of the screen towards the user):

I want to label only the two faces that have the rows of black solar panels on them, but I have had no luck coming up with a good set of criteria that isolates these faces from the other faces in the Sketchup.active_model.entities collection. The solar panels are a custom component that is placed on the face, so I would imagine there is a way to check that, but I don’t know how to do that, so a nudge in the right direction or a quick example of how to do so would be fantastic.

Thanks in advance for any help provided.

UPDATE: I ended up going a slightly different direction than I intended when I began this post. Because of the way the solar panels are put onto the roof plane, they are not actually attached to the roof plane in any way (as far as I can tell), so my solution was to add a text label directly above the group of solar panels instead of trying to label the associated roof plane. I did this by inserting a text label at a point directly above the center point of the group (local_bounds.center).

EDIT: I ended up changing my solution again. I found a way to reliably find which roof planes have a solar panel group “on” them by extending the bounding box of the roof plane in both +/- Z direction and then checking each Sketchup::Group element in the model to see if there is a Group whose bounding box falls within the roof plane’s enlarged bounding box (see here for more info about the BoundingBox class). If a Group falls within the enlarged bounding box, then there are solar panels on the roof, if no group falls within the enlarged bounding box, there are no solar panels on that roof plane. I filtered out the roof planes that need to be checked by looking for a normal vector with a rounded Z-component greater than 0 (face.normal.z.round > 0).

Let us assume that you have a reference to a solar panel, named sp.

You can find one of these simply enough using the Enumerable library methods that are mixed into SketchUp::Entities class objects (as well as most other API collection classes.)
I posted examples here in the forum:

Now,… if the component was set up as a glue to component, then you can get the face the instance is “snapped” to:

mounting_surface = sp.glued_to()

See:

And,… if the component was NOT set up as a glue to component, then it should be.

To do it manually, see the user guide on “choosing alignment options”:

To do it via code see:

And the Behavior class:

Thanks for the quick reply @DanRathbun. On closer inspection, the solar panels themselves are a component, but they are inserted as a group using the Skelion plugin, and when I try to call the glued_to() method on an individual panel, it comes back as nil, so I don’t think the panels themselves are associated with the face. Is there some way to associate a group with a face? If so, how would I retrieve the face that the group is associated with since the Sketchup::Group class doesn’t have a glued_to() method?

For the record, it has been requested to expose these methods, because a group is actually a special component instance, whose definition has it’s group? flag set to true.


Firstly you can try and be certain whether these panel components have their behavior set correctly. (Check their definition’s behavior.) If not, either you’ll need to edit them yourself (start a custom component library,) or contact the author of the component and ask that their snap behavior be set correctly.


Perhaps ask the Skellion author to add an option to wrap the panel set in a component instead of a group.


You might be able to convert the outside group to a component thus:

grp.definition.behavior.snap_to= SnapTo_Sloped
instance = grp.to_component
face = instance.glued_to
puts "face is: "<< face.inspect

(untested)

If it doesn’t work, the new component instance may need to be replaced …

xform = grp.transformation
# do the component conversion
cdef = instance.definition
entities = instance.parent.entities
instance.erase!
# make a new clone of the instance in the correct entities
instance = entities.add_instance(cdef,xform)
# then check the face again ...
face = instance.glued_to
puts "face is: "<< face.inspect

Here is another possible brute force search:

# Given a solar panel object referenced as "sp", and
#   a reference to the entities context of the faces ...
xform = sp.transformation
sp_ip = xform.origin
faces = entities.grep(Sketchup::Face)
found = faces.find {|face|
  sp_ip.on_plane?(face.plane)
}
if found # nil if not found
  # use the found face
end

It is possible that if the faces and the sp insertion point are in different contexts, you’ll need to transform the sp_ip point using the grp.transformation, …

sp_ip = xform.origin.transform( xform * grp.transformation )

… if the grp and the faces are in the same context.

ADD: You can do the same thing with the Skellion group’s transformation if you KNOW that you are using an “OnFace” inference to place the panel group. Meaning you can use the group’s transformation.origin as the test point for on_plane?(face.plane).

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.