[Closed] Best way to trim down an overly complex hierarchy structure
We get a lot of CAD which comes in with sometimes literally 30,000 help objects. Most of the time we only need the first 5 or 6 levels of hierarchy and then the rest is nonsensical names with just helpers linked to helpers linked to helpers with finally a bit of geometry on the end. I wrote a script to simplify the structure down to 6 levels but I’m interested to see how other people would do this as I thought it was quite a fun challenge.
I wrote this in a rush… It loops through all the scene objects and gets everything at hierarchy level 5 and then gets all the children+children++ and relinks them to the level 5 helper.
fn getChildren theObjs newObjs=
(
for o in theObjs do
(
append newObjs o
getChildren o.children newObjs
)
newObjs
)
for i = 1 to rootnode.children[1].children.count do
(
for j = 1 to rootnode.children[1].children[i].children.count do
(
for k = 1 to rootnode.children[1].children[i].children[j].children.count do
(
for l = 1 to rootnode.children[1].children[i].children[j].children[k].children.count do
(
for m = 1 to rootnode.children[1].children[i].children[j].children[k].children[l].children.count do
(
--get all object subtree from here....
newObjs = #()
getChildren rootnode.children[1].children[i].children[j].children[k].children[l].children[m].children newObjs
for o in newObjs do o.parent = rootnode.children[1].children[i].children[j].children[k].children[l].children[m]
)
)
)
)
)
it’s my version:
fn descentLevel node =
(
level = 0
while (node = node.parent) != undefined do level += 1
level
)
garbage = #()
for node in objects where (descentLevel node) == 5 do join garbage node
delete garbage
I think the idea is not to delete them but to make them children of their fifth level.
At first I undertood it like you.
fn descentLevel node =
(
level = 0
while (node = node.parent) != undefined do level += 1
level
)
fn getChildrenRecursive node = (
local childs = #()
join childs node.children
if childs.count > 0 then (
for c in childs do join childs (getChildrenRecursive c)
)
childs
)
for node in objects where (descentLevel node) == 2 do (
for p in (getChildrenRecursive node) do p.parent = node
)
modified denisT version a bit
You amateurs This will collapse the hierarchy and link all nodes above level N (the number of ‘/*’ determines the depth) to the node found at that exact level:
(apparently this code is so advanced the [ code ] block doesn’t want to display it, so here it is in plain text)
for childs in ($/objects/////*) do ( maxDepthNode=childs.parent; for obj in childs do obj.parent=maxDepthNode)
for childs in ($/objects/*/*/*/*/*) do ( maxDepthNode=childs.parent; for obj in childs do obj.parent=maxDepthNode)
this is actually an example of ‘amateur’.
( maxDepthNode=childs.parent; for obj in childs do obj.parent=maxDepthNode)
is
(join #() node).parent = node.parent
$/objects/*/*/*/*/*
has to be ‘modifiable’ thing which takes a hierarchy depth as a parameter.
my goal was just to show how to do this kind of things without recursion
Ahh yes, that join thing is pretty slick!
To avoid an execute maybe some clever thing can be done by replacing ‘objects’ with ‘selection’ to use the depth of the current selected node as a limit.
“(join #() node).parent = node.parent”
This code is incredible, DenisT:
- Why “(join #() node)” gets all children of ‘node’? How should I do if I just want to join a node but not its children?
- “(join #() node).parent” gives an error in the listener (“– Unknown property: “parent” in #($Sphere:Sph…”) but “(join #() node).parent = node.parent” works! I don’t understand. Where are all those things explained in the mxs help???
(join #() node)
tip was shown on this forum by LO first time. after that we found
for n in node
you can find an explanation why it works this way. shortly: every node is mappable object (as well as selection set, material, etc.) there is a thread that tells it and shows examples on this forum.
“(join #() node).parent” gives an error because you ask a value (getting)… it works only for setting a value
and it works only if a specified parameter is common for all objects in the list:
#(cone(), cylinder(), pyramid()).height = 20
both these tricks are not documented in the mxs help.
To avoid go through all nodes, the code could be the next one (but I don’t know really if it’ll take more time while finding and deleting items):
fn descentLevel node =
(
level = 0
while (node = node.parent) != undefined do level += 1
level
)
theObjects = objects as array
for node in theObjects where (descentLevel node) == 5 do
(
aaa = (join #() node)
aaa.parent = node.parent
for o in aaa do
(
item = finditem theObjects o
deleteitem theObjects item
)
)