Reversed Faces Method for Manifolds

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 = Set.new
        
        while face_stack.length > 0 do 

            face0 = face_stack.pop
            processed.add(face0)
            
            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)
                face_stack.push(face1)
                processed.add(edge)
            }
        end
    end

    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]
    end

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 
    end

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

1 Like