Have D3 force directed graph form a specific shape? - javascript

I'm wondering if there is a way to have a D3 force graph form a specific shape. Here's what I mean. This what the graph looks like right now.
What I want is to be able to have the nodes form a shape such as this:
(ultra pro ms paint skills)
So I want all the nodes to be inside the black line, forming this shape. Is there a way to do this inside d3?

No, you can't do this directly with the D3 force layout. It doesn't allow for any additional constraints. What you can do is enforce this layout yourself in the tick handler function:
force.on("tick", function() {
// iterate over all nodes, check if they're in a position they shouldn't be in
// if so, adjust the position
});
That said, you almost certainly don't need the force layout in this case. As suggested in the comments, it would be easier to manually position the nodes along the shape that you want. Again, there's no support in D3 to do that.

Related

Draw links to a d3 circle pack layout

I need to be able to draw links between the circles in a circle pack layout, like {source: i, target: j}. I've seen some questions about how to combine this layout with the force layout that made me think It could be a way to achieve this but I haven't had any luck on that path, also what I need is something completely static. Thank you in advance for any suggestions.
I finally could draw lines between nodes by appending them to the svg and calculating each line position based on the radius of the nodes that each line were to connect, but the problem was that the pack layout that I'm using is zoomable, so when I tried to zoom by clicking the lines neither translate nor re-sized (of course, since there was no code performing such things), so I tried to implement a translation function for the lines so they would move along with the zoom, then I saw that it would take some serious geometry to achieve this, so since I'm a lazy programmer and not at all experienced with d3 I tried to come with something more simple... at last I decided to represent the links between the nodes with a different approach (without lines), I used the "mouseover" event so when the pointer is over a node it will highlight (changed circle stroke attribute color and width) the nodes connected to it. This way I achieved my goal and the view looks a lot cleaner without all the lines crossing over it (they were a lot). I know that some may think that this does not answer the original question, and I'm sure that this can be achieved by someone with more experience (and time and patience) using lines and implementing the right calculation, but in my case this solution solves my problem and maybe it could be of help to others.

Multiple forces in d3

Hi I have the following graph.The rectangles represent groups where the nodes inside or on the border of the rectangle are restricted to that rectangle. I am using d3 force layout to layout the nodes but then restrict them to the bounding rectangles in the tick.
What I need is,
1. One force layout to handle the nodes as they currently do
2. A second force layout that handles the rectangles in the graph, so that rectangles don't overlap with each other.
It would be an added bonus if the rectangles could also be stopped from overlapping with nodes that are outside the rectangles to avoid confusion.
Can anyone point me to an example that does something similar or code something up quickly to demonstrate how this can be achieved.
Thanks.

D3.js Force Layout - showing only part of a graph

Good morning,
just starting with the awesome d3js library ...
I want to show only a portion of a graph with the force directed layout. The idea is to have one node declared as the "center" and show all nodes within a distance of two (for example) from this center node, the neighbors of the center node and the neighbors of the neighbors. If the user clicks on one of the displayed nodes it becomes the "new" center node and a different "subgraph" is displayed. I wonder if there is an example around implementing this kind of subgraph layout and if some kind of a "node-distance" algorithm is already implemented in d3js.
Thanks a lot
martin
UPDATE:
Just found the example Modifying a Force Layout which illuminates how to add and remove nodes and edges from a force directed layout.
I just uploaded a "proof of concept level" of an interactive force directed subgraph.
http://justdharma.com/d3/sub-graph/
In this example I use backbonejs under the hood. Being the first time I implement something with backbonejs, I for sure use it in a very crude manner. While this example might illuminate one way how an interactive sub-graph can be achieved it is for sure not a template how to do it - as said just a proof of concept hack ...
This isn't implemented in D3, and I'm not aware of any examples. What you would have to do is the following:
Set the fixed attribute of the new center node to true to prevent the force layout from changing its position.
Set the px and py attributes of that same node to the center position.
For each node in your force layout, compute the shortest path to the new center node.
Depending on the length of the path in each case, either remove the node or keep it.
The trickiest part here is the computation of the path from each node to the new center, but even this is a pretty standard algorithmic problem. Another thing to keep in mind is that you need to modify the data structures that contain the nodes and links of the force layout in place, i.e. you can't set new nodes and links for the force layout and expect everything to work smoothly.

Key binding with d3.svg.path()

I have a simple d3.js time-series graph plotted as SVG circles. The circles are key bound so that when I remove data from end of the array, circles from right are removed and when I remove items from the beginning of the array, circles from left are removed on exit.remove().
var circles = svg.selectAll('circle')
.data(data, function(d){return d.key})
Now, I want to do the same with a SVG path.
Is there a way to apply key binding to SVG path?
I had a similar issue when I wanted to make a live-updating plot in d3 with an SVG path. d3 uses only one path element for an entire data sequence, i.e. for a given array there is one path drawn that can get very very long depending on your data. This means that d3 cannot simply remove bound data elements by removing DOM elements like circles. It would have to modify something like <path d="M0,0L1,0L2,1L3,2"> to <path d="M1,0L2,1L3,2">. I do not think d3 has this capability, unfortunately (Though you could code this yourself! You need to override d3.interpolateString and write some custom interpolator that notices the dropped points.)
This also means that you can't use D3's data selector, since data works on a group with multiple elements, like svg circles. You're going to have to use select("#yoursvgpath").datum(data) instead, which sets the data of a single element, where data is your data array.
Since I knew the hardware my code would run on was fast (desktop i7, ssd, etc...), I simply redrew the path every time I added or removed elements. Even still, it's pretty slow in Firefox (but fine in Chrome), especially when the number of points gets over around 10,000. To redraw, just call datum again and then re-apply your coordinate transformer (something like select("#yoursvgpath").attr("d", line) where line is your path data transformer). I ended up only redrawing every 5,000 data elements so that the path wasn't constantly being recalculated.
If any of this was confusing, I would definitely read up on making line charts in d3, it's quite a bit different (and less intuitive) than point-based charts. I'd also take a look at https://gist.github.com/mbostock/1642874 and http://bost.ocks.org/mike/selection/, for learning more about d3 selections and line charts.

Add/Remove nodes in a line graph in jqPlot

Is it possible to start with a plot (in jqPlot), either as a function or a list of points, and make it possible for the user to add or remove nodes on the graph? Ideally, it would keep the line/curve the same and just add another node, though with some curves that obviously won't be possible. It isn't crucial that the existing nodes stay in the same place; in fact, it is crucial that the nodes remain equidistant along the x-axis. I'm using Can someone point me in the right direction?

Categories