I'm working with D3 as a newcomer and trying to figure out if the following is possible.
I want two collapsable trees, I'm thinking based the gallery example:
Collapsible Indented Tree
I want to draw lines and make associations between their nodes and a 3rd object.
This is a rough mock-up:
My confusions at this point are:
Is it possible to have two tree layouts present?
How can I draw lines from the tree layout nodes to some other object outside the layout?
Yes, this is entirely possible -- you could even use the same tree layout for both if you wanted to. The fundamental thing to understand is that the tree layout is only a means of getting the coordinates for the nodes; it doesn't have anything to do with actually drawing them. So you first run the tree layout to get those coordinates and then draw the nodes in a separate step.
In the example you've linked to, the layout is computed at the start of the update function:
// Compute the flattened node list. TODO use d3.layout.hierarchy.
var nodes = tree.nodes(root);
// Compute the "layout".
nodes.forEach(function(n, i) {
n.x = i * barHeight;
});
The rest of that function is only concerned with actually drawing the nodes and links. So in order to have several trees, you would run the above code again for a different root. This gives you coordinates for both trees which you can then append to container elements that are offset from each other:
var tree1 = svg.append("g");
var tree2 = svg.append("g").attr("transform", "translate(500,0)");
Note that you don't need to change the coordinates of the nodes at all, as they will be relative to their containers. Then you can draw your center element and the links going to it. The only caveat there is that for links starting at the right tree, you would have to offset the coordinates you get from the tree layout by the amount the container element is offset.
Related
My object is constructed in a honeycomb grid. All objects are connected. The red lines represents the connection between each node. I heard Binary Space Partitioning (BSP) Trees is good with this type of problem, but not sure what is front and back in my case.
I've implemented the lookup using the honeycomb grid system as shown (x , y)
class Node {
Point position; //center position
Point grid; //honeycomb grid system
}
class MyObject {
Node lookup(Point grid);
}
I need a data structure that represent the graph as user add more nodes onto the scene and a way to quickly determine if a grid point is (against MyObject):
1. outside
2. inside
3. inside a hole
How big is the space you're working in?
Simulate the whole thing with a simple rectangular grid assuming even-rows are staggered right.
Any node has coordinates [x,y]
For (y%2 == 0) neighbor nodes are [x-1,y][x+1,y][x,y+1][x,y-1][x-1,y-1][x-1,y+1]
For (y%2 == 1) neighbor nodes are [x-1,y][x+1,y][x,y+1][x,y-1][x+1,y-1][x+1,y+1]
Each node can be full or empty and empty nodes can be checked or not checked. Originally all empty nodes are not checked.
Check if a node belongs to a hole by:
if node is full - it does not belong to hole, it belongs to the shape.
if a node is empty mark node as checked.
Iterate over all neighbor nodes:
Skip nodes marked as checked or full
recursively repeat the search for all nodes not checked.
If the recursion brings you into any x<0, y<0, x>MAX_X, y>MAX_Y, abort. The node is outside the shape
If the recursion ends without finding edges of the playfield, the node belongs to a hole.
Additionally, you may now repeat the procedure turning all checked nodes into outside or hole for later reference.
If you want to index all holes at start, it may be easier to find all not checked empty nodes at borders of the playfield (x==0, y==0, x==MAX_X, y==MAX_Y) and use the above algorithm to mark them as outside. All remaining empty nodes are holes.
Depending on your grid size, you may implement it as 2D array of structs/objects containing object state (or even chars, with status as bits of the number), sized [MAX_X+1][MAX_Y+1] if it's reasonably sized, or as a list (vector) of full nodes, each containing its coords, status and if you want this to be more speed-optimal, neighbors. In this case, search the shape, finding all empty neighbor nodes for potential holes. Edge nodes with extreme coords (lowest/highest x/y) belong to "outside". Follow their empty neighbors that have full neighbors, to find the outer edge of the shape. All remaining are inner edges and after following the algorithm starting with them you'll have all your "holes".
My suggestion:
Assign each tile a center position in a 2d cartesian space.
Build a binary search tree (BST) containing all center positions.
For a query point find the relative position to the nearest occupied tile using that BST.
Determine whether that position is inside or outside the tile using some geometric formula, e.g., as in here:
Is a point inside regular hexagon
Alternatively, work with an approximation using squares, e.g., as seen here:
Hexagonal Grids, how do you find which hexagon a point is in?
In d3.js, i find that the tree layout cannot calculate the previous nodes by a certain node, it only can draw the successor nodes. is that some layout like DAG can be draw in d3.js?
Couple of ideas you might find useful:
You can use the tree layout to place the nodes in the canvas, create link objects pointing back and forth, then bind the link objects to a diagonal.
http://www.durablejs.org/examples/flowchart/1/admin.html
You can also use place the nodes using a pack layout, create the link objects pointing back and forth, and bind the links to a Bezier curve.
http://www.durablejs.org/examples/statechart/1/admin.html
You can find the code for the graphs above:
https://github.com/jruizgit/durable/tree/master/lib/durabjevisual.js
I want to visualize a series of hierarchical bullet graphs. Specifically, I want to be able to click on my top level category bullet graphs, and have them expand into the sub-topic breakdowns with a bullet graph for each sub-topic.
So basically, I want to recreate this D3 tree example:
http://mbostock.github.com/d3/talk/20111018/tree.html
But have each node be a bullet graph instead of just a circle:
http://mbostock.github.com/d3/ex/bullet.html
I'm brand new to D3, so even looking at the example source code, I'm not sure where to start.
The key is that the canvas acts like a real two dimensional drawing canvas. You, as the author of the visualization control where you place any object on the canvas. There are two things you need to worry about... 1) Making sure you have all data that you need to realize a visualization at a specific point on the canvas, and 2) Understanding how to draw your visualization in the way you want to render it, where you want to render it on the canvas.
In the case of mixing charts with the nodes of a tree, the nodes act as reference points for placement of the charts. You'll quickly notice that the more nodes you have, the more difficult it will be to render your charts because of canvas clutter. In other words, you will be dynamically be drawing charts over tree elements (nodes and branches). You may want to consider something like rendering the chart related to a node in another area of the canvas that does not contend with the tree visualization (such as the upper left or lower left of the canvas). So, for example, if you hover over a node, the node changes size and/or color and/or shape to show that it is currently "in context" and, simultaneously, you see the corresponding bullet chart (or any other relevant information) in a clear and uncluttered area of the screen (such as in the upper left hand corner of the drawing, away from the branch "sprawl" of the tree, which becomes more and more cluttered, as the tree grows further to the right of the canvas (this assumes a tree that grows from left to right). Doing so ensures that there is no clutter blocking between any one drawing or any other. Keeping the bullet chart that is drawn when you hover over a node in an area of the canvas that does not contend with the tree means you won't have to "redraw" the elements of the tree that get blocked out each time the chart draws itself over specific tree elements, which would be the case if you draw the chart "over tree elements".
Anyhow, I hope this helps.
My Best,
Frank
I am using the D3.js library and looking at the force-directed graph demo:
http://mbostock.github.com/d3/ex/force.html
I am also looking at the node-link tree:
http://mbostock.github.com/d3/ex/tree.html
What I would like to do is:
- Start with the force-directed graph and when the user clicks on a
node, have it animated smoothly into a tree, with the selected node
in the center.
- Then, when the user clicks on any empty space in the canvas, it
should animate back to the force-directed graph.
Has anyone done anything like this before, or have any advice as to the best approach to take? I am new to D3.js and have no idea if this is even supported by the framework.
What you need to do is stop the force and apply a transformation of the existing nodes to the x-y derived from the other layout. So your function would look like this:
force.stop();
d3.selectAll("g.nodes").transtion().duration(500)
.attr("translate","transform("+newLayoutX+","+newLayoutY+")"
Then iterate through your nodes array and set the x, y, px, py values to reflect the new X and Y. This will set your nodes to know the current x and y position for the force layout when you run force.start()
You can take a look at the plotLayout() function in this example:
https://gist.github.com/emeeks/4588962
This does not rely on a second d3.layout, though. The problem you'll run into is that you need a hierarchical dataset for the tree layout, which requires you to transform your nodes and edges data into an array of node.children as expected in the hierarchical layouts. The way that I would do it is to duplicate the dataset and manually flatten it, but there may be a more elegant solution that I'm unaware of.
I am creating a family tree program. My question is how do i position the nodes? Originally i positioned the root at the center of my screen and it works fine if it is a perfect binary tree and the levels are very less. However it is not most often the case. This is a sample tree :-
A
B C
D E F I J
K L N O
As you can see, the main problem is regarding the position of the nodes. If a node has many childs and it's adjacent node also has many children, they tend to overlap.(MAIN PROBLEM) I am using absolute positioning of the node using Canvas in Silverlight. You may not bother with the Silverlight and Canvas part if you are not a Silverlight developer. I just need the logic of how to position the nodes.
The height of the tree can be computed fairly easily by knowing the total number of levels of tree but the width of the tree is what is troubling me. How can i calculate the width of the tree (total width of the canvas)
Can somebody give me some general guidelines regarding how to set the width of the canvas and what logic will work perfect for the positioning of the nodes.
NOTE :- I am not asking for the whole algorithm and it is not my homework. I already have the algorithm and database. I just need guideline for the positioning part of the node.
Thanks in advance :)
If you implement a function: width(node) for arbitrary node of this tree, it is easy to positioning each node
This function may be defined recursively:
- for a tree of height 1 it tree this is exactly length of this node
- for a tree of height bigger than 1 this is a sum of lengths of all direct children of this node (plus some spaces between those)
I would recommend starting with the widest level of the tree if you want to guess the width of the canvas. You can calculate by traversing the tree breadth-first. Multiply the number of nodes at that level by the amount of lateral space each node needs and you have the width of canvas you require.
However, that's no guarantee that adjacent nodes on the widest level won't each have many children. So, to perform spacing with no overlap, start by positioning the leaves of the tree at the deepest level and traverse the tree backwards, adding parents above and putting leaves into the gaps and at the sides.
I would suggest to give zoom in and zoom out functionality to unclutter the GUI Real Estate.
A Node with many children can be grouped and a special icon to denote it can be zoomed in to next level would be good i feel, as the family grows, as user can get big picture at first and as then can zoom into any branch he wishes too.
Take cues from google map's UI, might help.