Search code examples
javascriptpath-finding

How can I construct a path between two distant node in pathfinding3d.js?


To create a path in pathfinding3d.js, we have to add all nodes and their neighbors.

var nodes = [
    new PF.Node(0,0,0),
    new PF.Node(1,0,0),
    new PF.Node(2,0,0),
];
nodes[0].neighbors.push(nodes[1]);
nodes[1].neighbors.push(nodes[0],nodes[2]);
nodes[2].neighbors.push(nodes[1]);
var finder = new PF.AStarFinder();
var path = finder.findPath(nodes[0], nodes[2], nodes);

The problem is, if I want to create a large 3d mesh of node, to create a path I need to push neighbour in each node to create a path. Is there another way to do this? Can I create path from one point to another distant just by adding the origin node and destination node? Such as createPath(node(1,2,3), node(4,5,6) and the path between them create the path. Or is there another solution more fitting than this?


Solution

  • I've managed to find a solution. First, I create three function to help me create layout, make all node connected, and, then, make only the necessary node connected using the pathfinding3d.js to calculate which node it need to connect based on proposed connected nodes. Here are the function:

    function create3DLayout(x, y, z) {
        let layout = new Array(x);
        for (let i = 0; i < x; i++) {
            layout[i] = new Array(y);
            for (let j = 0; j < y; j++) {
                layout[i][j] = new Array(z);
                for (let k = 0; k < z; k++) {
                    layout[i][j][k] = new PF.Node(i, j, k);
                }
            }
        }
        return layout;
    }
    
    function createAllWalkable(layout) {
        for (let i = 0; i < layout.length; i++) {
            for (let j = 0; j < layout[i].length; j++) {
                for (let k = 0; k < layout[i][j].length; k++) {
    
                    let mInit = (i + -1 >= 0) ? -1 : 0;
                    let mEnd = (i + 1 < layout.length) ? 1 : 0;
    
                    for (let m = mInit; m <= mEnd; m++) {
    
                        let nInit = (j + -1 >= 0) ? -1 : 0;
                        let nEnd = (j + 1 < layout[i].length) ? 1 : 0;
    
                        for (let n = nInit; n <= nEnd; n++) {
    
                            let oInit = (k + -1 >= 0) ? -1 : 0;
                            let oEnd = (k + 1 < layout[i][j].length) ? 1 : 0;
    
                            for (let o = oInit; o <= oEnd; o++) {
    
                                let xt = m + i;
                                let yt = n + j;
                                let zt = o + k;
    
                                if (layout[xt][yt][zt] != layout[i][j][k]) {
                                    layout[i][j][k].neighbors.push(layout[xt][yt][zt]);
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    
    function createWalkablePath(layout, nodeStart, nodeEnd) {
        // Create building
        let walkablelayout = create3DLayout(layout.length, layout[0].length, layout[0][0].length);
    
        // Create path to every corner of building
        createAllWalkable(walkablelayout);
    
        let startPath = walkablelayout[nodeStart.x][nodeStart.y][nodeStart.z];
        let endPath = walkablelayout[nodeEnd.x][nodeEnd.y][nodeEnd.z];
    
        let explorer = new PF.AStarFinder();
        let exploredPath = explorer.findPath(startPath, endPath, walkablelayout);
    
        for (let i = 0; i < exploredPath.length - 1; i++) {
            layout[exploredPath[i][0]][exploredPath[i][1]][exploredPath[i][2]].neighbors.push(layout[exploredPath[i + 1][0]][exploredPath[i + 1][1]][exploredPath[i + 1][2]]);
            layout[exploredPath[i + 1][0]][exploredPath[i + 1][1]][exploredPath[i + 1][2]].neighbors.push(layout[exploredPath[i][0]][exploredPath[i][1]][exploredPath[i][2]]);
        }
    
    }
    

    Then, I'll do the calculation:

    var nodes = create3DLayout(26, 26, 3);
    
            createWalkablePath(nodes, nodes[7][14][0], nodes[9][17][0]);
            createWalkablePath(nodes, nodes[0][0][0], nodes[25][25][2]);
            createWalkablePath(nodes, nodes[0][25][0], nodes[9][17][0]);
            createWalkablePath(nodes, nodes[1][15][1], nodes[9][17][0]);
            createWalkablePath(nodes, nodes[20][25][1], nodes[9][17][0]);
    
            // Create finder
            var finder = new PF.AStarFinder();
    
            // origin
            var startNode = nodes[14][14][2];
            console.log(startNode);
    
            // Destination
            var endNode = nodes[17][17][2];
            console.log(endNode);
    
            var path;
    
            // Find path
            path = finder.findPath(startNode, endNode, nodes);
            console.log(path);
    

    Hope this helps anyone who face same problem.