I've implemented a scene tree to be used in a 2D game. The tree nodes contain transformations and drawable objects.
This is what the scene tree looks like:
Root
|
--------------------------
| |
Layer1 Layer2
| |
----------------- ---------
| | | | |
A B C F G
|
---------
| |
D E
In order to draw the scene the tree is first traversed in depth-first order. During traversal the drawables are collected in a render queue. The render queue is then passed to a renderer to be processed.
As the drawables are collected in depth-first order, this is also the order in which they are drawn by the renderer. To change the drawing order I have to rearrange tree nodes. If, for example, I want node G to be drawn before node F, I have to swap them. I would like to change that so that the nodes don't have to be rearranged anymore. Instead the renderer should be able to sort the render queue by itself.
The problem:
Each group of sibling nodes (e.g. [A, B, C] or [F, G] or [D, E]) has to be sorted individually so that the hierarchy stays intact. If the tree nodes are sorted directly this is not a problem. However, if the tree is flattened to a render queue, things become complicated.
My questions:
How can I sort the render queue without disturbing the hierarchy of nodes?
Are there alternative solutions for this kind of problem?
Additional info:
The best resource I could find is the blog article Order your graphics draw calls around. It explains how to sort a render queue using a 64-bit key that is assembled from multiple chunks of information. It doesn't deal with the problem I have, though.
You might ask why I don't content myself with sorting the tree nodes directly. There are two reasons: Firstly, I would like to keep concerns separated. Rearranging nodes in the scene tree so that the renderer draws them in the right order would not be conducive to this goal. Secondly, it would not be possible to exclude non-visible nodes/drawables from sorting (whereas the render queue only contains visible drawables).
Related
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.
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.
I have an arbitrary tree structure of nodes. I want to draw this tree to provide users a visual representation. I need to recurse over the tree and for each node add a graphic item to a list, and then just draw the list of items once tree recursion has finished. The recursion and drawing of items is of course trivial - what's a bit more complicated is how to position the graphic nodes so they do not overlap with other branches.
I'm using Android but that is not important - I'm looking for an approach, possibly an algorithm that can maintain a picture of 2D space as it passes over the tree so it just allocates the most appropriate coordinates for each node as it makes the pass.
Any ideas?
Update
This is the article with the best and most complete algorithm.
I would try the Walker algorithm. Here's an academic paper on the algorithm. If you want code to look at, look at the NodeLinkTreeLayout in Prefuse. Prefuse is open source so there shouldn't be any problems adapting the code to your situation as long as you follow the terms of the license.
I suggest drawing the tree linewise. You do this by using some kind of moving "drawing cursor".
You could store an attribute width for each node which is calculated as follows:
the width of a leave is 1
the width of an inner node is the sum of all childrens' widths
Then, you draw the root "in the first line" in the middle, which means, you just take root's width's half.
Then, you generate a grid over the image such that each gridline corresponds to one line resp. one step from left to right and each intersection of grid lines can contain a node and each node has enough space.
Then, you iterate through the childs and while iterating, you accumulate the children's widths and draw the children "in the next line". To draw currentChild, you move your drawing cursor currentWidth/2 to the right, draw currentChild, and move the drawing cursor the remaining currentWidth/2 to the right.
In order to get the nodes in a good order, you might consider a breadth first search.
I hope my explanation is clear, but I think it will be better, if I draw a little picture.
This is our tree (x are nodes, everything else edges)
+-------x--+-------+
| | |
+-x-+ +-+x+-+ +-x-+
| | | | | | | | |
x x x x x x x x x
So, you calculate the leaf's widths:
+-------x--+-------+
| | |
+-x-+ +-+x+-+ +-x-+
| | | | | | | | |
1 1 1 1 1 1 1 1 1
Then, bottom up, the widths as sums of childrens' widths:
+-------9--+-------+
| | |
+-2-+ +-+4+-+ +-3-+
| | | | | | | | |
1 1 1 1 1 1 1 1 1
So, you start at the root (width 9) and go 4.5 steps to the rigt in the first line.
Then, you move your "drawing cursor" to the second line, "column 0" (go to left).
The first child has width 2, so we go 2/2=1 grid lines to the right and draw the node and move the drawing cursor the remaining 1 grid lines to the right in order to finish the node. So, the next node has width 4, which means, that we go right 4/2=2 grid lines, draw, go the remaining 2 steps, and so on.
And so on with the next line. At the end (or in intermediate steps), connect the nodes.
This procedure ensures that there are no overlapping nodes (if grid lines are far enough from each other), but it might lead to quite large tree diagrams that could use the space more efficiently.
In order to detect unused space, one might just scan the lines after the above process and look if there are unused grid line intersections and then possibly realign some nodes in order to fill space.
Take a look at Dot. You can convert your tree to the dot representation and then using Graphviz visualize in any format you like. For example Doxygen uses it to represent the structure of program.
Graphviz and mfgraph are powerful, but they're for general graphs and are probably overkill for trees.
Try googling on tree+layout+algorithm or see Graphic Javascript Tree with Layout.
The latter is old but it uses HTML canvas and javascript, and it explains the code, so both the code and the approach should be portable.
Depending on the nature of your data, a TreeMap may be more appropriate than a tinkertoy representation.
The Problem:
I have a large double (2d) array populated with various labels. Each element (cell) in the double array contains a set of labels and some elements in the double array may be empty. I need an algorithm to cluster elements in the double array into discrete segments. A segment is defined as a set of pixels that are adjacent within the double array and one label that all those pixels in the segment have in common. (Diagonal adjacency doesn't count and I'm not clustering empty cells).
|-------|-------|-------|
| Jane | Joe | |
| Jack | Jane | |
|-------|-------|-------|
| Jane | Jane | |
| | Joe | |
|-------|-------|-------|
| | Jack | Jane |
| | Joe | |
|-------|-------|-------|
In the above arrangement of labels distributed over nine elements, the largest cluster is the “Jane” cluster occupying the four upper left cells.
What I've Considered:
I've considered iterating through every label of every cell in the double array and testing to see if the cell-label combination under inspection can be associated with a preexisting segment. If the element under inspection cannot be associated with a preexisting segment it becomes the first member of a new segment. If the label/cell combination can be associated with a preexisting segment it associates.
Of course, to make this method reasonable I'd have to implement an elaborate hashing system. I'd have to keep track of all the cell-label combinations that stand adjacent to preexisting segments and are in the path of the incrementing indices that are iterating through the double array. This hash method would avoid having to iterate through every pixel in every preexisting segment to find an adjacency.
Why I Don't Like it:
As is, the above algorithm doesn't take into consideration the case where an element in the double array can be associated with two unique segments, one in the horizontal direction and one in the vertical direction. To handle these cases properly, I would need to implement a test for this specific case and then implement a method that will both associate the element under inspection with a segment and then concatenate the two adjacent identical segments.
On the whole, this method and the intricate hashing system that it would require feels very inelegant. Additionally, I really only care about finding the large segments in the double array and I'm much more concerned with the speed of this algorithm than with the accuracy of the segmentation, so I'm looking for a better way.
I assume there is some stochastic method for doing this that I haven't thought of.
Any suggestions?
Edit:
My desired output is a list of segments, each segment being a label and a list of points. Therefore, in the example above I'd want two segments to be returned:
Segment 1 - Jane: (1,3), (2,3), (1,2), (2,2)
Segment 2 - Joe: (2,3), (2,2), (2,1)
You basically want to implement a flood fill algorithm--consider the array as a set of images, one per distinct label, where the label is a color, and the lack of a label is black; you then want to segment it into all connected components of that color.
Repeat for all labels and you're done.
If your labels are sparse, you're probably better off not actually creating an image for each label and using an existing flood fill routine. In that case, do your own breadth-first flood fill by creating a copy of the array and building connected blocks one label at a time while destroying the existing label.
I am going to call one entry a "pixel" and the whole array an "image".
The algorithm goes, roughly,
for each pixel in the image
for each label in the pixel
1. remove the label
2. mark the current pixel
3. for each marked pixel, look in every adjacent pixel for the label
4. remove any labels found
5. if labels are found, clear marks, and mark the newly label-removed pixels
6. if anything is marked, go back to 3
7. report the set of points where you removed labels
Since this is destructive, you don't have to worry about backtracking. (If you can't destroy your original, and can't make a copy, then you have to keep track of what you've done along the way, which is more of a hassle.)
I am importing massive amounts of data from Excel that have various table layouts. I have good enough table detection routines and merge cell handling, but I am running into a problem when it comes to dealing with borders. Namely performance. The bordered regions in some of these files have meaning.
Data Setup:
I am importing directly from Office Open XML using VB6 and MSXML. The data is parsed from the XML into a dictionary of cell data. This wonks wonderfully and is just as fast as using docmd.transferspreadsheet in Access, but returns much better results. Each cell contains a pointer to a style element which contains a pointer to a border element that defines the visibility and weight of each border (this is how the data is structured inside OpenXML, also).
Challenge:
What I'm trying to do is find every region that is enclosed inside borders, and create a list of cells that are inside that region.
What I have done:
I initially created a BFS(breadth first search) fill routine to find these areas. This works wonderfully and fast for "normal" sized spreadsheets, but gets way too slow for imports into the thousands of rows. One problem is that a border in Excel could be stored in the cell you are checking or the opposing border in the adjacent cell. That's ok, I can consolidate that data on import to reduce the number of checks needed.
One thing I thought about doing is to create a separate graph that outlines the cells using the borders as my edges and using a graph algorithm to find regions that way, but I'm having trouble figuring out how to implement the algorithm. I've used Dijkstra in the past and thought I could do similar with this. So I can span out using no endpoint to search the entire graph, and if I encounter a closed node I know that I just found an enclosed region, but how can I know if the route I've found is the optimal one? I guess I could flag that to run a separate check for the found closed node to the previous node ignoring that one edge.
This could work, but wouldn't be much better performance wise on dense graphs. Can anyone else suggest a better method? Thanks for taking the time to read this.
Your question is pretty complicated, but it sounds as though you need an algorithm to find the connected components of a graph (connected component = set of nodes all connected to one another but to no other nodes), which can be accomplished in linear time by repeated traversals. Pseudocode:
FindComponents(G):
For all vertices v in G:
Let C be a mutable empty collection
Traverse(G, C, v)
If C is nonempty, then it is a connected component
Traverse(G, C, v):
If v has not been visited:
Mark v as visited
Add v to C
For each neighbor w of v in G:
Traverse(G, C, w)
Iterative variant of Traverse:
Traverse(G, C, r):
Let S be an empty stack
Push r onto S
While S is not empty:
Pop the top element v of S
If v is not marked as visited:
Mark v as visited
Add v to C
For each neighbor w of v in G:
Push w onto S