How to translate a box made by pushpull into a component? (modified post with correct coding format)

Hej guys, I am new to Ruby API and am trying to create a component (possibly with its definition) with selected face after pushpull.

I made two codes, No.1 tries to select surface and then pushpull and to make it into a component but I failed when to make component due to my limited programming knowledge in Ruby for Sketchup. No.2 works with the line but not the face.

Here is the code No.1 (failed)

# Dependencies
mod = Sketchup.active_model  # Open model
ent = mod.entities  # All entities in model
sel = mod.selection  # Current selection

# User's input
Thickness = 10

# Iterate through selection
sel.each do e # e is an element in sel and this is for loop in Ruby

  # Check face
  if e.is_a SketchupFace
  
    # Extrude 
    group = ent.add_group

    e.pushpull Thickness
    
    #comp = group.to_component (not working)
    
  end
  
end
`

Here is the code No.2 (and this works but this is based on only the selected line rather than the face that I want to select)

# Dependencies
mod = Sketchup.active_model  # Open model
ent = mod.entities  # All entities in model
sel = mod.selection  # Current selection

new_comp_def = Sketchup.active_model.definitions.add(thickness.to_s +  träregel med isolering)

#User data (input)
thickness = 220.mm
height = 3700.mm

# Get the first entity in the selection
entity = sel.first

# Get the starting point of the first entity
point_start = entity.start.position
point_end = entity.end.position


# Get the x, y, and z position of the starting point
x_1 = point_start.x
y_1 = point_start.y
z_1 = point_start.z

# Get the x, y, and z position of the end point
x_2 = point_end.x
y_2 = point_end.y
z_2 = point_end.z

point_1 = [x_1, y_1, z_1]
point_2 = [x_2, y_2, z_2]
point_3 = [x_2, y_2, z_2 + height]
point_4 = [x_1, y_1, z_1 + height]


# Actions
#group = ent.add_group (usefull)
face = new_comp_def.entities.add_face point_1, point_2, point_3, point_4
face.pushpull thickness

trans = GeomTransformation.new
Sketchup.active_model.active_entities.add_instance(new_comp_def, trans) 
`

I would like to get some tips for No.1 code to make the volume of pushpulled and selected face into a component with its definition.

Thank you so much for the help!

Pleas post code not images of code. Periodically the server has lost all images for the forum.


To make a component. Start by adding a new Defintion to the model’s DefinitionList collection.
Then add your edges and faces to the definition’s Entities collection, instead of the model’s.
Lastly add an instance of the new definition to the model’s Entities collection at some tranformation.

Please correct your post to properly delimit code in the forum.

Sorry for the mistake of posting.

I made two codes, No.1 tries to select surface and then pushpull and to make it into a component but I could not due to my limited programming knowledge in Ruby API for Sketchup. No.2 works with the line but not the face.

Here is the code No.1 (failed)

# Dependencies
mod = Sketchup.active_model  # Open model
ent = mod.entities  # All entities in model
sel = mod.selection  # Current selection

# User's input
Thickness = 10

# Iterate through selection
sel.each do e # e is an element in sel and this is for loop in Ruby

  # Check face
  if e.is_a SketchupFace
  
    # Extrude 
    group = ent.add_group

    e.pushpull Thickness
    
    #comp = group.to_component (not working)
    
  end
  
end
`

Here is the code No.2 (and this works but this is based on only the selected line rather than the face that I want to select)

# Dependencies
mod = Sketchup.active_model  # Open model
ent = mod.entities  # All entities in model
sel = mod.selection  # Current selection

new_comp_def = Sketchup.active_model.definitions.add(thickness.to_s +  träregel med isolering)

#User data (input)
thickness = 220.mm
height = 3700.mm

# Get the first entity in the selection
entity = sel.first

# Get the starting point of the first entity
point_start = entity.start.position
point_end = entity.end.position


# Get the x, y, and z position of the starting point
x_1 = point_start.x
y_1 = point_start.y
z_1 = point_start.z

# Get the x, y, and z position of the end point
x_2 = point_end.x
y_2 = point_end.y
z_2 = point_end.z

point_1 = [x_1, y_1, z_1]
point_2 = [x_2, y_2, z_2]
point_3 = [x_2, y_2, z_2 + height]
point_4 = [x_1, y_1, z_1 + height]


# Actions
#group = ent.add_group (usefull)
face = new_comp_def.entities.add_face point_1, point_2, point_3, point_4
face.pushpull thickness

trans = GeomTransformation.new
Sketchup.active_model.active_entities.add_instance(new_comp_def, trans) 
`

I would like to get some tips for No.1 code to make the volume of pushpulled and selected face into a component with its definition.

Thank you so much for the help!

Try this… I have no tested

mod = Sketchup.active_model  # Open model
ent = mod.entities  # All entities in model
sel = mod.selection  # Current selection

# User's input
Thickness = 10

# Iterate through selection
sel.each {|e|
  # Check face
  if e.is_a? Sketchup::Face
    # Extrude
    e.pushpull(Thickness, true)
  end
  }

Hi Rafa,

Thanks for response!

This is exactly what I did. But this one only works for pushpull that creates seperate edges and faces not including a component as whole part.

You should make the group (with the face inside) first and iterate inside it’s entities to find the faces. You are iterating the selection.

1 Like

This works

mod = Sketchup.active_model  # Open model
ent = mod.entities  # All entities in model
sel = mod.selection  # Current selection

# User's input
Thickness = 10
onlyFaces = sel.grep(Sketchup::Face)
# Iterate through faces
onlyFaces.each {|f|
  group = ent.add_group(f)
  f.pushpull(Thickness, true)
  status = group.to_component
  }

if you only want a group remove the line status = group.to_component

1 Like

This should be …

ent = mod.active_entities

… otherwise, if the user is within a group or component editing context, SketchUp can crash when the #add_group(face) call is made.

In other words, the new group and the drawing element arguments must be in the same editing context (which is normally the active_model.active_entities.)


Your closing } should be lined up with the line with it’s opening {, ie …

# Iterate through faces
onlyFaces.each { |f|
  group = ent.add_group(f)
  f.pushpull(Thickness, true)
  status = group.to_component
}

The reason is that the indent guidelines in your editor will not help you line up the start and end of code blocks.

Ie, wrong:

image

Ie, correct the guideline shows the start of the block lined up with the end of the block:

image

1 Like

This reference should be: thickness

In Ruby constants and specifically module and class identifiers start with a capital character.
They are also CamelCase (aka SnakeCase,) with no spaces and each word starting with a capital letter.

Local variables are all lower_case with underscore character in place of spaces.

See also: UI.inputbox for getting input values from the user.


Actually the #each iterator that most collections in Ruby have is not exactly a for loop.

Ruby does have a dedicated for loop. It looks like this …

for e in sel
  # do stuff with e here ...
end

The difference in Ruby is that #each is a method call and for is an interpreter function.
(It used to be that for was faster, but not so much anymore with Ruby 2 and higher.)


Code should seek to identify the specific face to operate upon.

Since in this scenario there is only 1 face, there is no need to iterate the selection or the new group.
So the each loop can go away …

face = sel.grep(Sketchup::Face).first
if face # nil if grep found no faces
  group = ent.add_group(face)
  # Just in case SketchUp gave the face a new reference:
  face = group.grep(Sketchup::Face).first
  face.pushpull(thickness, true)
  inst = group.to_component
  inst.definition.name= "Box Component"
  inst.name= "Box 1"
end
1 Like

Thank you very much for the correction!! The code with your help works very well in practice! Cheers!

Thank you so much for your patience and deep explanations of the theory ! And now the code with your help works very well!

1 Like