binning.js 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. function displayBinning(scope, dimensions, projection, path) {
  2. /**
  3. * Hexbin-specific setup
  4. */
  5. var hexbin = d3.hexbin()
  6. .size(dimensions)
  7. .radius(scope.panel.display.binning.hexagonSize);
  8. var binPoints = [],
  9. binnedPoints = [],
  10. binRange = 0;
  11. if (scope.panel.display.binning.enabled) {
  12. //primary field is just binning raw counts
  13. //secondary field is binning some metric like mean/median/total. Hexbins doesn't support that,
  14. //so we cheat a little and just add more points to compensate.
  15. //However, we don't want to add a million points, so normalize against the largest value
  16. if (scope.panel.display.binning.areaEncodingField === 'secondary') {
  17. var max = Math.max.apply(Math, _.map(scope.data, function(k,v){return k;})),
  18. scale = 50/max;
  19. _.map(scope.data, function (k, v) {
  20. var decoded = geohash.decode(v);
  21. return _.map(_.range(0, k*scale), function(a,b) {
  22. binPoints.push(projection([decoded.longitude, decoded.latitude]));
  23. })
  24. });
  25. } else {
  26. binPoints = scope.projectedPoints;
  27. }
  28. //bin and sort the points, so we can set the various ranges appropriately
  29. binnedPoints = hexbin(binPoints).sort(function(a, b) { return b.length - a.length; });
  30. binRange = binnedPoints[0].length;
  31. //clean up some memory
  32. binPoints = [];
  33. } else {
  34. binnedPoints = [];
  35. binRange = 0;
  36. }
  37. var radius = d3.scale.sqrt()
  38. .domain([0, binRange])
  39. .range([0, scope.panel.display.binning.hexagonSize]);
  40. var color = d3.scale.linear()
  41. .domain([0,binRange])
  42. .range(["white", "steelblue"])
  43. .interpolate(d3.interpolateLab);
  44. /**
  45. * D3 Drawing
  46. */
  47. var hex = scope.g.selectAll(".hexagon")
  48. .data(binnedPoints);
  49. hex.enter().append("path")
  50. .attr("d", function (d) {
  51. if (scope.panel.display.binning.areaEncoding === false) {
  52. return hexbin.hexagon();
  53. } else {
  54. return hexbin.hexagon(radius(d.length));
  55. }
  56. })
  57. .attr("class", "hexagon")
  58. .attr("transform", function (d) {
  59. return "translate(" + d.x + "," + d.y + ")";
  60. })
  61. .style("fill", function (d) {
  62. if (scope.panel.display.binning.colorEncoding === false) {
  63. return color(binnedPoints[0].length / 2);
  64. } else {
  65. return color(d.length);
  66. }
  67. })
  68. .attr("opacity", scope.panel.display.binning.hexagonAlpha);
  69. hex.exit().remove();
  70. }