Dear Friends,
In Ruby sketchup I have a face on one side of a box. Now I wish to pushpull it till other side of box. How can I do it? I don’t know how to find other side face. Thank you for your help in advance.
Dear Friends,
In Ruby sketchup I have a face on one side of a box. Now I wish to pushpull it till other side of box. How can I do it? I don’t know how to find other side face. Thank you for your help in advance.
oh sorry for my mistake. I mean in Ruby sketchup.
I’ll move this to the right category and edit the title, then.
In the spirit of the old “teach a man to fish”, I won’t give you a pre-written code answer, just textual outline of an approach. If you can’t figure it out from that, come back and show us what you tried and we will point out where you went astray.
Can I assume that you know how to invoke Face#pushpull? I.e. that the question isn’t how to do the pushpull, but rather identifying the end Face after the extrusion?
As usual when programming, there are multiple ways to proceed. A key factor is how “clean” was the Entities collection containing the start Face before the pushpull? Things get messier if those Entities already contained other Edges and Faces because you have to test more carefully to be certain you found the desired end Face rather than some other pre-existing Face.
If the start Face was the only thing in its Entities (e.g. if you created a new Group and added the Face to the Group’s Entities), then you just have to search that Entities collection for a new, different Face that is parallel to the start Face (i.e. their normal vectors are parallel). There will be only one such, and it will be the end Face.
If there were other Faces in the Entities before the pushpull then it is possible that there will be more than one Face parallel to the start Face. Then you have to search through them to find the right one. One way to test is to get the Vertices and compare their positions to those of the Vertices of the original Face. There must be the same number of vertices, and they must all be offset from the original Face’s Vertices by the distance used in pushpull and in the direction of the start Face’s normal.
Edit: BTW please correct your forum profile. It says you are running SketchUp Make (desktop) 2020, which does not exist. The last version of Make is 2017.
I could create a face on one side of a box and also I can pushpull it. I don’t know how can I don’t know how can I calculate pushpull distance.
I corrected my profile as your advice.
Thank you.
The distance is one of the parameters to the pushpull method. You can’t invoke pushpull without a distance. It sounds like you are saying you don’t know how big you want the box to be?
It still says SketchUp Make 2020. There is no Make edition for 2020 !
Do you understand this ?
# Given a face referenced as: face1
pt1 = face1.outer_loop.vertices[0].position
# Fire a ray in the reverse direction of face1's normal vector:
result = model.raytest( [ pt1, face1.normal.reverse ] )
# Check the result. nil if failure:
if result
# The point that the ray hit:
pt2 = result.first
# The face that the ray hit:
if result.last[0].is_a?(Sketchup::Face)
face2 = result.last[0]
# Distance between pt1 and pt2 (on face2):
dist = pt1.distance(pt2)
# PushPull in negative direction:
face1.pushpull(-dist)
end
end
REF:
Dear Dan,
Your codes works well. Also you explain it clearly. My problem solved. Thank you so much.
Thank you so much for your attention. Next time, I will ask more clear questions. My mistake.
if box is in a group than we can edit its face, answer of following if is false. Can you help me for it?
if result.last[0].is_a?(Sketchup::Face)
Dear Dan,
You can see my problem in following example. If I delete last “if” it works.
UI.menu("Plugins").add_item("Box") {
Sketchup.active_model.select_tool(Box.new)
}
class Box
def activate
mod = Sketchup.active_model
#Make a group
pt1 = [0, 0, 0]
pt2 = [2, 0, 0]
pt3 = [2, 10, 0]
pt4 = [0, 10, 0]
grp = mod.active_entities.add_group
face1 = grp.entities.add_face [pt1, pt2, pt3, pt4]
face1.pushpull -10
end
def deactivate(view)
view.invalidate
end
def onLButtonDown(flags, x, y, view)
mod = Sketchup.active_model
# select face
input = Sketchup::InputPoint.new
input.pick view, x, y
view.model.active_path = input.instance_path.valid? ? input.instance_path : nil
face1 = input.face
# Given a face referenced as: face1
pt1 = face1.outer_loop.vertices[0].position
# Fire a ray in the reverse direction of face1's normal vector:
result = mod.raytest( [ pt1, face1.normal.reverse ] )
# Check the result. nil if failure:
if result
# The point that the ray hit:
pt2 = result.first
# The face that the ray hit:
if result.last[0].is_a?(Sketchup::Face)
face2 = result.last[0]
# Distance between pt1 and pt2 (on face2):
dist = pt1.distance(pt2)
# PushPull in negative direction:
face1.pushpull(-dist)
end
end
end
end
In your profile you mentioning you are using SU Make 2017.
But if you are using this code:
…In earlier version than SU 2020 you will get this error massage:
Error: #<NoMethodError: undefined method `active_path=' for #<Sketchup::Model:0x000001cb186baff0>>
<main>:24:in `onLButtonDown'
Codes run without any problem. I try to follow friends advice.
So, you are using the SU 2020. Would you please correct your profile?
I did it and next time I will tell others SU 2020 does exist.
I hope my profile is right now. Thank you for your help.
Sorry, it was a “boo-boo” on my part. I did not know you would be inside a group.
When this is true, the instance path array returned by model.raytest
has more than 1 member in it, so [0]
cannot be used because it assumes only 1 member in the array.
This should explain it better …
# encoding: UTF-8
module Majid866
module BoxTest
class Box
def activate
@mod = Sketchup.active_model
# Define 4 points:
pts = [
[0, 0, 0],
[2, 0, 0],
[2, 10, 0],
[0, 10, 0]
]
# Make a group
grp = @mod.active_entities.add_group
face1 = grp.entities.add_face(*pts)
# Pushpull into 3D:
face1.pushpull(-10)
# Draw a face to select:
pts = [
[2, 2, 2],
[2, 8, 2],
[2, 8, 8],
[2, 2, 8]
]
face1 = grp.entities.add_face(*pts)
instance_path = Sketchup::InstancePath.new([grp])
@mod.active_path= instance_path
Sketchup.status_text = "Choose a face ..."
@state = 1
end
def deactivate(view)
view.invalidate
Sketchup.status_text = ""
end
def suspend(view)
view.invalidate
Sketchup.status_text = ""
end
def resume(view)
view.invalidate
Sketchup.status_text = "Choose a face ..." if @state == 1
end
def onLButtonDown(flags, x, y, view)
# @mod is set as the active model
# Select face
input = Sketchup::InputPoint.new
input.pick(view, x, y)
#@model.active_path = input.instance_path.valid? ? input.instance_path : nil
face1 = input.face
if face1 && face1.is_a?(Sketchup::Face)
Sketchup.status_text = ""
@state = 2
push_through(face1)
end
end ### onLButtonDown()
def push_through(face1)
# Given a face referenced as: face1
pt1 = face1.outer_loop.vertices[0].position
# Fire a ray in the reverse direction of face1's normal vector:
result = @mod.raytest( [ pt1, face1.normal.reverse ] )
# Check the result. nil if failure:
if result
# The point that the ray hit:
pt2 = result.first
instance_path = result.last
# The face that the ray hit:
puts "the result object: #{instance_path.last.inspect}"
if instance_path.last.is_a?(Sketchup::Face)
face2 = instance_path.last
# Distance between pt1 and pt2 (on face2):
dist = pt1.distance(pt2)
# PushPull in negative direction:
face1.pushpull(-dist)
end
end
end ### push_through()
end # class Box
unless defined? @loaded
@loaded = true
UI.menu("Plugins").add_item("Box") {
Sketchup.active_model.select_tool(Box.new)
}
end
end # module BoxTest
end # module Majid866
Thank you so much, it works well also your explanation help me so much to write my codes in right way. You are great!!!
Please stop quoting full posts from other members.
(You were told already, so you’ve earned your first flag.)