Accessing data automatically assigned by force layout - d3.js

I am creating a network of nodes and edges using force layout. My application has some dynamic nodes (which can be any number determined by backend code). I am allowing the force layout to assign the x and y for these dynamic nodes by itself which it does on calling force.start() function.
Now, there are a different set of nodes which are moving over the edges(eg. cars moving on roads) connecting the static and dynamic nodes. For this animation, I need to get the x and y values from the force.nodes() which it has assigned to the dynamic nodes. I tried the normal dot operator to get the values but it fails to return the actual value.
Below is one of the value of node
[09:13:07.505] ({name:"D_Exit_0", dynamic:true, act_cap:-1, danger:0, index:0, weight:1, x:3014.087389427884, y:513.2901517247882, px:3013.9965777253265, py:513.0782974731648})
The x and y values here are assigned by the force layout.
When I tried node.x, it is returning me a value I had accessed just before accessing this node. However, when I directly print the node using console.log(node) it gives the above output.
Kindly let me know how I can get the dynamic data assigned by the force layout itself i.e. value x: 3014.08.. in above case?

force.nodes() should return an array of all the nodes. To get the x value from one the first one, use force.nodes()[0].x (documentation).
To animate something along the connection between the nodes, you might better off working with force.links(), which returns all the links between nodes. If you're working off of one of the examples, there should be a line of code similar to var link = svg.selectAll(".link"); if there is you could, for example, slowly turn all the links green with:
> link.transition().duration(5000).style("stroke", "green")
If you have any more questions, post the code you have so far on jsfiddle or bl.ocks.org.

Related

Why in THREE.js the arithmetic expression in Object3D.translateX isn't evaluated as expected or Vector.copy doesn't work correctly in animate loop?

I'm trying to move an object called "car" via the dat.gui. If the user changes the x value using the dat.gui slider, the car should move along the x-axis of its local coordinate system.
here I have copied the part of the code that is causing me problems:
var m = new THREE.Vector3;
m.copy(car.position);
if (changed.key=='X') car.translateX(changed.value-car.worldToLocal(m).x);
My problem is that the expression in car.translateX always evaluates to the value that is in changed.value. The part after the minus has no effect at all or maybe is permanently 0. I have printed the values ​with console.log and the values ​​of car.position.x and m change in each step, but the subtraction still delivers in every step only the result that is already in changed.value anyway. Can someone help me and tell me why this happens?
Unfortunately, I am absolutely stuck.
car.worldToLocal(m)
I'm afraid this piece of code makes no sense since car.position (and thus m) already represents the car's position in local space.
Instead of using translateX() you achieve the same result by modifying car.position directly:
car.position.x = changed.value;

What's the right way to expand filtered nodes in ivh-treeview?

Per the discussion here, currently the ivh-treeview Angular library does not expand collapsed nodes when the tree is filtered and a leaf node matches the filter.
Would the right way to implement this behavior be to add an ng-change handler to the input element used for the filter text and then query the tree in the containing controller (thus, doing it manually)?
There doesn't appear to be any other mechanism by which to detect if the filter is changed.
BTW, there exists no ivh-treeview tag so I can't really tag this properly. Apologies if I've hijacked someone else's tag. That said it appears to be the tag used for other ivh-treeview related questions.
There's really no way to do this elegantly I'm afraid. The best you can do is expand the entire tree (with expandRecursive) when you detect the filter is non-empty (or past some threshold). By completely expanding the tree you get to "show filtered nodes" by virtue of the fact that everything else is hidden by ivhTreeview. That's the easy part. The hard part is when there's no longer a filter how do you restore the tree to it's previous partially-expanded state.
If I had to do it I'd probably end up walking the tree to grab the expanded state from each node before the recursive expand then restore that state when the filter is removed. This would clobber collapse/expand actions while there was a filter in play... you could handle that too but things start to get hairy very quickly. E.g.:
var isExpanded = ivhTreeviewOpts().expandedAttribute
// When the filter becomes non-empty
ivhTreeviewBfs(myTree, function(node) {
node.savedExpandedState = n[isExpanded]
})
ivhTreeviewMgr.expandRecursive(tree)
// When the filter becomes empty
ivhTreeviewBfs(myTree, function(node) {
node[isexpanded] = node.savedExpandedState
})
Here's a rough demo: http://jsbin.com/jijoma/3/edit?html,js,output
Hope that helps!

Modifying a Force Layout - using indexes rather than references gives TypeError

I am working on a simple D3 force-directed layout, based on the Modifying a Force Layout example, which works fine, using hard-coded data updated using setTimeout callbacks:
However, I will be loading the data dynamically from the server as JSON, so would like the link source and target to be specified as indexes into the nodes array, rather than references to the actual JavaScript node objects. This option is described in the documentation;
Note: the values of the source and target attributes may be initially
specified as indexes into the nodes array; these will be replaced by
references after the call to start.
As a first step, I have tried modifying the example to use indexes; in the snippet below:
var a = {id: "a"}, b = {id: "b"}, c = {id: "c"};
nodes.push(a, b, c);
links.push({source: a, target: b},{source: a, target: c},{source: b, target: c});
start(); // joins the data, (re)starts the d3.layout.force
I change just a single line to use indexes into the nodes as follows:
links.push({source: 0, target: 1},{source: 0, target: 2},{source: 1, target: 2});
However, this results in a JavaScript error from d3.v3.min.js (Firefox 35.0.1):
TypeError: u is undefined
and the graph is only partially created - all 3 nodes are shown, but only one link:
Is is possible to use indexes in this manner?
No, using indices in this way isn't possible with the current implementation of the force layout. When you start the layout, all indices in the links are replaced by references to the objects (this is why the documentation says that you can use indices, see lines 223-229 of the source). When you push indices without (re)starting the layout, this substitution doesn't happen and the code breaks.
You have two choices to make this work -- either push references to the node objects, or call .start() on the force layout after each push. Note that for the latter you should also stop the layout before pushing and all forces will be re-initialised, making the layout very "jumpy" every time you change something.
It sounds like in your case pushing references to node objects rather than indices wouldn't be a problem though, as you have access to the array of nodes. All you need to do then is index into it, as done in the D3 source.

Using dc.js without crossfilter

They have been various discussions on how to use dc.js simply as graph library (eg. to draw a piechart, a barchart...) without needing crossfilter, for instance if you simply want to draw a single pie when the data is already a (label, value).
I didn't find any example of how to do that. Is this possible on the 2.0 branch? Will it work for every chart?
So the "normal" way is to define data(), but as this function is already defined internally from some charts, it doesn't work that well:
in http://github.com/dc-js/dc.js/issues/584
Details: the following charts use .data() internally:
Stack Mixin (thus Line and Bar) - filters and then does stack d3.layout.stack on the data Cap Mixin (thus Pie and Row) - optionally limits the number of bins, sorts the groups using the ordering, and optionally creates the "others" bin
Number Chart - looks to see if the group has a value() function (e.g. it's a group-all). Otherwise, takes the top value. Runs the valueAccessor on the result (!!!)
Box Plot - adds a mapping function to the data. Filters out values (which are themselves arrays) that are of length 0.

how to establish relation between any two nodes of d3 tree layout

I have a D3 tree layout.There will be relation between any two nodes,based on this relation i want to show some connection between 2 nodes.Till now i was using circles.on onmouse circles of the 2 nodes will be in some specified color.circles were not covering images exaclty.so i applied transform but it disturbing some other functionalities.
my sole purpose is to show some connection between any two nodes using circles or something else.i tried applying circles using CSS3 but it didnt work
is there any way to achieve my requirement
If I am understanding you, there are different ways to achieve this, and this is only one.
Consider this:
function highlight() {
var selectedClass = d3.select(this).attr("class");
d3.selectAll("circle")
.style("fill",function(d) {
if ( selectedClass == d3.select(this).attr("class"))
return "magenta";
});
}
Assuming you have established the relationship between any given number of nodes (two or more) by assigning them the same class (perhaps a big assumption), then code like the one above can display such relationship. If you click on one of the nodes (this function is called by the node .on("click"...), the others will also display the desired change, illustrated here by a change in color. Does this help?

Resources