Detect the doors exists in which face

hello everyone,

i have a model and i need to detect which face contains a door, i managed to detect windows using the outer and inner loops but it doesn’t work on doors as the door has an edge that is common between the face and the floor.

this is the code i use to detect windows and find to which face they belong:

model = Sketchup.active_model
ents= model.active_entities
ents.each do |f|
if f.is_a? Sketchup::Face
inner_loops = (f.loops - [f.outer_loop])
   nested_faces = []
   inner_loops.each{|loop|
  loop.edges[0].faces.each{|e|
     nested_faces << e unless e == f
  }
   }
   if nested_faces.empty?
  
  UI.messagebox("Face: #{f.material.display_name} has no windows ")
	  
   else
 
   nested_faces.each{|ff|
 
	 UI.messagebox("Face: #{f.material.display_name} contains the window #{ff.material.display_name} ")
  
   }
  
   end
   end
   end

how can i change my code so that it detects doors also ?
thnx a lot.
that’s the model where i’m testing the windows’ detection.
windows model.skp (723.1 KB)

add your example skp and edit your code block so it works on your model…

you should know to do this by now…

to expect people to make a model, add the missing bits to your code and offer you a solution, is asking too much… [IMHO]

we don’t get paid to help, so make it as easy as possible to test what you have and you are more likely to get answers…

john

1 Like

hello sir thank you so much for your advice, i did upload on which i’m testing the windows and doors detection, i tryed to solve this problem but it seems to show the door as an independent face and not as a part of an other face.
it gets the windows and show to which face they belong but not the door it shows it as a face with no windows.

thank you for your answer and sorry for any disturbance.

I had the same problem once and detecting doors is a bit icky. Specifically, because “door” is quite hard to define in terms of faces shared edges with some outer wall. For example corner-windows, doors drawn with an offset (now they look exactly like windows), divided walls etc.

I kinda solved it by grouping faces belonging to a wall (connected and same plane), find the outer edges to this group (1, 2), use the face which shares the most edges as my BaseWall. From that, I use the inner-loops to get the windows and then only Doors should be left. But since there are quite a few special cases I denote them as Subwalls and let the user select doors by hand. If you can be certain in how a model is created, it could be enough for you.

1 Like

can you explain the part “grouping faces belonging to a wall (connected and same plane)” also yes there may be some walls that are divided into two subwalls so will that cause a problem ?

def group_by_walls(faces)
  result = []
  queue = faces

  # Uses a queue to remove utilized faces
  until queue.empty?
    curr = queue.pop
    same = get_connected_faces_on_plane(curr)
    result << Wall.new(same)
    queue -= same
  end
  result
end

  # Return list of connected faces that have the same plane
def get_connected_faces_on_plane(face)
  result = {}
  queue = [face]
  until queue.empty?
    curr = queue.pop
    next if result.key? curr
    result[curr] = curr
    same = get_connected_faces(curr).select { |x| same_plane?(curr, x) }
    same.each do |f|
      queue << f
    end
  end
  result.keys
end

  # Return list of faces that share the same edges
def get_connected_faces(face)
  edges = face.loops.map(&:edges).flatten.uniq
  edges.map(&:faces).flatten.uniq - [face]
end

  # True if a and b share the same plane
  def same_plane?(a, b)
    a.plane[1..-1].zip(b.plane[1..-1]).select do |x, y|
      (x - y).abs > 0.001
    end.empty?
  end

than you so much.
What does Wall.new(same) do ?
there is also a case like the model bellow, will it cause a problem as there are 2 windows linked to a door is it possible to detect that the 3 faces (2 windows and 1 door) belong to the green wall ?

data extraction.skp (190.0 KB)

Wall.new(same) creates a Wall object that has a few more methods and stores the faces associated with a specific wall. You’d need to modify that or use your own implementation. Please note that “Wall” is loosely defined too, if your gable were on the same plane, it too would be part of the “Wall”.

With my algorithm the two bottom windows and door would be Subwalls initially and would need to be assigned Window and Door respectively by the user. You can do this by using a specific material for those entities or add a key to its dictionary.

There are a few more special cases and I didn’t want to invest more time in solving the issue completely, so I left it to the user.

1 Like

i separate between walls and windows by material types so how can change the “Wall.new(same)” as when i store the “same” directly it shows an error as it’s an array ? how is your “Wall” represented so as to know what is stored in the “result” variable ?