Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow setting individual thickness and length of lines, maybe directly or using a "prority number" #317

Open
56independent opened this issue Apr 18, 2023 · 3 comments

Comments

@56independent
Copy link

56independent commented Apr 18, 2023

Is your feature request related to a problem? Please describe.
I made an issue on Trilium asking for the graph to be able to contract or pull individual links, keeping porportion similar. However, the developer discussed the fact that this library limits this from happening.

One problem with that is that IIRC the library which I'm using to render the maps ("force-graph") does not support per-connection "strength". They all "pull" the notes together with the same force.

However, this limitation may be due to the fact that:

Force-directed graphs are quite computation expensive, but this force-graph manages to behave well even with tens of thousands of objects. Not sure what the trick is, but maybe some of the optimizations require certain simplifications such as these.

Describe the solution you'd like

Firstly, i'd like to seek clarification of whether, in the eyes of the developer, these simplifications are required. If not, then i would like the ability to set the thickness and length of lines in two ways:

  • Setting an individual length: and thickness: (measured in arbitary units) to show how they're displayed, where in "impossible situations" (where the lengths are not able to interface), the biggest number is made a little bigger and the smallest a little smaller, the node with the most connections having priority
  • A priority number that works as above, but automatically determines the thickness

I don't have much experience with this project (yet), but i think that in the below snippet of code:

    const gData = {
      nodes: [...Array(N).keys()].map(i => ({ id: i })),
      links: [...Array(N).keys()]
        .filter(id => id)
        .map(id => ({
          source: id,
          target: Math.round(Math.random() * (id-1))
        }))
    };

we could add line thicknesses like so?

    const gData = {
      nodes: [...Array(N).keys()].map(i => ({ id: i })),
      links: [...Array(N).keys()]
        .filter(id => id)
        .map(id => ({
          source: id,
          target: Math.round(Math.random() * (id-1))
        })
        .looks(id => ({
          length: 20,
          thickness: 10
        }))
    };

This adds a new .looks function, opening the door to new "looks" and allowing more styling options to be added in the future.

@vasturiano
Copy link
Owner

@56independent thanks for reaching out.

It's certainly possible to add line thickness and calibrate the link attraction force between nodes.

Let's look at line thickness first. This is a purely cosmetic item (does not influence the force engine), and you can manipulate it per link, using the .lineWidth method.

As for the distance, or any other attributes of the link attraction force, you can calibrate it using all settings found in d3-force forceLink. The link force works a little bit like a spring in which each link has a target length (at rest), and any push/pulls from that position will be counter-acted with a linear attraction force. In this case if you're interested in changing the target distance of the links, you can do something like:

myGraph.d3Force('link').distance(link => /* your code */)

The same way you can modify other attributes of the force, like strength for instance.

@56independent
Copy link
Author

56independent commented Apr 18, 2023

Are you sure the link length is individually settable? I'd like each link to have it's own target distance.

However, i would like to see a "priority" value as well, which abstracts away the need for both to be modified; if the actual length post-being-made-a-spring is shorter then the amount set, it then makes the line thicker, and vice versa.

See my potential algorithm:

  1. Find the set priority number
  2. Multiply it by the "length factor" constant
  3. Use this to set the length
  4. Find the actual length afterwards
  5. Use the difference and multiply it by the "thickness reaction constant" to get the thickness
  6. Set the thickness to that amount

This then allows us to see how the nodes have been forced to change and where the most extreme relationships are.

@vasturiano
Copy link
Owner

Are you sure the link length is individually settable? I'd like each link to have it's own target distance.

Yes, both the distance and strength of the link force can be set independently per link, as mentioned in the docs.

This logic is quite app specific, so it makes sense for it to exist in the app, not in this module. But you should have all the configuration available from this module to be able to build it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants