Collect internal and external loops of a component and apply a tag

Hello my friends, I am here again, first I would like to thank you, because of the rich discussions here, I am already managing to use my own plugin.


I make physical models and for laser cutting I needed to layer (or color) the edges, just like in the attached image, I managed a little progress with a code, but it selects all faces on the same side, I need to let the inner loop (hole) and the outer loop (outline) be distinguished, and any edge on the z face would be another tag.

clr='Gray'
rfClr='yellow'
ent = Sketchup.active_model.entities

     entities = model.active_entities

vfaces = entities.grep(Sketchup::Face) #.find_all{|f| f.normal.z != 0 }
top_faces = vfaces.select { |face|
      face.normal.samedirection?([-1,0,0])
      face.normal.samedirection?([1,0,0])
    }
vfaces = [ ]
    edge_faces = []
   top_faces.each{|top| 
   #UI.messagebox top.loops.length
   top.loops.each{|l| next if l.outer? 
   l.edges.each{|e|  edge_faces = e.faces
   edge_faces.delete(top)
   vfaces.concat(edge_faces)
   }
   }
   }
top_faces.each{|f| f.layer = 'oia' }

The blue edges makes this a tricky problem since the assembly contains no inner loops from Sketchup’s point of view, so you can’t query the existing faces for the information you want. One hackish way to solve it is to create faces that cover the holes and extract the “inner loops” from the outer loops of these faces. The code could look something like:

mod = Sketchup.active_model
ents = mod.entities

# filter out all faces
fs_all = ents.grep(Sketchup::Face)

# filter out top faces (assuming the faces have correct orientation)
fs_top = fs_all.select { |f| f.normal % Z_AXIS > 0.9999999999 }

# filter out top edges
es_top = fs_top.flat_map(&:edges).uniq

# filter out top internal edges (edges connected to two faces with vertical normals)
es_internal = es_top.select { |e| e.faces.all? { |f| f.normal % Z_AXIS > 0.999999999}}

# employ find faces on all top edges. This will create faces over the holes
es_top.each(&:find_faces)

# collect the newly created faces (fs_inner)
fs_all = ents.grep(Sketchup::Face)
fs_top_2 = fs_all.select { |f| f.normal % Z_AXIS > 0.9999999999 }
fs_inner = fs_top_2 - fs_top

# collect the outer loops of these faces (which are the inner loops (holes) of the assembly)
es_inner = fs_inner.flat_map(&:edges)

# erase the created faces (bring back the holes)
ents.erase_entities(fs_inner)

# extract the outer edges
es_outer = es_top - es_internal - es_inner

# the results are
# es_outer -> RED IN THE IMAGE
# es_internal -> BLUE IN THE IMAGE
# es_inner -> ORANGE IN THE IMAGE 
1 Like

`My brother, I have been testing the lines of your code, and it seems to me that this is the way to go, I am very anxious lol, I am awake since 5 am trying to apply the data collected in tags I thought that:

    es_outer.layer = '1'
    es_internal.layer = '2'
    es_inner.layer = '3'

it would work, but nothing happens, I already created these tags.

es_... is an array. e for edge and s for plural (edges). You can not assign a layer to an array, you need to assign a layer to the individual elements in the array.

You first need to retrieve or create the layers you want to assign. Then you go over the array and assign the layer to the individual edges

es_outer.each { |e| e.layer = appropriate_layer }