Notifications
Clear all

[Closed] Best way to trim down an overly complex hierarchy structure

Here’s a new one, trying to get it into a one liner:


   maxDepth=4;
   
   for obj in objects where (tmp=obj; i=0; (while(tmp.parent!=undefined) do ( tmp=tmp.parent; i += 1 );  i >= maxDepth)  ) do ( obj.parent=obj.parent.parent)


  
1 Reply
(@denist)
Joined: 11 months ago

Posts: 0

this is not “one-line”.

the using of “;” just formats “multi-line” in one-line. TRUE one-line shouldn’t use “;” at all, because it’s only replaces “
” (go to new line) of original syntax

Hence the ‘trying to get’… I could get rid of the i=0; by replacing the while-loop with a for-loop and a break, which leaves the tmp=obj; …

2 Replies
(@denist)
Joined: 11 months ago

Posts: 0

yes. but you can solve ‘tmp=obj’ as well.

i can show my code above written in one-line:

-- predefined:
maxDepth = 5
nodes = objects
-- one-line:
for node in nodes where isvalidnode (n = node) and (for k=1 to maxDepth where (n = n.parent) == undefined do exit with k) == maxDepth do (join #() node).parent = node.parent

but i don’t recommend to write code this way

(@jonadb)
Joined: 11 months ago

Posts: 0

One day I’ll beat you at this game

here is an example(s) of using join #() trick:

delete objects
b = box material:(multimaterial())
(
	in b (box())
	addmodifier b (edit_normals())
	addmodifier b (unwrap_uvw())
	ok
)
/*
b.material as array
-- Unable to convert: #Multi/Sub-Object:Multimaterial(Standard:Material #45, Standard:Material #46, Standard:Material #47, Standard:Material #48, Standard:Material #49, Standard:Material #50, Standard:Material #51, Standard:Material #52, Standard:Material #53, Standard:Material #54) to type: Array
b.modifiers as array
-- Unable to convert: #modifiers() to type: Array
b.children as array
-- Unable to convert: #children($Box011) to type: Array
*/

join #() b.material
join #() b.modifiers
join #() b.children

Yeah a good few options better than mine there! I like the variable depth level from DenisT’s solution.

Good work chaps, nice to bounce ideas about!

I’m revisiting this problem again, as I don’t like the flattening it does. There are some times when we want a deep hierarchy.

I came up with a nice solution to this… basically it looks for a places in the scene tree where it’s…

Helper
–helper
—-helper
——helper
——–helper
———-helper
————object

and reduces that to
Helper
–object

based on the number of children and siblings…

Helper
–helper
—-helper
——object
–helper
—-helper
——object

would become

Helper
–helper
—-object
–helper
—-object

Code including amusing commentary…


fn reParent o =
(
   --if my object has a grandparent....
   if o.parent.parent != undefined do
   (
      --if my parent has a sibling...
      if o.parent.parent.children.count != 1 then
      (
         --..stop
      )
      else
      (
      ----get all my parent's children....
         theParent = o.parent
         theObjs = o.parent.children
      ----and link them to my grandparent
         for obj in theObjs do obj.parent = o.parent.parent
      ----kill my parent.
         delete theParent
      ----now go again
         
         reParent o
      )
   )
)
--for each piece of geo
for o in objects do
(
   if o.parent != undefined do reParent o
)


if o.parent.parent != undefined

is already not good… the object can not have a parent. of course i see you check this situation before the passing a node to the function, but i think you have to do this check on the function level

Good spot (although would never happen in my dataset).
Found another bug too with the childrenCollection… this seems to fix it.


fn reParent o =
(
   if o.parent != undefined and o.parent.parent != undefined  do
   (
      --if my parent has a sibling...
      if o.parent.parent.children.count != 1 then
      (
         --..stop
      )
      else
      (
      ----get all my parent's children....
         theParent = o.parent
         grandpa = o.parent.parent
         theObjs = (for a in o.parent.children collect a)
      ----and link them to my grandparent
         for obj in theObjs do obj.parent = grandPa
      ----kill my parent.
         delete theParent
         
         --reParent o
      )
   )
)
--for each piece of geo
for o in selection do
(
   if o.parent != undefined do reParent o
)

a universal function should be something like “reduce hierarchy depth to specified number”. in your case the maximum depth is 2 >> root parent <- parent <- node
every parents between last specified parent and node must be skipped…

there is another problem:


delete theParent

you can’t do it per node processing… you kill a potential parent of another nodes in the process… you have to collect candidates for deletion and delete them after optionally.

also the reparent function has to be mapped

1 Reply
(@davewortley)
Joined: 11 months ago

Posts: 0

The children of the parent get collected and get given to the grand parent. There’s multiple testing going on, but performance isn’t the main need here.

Actually it’s not reducing to a maximum depth at all. It’s looking for where the hierachy brances… and removes any unnecessary hierarchy branches between. And I forgot an important step to make sure we don’t accidentally delete any geometry.


fn reParent theObj =
(
   if theObj.parent != undefined and superclassof theObj.parent == helper and theObj.parent.parent != undefined do
   (
      --if my parent has a sibling...
      if theObj.parent.parent.children.count != 1 then
      (
         --..stop
      )
      else
      (
      ----get all my parent's children....
         theParent = theObj.parent
         grandpa = theObj.parent.parent
         theObjs = (for a in theObj.parent.children collect a)
      ----and link them to my grandparent
         for obj in theObjs do obj.parent = grandPa
      ----kill my parent.
         delete theParent
         
         reParent theObj
      )
   )
)
--for each piece of geo
for o in objects do
(
   if o.parent != undefined do reParent o
)

Page 2 / 2