I have an application that generates a d3 display using the force-directed layout. One of capabilities in the application is to show all paths from vertex A to vertex B. I want to pin the start and end vertices to the left and right edges of the display and I've accomplished this programmatically, but I'm not happy with results as the force directed layout clumps all of the remaining vertices in the middle of the graph div. Changing the gravity and the link strength parameters to the force directed layout simply changes the size of the clump in the middle of the screen.
Any suggestions on how I can distribute the middle vertices more uniformly between the two pinned endpoints?
Thanks in advance.
Related
In this force directed graph,
https://codesandbox.io/s/3d-force-graph-forked-le6ny7
I want all nodes in group 2 to repel each other alot, but I want all nodes with any other group combination to repel each other only a little.
I saw this answer for how to apply a custom force to only certain nodes.
https://stackoverflow.com/a/61985672
I added this in the codesandbox (for whatever reason, this code isnt applied on page load - it doesnt re-draw the graph until I make some kind of code change, like adding a newline. Weird).
But after re-drawing the graph, now the graph is in 2D - not 3D anymore.
How can I add a custom force to only certain nodes, AND keep the graph in 3D?
I want to know that what algorithm is used for drawing the curve line between nodes in Node-RED Editor.
Here is an screenshot of the curved line.
Thanks.
You can see the code that generates the path here:
https://github.com/node-red/node-red/blob/d57edaa4c102a1bc2ec09f7703c7c8e6cdf04894/packages/node_modules/%40node-red/editor-client/src/js/ui/view.js#L666
It varies the approach used to determine the path based on the relative position of the two nodes it is connecting.
If the nodes don't overlap (that is, the right edge of the source node is to the left of the left edge of the destination node), then a simple bezier curve is used. The positions of the control points determined by the relative distance between the nodes.
If the destination node is further to the left of the source node (that is, the wire has to loop back on itself), then it gets more complicated, using 4 different curves. Again, all of the control points are determined by the relative distance and other scaling factors.
I have to create the nodes and edges, having interconnections. I am using d3 js for the same. Now the problem is that the graphs look so much messy. I tried using quadratic bezier curves to draw the edges between the nodes. I want that If a press a button it should rearrange into simplified view.
I happened to look at metacademy, they are a open source project. Which have the exact functionality I am looking for. https://metacademy.org/graphs/edit/new, you would need to login. However not able to find their part of code which is doing the same.
Initially created graph
After pressing the refresh button
I am pretty new to d3js, so I will be thankful for any help/suggestions.
I see this is a pretty old question, but FWIW, I designed the graph you're referring to.
Getting graphs to organize so that it minimizes edge crossing is an area of active research. For metacademy, I integrated d3.js + dagre
https://github.com/dagrejs/dagre
I would like to use graphviz for a project and am unable to get the behaviour I want. I have a graph that I can draw with graphviz just fine, but I also have a version of the same graph that has some extra edges. I would like the second graph to be drawn with the nodes in the same positions as the first one and the edges in the same positions, but the new edges to be drawn without avoiding any overlap with nodes.
To get a better idea of what I want, imagine a Powerpoint slide with a graph and then on the next slide the same graph with these extra edges that appear on top of the first graph, wihtout modifying the look of the old parts of the graph. That is the effect I want.
I think the effect could be achieved by having some edges ignore any overlapping constraints. I could not figure out how to control the overlap between edges and nodes for particular edges (or even for all edges).
Any ideas?
You can get dot to output another .dot file, with positions assigned to all elements, via dot -Tdot (or maybe dot -Txdot). Add your additional edges to that file, and run it through dot again to produce your second graph.
I am building a graph editor in C# where the user can place nodes and then connect them with either a directed or undirected edge. When finished, an A* pathfinding algorithm determines the best path between two nodes.
What I have: A Node class with an x, y, list of connected nodes and F, G and H scores.
An Edge class with a Start, Finish and whether or not it is directed.
A Graph class which contains a list of Nodes and Edges as well as the A* algorithm
Right now when a user wants to select a node or an edge, the mouse position gets recorded and I iterate through every node and edge to determine whether it should be selected. This is obviously slow. I was thinking I can implement a QuadTree for my nodes to speed it up however what can I do to speed up edge selection?
Since users are "drawing" these graphs I would assume they include a number of nodes and edges that humans would likely be able to generate (say 1-5k max?). Just store both in the same QuadTree (assuming you already have one written).
You can easily extend a classic QuadTree into a PMR QuadTree which adds splitting criteria based on the number of line segments crossing through them. I've written a hybrid PR/PMR QuadTree which supported bucketing both points and lines, and in reality it worked with a high enough performance for 10-50k moving objects (rebalancing buckets!).
So your problem is that the person has already drawn a set of nodes and edges, and you'd like to make the test to figure out which edge was clicked on much faster.
Well an edge is a line segment. For the purpose of filtering down to a small number of possible candidate edges, there is no harm in extending edges into lines. Even if you have a large number of edges, only a small number will pass close to a given point so iterating through those won't be bad.
Now divide edges into two groups. Vertical, and not vertical. You can store the vertical edges in a sorted datastructure and easily test which vertical lines are close to any given point.
The not vertical ones are more tricky. For them you can draw vertical boundaries to the left and right of the region where your nodes can be placed, and then store each line as the pair of heights at which the line intersects those lines. And you can store those pairs in a QuadTree. You can add to this QuadTree logic to be able to take a point, and search through the QuadTree for all lines passing within a certain distance of that point. (The idea is that at any point in the QuadTree you can construct a pair of bounding lines for all of the lines below that point. If your point is not between those lines, or close to them, you can skip that section of the tree.)
I think you have all the ingredients already.
Here's a suggestion:
Index all your edges in a spatial data structure (could be QuadTree, R-Tree etc.). Every edge should be indexed using its bounding box.
Record the mouse position.
Search for the most specific rectangle containing your mouse position.
This rectangle should have one or more edges/nodes; Iterate through them, according to the needed mode.
(The tricky part): If the user has not indicated any edge from the most specific rectangle, you should go up one level and iterate over the edges included in this level. Maybe you can do without this.
This should be faster.