increase force between nodes that are not linked - d3.js

I have a force-directed graph using d3.js, part of the code is like:
simulation
.force("center", d3.forceCenter(width / 2, height / 2))
.force("nodes", d3.forceManyBody())
.force(
"links",
d3
.forceLink(links)
.id(d => d.id)
.distance(d => 5 * (d.source.size + d.target.size))
)
.on("tick", ticked);
this line determines the force between linked nodes:
.distance(d => 5 * (d.source.size + d.target.size))
however, I would like to provide a force between unlinked nodes (ideally, the force would increase as the degree of freedom increases).
How can I accomplish this?

these seem to do the trick:
.force("charge", d3.forceManyBody().strength(-98))
.force("collide", d3.forceCollide().radius(50))
how can I change these forces dynamically as the animation progresses?

Related

Avoid crossing links in force-directed graph (d3.js)

Using d3.js, I have this force-directed-graph situation:
let simulation = d3.forceSimulation(nodes);
simulation
.force("center", d3.forceCenter(width / 2, height / 2))
.force("nodes", d3.forceManyBody())
.force(
"links",
d3
.forceLink(links)
.id(d => d.id)
.distance(d => 5 * (d.source.size + d.target.size))
)
.on("tick", ticked);
this creates a repelling force between nodes. My goal: I would like to find a way to tell d3 to avoid crossing links - perhaps create an "artificial" midpoint element in the middle of the links and then repel those midpoints? One possibility.
In the above image, we can see that the blue node link is crossing/overlapping. I am seeking to discourage links from crossing/intersecting.
How can I accomplish this?

Box plot with dual dimension and dual x-axis using dc.js

Is it possible with dc.js to draw two x-axis of a graph i.e. one is below and one is above. One Dimension/ x-axis contain a b and above x-axis contain 1 (a b with below a-axis) 2 (a b with below x-axis). An img is attached to explain the view. If it is possible kindly give some suggestion.
Regards.
As for adding lines between the box plots, here is a hacky solution that works ok. Would probably need some work to make it general.
Assume we have the domain (['1A', '1B', '2A, '2B', ...]) in a variable called domain.
We can add a pretransition handler that draws lines after every second box:
function x_after(chart, n) {
return (chart.x()(domain[n]) + chart.x()(domain[n+1])) / 2 + chart.margins().left + 7; // why 7?
}
chart.on('pretransition', chart => {
let divide = chart.g().selectAll('line.divide').data(d3.range(domain.length/2));
divide.exit().remove();
divide = divide.enter()
.append('line')
.attr('class', 'divide')
.attr('stroke', 'black')
.merge(divide);
divide
.attr('x1', n => x_after(chart, n*2 + 1))
.attr('x2', n => x_after(chart, n*2 + 1))
.attr('y1', chart.margins().top)
.attr('y2', chart.margins().top + chart.effectiveHeight())
})
This uses the D3 general update pattern to add a vertical line after every other box (specifically those with odd index number).
It takes the average of the X position of 1B and 2A, 2B and 3A, etc. I have no idea why I had to add 7, so probably I am missing something.
demo fiddle.

D3.js spawn new circles at fixed time intervals with forceSimulation

Hi I am trying to spawn new circles in a set time interval (e.g., double the amount of existing circles every ten seconds) with D3.forceSimulation. I am using forceSimulation to make sure the circles do not overlap. My goal is to also have the new circles spawn in a position near the existing circles.
My initial approach is to append new {} elements into the nodes array using a setInterval function. Basically check the length of the nodes array every ten seconds and append new {} elements so that the new length of the array is double the previous length.
However, I don't think I am understanding/using nodes and d3.forceSimulation correctly. In the code below I see five circles appearing and moving away from each other. But I didn't pass any x or y positions to the circle elements that are joined to the nodes data? Are default/random positions being assigned to the circles?
I know if I add .force('center', d3.forceCenter(width / 2, height / 2)) the five circles will appear near the center of the screen before moving away. But I'm not sure how d3.forceSimulation is setting the initial positions of the five circles when they spawn in.
var nodes = [{}, {}, {}, {}, {}]
var simulation = d3.forceSimulation(nodes)
.force('charge', d3.forceManyBody())
.on('tick', ticked);
function ticked() {
var u = d3.select('svg')
.selectAll('circle')
.data(nodes)
u.enter()
.append('circle')
.attr('r', 5)
.merge(u)
.attr('cx', function(d) {
return d.x
})
.attr('cy', function(d) {
return d.y
})
u.exit().remove()
}
Yes, there are default position which are assigned to the circles.
Here is a quote from d3js docs:
The position ⟨x,y⟩ and velocity ⟨vx,vy⟩ may be subsequently modified
by forces and by the simulation. If either vx or vy is NaN, the
velocity is initialized to ⟨0,0⟩. If either x or y is NaN, the
position is initialized in a phyllotaxis arrangement, so chosen to
ensure a deterministic, uniform distribution around the origin.

How to change the Speed of a force-directed graph in d3.js?

I generated a force-directed graph in d3.js v4.
But I want to change the speed of the simulation, which is too fast. So, I want to slow it down. My simulation is below:
var simulation = d3.forceSimulation()
.force("link", d3.forceLink().id(function (d) { return d.id; }).distance(100).strength(1))
.force("collide", d3.forceCollide(function (d) { return d.r + 8 }).iterations(16))
.force("charge", d3.forceManyBody().strength(-700).distanceMin(100).distanceMax(1000))
.force("center", d3.forceCenter(width / 2, height / 2));
I want to make my force directed graph slow.
If your issue is that the nodes move around to fast, and you're looking for the plot to converge in a slower manner, use simulation.alphaDecay.
From the simulation.alphaDecay documentation:
The alpha decay rate determines how quickly the current alpha interpolates towards the desired target alpha; since the default target alpha is zero, by default this controls how quickly the simulation cools. Higher decay rates cause the simulation to stabilize more quickly, but risk getting stuck in a local minimum; lower values cause the simulation to take longer to run, but typically converge on a better layout. To have the simulation run forever at the current alpha, set the decay rate to zero; alternatively, set a target alpha greater than the minimum alpha.

D3: clustered force layout with fixed centers

I'm trying to accomplish something similar to the image below
example http://www.magora-systems.com/media/good.png
which I found on this page. The author gives some explanation on how he does this, using a clustered force technique from http://bl.ocks.org/mbostock/7882658, but not enough for me to fully understand it
What I do not know is how to set the centers of each cluster to a predefined location (where I define these center locations in a variable for example)?
My second, but less important question is about an extra feature that is mentioned on the blog where I found the image: "it’s been decided that a bubble with the largest diameter in a group will become central".
Does anybody know how to do this?
Thank you for any help!
It is an interesting cluster view that I haven't seen before with D3, thanks for that. I looked at the pages you linked, and the author describes a guide found here.
The Grants by Year tab for the example puts 3 clusters organized by year. The example code is calling vis.coffee and defining the year center locations like this :
#year_centers = {
"2008": {x: #width / 3, y: #height / 2},
"2009": {x: #width / 2, y: #height / 2},
"2010": {x: 2 * #width / 3, y: #height / 2}
}
And I see a method for moving the circles to their year_centers like this:
# move all circles to their associated #year_centers
move_towards_year: (alpha) =>
(d) =>
target = #year_centers[d.year]
d.x = d.x + (target.x - d.x) * (#damper + 0.02) * alpha * 1.1
d.y = d.y + (target.y - d.y) * (#damper + 0.02) * alpha * 1.1
You may want to poke around in the vis.coffee or vis.js files, but the vis.coffee file is the one referenced with the source example.

Resources