d3 force layout nodes in predictable order - javascript

Whenever you refresh this example, the nodes are in a different order. How could you make it so the order is the same upon each refresh? Perhaps "sub node 1" at the top, then adjacent to the right is "sub node 2", etc, all the way around. Other than that, this example works for what I need to achieve.
The solutions below seem to require fixing the nodes to x,y points. But doing that seems to eliminate the drag functionality (the nodes need to be able to be dragged into different locations to change the order). Also, I don't always know how many nodes there will be initially.
https://groups.google.com/forum/#!topic/d3-js/NsHlubbv3pc
Calm down initial tick of a force layout
Configure fixed-layout static graph in d3.js
While the drag is a requirement, the animation is not. I tried seeing if stoping the animation had any effect, but it didn't.
var n = 50;
for (var i = 0; i < n; ++i) force.tick();
force.stop();
Also, tried adding a new property to the data giving each child a rank to manipulate somehow. And tried assigning id of the rank and sorting. Also tried using the index number of the array of objects. No luck. Thanks for any ideas.

Per Lars' comment, it seems this is not possible in a force layout. Switched to tree layout. JSFIDDLE Still need to add the drag piece. Will update if I can get that working.
Links to jsfiddle.net must be accompanied by code.

The reason it is not the same each time is d3 uses a random number to prevent nodes getting stuck in odd places. In my limited understanding the random number acts to "jiggle" the graph to help it untangle itself.
A simple solution to making it predictable is to replace the random number generator with a predictable random number generator such as that provided by seedrandom.
If you seed the random number generator with the same seed before running the simulation the results will be the same every time.
Note only a small change to the graph will cause the graph to have a completely different layout. (I always think of the butterfly chaos effect to explain why).

Related

Compound nodes layout issues - cytoscape js

Update: Added a collage of the images I was going to add to get around reputation block
I've been working on a cytoscape implementation that will dynamically display information I'm pulling from my database onto a webpage. The goal is to be an organization chart, displaying nodes in groups, in a directed tree structure. I've been doing a lot of research, and trying out several different layouts and api options to try and meet the use case, but I'm having issues getting it to work the way I'm intending.
Specifically I want to use compound nodes - the parents being the people's ranks. I've learned that a lot of layouts simply haven't been designed with compound nodes in mind, and I've been trying different implementations, including ones that create an initial layout, and then try to run a secondary layout specifically on the descendants of the parents.
Following are the closest of what I've tried and their issues:
Images of graphs: https://i.stack.imgur.com/6hzVS.png
cose-bilkent:
The main issue with this is that it doesn't seem to be meant for directed trees, but rather decides placement on its own. The bigger issue I've had is that I couldn't find a way to spread the nodes out better within their groups. I've tried to use the node padding options included, but they haven't had an affect, which I'm assuming is due to the compound nature.
grid:
Graph is in a perfectly grid like layout of all the nodes, but ignores parent nodes.
This layout was working for me initially, and would have the benefit of being able to easily change the amount of people per column. As I changed the elements though I realized it was a coincidence that it worked initially - it seems like it's totally ignoring the parent nodes, which is understandable if it wasn't designed with them in mind.
grid - descendants:
Graph is of the two sets of descendants layered on top of each other.
What I tried next was using a different layout to determine the initial placing of the parents, and then performing a grid layout on the descendants to make them organized in their groups. I realized then that parents are simply reacting to their child's placement. Also, it appears that calling layouts on sets of nodes separately for grid was completely ignoring anything else that exists on the graph, causing the groups to be put on top of each other.
cola:
It's close, but the way it puts them on the graph is not well structured, causing the placement in the groups to be jumbled up, though they are spaced out enough.
This appears it would work great if I could figure out how to run a proper layout on the parent nodes, forcing the tree structure that works without compound nodes.
Here is more or less what I'd like to see, though the logic for # of nodes per column isn't that important. As long as they're organized neatly:
https://i.stack.imgur.com/irVaK.png
Is there any advice someone could give on how I could go about making this work? I haven't been able to find any layout setups that work quite right, and I don't really know what to do from here. I would also prefer to avoid creating an entirely new layout from scratch. Any help is greatly appreciated.
If you have a proper tree data structure, you shouldn't be using compound nodes for layout. It's not generally possible to satisfy compound parent position restrictions when there are additional constraints on the children. This is because a parent is naturally constrained by its children -- a parent doesn't have its own position or size, it's children define it implicitly.
The best layouts for compound graphs are force-directed (physics simulation) ones like CoSE or Cola.
In your case, you just have a tree. I would use the breadthfirst or Dagre layouts without any compounds. Each level will naturally indicate rank.
For anyone interested, what I've done to solve this is create my own preset layout function that dictates where (children) nodes go on the graph, using their properties to dictate where they go.
It's designed to only display linear compound graphs, in order based on "level" in the hierarchy. It's capable of displaying the children nodes in grid-like sets within their parent nodes (visually - remember parents simply adjust according to their children), in the order of the mentioned linear levels.
You can also specify the values for how many columns in a set, space between nodes, and space between levels. There's obviously lots of room to make the variables more verbose if you'd like to specify "x-space" and "y-space" between nodes, and things like that.
It assumes the following:
-You know ahead of time what level corresponds to each compound group
-You know ahead of time how many nodes are in each compound group
-If you're making this dynamically, that you have a way to dynamically produce the javascript variables necessary for the dictionary, which tracks the total size of each group and how many nodes of each group have been accounted for.
Here's the code. I know it's a niche case, but if you do have a reason to use it, just keep in mind that it's sure to be bug prone, and is definitely inefficient (Javascript isn't my forte...). I've tested certain edge cases that I feel are common in my project, but there could be others that aren't accounted for.
http://jsbin.com/quyipo/edit
(Also upvotes/comments don't hurt either. I'm curious if this could actually help someone...)

vis.js physics - how to fix some nodes in place

In my application, a graph is loaded initially with the one-net of a particular node. The user can expand the graph by double-clicking any node to add its one-net.
The problem is that every time the user does that, the nodes all jump around, so it's confusing. I don't want to just disable physics, because then the new nodes get jumbled on top of the old ones. For lack of a better explanation, I want to freeze the existing nodes, only using physics to arrange the new nodes (and then freeze them before adding more). I looked at Stop vis.js physics after nodes load but allow drag-able nodes, but that doesn't solve my problem.
I'm pretty clueless about what the various options to the physics solving algorithms mean, and can't find a good description anywhere, so I wonder if there may be tweaks there that would help me.
Thanks!
You can give some of your nodes a fixed x and y position. There are also methods like getPositions() and storePositions() to retrieve or set the positions after the first stabilization or something like that.

D3 Force Directed Graph Design

Can someone review my implementation on JSFiddle and give me some pointers making my code cleaner and robust?
I've been working on this in JsFiddle. I am attempting to get a nice clean graph implementation for workflow design. For instance, we have input and output nodes and processes in between. Although I've done linq style functional programming in C#, this javascript implementation is a bit tougher to get my head around. All of the functionality that I want is in the various example pieces of code. I have attempted to bring them together, but it could be tidier and nicer.
http://jsfiddle.net/3ckG5/9/
These definitions confuse me, they have different names and properties across the examples. Really not getting it.
var svg = d3.select('body')
.append('svg')
.attr('width', width)
.attr('height', height);
The object scopes confuse me and I don't fully understand them.
Here is a list of functionality, a bold text indicates working. This example forms the basis of the implementation (http://bl.ocks.org/rkirsling/5001347), and others are linked next to the bit of functionality that they confer. However i am getting confused as they each work slightly differently and bringing them together is more of a challenge than anticipated.
Nodes
Nodes repel each other with charge value
Control node colour
Control node radius
Control node label
Delete a node
Deleting a node, also deletes that node's inputs and outputs //Node selector???
Node dragging and repositioning. kinda.... but oh so buggy (http://bl.ocks.org/norrs/2883411)
Only process nodes can be dragged and repositioned.
Node inputs or outputs repositioned based on associated process node position.
Labels on nodes
Only node inputs and outputs can form links
Only node inputs can connect to node outputs and vice versa.
Can only connect if same input/output type
Change colour of all nodes of the same type that can be connected to, when going to connect two nodes.
Links
Set link lengths
A drag line is is made on mouse down.
Markers on links
Markers always point from input to output.
Area
Pan/Zoom (http://bl.ocks.org/benzguo/4370043)
Any tips would be greatly appreciated.
DUPLICATED IN STACKEXCHANGE..... although they feel it is off topic on there. Anyone? Anyone at all have some positive input here?

Algorithm for finding empty cell around desired position in a grid

I will describe my problem using the attached image :
The green block is the starting position of my game entity. Next I'd like to move it to the position marked by the orange square. But at the same time, I assume that levitation is not possible or/& this block is a wall. In either case going there is not possible. So I need to figure out a way of finding the first available place (as close to the orange square as possible) for my entity to move (in this case it would be either the top of the grey column or point two rows beneath the orange square).
I have a 2d array describing the grid, where 1 is a wall and 0 is empty space.
data = [
[1,1,1,1,...],
[1,0,0,0,0,...],
[1,0,0,...],
...
]
I was thinking about solution in this way (where for example I can check at 1. if beneath my cell is floor and end the algo, or continue if not to cell 2.) but I can't think of a way of doing this efficiently (and easily).
Does anyone has any ideas how to tackle this ? I'm not really sure what algo should I ask google for :)
You are looking for Q-learning algorithms. This is a form of reinforcement learning. Here's one http://en.wikipedia.org/wiki/SARSA
Basically you run the simulation between source and destination multiple times and each time it gets close and closer to discovering the goal.
I think you can use Cellular Automata for your case, if it is worth the trouble. It is not AI per se, easy to implement and you can replace A* as well as the final position finding problem using one logic.
Consider the eight neighbourhood cells around the game entity. Each cell can be free or blocked (0 or 1). There will be 2^8 combinations of the neighbourhood, but you may or may not have to use that many rules for the CA.
Try looking into this: http://www.cs.sun.ac.za/rw711/2012term1/documents/CABehringPathPlanning.pdf
they implemented CA for path planning in robotics, you can tweak it to suit your need.
The advantage is, with proper rule set, your CA will terminate only when the game entity has reached the appropriate position around the goal (closest to the goal and not levitating).
You can also implement multiple rule sets on the system, thereby making it more robust.

Positioning multiple, random sized, absolutely positioned elements so they don't overlap

Ok I need to be able to position a bunch of random sized absolutely positioned words on a page but I don't want any of the elements to overlap.
The end goal is to have a fluid word cloud that responds to user interaction (remember the Google Balls Doodle?). I would really like to build this from scratch to develop my understanding of this type of development. Any help in this department would also be appreciated :)
I'm not sure if you also want to position the words randomly inside a container, but i've written a fiddle that does just that. You can modify the code to position one word right after the other if you want to though. I think the key part is the method to check if there's a collision.
see http://jsfiddle.net/fZtdt/13/
EDIT: Be aware that this is very simple and unoptimized code. If for example you would add to many words, chances are that the script won't be able to fit all words inside the container, and get into an endless loop.
I have forked Jules' script to add this improvement : the search for a non-overlapping region is bounded (otherwise the original script will loop I believe), and the best region (the one with the smallest overlap) is selected.
see http://jsfiddle.net/Vnyvc/21/
play with the maxSearchIterations variable and/or the size of the whole region, it really makes a difference.

Categories

Resources