SUFace / SUFaceIsComplex problems


I am creating an extension that traverses the SUModel using SUModelFromExisting content and retrieve the geometries of the different faces.

Everything works fine until I tried converting a model that contains a face with a hole.

Here is the model:
percee.skp (126.4 KB)

That model contains a square face that contains the hole.
When I traverse the faces, I check SUFaceIsComplex to know if there is hole or not.

SUFaceIsComplex never return true to tell me that one of the face contains hole.
All the face are considered simple and as a result I get the mesh converted without the hole as shown below.

But! If I do the same operation using SUModelCreateFromFile and traverse the face with the same code, things go differently.
SUFaceIsComplex returns true for the square plane and the code that handle the face triangulation (that take care of the hole) is reached. As a result, I’ve got the mesh correctly converted as shown below:


So the question is why faces that come from SUModelFromExisting does not handle correctly holes whereas the one that came from SUModelCreateFromFile are correct.

Does I miss something?

Thanks for your help!

there is no hole in the live model, unless you explode the cutting component/group…


Bad news :frowning:

This lead to modify the user model, which is usually not a good idea.
Is there a proper way to do that operation?

Most of the component group does not contains holes.
How can I know that a component/group explode operation is needed because it will lead to create the appropriate geometry?

I feel that this can be only done at the ruby level but I might be wrong.
Is the explode operation is undoable?


Have you thought of saving out to a temp file and then work on the temp file ?
Then it would not matter if you modify the model.

@DanRathbun I thought to such a solution, but this will result in a lack of performance as well as memory loss.
I also note that SUGroupExplode is mark as a comment, meaning that there is probably no solution through the SDK.

//SU_RESULT SUGroupExplode(SUGroupRef group, bool* is_locked);

Even if I force SUFaceIsComplex to true, the SUMeshHelperRef class does not perform the correct triangulation of the face, and the relation between the face and the cutting component is not taken into account.

Is there any way to make this relation enable in the live model situation?


maybe SUSnapToBehavior_Any can help…


@john_drivenupthewall How do you think this can be used?

Looking the component definition for the file:

the plane component_snap = SUSnapToBehavior_None
The cube component_snap = SUSnapToBehavior_Any

Playing with that setting using SUComponentDefinitionSetBehavior does not produce any different result and no hole appears.

I was thinking more as a means of finding any that have that behaviour and explode only those…



Yes that would be definitively a good idea to check this flag (or SUComponentBehavior::component_cuts_opening?) but as I can’t see any way to explode them from the SDK, I don’t know what to do with this flag! :flushed:

The “hole” caused by SketchUp cutting components is only a display feature. An actual geometric hole does not exist so the geometric database has no information about it. This is why it seems to the end user that the hole moves easily when the cutting component is moved.

The API could use C functions to get these “virtual” inner edge loops from faces that have cutting components “snapped” to them.

@DanRathbun Thanks Dan. You clear answers are really appreciated :slight_smile:

You confirm what I was feeling. Anyway, as Sketchup is able to create the geometric holes when using the SUModelCreateFromFile way, I guess that you have some internal algorithms that are able to compute such holes.

Any chance that you expose this mechanism (for example through SUMeshHelperRef) in order to get a really cut geometry?

So, until now, to have a workaround to that problem, I will perform the explode operation at the ruby level.
But what would be the correct explode operation to get the hole?

As a test, I simply tried

Sketchup.active_model.active_entities.each{|e|e.explode if (e.class==Sketchup::ComponentInstance || e.class==Sketchup::Group) }

But the result isn’t the one I expect as the hole is fill!

I have the same result with some cut on Chris head in the above model.
Chris with cut opening.skp (101.2 KB)

I can’t get the hole appear on this model and the best I get is tghe following:


Do you have any idea on the way to correctly make the holes appear?

The SketchUp application core has these methods so that the cut holes can be shown in the model view.

I do not work for Trimble. This is a question for @bugra or @thomthom.

As I said above, I agree that exposure of these “virtual” inner loops could be helpful …

My opinion applies to both the C and Ruby APIs, as coders can use both to write geometric exporters.

This confuses me. This function is used to load a SKP file into memory.

John omitted a crucial few steps.

Explode alone will not create the holes. Prior to the explode, you need to determine the edge loops that lie upon the components cutting plane.

Then after the explode use these edge loops to intersect with the model. Then erase the new faces within the edge loops.

But then you have a bunch of other geometry that would need cleaning up.

So, I’m not convinced that explode is even desired at all.
Most especially with the C API is standalone mode in a third party application environment.

@Dan About your confusion with SUModelCreateFromFile. The methods loads a SKP file but it gently performs the required process for creating the holes (look at the screenshot at the beginning of the post)

Explode alone will not create the holes. Prior to the explode, you need to determine the edge loops that lie upon the components cutting plane.

A lot of extra stuff. Implementing the feature at the display level would be easier.
With the hope that the core methods for creating holes will be one day exposed in the API, which would be very useful.


Oh WAIT! The C functions ARE there. (Sorry I forgot. It has been awhile since I read about them.)

The “virual holes” caused by cutting components are called “openings” in the C API.





The actual holes are real geometry and are inner loops (of edges.)

ADD: Note that openings have not yet been exposed to the Ruby API. I logged an issue …

SUFaceGetNumOpenings always returns 0 in the live model whereas it returns the correct number of inner loop in the from file model.

This is like if these functions were inoperative or if I missed something in the way to use it in the live situation.

Well if you believe the API is not working the way it should, please file a bug report in the public issue tracker …

You are seeing this in the 2017 version of the C API ?

If so, it is not fully compatible with the live model, yet. But they are slowly working on it, bit by bit.
It will help to have an issue for the “live” openings in the tracker.

Are you using the Live C API? If you are, on what platform are you seeing this issue?

I’m wondering if it’s related to this:

No. This is occurs even on Windows. This is due a difference of the way live and readed model are handled. I have to make an issue in gitlab. Not found the time yet!

1 Like