View Full Version : How to get the Full Node PathName ??
silverframe 01-19-2010, 08:49 PM Using Maxscript.
I am trying to figure out how on earth I could get the full pathname of an object. I know that I can get objects with $torso/left_upper_arm/left_lower_arm etc. But how do i get the full path from an object ??
If any one have any ideas It would be awsome.
Thanks // K
|
|
I don't think there's any direct function for it so you should recurse the tree to the parent.
For example:
(
local thePath = ""
fn recursePath obj &thePath =
(
if isValidNode obj do
(
thePath = obj.name + thePath
if obj.parent != undefined do
(
thePath = "/" + thePath
recursePath obj.parent &thePath
)
)
)
recursePath selection[1] &thePath
print thePath
ok
)
-Johan
Pjanssen
01-20-2010, 07:20 PM
Hey Krister!
How does this look?
function getNodePath node =
(
local p = node;
local path = "";
while (isValidNode p) do
(
path = "/" + p.name + path;
p = p.parent;
)
return path;
)
This might save some on function call overhead compared to Johan's function (which is also just fine of course, you will never notice the difference).
If you don't want the / at the beginning of the path, then you'll have to put a small if statement in the loop.
Hi Pier,
I like your function, it's clean, takes one input parameter... but it just doesn't sound as cool as, "I'm using a recursive function to traverse the hierarchy" ;)
-Johan
P.s. your code is better, recursive functions seem to have a limit, it crashed on mine with over 300 nodes linked, your's didn't, performance wise I couldn't measure a thing, until max started crashing on the recursion.
Pjanssen
01-20-2010, 09:07 PM
Hi Pier,
I like your function, it's clean, takes one input parameter... but it just doesn't sound as cool as, "I'm using a recursive function to traverse the hierarchy" ;)
Very true, recursive functions definitely have a certain coolness factor :D
P.s. your code is better, recursive functions seem to have a limit, it crashed on mine with over 300 nodes linked, your's didn't, performance wise I couldn't measure a thing, until max started crashing on the recursion.
Hmm you got a stack overflow for 300 recursive calls? I have to admit that I don't know if this is normal for other programming languages as well, but I must say I am surprised on how quickly that happens.
ps. I edited my post earlier saying that I didn't read Krister's question properly, but now that I read it again, I did actually assume the correct thing. I was just being confused for a while, hehe.
denisT
01-20-2010, 09:39 PM
this is my version... it makes executable string and takes to account the possibility of using space symbols in node names:
fn nodePathname node name:"" = if isvalidnode node do
(
name = "'" + node.name + "'" + name
if node.parent != undefined then name = (nodePathname node.parent name:("/" + name))
else "$" + name
)
-- sample:
(
c = in (b = box name:"Box Node") in (s = sphere name:"Sphere Node") cylinder name:"Cylinder Node"
p = nodePathname c
format " path: %\n node: %\n" p (execute p)
)
denisT
01-20-2010, 09:54 PM
Hmm you got a stack overflow for 300 recursive calls? I have to admit that I don't know if this is normal for other programming languages as well, but I must say I am surprised on how quickly that happens.
it's true. i changed my function because of that:
fn nodePathname node = if isvalidnode node do
(
name = "'" + node.name + "'"
while (node = node.parent) != undefined do
(
name = "'" + node.name + "'/" + name
)
"$" + name
)
-- sample:
b = box()
for k=2 to 1000 do in b (b = box())
nodePathname b
silverframe
01-20-2010, 09:57 PM
Thanks for the replies guys =)
Denis Denis what can I say when all hope is lost there is a light !!
Your script is tested and awsome-approved so is your name in my script.
Thanks alot
// K
denisT
01-20-2010, 11:49 PM
well. here is the recursive version and it doesn't crash max for long path.
fn nodePathname node name: = if isvalidnode node do
(
name = if name == unsupplied then ("'" + node.name + "'") else ("'" + node.name + "'/" + name)
if (node = node.parent) != undefined then nodePathname node name:name else ("$" + name)
)
delete objects
-- sample:
b = box()
for k=2 to 1000 do in b (b = box())
nodePathname b
using of recursion was not a problem in the previous version. it was crashing because of creation of copies of long strings. new version doesn't create string copies.
Is the recursion a problem that the maxscript heap is not growing fast enough with the function calls then, I have 8gigs in my machine and max crashed with only 1.5 gigs in use. I have heard of recursion problems before, I think Neil Blevins had some problems with them too, I even recal reading somewhere c++ has some recursion limits. Maybe a stringstream would also not make my version crash..
-JOhan
denisT
01-21-2010, 04:41 PM
As I said in my other posts I work in MAXScript more then 13 years but I keep learning and finding anything new...
Today I want to share some results of my last research. It might answer the question: Should we try to optimize a code or can leave it in "just works and it's good enough" stage?
We have the task - to get full path of a node.
I wrote 4 functions that does do it but in a different way:
1. Recursive function with strings using:
fn nodePathname_v1 node name: = if isvalidnode node do
(
name = if name == unsupplied then ("'" + node.name + "'") else ("'" + node.name + "'/" + name)
if node.parent != undefined then nodePathname_v1 node.parent name:name
else ("$" + name)
)
2. Recursive function with string streams:
fn nodePathname_v2 node list:#() = if isvalidnode node do
(
append list node
if node.parent != undefined then nodePathname_v2 node.parent list:list
else
(
ss = stringstream ""
format "$" to:ss
for k=list.count to 1 by -1 do format "'%'%" list[k].name (if k != 1 then "/" else "") to:ss
ss as string
)
)
3. Not Recursive function with strings:
fn nodePathname_v3 node = if isvalidnode node do
(
name = ("'" + node.name + "'")
while (node = node.parent) != undefined do
(
name = "'" + node.name + "'/" + name
)
"$" + name
)
3. Not Recursive function with string streams:
fn nodePathname_v4 node = if isvalidnode node do
(
ss = stringstream ""
format "$" to:ss
list = #(node)
while (node = node.parent) != undefined do append list node
for k=list.count to 1 by -1 do format "'%'%" list[k].name (if k != 1 then "/" else "") to:ss
ss as string
)
all 4 work for 1000 nodes depth hierarchy.
There is the results:
version 1:
time: 31 memory: 332560L
version 2:
time: 15 memory: 127952L
version 3:
time: 31 memory: 196328L
version 4:
time: 15 memory: 97008L
You can see that strings operations slower and more memory expensive. And it was predictable.
Recursive versions are more memory expensive then not recursive but performance is the same.
But for 2000 nodes only 4th version survives. And it keeps working for 10000 as well.
So, sometimes it's better to sacrifice the charm of recursion but reach the goal. :)
However, our task is "one branch" task and it's possible to solve it without recursion. But what have we to do for "tree" task? In that case only "recursive" version might help.
Here is the test to play with:
fn nodePathname_v1 node name: = if isvalidnode node do
(
name = if name == unsupplied then ("'" + node.name + "'") else ("'" + node.name + "'/" + name)
if node.parent != undefined then nodePathname_v1 node.parent name:name
else ("$" + name)
)
fn nodePathname_v2 node list:#() = if isvalidnode node do
(
append list node
if node.parent != undefined then nodePathname_v2 node.parent list:list
else
(
ss = stringstream ""
format "$" to:ss
for k=list.count to 1 by -1 do format "'%'%" list[k].name (if k != 1 then "/" else "") to:ss
ss as string
)
)
fn nodePathname_v3 node = if isvalidnode node do
(
name = ("'" + node.name + "'")
while (node = node.parent) != undefined do
(
name = "'" + node.name + "'/" + name
)
"$" + name
)
fn nodePathname_v4 node = if isvalidnode node do
(
ss = stringstream ""
format "$" to:ss
list = #(node)
while (node = node.parent) != undefined do append list node
for k=list.count to 1 by -1 do format "'%'%" list[k].name (if k != 1 then "/" else "") to:ss
ss as string
)
-- sample:
undo off
(
delete objects
b = box()
for k=2 to 1000 do in b (b = box())
gc()
format "Created ...\n"
h1 = heapfree
t1 = timestamp()
p1 = nodePathname_v1 b
h2 = heapfree
t2 = timestamp()
p2 = nodePathname_v2 b
h3 = heapfree
t3 = timestamp()
p3 = nodePathname_v3 b
h4 = heapfree
t4 = timestamp()
p4 = nodePathname_v4 b
h5 = heapfree
t5 = timestamp()
format "version 1: %\n\ttime: %\tmemory: %\n" p1 (t2-t1) (h1-h2)
format "version 2: %\n\ttime: %\tmemory: %\n" p2 (t3-t2) (h2-h3)
format "version 3: %\n\ttime: %\tmemory: %\n" p3 (t4-t3) (h3-h4)
format "version 4: %\n\ttime: %\tmemory: %\n" p4 (t5-t4) (h4-h5)
gc()
)
Enjoy! :)
CGTalk Moderation
01-21-2010, 04:41 PM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.
vBulletin v3.0.5, Copyright ©2000-2012, Jelsoft Enterprises Ltd.