cytoscape / cytoscape.js

Graph theory (network) library for visualisation and analysis
https://js.cytoscape.org
MIT License
10k stars 1.64k forks source link

Compound nodes not working for CoSE layout #3254

Closed brettzallen closed 3 weeks ago

brettzallen commented 2 months ago

Before you post

A request for help or a request for a how-to should be directed to Phind.

lol

image

Environment info

Current (buggy) behaviour

What does the bug do?

I have this simple code:

function testCytoscape() {
  const cy = cytoscape({
    elements: {
      nodes: [
        { data: { id: 'a', parent: 'b' } },
        { data: { id: 'b' } },
        { data: { id: 'c', parent: 'b' } },
        // { data: { id: 'd' } },
        // { data: { id: 'e', parent: 'd' } },
        // { data: { id: 'f', parent: 'd' } },
      ],
      edges: [
        // { data: { id: 'af', source: 'a', target: 'f' } },
        // { data: { id: 'ec', source: 'e', target: 'c' } },
      ],
    },
  });
  cy.layout({
    name: 'cose',
    fit: true,
    randomize: false,
    componentSpacing: 100,
    idealEdgeLength: () => 100,
    nodeRepulsion: () => 40000,
    numIter: 100,
    initialTemp: 200,
  })
    .run()
    .promiseOn('layoutstop')
    .then(() => {
      console.log({
        positionsStopped: cy
          .nodes()
          .map((node) => ({ name: node.id(), ...node.position() })),
      });
    })
    .catch((error) => {
      console.error('Layout error:', error);
    });

  console.log({ positions: cy.nodes().map((node) => node.position()) });
}

and I am getting what looks like a correct output:

{
    "positionsStopped": [
        {
            "name": "a",
            "x": 0.5,
            "y": 0.5
        },
        {
            "name": "b",
            "x": null,
            "y": null
        },
        {
            "name": "c",
            "x": 101.5,
            "y": 0.5
        }
    ]
}

But then when I uncomment those three more nodes:

  const cy = cytoscape({
    elements: {
      nodes: [
        { data: { id: 'a', parent: 'b' } },
        { data: { id: 'b' } },
        { data: { id: 'c', parent: 'b' } },
        { data: { id: 'd' } },
        { data: { id: 'e', parent: 'd' } },
        { data: { id: 'f', parent: 'd' } },
      ],
      edges: [
        // { data: { id: 'af', source: 'a', target: 'f' } },
        // { data: { id: 'ec', source: 'e', target: 'c' } },
      ],
    },
  });

all of the sudden something breaks:

{
    "positionsStopped": [
        {
            "name": "a",
            "x": null,
            "y": null
        },
        {
            "name": "b",
            "x": null,
            "y": null
        },
        {
            "name": "c",
            "x": null,
            "y": null
        },
        {
            "name": "d",
            "x": null,
            "y": null
        },
        {
            "name": "e",
            "x": null,
            "y": null
        },
        {
            "name": "f",
            "x": null,
            "y": null
        }
    ]
}

Desired behaviour

What do you expect Cytoscape.js to do instead?

I would expect positions to be generated for the non-compound nodes just the same as it did in the first iteration.

Minimum steps to reproduce

What do you need to do to reproduce the issue?

Fork/clone this JSBin demo and reproduce your issue so that your issue can be addressed quickly and effectively: http://jsbin.com/fiqugiq

Just run the code I attached above!

For reviewers

Reviewers should ensure that the following tasks are carried out for incorporated issues:

maxkfranz commented 2 months ago

This looks like a good start to the issue. Let's expand it with a demo of your issue (e.g. jsbin) so we can move forward to the next step.

maxkfranz commented 1 month ago

Assigning to @brettzallen until he posts his demo

brettzallen commented 1 month ago

Here is the demo!

https://jsbin.com/gitebepobo/edit?js,console

image

it looks like the positions are 0 instead of null in this case. Interestingly if you click the output the graph appears to work, but I am not sure where the positions are coming from. Regardless, I just need the coordinates so the display doesn't matter in this case

brettzallen commented 1 month ago
image

See the output graph working, but the positions are not...

brettzallen commented 1 month ago

@maxkfranz don't think I am able to assign this back to you but that is the demo

maxkfranz commented 1 month ago

Here are some references on how asynchronous code works in JS and force-directed (continuous/async) layouts. That should sort it out.

See