Reversed Faces Method for Manifolds

SketchUp really should provide a method in the API for detecting and/or correcting reversed faces in manifolds.

I have yet to come up with a really efficient and successful way of dealing with reversed faces.

1 Like

SketchUp shouldn’t even mark mixed faces manifolds as Solids.
It should detect if manifolds have their faces:

  • all white outside > Solids
  • (all back faces outside > “Solid Void”)
1 Like

I think it lies in the SketchUp concept to be forgiving, but I really like the concept of solid voids, as it is a perfectly valid topology.

1 Like

I think the issue is differentiating ‘voids inside solids’…

the check needs to to all

‘back faces face back faces’ > “Solid with or without Void”…


Have you cribbed my ‘solidsolver’ code ?
Around line #456

# Based on Shellify by Anders Lyhagen && some later TT's recoding
# methods added/adjusted by TIG
  class Shell

If checks the surfaces of a known solid and tries to reverse them all ‘outwards’ where necessary.
It finds connected surfaces and does a centered raytest to find if a face is reversed etc and fixes it…
It seems to work in most cases,

1 Like

I know, but I wasn’t ready yet.
I know that a void inside a Solid (the grouped geometry) subtracts from the Solid. At least that is what it should do. Whatever the outcome of ones geometry, all faces should have their back towards where the material is, irrespective of how many manifolds are in the same grouped environment, resulting in a SketchUp Solid.

I guess so. But people learn fast enough. Questioning “why isn’t my manifold seen as solid?” You make that mistake once and never forget. Unlike with wresteling with a face that looks planar but inreality isn’t. SketchUp has its tolerance and cannot do without.

I should probably take a second look at your code. I’ve previously tried to come up with my own “simple” algorithm but it fails for certain solids.

Wouldn’t a center ray test potentially fail with a convoluted solid like this roof?

Actually, with this example I can easily check the Z component of the face normal (of the inclined roof planes) and determine if it is positive or negative which tells me which face(s) to reverse. The bottom face is also another easy check of the face normal to see if it is parallel (same direction) to the Z axis.

The problem is when I have some gable ends added to the mix, with randomly reversed faces.

I can quite easily determine those vertical faces (gable ends) however it is not readily apparent on how to determine if they are reversed or not. One thought is to compare them to a properly oriented bottom face or inclined (faces) and then cheat it this way.

Test it…

In the example you illustrated each of the roof face.normal.z are > 0
So for each face, if it’s correctly oriented OK… but if it’s not, then reverse that face…

My ‘Shell’ code is probably too complex for what you want !
A simple face.normal.z check with a face.reverse if NOT should suffice…

To check the gable-faces orientation you could check everything else first, then deal with just the vertical faces…
Compare their normal orientations with adjoining face.normal results.
If necessary, reverse the gable-face to match…

1 Like

You’ve just confirmed what I thought might be the simplest solution to this problem.

Here is a snippet from a previous post that I am still wrapping my head around how it is supposed to work:

face1.reverse! if edge.reversed_in?(face0) == edge.reversed_in?(face1)

A face is oriented according to its face loop. If the face loop is counter clockwise as seen from the camera you will see the front material.

If you look in the first image below, there are two faces sharing an edge. In order for BOTH faces to be correctly oriented the face loops at the edge must use the edge in opposite directions. For a solid to be consistently oriented, then for every edge the two connected faces must use the edge in opposite directions.

face1.reverse! if edge.reversed_in?(face0) == edge.reversed_in?(face1)

This code reverse face1 if we have the situation in the second image. That is, we know that face0 is correctly oriented. If face1 uses the common edge in the same direction as face0, then it must be reversed.

Thus, if we start with a face that we know is correctly oriented we can orient all other faces in the solid consistently by unwinding the geometry from the start face.



In my suite of Plugins, FredoTools, there is one tool called AutoReverseFaces. It normally works on true manifold solids, but also on pseudo-solids, independently of the view camera.

Can you try it on one of your roofs and see if it does the job.

If so, I’ll post the algorithm.

1 Like

Sure, I’ll give it a try.

Now I’m just trying to think up the best way (most efficient) to cycle through each (wall) vertical face and then grab an adjacent face (and its common edge) without having to eat up too much processing power.

The good news is that no two vertical faces will ever be adjacent to each other, so every vertical face will be surrounded by inclined faces (or in some cases, the bottom face) that are all correctly oriented.

Here is my first crack at it:

@wall_faces = @all_roof_faces.find_all {|f| f.normal.perpendicular?(Z_AXIS) }

@wall_faces.each do |w|
	edgelist = w.edges
	ce = edgelist[0]
	facelist = ce.faces
	adjface = facelist.find {|a| a != w }

	w.reverse! if ce.reversed_in?(adjface) == ce.reversed_in?(w)


It is a little verbose, so I can probably declare a few less variables and make it more compact, but I think it might work.


Since I’ve already collected the inclined roof faces in a previous section of code, I will replace the first line with this:

@wall_faces = @all_roof_faces - @roof_faces

Slightly compressed, yields this block of code:

@wall_faces = @all_roof_faces - @roof_faces

@wall_faces.each do |w|
	ce = w.edges[0]
	adjface = ce.faces.find {|a| a != w }
	w.reverse! if ce.reversed_in?(adjface) == ce.reversed_in?(w)

Since I’ve managed to deal with all of the inclined roof faces and bottom face previously and the wall faces are always adjacent to only properly oriented faces the solution is actually relatively simple.

This still does not fully solve my quest for a general method to check manifolds for reversed faces but it does solve my immediate problem.

Or just post a model with mixed reversed faces and I will check

1 Like

Give this one a go:

Turn off the sheathing layer, and you can delete or ignore the roof outline group (blue).

I’m mostly interested in the roof primitive (lumber color). This group should be a solid and it needs to be clean (no reversed faces).

With my current algorithm the roof primitive is a solid and the reversed faces are now eliminated, you can verify per the model.

The reason that I want it to be a valid solid is that it should be available to the user to perform additional boolean operations with SketchUp’s or @Eneroth3’s solid tools. And just as a plug for Eneroth’s tools, I will say that they do have some distinct advantages over the built in tools.

1 Like

It seems to work fine.

But this is somehow normal because your roof is based on solids, since you keep the horizontal base.

I’ll make more thorough tests tomorrow to see what happens in degraded conditions, when the roofs elements are not solid.


I don’t think that will work because you just randomly access the faces in your face array. What you need is something like a flood fill, that is, you start with a correct face and then you unwind the geometry from there, reaching new faces from faces already processed and so on.

Something like:

    def self.orient_faces(start_face)
        face_stack = [start_face]
        processed =
        while face_stack.length > 0 do 

            face0 = face_stack.pop
            face0.edges.each { |edge|
                next if processed.include?(edge) 
                face1 = get_other_face(edge, face0)                     
                next if face1.nil? || processed.include?(face1) 
                face1.reverse! if edge.reversed_in?(face0) == edge.reversed_in?(face1)

    def self.get_other_face(edge, face)
        return nil if edge.faces.length == 1
        return edge.faces[0] == face ? edge.faces[1] : edge.faces[0]

The only problem remaining is to find a start face and orient it correctly. I think something like the below will work:

    def self.get_start_face(ents)
        vxs = ents.grep(Sketchup::Edge).map{ |e| e.vertices}.flatten!.uniq!
        max_vx = vxs.max_by { |vx| vx.position.z }
        min_e = max_vx.edges.min_by { |e| 
            (e.start.position - e.end.position).normalize!.z.abs 
        max_f = min_e.faces.max_by { |f| f.normal.z.abs }
        return max_f.normal.z < 0 ? max_f.reverse! : max_f 

Send in an array with all the faces in your solid and you should get a correctly oriented start face in return.

1 Like

Even though my current algorithm works for what I currently have, I may have use for a more general solution as my roof primitives are going to get a lot more ugly with the introduction of the secondary roof concept (ie. connecting two complex roofs together).