Fastest way to retrieve the corners that make up a face?
-
I need to know the coordinates of the corners that make up selected faces. Right now I'm doing something like this:
for face in selection corner.insert face.bounds.corner(0) corner.insert face.bounds.corner(1) corner.insert face.bounds.corner(6) corner.insert face.bounds.corner(7) end
Where
selection
is all of the currently selected entities (which have been checked to only be faces) andcorner
is a previously empty Set. Obviously, using the BoundingBox only works if the faces are oriented exactly along the axes of the model. I know I can get the edges of each face, and then get the vertexes that make up the edges, then convert those to Point3d... but that seems really slow. Since I need to do this a lot (over 2,500 times in one example model) I'm looking for the fastest way to do this... any ideas? -
This will only work on rectangular faces ?
face.vertices
returns an array of each actual corner [vertex].
vertex.position
returns the point of a vertex. -
@tig said:
This will only work on rectangular faces ?
face.vertices
returns an array of each actual corner [vertex].
vertex.position
returns the point of a vertex.Oh jeez, that seems pretty obvious now. Thanks!
-
so take it to a 1 liner (where your Set is named
corners
, and need not really be empty):corners.insert( *face.vertices.map{|vertex| vertex.position } )
NOTE: The API does not say so, but the
insert()
method can take multiple args separated by commas.
Themap
method returns an array, so we can use the*
expand/contract (I call it the "accordian",) operator, to convert the array to an argument list. -
@dan rathbun said:
NOTE: The API does not say so, but the insert() method can take multiple args separated by commas.
Doh!!!
-
@thomthom said:
@dan rathbun said:
NOTE: The API does not say so, but the insert() method can take multiple args separated by commas.
Doh!!!
Which brings up a compatibility issue between Sketchup's
Set
and RubySet
.The Ruby
Set#add()
method only takes 1 argument, so I cannot just alias add as insert in my set_fix.rb file. -
@dan rathbun said:
so take it to a 1 liner (where your Set is named
corners
, and need not really be empty):corners.insert( *face.vertices.map{|vertex| vertex.position } )
NOTE: The API does not say so, but the
insert()
method can take multiple args separated by commas.
Themap
method returns an array, so we can use the*
expand/contract (I call it the "accordian",) operator, to convert the array to an argument list.Wow, well, that's a little over my head, I'm just learning Ruby, so I'll have to dissect that. Thanks!
-
Ok well assigning values to references may help you understand, but it will slow down the loop.
(Also it's confusing both to read, and slows down Ruby interpreter, when you use ref names that are the same as method names.)So:
coord = Set.new() for f in sel verts = f.vertices posary = verts.map {|v| v.position } for p3d in posary coord.insert( p3d ) end end
The only persistent reference you really need is
coord
.Now simplify a bit:
coord = Set.new() for f in sel verts = f.vertices posary = verts.map {|v| v.position } coord.insert( *posary ) end
The
*
operator will expand an array into an argument list, or (if used within method definition's parameters,) compress the remaining argument list into an array. We are using the former, in this example.So, simplify a bit more:
coord = Set.new() for f in sel verts = f.vertices coord.insert( *verts.map{|v| v.position } ) end
And again:
coord = Set.new() for f in sel coord.insert( *f.vertices.map{|v| v.position } ) end
And finally:
coord = Set.new() sel.each{|f|coord.insert(*f.vertices.map{|v|v.position})}
ADD: For some reason,
for
..in
loops are faster thaneach
block methods. -
@dan rathbun said:
ADD: For some reason,
for
..in
loops are faster thaneach
block methods.They may be faster - because they don't create a local variable scope - the scope is shared with it's parent scope. Creating variables in Ruby is an expensive operation, so if you create variables within an
each
loop it's created every time, within afor
loop it's reused.
Advertisement