I am working on a visualization tool for an excel document containing a relatively large amount of business requirements (70 data elements).
The purpose is to show some of the internal structures of the data which is not immediately obvious when staring at the excel file. The structure looks something like this:
root-->(
(component 1)--->(
sub-component a)--->(data element 1, data element 2, ..., data element 30),
(component 2)--->(
sub-component a)--->(data element 1, data element 2, ..., data element 30),
(component 3)--->(
sub-component a)--->(data element 2, data element 2, ..., data element 30)
)
What I'm noticing is that:
Graphs are great at showing structure, but suck at showing data.
Tables are great at showing data, but suck at showing structure.
At this point I can no longer use the default autolayout of GraphStream. Due to the large number of data elements attached to a single sub component, the autolayout cannot position those elements in such a way that they don't overlap and become impossible to read. What happens is a sort of flower effect, where the data elements are are like overlapping petals around their parent.
If I disable the autolayout, I have to position the nodes myself. Graphstream says the following:
You fix the coordinates as you wish. The units you use will be called “Graph Units”. However, as you will see later, the viewer supports two other units: pixels and percents.
http://graphstream-project.org/doc/Tutorials/Graph-Visualisation/1.0/
Alright, as it turns out, either this is a difficult problem or I am slow. I have been unable to position nodes is a readable way.
Things I've tried:
Positioning children relative to their parent: Iterate through the nodes with for loops (in retrospect it may be worth implementing this recursively to support n levels), starting with root. Determine the number of children of root divided by 2 (3/2 = 1 with integer division) call this middle. Set component 1 X position to i - middle. Set the y position to root y position - 1. In this way I can create a 'tree' structure where the parent sits centered on top of its children.
Other people's children are what's wrong with this world...
Unfortunately this doesn't work out well in practice. Any single component is ok but if there are other parents on the same level their children overlap with every other parent's children. This happens because the children are being positioned relative to their parent, and have no idea that, in fact, the position they want to go in is already being taken up by someone else's kids.
So now I don't know what to do. I can't position nodes taking into account nodes that don't exist yet. I have a few idea fragments, but they all seem convoluted.
So before I venture into hell code, I made this question because I feel like I can't possibly be the first person to have to draw a readable graph, and there probably are established ways to do this.
For reference these are the idea fragments:
Make individual graph elements responsible for their own position and have them position themselves relative to their children or lack there of.
Look into manipulating the camera in combination with some positioning solution. Limit the number of nodes that can be visible at a given time (kill other people's children if there's too many). Use zoom and panning based on which component is clicked.
Recursion. Is a word I know. Kidding aside, I have used recursion before and I feel graphs, especially graphs like mine without cyclic structures in them, practically beg for recursive solution. I actually have, in a different project used a recursive approach to draw graphs, but I ended up in the same situation. How can I be aware of the recursive paths drawing other parent's children? I should still probably brainstorm some recursive approaches.
Create a new data structure that represents relative real estate in the viewport. Segment into regions, nodes take up the relative regions, 2 nodes cannot take up the same relative region. Figure out what to do when some one try's to sit on someone else's kid. I came up with this while writing this post actually.
That's all I got, what do you guys think? Is there some well known algorithm for node positioning that already solves my issue? Which of my idea fragments sound most promising?
Related
I have had issues trying to change the order in which data series are layed out in a ScatterChart.
Basically, regarding multiple series, the layout order is given from the order the series are added to the chart. Yet, if I remove one and add it again later, it will appear on top.
I tried :
myChart.getData().add(specificIndex, series)
to make sure that the last one is not on top, but it doesn't work
I also tried:
myChart.getData().add(lastSeries);
myChart.getData().stream().sort((seriesA, seriesB)->myComparator(seriesA, seriesB));
But it does not work either.
Also, I experience similar problems when it comes to displaying data points.
Basically, I am trying to create a scattered heatmap where points are colored depending on their density on the chart. So the data is associated with a Rectangle Node that is colored with a hue proportional to the number of nodes present within a given radius.
This is fine, except that in very dense region, some points are hiding others with higher density, and the end result is not representative of the density function...
The only work around was this (for series):
myChart.getData().clear()
myChart.getData().addAll(myCorrectlyOrderedListOfSeries);
which seems very dirty and computationnaly inneficient...
any other way?
EDIT
I actually solved the problem for data Point, realizing that there was a "toFront" method.
Yet, since I don't have a node for the series, I don't know on which Item I should call the toFront() regarding the series. Do I really need to call in on all data points from all series, in the order I want for the series?
I checked the Node tree generated by a scatter chart, and in fact, all the dataPoints are actually children of the same group, regardless of the Series they belong too.
So there is no other way than the following to put the series in the correct order:
//List<Series<Double, Double>> myOrderedListOfSeries;
myOrderedListOfSeries.forEach(series->
series.getData().forEach(dataPoint->
dataPoint.getNode().toFront()
)
);
Situation:
I have potentially tens of thousands of moving (2D) points. They affect each other only to a certain radius. They can move from place to place (not teleporting, just flying around the screen, essentially).
Since I have to check for updates every tick, it is rather important to do this efficiently.
My naive solution is to simply create a grid type structure with grid spacing somewhere around the radius of effect and as points move from cell to cell, update which cell they are in. So when I need to do effects checking, I only have to check a point's cell and a few neighboring cells.
I am familiar with quadtree, but I worry that it is a bit more expensive than what I need to do, but I am open to suggestions if this is indeed the correct route.
Also, for added information, this is in Java.
Thanks
i was and for my next project will be in a similar situation.
I choosed the simple grid variant, because its simpler and faster to implement.
tens of thousands is at the border where an quad tree or k-d tree could make sense. (especially when many cells would be empty)
You should try to test if an grid approach is sufficient. probably it is.
I have a java component on which I draw 100 by 40 rectangles to represent nodes of a graph. When a new node is added, I would like to be able to position it in a useful position. Currently, I simply choose the next available space on the x-axis. However, this means when I load a graph, I get a large chain of nodes spanning off the view to the right - not ideal!
A better solution may involve adding a node at the point closest to the center-point of the user's view. I'm sure there are many solutions to this problem I am unable to think of a reasonable way to achieve this.
I have three methods that are relevant to this problem:
positionNode(Node) // which tries to find suitable x,y to place a node
setPos(x,y) // which moves a node to the respective position
findElementAt(x,y) // which returns a node's model if such a node exists at (x,y)
A potential solution may somehow involve spiraling around the center point but I am unable to imagine a good solution for performing this.
Graph rendering is a hard problem which is the subject of a lot of research.
If you want to make the nodes into a sort of a bundle, rather than a line of nodes, the main disadvantage will be that lines coming out of the nodes will get overlapped by the other children.
You can make a square bundle or a round bundle. To make a square bundle, take the square root of the number of nodes and add one. For example, if you have 17 nodes, the sides of the square is 4 + 1 = 5. So you have a 5 x 5 square. Position each node in a cell of the square.
To make a round bundle draw concentric circles. So first node is at center. Then calculate an imaginary circle around that node. Divide the circle into segments by degrees according to how much space you need. Then locate each additional node in the center of each segment.
Note that you might want to overlap nodes. Depending on how your interface works, overlapping might allow you to fit more nodes in.
Sounds like an opportunity for force based layout:
http://en.wikipedia.org/wiki/Force-based_algorithms_(graph_drawing)
When you say graph I assume nodes are connected with each other so drawing them so their lines minimally criss cross to make it easier to visualize what the graph is telling you seems important. Forced based layout can help arrange the graph so it isn't under "stress" with lots of lines intersecting each other.
I want to draw a dendrogram from objects which I have already clustered and saved in a (leave)tree. My Cluster object in Java can be represented by these pictures. Each leaves contains an object and each node contains the distance between its children.
Now, I want to draw a dendrogram stepwise, so first object 1 and 2 should be drawn, then object 3 should be added to those. Then 5 and 6 together etc.. to the end where everything is connected. I already have all the tools to draw this easily, but I cannot find an efficient way in walking through the tree correctly.
This should be the result so far in the example (EDIT: There's a mistake, the distance from 5 to 6 now looks smaller than the distance from 3 to 1&2, but that isn't the case in my example!):
Does anyone have some tips for this recursive algorithm?
you're rendering depth first - you may find you need to keep track of depth to get the layout to work right - also note you have to draw non-terminal notes as well ("*" gets drawn before 3)
basically
draw(node)
{
if(hasleft) draw(left)
if(hasright) draw(right)
drawme()
}
this does assume a binary tree, but that is what you've drawn - and this is going to get a lot more complicated because of layout issues - you really want to consider drawing breadth first from the top down, it makes layout a lot less painful
I've built a 2D grid in java where each cell can have a certain attribute, say color. At each iteration of the main loop, that color can possibly change.
What I want to be able to do:
- when zoomed in, it will show a small subset of the grids and the actual color of each grid.
- as you zoom out and see more cells at once, the cells will start to get too small to be seen individually, so I want to be able to just represent that area(a collection of cells) as a single color (say the most often occurring one in that collection)
One thing I thought of for doing this would be to use a hierarchical tree/pyramid structure, where at the leaves you have each cell. Each parent node contains summary information of each of its children. So to draw the map at a high zoom level, I'd only need to go down a few levels in the tree instead of looking at each cell individually. However, propagation of changes from leaves to parents and subsequently to each higher level seems like it'd take quite awhile in a large grid for every loop iteration.
Is there a better way to do this? This problem seems like it should have been handled before by people in the graphics/gaming world but I'm having trouble even finding the right keywords to Google, so any help or direction is appreciated. Thanks.
Perhaps quadtree would be a helpful search term.
http://www.google.com/m/url?client=safari&ei=idePTdD_LuWJiAKbgM3pAQ&hl=en&oe=UTF-8&q=http://en.wikipedia.org/wiki/Quadtree&ved=0CBMQFjAA&usg=AFQjCNEjIDTtDl-nIhlMVz6WemoQ_w8jYg
I think you're on the right track. What you propose is a typical implementation of a 2D scene graph and determining bounds of parent nodes.
Keep in mind that even though leaf nodes might change colors, the change may not be propogated all the way up due to previous state. What you need to be sure to do is track dirty leaves so you don't do the update for everything when its not necessary.
I think you should implement what you propose and then see if performance is really an issue. How many cells are in your grid?