javascript d3 culling d3 values outside of clippath - javascript

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.

Related

D3.js animated grouped bar chart with variable number of groups

I am trying to adapt the animated grouped bar chart example from
https://bl.ocks.org/aholachek/fb0c1cd7ea9707bc8ff55a82402c54b1
for my own purposes. One modification that I am stuck at right now is that my data will have a variable number of groups and the xAxes and blocks have to resize accordingly.
I have already added the resizing of the domains with
x0.domain(data[Object.keys(data)[0]].map(obj =>obj.name))
x1.domain(valueKeys).rangeRound([0, x0.bandwidth()])
in the update function, but this does not seem to be enough. While the width of the bars is resized correctly, the x values are not spaced out evenly and instead get pushed into the far right corner of the graph when adding more elements after the initial creation for example.
For now I only care about the grouped version, not the stacked one.
I would appeciate any pointers
Problem could be solved by clearing out the barContainer before the update. This of course prevents transitions on the already existing bars, but that is good enough for me

Leaflet heatmap based on value not quantity

I got some thousand points containing weights.
Many of those points have (more or less) the same coordinate and I want to visualize those points on a leaflet map using absolute coloring of the map. (Same coloring for a point at every zoom level)
I tried using leaflet.heat but it seems to be adding up the values (resulting in everything colored red) and does relative rendering.
It would be ideal if it would use the average or maximum of the provided weights for rendering a heatmap.
Anyone has an idea how this could be done quickly?
An approach would be to use Leaflet-MarkerCluster, use a custom cluster symbolizer, and symbolize each cluster with the symbol corresponding to the point with the highest value of the property.
Another approach would be to use Turf.js to hexbin the data in the client and apply the highest value to the hex.
Another approach would be to use a Voronoi tesselation, and symbolize each area of the tesselation with the desired value, optionally clipping the symbols to prevent symbolizing large empty areas.

Prevent node overlap in force directed graph

I have build a force directed graph for the social network analysis.
The problem which I am facing is that nodes keeps on overlapping each other,
How can I prevent overlapping of node in force directed graph ?
Here is my code with dummy data
And following is the image for my force directed graph
How can I remove overlapping of these nodes ? and how can I keep atleast some distance between links so that links are properly visible ?
There are two approaches to avoiding overlap in a d3 force layout.
The first is to adjust the parameters of the force object, the most relevant of which is the "charge" parameter. Nodes with negative "charge" values push other nodes away (versus nodes with positive values pull other nodes closer), and you can increase the amount of charge to cause a greater push.
The default value for the "charge" is -30, so from there you can adjust it until you get an effect you want. There's no simple formula for determining the value you want, since it also depends on the other parameters and the amount of links in your graph.
If for any reason adjusting the charge doesn't work for you (for example, if you want the nodes to cluster close to each other -- not repel each other -- but still not overlap), then you can manually check for overlapping nodes, as in this Mike Bostock example suggested by Josh in the comments.

d3 y Domain and Range

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.

determine efficiently which rectangle a point is in 2d space

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)

Categories