Pushpull/move a component instance's face
-
How can the pushpull tool be replicated with the API?
If I want to pushpull/move the blue highlighed faces, which are a subcomponent of a component(only the subcomponent is), in the attached picture in the Z dircetion how would I go about doing that?
I've tried a few things but the results aren't good.
Here's what I've tried so far, array[1][0] is the subcomponent of the parent component.# retrieve faces and edges edges=[] faces=[] array[1][0].entities.each{|e| if e.is_a?(Sketchup;;Face) faces.push([e]) end if e.is_a?(Sketchup;;Edge) edges.push([e]) end }
this doesn't give the desired result, it doesn't move the face, more like just a single edge of the face and also 'copies' the subcomponent to the model origin.
t=Geom;;Transformation.translation [10,0,0] entities.transform_entities(t, faces[0])
I was hoping it would as simple as this but this doesn't work either, I get this error
Error: #<NoMethodError: undefined method `pushpull' for [#Sketchup::Face:0xce78a90]:Array>faces[0].pushpull 1
Thanks,
Frank
-
You are adding the faces each as an array. so they are each inside a one element array [same with the edges!]
faces.push([e])
should befaces.push(e)
or evenfaces << e
i.e. NO enclosing**[]**
then it'll work !Another way would be something like the slightly faster:
faces=array[1][0].grep(Sketchup::Face)
you don't actually explain what 'array
' is -
@tig said:
You are adding the faces each as an array. so they are each inside a one element array [same with the edges!]
faces.push([e])
should befaces.push(e)
or evenfaces << e
i.e. NO enclosing**[]**
then it'll work !Another way would be something like the slightly faster:
faces=array[1][0].grep(Sketchup::Face)
you don't actually explain what 'array
' isThanks you sir that works perfect! I haven't tried your second suggestion yet and I really need to find the time to read up on 'grep' seems I see you 'pros' using it more and more.
array
is somewhat of a 'test' array which includes different information in regards to the individual subcomponents and I've been playing around with the info I add to it, which is why I didn't go into detail as to what holds.On a related note, is there an 'easy' way to identify which face is which? Right now I just do it through trial and error changing the value X in
faces[X].pushpull 10
till I find the ones I want to pushpull. -
Each face has a face.normal, the direction it faces [vector3d], it can also have material/back_material, layer, and area and bounds [max/mix.center etc]. Depending on what you 'know' about the face you can test each one till it matches you test and use that face ?
-
Thanks Tig,
Took a little while for me to figure out what Vector3d value referenced what face but once I figured that out I was able to test which face was facing is which direction...
left=Geom::Vector3d.new(-1,0,0)
right=Geom::Vector3d.new(1,0,0)
front=Geom::Vector3d.new(0,-1,0)
back=Geom::Vector3d.new(0,1,0)
up=Geom::Vector3d.new(0,0,1)
down=Geom::Vector3d.new(0,0,-1)Then I can test to see which faces I need to pushpull. I'm sure there are more efficient ways to doing this but for me and for now with a relatively simple model it works and I'm happy.
-
You can also use the built-in Constants [X_AXIS, Y_AXIS and Z_AXIS] if the face.normak vectors are known to be 'axial'.
` if face.normal==X_AXIS ### exactly right facingdo stuff
elsif face.normal==X_AXIS.reverse ### exactly left facing
etc
end
OR say you want to only pushpull faces that look 'up', even if they are 'angled'...
if face.normal.z>0or to they look to the right, somewhat...
if face.normal.x>0`there are many ways to slice-and-dice this...
-
@tig said:
OR say you want to only pushpull faces that look 'up', even if they are 'angled'...
if face.normal.z>0
or to they look to the right, somewhat...
if face.normal.x>0
there are many ways to slice-and-dice this...
That totally makes sense but I didn't even realise I could do it that way...
Thanks again!
Frank -
I'm able to manipulate faces as I wish by determining their orientation BUT how can I identify specific faces that I want to manipulate when there are multiple faces pointing in the same direction? For example if I wanted to only pushpull the middle blue face in the picture in my op?
I tried naming the faces like this
face.name="face 1"
but that didn't work.
Any ideas?
Thanks,
Frank -
Let's assume that the three share a
face.normal==X_AXIS
.
We make an array of those 'faces
'.
Now we'll compare the 'bounding-box' of each in turn, finding the 'center' of each and choosing the one with its Y value between the others [for other axis normals other center XYZ need to be compared].
Something like...
` face=faces[0]
y=face.bounds.center.y
if faces[1].bounds.center.y > y && faces[2].bounds.center.y > y
face=faces[1]
y=face.bounds.center.y
face=faces[2] if faces[2].bounds.center.y < y
elsif faces[1].bounds.center.y > y && faces[2].bounds.center.y < y
face=faces[1]
elsif faces[1].bounds.center.y < y && faces[2].bounds.center.y < y
face=faces[1]
y=face.bounds.center.y
face=faces[2] if faces[2].bounds.center.y > y
elseface is faces[0] as we started
end`
Of course if you make the parts in order and do any pushpulls 'as you go', then you won't need to find the correct face later -
Damn you Tig!! Because of your ingenious solution I have to rethink my code
BUT that's a good thing since in the end it'll be efficient.
On semi-related note... when rotating a component on Z axis from center 180deg(basically mimicing flip along blue, i think ) the left becomes the right and the right becomes the left, anyway to change face.normal?
Using the upper image as an example, if I add 2 instances of that component and flip one so that the side with the 3 blue faces face each other the unflipped components ahs the blue faces as 'top faces' and the flipped faces has them as 'bottom faces' which is true BUT it makes it harder to 'find' those faces. So i'd like to be able to flip the component but keep the original direction of the faces... amke sense??
I came up with a solution but it seems like so much work!
-
@frankn said:
On semi-related note... when rotating a component on Z axis from center 180deg(basically mimicing flip along blue, i think ) the left becomes the right and the right becomes the left, anyway to change face.normal?
Possibly? face.reverse!
No I guess not... that will change the faces for ALL instances. (Remember that it is the Definition that owns the component entities, not the instances. ALL instances share the same entities collection from their parent definition.)
-
@unknownuser said:
](http://www.sketchup.com/intl/en/developer/docs/ourdoc/face#reverse!)
I had seen that but I never tried it thinking it was like the Skethup function 'reverse faces' which turns the face from purple to white.
No I guess not... that will change the faces for ALL instances. (Remember that it is the Definition that owns the component entities, not the instances. ALL instances share the same entities collection from their parent definition.)
Actually that works in my situation because I make all my instances unique... but I'm just starting to play around with this and might run into problems later.
edit: just took a closer look at my model and yes it does turn the face from white to purple doing exactly like the Sketchup function. So yes it works but not the ideal solution.
Advertisement