RSS FEED

Get heaviest objects

This time I will post a really simple function to get a number of heaviest meshes (in terms of face count) from given object set. As it's nothing fancy, there's not much to explain about it  – but maybe someone will find it useful:
fn getNHeaviestObjects objs n result_type:#objects =
(
   local result
   struct geom_item (obj, facecount)
   
   fn getNumFacesAsMesh obj =
   (
      local temp_mesh = snapshotAsMesh obj
      local num_faces = temp_mesh.numFaces
      delete temp_mesh
      num_faces
   )
   
   fn compareNumFaces obj1 obj2 =
      obj2.facecount - obj1.facecount
   
   geom_arr = for g in objs collect geom_item obj:g facecount:(getNumFacesAsMesh g)
   
   with redraw off
      qsort geom_arr compareNumFaces
   
   result = for item = 1 to n where geom_arr[item] != undefined collect case result_type of
   (
      #objects : geom_arr[item].obj
      #names   : geom_arr[item].obj.name
      #numbers : geom_arr[item].facecount
      default  : geom_arr[item]
   )
)
USAGE:  As arguments pass an array of objects and a number of them you want to get in the end. Optionally, you can choose to collect only object names, numbers of faces or, if giving any other argument, structs with properties .obj (the object itself) and .facecount that you can use for other purposes. To select ten meshes with the highest polycount in your scene, the command would look like this:

select (getNHeaviestObjects (geometry as array + shapes as array) 10)

DISCLAIMER: All scripts and snippets are provided as-is under Creative Commons Zero (public domain, no restrictions) license. The author and this blog cannot be held liable for any loss caused as a result of inaccuracy or error within these web pages. Use at your own risk.

This Post needs Your Comment!

PolygonRunner

Lines 24-27:
I don't fully understand.
The use of "#" and ":" here confuse me.
Could you explain how that works, or point me
to some documentation?

Also: Your code display is incredible.
Where did you come across that?

Vojta

Hi, the "#" values are names and their sole purpose is to be used as optional switches. I could have just as well used integers from one to three but this way it's a bit more descriptive when included in a bigger piece of code.

The ":" is a part of case/of expression. Used like this when passed a large collection of nodes, it is actually a sub-optimal way of dealing with the task as for each iteration the script asks for a value of result_type and compares it to predefined set of labels. For that case I could have made a function getVal like this

   local getVal = case result_type of
   (
      #objects : fn getVal node = node.obj
      #names : fn getVal node = node.obj.name
      #numbers : fn getVal node = node.facecount
      default : fn getVal node = node
   )

and output the result this way:

   result = for item = 1 to n where geom_arr[item] != undefined collect getVal geom_arr[item]

Of course the "result" variable is unnecessary in both cases, it's there only to increase code readability.

As for the code box, I'm glad you like. I edited the template to add some styling to pre and code tags, the syntax coloring is done by exporting as html from ConTEXT. If I wasn't so lazy I could have made a custom brush for SyntaxHighlighter and use that instead.

EDIT: noticed some glitches with the embedded comment box, switched to pop-up instead...

Return to top