I need to find out where to draw my y axis dependent of a date
My data looks like the following in .csv format:
startYYYYMM, endYYYYMM, ProjectName
201301, 201303, Proj1
201302, 201412, Proj2
201304, 201311, Proj3
I've done the chart as laying bar chart
Where to start my bars on the x axis is dependent on the start and is no problem. It's the y that is the problem.
I wonder If there is any built in "optimization" in d3 that I can use. I release that I can loop through my data to decide "the grouping" of my data.
And a pic of how I would like it to look like:
https://www.dropbox.com/s/5xs0jfxb33ipn60/temp.jpg
/Thank's
If I understand correctly, the difference between what you want and a standard Gantt chart is that the Gantt chart puts every project on its own line, but you want to compact the display so that long-finished projects don't continue to take up a row of blank space.
To get that "optimized function based on date" that figures out where on the Y-domain you can fit a project to keep the display compact, you're going to need to keep track of which projects are active at a given time, and loop through them to find out where you have room on your display for a new project.
Here's an algorithm you could implement. The results won't always be perfect (sometimes a small rectangle will end up taking up room in a space where a larger rectangle could have been positioned) but it should be much more compact than a standard Gantt chart.
Sort your projects by start date and work through them in that order, assigning y-positions to each.
As you work through your project list, keep a secondary array of "active" projects -- ones that have been started but not finished at the time you are looking. These will always be projects that you have already positioned on the graph, since you're positioning projects in order of start time.
For each project in your main array:
go through the active-project array (if it's not empty) and remove any projects that finished before the project you are plotting started (if you want padding between rectangles, require a certain minimum time to have passed in between);
sort the active-project array by the y-position you have already assigned to each project-rectangle;
scan through the active-project array, checking the y-position and height of each rectangle, to see if you have room to place the rectangle for your current project;
if you can't fit it in-between any of the currently active projects, set it's position to be above the last active project, and check whether the new position+height of this rectangle exceeds your previous maximum height;
either way, store the calculated y position (which will be in the same units as the variable you are using for rectangle height) in the project's data-object.
Now that you've set this project's position, add it to the active-project array and move on to the next project in your main array.
Once you have determined a relative y-position for each rectangle, set your y-scale domain according to the maximum height you used and draw the axis and rectangles.
You can look at this answer for some inspiration, although that example is more complicated than what you need.
Related
I am building a timeline graphic where the x axis is time and the y axis is a discriminator value from a column selected out of a csv.
It essentially pulls out the unique values from the key column and sets it up as its own row on the y-axis
In the above example the random digits on the left are unique values from a column. The reason I do this is because I want all timerange values using the same unique key to appear on the same row.
I am struggling with latency right now as I test it out, There are 6000 unique keys that are all being displayed (if you pan down more appear). What I'd like in order to maintain speed is to completely cull any values that aren't within the clip-path rectangle set.
As an example, there are currently 6000 group nodes with thousands more rectangles within the dom that aren't visible or being drawn. The updating of the translation of all these values are causing the serious lag.
Is there an efficient way to effectively test only for values within the clip-path range and enter/exit them such that only what would be visible is actually being drawn? I'm essentially looking for a way to completely cull the dom nodes out to speed the process up.
I'm working on a project where we have some Highcharts graphs populated from database; one of them is an scatter graph and we need to surround the points placed on the outside area of the graph.
We need a graph like this but we need the area surrounding the outside points of the scatter; is there a easy way to do this with Highcharts?
We need it to work on IE11 (client's specs).
We can do it with a new polygon serie to make by getting it from codebehind or from database, but that may take too much development time and will slow down the queries. So we need to know if there is an easier way to do it via Highcharts or Javascript
Thanks in advance.
I am not very familiar with Highcharts, but i could not find such functionality in their API. However there is an easy algorithm to solve your problem.
All you need is to have an array containing the border elements and connect the points from this list like here.
Finding those points is not too hard. Compute the linear equation between two extreme points (like the one on the very top and very right). The resulting formula looks like f(x) = m*x + b
Now you check for all points within that x-range if their y-coordinate is higher than this line (or lower when doing it with the point on the very bottom). If so just add them to your border array and continue with the other extreme points.
I have a large set of rectangles that are drawn on html5 canvas.
I would like to be able to interact with this image using mouse tracking (I cannot use SVG because it does not scale to 10-100k rectangles). Is there any data structure/algo that, given the mouse x,y coordinates would be able to tell you which box the mouse was over (using the computed locations of the rectangles)? I was thinking something like a k-d tree but was not sure.
If your data is always of the form shown I think you should be able to do better than a spatial tree data structure.
Since the data is structured in y you should be able to calculate which 'strip' of rectangles the points is in based on offsets in O(1) time.
If you store the individual rectangles within each 'strip' in sorted order (using xmax say) you should then be able to locate the specific rectangle within the strip using a binary search (in O(log(n))).
Hope this helps.
The naive solution would be to iterate over all rectangles and check if you are in it. Checking for a single rectangle is easy (if you want I will write it down explicitly).
If you have many rectangles and care about performance, you can easily speed things up by putting the rectangles in a data structure which is faster to look in. Looking at the image you sent, one obvious property of your data is that there is a limited amount of vertical positions ("rows"). This means that if you check which row you are on, you then only need to check rectangles within that row. Finally, to select which row you are on or within a row select which rectangle, keep a sorted data structure (e.g. some search tree).
So your data structure could be something like a search tree for row, where each node holds a search tree of rectangles along the row.
R-tree is suitable for providing spatial access of this kind
But some questions:
Is your rectangle set static or dynamic?
How many point queries do you expect for rectangle set?
Edit:
Because rectangle set is static:
There is method, used in traditional graphics with bitmaps (don't know is it applicable to html5 canvas or not):
Make additional bitmap with the same size as main picture. Draw every rectangle with the same coordinates, but fill it with unique color (for example, color = rectangle index). Then check color under mouse point => get rectangle index in O(1)
I need a Time Line For My Web Project.
Something like this - I read the code of this Time Line but did not understand it because it is not documented enough.
My problem is the math behind all of this (not the interaction with the canvas).
I have read several articles about the math of the scroll bars, but none of them talk about zoom.
Some
articles suggest to hold canvas element with very large width value - and to display just the
View Port.
I don't think that's the right way to do it - I want to draw just the correct viewport.
In my project, I have array of n points.
Each point holds time value represented in seconds, but not all of the points are within the Viewp Port.
Considering the current zoom level, how do I calculate:
What points should be drawn and where to draw them?
What is the size and position of the thumb?
Any articles / tutorials about such a thing?
You might be able to use something like Flot which handles the placement of points, as well as zooming and panning. Here's an example of that.
There are a bunch of other drawing libraries, here a good list.
You always have Raphealjs.com , one of the most used library to play with SVG, with this you can write your own js to generate the timeline.
I have an image with flags on it like the one with a pie chart here .
How can I find a particular flag on it and replace with another flag using canvas?
Edit:
I cannot control the source image, but the region to find is always known and the image to replace is always the same size as the one to find. I just need to replace one particular flag with another particular flag.
Edit 2:
The flag may appear in the image several times.
You won't see spectacular performance, but one way to approach this is by just iterating over the pixels in your pie chart image.
Call getImageData() on your pie chart image to acquire all the pixel data for the image (ie. request the maximum dimensions). Similarly, call getImageData() on the flag you want to search for. Setup a loop that iterates over all the pixels acquired from the pie chart. For each pixel, assume it is the top left (or another corner based on your iteration order) of the flag you are searching for. Compare it to the first pixel in your flag pixel data, and if they agree, continue iterating within a window size equal to the width and height of your flag. If you get to the end of the window iteration and each pixel pair matches, you've found the flag you're looking for. If they don't, move on to the next pixel in the pie chart data and iterate over the window again.
Note that in the worst case you're looking at O([N * W * H] - [W * H]) or just O(N * W * H) with N = pie chart pixels and W x H = flag dimensions. You could probably improve this by not iterating over windows where you know there will be no flags, and by shifting the window more intelligently. Once you do find a match, you have the coordinates of the corner where you want to call drawImage() to paste your new flag on top.
Of course this approach assumes that the flag you're searching for is represented exactly in the pie chart image. If you are comparing a non-compressed flag to a compressed pie chart image, or vice versa, you won't find a match. Likewise, any size or orientation variations will completely defeat this approach. If you need that kind of flexibility, you're delving into something like SIFT territory. While I'm sure that could be implemented using canvas elements, I wouldn't want to be the one to do it.
In this situation, you'll want to make sure that you don't traverse the DOM unnecessarily while performing iterations. In particular, you will want to store local references to the pixel data as explained here: http://www.onaluf.org/en/entry/13
Given you already know the coordinates and have an image to map, you'll likely want to use drawImage.