I have been trying to create a function that takes needed parameters and creates and returns a path. But I could not found any solution.
In detail, as you see below I'm using treelib library. I'm reading data from a 3d model than skeletonizing it with skeletor library. It gives me results as ->
node_id parent_id x y z radius
0 0 -1 -1.228041 -0.106300 0.001783 None
1 1 0 -1.223447 -0.108507 -0.003192 None
2 2 4 -1.203667 -0.120944 -0.014145 None
3 3 5 -0.332745 0.222496 1.590621 None
4 4 1 -1.217804 -0.115034 -0.011167 None
.. ... ... ... ... ... ...
655 655 534 0.179983 -1.285225 0.181451 None
656 656 480 -0.408439 -0.766452 0.132349 None
657 657 545 -0.085553 -0.860636 0.359673 None
658 658 659 -0.079773 -0.854532 0.385282 None
659 659 657 -0.081701 -0.857868 0.373008 None
While storing these values, I use a basic class "MyNode". (I will give the code below)
After that, I'm creating a tree with treelib Tree class according to the taken info from skeleton. Se the tree output here -> ("Note you can also generate the tree by the code I give") zoomed out photo of tree_output.txt
In this tree, nodes are represented with their ID's, and I want to create method that takes (startID, endID) to create path between these two ids. I have tried several methods, but I keep facing with errors or only empty list returns and etc.
About the usage case, I really like to find a path from "8" to "482" or opposite. See here -> desired function's result explained (The red node IDS should be returned as path in a list. Order is not required)
Shortly, the only thing I need is to get a list including the nodes.
The input file used -> ply file used
See the code here,
from collections import defaultdict
from treelib import Tree
import skeletor as sk
import trimesh as tm
class MyNode :
def __init__(self, nodeID:int, parentNodeID:int, nodeX:float, nodeY:float, nodeZ:float) -> None:
self.nodeID, self.parentNodeID, self.nodeX, self.nodeY, self.nodeZ = int(nodeID), int(parentNodeID), float(nodeX), float(nodeY), float(nodeZ)
def __str__(self) -> str:
return (f"MyNode(SelfID:{self.nodeID}, ParentID:{self.parentNodeID}, X:{self.nodeX}, Y:{self.nodeY}, Z:{self.nodeZ})")
inputMeshFile = "question_input.ply"
mesh = tm.load_mesh(inputMeshFile)
skeleton = sk.skeletonize.by_teasar(mesh=mesh, inv_dist=0.27)
skeletonInfo = skeleton.swc
allNodes = []
for i in range(len(skeletonInfo)) :
allNodes.append(
MyNode(
skeletonInfo["node_id"].values[i],
skeletonInfo["parent_id"].values[i],
skeletonInfo["x"].values[i],
skeletonInfo["y"].values[i],
skeletonInfo["z"].values[i]
)
)
childrenParen_DDict = defaultdict(list) # <-- children-parent ddict, ddict is used for creating tree easier
for currentNode in allNodes :
childrenParen_DDict[currentNode.parentNodeID].append(currentNode.nodeID)
root = childrenParen_DDict[-1][0]
tree = Tree()
tree.create_node(root, root)
agenda, seen = [root], set([root])
while agenda:
nxtParent = agenda.pop()
for child in childrenParen_DDict[nxtParent]:
tree.create_node(child, child, parent=nxtParent)
if child not in seen:
agenda.append(child)
seen.add(child)
tree.save2file("tree_output.txt")
#Rest of the code I want to make it run.
def findPath(startNode:MyNode, endNode:MyNode, tree:Tree, allNodes:list) -> list :
path = []
#.
#.
#.
return path
print("Path is :", findPath(allNodes[8], allNodes[482], tree, allNodes))