tisoap / react-flow-smart-edge

Custom Edge for React Flow that never intersects with other nodes
https://tisoap.github.io/react-flow-smart-edge/
MIT License
242 stars 26 forks source link

Smart Edge Not Considering nodes inside a group. #47

Closed SujayRhombuz closed 1 year ago

SujayRhombuz commented 1 year ago

Describe the Bug

im facing an issue while using the custom edge example from the docs,

case 1

Screenshot 2023-03-09 at 12 32 14 AM

case 2

Screenshot 2023-03-09 at 12 42 19 AM

The connection of edges can be made within the sub-flow or in between another group or a node from outside of the group.

here is my custom edge component `import { useNodes, BezierEdge } from 'reactflow'; import { getSmartEdge, svgDrawStraightLinePath, pathfindingJumpPointNoDiagonal } from '@tisoap/react-flow-smart-edge'; import { AStarFinder, JumpPointFinder, Util, DiagonalMovement } from 'pathfinding'; export function SmartEdgeWithSubFlow(props: any) { const { id, sourcePosition, targetPosition, sourceX, sourceY, targetX, targetY, style, markerStart, markerEnd } = props;

const nodes = useNodes();
console.log('nodes :>> ', nodes);
const getSmartEdgeResponse = getSmartEdge({
    sourcePosition,
    targetPosition,
    sourceX,
    sourceY,
    targetX,
    targetY,
    nodes,
    options: {
        drawEdge: svgDrawStraightLinePath,
        generatePath: (grid, start, end) => {
            try {
                // FIXME: The "pathfinding" module doe not have proper typings.
                // @ts-ignore
                const finder = new JumpPointFinder({
                    diagonalMovement: DiagonalMovement.Never,
                });
                console.log('grid :>> ', grid);
                console.log('finder :>> ', finder);
                console.log('start :>> ', start);
                console.log('end :>> ', end);
                const fullPath = finder.findPath(start.x, start.y, end.x, end.y, grid);
                const smoothedPath = fullPath;
                if (fullPath.length === 0 || smoothedPath.length === 0) return null;
                console.log('fullPath :>> ', fullPath);
                console.log('smoothedPath :>> ', smoothedPath);
                return { fullPath, smoothedPath };
            } catch {
                return null;
            }
        },
        gridRatio: 2,
        nodePadding: 20,
    },
});

// If the value returned is null, it means "getSmartEdge" was unable to find
// a valid path, and you should do something else instead
// console.log('getSmartEdgeResponse :>> ', getSmartEdgeResponse);
if (getSmartEdgeResponse === null) {
    console.log('null :>> ', null);
    return <BezierEdge {...props} />;
}

const { edgeCenterX, edgeCenterY, svgPathString } = getSmartEdgeResponse;

return (
    <>
        <path
            style={style}
            className="react-flow__edge-path"
            d={svgPathString}
            markerEnd={markerEnd}
            markerStart={markerStart}
        />
    </>
);

} `

My findings and requirements: 1) A group is also considered a node(or obstacle) and so in case 2 you can see that the edge is going around the group border, I want to check a condition if target node is within the group don't consider the group to be a node and don't go around the group, but still consider other nodes within the group as obstacles. 2) If the edge is coming from or to another node or group outside the current group, similar to the condition above, consider all nodes to be obstacles but don't consider the group to be an obstacle

It would be great if you can help me out on this one

Minimal Example

https://github.com/tisoap/react-flow-smart-edge#custom-smart-edges

Steps to Reproduce the Bug or Issue

1) Use a reactflow boiler plate 2) using this component as your edgeType `import { useNodes, BezierEdge } from 'reactflow'; import { getSmartEdge, svgDrawStraightLinePath, pathfindingJumpPointNoDiagonal } from '@tisoap/react-flow-smart-edge'; import { AStarFinder, JumpPointFinder, Util, DiagonalMovement } from 'pathfinding'; export function SmartEdgeWithSubFlow(props: any) { const { id, sourcePosition, targetPosition, sourceX, sourceY, targetX, targetY, style, markerStart, markerEnd } = props;

const nodes = useNodes();
console.log('nodes :>> ', nodes);
const getSmartEdgeResponse = getSmartEdge({
    sourcePosition,
    targetPosition,
    sourceX,
    sourceY,
    targetX,
    targetY,
    nodes,
    options: {
        drawEdge: svgDrawStraightLinePath,
        generatePath: (grid, start, end) => {
            try {
                // FIXME: The "pathfinding" module doe not have proper typings.
                // @ts-ignore
                const finder = new JumpPointFinder({
                    diagonalMovement: DiagonalMovement.Never,
                });
                console.log('grid :>> ', grid);
                console.log('finder :>> ', finder);
                console.log('start :>> ', start);
                console.log('end :>> ', end);
                const fullPath = finder.findPath(start.x, start.y, end.x, end.y, grid);
                const smoothedPath = fullPath;
                if (fullPath.length === 0 || smoothedPath.length === 0) return null;
                console.log('fullPath :>> ', fullPath);
                console.log('smoothedPath :>> ', smoothedPath);
                return { fullPath, smoothedPath };
            } catch {
                return null;
            }
        },
        gridRatio: 2,
        nodePadding: 20,
    },
});

// If the value returned is null, it means "getSmartEdge" was unable to find
// a valid path, and you should do something else instead
// console.log('getSmartEdgeResponse :>> ', getSmartEdgeResponse);
if (getSmartEdgeResponse === null) {
    console.log('null :>> ', null);
    return <BezierEdge {...props} />;
}

const { edgeCenterX, edgeCenterY, svgPathString } = getSmartEdgeResponse;

return (
    <>
        <path
            style={style}
            className="react-flow__edge-path"
            d={svgPathString}
            markerEnd={markerEnd}
            markerStart={markerStart}
        />
    </>
);

} `

3) make connections between sub-flows and stand alone nodes, connections between nodes within the subflows like in the 2 images

Expected behavior

1) A group is also considered a node(or obstacle) and so in case 2 you can see that the edge is going around the group border, I want to check a condition if target node is within the group don't consider the group to be a node and don't go around the group, but still consider other nodes within the group as obstacles. 2) If the edge is coming from or to another node or group outside the current group, similar to the condition above, consider all nodes to be obstacles but don't consider the group to be an obstacle

Screenshots or Videos

No response

Platform

Additional context

No response

SujayRhombuz commented 1 year ago

this was not a but, the edges are working as expected, i had to filter the nodes and consider only nodes which are of type "component" and not "group". this solved my issue but with more nodes on the screen the performance is bad anyhow im closing this issue as it is not a bug

tisoap commented 1 year ago

Filtering nodes is the current workaround for groups, this issue was noted here: https://github.com/tisoap/react-flow-smart-edge/issues/32

Closing as duplicate