Convert the faces of one component to multiple components

Hello,

I drew a simple textured box which I converted into a component.

I would now like to convert all the faces of this box into component:

mod = Sketchup.active_model
sel = mod.selection
ents = mod.active_entities
mod.start_operation('Convert faces to components', true)  
sel.grep(Sketchup::ComponentInstance).each do |s| 
  s.definition.entities.grep(Sketchup::Face).each do |f|
    grp = ents.add_group(f)
    inst = grp.to_component
    defn = inst.definition
    defn.invalidate_bounds
    defn.name = "Component#1"
    tr = inst.transformation
    pts = tr.origin    
    s.definition.entities.add_instance(defn, pts)
    inst.erase!
  end
end
mod.commit_operation

This method works but there are still faces in my box which mix with the instances.

If I aunt delete the faces with ā€œf.erase!ā€ all faces even those of new instances will be deleted.

Do you know how to avoid this problem?

Thank you in advance for your help.

When asking for help with a problem or test model, post the model in the initial question post.

BTW ā€¦ you cannot name all of the face component definitions with the same string.

You can, but if a component already exists with that name #n is appended to the name. IOW no error the name might just not be what you expect.

1 Like

I suppose I should have said ā€œshould notā€ ā€¦ :wink:

1 Like

Each definition name will take a new # number.

Here is as requested the BOX component once I have applied my method.

BOX.skp (101.6 KB)

It looks correct to me ā€¦

Surprising because with me there are still faces and edges that I cannot delete without affecting the new instances.

I just opened the box.skp file and indeed the problem disappeared with saving and opening the file.

Here is the initial box component:
BOX 2.skp (69.6 KB)

Apply my method and can you tell me if you encounter the same bug?

Thank you

Sketchup crashes after I close the project.
Thereā€™s something Sketchup doesnā€™t like it fixing on opening or saving.
It would be interesting to know which methods are executed in both cases so that I can do like Sketchup directly in my code.

What version of SU? From the screenshot it looks like a rather old version, like SU8 or older?

Well seen, this is Sketchup 2014 PRO.

Iā€™m not sure if the code produces the same error on a newer version of SketchUp.
I also tried with SketchUp Make 2017 and the crash occurs when closing or opening a new project.

I even tried your CleanUpĀ³ extension to see if it fixes the faces error produced by my code and the error is beyond repair.

I donā€™t know if my code is badly written or if it is impossible to convert all the faces of a component into a component?

Iā€™m exploring a lot of avenues because I donā€™t like to give up when I want to do something in ruby.
I donā€™t know if itā€™s a quality or a flaw to strive to find solutions because it wastes a lot of time but ended up bringing a lot of learning.

Have you submitted the BugSplat? (If so, did you enter any details into the report that we can use to look it up?)

As this is a BugSplat committed by my code, I did not submit the error because the error can come from my method.
I wrote a new method which after transforming the faces of my box into components exports the box to a plugin folder.
This method then removes the instance and the definition from the list to import the previously exported cube.

The goal is to force SketchUp to fix the bug and I get this error message:

Message d'erreur

Whatever I choose in the options offered, the cube is imported but it is invisible in the project even if it is perfectly displayed in the components and structures window.
In the end, even importing into SketchUp does not correct the error.

FYI: I opened in the latest version of SketchUp. I did notice that it was a v14 file, but as your forum profile indicates v17 I thought perhaps you might have back saved it to 14.

There have been quite a few bug fixes including fixes to the SKP file format post v17.

I just updated my information so that SketchUp 2014 appears.

For the 2014 version, I donā€™t have a solution:

  • The load method interrupts the method and sends the error message to force the face correction.

  • The Import method also interrupts my method because the user has to manually position the box on the Stage. (To my knowledge this method does not allow an import with defined 3D points.)

  • The import method in the definition list only exists as of SketchUp 2021.1.

Iā€™ll install a newer version of SketchUp to see if my method works better.
However, my goal is to find a solution that works from SketchUp 2014.

Okay ā€¦ in SU2021 (21.1.332) ā€¦

I imported your ā€˜BOX 2ā€™ component, then exploded the extra context that import adds.

I selected the Box instance and ran your test method ā€¦

def test
  mod = Sketchup.active_model
  sel = mod.selection
  ents = mod.active_entities
  mod.start_operation('Convert faces to components', true)  
  sel.grep(Sketchup::ComponentInstance).each do |s| 
    s.definition.entities.grep(Sketchup::Face).each do |f|
      grp = ents.add_group(f)
      inst = grp.to_component
      defn = inst.definition
      defn.invalidate_bounds
      defn.name = "Component#1"
      tr = inst.transformation
      pts = tr.origin    
      s.definition.entities.add_instance(defn, pts)
      inst.erase!
    end
  end
  mod.commit_operation
end

And YES ā€¦ I also see the funky phantom faces (left behind in the parent definitionā€™s entities) that are somehow still connected to the child face component instances. Weirdly, 3 of the phantom faces are in the same position as their ā€œcloneā€, but 3 are directly across the cube from their clone (given a stacked face scenario. As there are textures on both sides we see z-fighting as the view is orbited.)


Well, see faces are special in that they also have vertices and edges attached that can be (and in this situation are) shared with other faces.

So trying to rip out faces from an entities context and move them into a group may not be the best paradigm.

I would say instead, (one by one) create a new component definition, and use the vertex positions of the existing faces to recreate the face in the new definition(s) also copying properties like material texture, etc. Then erase the old faces and replace with a new face component instance in the same location.

2 Likes

Thanks to your advice I managed to do what I wanted:

mod = Sketchup.active_model
sel = mod.selection
ents = mod.active_entities
defs = mod.definitions
mod.start_operation('Convert faces to components', true)  
sel.grep(Sketchup::ComponentInstance).each do |s|
  s.definition.entities.grep(Sketchup::Face).each do |f|  
    mat = f.material 
    normal = f.normal  
    uv_helper = f.get_UVHelper(true, true)   
    mapping_front = []      
    f.outer_loop.vertices.each do |vert| 
      mapping_front << vert.position
      uvq = uv_helper.get_front_UVQ(vert.position)
      mapping_front << Geom::Point3d.new(uvq)
    end   
    edg = []
    f.edges.each{|e| edg << e}      
    grp = ents.add_group(edg)
    inst = grp.to_component
    defn = inst.definition
    defn.name = "Component#1"
    tr = inst.transformation
    inst.erase!
    pts = tr.origin        
    s.definition.entities.add_instance(defn, pts) 
    f.erase!      
    defn.entities.grep(Sketchup::Edge).each{|e| e.find_faces }
    defn.entities.grep(Sketchup::Face).each do |f|
      face_normal = f.normal
      if face_normal != normal
        f.reverse!
      end 
      f.material = mat  
      material_front = f.material = mat
      f.position_material(material_front, mapping_front, true)        
    end      
  end
  s.definition.entities.grep(Sketchup::Edge).each{|e| e.erase!}
end
mod.commit_operation

With this Sketchup method no longer crashes because the cube no longer has phantom faces and edges.

Another problem:
If I use ā€œposition_materialā€ on a more complex form like an exagon, I get this error message:

Error: # <ArgumentError: Wrong number of points: must be between 2 and 8>

If you want to see what Iā€™m talking about, try my method on this shape:
EXAGON.skp (41.6 KB)

How to recover the UVQ coordinates on a face with more than 4 vertices?

Please search this forum on that method name, and if you do not find the answer begin a new topic.

Sorry Dan for bouncing off another issue so quickly while the basic topic is resolved!
Finally I found out how to recover the UV from a face with more than 4 vertices to apply them to any other face.