Hi guys! Last time I was trying to create two boxes (wall layers) attached together by selecting a face. The method in Ruby was to select the face, push-pull, get vertices of the loop of the face, change coordination of the vertices that create a new face then push pull. I managed to do it with help from here. Really appreciate!
Now I am trying to use another method ‘Geom::Transformation’ to reach the result. The process is like: 1.select the face, 2.push-pull, 3.move the face, 4.push pull again. The direction of the push-pull and the move is the same. (please see image) The process might be simple in Grasshopper but not in Ruby.
mod = Sketchup.active_model # Open model
ent = mod.entities # All entities in model
sel = mod.selection # Current selection
# Default values
material_1 = "CLT"
material_2 = "CLT"
thickness_1_prompt = 100.mm
thickness_2_prompt = 30.mm
# Create a new group for the face(s) selected by the user
only_faces = sel.grep(Sketchup::Face)
#mod.start_operation('Push_test_a', true)
only_faces.each do |f|
group_1 = ent.add_group(f)
f.pushpull(thickness_1_prompt)
# Calculate the translation vector based on the push direction
push_direction = f.normal # push-pull's direction
translation_vector_for_2 = push_direction.reverse * thickness_1_prompt # push-pull's vector
#translation_vector_for_2 = push_direction.transform(Geom::Transformation.scaling(thickness_1_prompt)) # another way
# Create a transformation that represents the translation
translation = Geom::Transformation.translation(translation_vector_for_2)
# Transform the face by applying the translation transformation
f.transform!(translation)
# Push-pull the transformed face
f.pushpull(thickness_2_prompt)
end
#mod.commit_operation('Push_test_a')
But it always shows the error: “Cannot convert argument to Geom::Vector3d” whatever I type for the vector
The Vector3d #* method is used to compute the cross product between two vectors.
Where the parameter should be Geom::Vector3d, however you are using thickness_1_prompt = 100.mm which is a Length, not a Vector3d. That is a reason you get an error message.
I assume you want to set the vector length, so you need to use
the Vector3d #length= method to set the length of the vector.
Hi, Dezmo, thanks for the reply.
Now I tried ‘length’ to move the selected face ‘f’ as you said and the modification is below.
mod = Sketchup.active_model # Open model
ent = mod.entities # All entities in model
sel = mod.selection # Current selection
# Default values
material_1 = "CLT"
material_2 = "CLT"
thickness_1_prompt = 100.mm
thickness_2_prompt = 10.mm
# Create a new group for the face(s) selected by the user
only_faces = sel.grep(Sketchup::Face)
#mod.start_operation('Push_test_a', true)
only_faces.each do |f|
group_1 = ent.add_group(f)
f.pushpull(thickness_1_prompt)
# Calculate the translation vector based on the push direction
push_direction = f.normal # push-pull's direction
translation_vector_for_2 = push_direction.reverse # push-pull's vector
translation_vector_for_2.length = thickness_1_prompt = 100.mm # Set the desired distance
# Apply the transformation to the face
face_2 = f.transform!(Geom::Transformation.translation(translation_vector_for_2))
# Push-pull the transformed face by thickness_2_prompt
face_2 = f.pushpull(thickness_2_prompt)
end
#mod.commit_operation('Push_test_a')
But now another problem comes that whatever I put ‘transform!’ or ‘transform’ for ‘face_2’, it gives me ‘undefined method ‘transform! (transform)’’ when I select the face in Sketchup and run the code. Do you think what the problem is or there are other methods to get the same result? Thank you!
After checking again you original post… I would do something like this:
mod = Sketchup.active_model # Open model
ent = mod.entities # All entities in model
sel = mod.selection # Current selection
material_1 = "CLT"
material_2 = "CLT"
thickness_1_prompt = 100.mm
thickness_2_prompt = 10.mm
only_faces = sel.grep(Sketchup::Face)
mod.start_operation('Push_test_3', true)
only_faces.each do |f|
group_1 = ent.add_group(f)
f.pushpull(thickness_1_prompt)
# find new face creted pararell to 'f'
face_2 = group_1.entities.grep(Sketchup::Face).find{|face|
face.normal.parallel?(f.normal) && face != f
}
face_2.pushpull(thickness_2_prompt, true)
end
mod.commit_operation
Take attention of the Face #pushpull method second parameter… (for the second pushpull)
Thank you for your reference. You code works partly. However I want to make the two faces into groups so that I can later on add components with definitions to them. And they are solid componets. For this purpose, I added ‘group_2’ to ‘face_2’ in your code.
mod = Sketchup.active_model # Open model
ent = mod.entities # All entities in model
sel = mod.selection # Current selection
material_1 = "CLT"
material_2 = "CLT"
thickness_1_prompt = 100.mm
thickness_2_prompt = 50.mm
only_faces = sel.grep(Sketchup::Face)
mod.start_operation('Push_test_3', true)
only_faces.each do |f|
group_1 = ent.add_group(f)
f.pushpull(thickness_1_prompt)
# find new face creted pararell to 'f'
face_2 = group_1.entities.grep(Sketchup::Face).find{|face|
face.normal.parallel?(f.normal) && face != f
}
group_2 = ent.add_group(face_2)
face_2.pushpull(thickness_2_prompt, true)
end
mod.commit_operation
But something weird happened (see image): the first is the faces messed up in two groups. You could copy the code in SU to see how messed it is lol (hard to explain in texts) . The second is that ‘face_2’ is always based on origin (0,0,0) after adding ‘group’ to it. This issue you mentioned last time for me when I created face(group) by vertices but in this case for face, I tried but failed
Because previously I managed to move the coordination of vertices of a selected face towards a push-pull’s vector, and that becomes a new face by ‘add_face’ function, I am wondering if there are ways of directly moving the selected face, that is push-pulled first, towards the direction of push-pull. And after moving, it becomes a new face push-pulled again. As a result, they are two boxes next to each other. Then I can have better control of adding more faces with its thickness (push-pull) and definitions if they become components later.
Actually you added a new group to model entities, then you assigned the face_2 to that new group also. That face_2 is now assigned to two different entities collection, witch is “illegal”. You’re lucky that it’s “only” “weird happening” and the whole Sketchup didn’t fall apart…
(You also did not considered the group_1 own coordinate system I mentioned in you other similar topic…)
Here is one example how you can do it:
mod = Sketchup.active_model
ent = mod.entities
sel = mod.selection
thickness_1_prompt = 100.mm
thickness_2_prompt = 10.mm
only_faces = sel.grep(Sketchup::Face)
mod.start_operation('Push_test_4', true)
only_faces.each do |f|
# Motto: You have to think ahead...
# determine the selected face normal. Will be used
# for moving the second group in a direction of pushpull
move_vec = f.normal
# set the length, so the mowing will be same
# as the first pushpull
move_vec.length = thickness_1_prompt
# create a transformation for move
tr_move = Geom::Transformation.translation(move_vec)
# create a group and add the selected face into it
group_1 = ent.add_group(f)
# "clone" that group, to same position as the original
group_2 = group_1.copy
# move the new group with the transformation calculated above
group_2.transform!(tr_move)
# get the face inside the second group
face_2 = group_2.entities.grep(Sketchup::Face).first
# make the pushpull's
f.pushpull(thickness_1_prompt)
face_2.pushpull(thickness_2_prompt)
end
mod.commit_operation
Hi, Dezmo, Now I am able to create and modify the functions I prefer in Sketchup with this one. Thank you very much for helping me who is a beginner in Ruby. You are always very kind checking the problems, explaining the theories behind and even giving some references. All of these helped me gain a better understanding of how Ruby works in Sketchup so I could get a step further ! Thank you and others who helped me here @DanRathbun again!