Why am I inconsistently getting my outer faces going the right direction

@DanRathbun @dezmo
I have created a solution that works using some code I found here and I also added some code in to elucidate what exactly it is that I am doing. I haven’t tried it yet on multiple faces but this solution should work for anyone where the bottom face is on a single plane.

SKETCHUP_CONSOLE.clear
Sketchup.file_new
module Example
  extend self
  # Default code, use or delete...
  mod = Sketchup.active_model # Open model
  ent = mod.entities # All entities in model
  sel = mod.selection # Current selection

  # add first group
  group = ent.add_group

  # add face to first group and get the edges to be followed.
  face = group.entities.add_face [0,0,0],[0,10,0],[10,10,0],[10,0,0]
  face.reverse! unless face.normal.z == 1
  edges_to_follow = face.edges

  # from a different part of the program
  inversion = true

  # add group2
  group2 = ent.add_group
  face_g2 = group2.entities.add_face [[-1,-1,-1], [-1,11,-1], [11,11,-1], [11,-1,-1]]
  face_g2.reverse! unless face_g2.normal == 1
  face_g2.pushpull 2

  # find the e1_direction
  e1_dir = edges_to_follow[0].line[1]

  # move the edges out of the way.
  transform = Geom::Transformation.new([0,0,10])
  group.entities.transform_entities(transform, edges_to_follow)

  # minimum xy corner value
  min_v = [0,0,0]

  # various modifiers
  d = 1
  z = 1
  o = 0

  # vectors for cuts
  cut_vector = [-d,d,-z-o]
  up_vector = [d,d,z-o]
  down_vector = [d,d,-z-o]
  trim_vector = [-d,d,z-o]

  # add trimmer_group
  trimmer_group = ent.add_group
  trimmer_pts = [ min_v.offset(cut_vector),min_v.offset(trim_vector),min_v.offset(up_vector),min_v.offset(down_vector)]
  trim_face = trimmer_group.entities.add_face trimmer_pts


  p " trim_face direction = #{trim_face.normal}"
  trim_face.reverse! unless trim_face.normal.samedirection?(e1_dir)
  p " trim_face direction = #{trim_face.normal}"
  trim_face.followme edges_to_follow

  pts = [ min_v.offset(cut_vector),min_v.offset(down_vector),min_v.offset(up_vector)] 

  # add cut face
  cut = group.entities.add_face pts
  p " cut direction = #{cut.normal}"
  # make cut face follow edges
  cut.reverse! unless cut.normal.samedirection?(e1_dir)
  p " cut direction = #{cut.normal}"

  cut.followme edges_to_follow

  group.entities.erase_entities(edges_to_follow)

  def getOtherFace(e, f)
    f1 = e.faces[0] == f ? e.faces[1] : e.faces[0]
    return nil if f == f1
    return e.reversed_in?(f) == e.reversed_in?(f1) ? f1.reverse! : f1
  end

  def getShell(start_face)
    front_q = []  #unprocessed shell faces
    face_h  = {}  #hash with expanded faces
    edge_h  = {}  #Hash with expanded edges 
    shell_h = {}  #final shell

    #push start face
    front_q.push(start_face)
    face_h[start_face] = nil

    while front_q.length > 0 do 
      f = front_q.pop
      shell_h[f] = nil
      f.edges.each { |e|
        next if edge_h.has_key?(e) || e.faces.length <= 1 
        edge_h[e] = nil
        f1 = getOtherFace(e, f)                     
        unless f1 == nil || face_h.has_key?(f1)  
          front_q.push(f1)
          face_h[f1] = nil
        end
      }
    end

    return shell_h
  end

  # get all faces 
  c_faces = group.entities.grep(Sketchup::Face)
  if trimmer_group
    t_faces = trimmer_group.entities.grep(Sketchup::Face)
  end

  if inversion == true
    # for cut
    b_face = c_faces.find{|f| f.normal.parallel?(Z_AXIS)}
    b_face.reverse! unless b_face.normal.z == -1
    getShell(b_face)
    # for trimmer group.
    if trimmer_group
      b_face_t = t_faces.find{|f| f.normal.parallel?(Z_AXIS) && [1,2,4].include?(f.classify_point(min_v.offset(cut_vector)))}
      b_face_t.reverse! unless b_face_t.normal.z == -1
      getShell(b_face_t)
    end
  else 
    # for cut
    t_face = c_faces.find{|f| f.normal.parallel?(Z_AXIS)}
    t_face.reverse! unless t_face.normal.z == 1
    getShell(t_face)
    # for trimmer_group
    if trimmer_group
      b_face_t = t_faces.find{|f| f.normal.parallel?(Z_AXIS) && [1,2,4].include?(f.classify_point(min_v.offset(cut_vector)))}
      b_face_t.reverse! unless b_face_t.normal.z == 1
      getShell(b_face_t)
    end
  end

  g2 = trimmer_group.subtract(group2)
  group.outer_shell(g2)
end