[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)
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; …
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
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
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
)