Min. z value of some points
-
Hi!
I have lots of 3D points: points = [[1, 2, 3], [2, 3, 5], ...]
Is there a easy way to get for example the minimum z value of all these points in Ruby?
At the moment I have a points.each loop and compare every z value with the last one....
Thanks for your help!
-
min = points.inject(0) { |m,pt| ( pt.z < m ) ? pt.z : m }
Inject have many neat usages - I noted a couple of examples: http://forums.sketchucation.com/viewtopic.php?t=41176&p=364915
-
Haven't checked if it is faster, but
BoundingBox
might help:<span class="syntaxdefault">bb </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> Geom</span><span class="syntaxkeyword">;;</span><span class="syntaxdefault">BoundingBox</span><span class="syntaxkeyword">.new<br /></span><span class="syntaxdefault">bb</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">add</span><span class="syntaxkeyword">(</span><span class="syntaxdefault"> points </span><span class="syntaxkeyword">)<br /></span><span class="syntaxdefault">min </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> bb</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">min</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">z</span>
Since it's SU's native code doing the handling of the points, it might yield faster calculations.
-
oh thank you very much!
I saw the function "inject", but I ignored them because I thought, that's not interesting for me.
Just for the sake of completeness: One have to add a "Geom::" in the front of "BoundingBox.new"
Thanks a lot again for your help!
br
-
@niccah said:
Just for the sake of completeness: One have to add a "Geom::" in the front of "BoundingBox.new"
Good catch! Updated the example.
-
to be absolutely accurate, I guess the inject statement should be
min = points.inject(points[0].z) { |m,pt| ( pt.z < m ) ? pt.z : m }
Fredo
PS: Did not know this method, as it is not documented in the Pragmatic Programmer's guide. Seems useful and elegant
-
@unknownuser said:
PS: Did not know this method, as it is not documented in the Pragmatic Programmer's guide. Seems useful and elegant
Do not use the object reference from that OLD guide, which was written in the Ruby v 1.6.x timeframe. (The tutorial text is still relevant and recommended, however.)
Instead use the v 1.8.6 CHM here
or access on-line http://www.ruby-doc.org/core-1.8.6/index.html.
Note that these methods come from the mixin module
Enumerable
which is mixed intoArray
,Hash
,IO
(and subclasses, such asFile
,)Range
,String
,Struct
, ... etc. -
@unknownuser said:
to be absolutely accurate, I guess the inject statement should be
min = points.inject(points[0].z) { |m,pt| ( pt.z < m ) ? pt.z : m }
At, one time, in another thread, we were comparing various methods of getting min and max, speedwise.
There is also:
min_z = points.min {|a,b| a.z <=> b.z }
Can't remember which was the faster.
P.S.: Because
min
andmax
are method names inEnumerable
, and that they are mixed into quite a few classes, .. it is recommended to not use them as var names.
Difference them. It seems that the API's tradition is to add an "_" and then a descriptor:min_x
,min_y
,min_z
,min_height
,min_width
,min_size
, etc. -
This forum is amazing!
I learn a lot from you! Thanks a lot for all these information!
-
This is how I would do it:
minZ = points.collect { |pt| pt.z }.min
-
@david: Your example should be slower, as it must iterate 2 arrays, and also create a temporary array.
Why ?? (I suspect you like the "readability" of your version.)
-
Yes, readability. If it was operating on large quantities of data, I would definitely use your suggested method.
Advertisement